Skip to content

Commit b6cd700

Browse files
committed
Reuse MIR validator for inliner.
1 parent 2ef2ac0 commit b6cd700

File tree

2 files changed

+18
-118
lines changed

2 files changed

+18
-118
lines changed

compiler/rustc_const_eval/src/transform/validate.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
499499
}
500500
}
501501

502-
fn validate_types<'tcx>(
502+
pub fn validate_types<'tcx>(
503503
tcx: TyCtxt<'tcx>,
504504
mir_phase: MirPhase,
505505
param_env: ty::ParamEnv<'tcx>,

compiler/rustc_mir_transform/src/inline.rs

Lines changed: 17 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Inlining pass for MIR functions
22
use crate::deref_separator::deref_finder;
33
use rustc_attr::InlineAttr;
4+
use rustc_const_eval::transform::validate::validate_types;
45
use rustc_hir::def_id::DefId;
56
use rustc_index::bit_set::BitSet;
67
use rustc_index::Idx;
@@ -10,7 +11,7 @@ use rustc_middle::mir::*;
1011
use rustc_middle::ty::TypeVisitableExt;
1112
use rustc_middle::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt};
1213
use rustc_session::config::OptLevel;
13-
use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
14+
use rustc_target::abi::FieldIdx;
1415
use rustc_target::spec::abi::Abi;
1516

1617
use 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

780785
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) {
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

Comments
 (0)