@@ -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
@@ -432,7 +433,7 @@ fn collect_items_rec<'tcx>(
432433 hir:: InlineAsmOperand :: SymFn { anon_const } => {
433434 let fn_ty =
434435 tcx. typeck_body ( anon_const. body ) . node_type ( anon_const. hir_id ) ;
435- visit_fn_use ( tcx, fn_ty, false , * op_sp, & mut used_items) ;
436+ visit_fn_use ( tcx, fn_ty, false , * op_sp, & mut used_items, & [ ] ) ;
436437 }
437438 hir:: InlineAsmOperand :: SymStatic { path : _, def_id } => {
438439 let instance = Instance :: mono ( tcx, * def_id) ;
@@ -593,6 +594,11 @@ struct MirUsedCollector<'a, 'tcx> {
593594 instance : Instance < ' tcx > ,
594595 /// Spans for move size lints already emitted. Helps avoid duplicate lints.
595596 move_size_spans : Vec < Span > ,
597+ /// If true, we should temporarily skip move size checks, because we are
598+ /// processing an operand to a `skip_move_check_fns` function call.
599+ skip_move_size_check : bool ,
600+ /// Set of functions for which it is OK to move large data into.
601+ skip_move_check_fns : Vec < DefId > ,
596602}
597603
598604impl < ' a , ' tcx > MirUsedCollector < ' a , ' tcx > {
@@ -691,7 +697,14 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
691697 ) => {
692698 let fn_ty = operand. ty ( self . body , self . tcx ) ;
693699 let fn_ty = self . monomorphize ( fn_ty) ;
694- visit_fn_use ( self . tcx , fn_ty, false , span, & mut self . output ) ;
700+ visit_fn_use (
701+ self . tcx ,
702+ fn_ty,
703+ false ,
704+ span,
705+ & mut self . output ,
706+ & self . skip_move_check_fns ,
707+ ) ;
695708 }
696709 mir:: Rvalue :: Cast (
697710 mir:: CastKind :: PointerCoercion ( PointerCoercion :: ClosureFnPointer ( _) ) ,
@@ -790,7 +803,14 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
790803 mir:: TerminatorKind :: Call { ref func, .. } => {
791804 let callee_ty = func. ty ( self . body , tcx) ;
792805 let callee_ty = self . monomorphize ( callee_ty) ;
793- visit_fn_use ( self . tcx , callee_ty, true , source, & mut self . output )
806+ self . skip_move_size_check = visit_fn_use (
807+ self . tcx ,
808+ callee_ty,
809+ true ,
810+ source,
811+ & mut self . output ,
812+ & self . skip_move_check_fns ,
813+ )
794814 }
795815 mir:: TerminatorKind :: Drop { ref place, .. } => {
796816 let ty = place. ty ( self . body , self . tcx ) . ty ;
@@ -802,7 +822,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
802822 match * op {
803823 mir:: InlineAsmOperand :: SymFn { ref value } => {
804824 let fn_ty = self . monomorphize ( value. literal . ty ( ) ) ;
805- visit_fn_use ( self . tcx , fn_ty, false , source, & mut self . output ) ;
825+ visit_fn_use ( self . tcx , fn_ty, false , source, & mut self . output , & [ ] ) ;
806826 }
807827 mir:: InlineAsmOperand :: SymStatic { def_id } => {
808828 let instance = Instance :: mono ( self . tcx , def_id) ;
@@ -841,12 +861,13 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
841861 }
842862
843863 self . super_terminator ( terminator, location) ;
864+ self . skip_move_size_check = false ;
844865 }
845866
846867 fn visit_operand ( & mut self , operand : & mir:: Operand < ' tcx > , location : Location ) {
847868 self . super_operand ( operand, location) ;
848869 let move_size_limit = self . tcx . move_size_limit ( ) . 0 ;
849- if move_size_limit > 0 {
870+ if move_size_limit > 0 && ! self . skip_move_size_check {
850871 self . check_move_size ( move_size_limit, operand, location) ;
851872 }
852873 }
@@ -877,8 +898,11 @@ fn visit_fn_use<'tcx>(
877898 is_direct_call : bool ,
878899 source : Span ,
879900 output : & mut MonoItems < ' tcx > ,
880- ) {
901+ skip_move_check_fns : & [ DefId ] ,
902+ ) -> bool {
903+ let mut skip_move_size_check = false ;
881904 if let ty:: FnDef ( def_id, args) = * ty. kind ( ) {
905+ skip_move_size_check = skip_move_check_fns. contains ( & def_id) ;
882906 let instance = if is_direct_call {
883907 ty:: Instance :: expect_resolve ( tcx, ty:: ParamEnv :: reveal_all ( ) , def_id, args)
884908 } else {
@@ -889,6 +913,7 @@ fn visit_fn_use<'tcx>(
889913 } ;
890914 visit_instance_use ( tcx, instance, is_direct_call, source, output) ;
891915 }
916+ skip_move_size_check
892917}
893918
894919fn visit_instance_use < ' tcx > (
@@ -1369,6 +1394,31 @@ fn collect_alloc<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoIt
13691394 }
13701395}
13711396
1397+ fn add_assoc_fn < ' tcx > (
1398+ tcx : TyCtxt < ' tcx > ,
1399+ def_id : Option < DefId > ,
1400+ fn_ident : Ident ,
1401+ skip_move_check_fns : & mut Vec < DefId > ,
1402+ ) {
1403+ if let Some ( def_id) = def_id. and_then ( |def_id| assoc_fn_of_type ( tcx, def_id, fn_ident) ) {
1404+ skip_move_check_fns. push ( def_id) ;
1405+ }
1406+ }
1407+
1408+ fn assoc_fn_of_type < ' tcx > ( tcx : TyCtxt < ' tcx > , def_id : DefId , fn_ident : Ident ) -> Option < DefId > {
1409+ for impl_def_id in tcx. inherent_impls ( def_id) {
1410+ if let Some ( new) = tcx. associated_items ( impl_def_id) . find_by_name_and_kind (
1411+ tcx,
1412+ fn_ident,
1413+ AssocKind :: Fn ,
1414+ def_id,
1415+ ) {
1416+ return Some ( new. def_id ) ;
1417+ }
1418+ }
1419+ return None ;
1420+ }
1421+
13721422/// Scans the MIR in order to find function calls, closures, and drop-glue.
13731423#[ instrument( skip( tcx, output) , level = "debug" ) ]
13741424fn collect_used_items < ' tcx > (
@@ -1377,8 +1427,39 @@ fn collect_used_items<'tcx>(
13771427 output : & mut MonoItems < ' tcx > ,
13781428) {
13791429 let body = tcx. instance_mir ( instance. def ) ;
1380- MirUsedCollector { tcx, body : & body, output, instance, move_size_spans : vec ! [ ] }
1381- . visit_body ( & body) ;
1430+
1431+ let mut skip_move_check_fns = vec ! [ ] ;
1432+ if tcx. move_size_limit ( ) . 0 > 0 {
1433+ add_assoc_fn (
1434+ tcx,
1435+ tcx. lang_items ( ) . owned_box ( ) ,
1436+ Ident :: from_str ( "new" ) ,
1437+ & mut skip_move_check_fns,
1438+ ) ;
1439+ add_assoc_fn (
1440+ tcx,
1441+ tcx. get_diagnostic_item ( sym:: Arc ) ,
1442+ Ident :: from_str ( "new" ) ,
1443+ & mut skip_move_check_fns,
1444+ ) ;
1445+ add_assoc_fn (
1446+ tcx,
1447+ tcx. get_diagnostic_item ( sym:: Rc ) ,
1448+ Ident :: from_str ( "new" ) ,
1449+ & mut skip_move_check_fns,
1450+ ) ;
1451+ }
1452+
1453+ MirUsedCollector {
1454+ tcx,
1455+ body : & body,
1456+ output,
1457+ instance,
1458+ move_size_spans : vec ! [ ] ,
1459+ skip_move_size_check : false ,
1460+ skip_move_check_fns,
1461+ }
1462+ . visit_body ( & body) ;
13821463}
13831464
13841465#[ instrument( skip( tcx, output) , level = "debug" ) ]
0 commit comments