Auto merge of #77306 - lcnr:inline-ok, r=eddyb
normalize substs while inlining fixes #68347 or more precisely, this fixes the same ICE in rust analyser as veloren is pinned to a specific nightly and had an error with the current one. I didn't look into creating an MVCE here as that seems fairly annoying, will spend a few minutes doing so rn. (failed) r? `@eddyb` cc `@bjorn3`
This commit is contained in:
commit
4d247ad7d3
@ -201,9 +201,13 @@ impl Inliner<'tcx> {
|
|||||||
let terminator = bb_data.terminator();
|
let terminator = bb_data.terminator();
|
||||||
if let TerminatorKind::Call { func: ref op, .. } = terminator.kind {
|
if let TerminatorKind::Call { func: ref op, .. } = terminator.kind {
|
||||||
if let ty::FnDef(callee_def_id, substs) = *op.ty(caller_body, self.tcx).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)
|
// To resolve an instance its substs have to be fully normalized, so
|
||||||
.ok()
|
// we do this here.
|
||||||
.flatten()?;
|
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 {
|
if let InstanceDef::Virtual(..) = instance.def {
|
||||||
return None;
|
return None;
|
||||||
|
@ -17,14 +17,17 @@ use rustc_middle::ty::{self, TyCtxt};
|
|||||||
/// (necessarily) resolve all nested obligations on the impl. Note
|
/// (necessarily) resolve all nested obligations on the impl. Note
|
||||||
/// that type check should guarantee to us that all nested
|
/// that type check should guarantee to us that all nested
|
||||||
/// obligations *could be* resolved if we wanted to.
|
/// obligations *could be* resolved if we wanted to.
|
||||||
|
///
|
||||||
/// Assumes that this is run after the entire crate has been successfully type-checked.
|
/// 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>(
|
pub fn codegen_fulfill_obligation<'tcx>(
|
||||||
ty: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
(param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>),
|
(param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>),
|
||||||
) -> Result<ImplSource<'tcx, ()>, ErrorReported> {
|
) -> Result<ImplSource<'tcx, ()>, ErrorReported> {
|
||||||
// Remove any references to regions; this helps improve caching.
|
// 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!(
|
debug!(
|
||||||
"codegen_fulfill_obligation(trait_ref={:?}, def_id={:?})",
|
"codegen_fulfill_obligation(trait_ref={:?}, def_id={:?})",
|
||||||
(param_env, trait_ref),
|
(param_env, trait_ref),
|
||||||
@ -33,7 +36,7 @@ pub fn codegen_fulfill_obligation<'tcx>(
|
|||||||
|
|
||||||
// Do the initial selection for the obligation. This yields the
|
// Do the initial selection for the obligation. This yields the
|
||||||
// shallow result we are looking for -- that is, what specific impl.
|
// 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 mut selcx = SelectionContext::new(&infcx);
|
||||||
|
|
||||||
let obligation_cause = ObligationCause::dummy();
|
let obligation_cause = ObligationCause::dummy();
|
||||||
|
28
src/test/ui/mir/mir-inlining/ice-issue-68347.rs
Normal file
28
src/test/ui/mir/mir-inlining/ice-issue-68347.rs
Normal file
@ -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
src/test/ui/mir/mir-inlining/ice-issue-77306-1.rs
Normal file
17
src/test/ui/mir/mir-inlining/ice-issue-77306-1.rs
Normal file
@ -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
src/test/ui/mir/mir-inlining/ice-issue-77306-2.rs
Normal file
32
src/test/ui/mir/mir-inlining/ice-issue-77306-2.rs
Normal file
@ -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();
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user