@@ -179,15 +179,16 @@ use rustc_middle::query::TyCtxtAt;
179179use rustc_middle:: ty:: adjustment:: { CustomCoerceUnsized , PointerCoercion } ;
180180use rustc_middle:: ty:: print:: with_no_trimmed_paths;
181181use rustc_middle:: ty:: {
182- self , GenericParamDefKind , Instance , InstanceDef , Ty , TyCtxt , TypeFoldable , TypeVisitableExt ,
183- VtblEntry ,
182+ self , AssocKind , GenericParamDefKind , Instance , InstanceDef , Ty , TyCtxt , TypeFoldable ,
183+ TypeVisitableExt , VtblEntry ,
184184} ;
185185use rustc_middle:: ty:: { GenericArgKind , GenericArgs } ;
186186use rustc_middle:: { middle:: codegen_fn_attrs:: CodegenFnAttrFlags , mir:: visit:: TyContext } ;
187187use rustc_session:: config:: EntryFnType ;
188188use rustc_session:: lint:: builtin:: LARGE_ASSIGNMENTS ;
189189use rustc_session:: Limit ;
190190use rustc_span:: source_map:: { dummy_spanned, respan, Span , Spanned , DUMMY_SP } ;
191+ use rustc_span:: symbol:: { sym, Ident } ;
191192use rustc_target:: abi:: Size ;
192193use std:: path:: PathBuf ;
193194
@@ -431,7 +432,7 @@ fn collect_items_rec<'tcx>(
431432 hir:: InlineAsmOperand :: SymFn { anon_const } => {
432433 let fn_ty =
433434 tcx. typeck_body ( anon_const. body ) . node_type ( anon_const. hir_id ) ;
434- visit_fn_use ( tcx, fn_ty, false , * op_sp, & mut used_items) ;
435+ visit_fn_use ( tcx, fn_ty, false , * op_sp, & mut used_items, & [ ] ) ;
435436 }
436437 hir:: InlineAsmOperand :: SymStatic { path : _, def_id } => {
437438 let instance = Instance :: mono ( tcx, * def_id) ;
@@ -592,6 +593,11 @@ struct MirUsedCollector<'a, 'tcx> {
592593 instance : Instance < ' tcx > ,
593594 /// Spans for move size lints already emitted. Helps avoid duplicate lints.
594595 move_size_spans : Vec < Span > ,
596+ /// If true, we should temporarily skip move size checks, because we are
597+ /// processing an operand to a `skip_move_check_fns` function call.
598+ skip_move_size_check : bool ,
599+ /// Set of functions for which it is OK to move large data into.
600+ skip_move_check_fns : Vec < DefId > ,
595601}
596602
597603impl < ' a , ' tcx > MirUsedCollector < ' a , ' tcx > {
@@ -690,7 +696,14 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
690696 ) => {
691697 let fn_ty = operand. ty ( self . body , self . tcx ) ;
692698 let fn_ty = self . monomorphize ( fn_ty) ;
693- visit_fn_use ( self . tcx , fn_ty, false , span, & mut self . output ) ;
699+ visit_fn_use (
700+ self . tcx ,
701+ fn_ty,
702+ false ,
703+ span,
704+ & mut self . output ,
705+ & self . skip_move_check_fns ,
706+ ) ;
694707 }
695708 mir:: Rvalue :: Cast (
696709 mir:: CastKind :: PointerCoercion ( PointerCoercion :: ClosureFnPointer ( _) ) ,
@@ -789,7 +802,14 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
789802 mir:: TerminatorKind :: Call { ref func, .. } => {
790803 let callee_ty = func. ty ( self . body , tcx) ;
791804 let callee_ty = self . monomorphize ( callee_ty) ;
792- visit_fn_use ( self . tcx , callee_ty, true , source, & mut self . output )
805+ self . skip_move_size_check = visit_fn_use (
806+ self . tcx ,
807+ callee_ty,
808+ true ,
809+ source,
810+ & mut self . output ,
811+ & self . skip_move_check_fns ,
812+ )
793813 }
794814 mir:: TerminatorKind :: Drop { ref place, .. } => {
795815 let ty = place. ty ( self . body , self . tcx ) . ty ;
@@ -801,7 +821,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
801821 match * op {
802822 mir:: InlineAsmOperand :: SymFn { ref value } => {
803823 let fn_ty = self . monomorphize ( value. literal . ty ( ) ) ;
804- visit_fn_use ( self . tcx , fn_ty, false , source, & mut self . output ) ;
824+ visit_fn_use ( self . tcx , fn_ty, false , source, & mut self . output , & [ ] ) ;
805825 }
806826 mir:: InlineAsmOperand :: SymStatic { def_id } => {
807827 let instance = Instance :: mono ( self . tcx , def_id) ;
@@ -840,12 +860,13 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
840860 }
841861
842862 self . super_terminator ( terminator, location) ;
863+ self . skip_move_size_check = false ;
843864 }
844865
845866 fn visit_operand ( & mut self , operand : & mir:: Operand < ' tcx > , location : Location ) {
846867 self . super_operand ( operand, location) ;
847868 let move_size_limit = self . tcx . move_size_limit ( ) . 0 ;
848- if move_size_limit > 0 {
869+ if move_size_limit > 0 && ! self . skip_move_size_check {
849870 self . check_move_size ( move_size_limit, operand, location) ;
850871 }
851872 }
@@ -876,8 +897,11 @@ fn visit_fn_use<'tcx>(
876897 is_direct_call : bool ,
877898 source : Span ,
878899 output : & mut MonoItems < ' tcx > ,
879- ) {
900+ skip_move_check_fns : & [ DefId ] ,
901+ ) -> bool {
902+ let mut skip_move_size_check = false ;
880903 if let ty:: FnDef ( def_id, args) = * ty. kind ( ) {
904+ skip_move_size_check = skip_move_check_fns. contains ( & def_id) ;
881905 let instance = if is_direct_call {
882906 ty:: Instance :: expect_resolve ( tcx, ty:: ParamEnv :: reveal_all ( ) , def_id, args)
883907 } else {
@@ -888,6 +912,7 @@ fn visit_fn_use<'tcx>(
888912 } ;
889913 visit_instance_use ( tcx, instance, is_direct_call, source, output) ;
890914 }
915+ skip_move_size_check
891916}
892917
893918fn visit_instance_use < ' tcx > (
@@ -1365,6 +1390,31 @@ fn collect_alloc<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoIt
13651390 }
13661391}
13671392
1393+ fn add_assoc_fn < ' tcx > (
1394+ tcx : TyCtxt < ' tcx > ,
1395+ def_id : Option < DefId > ,
1396+ fn_ident : Ident ,
1397+ skip_move_check_fns : & mut Vec < DefId > ,
1398+ ) {
1399+ if let Some ( def_id) = def_id. and_then ( |def_id| assoc_fn_of_type ( tcx, def_id, fn_ident) ) {
1400+ skip_move_check_fns. push ( def_id) ;
1401+ }
1402+ }
1403+
1404+ fn assoc_fn_of_type < ' tcx > ( tcx : TyCtxt < ' tcx > , def_id : DefId , fn_ident : Ident ) -> Option < DefId > {
1405+ for impl_def_id in tcx. inherent_impls ( def_id) {
1406+ if let Some ( new) = tcx. associated_items ( impl_def_id) . find_by_name_and_kind (
1407+ tcx,
1408+ fn_ident,
1409+ AssocKind :: Fn ,
1410+ def_id,
1411+ ) {
1412+ return Some ( new. def_id ) ;
1413+ }
1414+ }
1415+ return None ;
1416+ }
1417+
13681418/// Scans the MIR in order to find function calls, closures, and drop-glue.
13691419#[ instrument( skip( tcx, output) , level = "debug" ) ]
13701420fn collect_used_items < ' tcx > (
@@ -1373,8 +1423,39 @@ fn collect_used_items<'tcx>(
13731423 output : & mut MonoItems < ' tcx > ,
13741424) {
13751425 let body = tcx. instance_mir ( instance. def ) ;
1376- MirUsedCollector { tcx, body : & body, output, instance, move_size_spans : vec ! [ ] }
1377- . visit_body ( & body) ;
1426+
1427+ let mut skip_move_check_fns = vec ! [ ] ;
1428+ if tcx. move_size_limit ( ) . 0 > 0 {
1429+ add_assoc_fn (
1430+ tcx,
1431+ tcx. lang_items ( ) . owned_box ( ) ,
1432+ Ident :: from_str ( "new" ) ,
1433+ & mut skip_move_check_fns,
1434+ ) ;
1435+ add_assoc_fn (
1436+ tcx,
1437+ tcx. get_diagnostic_item ( sym:: Arc ) ,
1438+ Ident :: from_str ( "new" ) ,
1439+ & mut skip_move_check_fns,
1440+ ) ;
1441+ add_assoc_fn (
1442+ tcx,
1443+ tcx. get_diagnostic_item ( sym:: Rc ) ,
1444+ Ident :: from_str ( "new" ) ,
1445+ & mut skip_move_check_fns,
1446+ ) ;
1447+ }
1448+
1449+ MirUsedCollector {
1450+ tcx,
1451+ body : & body,
1452+ output,
1453+ instance,
1454+ move_size_spans : vec ! [ ] ,
1455+ skip_move_size_check : false ,
1456+ skip_move_check_fns,
1457+ }
1458+ . visit_body ( & body) ;
13781459}
13791460
13801461#[ instrument( skip( tcx, output) , level = "debug" ) ]
0 commit comments