Skip to content
Closed
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
6 changes: 6 additions & 0 deletions compiler/rustc_trait_selection/src/solve/normalize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,12 @@ where
return Err(errors);
}

// The fallback in `normalize_with_universes` builds `value` using fresh inference
// variables and returns their obligations separately. Fulfillment may constrain
// these variables, but it does not fold `value` again, so resolve them before
// returning.
let value = at.infcx.resolve_vars_if_possible(value);

Ok((value, stalled_coroutine_goals))
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//@ needs-rustc-debug-assertions
//@ compile-flags: -Znext-solver

// Regression test for #160875.
//
// This needs a rustc with debug assertions: the only symptom of the bug is the
// `debug_assert_eq!` in `try_normalize_after_erasing_regions`. That function
// resolves inference variables itself before returning, so without the
// assertion the pre-fix and post-fix output are identical and there is nothing
// for a test to observe.
//
// The first normalization attempt folds the inner alias before trying the outer
// one. The outer goal then returns `NoSolution`, so `normalize_with_universes`
// discards the partial result and retries the original value with
// `ReplaceAliasWithInfer`. The nested alias stays in place because it has escaping
// bound vars, while the outer alias becomes a fresh inference variable.
//
// Fulfillment later proves the fallback obligations and constrains that variable,
// but it does not rebuild the value produced by the fold. Failing to resolve the
// value before returning made `normalize_erasing_regions` see `fn(?3t)` even though
// the inference context had already resolved it to `fn(&'?0 ())`.
//
// `bar` is a `const fn` so that drop elaboration -- and with it the
// `PostAnalysisNormalize` pass which normalizes its signature -- runs even
// though this test only emits metadata. The body error makes this test reach the
// MIR assertion; a valid body takes the same normalization fallback but does not
// reach that assertion here.

#![feature(inherent_associated_types)]
#![allow(incomplete_features)]

struct Foo<T>(T);

impl<'a> Foo<fn(&'a ())> {
type Assoc = &'a ();
}

const fn bar(_: fn(Foo<for<'b> fn(Foo<fn(&'b ())>::Assoc)>::Assoc)) {
//~^ ERROR lifetime bound not satisfied
//~| ERROR lifetime bound not satisfied
x
//~^ ERROR cannot find value `x` in this scope
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
error[E0425]: cannot find value `x` in this scope
--> $DIR/deeply-normalize-fallback-issue-160875.rs:41:5
|
LL | x
| ^ not found in this scope

error[E0478]: lifetime bound not satisfied
--> $DIR/deeply-normalize-fallback-issue-160875.rs:38:17
|
LL | const fn bar(_: fn(Foo<for<'b> fn(Foo<fn(&'b ())>::Assoc)>::Assoc)) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0478]: lifetime bound not satisfied
--> $DIR/deeply-normalize-fallback-issue-160875.rs:38:17
|
LL | const fn bar(_: fn(Foo<for<'b> fn(Foo<fn(&'b ())>::Assoc)>::Assoc)) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error: aborting due to 3 previous errors

Some errors have detailed explanations: E0425, E0478.
For more information about an error, try `rustc --explain E0425`.
Loading