Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

normalize substs while inlining #77306

Merged
merged 4 commits into from
Oct 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions compiler/rustc_mir/src/transform/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
11 changes: 7 additions & 4 deletions compiler/rustc_trait_selection/src/traits/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>(
ty: TyCtxt<'tcx>,
tcx: TyCtxt<'tcx>,
(param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>),
) -> Result<ImplSource<'tcx, ()>, ErrorReported> {
// Remove any references to regions; this helps improve caching.
let trait_ref = ty.erase_regions(&trait_ref);

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),
Expand All @@ -33,7 +36,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();
Expand Down
28 changes: 28 additions & 0 deletions src/test/ui/mir/mir-inlining/ice-issue-68347.rs
Original file line number Diff line number Diff line change
@@ -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) {}
}
17 changes: 17 additions & 0 deletions src/test/ui/mir/mir-inlining/ice-issue-77306-1.rs
Original file line number Diff line number Diff line change
@@ -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();
}
32 changes: 32 additions & 0 deletions src/test/ui/mir/mir-inlining/ice-issue-77306-2.rs
Original file line number Diff line number Diff line change
@@ -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<TokenTree> {
None
}
}

fn tokenstream_probably_equal_for_proc_macro() {
fn break_tokens(_tree: TokenTree) -> impl Iterator<Item = TokenTree> {
let token_trees: Vec<TokenTree> = 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();
}