11//! Inlining pass for MIR functions
22use crate :: deref_separator:: deref_finder;
33use rustc_attr:: InlineAttr ;
4+ use rustc_const_eval:: transform:: validate:: validate_types;
45use rustc_hir:: def_id:: DefId ;
56use rustc_index:: bit_set:: BitSet ;
67use rustc_index:: Idx ;
@@ -10,7 +11,7 @@ use rustc_middle::mir::*;
1011use rustc_middle:: ty:: TypeVisitableExt ;
1112use rustc_middle:: ty:: { self , Instance , InstanceDef , ParamEnv , Ty , TyCtxt } ;
1213use rustc_session:: config:: OptLevel ;
13- use rustc_target:: abi:: { FieldIdx , FIRST_VARIANT } ;
14+ use rustc_target:: abi:: FieldIdx ;
1415use rustc_target:: spec:: abi:: Abi ;
1516
1617use crate :: simplify:: { remove_dead_blocks, CfgSimplifier } ;
@@ -200,6 +201,19 @@ impl<'tcx> Inliner<'tcx> {
200201 return Err ( "failed to normalize callee body" ) ;
201202 } ;
202203
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+
203217 // Check call signature compatibility.
204218 // Normally, this shouldn't be required, but trait normalization failure can create a
205219 // validation ICE.
@@ -437,13 +451,8 @@ impl<'tcx> Inliner<'tcx> {
437451 instance : callsite. callee ,
438452 callee_body,
439453 cost : 0 ,
440- validation : Ok ( ( ) ) ,
441454 } ;
442455
443- for var_debug_info in callee_body. var_debug_info . iter ( ) {
444- checker. visit_var_debug_info ( var_debug_info) ;
445- }
446-
447456 // Traverse the MIR manually so we can account for the effects of inlining on the CFG.
448457 let mut work_list = vec ! [ START_BLOCK ] ;
449458 let mut visited = BitSet :: new_empty ( callee_body. basic_blocks . len ( ) ) ;
@@ -480,9 +489,6 @@ impl<'tcx> Inliner<'tcx> {
480489 }
481490 }
482491
483- // Abort if type validation found anything fishy.
484- checker. validation ?;
485-
486492 // N.B. We still apply our cost threshold to #[inline(always)] functions.
487493 // That attribute is often applied to very large functions that exceed LLVM's (very
488494 // generous) inlining threshold. Such functions are very poor MIR inlining candidates.
@@ -774,11 +780,10 @@ struct CostChecker<'b, 'tcx> {
774780 cost : usize ,
775781 callee_body : & ' b Body < ' tcx > ,
776782 instance : ty:: Instance < ' tcx > ,
777- validation : Result < ( ) , & ' static str > ,
778783}
779784
780785impl < ' 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 ) {
782787 // Don't count StorageLive/StorageDead in the inlining cost.
783788 match statement. kind {
784789 StatementKind :: StorageLive ( _)
@@ -787,11 +792,9 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
787792 | StatementKind :: Nop => { }
788793 _ => self . cost += INSTR_COST ,
789794 }
790-
791- self . super_statement ( statement, location) ;
792795 }
793796
794- fn visit_terminator ( & mut self , terminator : & Terminator < ' tcx > , location : Location ) {
797+ fn visit_terminator ( & mut self , terminator : & Terminator < ' tcx > , _ : Location ) {
795798 let tcx = self . tcx ;
796799 match terminator. kind {
797800 TerminatorKind :: Drop { ref place, unwind, .. } => {
@@ -835,109 +838,6 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
835838 }
836839 _ => self . cost += INSTR_COST ,
837840 }
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) ;
941841 }
942842}
943843
0 commit comments