205
205
//! this is not implemented however: a mono item will be produced
206
206
//! regardless of whether it is actually needed or not.
207
207
208
+ mod move_check;
209
+
208
210
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
209
211
use rustc_data_structures:: sync:: { par_for_each_in, LRef , MTLock } ;
210
212
use rustc_hir as hir;
@@ -227,7 +229,6 @@ use rustc_middle::ty::{
227
229
} ;
228
230
use rustc_middle:: ty:: { GenericArgKind , GenericArgs } ;
229
231
use rustc_session:: config:: EntryFnType ;
230
- use rustc_session:: lint:: builtin:: LARGE_ASSIGNMENTS ;
231
232
use rustc_session:: Limit ;
232
233
use rustc_span:: source_map:: { dummy_spanned, respan, Spanned } ;
233
234
use rustc_span:: symbol:: { sym, Ident } ;
@@ -236,9 +237,9 @@ use rustc_target::abi::Size;
236
237
use std:: path:: PathBuf ;
237
238
238
239
use crate :: errors:: {
239
- self , EncounteredErrorWhileInstantiating , LargeAssignmentsLint , NoOptimizedMir , RecursionLimit ,
240
- TypeLengthLimit ,
240
+ self , EncounteredErrorWhileInstantiating , NoOptimizedMir , RecursionLimit , TypeLengthLimit ,
241
241
} ;
242
+ use move_check:: MoveCheckState ;
242
243
243
244
#[ derive( PartialEq ) ]
244
245
pub enum MonoItemCollectionStrategy {
@@ -667,11 +668,8 @@ struct MirUsedCollector<'a, 'tcx> {
667
668
/// Note that this contains *not-monomorphized* items!
668
669
used_mentioned_items : & ' a mut FxHashSet < MentionedItem < ' tcx > > ,
669
670
instance : Instance < ' tcx > ,
670
- /// Spans for move size lints already emitted. Helps avoid duplicate lints.
671
- move_size_spans : Vec < Span > ,
672
671
visiting_call_terminator : bool ,
673
- /// Set of functions for which it is OK to move large data into.
674
- skip_move_check_fns : Option < Vec < DefId > > ,
672
+ move_check : move_check:: MoveCheckState ,
675
673
}
676
674
677
675
impl < ' a , ' tcx > MirUsedCollector < ' a , ' tcx > {
@@ -687,124 +685,6 @@ impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> {
687
685
)
688
686
}
689
687
690
- fn check_operand_move_size ( & mut self , operand : & mir:: Operand < ' tcx > , location : Location ) {
691
- let limit = self . tcx . move_size_limit ( ) ;
692
- if limit. 0 == 0 {
693
- return ;
694
- }
695
-
696
- // This function is called by visit_operand() which visits _all_
697
- // operands, including TerminatorKind::Call operands. But if
698
- // check_fn_args_move_size() has been called, the operands have already
699
- // been visited. Do not visit them again.
700
- if self . visiting_call_terminator {
701
- return ;
702
- }
703
-
704
- let source_info = self . body . source_info ( location) ;
705
- debug ! ( ?source_info) ;
706
-
707
- if let Some ( too_large_size) = self . operand_size_if_too_large ( limit, operand) {
708
- self . lint_large_assignment ( limit. 0 , too_large_size, location, source_info. span ) ;
709
- } ;
710
- }
711
-
712
- fn check_fn_args_move_size (
713
- & mut self ,
714
- callee_ty : Ty < ' tcx > ,
715
- args : & [ Spanned < mir:: Operand < ' tcx > > ] ,
716
- fn_span : Span ,
717
- location : Location ,
718
- ) {
719
- let limit = self . tcx . move_size_limit ( ) ;
720
- if limit. 0 == 0 {
721
- return ;
722
- }
723
-
724
- if args. is_empty ( ) {
725
- return ;
726
- }
727
-
728
- // Allow large moves into container types that themselves are cheap to move
729
- let ty:: FnDef ( def_id, _) = * callee_ty. kind ( ) else {
730
- return ;
731
- } ;
732
- if self
733
- . skip_move_check_fns
734
- . get_or_insert_with ( || build_skip_move_check_fns ( self . tcx ) )
735
- . contains ( & def_id)
736
- {
737
- return ;
738
- }
739
-
740
- debug ! ( ?def_id, ?fn_span) ;
741
-
742
- for arg in args {
743
- // Moving args into functions is typically implemented with pointer
744
- // passing at the llvm-ir level and not by memcpy's. So always allow
745
- // moving args into functions.
746
- let operand: & mir:: Operand < ' tcx > = & arg. node ;
747
- if let mir:: Operand :: Move ( _) = operand {
748
- continue ;
749
- }
750
-
751
- if let Some ( too_large_size) = self . operand_size_if_too_large ( limit, operand) {
752
- self . lint_large_assignment ( limit. 0 , too_large_size, location, arg. span ) ;
753
- } ;
754
- }
755
- }
756
-
757
- fn operand_size_if_too_large (
758
- & mut self ,
759
- limit : Limit ,
760
- operand : & mir:: Operand < ' tcx > ,
761
- ) -> Option < Size > {
762
- let ty = operand. ty ( self . body , self . tcx ) ;
763
- let ty = self . monomorphize ( ty) ;
764
- let Ok ( layout) = self . tcx . layout_of ( ty:: ParamEnv :: reveal_all ( ) . and ( ty) ) else {
765
- return None ;
766
- } ;
767
- if layout. size . bytes_usize ( ) > limit. 0 {
768
- debug ! ( ?layout) ;
769
- Some ( layout. size )
770
- } else {
771
- None
772
- }
773
- }
774
-
775
- fn lint_large_assignment (
776
- & mut self ,
777
- limit : usize ,
778
- too_large_size : Size ,
779
- location : Location ,
780
- span : Span ,
781
- ) {
782
- let source_info = self . body . source_info ( location) ;
783
- debug ! ( ?source_info) ;
784
- for reported_span in & self . move_size_spans {
785
- if reported_span. overlaps ( span) {
786
- return ;
787
- }
788
- }
789
- let lint_root = source_info. scope . lint_root ( & self . body . source_scopes ) ;
790
- debug ! ( ?lint_root) ;
791
- let Some ( lint_root) = lint_root else {
792
- // This happens when the issue is in a function from a foreign crate that
793
- // we monomorphized in the current crate. We can't get a `HirId` for things
794
- // in other crates.
795
- // FIXME: Find out where to report the lint on. Maybe simply crate-level lint root
796
- // but correct span? This would make the lint at least accept crate-level lint attributes.
797
- return ;
798
- } ;
799
- self . tcx . emit_node_span_lint (
800
- LARGE_ASSIGNMENTS ,
801
- lint_root,
802
- span,
803
- LargeAssignmentsLint { span, size : too_large_size. bytes ( ) , limit : limit as u64 } ,
804
- ) ;
805
- self . move_size_spans . push ( span) ;
806
- }
807
-
808
688
/// Evaluates a *not yet monomorphized* constant.
809
689
fn eval_constant (
810
690
& mut self ,
@@ -1367,19 +1247,6 @@ fn assoc_fn_of_type<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, fn_ident: Ident) ->
1367
1247
return None ;
1368
1248
}
1369
1249
1370
- fn build_skip_move_check_fns ( tcx : TyCtxt < ' _ > ) -> Vec < DefId > {
1371
- let fns = [
1372
- ( tcx. lang_items ( ) . owned_box ( ) , "new" ) ,
1373
- ( tcx. get_diagnostic_item ( sym:: Rc ) , "new" ) ,
1374
- ( tcx. get_diagnostic_item ( sym:: Arc ) , "new" ) ,
1375
- ] ;
1376
- fns. into_iter ( )
1377
- . filter_map ( |( def_id, fn_name) | {
1378
- def_id. and_then ( |def_id| assoc_fn_of_type ( tcx, def_id, Ident :: from_str ( fn_name) ) )
1379
- } )
1380
- . collect :: < Vec < _ > > ( )
1381
- }
1382
-
1383
1250
/// Scans the MIR in order to find function calls, closures, and drop-glue.
1384
1251
///
1385
1252
/// Anything that's found is added to `output`. Furthermore the "mentioned items" of the MIR are returned.
@@ -1409,9 +1276,8 @@ fn collect_items_of_instance<'tcx>(
1409
1276
used_items,
1410
1277
used_mentioned_items : & mut used_mentioned_items,
1411
1278
instance,
1412
- move_size_spans : vec ! [ ] ,
1413
1279
visiting_call_terminator : false ,
1414
- skip_move_check_fns : None ,
1280
+ move_check : MoveCheckState :: new ( ) ,
1415
1281
} ;
1416
1282
1417
1283
if mode == CollectionMode :: UsedItems {
0 commit comments