@@ -179,15 +179,16 @@ use rustc_middle::query::TyCtxtAt;
179
179
use rustc_middle:: ty:: adjustment:: { CustomCoerceUnsized , PointerCoercion } ;
180
180
use rustc_middle:: ty:: print:: with_no_trimmed_paths;
181
181
use 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 ,
184
184
} ;
185
185
use rustc_middle:: ty:: { GenericArgKind , GenericArgs } ;
186
186
use rustc_middle:: { middle:: codegen_fn_attrs:: CodegenFnAttrFlags , mir:: visit:: TyContext } ;
187
187
use rustc_session:: config:: EntryFnType ;
188
188
use rustc_session:: lint:: builtin:: LARGE_ASSIGNMENTS ;
189
189
use rustc_session:: Limit ;
190
190
use rustc_span:: source_map:: { dummy_spanned, respan, Span , Spanned , DUMMY_SP } ;
191
+ use rustc_span:: symbol:: { sym, Ident } ;
191
192
use rustc_target:: abi:: Size ;
192
193
use std:: path:: PathBuf ;
193
194
@@ -431,7 +432,7 @@ fn collect_items_rec<'tcx>(
431
432
hir:: InlineAsmOperand :: SymFn { anon_const } => {
432
433
let fn_ty =
433
434
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, & [ ] ) ;
435
436
}
436
437
hir:: InlineAsmOperand :: SymStatic { path : _, def_id } => {
437
438
let instance = Instance :: mono ( tcx, * def_id) ;
@@ -592,6 +593,11 @@ struct MirUsedCollector<'a, 'tcx> {
592
593
instance : Instance < ' tcx > ,
593
594
/// Spans for move size lints already emitted. Helps avoid duplicate lints.
594
595
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 > ,
595
601
}
596
602
597
603
impl < ' a , ' tcx > MirUsedCollector < ' a , ' tcx > {
@@ -690,7 +696,14 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
690
696
) => {
691
697
let fn_ty = operand. ty ( self . body , self . tcx ) ;
692
698
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
+ ) ;
694
707
}
695
708
mir:: Rvalue :: Cast (
696
709
mir:: CastKind :: PointerCoercion ( PointerCoercion :: ClosureFnPointer ( _) ) ,
@@ -789,7 +802,14 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
789
802
mir:: TerminatorKind :: Call { ref func, .. } => {
790
803
let callee_ty = func. ty ( self . body , tcx) ;
791
804
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
+ )
793
813
}
794
814
mir:: TerminatorKind :: Drop { ref place, .. } => {
795
815
let ty = place. ty ( self . body , self . tcx ) . ty ;
@@ -801,7 +821,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
801
821
match * op {
802
822
mir:: InlineAsmOperand :: SymFn { ref value } => {
803
823
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 , & [ ] ) ;
805
825
}
806
826
mir:: InlineAsmOperand :: SymStatic { def_id } => {
807
827
let instance = Instance :: mono ( self . tcx , def_id) ;
@@ -840,12 +860,13 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
840
860
}
841
861
842
862
self . super_terminator ( terminator, location) ;
863
+ self . skip_move_size_check = false ;
843
864
}
844
865
845
866
fn visit_operand ( & mut self , operand : & mir:: Operand < ' tcx > , location : Location ) {
846
867
self . super_operand ( operand, location) ;
847
868
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 {
849
870
self . check_move_size ( move_size_limit, operand, location) ;
850
871
}
851
872
}
@@ -876,8 +897,11 @@ fn visit_fn_use<'tcx>(
876
897
is_direct_call : bool ,
877
898
source : Span ,
878
899
output : & mut MonoItems < ' tcx > ,
879
- ) {
900
+ skip_move_check_fns : & [ DefId ] ,
901
+ ) -> bool {
902
+ let mut skip_move_size_check = false ;
880
903
if let ty:: FnDef ( def_id, args) = * ty. kind ( ) {
904
+ skip_move_size_check = skip_move_check_fns. contains ( & def_id) ;
881
905
let instance = if is_direct_call {
882
906
ty:: Instance :: expect_resolve ( tcx, ty:: ParamEnv :: reveal_all ( ) , def_id, args)
883
907
} else {
@@ -888,6 +912,7 @@ fn visit_fn_use<'tcx>(
888
912
} ;
889
913
visit_instance_use ( tcx, instance, is_direct_call, source, output) ;
890
914
}
915
+ skip_move_size_check
891
916
}
892
917
893
918
fn visit_instance_use < ' tcx > (
@@ -1365,6 +1390,31 @@ fn collect_alloc<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoIt
1365
1390
}
1366
1391
}
1367
1392
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
+
1368
1418
/// Scans the MIR in order to find function calls, closures, and drop-glue.
1369
1419
#[ instrument( skip( tcx, output) , level = "debug" ) ]
1370
1420
fn collect_used_items < ' tcx > (
@@ -1373,8 +1423,39 @@ fn collect_used_items<'tcx>(
1373
1423
output : & mut MonoItems < ' tcx > ,
1374
1424
) {
1375
1425
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) ;
1378
1459
}
1379
1460
1380
1461
#[ instrument( skip( tcx, output) , level = "debug" ) ]
0 commit comments