From 9c302f55bd07a04305dfa2bd815d2559deb8468f Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Mon, 28 Sep 2020 20:56:52 +0200 Subject: [PATCH 1/4] normalize in codegen_fulfill_obligations --- compiler/rustc_trait_selection/src/traits/codegen/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/codegen/mod.rs b/compiler/rustc_trait_selection/src/traits/codegen/mod.rs index dd7ea55cc1043..753d64d6115f6 100644 --- a/compiler/rustc_trait_selection/src/traits/codegen/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/codegen/mod.rs @@ -19,11 +19,11 @@ use rustc_middle::ty::{self, TyCtxt}; /// obligations *could be* resolved if we wanted to. /// Assumes that this is run after the entire crate has been successfully type-checked. pub fn codegen_fulfill_obligation<'tcx>( - ty: TyCtxt<'tcx>, + tcx: TyCtxt<'tcx>, (param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>), ) -> Result, ErrorReported> { - // Remove any references to regions; this helps improve caching. - let trait_ref = ty.erase_regions(&trait_ref); + // Remove any references to regions and normalize; this helps improve caching. + let trait_ref = tcx.normalize_erasing_regions(param_env, trait_ref); debug!( "codegen_fulfill_obligation(trait_ref={:?}, def_id={:?})", @@ -33,7 +33,7 @@ pub fn codegen_fulfill_obligation<'tcx>( // Do the initial selection for the obligation. This yields the // shallow result we are looking for -- that is, what specific impl. - ty.infer_ctxt().enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let mut selcx = SelectionContext::new(&infcx); let obligation_cause = ObligationCause::dummy(); From f0487cee7439f3a4b4c7daec0e7f2a0ccc21053c Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Sun, 4 Oct 2020 16:40:06 +0200 Subject: [PATCH 2/4] normalize substs during inlining --- compiler/rustc_mir/src/transform/inline.rs | 10 +++++++--- .../src/traits/codegen/mod.rs | 9 ++++++--- src/test/ui/mir/mir-inlining/ice-issue-77306.rs | 17 +++++++++++++++++ 3 files changed, 30 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/mir/mir-inlining/ice-issue-77306.rs diff --git a/compiler/rustc_mir/src/transform/inline.rs b/compiler/rustc_mir/src/transform/inline.rs index bec1eb790478c..e0bd4e8b68bec 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 753d64d6115f6..05e6c4804ff65 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 0000000000000..4d083bf232155 --- /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(); +} From 32739a2ff1b7b6e5c1b475341b01f4a499830a84 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Sun, 4 Oct 2020 22:42:01 +0200 Subject: [PATCH 3/4] add regression test --- .../ui/mir/mir-inlining/ice-issue-68347.rs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/test/ui/mir/mir-inlining/ice-issue-68347.rs diff --git a/src/test/ui/mir/mir-inlining/ice-issue-68347.rs b/src/test/ui/mir/mir-inlining/ice-issue-68347.rs new file mode 100644 index 0000000000000..88b80bc3333c1 --- /dev/null +++ b/src/test/ui/mir/mir-inlining/ice-issue-68347.rs @@ -0,0 +1,28 @@ +// run-pass +// compile-flags:-Zmir-opt-level=2 +pub fn main() { + let _x: fn() = handle_debug_column; +} + +fn handle_debug_column() { + let sampler = sample_columns(); + + let foo = || { + sampler.get(17); + }; + foo(); +} + +fn sample_columns() -> impl Sampler { + ColumnGen {} +} + +struct ColumnGen {} + +trait Sampler { + fn get(&self, index: i32); +} + +impl Sampler for ColumnGen { + fn get(&self, _index: i32) {} +} From ac893b8a02788eec6f6fad0cc89de0177b0c0a50 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Tue, 6 Oct 2020 17:51:02 +0200 Subject: [PATCH 4/4] add test for should_inline incorrect param_env --- ...ce-issue-77306.rs => ice-issue-77306-1.rs} | 0 .../ui/mir/mir-inlining/ice-issue-77306-2.rs | 32 +++++++++++++++++++ 2 files changed, 32 insertions(+) rename src/test/ui/mir/mir-inlining/{ice-issue-77306.rs => ice-issue-77306-1.rs} (100%) create mode 100644 src/test/ui/mir/mir-inlining/ice-issue-77306-2.rs diff --git a/src/test/ui/mir/mir-inlining/ice-issue-77306.rs b/src/test/ui/mir/mir-inlining/ice-issue-77306-1.rs similarity index 100% rename from src/test/ui/mir/mir-inlining/ice-issue-77306.rs rename to src/test/ui/mir/mir-inlining/ice-issue-77306-1.rs diff --git a/src/test/ui/mir/mir-inlining/ice-issue-77306-2.rs b/src/test/ui/mir/mir-inlining/ice-issue-77306-2.rs new file mode 100644 index 0000000000000..a346d450586bb --- /dev/null +++ b/src/test/ui/mir/mir-inlining/ice-issue-77306-2.rs @@ -0,0 +1,32 @@ +// run-pass +// compile-flags:-Zmir-opt-level=2 + +struct Cursor {} +struct TokenTree {} + +impl Iterator for Cursor { + type Item = TokenTree; + + fn next(&mut self) -> Option { + None + } +} + +fn tokenstream_probably_equal_for_proc_macro() { + fn break_tokens(_tree: TokenTree) -> impl Iterator { + let token_trees: Vec = vec![]; + token_trees.into_iter() + } + + let c1 = Cursor {}; + let c2 = Cursor {}; + + let mut t1 = c1.flat_map(break_tokens); + let mut t2 = c2.flat_map(break_tokens); + + for (_t1, _t2) in t1.by_ref().zip(t2.by_ref()) {} +} + +fn main() { + tokenstream_probably_equal_for_proc_macro(); +}