Skip to content

Commit

Permalink
Rollup merge of rust-lang#122907 - compiler-errors:uniquify-reerror, …
Browse files Browse the repository at this point in the history
…r=lcnr

Uniquify `ReError` on input mode in canonicalizer

See test descr

Fixes rust-lang#122861

r? lcnr
  • Loading branch information
matthiaskrgr authored Mar 23, 2024
2 parents 6b4f9c9 + 1fcf2ea commit 2e57c77
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 2 deletions.
3 changes: 1 addition & 2 deletions compiler/rustc_next_trait_solver/src/canonicalizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I>
// FIXME: We should investigate the perf implications of not uniquifying
// `ReErased`. We may be able to short-circuit registering region
// obligations if we encounter a `ReErased` on one side, for example.
ty::ReStatic | ty::ReErased => match self.canonicalize_mode {
ty::ReStatic | ty::ReErased | ty::ReError(_) => match self.canonicalize_mode {
CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT),
CanonicalizeMode::Response { .. } => return r,
},
Expand Down Expand Up @@ -277,7 +277,6 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I>
}
}
}
ty::ReError(_) => return r,
};

let existing_bound_var = match self.canonicalize_mode {
Expand Down
28 changes: 28 additions & 0 deletions tests/ui/traits/next-solver/dont-canonicalize-re-error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//@ compile-flags: -Znext-solver

trait Tr<'a> {}

// Fulfillment in the new solver relies on an invariant to hold: Either
// `has_changed` is true, or computing a goal's certainty is idempotent.
// This isn't true for `ReError`, which we used to pass through in the
// canonicalizer even on input mode, which can cause a goal to go from
// ambig => pass, but we don't consider `has_changed` when the response
// only contains region constraints (since we usually uniquify regions).
//
// In this test:
// Implicit negative coherence tries to prove `W<?0>: Constrain<'?1>`,
// which will then match with the impl below. This constrains `'?1` to
// `ReError`, but still bails w/ ambiguity bc we can't prove `?0: Sized`.
// Then, when we recompute the goal `W<?0>: Constrain<'error>`, when
// collecting ambiguities and overflows, we end up assembling a default
// error candidate w/o ambiguity, which causes the goal to pass, and ICE.
impl<'a, A: ?Sized> Tr<'a> for W<A> {}
struct W<A: ?Sized>(A);
impl<'a, A: ?Sized> Tr<'a> for A where A: Constrain<'a> {}
//~^ ERROR conflicting implementations of trait `Tr<'_>` for type `W<_>`

trait Constrain<'a> {}
impl<A: Sized> Constrain<'missing> for W<A> {}
//~^ ERROR use of undeclared lifetime name `'missing`

fn main() {}
21 changes: 21 additions & 0 deletions tests/ui/traits/next-solver/dont-canonicalize-re-error.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
error[E0261]: use of undeclared lifetime name `'missing`
--> $DIR/dont-canonicalize-re-error.rs:25:26
|
LL | impl<A: Sized> Constrain<'missing> for W<A> {}
| - ^^^^^^^^ undeclared lifetime
| |
| help: consider introducing lifetime `'missing` here: `'missing,`

error[E0119]: conflicting implementations of trait `Tr<'_>` for type `W<_>`
--> $DIR/dont-canonicalize-re-error.rs:21:1
|
LL | impl<'a, A: ?Sized> Tr<'a> for W<A> {}
| ----------------------------------- first implementation here
LL | struct W<A: ?Sized>(A);
LL | impl<'a, A: ?Sized> Tr<'a> for A where A: Constrain<'a> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `W<_>`

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0119, E0261.
For more information about an error, try `rustc --explain E0119`.

0 comments on commit 2e57c77

Please sign in to comment.