1
1
//! Inlining pass for MIR functions
2
2
use crate :: deref_separator:: deref_finder;
3
3
use rustc_attr:: InlineAttr ;
4
+ use rustc_const_eval:: transform:: validate:: validate_types;
4
5
use rustc_hir:: def_id:: DefId ;
5
6
use rustc_index:: bit_set:: BitSet ;
6
7
use rustc_index:: Idx ;
@@ -10,7 +11,7 @@ use rustc_middle::mir::*;
10
11
use rustc_middle:: ty:: TypeVisitableExt ;
11
12
use rustc_middle:: ty:: { self , Instance , InstanceDef , ParamEnv , Ty , TyCtxt } ;
12
13
use rustc_session:: config:: OptLevel ;
13
- use rustc_target:: abi:: { FieldIdx , FIRST_VARIANT } ;
14
+ use rustc_target:: abi:: FieldIdx ;
14
15
use rustc_target:: spec:: abi:: Abi ;
15
16
16
17
use crate :: simplify:: { remove_dead_blocks, CfgSimplifier } ;
@@ -200,6 +201,19 @@ impl<'tcx> Inliner<'tcx> {
200
201
return Err ( "failed to normalize callee body" ) ;
201
202
} ;
202
203
204
+ // Normally, this shouldn't be required, but trait normalization failure can create a
205
+ // validation ICE.
206
+ if !validate_types (
207
+ self . tcx ,
208
+ MirPhase :: Runtime ( RuntimePhase :: Optimized ) ,
209
+ self . param_env ,
210
+ & callee_body,
211
+ )
212
+ . is_empty ( )
213
+ {
214
+ return Err ( "failed to validate callee body" ) ;
215
+ }
216
+
203
217
// Check call signature compatibility.
204
218
// Normally, this shouldn't be required, but trait normalization failure can create a
205
219
// validation ICE.
@@ -437,13 +451,8 @@ impl<'tcx> Inliner<'tcx> {
437
451
instance : callsite. callee ,
438
452
callee_body,
439
453
cost : 0 ,
440
- validation : Ok ( ( ) ) ,
441
454
} ;
442
455
443
- for var_debug_info in callee_body. var_debug_info . iter ( ) {
444
- checker. visit_var_debug_info ( var_debug_info) ;
445
- }
446
-
447
456
// Traverse the MIR manually so we can account for the effects of inlining on the CFG.
448
457
let mut work_list = vec ! [ START_BLOCK ] ;
449
458
let mut visited = BitSet :: new_empty ( callee_body. basic_blocks . len ( ) ) ;
@@ -480,9 +489,6 @@ impl<'tcx> Inliner<'tcx> {
480
489
}
481
490
}
482
491
483
- // Abort if type validation found anything fishy.
484
- checker. validation ?;
485
-
486
492
// N.B. We still apply our cost threshold to #[inline(always)] functions.
487
493
// That attribute is often applied to very large functions that exceed LLVM's (very
488
494
// generous) inlining threshold. Such functions are very poor MIR inlining candidates.
@@ -774,11 +780,10 @@ struct CostChecker<'b, 'tcx> {
774
780
cost : usize ,
775
781
callee_body : & ' b Body < ' tcx > ,
776
782
instance : ty:: Instance < ' tcx > ,
777
- validation : Result < ( ) , & ' static str > ,
778
783
}
779
784
780
785
impl < ' tcx > Visitor < ' tcx > for CostChecker < ' _ , ' tcx > {
781
- fn visit_statement ( & mut self , statement : & Statement < ' tcx > , location : Location ) {
786
+ fn visit_statement ( & mut self , statement : & Statement < ' tcx > , _ : Location ) {
782
787
// Don't count StorageLive/StorageDead in the inlining cost.
783
788
match statement. kind {
784
789
StatementKind :: StorageLive ( _)
@@ -787,11 +792,9 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
787
792
| StatementKind :: Nop => { }
788
793
_ => self . cost += INSTR_COST ,
789
794
}
790
-
791
- self . super_statement ( statement, location) ;
792
795
}
793
796
794
- fn visit_terminator ( & mut self , terminator : & Terminator < ' tcx > , location : Location ) {
797
+ fn visit_terminator ( & mut self , terminator : & Terminator < ' tcx > , _ : Location ) {
795
798
let tcx = self . tcx ;
796
799
match terminator. kind {
797
800
TerminatorKind :: Drop { ref place, unwind, .. } => {
@@ -835,109 +838,6 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
835
838
}
836
839
_ => self . cost += INSTR_COST ,
837
840
}
838
-
839
- self . super_terminator ( terminator, location) ;
840
- }
841
-
842
- /// This method duplicates code from MIR validation in an attempt to detect type mismatches due
843
- /// to normalization failure.
844
- fn visit_projection_elem (
845
- & mut self ,
846
- place_ref : PlaceRef < ' tcx > ,
847
- elem : PlaceElem < ' tcx > ,
848
- context : PlaceContext ,
849
- location : Location ,
850
- ) {
851
- if let ProjectionElem :: Field ( f, ty) = elem {
852
- let parent_ty = place_ref. ty ( & self . callee_body . local_decls , self . tcx ) ;
853
- let check_equal = |this : & mut Self , f_ty| {
854
- // Fast path if there is nothing to substitute.
855
- if ty == f_ty {
856
- return ;
857
- }
858
- let ty = this. instance . subst_mir ( this. tcx , ty:: EarlyBinder :: bind ( & ty) ) ;
859
- let f_ty = this. instance . subst_mir ( this. tcx , ty:: EarlyBinder :: bind ( & f_ty) ) ;
860
- if ty == f_ty {
861
- return ;
862
- }
863
- if !util:: is_subtype ( this. tcx , this. param_env , ty, f_ty) {
864
- trace ! ( ?ty, ?f_ty) ;
865
- this. validation = Err ( "failed to normalize projection type" ) ;
866
- return ;
867
- }
868
- } ;
869
-
870
- let kind = match parent_ty. ty . kind ( ) {
871
- & ty:: Alias ( ty:: Opaque , ty:: AliasTy { def_id, args, .. } ) => {
872
- self . tcx . type_of ( def_id) . instantiate ( self . tcx , args) . kind ( )
873
- }
874
- kind => kind,
875
- } ;
876
-
877
- match kind {
878
- ty:: Tuple ( fields) => {
879
- let Some ( f_ty) = fields. get ( f. as_usize ( ) ) else {
880
- self . validation = Err ( "malformed MIR" ) ;
881
- return ;
882
- } ;
883
- check_equal ( self , * f_ty) ;
884
- }
885
- ty:: Adt ( adt_def, args) => {
886
- let var = parent_ty. variant_index . unwrap_or ( FIRST_VARIANT ) ;
887
- let Some ( field) = adt_def. variant ( var) . fields . get ( f) else {
888
- self . validation = Err ( "malformed MIR" ) ;
889
- return ;
890
- } ;
891
- check_equal ( self , field. ty ( self . tcx , args) ) ;
892
- }
893
- ty:: Closure ( _, args) => {
894
- let args = args. as_closure ( ) ;
895
- let Some ( f_ty) = args. upvar_tys ( ) . nth ( f. as_usize ( ) ) else {
896
- self . validation = Err ( "malformed MIR" ) ;
897
- return ;
898
- } ;
899
- check_equal ( self , f_ty) ;
900
- }
901
- & ty:: Generator ( def_id, args, _) => {
902
- let f_ty = if let Some ( var) = parent_ty. variant_index {
903
- let gen_body = if def_id == self . callee_body . source . def_id ( ) {
904
- self . callee_body
905
- } else {
906
- self . tcx . optimized_mir ( def_id)
907
- } ;
908
-
909
- let Some ( layout) = gen_body. generator_layout ( ) else {
910
- self . validation = Err ( "malformed MIR" ) ;
911
- return ;
912
- } ;
913
-
914
- let Some ( & local) = layout. variant_fields [ var] . get ( f) else {
915
- self . validation = Err ( "malformed MIR" ) ;
916
- return ;
917
- } ;
918
-
919
- let Some ( f_ty) = layout. field_tys . get ( local) else {
920
- self . validation = Err ( "malformed MIR" ) ;
921
- return ;
922
- } ;
923
-
924
- f_ty. ty
925
- } else {
926
- let Some ( f_ty) = args. as_generator ( ) . prefix_tys ( ) . nth ( f. index ( ) ) else {
927
- self . validation = Err ( "malformed MIR" ) ;
928
- return ;
929
- } ;
930
-
931
- f_ty
932
- } ;
933
-
934
- check_equal ( self , f_ty) ;
935
- }
936
- _ => self . validation = Err ( "malformed MIR" ) ,
937
- }
938
- }
939
-
940
- self . super_projection_elem ( place_ref, elem, context, location) ;
941
841
}
942
842
}
943
843
0 commit comments