diff --git a/compiler/rustc_mir/src/transform/inline.rs b/compiler/rustc_mir/src/transform/inline.rs index bec1eb79047..e0bd4e8b68b 100644 --- a/compiler/rustc_mir/src/transform/inline.rs +++ b/compiler/rustc_mir/src/transform/inline.rs @@ -201,9 +201,13 @@ impl Inliner<'tcx> { let terminator = bb_data.terminator(); if let TerminatorKind::Call { func: ref op, .. } = terminator.kind { if let ty::FnDef(callee_def_id, substs) = *op.ty(caller_body, self.tcx).kind() { - let instance = Instance::resolve(self.tcx, self.param_env, callee_def_id, substs) - .ok() - .flatten()?; + // To resolve an instance its substs have to be fully normalized, so + // we do this here. + let normalized_substs = self.tcx.normalize_erasing_regions(self.param_env, substs); + let instance = + Instance::resolve(self.tcx, self.param_env, callee_def_id, normalized_substs) + .ok() + .flatten()?; if let InstanceDef::Virtual(..) = instance.def { return None; diff --git a/compiler/rustc_trait_selection/src/traits/codegen/mod.rs b/compiler/rustc_trait_selection/src/traits/codegen/mod.rs index 753d64d6115..05e6c4804ff 100644 --- a/compiler/rustc_trait_selection/src/traits/codegen/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/codegen/mod.rs @@ -17,14 +17,17 @@ use rustc_middle::ty::{self, TyCtxt}; /// (necessarily) resolve all nested obligations on the impl. Note /// that type check should guarantee to us that all nested /// obligations *could be* resolved if we wanted to. +/// /// Assumes that this is run after the entire crate has been successfully type-checked. +/// This also expects that `trait_ref` is fully normalized. pub fn codegen_fulfill_obligation<'tcx>( tcx: TyCtxt<'tcx>, (param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>), ) -> Result, ErrorReported> { - // Remove any references to regions and normalize; this helps improve caching. - let trait_ref = tcx.normalize_erasing_regions(param_env, trait_ref); - + // Remove any references to regions; this helps improve caching. + let trait_ref = tcx.erase_regions(&trait_ref); + // We expect the input to be fully normalized. + debug_assert_eq!(trait_ref, tcx.normalize_erasing_regions(param_env, trait_ref)); debug!( "codegen_fulfill_obligation(trait_ref={:?}, def_id={:?})", (param_env, trait_ref), diff --git a/src/test/ui/mir/mir-inlining/ice-issue-77306.rs b/src/test/ui/mir/mir-inlining/ice-issue-77306.rs new file mode 100644 index 00000000000..4d083bf2321 --- /dev/null +++ b/src/test/ui/mir/mir-inlining/ice-issue-77306.rs @@ -0,0 +1,17 @@ +// run-pass +// compile-flags:-Zmir-opt-level=2 + +// Previously ICEd because we did not normalize during inlining, +// see https://github.com/rust-lang/rust/pull/77306 for more discussion. + +pub fn write() { + create()() +} + +pub fn create() -> impl FnOnce() { + || () +} + +fn main() { + write(); +}