From 4f14e5bd652531704796e78348c1f7889ac401e9 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 9 Oct 2026 21:53:14 +0200 Subject: [PATCH 1/2] don't just ignore ambig goals in MIR borrowck --- .../src/type_check/canonical.rs | 2 +- .../src/traits/query/type_op/mod.rs | 16 ++++++++--- ...iguity-due-to-uniquification-1.next.stderr | 23 ++++++++++++++++ .../ambiguity-due-to-uniquification-1.rs | 3 ++- ...iguity-due-to-uniquification-2.next.stderr | 21 +++++++++++++++ .../ambiguity-due-to-uniquification-2.rs | 3 ++- ...iguity-due-to-uniquification-3.next.stderr | 21 +++++++++++++++ .../ambiguity-due-to-uniquification-3.rs | 3 ++- ...-uniquification-unsoundness.current.stderr | 21 +++++++++++++++ ...-to-uniquification-unsoundness.next.stderr | 16 +++++++++++ ...guity-due-to-uniquification-unsoundness.rs | 27 +++++++++++++++++++ .../unsize-goal-mismatch-2.next.stderr | 13 +++++++++ .../next-solver/unsize-goal-mismatch-2.rs | 3 ++- .../unsize-goal-mismatch.current.stderr | 4 +-- .../unsize-goal-mismatch.next.stderr | 13 +++++++++ .../next-solver/unsize-goal-mismatch.rs | 3 +-- ...nnormalized-projection-guides-inference.rs | 4 +++ 17 files changed, 183 insertions(+), 13 deletions(-) create mode 100644 tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-1.next.stderr create mode 100644 tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-2.next.stderr create mode 100644 tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-3.next.stderr create mode 100644 tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-unsoundness.current.stderr create mode 100644 tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-unsoundness.next.stderr create mode 100644 tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-unsoundness.rs create mode 100644 tests/ui/traits/next-solver/unsize-goal-mismatch-2.next.stderr create mode 100644 tests/ui/traits/next-solver/unsize-goal-mismatch.next.stderr diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index b295a66ee74ee..c6f99c16229d8 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -175,7 +175,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let param_env = self.infcx.param_env; // Upcast to a `Clause`, then to a `Predicate`. let predicate = clause.upcast(self.tcx()).upcast(self.tcx()); - let _: Result<_, ErrorGuaranteed> = self.fully_perform_op( + let _: Result<(), ErrorGuaranteed> = self.fully_perform_op( locations, category, param_env.and(type_op::prove_predicate::ProvePredicate { predicate }), diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs index 250579a2b064a..6a9f7907a8eb4 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs @@ -6,6 +6,7 @@ use rustc_infer::traits::PredicateObligations; use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::{ParamEnvAnd, TyCtxt, TypeFoldable}; use rustc_span::Span; +use tracing::debug; use crate::infer::canonical::{ CanonicalQueryInput, CanonicalQueryResponse, Certainty, OriginalQueryValues, @@ -93,14 +94,13 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable> + 't Self::QueryResponse, Option>>, PredicateObligations<'tcx>, - Certainty, ), NoSolution, > { if !infcx.disable_trait_solver_fast_paths() && let Some(result) = QueryTypeOp::try_fast_path(infcx.tcx, &query_key) { - return Ok((result, None, PredicateObligations::new(), Certainty::Proven)); + return Ok((result, None, PredicateObligations::new())); } let mut canonical_var_values = OriginalQueryValues::default(); @@ -117,7 +117,15 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable> + 't output_query_region_constraints, )?; - Ok((value, Some(canonical_self), obligations, canonical_result.value.certainty)) + match canonical_result.value.certainty { + Certainty::Proven => {} + Certainty::Ambiguous => { + debug!("type_op resulted in unexpected ambiguity: {query_key:?}"); + return Err(NoSolution); + } + } + + Ok((value, Some(canonical_self), obligations)) } } @@ -143,7 +151,7 @@ where // collecting region constraints via `region_constraints`. let (mut output, _) = scrape_region_constraints(infcx, root_def_id, "fully_perform", span, |ocx| { - let (output, ei, obligations, _) = + let (output, ei, obligations) = Q::fully_perform_into(self, infcx, &mut region_constraints, span)?; error_info = ei; diff --git a/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-1.next.stderr b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-1.next.stderr new file mode 100644 index 0000000000000..3136114081c08 --- /dev/null +++ b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-1.next.stderr @@ -0,0 +1,23 @@ +error[E0283]: type annotations needed: cannot satisfy `dyn D<&(), &()>: B<&()>` + --> $DIR/ambiguity-due-to-uniquification-1.rs:15:31 + | +LL | (&() as &dyn D<&(), &()>).f() + | ^ + | + = note: cannot satisfy `dyn D<&(), &()>: B<&()>` +help: the trait `B` is implemented for `()` + --> $DIR/ambiguity-due-to-uniquification-1.rs:9:1 + | +LL | impl B for () {} + | ^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `D::f` + --> $DIR/ambiguity-due-to-uniquification-1.rs:10:16 + | +LL | trait D: B + B { + | ^^^^ required by this bound in `D::f` +LL | fn f(&self) {} + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-1.rs b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-1.rs index f94b3a10f5ae8..1228d1cfef6ff 100644 --- a/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-1.rs +++ b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-1.rs @@ -1,7 +1,7 @@ //@ revisions: current next //@[next] compile-flags: -Znext-solver //@ ignore-compare-mode-next-solver (explicit revisions) -//@ check-pass +//@[current] check-pass // Regression test for #139409 and trait-system-refactor-initiative#27. @@ -13,4 +13,5 @@ trait D: B + B { impl D for () {} fn main() { (&() as &dyn D<&(), &()>).f() + //[next]~^ ERROR: type annotations needed: cannot satisfy `dyn D<&(), &()>: B<&()>` } diff --git a/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-2.next.stderr b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-2.next.stderr new file mode 100644 index 0000000000000..61c6ef9a449ef --- /dev/null +++ b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-2.next.stderr @@ -0,0 +1,21 @@ +error[E0283]: type annotations needed: cannot satisfy `impl Trait<'_> + Trait<'_>: Trait<'_>` + --> $DIR/ambiguity-due-to-uniquification-2.rs:16:5 + | +LL | impls_trait::<'y, _>(foo::<'x, 'y>()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: cannot satisfy `impl Trait<'_> + Trait<'_>: Trait<'_>` +help: the trait `Trait<'t>` is implemented for `()` + --> $DIR/ambiguity-due-to-uniquification-2.rs:9:1 + | +LL | impl<'t> Trait<'t> for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `impls_trait` + --> $DIR/ambiguity-due-to-uniquification-2.rs:13:23 + | +LL | fn impls_trait<'x, T: Trait<'x>>(_: T) {} + | ^^^^^^^^^ required by this bound in `impls_trait` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-2.rs b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-2.rs index d2eadc7650711..0914c599d614f 100644 --- a/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-2.rs +++ b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-2.rs @@ -1,7 +1,7 @@ //@ revisions: current next //@[next] compile-flags: -Znext-solver //@ ignore-compare-mode-next-solver (explicit revisions) -//@ check-pass +//@[current] check-pass // Regression test from trait-system-refactor-initiative#27. @@ -14,6 +14,7 @@ fn impls_trait<'x, T: Trait<'x>>(_: T) {} fn bar<'x, 'y>() { impls_trait::<'y, _>(foo::<'x, 'y>()); + //[next]~^ ERROR: type annotations needed: cannot satisfy `impl Trait<'_> + Trait<'_>: Trait<'_>` } fn main() {} diff --git a/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-3.next.stderr b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-3.next.stderr new file mode 100644 index 0000000000000..b6cbb9866a1d7 --- /dev/null +++ b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-3.next.stderr @@ -0,0 +1,21 @@ +error[E0283]: type annotations needed: cannot satisfy `dyn Object<&(), &()>: Trait<&()>` + --> $DIR/ambiguity-due-to-uniquification-3.rs:30:5 + | +LL | impls_trait(obj, t); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: cannot satisfy `dyn Object<&(), &()>: Trait<&()>` +help: the trait `Trait` is implemented for `()` + --> $DIR/ambiguity-due-to-uniquification-3.rs:17:1 + | +LL | impl Trait for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `impls_trait` + --> $DIR/ambiguity-due-to-uniquification-3.rs:26:19 + | +LL | fn impls_trait, U>(_: Inv, _: Inv) {} + | ^^^^^^^^ required by this bound in `impls_trait` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-3.rs b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-3.rs index f734e4c297a65..9f6cee07dcba3 100644 --- a/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-3.rs +++ b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-3.rs @@ -1,7 +1,7 @@ //@ revisions: current next //@[next] compile-flags: -Znext-solver //@ ignore-compare-mode-next-solver (explicit revisions) -//@ check-pass +//@[current] check-pass // Regression test from trait-system-refactor-initiative#27. // @@ -28,6 +28,7 @@ fn impls_trait, U>(_: Inv, _: Inv) {} fn bar() { let (obj, t) = foo(); impls_trait(obj, t); + //[next]~^ ERROR: type annotations needed: cannot satisfy `dyn Object<&(), &()>: Trait<&()>` let _: Inv> = obj; } diff --git a/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-unsoundness.current.stderr b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-unsoundness.current.stderr new file mode 100644 index 0000000000000..a807d625ec240 --- /dev/null +++ b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-unsoundness.current.stderr @@ -0,0 +1,21 @@ +error[E0283]: type annotations needed: cannot satisfy `Self: Tr<'a>` + --> $DIR/ambiguity-due-to-uniquification-unsoundness.rs:12:18 + | +LL | trait D<'a, 'b>: Tr<'a> + Tr<'b> {} + | ^^^^^^ + | +note: multiple `impl`s or `where` clauses satisfying `Self: Tr<'a>` found + --> $DIR/ambiguity-due-to-uniquification-unsoundness.rs:12:18 + | +LL | trait D<'a, 'b>: Tr<'a> + Tr<'b> {} + | ^^^^^^ ^^^^^^ + +error: lifetime may not live long enough + --> $DIR/ambiguity-due-to-uniquification-unsoundness.rs:18:47 + | +LL | fn f<'a>(x: &dyn D<'a, 'a>) -> &'static str { x.get() } + | -- lifetime `'a` defined here ^^^^^^^ returning this value requires that `'a` must outlive `'static` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-unsoundness.next.stderr b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-unsoundness.next.stderr new file mode 100644 index 0000000000000..8a7124a35a208 --- /dev/null +++ b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-unsoundness.next.stderr @@ -0,0 +1,16 @@ +error[E0283]: type annotations needed: cannot satisfy `dyn D<'_, '_>: Tr<'_>` + --> $DIR/ambiguity-due-to-uniquification-unsoundness.rs:18:49 + | +LL | fn f<'a>(x: &dyn D<'a, 'a>) -> &'static str { x.get() } + | ^^^ + | + = note: cannot satisfy `dyn D<'_, '_>: Tr<'_>` +help: the trait `Tr<'t>` is implemented for `&'t str` + --> $DIR/ambiguity-due-to-uniquification-unsoundness.rs:15:1 + | +LL | impl<'t> Tr<'t> for &'t str { fn get(&self) -> &'t str { *self } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-unsoundness.rs b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-unsoundness.rs new file mode 100644 index 0000000000000..65524b34edc31 --- /dev/null +++ b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-unsoundness.rs @@ -0,0 +1,27 @@ +// A regression test for trait-system-refactor-initiative#307. Proving +// `dyn D<'a, 'a>: Tr<'whatever>` passed in HIR typeck, but after +// uniquification proving `dyn D<'x, 'y>: Tr<'z>` in MIR borrowck +// failed with ambiguity. We incorrectly ignored this ambiguous result +// without registering any constraints, causing `f` to compile. + +//@ revisions: current next +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) + +trait Tr<'t> { fn get(&self) -> &'t str; } +trait D<'a, 'b>: Tr<'a> + Tr<'b> {} +//[current]~^ ERROR: type annotations needed: cannot satisfy `Self: Tr<'a>` + +impl<'t> Tr<'t> for &'t str { fn get(&self) -> &'t str { *self } } +impl<'a> D<'a, 'a> for &'a str {} + +fn f<'a>(x: &dyn D<'a, 'a>) -> &'static str { x.get() } +//[current]~^ ERROR: lifetime may not live long enough +//[next]~^^ ERROR: type annotations needed: cannot satisfy `dyn D<'_, '_>: Tr<'_>` + +fn main() { + let b = String::from("hi"); + let r: &'static str = f(&b.as_str()); + drop(b); + println!("{r}"); +} \ No newline at end of file diff --git a/tests/ui/traits/next-solver/unsize-goal-mismatch-2.next.stderr b/tests/ui/traits/next-solver/unsize-goal-mismatch-2.next.stderr new file mode 100644 index 0000000000000..b415db33addbf --- /dev/null +++ b/tests/ui/traits/next-solver/unsize-goal-mismatch-2.next.stderr @@ -0,0 +1,13 @@ +error[E0283]: type annotations needed: cannot satisfy `dyn Trait<&()>: Unsize>` + --> $DIR/unsize-goal-mismatch-2.rs:15:5 + | +LL | x + | ^ + | + = note: cannot satisfy `dyn Trait<&()>: Unsize>` + = note: required for `Box>` to implement `CoerceUnsized>>` + = note: required for the cast from `Box<(dyn Trait<&'a ()> + 'static)>` to `Box<(dyn Super<&'a ()> + 'static)>` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/next-solver/unsize-goal-mismatch-2.rs b/tests/ui/traits/next-solver/unsize-goal-mismatch-2.rs index a9aae7e78cee8..d436bdb7fe32d 100644 --- a/tests/ui/traits/next-solver/unsize-goal-mismatch-2.rs +++ b/tests/ui/traits/next-solver/unsize-goal-mismatch-2.rs @@ -1,7 +1,7 @@ //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver -//@ check-pass +//@[current] check-pass // Test from trait-system-refactor-initiative#241: // Used to ICE in mir typeck because of ambiguity in the new solver. // The wrong (first) trait bound was selected. @@ -13,6 +13,7 @@ trait Trait: Super + for<'hr> Super<&'hr ()> {} fn foo<'a>(x: Box>) -> Box> { x + //[next]~^ ERROR: type annotations needed: cannot satisfy `dyn Trait<&()>: Unsize>` } fn main() {} diff --git a/tests/ui/traits/next-solver/unsize-goal-mismatch.current.stderr b/tests/ui/traits/next-solver/unsize-goal-mismatch.current.stderr index b96426d851294..278a68e154714 100644 --- a/tests/ui/traits/next-solver/unsize-goal-mismatch.current.stderr +++ b/tests/ui/traits/next-solver/unsize-goal-mismatch.current.stderr @@ -1,11 +1,11 @@ error[E0283]: type annotations needed: cannot satisfy `Self: Super<'a>` - --> $DIR/unsize-goal-mismatch.rs:12:18 + --> $DIR/unsize-goal-mismatch.rs:11:18 | LL | trait Trait<'a>: Super<'a> + for<'hr> Super<'hr> {} | ^^^^^^^^^ | note: multiple `impl`s or `where` clauses satisfying `Self: Super<'a>` found - --> $DIR/unsize-goal-mismatch.rs:11:1 + --> $DIR/unsize-goal-mismatch.rs:10:1 | LL | trait Super<'a> {} | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/next-solver/unsize-goal-mismatch.next.stderr b/tests/ui/traits/next-solver/unsize-goal-mismatch.next.stderr new file mode 100644 index 0000000000000..cfb978240cbc6 --- /dev/null +++ b/tests/ui/traits/next-solver/unsize-goal-mismatch.next.stderr @@ -0,0 +1,13 @@ +error[E0283]: type annotations needed: cannot satisfy `dyn Trait<'_>: Unsize>` + --> $DIR/unsize-goal-mismatch.rs:15:5 + | +LL | x + | ^ + | + = note: cannot satisfy `dyn Trait<'_>: Unsize>` + = note: required for `Box>` to implement `CoerceUnsized>>` + = note: required for the cast from `Box<(dyn Trait<'a> + 'static)>` to `Box<(dyn Super<'a> + 'static)>` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/next-solver/unsize-goal-mismatch.rs b/tests/ui/traits/next-solver/unsize-goal-mismatch.rs index dc476afa5ee90..4d73a38c00b47 100644 --- a/tests/ui/traits/next-solver/unsize-goal-mismatch.rs +++ b/tests/ui/traits/next-solver/unsize-goal-mismatch.rs @@ -1,7 +1,6 @@ //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver -//@[next] check-pass // Test from trait-system-refactor-initiative#241: // Used to ICE in mir typeck because of ambiguity in the new solver. // The wrong (first) trait bound was selected. @@ -13,7 +12,7 @@ trait Trait<'a>: Super<'a> + for<'hr> Super<'hr> {} //[current]~^ ERROR type annotations needed: cannot satisfy `Self: Super<'a>` fn foo<'a>(x: Box>) -> Box> { - x + x //[next]~ ERROR: type annotations needed: cannot satisfy `dyn Trait<'_>: Unsize>` } fn main() {} diff --git a/tests/ui/wf/unnormalized-projection-guides-inference.rs b/tests/ui/wf/unnormalized-projection-guides-inference.rs index e1fc962c00b4b..3d7de5ef9080a 100644 --- a/tests/ui/wf/unnormalized-projection-guides-inference.rs +++ b/tests/ui/wf/unnormalized-projection-guides-inference.rs @@ -1,5 +1,9 @@ // The WF requirements of the *unnormalized* form of type annotations // can guide inference. + +//@ revisions: current next +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) //@ check-pass pub trait EqualTo { From 14f0018fcd98689bb93f074ed56ecc3adced5880 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 9 Oct 2026 22:39:46 +0200 Subject: [PATCH 2/2] add regression test for old solver unsoundness --- ...e-to-uniquification-old-solver.next.stderr | 23 +++++++++ ...iguity-due-to-uniquification-old-solver.rs | 17 +++++++ ...-to-uniquification-unsound-old.next.stderr | 23 +++++++++ ...guity-due-to-uniquification-unsound-old.rs | 47 +++++++++++++++++++ 4 files changed, 110 insertions(+) create mode 100644 tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-old-solver.next.stderr create mode 100644 tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-old-solver.rs create mode 100644 tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-unsound-old.next.stderr create mode 100644 tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-unsound-old.rs diff --git a/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-old-solver.next.stderr b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-old-solver.next.stderr new file mode 100644 index 0000000000000..3435a9938f091 --- /dev/null +++ b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-old-solver.next.stderr @@ -0,0 +1,23 @@ +error[E0283]: type annotations needed: cannot satisfy `dyn D<&(), &()>: B<&()>` + --> $DIR/ambiguity-due-to-uniquification-old-solver.rs:15:31 + | +LL | (&() as &dyn D<&(), &()>).f() + | ^ + | + = note: cannot satisfy `dyn D<&(), &()>: B<&()>` +help: the trait `B` is implemented for `()` + --> $DIR/ambiguity-due-to-uniquification-old-solver.rs:9:1 + | +LL | impl B for () {} + | ^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `D::f` + --> $DIR/ambiguity-due-to-uniquification-old-solver.rs:10:16 + | +LL | trait D: B + B { + | ^^^^ required by this bound in `D::f` +LL | fn f(&self) {} + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-old-solver.rs b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-old-solver.rs new file mode 100644 index 0000000000000..1228d1cfef6ff --- /dev/null +++ b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-old-solver.rs @@ -0,0 +1,17 @@ +//@ revisions: current next +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[current] check-pass + +// Regression test for #139409 and trait-system-refactor-initiative#27. + +trait B {} +impl B for () {} +trait D: B + B { + fn f(&self) {} +} +impl D for () {} +fn main() { + (&() as &dyn D<&(), &()>).f() + //[next]~^ ERROR: type annotations needed: cannot satisfy `dyn D<&(), &()>: B<&()>` +} diff --git a/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-unsound-old.next.stderr b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-unsound-old.next.stderr new file mode 100644 index 0000000000000..3a5959968d2f0 --- /dev/null +++ b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-unsound-old.next.stderr @@ -0,0 +1,23 @@ +error[E0283]: type annotations needed: cannot satisfy `dyn Tr<'a, 'a, (), ()>: Sup<'a, ()>` + --> $DIR/ambiguity-due-to-uniquification-unsound-old.rs:38:7 + | +LL | x.hide_me() + | ^^^^^^^ + | + = note: cannot satisfy `dyn Tr<'a, 'a, (), ()>: Sup<'a, ()>` +help: the trait `Sup<'a, ()>` is implemented for `&'a str` + --> $DIR/ambiguity-due-to-uniquification-unsound-old.rs:16:1 + | +LL | impl<'a> Sup<'a, ()> for &'a str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required for `dyn Tr<'a, 'a, (), ()>` to implement `HideMe` + --> $DIR/ambiguity-due-to-uniquification-unsound-old.rs:32:57 + | +LL | impl<'a, T: Sup<'a, (), Assoc = &'static str> + ?Sized> HideMe for T { + | --------------------------------- ^^^^^^ ^ + | | + | unsatisfied trait bound introduced here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-unsound-old.rs b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-unsound-old.rs new file mode 100644 index 0000000000000..7b6474fd56d8f --- /dev/null +++ b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-unsound-old.rs @@ -0,0 +1,47 @@ +// A regression test for trait-system-refactor-initiative#307 affecting +// the old solver instead. The old solver only cares about region identity +// inside of `project` when merging candidates. This means this unsoundness +// also affects the old solver. + +//@ revisions: current next +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[current] failure-status: 101 +//@[current] dont-check-compiler-stderr +//@[current] known-bug: unknown +trait Sup<'a, T> { + type Assoc; + fn to_assoc(&self) -> Self::Assoc; +} +impl<'a> Sup<'a, ()> for &'a str { + type Assoc = &'a str; + fn to_assoc(&self) -> Self::Assoc { self } +} + +// Need the trait arguments to pass WF-checking +trait Tr<'a, 'b, T, U>: Sup<'a, T, Assoc = &'a str> + Sup<'b, U, Assoc = &'b str> {} +impl<'a> Tr<'a, 'a, (), ()> for &'a str {} + +trait HideMe { + fn hide_me(&self) -> &'static str; +} + +// Need the ambiguous `T: Sup<'a, (), Assoc = &'static str>` bound to only be +// used inside of the trait impl, as otherwise we also encounter ambiguity +// during normalization, which ICEs instead of ignoring it. +impl<'a, T: Sup<'a, (), Assoc = &'static str> + ?Sized> HideMe for T { + fn hide_me(&self) -> &'static str { + self.to_assoc() + } +} +fn yeet<'a>(x: &dyn Tr<'a, 'a, (), ()>) -> &'static str { + x.hide_me() + //[next]~^ ERROR: type annotations needed: cannot satisfy `dyn Tr<'a, 'a, (), ()>: Sup<'a, ()>` +} + +fn main() { + let s = String::from("hello"); + let r = yeet(&s.as_str()); + drop(s); + println!("{r}"); +}