@@ -614,8 +614,8 @@ impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> {
614614 }
615615
616616 fn check_operand_move_size ( & mut self , operand : & mir:: Operand < ' tcx > , location : Location ) {
617- let limit = self . tcx . move_size_limit ( ) . 0 ;
618- if limit == 0 {
617+ let limit = self . tcx . move_size_limit ( ) ;
618+ if limit. 0 == 0 {
619619 return ;
620620 }
621621
@@ -627,48 +627,19 @@ impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> {
627627 return ;
628628 }
629629
630- let limit = Size :: from_bytes ( limit) ;
631- let ty = operand. ty ( self . body , self . tcx ) ;
632- let ty = self . monomorphize ( ty) ;
633- let Ok ( layout) = self . tcx . layout_of ( ty:: ParamEnv :: reveal_all ( ) . and ( ty) ) else { return } ;
634- if layout. size <= limit {
635- return ;
636- }
637- debug ! ( ?layout) ;
638630 let source_info = self . body . source_info ( location) ;
639631 debug ! ( ?source_info) ;
640- for span in & self . move_size_spans {
641- if span. overlaps ( source_info. span ) {
642- return ;
643- }
644- }
645- let lint_root = source_info. scope . lint_root ( & self . body . source_scopes ) ;
646- debug ! ( ?lint_root) ;
647- let Some ( lint_root) = lint_root else {
648- // This happens when the issue is in a function from a foreign crate that
649- // we monomorphized in the current crate. We can't get a `HirId` for things
650- // in other crates.
651- // FIXME: Find out where to report the lint on. Maybe simply crate-level lint root
652- // but correct span? This would make the lint at least accept crate-level lint attributes.
653- return ;
632+
633+ if let Some ( too_large_size) = self . operand_size_if_too_large ( limit, operand) {
634+ self . lint_large_assignment ( limit. 0 , too_large_size, location, source_info. span ) ;
654635 } ;
655- self . tcx . emit_spanned_lint (
656- LARGE_ASSIGNMENTS ,
657- lint_root,
658- source_info. span ,
659- LargeAssignmentsLint {
660- span : source_info. span ,
661- size : layout. size . bytes ( ) ,
662- limit : limit. bytes ( ) ,
663- } ,
664- ) ;
665- self . move_size_spans . push ( source_info. span ) ;
666636 }
667637
668638 fn check_fn_args_move_size (
669639 & mut self ,
670640 callee_ty : Ty < ' tcx > ,
671641 args : & [ Spanned < mir:: Operand < ' tcx > > ] ,
642+ fn_span : Span ,
672643 location : Location ,
673644 ) {
674645 let limit = self . tcx . move_size_limit ( ) ;
@@ -692,10 +663,65 @@ impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> {
692663 return ;
693664 }
694665
666+ debug ! ( ?def_id, ?fn_span) ;
667+
695668 for arg in args {
696- self . check_operand_move_size ( & arg. node , location) ;
669+ if let Some ( too_large_size) = self . operand_size_if_too_large ( limit, & arg. node ) {
670+ self . lint_large_assignment ( limit. 0 , too_large_size, location, arg. span ) ;
671+ } ;
672+ }
673+ }
674+
675+ fn operand_size_if_too_large (
676+ & mut self ,
677+ limit : Limit ,
678+ operand : & mir:: Operand < ' tcx > ,
679+ ) -> Option < Size > {
680+ let ty = operand. ty ( self . body , self . tcx ) ;
681+ let ty = self . monomorphize ( ty) ;
682+ let Ok ( layout) = self . tcx . layout_of ( ty:: ParamEnv :: reveal_all ( ) . and ( ty) ) else {
683+ return None ;
684+ } ;
685+ if layout. size . bytes_usize ( ) > limit. 0 {
686+ debug ! ( ?layout) ;
687+ Some ( layout. size )
688+ } else {
689+ None
697690 }
698691 }
692+
693+ fn lint_large_assignment (
694+ & mut self ,
695+ limit : usize ,
696+ too_large_size : Size ,
697+ location : Location ,
698+ span : Span ,
699+ ) {
700+ let source_info = self . body . source_info ( location) ;
701+ debug ! ( ?source_info) ;
702+ for reported_span in & self . move_size_spans {
703+ if reported_span. overlaps ( span) {
704+ return ;
705+ }
706+ }
707+ let lint_root = source_info. scope . lint_root ( & self . body . source_scopes ) ;
708+ debug ! ( ?lint_root) ;
709+ let Some ( lint_root) = lint_root else {
710+ // This happens when the issue is in a function from a foreign crate that
711+ // we monomorphized in the current crate. We can't get a `HirId` for things
712+ // in other crates.
713+ // FIXME: Find out where to report the lint on. Maybe simply crate-level lint root
714+ // but correct span? This would make the lint at least accept crate-level lint attributes.
715+ return ;
716+ } ;
717+ self . tcx . emit_spanned_lint (
718+ LARGE_ASSIGNMENTS ,
719+ lint_root,
720+ span,
721+ LargeAssignmentsLint { span, size : too_large_size. bytes ( ) , limit : limit as u64 } ,
722+ ) ;
723+ self . move_size_spans . push ( span) ;
724+ }
699725}
700726
701727impl < ' a , ' tcx > MirVisitor < ' tcx > for MirUsedCollector < ' a , ' tcx > {
@@ -813,11 +839,11 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
813839 } ;
814840
815841 match terminator. kind {
816- mir:: TerminatorKind :: Call { ref func, ref args, .. } => {
842+ mir:: TerminatorKind :: Call { ref func, ref args, ref fn_span , .. } => {
817843 let callee_ty = func. ty ( self . body , tcx) ;
818844 let callee_ty = self . monomorphize ( callee_ty) ;
819- self . check_fn_args_move_size ( callee_ty, args, location) ;
820- visit_fn_use ( self . tcx , callee_ty, true , source, self . output )
845+ self . check_fn_args_move_size ( callee_ty, args, * fn_span , location) ;
846+ visit_fn_use ( self . tcx , callee_ty, true , source, & mut self . output )
821847 }
822848 mir:: TerminatorKind :: Drop { ref place, .. } => {
823849 let ty = place. ty ( self . body , self . tcx ) . ty ;
0 commit comments