From d1b2d29528b7794b41e66fc2136e395a02f8529b Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 30 May 2024 05:59:35 +0200 Subject: Merging upstream version 1.73.0+dfsg1. Signed-off-by: Daniel Baumann --- .../ui/traits/new-solver/alias-bound-preference.rs | 39 +++++++++++ tests/ui/traits/new-solver/alias-bound-unsound.rs | 9 ++- .../traits/new-solver/alias-bound-unsound.stderr | 65 +++++++++++++++++-- .../assemble-normalizing-self-ty-impl-ambiguity.rs | 27 ++++++++ .../assembly/runaway-impl-candidate-selection.rs | 15 +++++ .../runaway-impl-candidate-selection.stderr | 9 +++ .../trait_ref_is_knowable-norm-overflow.rs | 20 ++++++ .../trait_ref_is_knowable-norm-overflow.stderr | 12 ++++ .../trait_ref_is_knowable-normalization-1.rs | 22 +++++++ .../trait_ref_is_knowable-normalization-2.rs | 25 ++++++++ .../trait_ref_is_knowable-normalization-3.rs | 24 +++++++ .../coinduction/fixpoint-exponential-growth.rs | 32 +++++++++ .../coinduction/fixpoint-exponential-growth.stderr | 23 +++++++ .../coinduction/incompleteness-unstable-result.rs | 69 ++++++++++++++++++++ .../incompleteness-unstable-result.stderr | 16 +++++ .../cycles/double-cycle-inductive-coinductive.rs | 37 +++++++++++ .../double-cycle-inductive-coinductive.stderr | 29 +++++++++ .../new-solver/cycles/inductive-cycle-but-err.rs | 48 ++++++++++++++ .../cycles/inductive-cycle-but-err.stderr | 16 +++++ .../new-solver/cycles/inductive-cycle-but-ok.rs | 44 +++++++++++++ ...tive-cycle-discarded-coinductive-constraints.rs | 36 +++++++++++ .../new-solver/cycles/inductive-not-on-stack.rs | 46 +++++++++++++ .../cycles/inductive-not-on-stack.stderr | 16 +++++ .../cycles/leak-check-coinductive-cycle.rs | 33 ++++++++++ .../new-solver/cycles/provisional-result-done.rs | 33 ++++++++++ .../traits/new-solver/dont-coerce-infer-to-dyn.rs | 17 +++++ .../dont-loop-fulfill-on-region-constraints.rs | 32 +++++++++ .../new-solver/dont-normalize-proj-with-error.rs | 22 +++++++ .../dont-normalize-proj-with-error.stderr | 9 +++ .../traits/new-solver/dyn-any-dont-prefer-impl.rs | 4 ++ ...caping-bound-vars-in-writeback-normalization.rs | 18 ++++++ .../traits/new-solver/exponential-trait-goals.rs | 20 ------ .../new-solver/exponential-trait-goals.stderr | 23 ------- .../generalize-proj-new-universe-index-1.rs | 73 +++++++++++++++++++++ .../generalize-proj-new-universe-index-2.rs | 75 ++++++++++++++++++++++ .../generalize-proj-new-universe-index-2.stderr | 9 +++ .../traits/new-solver/lazy-nested-obligations-2.rs | 2 +- .../new-solver/lazy-nested-obligations-2.stderr | 39 ----------- .../new-solver/leak-check-coinductive-cycle.rs | 33 ---------- .../ui/traits/new-solver/more-object-bound.stderr | 4 +- tests/ui/traits/new-solver/normalize-unsize-rhs.rs | 23 +++++++ .../object-soundness-requires-generalization.rs | 20 ++++++ .../new-solver/overflow/exponential-trait-goals.rs | 20 ++++++ .../overflow/exponential-trait-goals.stderr | 23 +++++++ .../ui/traits/new-solver/overflow/global-cache.rs | 23 +++++++ .../traits/new-solver/overflow/global-cache.stderr | 16 +++++ .../overflow/recursive-self-normalization-2.rs | 20 ++++++ .../overflow/recursive-self-normalization-2.stderr | 20 ++++++ .../overflow/recursive-self-normalization.rs | 16 +++++ .../overflow/recursive-self-normalization.stderr | 20 ++++++ .../traits/new-solver/provisional-result-done.rs | 33 ---------- .../new-solver/recursive-self-normalization-2.rs | 20 ------ .../recursive-self-normalization-2.stderr | 20 ------ .../new-solver/recursive-self-normalization.rs | 16 ----- .../new-solver/recursive-self-normalization.stderr | 20 ------ .../new-solver/runaway-impl-candidate-selection.rs | 15 ----- .../runaway-impl-candidate-selection.stderr | 9 --- .../trait-upcast-lhs-needs-normalization.rs | 20 ++++++ .../traits/new-solver/unsize-although-ambiguous.rs | 13 ++++ 59 files changed, 1234 insertions(+), 258 deletions(-) create mode 100644 tests/ui/traits/new-solver/alias-bound-preference.rs create mode 100644 tests/ui/traits/new-solver/assembly/assemble-normalizing-self-ty-impl-ambiguity.rs create mode 100644 tests/ui/traits/new-solver/assembly/runaway-impl-candidate-selection.rs create mode 100644 tests/ui/traits/new-solver/assembly/runaway-impl-candidate-selection.stderr create mode 100644 tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-norm-overflow.rs create mode 100644 tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr create mode 100644 tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-normalization-1.rs create mode 100644 tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-normalization-2.rs create mode 100644 tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-normalization-3.rs create mode 100644 tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.rs create mode 100644 tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.stderr create mode 100644 tests/ui/traits/new-solver/cycles/coinduction/incompleteness-unstable-result.rs create mode 100644 tests/ui/traits/new-solver/cycles/coinduction/incompleteness-unstable-result.stderr create mode 100644 tests/ui/traits/new-solver/cycles/double-cycle-inductive-coinductive.rs create mode 100644 tests/ui/traits/new-solver/cycles/double-cycle-inductive-coinductive.stderr create mode 100644 tests/ui/traits/new-solver/cycles/inductive-cycle-but-err.rs create mode 100644 tests/ui/traits/new-solver/cycles/inductive-cycle-but-err.stderr create mode 100644 tests/ui/traits/new-solver/cycles/inductive-cycle-but-ok.rs create mode 100644 tests/ui/traits/new-solver/cycles/inductive-cycle-discarded-coinductive-constraints.rs create mode 100644 tests/ui/traits/new-solver/cycles/inductive-not-on-stack.rs create mode 100644 tests/ui/traits/new-solver/cycles/inductive-not-on-stack.stderr create mode 100644 tests/ui/traits/new-solver/cycles/leak-check-coinductive-cycle.rs create mode 100644 tests/ui/traits/new-solver/cycles/provisional-result-done.rs create mode 100644 tests/ui/traits/new-solver/dont-coerce-infer-to-dyn.rs create mode 100644 tests/ui/traits/new-solver/dont-loop-fulfill-on-region-constraints.rs create mode 100644 tests/ui/traits/new-solver/dont-normalize-proj-with-error.rs create mode 100644 tests/ui/traits/new-solver/dont-normalize-proj-with-error.stderr create mode 100644 tests/ui/traits/new-solver/escaping-bound-vars-in-writeback-normalization.rs delete mode 100644 tests/ui/traits/new-solver/exponential-trait-goals.rs delete mode 100644 tests/ui/traits/new-solver/exponential-trait-goals.stderr create mode 100644 tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-1.rs create mode 100644 tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.rs create mode 100644 tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.stderr delete mode 100644 tests/ui/traits/new-solver/lazy-nested-obligations-2.stderr delete mode 100644 tests/ui/traits/new-solver/leak-check-coinductive-cycle.rs create mode 100644 tests/ui/traits/new-solver/normalize-unsize-rhs.rs create mode 100644 tests/ui/traits/new-solver/object-soundness-requires-generalization.rs create mode 100644 tests/ui/traits/new-solver/overflow/exponential-trait-goals.rs create mode 100644 tests/ui/traits/new-solver/overflow/exponential-trait-goals.stderr create mode 100644 tests/ui/traits/new-solver/overflow/global-cache.rs create mode 100644 tests/ui/traits/new-solver/overflow/global-cache.stderr create mode 100644 tests/ui/traits/new-solver/overflow/recursive-self-normalization-2.rs create mode 100644 tests/ui/traits/new-solver/overflow/recursive-self-normalization-2.stderr create mode 100644 tests/ui/traits/new-solver/overflow/recursive-self-normalization.rs create mode 100644 tests/ui/traits/new-solver/overflow/recursive-self-normalization.stderr delete mode 100644 tests/ui/traits/new-solver/provisional-result-done.rs delete mode 100644 tests/ui/traits/new-solver/recursive-self-normalization-2.rs delete mode 100644 tests/ui/traits/new-solver/recursive-self-normalization-2.stderr delete mode 100644 tests/ui/traits/new-solver/recursive-self-normalization.rs delete mode 100644 tests/ui/traits/new-solver/recursive-self-normalization.stderr delete mode 100644 tests/ui/traits/new-solver/runaway-impl-candidate-selection.rs delete mode 100644 tests/ui/traits/new-solver/runaway-impl-candidate-selection.stderr create mode 100644 tests/ui/traits/new-solver/trait-upcast-lhs-needs-normalization.rs create mode 100644 tests/ui/traits/new-solver/unsize-although-ambiguous.rs (limited to 'tests/ui/traits/new-solver') diff --git a/tests/ui/traits/new-solver/alias-bound-preference.rs b/tests/ui/traits/new-solver/alias-bound-preference.rs new file mode 100644 index 000000000..e4e0f634e --- /dev/null +++ b/tests/ui/traits/new-solver/alias-bound-preference.rs @@ -0,0 +1,39 @@ +// revisions: old next +//[next] compile-flags: -Ztrait-solver=next +// run-pass + +// A test for https://github.com/rust-lang/trait-system-refactor-initiative/issues/45. + +trait Trait { + type Assoc: Into; +} +impl> Trait for T { + type Assoc = T; +} +fn prefer_alias_bound_projection(x: T::Assoc) { + // There are two possible types for `x`: + // - `u32` by using the "alias bound" of `::Assoc` + // - `::Assoc`, i.e. `u16`, by using `impl From for T` + // + // We infer the type of `x` to be `u32` here as it is highly likely + // that this is expected by the user. + let x = x.into(); + assert_eq!(std::mem::size_of_val(&x), 4); +} + +fn impl_trait() -> impl Into { + 0u16 +} + +fn main() { + // There are two possible types for `x`: + // - `u32` by using the "alias bound" of `impl Into` + // - `impl Into`, i.e. `u16`, by using `impl From for T` + // + // We infer the type of `x` to be `u32` here as it is highly likely + // that this is expected by the user. + let x = impl_trait().into(); + assert_eq!(std::mem::size_of_val(&x), 4); + + prefer_alias_bound_projection::(1); +} diff --git a/tests/ui/traits/new-solver/alias-bound-unsound.rs b/tests/ui/traits/new-solver/alias-bound-unsound.rs index 959f1afa0..38d83d289 100644 --- a/tests/ui/traits/new-solver/alias-bound-unsound.rs +++ b/tests/ui/traits/new-solver/alias-bound-unsound.rs @@ -16,12 +16,17 @@ trait Foo { impl Foo for () { type Item = String where String: Copy; + //~^ ERROR overflow evaluating the requirement `<() as Foo>::Item: Copy` } fn main() { let x = String::from("hello, world"); drop(<() as Foo>::copy_me(&x)); - //~^ ERROR the type `&<() as Foo>::Item` is not well-formed - //~| ERROR `<() as Foo>::Item` is not well-formed + //~^ ERROR overflow evaluating the requirement `<() as Foo>::Item: Sized` + //~| ERROR overflow evaluating the requirement `<() as Foo>::Item == _` + //~| ERROR overflow evaluating the requirement `<() as Foo>::Item well-formed` + //~| ERROR overflow evaluating the requirement `String <: <() as Foo>::Item` + //~| ERROR overflow evaluating the requirement `&<() as Foo>::Item well-formed` + //~| ERROR type annotations needed println!("{x}"); } diff --git a/tests/ui/traits/new-solver/alias-bound-unsound.stderr b/tests/ui/traits/new-solver/alias-bound-unsound.stderr index 5800e2c43..abc6677c1 100644 --- a/tests/ui/traits/new-solver/alias-bound-unsound.stderr +++ b/tests/ui/traits/new-solver/alias-bound-unsound.stderr @@ -1,14 +1,69 @@ -error: the type `&<() as Foo>::Item` is not well-formed - --> $DIR/alias-bound-unsound.rs:23:31 +error[E0275]: overflow evaluating the requirement `<() as Foo>::Item: Copy` + --> $DIR/alias-bound-unsound.rs:18:17 + | +LL | type Item = String where String: Copy; + | ^^^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`) +note: required by a bound in `Foo::Item` + --> $DIR/alias-bound-unsound.rs:8:16 + | +LL | type Item: Copy + | ^^^^ required by this bound in `Foo::Item` + +error[E0282]: type annotations needed + --> $DIR/alias-bound-unsound.rs:24:5 + | +LL | drop(<() as Foo>::copy_me(&x)); + | ^^^^ cannot infer type of the type parameter `T` declared on the function `drop` + | +help: consider specifying the generic argument + | +LL | drop::(<() as Foo>::copy_me(&x)); + | +++++ + +error[E0275]: overflow evaluating the requirement `&<() as Foo>::Item well-formed` + --> $DIR/alias-bound-unsound.rs:24:31 | LL | drop(<() as Foo>::copy_me(&x)); | ^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`) -error: the type `<() as Foo>::Item` is not well-formed - --> $DIR/alias-bound-unsound.rs:23:10 +error[E0275]: overflow evaluating the requirement `String <: <() as Foo>::Item` + --> $DIR/alias-bound-unsound.rs:24:31 + | +LL | drop(<() as Foo>::copy_me(&x)); + | ^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`) + +error[E0275]: overflow evaluating the requirement `<() as Foo>::Item well-formed` + --> $DIR/alias-bound-unsound.rs:24:10 + | +LL | drop(<() as Foo>::copy_me(&x)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`) + +error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _` + --> $DIR/alias-bound-unsound.rs:24:10 | LL | drop(<() as Foo>::copy_me(&x)); | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`) + +error[E0275]: overflow evaluating the requirement `<() as Foo>::Item: Sized` + --> $DIR/alias-bound-unsound.rs:24:10 + | +LL | drop(<() as Foo>::copy_me(&x)); + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`) + = note: the return type of a function must have a statically known size -error: aborting due to 2 previous errors +error: aborting due to 7 previous errors +Some errors have detailed explanations: E0275, E0282. +For more information about an error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/new-solver/assembly/assemble-normalizing-self-ty-impl-ambiguity.rs b/tests/ui/traits/new-solver/assembly/assemble-normalizing-self-ty-impl-ambiguity.rs new file mode 100644 index 000000000..826e8c1e0 --- /dev/null +++ b/tests/ui/traits/new-solver/assembly/assemble-normalizing-self-ty-impl-ambiguity.rs @@ -0,0 +1,27 @@ +// compile-flags: -Ztrait-solver=next +// check-pass + +// Checks that we do not get ambiguity by considering an impl +// multiple times if we're able to normalize the self type. + +trait Trait<'a> {} + +impl<'a, T: 'a> Trait<'a> for T {} + +fn impls_trait<'a, T: Trait<'a>>() {} + +trait Id { + type Assoc; +} +impl Id for T { + type Assoc = T; +} + +fn call() { + impls_trait::<::Assoc>(); +} + +fn main() { + call::<()>(); + impls_trait::<<<() as Id>::Assoc as Id>::Assoc>(); +} diff --git a/tests/ui/traits/new-solver/assembly/runaway-impl-candidate-selection.rs b/tests/ui/traits/new-solver/assembly/runaway-impl-candidate-selection.rs new file mode 100644 index 000000000..1dca86d36 --- /dev/null +++ b/tests/ui/traits/new-solver/assembly/runaway-impl-candidate-selection.rs @@ -0,0 +1,15 @@ +// compile-flags: -Ztrait-solver=next + +// In the new solver, we are trying to select `::Item: Debug`, +// which, naively can be unified with every impl of `Debug` if we're not careful. +// This test makes sure that we treat projections with inference var substs as +// placeholders during fast reject. + +fn iter() -> ::Item { + todo!() +} + +fn main() { + println!("{:?}", iter::<_>()); + //~^ ERROR type annotations needed +} diff --git a/tests/ui/traits/new-solver/assembly/runaway-impl-candidate-selection.stderr b/tests/ui/traits/new-solver/assembly/runaway-impl-candidate-selection.stderr new file mode 100644 index 000000000..47004821a --- /dev/null +++ b/tests/ui/traits/new-solver/assembly/runaway-impl-candidate-selection.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/runaway-impl-candidate-selection.rs:13:22 + | +LL | println!("{:?}", iter::<_>()); + | ^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `iter` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-norm-overflow.rs b/tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-norm-overflow.rs new file mode 100644 index 000000000..b39ae0333 --- /dev/null +++ b/tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-norm-overflow.rs @@ -0,0 +1,20 @@ +// compile-flags: -Ztrait-solver=next + +// Coherence should handle overflow while normalizing for +// `trait_ref_is_knowable` correctly. + +trait Overflow { + type Assoc; +} +impl Overflow for T { + type Assoc = ::Assoc; +} + + +trait Trait {} +impl Trait for T {} +struct LocalTy; +impl Trait for ::Assoc {} +//~^ ERROR conflicting implementations of trait `Trait` for type `::Assoc` + +fn main() {} diff --git a/tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr b/tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr new file mode 100644 index 000000000..5d5f325e4 --- /dev/null +++ b/tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `Trait` for type `::Assoc` + --> $DIR/trait_ref_is_knowable-norm-overflow.rs:17:1 + | +LL | impl Trait for T {} + | ------------------------- first implementation here +LL | struct LocalTy; +LL | impl Trait for ::Assoc {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `::Assoc` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-normalization-1.rs b/tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-normalization-1.rs new file mode 100644 index 000000000..c38e3baf5 --- /dev/null +++ b/tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-normalization-1.rs @@ -0,0 +1,22 @@ +// compile-flags: -Ztrait-solver=next +// check-pass + +trait Id { + type Assoc; +} +impl Id for T { + type Assoc = T; +} + + +// Coherence should be able to reason that `::Assoc: Copy` +// does not hold. +// +// See https://github.com/rust-lang/trait-system-refactor-initiative/issues/51 +// for more details. +trait Trait {} +impl Trait for T {} +struct LocalTy; +impl Trait for ::Assoc {} + +fn main() {} diff --git a/tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-normalization-2.rs b/tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-normalization-2.rs new file mode 100644 index 000000000..2d53266db --- /dev/null +++ b/tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-normalization-2.rs @@ -0,0 +1,25 @@ +// compile-flags: -Ztrait-solver=next +// check-pass + +use std::future::{Future, IntoFuture}; +use std::pin::Pin; + +// We check that this does not overlap with the following impl from std: +// impl

Future for Pin

where P: DerefMut,

::Target: Future { .. } +// This should fail because we know ` <&mut Value as Deref>::Target: Future` not to hold. +// For this to work we have to normalize in the `trait_ref_is_knowable` check as we +// otherwise add an ambiguous candidate here. +// +// See https://github.com/rust-lang/trait-system-refactor-initiative/issues/51 +// for more details. +struct Value; +impl<'a> IntoFuture for Pin<&'a mut Value> { + type Output = (); + type IntoFuture = Pin + Send>>; + + fn into_future(self) -> Self::IntoFuture { + todo!() + } +} + +fn main() {} diff --git a/tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-normalization-3.rs b/tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-normalization-3.rs new file mode 100644 index 000000000..2f27de4e4 --- /dev/null +++ b/tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-normalization-3.rs @@ -0,0 +1,24 @@ +// compile-flags: -Ztrait-solver=next +// check-pass + +trait Id { + type Assoc; +} +impl Id for T { + type Assoc = T; +} + + +// Coherence should be able to reason that `(): PartialEq<::Assoc>>` +// does not hold. +// +// See https://github.com/rust-lang/trait-system-refactor-initiative/issues/51 +// for more details. +trait Trait {} +impl Trait for T +where + (): PartialEq {} +struct LocalTy; +impl Trait for ::Assoc {} + +fn main() {} diff --git a/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.rs b/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.rs new file mode 100644 index 000000000..fcafdcf63 --- /dev/null +++ b/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.rs @@ -0,0 +1,32 @@ +// compile-flags: -Ztrait-solver=next + +// Proving `W: Trait` instantiates `?0` with `(W, W)` and then +// proves `W: Trait` and `W: Trait`, resulting in a coinductive cycle. +// +// Proving coinductive cycles runs until we reach a fixpoint. This fixpoint is +// never reached here and each step doubles the amount of nested obligations. +// +// This previously caused a hang in the trait solver, see +// https://github.com/rust-lang/trait-system-refactor-initiative/issues/13. + +#![feature(rustc_attrs)] + +#[rustc_coinductive] +trait Trait {} + +struct W(T); + +impl Trait for W<(W, W)> +where + W: Trait, + W: Trait, +{ +} + +fn impls() {} + +fn main() { + impls::>(); + //~^ ERROR type annotations needed + //~| ERROR overflow evaluating the requirement +} diff --git a/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.stderr b/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.stderr new file mode 100644 index 000000000..7d3535e1f --- /dev/null +++ b/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.stderr @@ -0,0 +1,23 @@ +error[E0282]: type annotations needed + --> $DIR/fixpoint-exponential-growth.rs:29:5 + | +LL | impls::>(); + | ^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `impls` + +error[E0275]: overflow evaluating the requirement `W<_>: Trait` + --> $DIR/fixpoint-exponential-growth.rs:29:5 + | +LL | impls::>(); + | ^^^^^^^^^^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`fixpoint_exponential_growth`) +note: required by a bound in `impls` + --> $DIR/fixpoint-exponential-growth.rs:26:13 + | +LL | fn impls() {} + | ^^^^^ required by this bound in `impls` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0275, E0282. +For more information about an error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/new-solver/cycles/coinduction/incompleteness-unstable-result.rs b/tests/ui/traits/new-solver/cycles/coinduction/incompleteness-unstable-result.rs new file mode 100644 index 000000000..0cd14f05c --- /dev/null +++ b/tests/ui/traits/new-solver/cycles/coinduction/incompleteness-unstable-result.rs @@ -0,0 +1,69 @@ +// compile-flags: -Ztrait-solver=next +#![feature(rustc_attrs)] + +// This test is incredibly subtle. At its core the goal is to get a coinductive cycle, +// which, depending on its root goal, either holds or errors. We achieve this by getting +// incomplete inference via a `ParamEnv` candidate in the `A` impl and required +// inference from an `Impl` candidate in the `B` impl. +// +// To make global cache accesses stronger than the guidance from the where-bounds, we add +// another coinductive cycle from `A: Trait` to `A: Trait` and only +// constrain `D` directly. This means that any candidates which rely on `V` only make +// progress in the second iteration, allowing a cache access in the first iteration to take +// precedence. +// +// tl;dr: our caching of coinductive cycles was broken and this is a regression +// test for that. + +#[rustc_coinductive] +trait Trait {} +struct A(*const T); +struct B(*const T); + +trait IncompleteGuidance {} +impl IncompleteGuidance for T {} +impl IncompleteGuidance for T {} +impl IncompleteGuidance for T {} + +trait ImplGuidance {} +impl ImplGuidance for T {} +impl ImplGuidance for T {} + +impl Trait for A +where + T: IncompleteGuidance, + A: Trait, + B: Trait, + (): ToU8, +{ +} + +trait ToU8 {} +impl ToU8 for () {} + +impl Trait for B +where + T: ImplGuidance, + A: Trait, +{ +} + +fn impls_trait, U: ?Sized, V: ?Sized, D: ?Sized>() {} + +fn with_bound() +where + X: IncompleteGuidance, + X: IncompleteGuidance, + X: IncompleteGuidance, +{ + impls_trait::, _, _, _>(); // entering the cycle from `B` works + + // entering the cycle from `A` fails, but would work if we were to use the cache + // result of `B`. + impls_trait::, _, _, _>(); + //~^ ERROR the trait bound `A: Trait<_, _, _>` is not satisfied +} + +fn main() { + with_bound::(); +} diff --git a/tests/ui/traits/new-solver/cycles/coinduction/incompleteness-unstable-result.stderr b/tests/ui/traits/new-solver/cycles/coinduction/incompleteness-unstable-result.stderr new file mode 100644 index 000000000..f1871ff05 --- /dev/null +++ b/tests/ui/traits/new-solver/cycles/coinduction/incompleteness-unstable-result.stderr @@ -0,0 +1,16 @@ +error[E0277]: the trait bound `A: Trait<_, _, _>` is not satisfied + --> $DIR/incompleteness-unstable-result.rs:63:19 + | +LL | impls_trait::, _, _, _>(); + | ^^^^ the trait `Trait<_, _, _>` is not implemented for `A` + | + = help: the trait `Trait` is implemented for `A` +note: required by a bound in `impls_trait` + --> $DIR/incompleteness-unstable-result.rs:51:28 + | +LL | fn impls_trait, U: ?Sized, V: ?Sized, D: ?Sized>() {} + | ^^^^^^^^^^^^^^ required by this bound in `impls_trait` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/new-solver/cycles/double-cycle-inductive-coinductive.rs b/tests/ui/traits/new-solver/cycles/double-cycle-inductive-coinductive.rs new file mode 100644 index 000000000..5617e45ad --- /dev/null +++ b/tests/ui/traits/new-solver/cycles/double-cycle-inductive-coinductive.rs @@ -0,0 +1,37 @@ +// compile-flags: -Ztrait-solver=next +#![feature(rustc_attrs)] + +// Test that having both an inductive and a coinductive cycle +// is handled correctly. + +#[rustc_coinductive] +trait Trait {} +impl Trait for T {} + +trait Inductive {} +impl Inductive for T {} +#[rustc_coinductive] +trait Coinductive {} +impl Coinductive for T {} + +fn impls_trait() {} + +#[rustc_coinductive] +trait TraitRev {} +impl TraitRev for T {} + +trait InductiveRev {} +impl InductiveRev for T {} +#[rustc_coinductive] +trait CoinductiveRev {} +impl CoinductiveRev for T {} + +fn impls_trait_rev() {} + +fn main() { + impls_trait::<()>(); + //~^ ERROR overflow evaluating the requirement + + impls_trait_rev::<()>(); + //~^ ERROR overflow evaluating the requirement +} diff --git a/tests/ui/traits/new-solver/cycles/double-cycle-inductive-coinductive.stderr b/tests/ui/traits/new-solver/cycles/double-cycle-inductive-coinductive.stderr new file mode 100644 index 000000000..4b8846da5 --- /dev/null +++ b/tests/ui/traits/new-solver/cycles/double-cycle-inductive-coinductive.stderr @@ -0,0 +1,29 @@ +error[E0275]: overflow evaluating the requirement `(): Trait` + --> $DIR/double-cycle-inductive-coinductive.rs:32:5 + | +LL | impls_trait::<()>(); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`double_cycle_inductive_coinductive`) +note: required by a bound in `impls_trait` + --> $DIR/double-cycle-inductive-coinductive.rs:17:19 + | +LL | fn impls_trait() {} + | ^^^^^ required by this bound in `impls_trait` + +error[E0275]: overflow evaluating the requirement `(): TraitRev` + --> $DIR/double-cycle-inductive-coinductive.rs:35:5 + | +LL | impls_trait_rev::<()>(); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`double_cycle_inductive_coinductive`) +note: required by a bound in `impls_trait_rev` + --> $DIR/double-cycle-inductive-coinductive.rs:29:23 + | +LL | fn impls_trait_rev() {} + | ^^^^^^^^ required by this bound in `impls_trait_rev` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/new-solver/cycles/inductive-cycle-but-err.rs b/tests/ui/traits/new-solver/cycles/inductive-cycle-but-err.rs new file mode 100644 index 000000000..cda987898 --- /dev/null +++ b/tests/ui/traits/new-solver/cycles/inductive-cycle-but-err.rs @@ -0,0 +1,48 @@ +// compile-flags: -Ztrait-solver=next +#![feature(trivial_bounds, marker_trait_attr)] +#![allow(trivial_bounds)] +// This previously triggered a bug in the provisional cache. +// +// This has the proof tree +// - `MultipleCandidates: Trait` proven via impl-one +// - `MultipleNested: Trait` via impl +// - `MultipleCandidates: Trait` (inductive cycle ~> OVERFLOW) +// - `DoesNotImpl: Trait` (ERR) +// - `MultipleCandidates: Trait` proven via impl-two +// - `MultipleNested: Trait` (in provisional cache ~> OVERFLOW) +// +// We previously incorrectly treated the `MultipleCandidates: Trait` as +// overflow because it was in the cache and reached via an inductive cycle. +// It should be `NoSolution`. + +struct MultipleCandidates; +struct MultipleNested; +struct DoesNotImpl; + +#[marker] +trait Trait {} + +// impl-one +impl Trait for MultipleCandidates +where + MultipleNested: Trait +{} + +// impl-two +impl Trait for MultipleCandidates +where + MultipleNested: Trait, +{} + +impl Trait for MultipleNested +where + MultipleCandidates: Trait, + DoesNotImpl: Trait, +{} + +fn impls_trait() {} + +fn main() { + impls_trait::(); + //~^ ERROR the trait bound `MultipleCandidates: Trait` is not satisfied +} diff --git a/tests/ui/traits/new-solver/cycles/inductive-cycle-but-err.stderr b/tests/ui/traits/new-solver/cycles/inductive-cycle-but-err.stderr new file mode 100644 index 000000000..57227321a --- /dev/null +++ b/tests/ui/traits/new-solver/cycles/inductive-cycle-but-err.stderr @@ -0,0 +1,16 @@ +error[E0277]: the trait bound `MultipleCandidates: Trait` is not satisfied + --> $DIR/inductive-cycle-but-err.rs:46:19 + | +LL | impls_trait::(); + | ^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `MultipleCandidates` + | + = help: the trait `Trait` is implemented for `MultipleCandidates` +note: required by a bound in `impls_trait` + --> $DIR/inductive-cycle-but-err.rs:43:19 + | +LL | fn impls_trait() {} + | ^^^^^ required by this bound in `impls_trait` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/new-solver/cycles/inductive-cycle-but-ok.rs b/tests/ui/traits/new-solver/cycles/inductive-cycle-but-ok.rs new file mode 100644 index 000000000..d4851eb69 --- /dev/null +++ b/tests/ui/traits/new-solver/cycles/inductive-cycle-but-ok.rs @@ -0,0 +1,44 @@ +// compile-flags: -Ztrait-solver=next +// check-pass +#![feature(trivial_bounds, marker_trait_attr)] +#![allow(trivial_bounds)] + +// This previously triggered a bug in the provisional cache. +// +// This has the proof tree +// - `Root: Trait` proven via impl +// - `MultipleCandidates: Trait` +// - candidate: overflow-impl +// - `Root: Trait` (inductive cycle ~> OVERFLOW) +// - candidate: trivial-impl ~> YES +// - merge respones ~> YES +// - `MultipleCandidates: Trait` (in provisional cache ~> OVERFLOW) +// +// We previously incorrectly treated the `MultipleCandidates: Trait` as +// overflow because it was in the cache and reached via an inductive cycle. +// It should be `YES`. + +struct Root; +struct MultipleCandidates; + +#[marker] +trait Trait {} +impl Trait for Root +where + MultipleCandidates: Trait, + MultipleCandidates: Trait, +{} + +// overflow-impl +impl Trait for MultipleCandidates +where + Root: Trait, +{} +// trivial-impl +impl Trait for MultipleCandidates {} + +fn impls_trait() {} + +fn main() { + impls_trait::(); +} diff --git a/tests/ui/traits/new-solver/cycles/inductive-cycle-discarded-coinductive-constraints.rs b/tests/ui/traits/new-solver/cycles/inductive-cycle-discarded-coinductive-constraints.rs new file mode 100644 index 000000000..530e6d0ec --- /dev/null +++ b/tests/ui/traits/new-solver/cycles/inductive-cycle-discarded-coinductive-constraints.rs @@ -0,0 +1,36 @@ +// check-pass +// compile-flags: -Ztrait-solver=next +#![feature(rustc_attrs, marker_trait_attr)] +#[rustc_coinductive] +trait Trait {} + +impl Trait for (T, U) +where + (U, T): Trait, + (T, U): Inductive, + (): ConstrainToU32, +{} + +trait ConstrainToU32 {} +impl ConstrainToU32 for () {} + +// We only prefer the candidate without an inductive cycle +// once the inductive cycle has the same constraints as the +// other goal. +#[marker] +trait Inductive {} +impl Inductive for (T, U) +where + (T, U): Trait, +{} + +impl Inductive for (u32, u32) {} + +fn impls_trait() +where + (T, U): Trait, +{} + +fn main() { + impls_trait::<_, _>(); +} diff --git a/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.rs b/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.rs new file mode 100644 index 000000000..3cfe7ab87 --- /dev/null +++ b/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.rs @@ -0,0 +1,46 @@ +// compile-flags: -Ztrait-solver=next +#![feature(rustc_attrs, trivial_bounds)] + +// We have to be careful here: +// +// We either have the provisional result of `A -> B -> A` on the +// stack, which is a fully coinductive cycle. Accessing the +// provisional result for `B` as part of the `A -> C -> B -> A` cycle +// has to make sure we don't just use the result of `A -> B -> A` as the +// new cycle is inductive. +// +// Alternatively, if we have `A -> C -> A` first, then `A -> B -> A` has +// a purely inductive stack, so something could also go wrong here. + +#[rustc_coinductive] +trait A {} +#[rustc_coinductive] +trait B {} +trait C {} + +impl A for T {} +impl B for T {} +impl C for T {} + +fn impls_a() {} + +// The same test with reordered where clauses to make sure we're actually testing anything. +#[rustc_coinductive] +trait AR {} +#[rustc_coinductive] +trait BR {} +trait CR {} + +impl AR for T {} +impl BR for T {} +impl CR for T {} + +fn impls_ar() {} + +fn main() { + impls_a::<()>(); + // FIXME(-Ztrait-solver=next): This is broken and should error. + + impls_ar::<()>(); + //~^ ERROR overflow evaluating the requirement `(): AR` +} diff --git a/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.stderr b/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.stderr new file mode 100644 index 000000000..0e1c86c1b --- /dev/null +++ b/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.stderr @@ -0,0 +1,16 @@ +error[E0275]: overflow evaluating the requirement `(): AR` + --> $DIR/inductive-not-on-stack.rs:44:5 + | +LL | impls_ar::<()>(); + | ^^^^^^^^^^^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`inductive_not_on_stack`) +note: required by a bound in `impls_ar` + --> $DIR/inductive-not-on-stack.rs:38:16 + | +LL | fn impls_ar() {} + | ^^ required by this bound in `impls_ar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/new-solver/cycles/leak-check-coinductive-cycle.rs b/tests/ui/traits/new-solver/cycles/leak-check-coinductive-cycle.rs new file mode 100644 index 000000000..a6d318726 --- /dev/null +++ b/tests/ui/traits/new-solver/cycles/leak-check-coinductive-cycle.rs @@ -0,0 +1,33 @@ +// compile-flags: -Ztrait-solver=next +// check-pass +#![feature(rustc_attrs)] + +#[rustc_coinductive] +trait Trait {} +impl<'a, 'b, T> Trait for (&'a (), &'b ()) +where + 'b: 'a, + &'a (): Trait, +{} + +impl Trait for &'static () {} +impl<'a> Trait for &'a () +where + for<'b> (&'a (), &'b ()): Trait, +{} + + +fn impls_trait, U>() {} + +fn main() { + // This infers to `impls_trait::<(&'static (), &'static ()), i32>();` + // + // In the first attempt we have 2 candidates for `&'a (): Trait<_>` + // and we get ambiguity. The result is therefore ambiguity with a `'b: 'a` + // constraint. The next attempt then uses that provisional result when + // trying to apply `impl<'a> Trait for &'a ()`. This means we get a + // `for<'b> 'b: 'a` bound which fails the leak check. Because of this we + // end up with a single impl for `&'a (): Trait<_>` which infers `_` to `i32` + // and succeeds. + impls_trait::<(&(), &()), _>(); +} diff --git a/tests/ui/traits/new-solver/cycles/provisional-result-done.rs b/tests/ui/traits/new-solver/cycles/provisional-result-done.rs new file mode 100644 index 000000000..589d34dd7 --- /dev/null +++ b/tests/ui/traits/new-solver/cycles/provisional-result-done.rs @@ -0,0 +1,33 @@ +// compile-flags: -Ztrait-solver=next +// check-pass + +// This tests checks that we update results in the provisional cache when +// we pop a goal from the stack. +#![feature(auto_traits)] +auto trait Coinductive {} +struct Foo(T); +struct Bar(T); + +impl Coinductive for Foo +where + Bar: Coinductive +{} + +impl Coinductive for Bar +where + Foo: Coinductive, + Bar: ConstrainInfer, +{} + +trait ConstrainInfer {} +impl ConstrainInfer for Bar {} +impl ConstrainInfer for Foo {} + +fn impls() -> T { todo!() } + +fn constrain(_: T) {} + +fn main() { + // This should constrain `_` to `u8`. + impls::>(); +} diff --git a/tests/ui/traits/new-solver/dont-coerce-infer-to-dyn.rs b/tests/ui/traits/new-solver/dont-coerce-infer-to-dyn.rs new file mode 100644 index 000000000..c2ac80459 --- /dev/null +++ b/tests/ui/traits/new-solver/dont-coerce-infer-to-dyn.rs @@ -0,0 +1,17 @@ +// compile-flags: -Ztrait-solver=next +// check-pass + +use std::fmt::Display; +use std::rc::Rc; + +fn mk(t: Option<&T>) -> Rc { + todo!() +} + +fn main() { + let mut x = None; + let y = mk(x); + // Don't treat the line below as a unsize coercion `Rc ~> Rc` + let z: Rc = y; + x = Some(&1 as &dyn Display); +} diff --git a/tests/ui/traits/new-solver/dont-loop-fulfill-on-region-constraints.rs b/tests/ui/traits/new-solver/dont-loop-fulfill-on-region-constraints.rs new file mode 100644 index 000000000..b241e3bf8 --- /dev/null +++ b/tests/ui/traits/new-solver/dont-loop-fulfill-on-region-constraints.rs @@ -0,0 +1,32 @@ +// compile-flags: -Ztrait-solver=next +// check-pass + +trait Eq<'a, 'b, T> {} + +trait Ambig {} +impl Ambig for () {} + +impl<'a, T> Eq<'a, 'a, T> for () where T: Ambig {} + +fn eq<'a, 'b, T>(t: T) +where + (): Eq<'a, 'b, T>, +{ +} + +fn test<'r>() { + let mut x = Default::default(); + + // When we evaluate `(): Eq<'r, 'r, ?0>` we uniquify the regions. + // That leads us to evaluate `(): Eq<'?0, '?1, ?0>`. The response of this + // will be ambiguous (because `?0: Ambig` is ambig) and also not an "identity" + // response, since the region constraints will contain `'?0 == '?1` (so + // `is_changed` will return true). Since it's both ambig and changed, + // fulfillment will both re-register the goal AND loop again. This hits the + // overflow limit. This should neither be considered overflow, nor ICE. + eq::<'r, 'r, _>(x); + + x = (); +} + +fn main() {} diff --git a/tests/ui/traits/new-solver/dont-normalize-proj-with-error.rs b/tests/ui/traits/new-solver/dont-normalize-proj-with-error.rs new file mode 100644 index 000000000..19a6fa990 --- /dev/null +++ b/tests/ui/traits/new-solver/dont-normalize-proj-with-error.rs @@ -0,0 +1,22 @@ +// compile-flags: -Ztrait-solver=next + +// Test that we don't incorrectly leak unconstrained inference variables +// if the projection contained an error. This caused an ICE in writeback. + +trait Mirror { + type Assoc: ?Sized; +} + +struct Wrapper(T); +impl Mirror for Wrapper { + type Assoc = T; +} + +fn mirror(_: W) -> Box { todo!() } + +fn type_error() -> TypeError { todo!() } +//~^ ERROR cannot find type `TypeError` in this scope + +fn main() { + let x = mirror(type_error()); +} diff --git a/tests/ui/traits/new-solver/dont-normalize-proj-with-error.stderr b/tests/ui/traits/new-solver/dont-normalize-proj-with-error.stderr new file mode 100644 index 000000000..5a7459ec1 --- /dev/null +++ b/tests/ui/traits/new-solver/dont-normalize-proj-with-error.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `TypeError` in this scope + --> $DIR/dont-normalize-proj-with-error.rs:17:20 + | +LL | fn type_error() -> TypeError { todo!() } + | ^^^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/traits/new-solver/dyn-any-dont-prefer-impl.rs b/tests/ui/traits/new-solver/dyn-any-dont-prefer-impl.rs index 7d15b8c63..af35a6195 100644 --- a/tests/ui/traits/new-solver/dyn-any-dont-prefer-impl.rs +++ b/tests/ui/traits/new-solver/dyn-any-dont-prefer-impl.rs @@ -1,6 +1,10 @@ // compile-flags: -Ztrait-solver=next // check-pass +// Test that selection prefers the builtin trait object impl for `Any` +// instead of the user defined impl. Both impls apply to the trait +// object. + use std::any::Any; fn needs_usize(_: &usize) {} diff --git a/tests/ui/traits/new-solver/escaping-bound-vars-in-writeback-normalization.rs b/tests/ui/traits/new-solver/escaping-bound-vars-in-writeback-normalization.rs new file mode 100644 index 000000000..29784c32a --- /dev/null +++ b/tests/ui/traits/new-solver/escaping-bound-vars-in-writeback-normalization.rs @@ -0,0 +1,18 @@ +// compile-flags: -Ztrait-solver=next +// check-pass + +trait Trivial { + type Assoc; +} + +impl Trivial for T { + type Assoc = (); +} + +fn main() { + // During writeback, we call `normalize_erasing_regions`, which will walk past + // the `for<'a>` binder and try to normalize `<&'a () as Trivial>::Assoc` directly. + // We need to handle this case in the new deep normalizer similarly to how it + // is handled in the old solver. + let x: Option fn(<&'a () as Trivial>::Assoc)> = None; +} diff --git a/tests/ui/traits/new-solver/exponential-trait-goals.rs b/tests/ui/traits/new-solver/exponential-trait-goals.rs deleted file mode 100644 index b37f09ee1..000000000 --- a/tests/ui/traits/new-solver/exponential-trait-goals.rs +++ /dev/null @@ -1,20 +0,0 @@ -// compile-flags: -Ztrait-solver=next - -trait Trait {} - -struct W(T); - -impl Trait for W<(W, W)> -where - W: Trait, - W: Trait, -{ -} - -fn impls() {} - -fn main() { - impls::>(); - //~^ ERROR type annotations needed - //~| ERROR overflow evaluating the requirement `W<_>: Trait` -} diff --git a/tests/ui/traits/new-solver/exponential-trait-goals.stderr b/tests/ui/traits/new-solver/exponential-trait-goals.stderr deleted file mode 100644 index 28a99cbbc..000000000 --- a/tests/ui/traits/new-solver/exponential-trait-goals.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0282]: type annotations needed - --> $DIR/exponential-trait-goals.rs:17:5 - | -LL | impls::>(); - | ^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `impls` - -error[E0275]: overflow evaluating the requirement `W<_>: Trait` - --> $DIR/exponential-trait-goals.rs:17:5 - | -LL | impls::>(); - | ^^^^^^^^^^^^^ - | - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`exponential_trait_goals`) -note: required by a bound in `impls` - --> $DIR/exponential-trait-goals.rs:14:13 - | -LL | fn impls() {} - | ^^^^^ required by this bound in `impls` - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0275, E0282. -For more information about an error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-1.rs b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-1.rs new file mode 100644 index 000000000..b0b9b6bbd --- /dev/null +++ b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-1.rs @@ -0,0 +1,73 @@ +// compile-flags: -Ztrait-solver=next +// check-pass + +// A minimization of an ambiguity when using typenum. See +// https://github.com/rust-lang/trait-system-refactor-initiative/issues/55 +// for more details. +trait Id { + type Assoc: ?Sized; +} +impl Id for T { + type Assoc = T; +} + +trait WithAssoc { + type Assoc: ?Sized; +} + + +struct Leaf; +struct Wrapper(U); + +impl WithAssoc for Leaf { + type Assoc = U; +} + +impl WithAssoc> for Wrapper