summaryrefslogtreecommitdiffstats
path: root/tests/ui/traits/next-solver
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ui/traits/next-solver')
-rw-r--r--tests/ui/traits/next-solver/alias-bound-preference.rs39
-rw-r--r--tests/ui/traits/next-solver/alias-bound-unsound.rs32
-rw-r--r--tests/ui/traits/next-solver/alias-bound-unsound.stderr65
-rw-r--r--tests/ui/traits/next-solver/alias-eq-in-canonical-response.rs40
-rw-r--r--tests/ui/traits/next-solver/alias-relate/deeply-nested-no-hang.rs22
-rw-r--r--tests/ui/traits/next-solver/alias-relate/opaque-hidden-ty-is-rigid-alias.rs8
-rw-r--r--tests/ui/traits/next-solver/alias-sub.rs34
-rw-r--r--tests/ui/traits/next-solver/alias_eq_cant_be_furthur_normalized.rs29
-rw-r--r--tests/ui/traits/next-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.rs47
-rw-r--r--tests/ui/traits/next-solver/alias_eq_simple.rs22
-rw-r--r--tests/ui/traits/next-solver/alias_eq_substs_eq_not_intercrate.rs17
-rw-r--r--tests/ui/traits/next-solver/alias_eq_substs_eq_not_intercrate.stderr13
-rw-r--r--tests/ui/traits/next-solver/array-default.rs8
-rw-r--r--tests/ui/traits/next-solver/assembly/assemble-normalizing-self-ty-impl-ambiguity.rs27
-rw-r--r--tests/ui/traits/next-solver/assembly/runaway-impl-candidate-selection.rs15
-rw-r--r--tests/ui/traits/next-solver/assembly/runaway-impl-candidate-selection.stderr16
-rw-r--r--tests/ui/traits/next-solver/async.fail.stderr17
-rw-r--r--tests/ui/traits/next-solver/async.rs19
-rw-r--r--tests/ui/traits/next-solver/auto-with-drop_tracking_mir.fail.stderr18
-rw-r--r--tests/ui/traits/next-solver/auto-with-drop_tracking_mir.rs27
-rw-r--r--tests/ui/traits/next-solver/borrowck-error.rs11
-rw-r--r--tests/ui/traits/next-solver/borrowck-error.stderr12
-rw-r--r--tests/ui/traits/next-solver/builtin-fn-must-return-sized.rs17
-rw-r--r--tests/ui/traits/next-solver/builtin-fn-must-return-sized.stderr16
-rw-r--r--tests/ui/traits/next-solver/canonical-int-var-eq-in-response.rs22
-rw-r--r--tests/ui/traits/next-solver/canonical-ty-var-eq-in-response.rs39
-rw-r--r--tests/ui/traits/next-solver/canonicalize-effect-var.rs22
-rw-r--r--tests/ui/traits/next-solver/cast-checks-handling-projections.rs6
-rw-r--r--tests/ui/traits/next-solver/closure-inference-guidance.rs11
-rw-r--r--tests/ui/traits/next-solver/closure-signature-inference-2.rs21
-rw-r--r--tests/ui/traits/next-solver/closure-signature-inference.rs15
-rw-r--r--tests/ui/traits/next-solver/closure-substs-ambiguity.rs7
-rw-r--r--tests/ui/traits/next-solver/coerce-ambig-alias-to-rigid-alias.rs15
-rw-r--r--tests/ui/traits/next-solver/coherence/issue-102048.rs44
-rw-r--r--tests/ui/traits/next-solver/coherence/issue-102048.stderr16
-rw-r--r--tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.rs20
-rw-r--r--tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr12
-rw-r--r--tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-normalization-1.rs22
-rw-r--r--tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-normalization-2.rs25
-rw-r--r--tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-normalization-3.rs24
-rw-r--r--tests/ui/traits/next-solver/const-param-placeholder.fail.stderr16
-rw-r--r--tests/ui/traits/next-solver/const-param-placeholder.rs21
-rw-r--r--tests/ui/traits/next-solver/coroutine.fail.stderr64
-rw-r--r--tests/ui/traits/next-solver/coroutine.rs32
-rw-r--r--tests/ui/traits/next-solver/cycles/coinduction/fixpoint-exponential-growth.rs35
-rw-r--r--tests/ui/traits/next-solver/cycles/coinduction/fixpoint-exponential-growth.stderr16
-rw-r--r--tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.rs69
-rw-r--r--tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.stderr16
-rw-r--r--tests/ui/traits/next-solver/cycles/double-cycle-inductive-coinductive.rs37
-rw-r--r--tests/ui/traits/next-solver/cycles/double-cycle-inductive-coinductive.stderr29
-rw-r--r--tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.rs53
-rw-r--r--tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.stderr10
-rw-r--r--tests/ui/traits/next-solver/cycles/inductive-cycle-but-err.rs48
-rw-r--r--tests/ui/traits/next-solver/cycles/inductive-cycle-but-err.stderr16
-rw-r--r--tests/ui/traits/next-solver/cycles/inductive-cycle-but-ok.rs44
-rw-r--r--tests/ui/traits/next-solver/cycles/inductive-cycle-discarded-coinductive-constraints.rs36
-rw-r--r--tests/ui/traits/next-solver/cycles/inductive-fixpoint-hang.rs33
-rw-r--r--tests/ui/traits/next-solver/cycles/inductive-fixpoint-hang.stderr16
-rw-r--r--tests/ui/traits/next-solver/cycles/inductive-not-on-stack.rs46
-rw-r--r--tests/ui/traits/next-solver/cycles/inductive-not-on-stack.stderr29
-rw-r--r--tests/ui/traits/next-solver/cycles/leak-check-coinductive-cycle.rs33
-rw-r--r--tests/ui/traits/next-solver/cycles/provisional-result-done.rs33
-rw-r--r--tests/ui/traits/next-solver/deduce-closure-signature-after-normalization.rs10
-rw-r--r--tests/ui/traits/next-solver/deduce-ty-from-object.rs6
-rw-r--r--tests/ui/traits/next-solver/dedup-regions.rs31
-rw-r--r--tests/ui/traits/next-solver/destruct.rs13
-rw-r--r--tests/ui/traits/next-solver/dont-coerce-infer-to-dyn.rs17
-rw-r--r--tests/ui/traits/next-solver/dont-elaborate-for-projections.rs12
-rw-r--r--tests/ui/traits/next-solver/dont-ice-on-assoc-projection.rs19
-rw-r--r--tests/ui/traits/next-solver/dont-ice-on-assoc-projection.stderr21
-rw-r--r--tests/ui/traits/next-solver/dont-loop-fulfill-on-region-constraints.rs32
-rw-r--r--tests/ui/traits/next-solver/dont-normalize-proj-with-error.rs22
-rw-r--r--tests/ui/traits/next-solver/dont-normalize-proj-with-error.stderr9
-rw-r--r--tests/ui/traits/next-solver/dont-remap-tait-substs.rs19
-rw-r--r--tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.not_send.stderr16
-rw-r--r--tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.rs24
-rw-r--r--tests/ui/traits/next-solver/dyn-any-dont-prefer-impl.rs17
-rw-r--r--tests/ui/traits/next-solver/elaborate-item-bounds.rs12
-rw-r--r--tests/ui/traits/next-solver/equating-projection-cyclically.rs31
-rw-r--r--tests/ui/traits/next-solver/escaping-bound-vars-in-writeback-normalization.rs18
-rw-r--r--tests/ui/traits/next-solver/float-canonical.rs8
-rw-r--r--tests/ui/traits/next-solver/fn-trait-closure.rs8
-rw-r--r--tests/ui/traits/next-solver/fn-trait.rs32
-rw-r--r--tests/ui/traits/next-solver/fn-trait.stderr126
-rw-r--r--tests/ui/traits/next-solver/generalize/generalize-proj-new-universe-index-1.rs73
-rw-r--r--tests/ui/traits/next-solver/generalize/generalize-proj-new-universe-index-2.rs75
-rw-r--r--tests/ui/traits/next-solver/generalize/generalize-proj-new-universe-index-2.stderr19
-rw-r--r--tests/ui/traits/next-solver/generalize/occurs-check-nested-alias.next.stderr11
-rw-r--r--tests/ui/traits/next-solver/generalize/occurs-check-nested-alias.rs38
-rw-r--r--tests/ui/traits/next-solver/higher-ranked-dyn-bounds.rs17
-rw-r--r--tests/ui/traits/next-solver/int-var-alias-eq.rs18
-rw-r--r--tests/ui/traits/next-solver/int-var-is-send.rs8
-rw-r--r--tests/ui/traits/next-solver/issue-118950-root-region.rs22
-rw-r--r--tests/ui/traits/next-solver/issue-118950-root-region.stderr36
-rw-r--r--tests/ui/traits/next-solver/iter-filter-projection.rs12
-rw-r--r--tests/ui/traits/next-solver/lazy-nested-obligations-1.rs13
-rw-r--r--tests/ui/traits/next-solver/lazy-nested-obligations-2.rs22
-rw-r--r--tests/ui/traits/next-solver/lazy-nested-obligations-3.rs38
-rw-r--r--tests/ui/traits/next-solver/member-constraints-in-root-universe.rs17
-rw-r--r--tests/ui/traits/next-solver/more-object-bound.rs27
-rw-r--r--tests/ui/traits/next-solver/more-object-bound.stderr22
-rw-r--r--tests/ui/traits/next-solver/negative-coherence-bounds.rs40
-rw-r--r--tests/ui/traits/next-solver/negative-coherence-bounds.stderr12
-rw-r--r--tests/ui/traits/next-solver/nested-alias-bound.rs20
-rw-r--r--tests/ui/traits/next-solver/nested-obligations-with-bound-vars-gat.rs43
-rw-r--r--tests/ui/traits/next-solver/normalize-async-closure-in-trait.rs9
-rw-r--r--tests/ui/traits/next-solver/normalize-param-env-1.rs40
-rw-r--r--tests/ui/traits/next-solver/normalize-param-env-2.rs26
-rw-r--r--tests/ui/traits/next-solver/normalize-param-env-3.rs32
-rw-r--r--tests/ui/traits/next-solver/normalize-rcvr-for-inherent.rs25
-rw-r--r--tests/ui/traits/next-solver/normalize-unsize-rhs.rs22
-rw-r--r--tests/ui/traits/next-solver/normalized-const-built-in-op.rs11
-rw-r--r--tests/ui/traits/next-solver/normalizes_to_ignores_unnormalizable_candidate.rs40
-rw-r--r--tests/ui/traits/next-solver/normalizes_to_ignores_unnormalizable_candidate.self_infer.stderr22
-rw-r--r--tests/ui/traits/next-solver/object-soundness-requires-generalization.rs20
-rw-r--r--tests/ui/traits/next-solver/object-unsafety.rs27
-rw-r--r--tests/ui/traits/next-solver/object-unsafety.stderr64
-rw-r--r--tests/ui/traits/next-solver/opportunistic-region-resolve.rs19
-rw-r--r--tests/ui/traits/next-solver/overflow/exponential-trait-goals.rs19
-rw-r--r--tests/ui/traits/next-solver/overflow/exponential-trait-goals.stderr16
-rw-r--r--tests/ui/traits/next-solver/overflow/global-cache.rs23
-rw-r--r--tests/ui/traits/next-solver/overflow/global-cache.stderr16
-rw-r--r--tests/ui/traits/next-solver/overflow/recursion-limit-normalizes-to-constraints.rs25
-rw-r--r--tests/ui/traits/next-solver/overflow/recursion-limit-zero-issue-115351.rs12
-rw-r--r--tests/ui/traits/next-solver/overflow/recursion-limit-zero-issue-115351.stderr27
-rw-r--r--tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs20
-rw-r--r--tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr24
-rw-r--r--tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs16
-rw-r--r--tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr24
-rw-r--r--tests/ui/traits/next-solver/param-candidate-doesnt-shadow-project.rs25
-rw-r--r--tests/ui/traits/next-solver/param-discr-kind.rs8
-rw-r--r--tests/ui/traits/next-solver/pointee.rs21
-rw-r--r--tests/ui/traits/next-solver/pointer-like.rs14
-rw-r--r--tests/ui/traits/next-solver/pointer-like.stderr24
-rw-r--r--tests/ui/traits/next-solver/prefer-candidate-no-constraints.rs22
-rw-r--r--tests/ui/traits/next-solver/prefer-param-env-on-ambiguity.rs10
-rw-r--r--tests/ui/traits/next-solver/projection-discr-kind.rs18
-rw-r--r--tests/ui/traits/next-solver/projection-discr-kind.stderr22
-rw-r--r--tests/ui/traits/next-solver/projection/param-env-trait-candidate-1.rs14
-rw-r--r--tests/ui/traits/next-solver/projection/param-env-trait-candidate-2.rs29
-rw-r--r--tests/ui/traits/next-solver/slice-match-byte-lit.rs11
-rw-r--r--tests/ui/traits/next-solver/specialization-transmute.rs28
-rw-r--r--tests/ui/traits/next-solver/specialization-transmute.stderr26
-rw-r--r--tests/ui/traits/next-solver/specialization-unconstrained.rs22
-rw-r--r--tests/ui/traits/next-solver/specialization-unconstrained.stderr32
-rw-r--r--tests/ui/traits/next-solver/stall-num-var-auto-trait.fallback.stderr17
-rw-r--r--tests/ui/traits/next-solver/stall-num-var-auto-trait.rs25
-rw-r--r--tests/ui/traits/next-solver/structural-resolve-field.rs13
-rw-r--r--tests/ui/traits/next-solver/tait-eq-proj-2.rs23
-rw-r--r--tests/ui/traits/next-solver/tait-eq-proj.rs35
-rw-r--r--tests/ui/traits/next-solver/tait-eq-tait.rs18
-rw-r--r--tests/ui/traits/next-solver/temporary-ambiguity.rs22
-rw-r--r--tests/ui/traits/next-solver/trait-upcast-lhs-needs-normalization.rs19
-rw-r--r--tests/ui/traits/next-solver/try-example.rs28
-rw-r--r--tests/ui/traits/next-solver/two-projection-param-candidates-are-ambiguous.rs30
-rw-r--r--tests/ui/traits/next-solver/two-projection-param-candidates-are-ambiguous.stderr17
-rw-r--r--tests/ui/traits/next-solver/unevaluated-const-impl-trait-ref.fails.stderr18
-rw-r--r--tests/ui/traits/next-solver/unevaluated-const-impl-trait-ref.rs22
-rw-r--r--tests/ui/traits/next-solver/unsafe-auto-trait-impl.rs8
-rw-r--r--tests/ui/traits/next-solver/unsize-although-ambiguous.rs13
-rw-r--r--tests/ui/traits/next-solver/unsize-good.rs25
-rw-r--r--tests/ui/traits/next-solver/upcast-right-substs.rs13
-rw-r--r--tests/ui/traits/next-solver/upcast-wrong-substs.rs11
-rw-r--r--tests/ui/traits/next-solver/upcast-wrong-substs.stderr14
-rw-r--r--tests/ui/traits/next-solver/winnow-specializing-impls.rs22
165 files changed, 4008 insertions, 0 deletions
diff --git a/tests/ui/traits/next-solver/alias-bound-preference.rs b/tests/ui/traits/next-solver/alias-bound-preference.rs
new file mode 100644
index 000000000..1c6e12096
--- /dev/null
+++ b/tests/ui/traits/next-solver/alias-bound-preference.rs
@@ -0,0 +1,39 @@
+// revisions: old next
+//[next] compile-flags: -Znext-solver
+// run-pass
+
+// A test for https://github.com/rust-lang/trait-system-refactor-initiative/issues/45.
+
+trait Trait {
+ type Assoc: Into<u32>;
+}
+impl<T: Into<u32>> Trait for T {
+ type Assoc = T;
+}
+fn prefer_alias_bound_projection<T: Trait>(x: T::Assoc) {
+ // There are two possible types for `x`:
+ // - `u32` by using the "alias bound" of `<T as Trait>::Assoc`
+ // - `<T as Trait>::Assoc`, i.e. `u16`, by using `impl<T> From<T> 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<u32> {
+ 0u16
+}
+
+fn main() {
+ // There are two possible types for `x`:
+ // - `u32` by using the "alias bound" of `impl Into<u32>`
+ // - `impl Into<u32>`, i.e. `u16`, by using `impl<T> From<T> 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::<u16>(1);
+}
diff --git a/tests/ui/traits/next-solver/alias-bound-unsound.rs b/tests/ui/traits/next-solver/alias-bound-unsound.rs
new file mode 100644
index 000000000..4e279a84a
--- /dev/null
+++ b/tests/ui/traits/next-solver/alias-bound-unsound.rs
@@ -0,0 +1,32 @@
+// compile-flags: -Znext-solver
+
+// Makes sure that alias bounds are not unsound!
+
+#![feature(trivial_bounds)]
+
+trait Foo {
+ type Item: Copy
+ where
+ <Self as Foo>::Item: Copy;
+
+ fn copy_me(x: &Self::Item) -> Self::Item {
+ *x
+ }
+}
+
+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 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 overflow evaluating the requirement `<() as Foo>::Item normalizes-to _`
+ println!("{x}");
+}
diff --git a/tests/ui/traits/next-solver/alias-bound-unsound.stderr b/tests/ui/traits/next-solver/alias-bound-unsound.stderr
new file mode 100644
index 000000000..ac3f19b3f
--- /dev/null
+++ b/tests/ui/traits/next-solver/alias-bound-unsound.stderr
@@ -0,0 +1,65 @@
+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[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 == _`
+ --> $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[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[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 normalizes-to _`
+ --> $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: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/next-solver/alias-eq-in-canonical-response.rs b/tests/ui/traits/next-solver/alias-eq-in-canonical-response.rs
new file mode 100644
index 000000000..aa7c94791
--- /dev/null
+++ b/tests/ui/traits/next-solver/alias-eq-in-canonical-response.rs
@@ -0,0 +1,40 @@
+// check-pass
+// compile-flags: -Znext-solver
+
+trait Foo {
+ type Gat<'a>
+ where
+ Self: 'a;
+ fn bar(&self) -> Self::Gat<'_>;
+}
+
+enum Option<T> {
+ Some(T),
+ None,
+}
+
+impl<T> Option<T> {
+ fn as_ref(&self) -> Option<&T> {
+ match self {
+ Option::Some(t) => Option::Some(t),
+ Option::None => Option::None,
+ }
+ }
+
+ fn map<U>(self, f: impl FnOnce(T) -> U) -> Option<U> {
+ match self {
+ Option::Some(t) => Option::Some(f(t)),
+ Option::None => Option::None,
+ }
+ }
+}
+
+impl<T: Foo + 'static> Foo for Option<T> {
+ type Gat<'a> = Option<<T as Foo>::Gat<'a>> where Self: 'a;
+
+ fn bar(&self) -> Self::Gat<'_> {
+ self.as_ref().map(Foo::bar)
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/alias-relate/deeply-nested-no-hang.rs b/tests/ui/traits/next-solver/alias-relate/deeply-nested-no-hang.rs
new file mode 100644
index 000000000..91cfda37a
--- /dev/null
+++ b/tests/ui/traits/next-solver/alias-relate/deeply-nested-no-hang.rs
@@ -0,0 +1,22 @@
+// check-pass
+// compile-flags: -Znext-solver
+// regression test for trait-system-refactor-initiative#68
+trait Identity {
+ type Assoc: ?Sized;
+}
+
+impl<T: ?Sized> Identity for T {
+ type Assoc = T;
+}
+
+type Id<T> = <T as Identity>::Assoc;
+
+type Five<T> = Id<Id<Id<Id<Id<T>>>>>;
+type Ty<T> = Five<Five<Five<Five<Five<T>>>>>;
+
+trait Trait<T> {}
+
+impl<T> Trait<T> for Ty<T> {}
+impl Trait<u32> for Ty<i32> {}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/alias-relate/opaque-hidden-ty-is-rigid-alias.rs b/tests/ui/traits/next-solver/alias-relate/opaque-hidden-ty-is-rigid-alias.rs
new file mode 100644
index 000000000..88bbd13f9
--- /dev/null
+++ b/tests/ui/traits/next-solver/alias-relate/opaque-hidden-ty-is-rigid-alias.rs
@@ -0,0 +1,8 @@
+// check-pass
+// compile-flags: -Znext-solver
+
+fn test<T: Iterator>(x: T::Item) -> impl Sized {
+ x
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/alias-sub.rs b/tests/ui/traits/next-solver/alias-sub.rs
new file mode 100644
index 000000000..f7f23a024
--- /dev/null
+++ b/tests/ui/traits/next-solver/alias-sub.rs
@@ -0,0 +1,34 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+trait Trait {
+ type Assoc: Sized;
+}
+
+impl Trait for &'static str {
+ type Assoc = &'static str;
+}
+
+// Wrapper is just here to get around stupid `Sized` obligations in mir typeck
+struct Wrapper<T: ?Sized>(std::marker::PhantomData<T>);
+fn mk<T: Trait>(x: T) -> Wrapper<<T as Trait>::Assoc> { todo!() }
+
+
+trait IsStaticStr {}
+impl IsStaticStr for (&'static str,) {}
+fn define<T: IsStaticStr>(_: T) {}
+
+fn foo<'a, T: Trait>() {
+ let y = Default::default();
+
+ // `<?0 as Trait>::Assoc <: &'a str`
+ // In the old solver, this would *equate* the LHS and RHS.
+ let _: Wrapper<&'a str> = mk(y);
+
+ // ... then later on, we constrain `?0 = &'static str`
+ // but that should not mean that `'a = 'static`, because
+ // we should use *sub* above.
+ define((y,));
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/alias_eq_cant_be_furthur_normalized.rs b/tests/ui/traits/next-solver/alias_eq_cant_be_furthur_normalized.rs
new file mode 100644
index 000000000..04d1b9496
--- /dev/null
+++ b/tests/ui/traits/next-solver/alias_eq_cant_be_furthur_normalized.rs
@@ -0,0 +1,29 @@
+// check-pass
+// compile-flags: -Znext-solver
+
+// check that a goal such as `alias-eq(<T as TraitB>::Assoc<bool>, <T as TraitB>::Assoc<?0>)`
+// succeeds with a constraint that `?0 = bool`
+
+// FIXME(deferred_projection_equality): add a test that this is true during coherence
+
+trait TraitA {}
+
+trait TraitB {
+ type Assoc<T: ?Sized>;
+}
+
+impl<T: TraitB> TraitA for (T, T::Assoc<bool>) {}
+
+impl TraitB for i32 {
+ type Assoc<T: ?Sized> = u32;
+}
+
+fn needs_a<T: TraitA>() {}
+
+fn bar<T: TraitB>() {
+ needs_a::<(T, <T as TraitB>::Assoc<_>)>();
+}
+
+fn main() {
+ bar::<i32>();
+}
diff --git a/tests/ui/traits/next-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.rs b/tests/ui/traits/next-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.rs
new file mode 100644
index 000000000..48157192a
--- /dev/null
+++ b/tests/ui/traits/next-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.rs
@@ -0,0 +1,47 @@
+// compile-flags: -Znext-solver
+
+// check-pass
+// (should not pass, should be turned into a coherence-only test)
+
+// check that when computing `alias-eq(<() as Foo<u16, T>>::Assoc, <() as Foo<?0, T>>::Assoc)`
+// we do not infer `?0 = u8` via the `for<STOP> (): Foo<u8, STOP>` impl or `?0 = u16` by
+// relating substs as either could be a valid solution.
+
+trait Foo<T, STOP> {
+ type Assoc;
+}
+
+impl<STOP> Foo<u8, STOP> for ()
+where
+ (): Foo<u16, STOP>,
+{
+ type Assoc = <() as Foo<u16, STOP>>::Assoc;
+}
+
+impl Foo<u16, i8> for () {
+ type Assoc = u8;
+}
+
+impl Foo<u16, i16> for () {
+ type Assoc = u16;
+}
+
+fn output<T, U>() -> <() as Foo<T, U>>::Assoc
+where
+ (): Foo<T, U>,
+{
+ todo!()
+}
+
+fn incomplete<T>()
+where
+ (): Foo<u16, T>,
+{
+ // `<() as Foo<u16, STOP>>::Assoc == <() as Foo<_, STOP>>::Assoc`
+ let _: <() as Foo<u16, T>>::Assoc = output::<_, T>();
+
+ // let _: <() as Foo<u16, T>>::Assoc = output::<u8, T>(); // OK
+ // let _: <() as Foo<u16, T>>::Assoc = output::<u16, T>(); // OK
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/alias_eq_simple.rs b/tests/ui/traits/next-solver/alias_eq_simple.rs
new file mode 100644
index 000000000..21ad1a4fa
--- /dev/null
+++ b/tests/ui/traits/next-solver/alias_eq_simple.rs
@@ -0,0 +1,22 @@
+// check-pass
+// compile-flags: -Znext-solver
+
+// test that the new solver can handle `alias-eq(<i32 as TraitB>::Assoc, u32)`
+
+trait TraitA {}
+
+trait TraitB {
+ type Assoc;
+}
+
+impl<T: TraitB> TraitA for (T, T::Assoc) {}
+
+impl TraitB for i32 {
+ type Assoc = u32;
+}
+
+fn needs_a<T: TraitA>() {}
+
+fn main() {
+ needs_a::<(i32, u32)>();
+}
diff --git a/tests/ui/traits/next-solver/alias_eq_substs_eq_not_intercrate.rs b/tests/ui/traits/next-solver/alias_eq_substs_eq_not_intercrate.rs
new file mode 100644
index 000000000..4717aa804
--- /dev/null
+++ b/tests/ui/traits/next-solver/alias_eq_substs_eq_not_intercrate.rs
@@ -0,0 +1,17 @@
+// compile-flags: -Znext-solver
+
+// check that a `alias-eq(<?a as TraitB>::Assoc, <?b as TraitB>::Assoc)` goal fails
+// during coherence. We must not incorrectly constrain `?a` and `?b` to be
+// equal.
+
+trait TraitB {
+ type Assoc;
+}
+
+trait Overlaps<T> {}
+
+impl<T: TraitB> Overlaps<Box<T>> for <T as TraitB>::Assoc {}
+impl<U: TraitB> Overlaps<U> for <U as TraitB>::Assoc {}
+//~^ ERROR conflicting implementations of trait
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/alias_eq_substs_eq_not_intercrate.stderr b/tests/ui/traits/next-solver/alias_eq_substs_eq_not_intercrate.stderr
new file mode 100644
index 000000000..8c6840f72
--- /dev/null
+++ b/tests/ui/traits/next-solver/alias_eq_substs_eq_not_intercrate.stderr
@@ -0,0 +1,13 @@
+error[E0119]: conflicting implementations of trait `Overlaps<Box<_>>` for type `<_ as TraitB>::Assoc`
+ --> $DIR/alias_eq_substs_eq_not_intercrate.rs:14:1
+ |
+LL | impl<T: TraitB> Overlaps<Box<T>> for <T as TraitB>::Assoc {}
+ | --------------------------------------------------------- first implementation here
+LL | impl<U: TraitB> Overlaps<U> for <U as TraitB>::Assoc {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `<_ as TraitB>::Assoc`
+ |
+ = note: downstream crates may implement trait `TraitB` for type `std::boxed::Box<_>`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/traits/next-solver/array-default.rs b/tests/ui/traits/next-solver/array-default.rs
new file mode 100644
index 000000000..6bfbce7d4
--- /dev/null
+++ b/tests/ui/traits/next-solver/array-default.rs
@@ -0,0 +1,8 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+fn has_default<const N: usize>() where [(); N]: Default {}
+
+fn main() {
+ has_default::<1>();
+}
diff --git a/tests/ui/traits/next-solver/assembly/assemble-normalizing-self-ty-impl-ambiguity.rs b/tests/ui/traits/next-solver/assembly/assemble-normalizing-self-ty-impl-ambiguity.rs
new file mode 100644
index 000000000..4401abd07
--- /dev/null
+++ b/tests/ui/traits/next-solver/assembly/assemble-normalizing-self-ty-impl-ambiguity.rs
@@ -0,0 +1,27 @@
+// compile-flags: -Znext-solver
+// 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<T> Id for T {
+ type Assoc = T;
+}
+
+fn call<T>() {
+ impls_trait::<<T as Id>::Assoc>();
+}
+
+fn main() {
+ call::<()>();
+ impls_trait::<<<() as Id>::Assoc as Id>::Assoc>();
+}
diff --git a/tests/ui/traits/next-solver/assembly/runaway-impl-candidate-selection.rs b/tests/ui/traits/next-solver/assembly/runaway-impl-candidate-selection.rs
new file mode 100644
index 000000000..1edc1a8c5
--- /dev/null
+++ b/tests/ui/traits/next-solver/assembly/runaway-impl-candidate-selection.rs
@@ -0,0 +1,15 @@
+// compile-flags: -Znext-solver
+
+// In the new solver, we are trying to select `<?0 as Iterator>::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<T: Iterator>() -> <T as Iterator>::Item {
+ todo!()
+}
+
+fn main() {
+ println!("{:?}", iter::<_>());
+ //~^ ERROR type annotations needed
+}
diff --git a/tests/ui/traits/next-solver/assembly/runaway-impl-candidate-selection.stderr b/tests/ui/traits/next-solver/assembly/runaway-impl-candidate-selection.stderr
new file mode 100644
index 000000000..4bd55ee80
--- /dev/null
+++ b/tests/ui/traits/next-solver/assembly/runaway-impl-candidate-selection.stderr
@@ -0,0 +1,16 @@
+error[E0283]: 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`
+ |
+ = note: cannot satisfy `_: Iterator`
+note: required by a bound in `iter`
+ --> $DIR/runaway-impl-candidate-selection.rs:8:12
+ |
+LL | fn iter<T: Iterator>() -> <T as Iterator>::Item {
+ | ^^^^^^^^ required by this bound in `iter`
+
+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/async.fail.stderr b/tests/ui/traits/next-solver/async.fail.stderr
new file mode 100644
index 000000000..ebd0ada26
--- /dev/null
+++ b/tests/ui/traits/next-solver/async.fail.stderr
@@ -0,0 +1,17 @@
+error[E0271]: type mismatch resolving `<{async block@$DIR/async.rs:12:17: 12:25} as Future>::Output == i32`
+ --> $DIR/async.rs:12:17
+ |
+LL | needs_async(async {});
+ | ----------- ^^^^^^^^ types differ
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `needs_async`
+ --> $DIR/async.rs:8:31
+ |
+LL | fn needs_async(_: impl Future<Output = i32>) {}
+ | ^^^^^^^^^^^^ required by this bound in `needs_async`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/traits/next-solver/async.rs b/tests/ui/traits/next-solver/async.rs
new file mode 100644
index 000000000..5833c0522
--- /dev/null
+++ b/tests/ui/traits/next-solver/async.rs
@@ -0,0 +1,19 @@
+// compile-flags: -Znext-solver
+// edition: 2021
+// revisions: pass fail
+//[pass] check-pass
+
+use std::future::Future;
+
+fn needs_async(_: impl Future<Output = i32>) {}
+
+#[cfg(fail)]
+fn main() {
+ needs_async(async {});
+ //[fail]~^ ERROR type mismatch
+}
+
+#[cfg(pass)]
+fn main() {
+ needs_async(async { 1i32 });
+}
diff --git a/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.fail.stderr b/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.fail.stderr
new file mode 100644
index 000000000..ac05dfb2d
--- /dev/null
+++ b/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.fail.stderr
@@ -0,0 +1,18 @@
+error[E0277]: `impl Future<Output = ()>` cannot be sent between threads safely
+ --> $DIR/auto-with-drop_tracking_mir.rs:25:13
+ |
+LL | is_send(foo());
+ | ------- ^^^^^ `impl Future<Output = ()>` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Send` is not implemented for `impl Future<Output = ()>`
+note: required by a bound in `is_send`
+ --> $DIR/auto-with-drop_tracking_mir.rs:24:24
+ |
+LL | fn is_send(_: impl Send) {}
+ | ^^^^ required by this bound in `is_send`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.rs b/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.rs
new file mode 100644
index 000000000..d4010a552
--- /dev/null
+++ b/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.rs
@@ -0,0 +1,27 @@
+// compile-flags: -Znext-solver
+// edition: 2021
+// revisions: pass fail
+//[pass] check-pass
+
+#![feature(negative_impls)]
+
+struct NotSync;
+impl !Sync for NotSync {}
+
+async fn foo() {
+ #[cfg(pass)]
+ let x = &();
+ #[cfg(fail)]
+ let x = &NotSync;
+ bar().await;
+ #[allow(dropping_references)]
+ drop(x);
+}
+
+async fn bar() {}
+
+fn main() {
+ fn is_send(_: impl Send) {}
+ is_send(foo());
+ //[fail]~^ ERROR `impl Future<Output = ()>` cannot be sent between threads safely
+}
diff --git a/tests/ui/traits/next-solver/borrowck-error.rs b/tests/ui/traits/next-solver/borrowck-error.rs
new file mode 100644
index 000000000..25f144594
--- /dev/null
+++ b/tests/ui/traits/next-solver/borrowck-error.rs
@@ -0,0 +1,11 @@
+// compile-flags: -Znext-solver
+
+use std::collections::HashMap;
+
+fn foo() -> &'static HashMap<i32, i32>
+{
+ &HashMap::new()
+ //~^ ERROR cannot return reference to temporary value
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/borrowck-error.stderr b/tests/ui/traits/next-solver/borrowck-error.stderr
new file mode 100644
index 000000000..4cb41e7d5
--- /dev/null
+++ b/tests/ui/traits/next-solver/borrowck-error.stderr
@@ -0,0 +1,12 @@
+error[E0515]: cannot return reference to temporary value
+ --> $DIR/borrowck-error.rs:7:5
+ |
+LL | &HashMap::new()
+ | ^--------------
+ | ||
+ | |temporary value created here
+ | returns a reference to data owned by the current function
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/tests/ui/traits/next-solver/builtin-fn-must-return-sized.rs b/tests/ui/traits/next-solver/builtin-fn-must-return-sized.rs
new file mode 100644
index 000000000..eab25214d
--- /dev/null
+++ b/tests/ui/traits/next-solver/builtin-fn-must-return-sized.rs
@@ -0,0 +1,17 @@
+// compile-flags: -Znext-solver
+
+#![feature(fn_traits)]
+#![feature(unboxed_closures)]
+#![feature(tuple_trait)]
+
+use std::ops::Fn;
+use std::marker::Tuple;
+
+fn foo<F: Fn<T>, T: Tuple>(f: Option<F>, t: T) {
+ let y = (f.unwrap()).call(t);
+}
+
+fn main() {
+ foo::<fn() -> str, _>(None, ());
+ //~^ expected a `Fn<_>` closure, found `fn() -> str`
+}
diff --git a/tests/ui/traits/next-solver/builtin-fn-must-return-sized.stderr b/tests/ui/traits/next-solver/builtin-fn-must-return-sized.stderr
new file mode 100644
index 000000000..08047852f
--- /dev/null
+++ b/tests/ui/traits/next-solver/builtin-fn-must-return-sized.stderr
@@ -0,0 +1,16 @@
+error[E0277]: expected a `Fn<_>` closure, found `fn() -> str`
+ --> $DIR/builtin-fn-must-return-sized.rs:15:11
+ |
+LL | foo::<fn() -> str, _>(None, ());
+ | ^^^^^^^^^^^ expected an `Fn<_>` closure, found `fn() -> str`
+ |
+ = help: the trait `Fn<_>` is not implemented for `fn() -> str`
+note: required by a bound in `foo`
+ --> $DIR/builtin-fn-must-return-sized.rs:10:11
+ |
+LL | fn foo<F: Fn<T>, T: Tuple>(f: Option<F>, t: T) {
+ | ^^^^^ required by this bound in `foo`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/next-solver/canonical-int-var-eq-in-response.rs b/tests/ui/traits/next-solver/canonical-int-var-eq-in-response.rs
new file mode 100644
index 000000000..ea2740523
--- /dev/null
+++ b/tests/ui/traits/next-solver/canonical-int-var-eq-in-response.rs
@@ -0,0 +1,22 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+trait Mirror {
+ type Assoc;
+}
+
+impl<T> Mirror for T {
+ type Assoc = T;
+}
+
+trait Test {}
+impl Test for i64 {}
+impl Test for u64 {}
+
+fn mirror_me<T: Mirror>(t: T, s: <T as Mirror>::Assoc) where <T as Mirror>::Assoc: Test {}
+
+fn main() {
+ let mut x = 0;
+ mirror_me(x, 1);
+ x = 1i64;
+}
diff --git a/tests/ui/traits/next-solver/canonical-ty-var-eq-in-response.rs b/tests/ui/traits/next-solver/canonical-ty-var-eq-in-response.rs
new file mode 100644
index 000000000..b1e4a9e58
--- /dev/null
+++ b/tests/ui/traits/next-solver/canonical-ty-var-eq-in-response.rs
@@ -0,0 +1,39 @@
+// check-pass
+// compile-flags: -Znext-solver
+
+trait Mirror {
+ type Item;
+}
+
+struct Wrapper<T>(T);
+impl<T> Mirror for Wrapper<T> {
+ type Item = T;
+}
+
+fn mirror<T>()
+where
+ Wrapper<T>: Mirror<Item = i32>,
+{
+}
+
+fn main() {
+ mirror::<_ /* ?0 */>();
+
+ // Solving `<Wrapper<?0> as Mirror>::Item = i32`
+
+ // First, we replace the term with a fresh infer var:
+ // `<Wrapper<?0> as Mirror>::Item = ?1`
+
+ // We select the impl candidate on line #6, which leads us to learn that
+ // `?0 == ?1`.
+
+ // That should be reflected in our canonical response, which should have
+ // `^0 = ^0, ^1 = ^0`
+ // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ // !! We used to return a totally unconstrained response here :< !!
+ // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+ // Then, during the "equate term" part of the projection solving, we
+ // instantiate the response from the unconstrained projection predicate,
+ // and equate `?0 == i32`.
+}
diff --git a/tests/ui/traits/next-solver/canonicalize-effect-var.rs b/tests/ui/traits/next-solver/canonicalize-effect-var.rs
new file mode 100644
index 000000000..4a13ba373
--- /dev/null
+++ b/tests/ui/traits/next-solver/canonicalize-effect-var.rs
@@ -0,0 +1,22 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+#![feature(effects)]
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Foo {
+ fn foo();
+}
+
+trait Bar {}
+
+impl const Foo for i32 {
+ fn foo() {}
+}
+
+impl<T> const Foo for T where T: Bar {
+ fn foo() {}
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/cast-checks-handling-projections.rs b/tests/ui/traits/next-solver/cast-checks-handling-projections.rs
new file mode 100644
index 000000000..406b4dc12
--- /dev/null
+++ b/tests/ui/traits/next-solver/cast-checks-handling-projections.rs
@@ -0,0 +1,6 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+fn main() {
+ (0u8 + 0u8) as char;
+}
diff --git a/tests/ui/traits/next-solver/closure-inference-guidance.rs b/tests/ui/traits/next-solver/closure-inference-guidance.rs
new file mode 100644
index 000000000..8175b92f8
--- /dev/null
+++ b/tests/ui/traits/next-solver/closure-inference-guidance.rs
@@ -0,0 +1,11 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+fn foo(i: isize) -> isize { i + 1 }
+
+fn apply<A, F>(f: F, v: A) -> A where F: FnOnce(A) -> A { f(v) }
+
+pub fn main() {
+ let f = |i| foo(i);
+ assert_eq!(apply(f, 2), 3);
+}
diff --git a/tests/ui/traits/next-solver/closure-signature-inference-2.rs b/tests/ui/traits/next-solver/closure-signature-inference-2.rs
new file mode 100644
index 000000000..8fece7ba9
--- /dev/null
+++ b/tests/ui/traits/next-solver/closure-signature-inference-2.rs
@@ -0,0 +1,21 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+fn map<T: Default, U, F: FnOnce(T) -> U>(f: F) {
+ f(T::default());
+}
+
+fn main() {
+ map::<i32, _ /* ?U */, _ /* ?F */>(|x| x.to_string());
+ // PREVIOUSLY when confirming the `map` call, we register:
+ //
+ // (1.) ?F: FnOnce<(i32,)>
+ // (2.) <?F as FnOnce<(i32,)>>::Output projects-to ?U
+ //
+ // While (1.) is ambiguous, (2.) immediately gets processed
+ // and we infer `?U := <?F as FnOnce<(i32,)>>::Output`.
+ //
+ // Thus, the only pending obligation that remains is (1.).
+ // Since it is a trait obligation, we don't use it to deduce
+ // the closure signature, and we fail!
+}
diff --git a/tests/ui/traits/next-solver/closure-signature-inference.rs b/tests/ui/traits/next-solver/closure-signature-inference.rs
new file mode 100644
index 000000000..355fc7902
--- /dev/null
+++ b/tests/ui/traits/next-solver/closure-signature-inference.rs
@@ -0,0 +1,15 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+struct A;
+impl A {
+ fn hi(self) {}
+}
+
+fn hello() -> Result<(A,), ()> {
+ Err(())
+}
+
+fn main() {
+ let x = hello().map(|(x,)| x.hi());
+}
diff --git a/tests/ui/traits/next-solver/closure-substs-ambiguity.rs b/tests/ui/traits/next-solver/closure-substs-ambiguity.rs
new file mode 100644
index 000000000..cc9ee58f2
--- /dev/null
+++ b/tests/ui/traits/next-solver/closure-substs-ambiguity.rs
@@ -0,0 +1,7 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+fn main() {
+ let mut x: Vec<_> = vec![];
+ x.extend(Some(1i32).into_iter().map(|x| x));
+}
diff --git a/tests/ui/traits/next-solver/coerce-ambig-alias-to-rigid-alias.rs b/tests/ui/traits/next-solver/coerce-ambig-alias-to-rigid-alias.rs
new file mode 100644
index 000000000..bcb48b5ac
--- /dev/null
+++ b/tests/ui/traits/next-solver/coerce-ambig-alias-to-rigid-alias.rs
@@ -0,0 +1,15 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+trait Trait {
+ type Assoc;
+}
+
+fn call<T: Trait>(_: <T as Trait>::Assoc, _: T) {}
+
+fn foo<T: Trait>(rigid: <T as Trait>::Assoc, t: T) {
+ // Check that we can coerce `<?0 as Trait>::Assoc` to `<T as Trait>::Assoc`.
+ call::<_ /* ?0 */>(rigid, t);
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/coherence/issue-102048.rs b/tests/ui/traits/next-solver/coherence/issue-102048.rs
new file mode 100644
index 000000000..600e63d4d
--- /dev/null
+++ b/tests/ui/traits/next-solver/coherence/issue-102048.rs
@@ -0,0 +1,44 @@
+// This must fail coherence.
+//
+// Getting this to pass was fairly difficult, so here's an explanation
+// of what's happening:
+//
+// Normalizing projections currently tries to replace them with inference variables
+// while emitting a nested `Projection` obligation. This cannot be done if the projection
+// has bound variables which is the case here.
+//
+// So the projections stay until after normalization. When unifying two projections we
+// currently treat them as if they are injective, so we **incorrectly** unify their
+// substs. This means that coherence for the two impls ends up unifying `?T` and `?U`
+// as it tries to unify `<?T as WithAssoc1<'a>>::Assoc` with `<?U as WithAssoc1<'a>>::Assoc`.
+//
+// `impl1` therefore has the projection `<?T as WithAssoc2<'a>>::Assoc` and we have the
+// assumption `?T: for<'a> WithAssoc2<'a, Assoc = i32>` in the `param_env`, so we normalize
+// that to `i32`. We then try to unify `i32` from `impl1` with `u32` from `impl2` which fails,
+// causing coherence to consider these two impls distinct.
+
+// compile-flags: -Znext-solver
+pub trait Trait<T> {}
+
+pub trait WithAssoc1<'a> {
+ type Assoc;
+}
+pub trait WithAssoc2<'a> {
+ type Assoc;
+}
+
+// impl 1
+impl<T, U> Trait<for<'a> fn(<T as WithAssoc1<'a>>::Assoc, <U as WithAssoc2<'a>>::Assoc)> for (T, U)
+where
+ T: for<'a> WithAssoc1<'a> + for<'a> WithAssoc2<'a, Assoc = i32>,
+ U: for<'a> WithAssoc2<'a>,
+{
+}
+
+// impl 2
+impl<T, U> Trait<for<'a> fn(<U as WithAssoc1<'a>>::Assoc, u32)> for (T, U) where
+ U: for<'a> WithAssoc1<'a> //~^ ERROR conflicting implementations of trait
+{
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/coherence/issue-102048.stderr b/tests/ui/traits/next-solver/coherence/issue-102048.stderr
new file mode 100644
index 000000000..4e93ae284
--- /dev/null
+++ b/tests/ui/traits/next-solver/coherence/issue-102048.stderr
@@ -0,0 +1,16 @@
+error[E0119]: conflicting implementations of trait `Trait<for<'a> fn(<_ as WithAssoc1<'a>>::Assoc, <_ as WithAssoc2<'a>>::Assoc)>` for type `(_, _)`
+ --> $DIR/issue-102048.rs:39:1
+ |
+LL | / impl<T, U> Trait<for<'a> fn(<T as WithAssoc1<'a>>::Assoc, <U as WithAssoc2<'a>>::Assoc)> for (T, U)
+LL | | where
+LL | | T: for<'a> WithAssoc1<'a> + for<'a> WithAssoc2<'a, Assoc = i32>,
+LL | | U: for<'a> WithAssoc2<'a>,
+ | |______________________________- first implementation here
+...
+LL | / impl<T, U> Trait<for<'a> fn(<U as WithAssoc1<'a>>::Assoc, u32)> for (T, U) where
+LL | | U: for<'a> WithAssoc1<'a>
+ | |_____________________________^ conflicting implementation for `(_, _)`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.rs b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.rs
new file mode 100644
index 000000000..af471b5e1
--- /dev/null
+++ b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.rs
@@ -0,0 +1,20 @@
+// compile-flags: -Znext-solver
+
+// Coherence should handle overflow while normalizing for
+// `trait_ref_is_knowable` correctly.
+
+trait Overflow {
+ type Assoc;
+}
+impl<T> Overflow for T {
+ type Assoc = <T as Overflow>::Assoc;
+}
+
+
+trait Trait {}
+impl<T: Copy> Trait for T {}
+struct LocalTy;
+impl Trait for <LocalTy as Overflow>::Assoc {}
+//~^ ERROR conflicting implementations of trait `Trait` for type `<LocalTy as Overflow>::Assoc`
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr
new file mode 100644
index 000000000..e3c0dabf5
--- /dev/null
+++ b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `Trait` for type `<LocalTy as Overflow>::Assoc`
+ --> $DIR/trait_ref_is_knowable-norm-overflow.rs:17:1
+ |
+LL | impl<T: Copy> Trait for T {}
+ | ------------------------- first implementation here
+LL | struct LocalTy;
+LL | impl Trait for <LocalTy as Overflow>::Assoc {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `<LocalTy as Overflow>::Assoc`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-normalization-1.rs b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-normalization-1.rs
new file mode 100644
index 000000000..e6ffb55b4
--- /dev/null
+++ b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-normalization-1.rs
@@ -0,0 +1,22 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+trait Id {
+ type Assoc;
+}
+impl<T> Id for T {
+ type Assoc = T;
+}
+
+
+// Coherence should be able to reason that `<LocalTy as Id>::Assoc: Copy`
+// does not hold.
+//
+// See https://github.com/rust-lang/trait-system-refactor-initiative/issues/51
+// for more details.
+trait Trait {}
+impl<T: Copy> Trait for T {}
+struct LocalTy;
+impl Trait for <LocalTy as Id>::Assoc {}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-normalization-2.rs b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-normalization-2.rs
new file mode 100644
index 000000000..d16f9d22c
--- /dev/null
+++ b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-normalization-2.rs
@@ -0,0 +1,25 @@
+// compile-flags: -Znext-solver
+// 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<P> Future for Pin<P> where P: DerefMut, <P as Deref>::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<Box<dyn Future<Output = ()> + Send>>;
+
+ fn into_future(self) -> Self::IntoFuture {
+ todo!()
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-normalization-3.rs b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-normalization-3.rs
new file mode 100644
index 000000000..90de6b847
--- /dev/null
+++ b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-normalization-3.rs
@@ -0,0 +1,24 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+trait Id {
+ type Assoc;
+}
+impl<T> Id for T {
+ type Assoc = T;
+}
+
+
+// Coherence should be able to reason that `(): PartialEq<<T as Id>::Assoc>>`
+// does not hold.
+//
+// See https://github.com/rust-lang/trait-system-refactor-initiative/issues/51
+// for more details.
+trait Trait {}
+impl<T> Trait for T
+where
+ (): PartialEq<T> {}
+struct LocalTy;
+impl Trait for <LocalTy as Id>::Assoc {}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/const-param-placeholder.fail.stderr b/tests/ui/traits/next-solver/const-param-placeholder.fail.stderr
new file mode 100644
index 000000000..163710706
--- /dev/null
+++ b/tests/ui/traits/next-solver/const-param-placeholder.fail.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `[T; N]: Foo` is not satisfied
+ --> $DIR/const-param-placeholder.rs:17:17
+ |
+LL | needs_foo::<[T; N]>();
+ | ^^^^^^ the trait `Foo` is not implemented for `[T; N]`
+ |
+ = help: the trait `Foo` is implemented for `[T; 1]`
+note: required by a bound in `needs_foo`
+ --> $DIR/const-param-placeholder.rs:8:17
+ |
+LL | fn needs_foo<F: Foo>() {}
+ | ^^^ required by this bound in `needs_foo`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/next-solver/const-param-placeholder.rs b/tests/ui/traits/next-solver/const-param-placeholder.rs
new file mode 100644
index 000000000..c22bc54cf
--- /dev/null
+++ b/tests/ui/traits/next-solver/const-param-placeholder.rs
@@ -0,0 +1,21 @@
+// compile-flags: -Znext-solver
+// revisions: pass fail
+//[pass] check-pass
+
+struct Wrapper<T, const N: usize>([T; N]);
+
+trait Foo {}
+fn needs_foo<F: Foo>() {}
+
+#[cfg(fail)]
+impl<T> Foo for [T; 1] {}
+
+#[cfg(pass)]
+impl<T, const N: usize> Foo for [T; N] {}
+
+fn test<T, const N: usize>() {
+ needs_foo::<[T; N]>();
+ //[fail]~^ ERROR the trait bound `[T; N]: Foo` is not satisfied
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/coroutine.fail.stderr b/tests/ui/traits/next-solver/coroutine.fail.stderr
new file mode 100644
index 000000000..14e67727d
--- /dev/null
+++ b/tests/ui/traits/next-solver/coroutine.fail.stderr
@@ -0,0 +1,64 @@
+error[E0277]: the trait bound `{coroutine@$DIR/coroutine.rs:18:21: 18:23}: Coroutine<A>` is not satisfied
+ --> $DIR/coroutine.rs:18:21
+ |
+LL | needs_coroutine(|| {
+ | _____---------------_^
+ | | |
+ | | required by a bound introduced by this call
+LL | |
+LL | |
+LL | |
+LL | | yield ();
+LL | | });
+ | |_____^ the trait `Coroutine<A>` is not implemented for `{coroutine@$DIR/coroutine.rs:18:21: 18:23}`
+ |
+note: required by a bound in `needs_coroutine`
+ --> $DIR/coroutine.rs:14:28
+ |
+LL | fn needs_coroutine(_: impl Coroutine<A, Yield = B, Return = C>) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `needs_coroutine`
+
+error[E0271]: type mismatch resolving `<{coroutine@$DIR/coroutine.rs:18:21: 18:23} as Coroutine<A>>::Yield == B`
+ --> $DIR/coroutine.rs:18:21
+ |
+LL | needs_coroutine(|| {
+ | _____---------------_^
+ | | |
+ | | required by a bound introduced by this call
+LL | |
+LL | |
+LL | |
+LL | | yield ();
+LL | | });
+ | |_____^ types differ
+ |
+note: required by a bound in `needs_coroutine`
+ --> $DIR/coroutine.rs:14:41
+ |
+LL | fn needs_coroutine(_: impl Coroutine<A, Yield = B, Return = C>) {}
+ | ^^^^^^^^^ required by this bound in `needs_coroutine`
+
+error[E0271]: type mismatch resolving `<{coroutine@$DIR/coroutine.rs:18:21: 18:23} as Coroutine<A>>::Return == C`
+ --> $DIR/coroutine.rs:18:21
+ |
+LL | needs_coroutine(|| {
+ | _____---------------_^
+ | | |
+ | | required by a bound introduced by this call
+LL | |
+LL | |
+LL | |
+LL | | yield ();
+LL | | });
+ | |_____^ types differ
+ |
+note: required by a bound in `needs_coroutine`
+ --> $DIR/coroutine.rs:14:52
+ |
+LL | fn needs_coroutine(_: impl Coroutine<A, Yield = B, Return = C>) {}
+ | ^^^^^^^^^^ required by this bound in `needs_coroutine`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0271, E0277.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/tests/ui/traits/next-solver/coroutine.rs b/tests/ui/traits/next-solver/coroutine.rs
new file mode 100644
index 000000000..727e23568
--- /dev/null
+++ b/tests/ui/traits/next-solver/coroutine.rs
@@ -0,0 +1,32 @@
+// compile-flags: -Znext-solver
+// edition: 2021
+// revisions: pass fail
+//[pass] check-pass
+
+#![feature(coroutine_trait, coroutines)]
+
+use std::ops::Coroutine;
+
+struct A;
+struct B;
+struct C;
+
+fn needs_coroutine(_: impl Coroutine<A, Yield = B, Return = C>) {}
+
+#[cfg(fail)]
+fn main() {
+ needs_coroutine(|| {
+ //[fail]~^ ERROR Coroutine<A>` is not satisfied
+ //[fail]~| ERROR as Coroutine<A>>::Yield == B`
+ //[fail]~| ERROR as Coroutine<A>>::Return == C`
+ yield ();
+ });
+}
+
+#[cfg(pass)]
+fn main() {
+ needs_coroutine(|_: A| {
+ let _: A = yield B;
+ C
+ })
+}
diff --git a/tests/ui/traits/next-solver/cycles/coinduction/fixpoint-exponential-growth.rs b/tests/ui/traits/next-solver/cycles/coinduction/fixpoint-exponential-growth.rs
new file mode 100644
index 000000000..947b52da7
--- /dev/null
+++ b/tests/ui/traits/next-solver/cycles/coinduction/fixpoint-exponential-growth.rs
@@ -0,0 +1,35 @@
+// compile-flags: -Znext-solver
+
+// Proving `W<?0>: Trait` instantiates `?0` with `(W<?1>, W<?2>)` and then
+// proves `W<?1>: Trait` and `W<?2>: Trait`, resulting in a coinductive cycle.
+//
+// Proving coinductive cycles runs until we reach a fixpoint. However, after
+// computing `try_evaluate_added_goals` in the second fixpoint iteration, the
+// self type already has a depth equal to the number of steps. This results
+// in enormous constraints, causing the canonicalizer to hang without ever
+// reaching the recursion limit. We currently avoid that by erasing the constraints
+// from overflow.
+//
+// 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>(T);
+
+impl<T, U> Trait for W<(W<T>, W<U>)>
+where
+ W<T>: Trait,
+ W<U>: Trait,
+{
+}
+
+fn impls<T: Trait>() {}
+
+fn main() {
+ impls::<W<_>>();
+ //~^ ERROR overflow evaluating the requirement
+}
diff --git a/tests/ui/traits/next-solver/cycles/coinduction/fixpoint-exponential-growth.stderr b/tests/ui/traits/next-solver/cycles/coinduction/fixpoint-exponential-growth.stderr
new file mode 100644
index 000000000..150100f2c
--- /dev/null
+++ b/tests/ui/traits/next-solver/cycles/coinduction/fixpoint-exponential-growth.stderr
@@ -0,0 +1,16 @@
+error[E0275]: overflow evaluating the requirement `W<_>: Trait`
+ --> $DIR/fixpoint-exponential-growth.rs:33:13
+ |
+LL | impls::<W<_>>();
+ | ^^^^
+ |
+ = 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:30:13
+ |
+LL | fn impls<T: Trait>() {}
+ | ^^^^^ required by this bound in `impls`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.rs b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.rs
new file mode 100644
index 000000000..a3c07b987
--- /dev/null
+++ b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.rs
@@ -0,0 +1,69 @@
+// compile-flags: -Znext-solver
+#![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<T>` impl and required
+// inference from an `Impl` candidate in the `B<T>` impl.
+//
+// To make global cache accesses stronger than the guidance from the where-bounds, we add
+// another coinductive cycle from `A<T>: Trait<U, V, D>` to `A<T>: Trait<U, D, V>` 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<T: ?Sized, V: ?Sized, D: ?Sized> {}
+struct A<T: ?Sized>(*const T);
+struct B<T: ?Sized>(*const T);
+
+trait IncompleteGuidance<T: ?Sized, V: ?Sized> {}
+impl<T: ?Sized, U: ?Sized + 'static> IncompleteGuidance<U, u8> for T {}
+impl<T: ?Sized, U: ?Sized + 'static> IncompleteGuidance<U, i8> for T {}
+impl<T: ?Sized, U: ?Sized + 'static> IncompleteGuidance<U, i16> for T {}
+
+trait ImplGuidance<T: ?Sized, V: ?Sized> {}
+impl<T: ?Sized> ImplGuidance<u32, u8> for T {}
+impl<T: ?Sized> ImplGuidance<i32, i8> for T {}
+
+impl<T: ?Sized, U: ?Sized, V: ?Sized, D: ?Sized> Trait<U, V, D> for A<T>
+where
+ T: IncompleteGuidance<U, V>,
+ A<T>: Trait<U, D, V>,
+ B<T>: Trait<U, V, D>,
+ (): ToU8<D>,
+{
+}
+
+trait ToU8<T: ?Sized> {}
+impl ToU8<u8> for () {}
+
+impl<T: ?Sized, U: ?Sized, V: ?Sized, D: ?Sized> Trait<U, V, D> for B<T>
+where
+ T: ImplGuidance<U, V>,
+ A<T>: Trait<U, V, D>,
+{
+}
+
+fn impls_trait<T: ?Sized + Trait<U, V, D>, U: ?Sized, V: ?Sized, D: ?Sized>() {}
+
+fn with_bound<X>()
+where
+ X: IncompleteGuidance<i32, u8>,
+ X: IncompleteGuidance<u32, i8>,
+ X: IncompleteGuidance<u32, i16>,
+{
+ impls_trait::<B<X>, _, _, _>(); // 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<X>`.
+ impls_trait::<A<X>, _, _, _>();
+ //~^ ERROR the trait bound `A<X>: Trait<_, _, _>` is not satisfied
+}
+
+fn main() {
+ with_bound::<u32>();
+}
diff --git a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.stderr b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.stderr
new file mode 100644
index 000000000..d49321917
--- /dev/null
+++ b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `A<X>: Trait<_, _, _>` is not satisfied
+ --> $DIR/incompleteness-unstable-result.rs:63:19
+ |
+LL | impls_trait::<A<X>, _, _, _>();
+ | ^^^^ the trait `Trait<_, _, _>` is not implemented for `A<X>`
+ |
+ = help: the trait `Trait<U, V, D>` is implemented for `A<T>`
+note: required by a bound in `impls_trait`
+ --> $DIR/incompleteness-unstable-result.rs:51:28
+ |
+LL | fn impls_trait<T: ?Sized + Trait<U, V, D>, U: ?Sized, V: ?Sized, D: ?Sized>() {}
+ | ^^^^^^^^^^^^^^ required by this bound in `impls_trait`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/next-solver/cycles/double-cycle-inductive-coinductive.rs b/tests/ui/traits/next-solver/cycles/double-cycle-inductive-coinductive.rs
new file mode 100644
index 000000000..0f19bc2c5
--- /dev/null
+++ b/tests/ui/traits/next-solver/cycles/double-cycle-inductive-coinductive.rs
@@ -0,0 +1,37 @@
+// compile-flags: -Znext-solver
+#![feature(rustc_attrs)]
+
+// Test that having both an inductive and a coinductive cycle
+// is handled correctly.
+
+#[rustc_coinductive]
+trait Trait {}
+impl<T: Inductive + Coinductive> Trait for T {}
+
+trait Inductive {}
+impl<T: Trait> Inductive for T {}
+#[rustc_coinductive]
+trait Coinductive {}
+impl<T: Trait> Coinductive for T {}
+
+fn impls_trait<T: Trait>() {}
+
+#[rustc_coinductive]
+trait TraitRev {}
+impl<T: CoinductiveRev + InductiveRev> TraitRev for T {}
+
+trait InductiveRev {}
+impl<T: TraitRev> InductiveRev for T {}
+#[rustc_coinductive]
+trait CoinductiveRev {}
+impl<T: TraitRev> CoinductiveRev for T {}
+
+fn impls_trait_rev<T: TraitRev>() {}
+
+fn main() {
+ impls_trait::<()>();
+ //~^ ERROR overflow evaluating the requirement
+
+ impls_trait_rev::<()>();
+ //~^ ERROR overflow evaluating the requirement
+}
diff --git a/tests/ui/traits/next-solver/cycles/double-cycle-inductive-coinductive.stderr b/tests/ui/traits/next-solver/cycles/double-cycle-inductive-coinductive.stderr
new file mode 100644
index 000000000..a3404da51
--- /dev/null
+++ b/tests/ui/traits/next-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:19
+ |
+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<T: Trait>() {}
+ | ^^^^^ required by this bound in `impls_trait`
+
+error[E0275]: overflow evaluating the requirement `(): TraitRev`
+ --> $DIR/double-cycle-inductive-coinductive.rs:35:23
+ |
+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<T: TraitRev>() {}
+ | ^^^^^^^^ 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/next-solver/cycles/fixpoint-rerun-all-cycle-heads.rs b/tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.rs
new file mode 100644
index 000000000..c7e2e2d5e
--- /dev/null
+++ b/tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.rs
@@ -0,0 +1,53 @@
+// compile-flags: -Znext-solver
+#![feature(rustc_attrs)]
+
+// Check that we correctly rerun the trait solver for heads of cycles,
+// even if they are not the root.
+
+struct A<T: ?Sized>(*const T);
+struct B<T: ?Sized>(*const T);
+struct C<T: ?Sized>(*const T);
+
+#[rustc_coinductive]
+trait Trait<'a, 'b> {}
+trait NotImplemented {}
+
+impl<'a, 'b, T: ?Sized> Trait<'a, 'b> for A<T> where B<T>: Trait<'a, 'b> {}
+
+// With this the root of `B<T>` is `A<T>`, even if the other impl does
+// not have a cycle with `A<T>`. This candidate never applies because of
+// the `A<T>: NotImplemented` bound.
+impl<'a, 'b, T: ?Sized> Trait<'a, 'b> for B<T>
+where
+ A<T>: Trait<'a, 'b>,
+ A<T>: NotImplemented,
+{
+}
+
+// This impl directly requires 'b to be equal to 'static.
+//
+// Because of the coinductive cycle through `C<T>` it also requires
+// 'a to be 'static.
+impl<'a, T: ?Sized> Trait<'a, 'static> for B<T>
+where
+ C<T>: Trait<'a, 'a>,
+{}
+
+// In the first iteration of `B<T>: Trait<'a, 'b>` we don't add any
+// constraints here, only after setting the provisional result to require
+// `'b == 'static` do we also add that constraint for `'a`.
+impl<'a, 'b, T: ?Sized> Trait<'a, 'b> for C<T>
+where
+ B<T>: Trait<'a, 'b>,
+{}
+
+fn impls_trait<'a, 'b, T: Trait<'a, 'b> + ?Sized>() {}
+
+fn check<'a, T: ?Sized>() {
+ impls_trait::<'a, 'static, A<T>>();
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {
+ check::<()>();
+}
diff --git a/tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.stderr b/tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.stderr
new file mode 100644
index 000000000..7b3075f4f
--- /dev/null
+++ b/tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.stderr
@@ -0,0 +1,10 @@
+error: lifetime may not live long enough
+ --> $DIR/fixpoint-rerun-all-cycle-heads.rs:47:5
+ |
+LL | fn check<'a, T: ?Sized>() {
+ | -- lifetime `'a` defined here
+LL | impls_trait::<'a, 'static, A<T>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/traits/next-solver/cycles/inductive-cycle-but-err.rs b/tests/ui/traits/next-solver/cycles/inductive-cycle-but-err.rs
new file mode 100644
index 000000000..fdc7afea3
--- /dev/null
+++ b/tests/ui/traits/next-solver/cycles/inductive-cycle-but-err.rs
@@ -0,0 +1,48 @@
+// compile-flags: -Znext-solver
+#![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<T: Trait>() {}
+
+fn main() {
+ impls_trait::<MultipleCandidates>();
+ //~^ ERROR the trait bound `MultipleCandidates: Trait` is not satisfied
+}
diff --git a/tests/ui/traits/next-solver/cycles/inductive-cycle-but-err.stderr b/tests/ui/traits/next-solver/cycles/inductive-cycle-but-err.stderr
new file mode 100644
index 000000000..acacaf6a3
--- /dev/null
+++ b/tests/ui/traits/next-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::<MultipleCandidates>();
+ | ^^^^^^^^^^^^^^^^^^ 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<T: Trait>() {}
+ | ^^^^^ required by this bound in `impls_trait`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/next-solver/cycles/inductive-cycle-but-ok.rs b/tests/ui/traits/next-solver/cycles/inductive-cycle-but-ok.rs
new file mode 100644
index 000000000..d6d9762bb
--- /dev/null
+++ b/tests/ui/traits/next-solver/cycles/inductive-cycle-but-ok.rs
@@ -0,0 +1,44 @@
+// compile-flags: -Znext-solver
+// 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<T: Trait>() {}
+
+fn main() {
+ impls_trait::<Root>();
+}
diff --git a/tests/ui/traits/next-solver/cycles/inductive-cycle-discarded-coinductive-constraints.rs b/tests/ui/traits/next-solver/cycles/inductive-cycle-discarded-coinductive-constraints.rs
new file mode 100644
index 000000000..a32f7a13a
--- /dev/null
+++ b/tests/ui/traits/next-solver/cycles/inductive-cycle-discarded-coinductive-constraints.rs
@@ -0,0 +1,36 @@
+// check-pass
+// compile-flags: -Znext-solver
+#![feature(rustc_attrs, marker_trait_attr)]
+#[rustc_coinductive]
+trait Trait {}
+
+impl<T, U> Trait for (T, U)
+where
+ (U, T): Trait,
+ (T, U): Inductive,
+ (): ConstrainToU32<T>,
+{}
+
+trait ConstrainToU32<T> {}
+impl ConstrainToU32<u32> 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<T, U> Inductive for (T, U)
+where
+ (T, U): Trait,
+{}
+
+impl Inductive for (u32, u32) {}
+
+fn impls_trait<T, U>()
+where
+ (T, U): Trait,
+{}
+
+fn main() {
+ impls_trait::<_, _>();
+}
diff --git a/tests/ui/traits/next-solver/cycles/inductive-fixpoint-hang.rs b/tests/ui/traits/next-solver/cycles/inductive-fixpoint-hang.rs
new file mode 100644
index 000000000..efeb8d023
--- /dev/null
+++ b/tests/ui/traits/next-solver/cycles/inductive-fixpoint-hang.rs
@@ -0,0 +1,33 @@
+// compile-flags: -Znext-solver
+
+// This currently hangs if we do not erase constraints from
+// overflow.
+//
+// We set the provisional result of `W<?0>` to `?0 := W<_>`.
+// The next iteration does not simply result in a `?0 := W<W<_>` constraint as
+// one might expect, but instead each time we evaluate the nested `W<T>` goal we
+// apply the previously returned constraints: the first fixpoint iteration goes
+// as follows: `W<?1>: Trait` constrains `?1` to `W<?2>`, we then evaluate
+// `W<W<?2>>: Trait` the next time we try to prove the nested goal. This results
+// inn `W<W<W<?3>>>` and so on. This goes on until we reach overflow in
+// `try_evaluate_added_goals`. This means the provisional result after the
+// second fixpoint iteration is already `W<W<W<...>>>` with a size proportional
+// to the number of steps in `try_evaluate_added_goals`. The size then continues
+// to grow. The exponential blowup from having 2 nested goals per impl causes
+// the solver to hang without hitting the recursion limit.
+trait Trait {}
+
+struct W<T: ?Sized>(*const T);
+
+impl<T: ?Sized> Trait for W<W<T>>
+where
+ W<T>: Trait,
+ W<T>: Trait,
+{}
+
+fn impls_trait<T: Trait>() {}
+
+fn main() {
+ impls_trait::<W<_>>();
+ //~^ ERROR overflow evaluating the requirement
+}
diff --git a/tests/ui/traits/next-solver/cycles/inductive-fixpoint-hang.stderr b/tests/ui/traits/next-solver/cycles/inductive-fixpoint-hang.stderr
new file mode 100644
index 000000000..424519207
--- /dev/null
+++ b/tests/ui/traits/next-solver/cycles/inductive-fixpoint-hang.stderr
@@ -0,0 +1,16 @@
+error[E0275]: overflow evaluating the requirement `W<_>: Trait`
+ --> $DIR/inductive-fixpoint-hang.rs:31:19
+ |
+LL | impls_trait::<W<_>>();
+ | ^^^^
+ |
+ = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`inductive_fixpoint_hang`)
+note: required by a bound in `impls_trait`
+ --> $DIR/inductive-fixpoint-hang.rs:28:19
+ |
+LL | fn impls_trait<T: Trait>() {}
+ | ^^^^^ required by this bound in `impls_trait`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.rs b/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.rs
new file mode 100644
index 000000000..f2f6e009d
--- /dev/null
+++ b/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.rs
@@ -0,0 +1,46 @@
+// compile-flags: -Znext-solver
+#![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<T: B + C> A for T {}
+impl<T: A> B for T {}
+impl<T: B> C for T {}
+
+fn impls_a<T: 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<T: CR + BR> AR for T {}
+impl<T: AR> BR for T {}
+impl<T: BR> CR for T {}
+
+fn impls_ar<T: AR>() {}
+
+fn main() {
+ impls_a::<()>();
+ //~^ ERROR overflow evaluating the requirement `(): A`
+
+ impls_ar::<()>();
+ //~^ ERROR overflow evaluating the requirement `(): AR`
+}
diff --git a/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.stderr b/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.stderr
new file mode 100644
index 000000000..859b3f3f1
--- /dev/null
+++ b/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.stderr
@@ -0,0 +1,29 @@
+error[E0275]: overflow evaluating the requirement `(): A`
+ --> $DIR/inductive-not-on-stack.rs:41:15
+ |
+LL | impls_a::<()>();
+ | ^^
+ |
+ = 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_a`
+ --> $DIR/inductive-not-on-stack.rs:25:15
+ |
+LL | fn impls_a<T: A>() {}
+ | ^ required by this bound in `impls_a`
+
+error[E0275]: overflow evaluating the requirement `(): AR`
+ --> $DIR/inductive-not-on-stack.rs:44:16
+ |
+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<T: AR>() {}
+ | ^^ required by this bound in `impls_ar`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/next-solver/cycles/leak-check-coinductive-cycle.rs b/tests/ui/traits/next-solver/cycles/leak-check-coinductive-cycle.rs
new file mode 100644
index 000000000..9ff362ec8
--- /dev/null
+++ b/tests/ui/traits/next-solver/cycles/leak-check-coinductive-cycle.rs
@@ -0,0 +1,33 @@
+// compile-flags: -Znext-solver
+// check-pass
+#![feature(rustc_attrs)]
+
+#[rustc_coinductive]
+trait Trait<T> {}
+impl<'a, 'b, T> Trait<T> for (&'a (), &'b ())
+where
+ 'b: 'a,
+ &'a (): Trait<T>,
+{}
+
+impl Trait<i32> for &'static () {}
+impl<'a> Trait<u32> for &'a ()
+where
+ for<'b> (&'a (), &'b ()): Trait<u32>,
+{}
+
+
+fn impls_trait<T: Trait<U>, 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<u32> 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/next-solver/cycles/provisional-result-done.rs b/tests/ui/traits/next-solver/cycles/provisional-result-done.rs
new file mode 100644
index 000000000..0f3b84ce5
--- /dev/null
+++ b/tests/ui/traits/next-solver/cycles/provisional-result-done.rs
@@ -0,0 +1,33 @@
+// compile-flags: -Znext-solver
+// 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>(T);
+struct Bar<T>(T);
+
+impl<T> Coinductive for Foo<T>
+where
+ Bar<T>: Coinductive
+{}
+
+impl<T> Coinductive for Bar<T>
+where
+ Foo<T>: Coinductive,
+ Bar<T>: ConstrainInfer,
+{}
+
+trait ConstrainInfer {}
+impl ConstrainInfer for Bar<u8> {}
+impl ConstrainInfer for Foo<u16> {}
+
+fn impls<T: Coinductive>() -> T { todo!() }
+
+fn constrain<T: ConstrainInfer>(_: T) {}
+
+fn main() {
+ // This should constrain `_` to `u8`.
+ impls::<Foo<_>>();
+}
diff --git a/tests/ui/traits/next-solver/deduce-closure-signature-after-normalization.rs b/tests/ui/traits/next-solver/deduce-closure-signature-after-normalization.rs
new file mode 100644
index 000000000..08f26686b
--- /dev/null
+++ b/tests/ui/traits/next-solver/deduce-closure-signature-after-normalization.rs
@@ -0,0 +1,10 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+trait Foo {
+ fn test() -> impl Fn(u32) -> u32 {
+ |x| x.count_ones()
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/deduce-ty-from-object.rs b/tests/ui/traits/next-solver/deduce-ty-from-object.rs
new file mode 100644
index 000000000..b627fd720
--- /dev/null
+++ b/tests/ui/traits/next-solver/deduce-ty-from-object.rs
@@ -0,0 +1,6 @@
+// check-pass
+// compile-flags: -Znext-solver
+
+fn main() {
+ let x: Box<dyn Iterator<Item = ()>> = Box::new(std::iter::empty());
+}
diff --git a/tests/ui/traits/next-solver/dedup-regions.rs b/tests/ui/traits/next-solver/dedup-regions.rs
new file mode 100644
index 000000000..dd406333f
--- /dev/null
+++ b/tests/ui/traits/next-solver/dedup-regions.rs
@@ -0,0 +1,31 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+struct A(*mut ());
+
+unsafe impl Send for A where A: 'static {}
+
+macro_rules! mk {
+ ($name:ident $ty:ty) => {
+ struct $name($ty, $ty, $ty, $ty, $ty, $ty, $ty, $ty, $ty, $ty);
+ };
+}
+
+mk!(B A);
+mk!(C B);
+mk!(D C);
+mk!(E D);
+mk!(F E);
+mk!(G F);
+mk!(H G);
+mk!(I H);
+mk!(J I);
+mk!(K J);
+mk!(L K);
+mk!(M L);
+
+fn needs_send<T: Send>() {}
+
+fn main() {
+ needs_send::<M>();
+}
diff --git a/tests/ui/traits/next-solver/destruct.rs b/tests/ui/traits/next-solver/destruct.rs
new file mode 100644
index 000000000..5093344e4
--- /dev/null
+++ b/tests/ui/traits/next-solver/destruct.rs
@@ -0,0 +1,13 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+#![feature(const_trait_impl)]
+
+fn foo(_: impl std::marker::Destruct) {}
+
+struct MyAdt;
+
+fn main() {
+ foo(1);
+ foo(MyAdt);
+}
diff --git a/tests/ui/traits/next-solver/dont-coerce-infer-to-dyn.rs b/tests/ui/traits/next-solver/dont-coerce-infer-to-dyn.rs
new file mode 100644
index 000000000..da07869f3
--- /dev/null
+++ b/tests/ui/traits/next-solver/dont-coerce-infer-to-dyn.rs
@@ -0,0 +1,17 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+use std::fmt::Display;
+use std::rc::Rc;
+
+fn mk<T: ?Sized>(t: Option<&T>) -> Rc<T> {
+ todo!()
+}
+
+fn main() {
+ let mut x = None;
+ let y = mk(x);
+ // Don't treat the line below as a unsize coercion `Rc<?0> ~> Rc<dyn Display>`
+ let z: Rc<dyn Display> = y;
+ x = Some(&1 as &dyn Display);
+}
diff --git a/tests/ui/traits/next-solver/dont-elaborate-for-projections.rs b/tests/ui/traits/next-solver/dont-elaborate-for-projections.rs
new file mode 100644
index 000000000..9123871db
--- /dev/null
+++ b/tests/ui/traits/next-solver/dont-elaborate-for-projections.rs
@@ -0,0 +1,12 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+trait Iter<'a, I: 'a>: Iterator<Item = &'a I> {}
+
+fn needs_iter<'a, T: Iter<'a, I> + ?Sized, I: 'a>(_: &T) {}
+
+fn test(x: &dyn Iter<'_, ()>) {
+ needs_iter(x);
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/dont-ice-on-assoc-projection.rs b/tests/ui/traits/next-solver/dont-ice-on-assoc-projection.rs
new file mode 100644
index 000000000..1e1ef8c23
--- /dev/null
+++ b/tests/ui/traits/next-solver/dont-ice-on-assoc-projection.rs
@@ -0,0 +1,19 @@
+// compile-flags: -Znext-solver=coherence
+
+// Makes sure we don't ICE on associated const projection when the feature gate
+// is not enabled, since we should avoid encountering ICEs on stable if possible.
+
+trait Bar {
+ const ASSOC: usize;
+}
+impl Bar for () {
+ const ASSOC: usize = 1;
+}
+
+trait Foo {}
+impl Foo for () {}
+impl<T> Foo for T where T: Bar<ASSOC = 0> {}
+//~^ ERROR associated const equality is incomplete
+//~| ERROR conflicting implementations of trait `Foo` for type `()`
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/dont-ice-on-assoc-projection.stderr b/tests/ui/traits/next-solver/dont-ice-on-assoc-projection.stderr
new file mode 100644
index 000000000..368f5cd0c
--- /dev/null
+++ b/tests/ui/traits/next-solver/dont-ice-on-assoc-projection.stderr
@@ -0,0 +1,21 @@
+error[E0658]: associated const equality is incomplete
+ --> $DIR/dont-ice-on-assoc-projection.rs:15:32
+ |
+LL | impl<T> Foo for T where T: Bar<ASSOC = 0> {}
+ | ^^^^^^^^^
+ |
+ = note: see issue #92827 <https://github.com/rust-lang/rust/issues/92827> for more information
+ = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable
+
+error[E0119]: conflicting implementations of trait `Foo` for type `()`
+ --> $DIR/dont-ice-on-assoc-projection.rs:15:1
+ |
+LL | impl Foo for () {}
+ | --------------- first implementation here
+LL | impl<T> Foo for T where T: Bar<ASSOC = 0> {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0119, E0658.
+For more information about an error, try `rustc --explain E0119`.
diff --git a/tests/ui/traits/next-solver/dont-loop-fulfill-on-region-constraints.rs b/tests/ui/traits/next-solver/dont-loop-fulfill-on-region-constraints.rs
new file mode 100644
index 000000000..a85098a95
--- /dev/null
+++ b/tests/ui/traits/next-solver/dont-loop-fulfill-on-region-constraints.rs
@@ -0,0 +1,32 @@
+// compile-flags: -Znext-solver
+// 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/next-solver/dont-normalize-proj-with-error.rs b/tests/ui/traits/next-solver/dont-normalize-proj-with-error.rs
new file mode 100644
index 000000000..fd1682cd6
--- /dev/null
+++ b/tests/ui/traits/next-solver/dont-normalize-proj-with-error.rs
@@ -0,0 +1,22 @@
+// compile-flags: -Znext-solver
+
+// 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: ?Sized>(T);
+impl<T: ?Sized> Mirror for Wrapper<T> {
+ type Assoc = T;
+}
+
+fn mirror<W: Mirror>(_: W) -> Box<W::Assoc> { 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/next-solver/dont-normalize-proj-with-error.stderr b/tests/ui/traits/next-solver/dont-normalize-proj-with-error.stderr
new file mode 100644
index 000000000..576ede52a
--- /dev/null
+++ b/tests/ui/traits/next-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 1 previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/tests/ui/traits/next-solver/dont-remap-tait-substs.rs b/tests/ui/traits/next-solver/dont-remap-tait-substs.rs
new file mode 100644
index 000000000..b089f0df3
--- /dev/null
+++ b/tests/ui/traits/next-solver/dont-remap-tait-substs.rs
@@ -0,0 +1,19 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+// Makes sure we don't prepopulate the MIR typeck of `define`
+// with `Foo<T, U> = T`, but instead, `Foo<B, A> = B`, so that
+// the param-env predicates actually apply.
+
+#![feature(type_alias_impl_trait)]
+
+type Foo<T: Send, U> = impl NeedsSend<T>;
+
+trait NeedsSend<T> {}
+impl<T: Send> NeedsSend<T> for T {}
+
+fn define<A, B: Send>(a: A, b: B, _: Foo<B, A>) {
+ let y: Option<Foo<B, A>> = Some(b);
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.not_send.stderr b/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.not_send.stderr
new file mode 100644
index 000000000..076dab29d
--- /dev/null
+++ b/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.not_send.stderr
@@ -0,0 +1,16 @@
+error[E0283]: type annotations needed: cannot satisfy `Foo: Send`
+ --> $DIR/dont-type_of-tait-in-defining-scope.rs:16:18
+ |
+LL | needs_send::<Foo>();
+ | ^^^
+ |
+ = note: cannot satisfy `Foo: Send`
+note: required by a bound in `needs_send`
+ --> $DIR/dont-type_of-tait-in-defining-scope.rs:13:18
+ |
+LL | fn needs_send<T: Send>() {}
+ | ^^^^ required by this bound in `needs_send`
+
+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/dont-type_of-tait-in-defining-scope.rs b/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.rs
new file mode 100644
index 000000000..a1f38e69e
--- /dev/null
+++ b/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.rs
@@ -0,0 +1,24 @@
+// revisions: is_send not_send
+// compile-flags: -Znext-solver
+//[is_send] check-pass
+
+#![feature(type_alias_impl_trait)]
+
+#[cfg(is_send)]
+type Foo = impl Send;
+
+#[cfg(not_send)]
+type Foo = impl Sized;
+
+fn needs_send<T: Send>() {}
+
+fn test(_: Foo) {
+ needs_send::<Foo>();
+ //[not_send]~^ ERROR type annotations needed: cannot satisfy `Foo: Send`
+}
+
+fn defines(_: Foo) {
+ let _: Foo = ();
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/dyn-any-dont-prefer-impl.rs b/tests/ui/traits/next-solver/dyn-any-dont-prefer-impl.rs
new file mode 100644
index 000000000..bb1c24a00
--- /dev/null
+++ b/tests/ui/traits/next-solver/dyn-any-dont-prefer-impl.rs
@@ -0,0 +1,17 @@
+// compile-flags: -Znext-solver
+// 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) {}
+
+fn main() {
+ let x: &dyn Any = &1usize;
+ if let Some(x) = x.downcast_ref::<usize>() {
+ needs_usize(x);
+ }
+}
diff --git a/tests/ui/traits/next-solver/elaborate-item-bounds.rs b/tests/ui/traits/next-solver/elaborate-item-bounds.rs
new file mode 100644
index 000000000..0f1f6c044
--- /dev/null
+++ b/tests/ui/traits/next-solver/elaborate-item-bounds.rs
@@ -0,0 +1,12 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+trait Foo {
+ type Bar: Bar;
+}
+
+trait Bar: Baz {}
+
+trait Baz {}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/equating-projection-cyclically.rs b/tests/ui/traits/next-solver/equating-projection-cyclically.rs
new file mode 100644
index 000000000..e7c80cfd7
--- /dev/null
+++ b/tests/ui/traits/next-solver/equating-projection-cyclically.rs
@@ -0,0 +1,31 @@
+// check-pass
+// compile-flags: -Znext-solver
+
+trait Test {
+ type Assoc;
+}
+
+fn transform<T: Test>(x: Inv<T>) -> Inv<T::Assoc> {
+ todo!()
+}
+
+impl Test for i32 {
+ type Assoc = i32;
+}
+
+impl Test for String {
+ type Assoc = String;
+}
+
+struct Inv<T>(Option<*mut T>);
+
+fn main() {
+ let mut x: Inv<_> = Inv(None);
+ // This ends up equating `Inv<?x>` with `Inv<<?x as Test>::Assoc>`
+ // which fails the occurs check when generalizing `?x`.
+ //
+ // We end up emitting a delayed obligation, causing this to still
+ // succeed.
+ x = transform(x);
+ x = Inv::<i32>(None);
+}
diff --git a/tests/ui/traits/next-solver/escaping-bound-vars-in-writeback-normalization.rs b/tests/ui/traits/next-solver/escaping-bound-vars-in-writeback-normalization.rs
new file mode 100644
index 000000000..77bedc351
--- /dev/null
+++ b/tests/ui/traits/next-solver/escaping-bound-vars-in-writeback-normalization.rs
@@ -0,0 +1,18 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+trait Trivial {
+ type Assoc;
+}
+
+impl<T: ?Sized> 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<for<'a> fn(<&'a () as Trivial>::Assoc)> = None;
+}
diff --git a/tests/ui/traits/next-solver/float-canonical.rs b/tests/ui/traits/next-solver/float-canonical.rs
new file mode 100644
index 000000000..90d75bacb
--- /dev/null
+++ b/tests/ui/traits/next-solver/float-canonical.rs
@@ -0,0 +1,8 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+fn foo(x: f64) {
+ let y = x + 1.0;
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/fn-trait-closure.rs b/tests/ui/traits/next-solver/fn-trait-closure.rs
new file mode 100644
index 000000000..cd2ae1f6f
--- /dev/null
+++ b/tests/ui/traits/next-solver/fn-trait-closure.rs
@@ -0,0 +1,8 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+fn require_fn(_: impl Fn() -> i32) {}
+
+fn main() {
+ require_fn(|| -> i32 { 1i32 });
+}
diff --git a/tests/ui/traits/next-solver/fn-trait.rs b/tests/ui/traits/next-solver/fn-trait.rs
new file mode 100644
index 000000000..1e3d8a21c
--- /dev/null
+++ b/tests/ui/traits/next-solver/fn-trait.rs
@@ -0,0 +1,32 @@
+// compile-flags: -Znext-solver
+
+fn require_fn(_: impl Fn() -> i32) {}
+
+fn f() -> i32 {
+ 1i32
+}
+
+extern "C" fn g() -> i32 {
+ 2i32
+}
+
+unsafe fn h() -> i32 {
+ 2i32
+}
+
+fn main() {
+ require_fn(f);
+ require_fn(f as fn() -> i32);
+ require_fn(f as unsafe fn() -> i32);
+ //~^ ERROR: expected a `Fn()` closure, found `unsafe fn() -> i32`
+ //~| ERROR: type mismatch resolving `<unsafe fn() -> i32 as FnOnce<()>>::Output == i32`
+ require_fn(g);
+ //~^ ERROR: expected a `Fn()` closure, found `extern "C" fn() -> i32 {g}`
+ //~| ERROR: type mismatch resolving `<extern "C" fn() -> i32 {g} as FnOnce<()>>::Output == i32`
+ require_fn(g as extern "C" fn() -> i32);
+ //~^ ERROR: expected a `Fn()` closure, found `extern "C" fn() -> i32`
+ //~| ERROR: type mismatch resolving `<extern "C" fn() -> i32 as FnOnce<()>>::Output == i32`
+ require_fn(h);
+ //~^ ERROR: expected a `Fn()` closure, found `unsafe fn() -> i32 {h}`
+ //~| ERROR: type mismatch resolving `<unsafe fn() -> i32 {h} as FnOnce<()>>::Output == i32`
+}
diff --git a/tests/ui/traits/next-solver/fn-trait.stderr b/tests/ui/traits/next-solver/fn-trait.stderr
new file mode 100644
index 000000000..e33487235
--- /dev/null
+++ b/tests/ui/traits/next-solver/fn-trait.stderr
@@ -0,0 +1,126 @@
+error[E0277]: expected a `Fn()` closure, found `unsafe fn() -> i32`
+ --> $DIR/fn-trait.rs:20:16
+ |
+LL | require_fn(f as unsafe fn() -> i32);
+ | ---------- ^^^^^^^^^^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Fn<()>` is not implemented for `unsafe fn() -> i32`
+ = note: unsafe function cannot be called generically without an unsafe block
+ = note: wrap the `unsafe fn() -> i32` in a closure with no arguments: `|| { /* code */ }`
+note: required by a bound in `require_fn`
+ --> $DIR/fn-trait.rs:3:23
+ |
+LL | fn require_fn(_: impl Fn() -> i32) {}
+ | ^^^^^^^^^^^ required by this bound in `require_fn`
+
+error[E0271]: type mismatch resolving `<unsafe fn() -> i32 as FnOnce<()>>::Output == i32`
+ --> $DIR/fn-trait.rs:20:16
+ |
+LL | require_fn(f as unsafe fn() -> i32);
+ | ---------- ^^^^^^^^^^^^^^^^^^^^^^^ types differ
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `require_fn`
+ --> $DIR/fn-trait.rs:3:31
+ |
+LL | fn require_fn(_: impl Fn() -> i32) {}
+ | ^^^ required by this bound in `require_fn`
+
+error[E0277]: expected a `Fn()` closure, found `extern "C" fn() -> i32 {g}`
+ --> $DIR/fn-trait.rs:23:16
+ |
+LL | require_fn(g);
+ | ---------- ^ expected an `Fn()` closure, found `extern "C" fn() -> i32 {g}`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Fn<()>` is not implemented for fn item `extern "C" fn() -> i32 {g}`
+ = note: wrap the `extern "C" fn() -> i32 {g}` in a closure with no arguments: `|| { /* code */ }`
+note: required by a bound in `require_fn`
+ --> $DIR/fn-trait.rs:3:23
+ |
+LL | fn require_fn(_: impl Fn() -> i32) {}
+ | ^^^^^^^^^^^ required by this bound in `require_fn`
+
+error[E0271]: type mismatch resolving `<extern "C" fn() -> i32 {g} as FnOnce<()>>::Output == i32`
+ --> $DIR/fn-trait.rs:23:16
+ |
+LL | require_fn(g);
+ | ---------- ^ types differ
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `require_fn`
+ --> $DIR/fn-trait.rs:3:31
+ |
+LL | fn require_fn(_: impl Fn() -> i32) {}
+ | ^^^ required by this bound in `require_fn`
+
+error[E0277]: expected a `Fn()` closure, found `extern "C" fn() -> i32`
+ --> $DIR/fn-trait.rs:26:16
+ |
+LL | require_fn(g as extern "C" fn() -> i32);
+ | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an `Fn()` closure, found `extern "C" fn() -> i32`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Fn<()>` is not implemented for `extern "C" fn() -> i32`
+ = note: wrap the `extern "C" fn() -> i32` in a closure with no arguments: `|| { /* code */ }`
+note: required by a bound in `require_fn`
+ --> $DIR/fn-trait.rs:3:23
+ |
+LL | fn require_fn(_: impl Fn() -> i32) {}
+ | ^^^^^^^^^^^ required by this bound in `require_fn`
+
+error[E0271]: type mismatch resolving `<extern "C" fn() -> i32 as FnOnce<()>>::Output == i32`
+ --> $DIR/fn-trait.rs:26:16
+ |
+LL | require_fn(g as extern "C" fn() -> i32);
+ | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `require_fn`
+ --> $DIR/fn-trait.rs:3:31
+ |
+LL | fn require_fn(_: impl Fn() -> i32) {}
+ | ^^^ required by this bound in `require_fn`
+
+error[E0277]: expected a `Fn()` closure, found `unsafe fn() -> i32 {h}`
+ --> $DIR/fn-trait.rs:29:16
+ |
+LL | require_fn(h);
+ | ---------- ^ call the function in a closure: `|| unsafe { /* code */ }`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Fn<()>` is not implemented for fn item `unsafe fn() -> i32 {h}`
+ = note: unsafe function cannot be called generically without an unsafe block
+ = note: wrap the `unsafe fn() -> i32 {h}` in a closure with no arguments: `|| { /* code */ }`
+note: required by a bound in `require_fn`
+ --> $DIR/fn-trait.rs:3:23
+ |
+LL | fn require_fn(_: impl Fn() -> i32) {}
+ | ^^^^^^^^^^^ required by this bound in `require_fn`
+
+error[E0271]: type mismatch resolving `<unsafe fn() -> i32 {h} as FnOnce<()>>::Output == i32`
+ --> $DIR/fn-trait.rs:29:16
+ |
+LL | require_fn(h);
+ | ---------- ^ types differ
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `require_fn`
+ --> $DIR/fn-trait.rs:3:31
+ |
+LL | fn require_fn(_: impl Fn() -> i32) {}
+ | ^^^ required by this bound in `require_fn`
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0271, E0277.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/tests/ui/traits/next-solver/generalize/generalize-proj-new-universe-index-1.rs b/tests/ui/traits/next-solver/generalize/generalize-proj-new-universe-index-1.rs
new file mode 100644
index 000000000..4a70bd5f8
--- /dev/null
+++ b/tests/ui/traits/next-solver/generalize/generalize-proj-new-universe-index-1.rs
@@ -0,0 +1,73 @@
+// compile-flags: -Znext-solver
+// 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<T: ?Sized> Id for T {
+ type Assoc = T;
+}
+
+trait WithAssoc<T: ?Sized> {
+ type Assoc: ?Sized;
+}
+
+
+struct Leaf;
+struct Wrapper<U: ?Sized>(U);
+
+impl<U: ?Sized> WithAssoc<U> for Leaf {
+ type Assoc = U;
+}
+
+impl<Ul: ?Sized, Ur: ?Sized> WithAssoc<Wrapper<Ur>> for Wrapper<Ul>
+where
+ Ul: WithAssoc<Ur>,
+{
+ type Assoc = <<Ul as WithAssoc<Ur>>::Assoc as Id>::Assoc;
+}
+
+fn bound<T: ?Sized, U: ?Sized, V: ?Sized>()
+where
+ T: WithAssoc<U, Assoc = V>,
+{
+}
+
+// normalize self type to `Wrapper<Leaf>`
+// This succeeds, HOWEVER, instantiating the query response previously
+// incremented the universe index counter.
+// equate impl headers:
+// <Wrapper<Leaf> as WithAssoc<<Wrapper<Leaf> as Id>::Assoc>>
+// <Wrapper<?2t> as WithAssoc<Wrapper<?3t>>>
+// ~> AliasRelate(<Wrapper<Leaf> as Id>::Assoc, Equate, Wrapper<?3t>)
+// add where bounds:
+// ~> Leaf: WithAssoc<?3t>
+// equate with assoc type:
+// ?0t
+// <Leaf as WithAssoc<?3t>>::Assoc as Id>::Assoc
+// ~> AliasRelate(
+// <<Leaf as WithAssoc<?3t>>::Assoc as Id>::Assoc,
+// Equate,
+// <<Leaf as WithAssoc<?4t>>::Assoc as Id>::Assoc,
+// )
+//
+// We do not reuse `?3t` during generalization because `?0t` cannot name `?4t` as we created
+// it after incrementing the universe index while normalizing the self type.
+//
+// evaluate_added_goals_and_make_query_response:
+// AliasRelate(<Wrapper<Leaf> as Id>::Assoc, Equate, Wrapper<?3t>)
+// YES, constrains ?3t to Leaf
+// AliasRelate(
+// <<Leaf as WithAssoc<Leaf>>::Assoc as Id>::Assoc,
+// Equate,
+// <<Leaf as WithAssoc<?4t>>::Assoc as Id>::Assoc,
+// )
+//
+// Normalizing <<Leaf as WithAssoc<?4t>>::Assoc as Id>::Assoc then *correctly*
+// results in ambiguity.
+fn main() {
+ bound::<<Wrapper<Leaf> as Id>::Assoc, <Wrapper<Leaf> as Id>::Assoc, _>()
+}
diff --git a/tests/ui/traits/next-solver/generalize/generalize-proj-new-universe-index-2.rs b/tests/ui/traits/next-solver/generalize/generalize-proj-new-universe-index-2.rs
new file mode 100644
index 000000000..70758e7de
--- /dev/null
+++ b/tests/ui/traits/next-solver/generalize/generalize-proj-new-universe-index-2.rs
@@ -0,0 +1,75 @@
+// compile-flags: -Znext-solver
+// known-bug: trait-system-refactor-initiative#60
+
+// Generalizing a projection containing an inference variable
+// which cannot be named by the `root_vid` can result in ambiguity.
+//
+// Because we do not decrement the universe index when exiting a forall,
+// this can cause unexpected failures.
+//
+// See generalize-proj-new-universe-index-1.rs for more details.
+
+// For this reproduction we need:
+// - an inference variable with a lower universe
+// - enter a binder to increment the current universe
+// - create a new inference variable which is constrained by proving a goal
+// - equate a projection containing the new variable with the first variable
+// - generalization creates yet another inference variable which is then
+// part of an alias-relate, resulting this to fail with ambiguity.
+//
+// Because we need to enter the binder in-between the creation of the first
+// and second inference variable, this is easiest via
+// `assemble_candidates_after_normalizing_self_ty` because eagerly call
+// `try_evaluate_added_goals` there before creating the inference variables
+// for the impl parameters.
+trait Id {
+ type Assoc: ?Sized;
+}
+impl<T: ?Sized> Id for T {
+ type Assoc = T;
+}
+
+// By adding an higher ranked bound to the impl we currently
+// propagate this bound to the caller, forcing us to create a new
+// universe.
+trait IdHigherRankedBound {
+ type Assoc: ?Sized;
+}
+
+impl<T: ?Sized> IdHigherRankedBound for T
+where
+ for<'a> T: 'a,
+{
+ type Assoc = T;
+}
+
+trait WithAssoc<T: ?Sized> {
+ type Assoc: ?Sized;
+}
+
+
+struct Leaf;
+struct Wrapper<U: ?Sized>(U);
+struct Rigid;
+
+impl<U: ?Sized> WithAssoc<U> for Leaf {
+ type Assoc = U;
+}
+
+
+impl<Ur: ?Sized> WithAssoc<Wrapper<Ur>> for Rigid
+where
+ Leaf: WithAssoc<Ur>,
+{
+ type Assoc = <<Leaf as WithAssoc<Ur>>::Assoc as Id>::Assoc;
+}
+
+fn bound<T: ?Sized, U: ?Sized, V: ?Sized>()
+where
+ T: WithAssoc<U, Assoc = V>,
+{
+}
+
+fn main() {
+ bound::<<Rigid as IdHigherRankedBound>::Assoc, <Wrapper<Leaf> as Id>::Assoc, _>()
+}
diff --git a/tests/ui/traits/next-solver/generalize/generalize-proj-new-universe-index-2.stderr b/tests/ui/traits/next-solver/generalize/generalize-proj-new-universe-index-2.stderr
new file mode 100644
index 000000000..4548ab1e2
--- /dev/null
+++ b/tests/ui/traits/next-solver/generalize/generalize-proj-new-universe-index-2.stderr
@@ -0,0 +1,19 @@
+error[E0284]: type annotations needed
+ --> $DIR/generalize-proj-new-universe-index-2.rs:74:5
+ |
+LL | bound::<<Rigid as IdHigherRankedBound>::Assoc, <Wrapper<Leaf> as Id>::Assoc, _>()
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `V` declared on the function `bound`
+ |
+ = note: cannot satisfy `<<Rigid as IdHigherRankedBound>::Assoc as WithAssoc<<Wrapper<Leaf> as Id>::Assoc>>::Assoc == _`
+note: required by a bound in `bound`
+ --> $DIR/generalize-proj-new-universe-index-2.rs:69:21
+ |
+LL | fn bound<T: ?Sized, U: ?Sized, V: ?Sized>()
+ | ----- required by a bound in this function
+LL | where
+LL | T: WithAssoc<U, Assoc = V>,
+ | ^^^^^^^^^ required by this bound in `bound`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0284`.
diff --git a/tests/ui/traits/next-solver/generalize/occurs-check-nested-alias.next.stderr b/tests/ui/traits/next-solver/generalize/occurs-check-nested-alias.next.stderr
new file mode 100644
index 000000000..ad8b24a39
--- /dev/null
+++ b/tests/ui/traits/next-solver/generalize/occurs-check-nested-alias.next.stderr
@@ -0,0 +1,11 @@
+error[E0275]: overflow evaluating the requirement `<<T as Id<_>>::Id as Unnormalizable>::Assoc == _`
+ --> $DIR/occurs-check-nested-alias.rs:36:9
+ |
+LL | x = y;
+ | ^
+ |
+ = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`occurs_check_nested_alias`)
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/next-solver/generalize/occurs-check-nested-alias.rs b/tests/ui/traits/next-solver/generalize/occurs-check-nested-alias.rs
new file mode 100644
index 000000000..e51508d68
--- /dev/null
+++ b/tests/ui/traits/next-solver/generalize/occurs-check-nested-alias.rs
@@ -0,0 +1,38 @@
+// revisions: old next
+//[old] check-pass
+
+// Currently always fails to generalize the outer alias, even if it
+// is treated as rigid by `alias-relate`.
+//[next] compile-flags: -Znext-solver
+//[next] known-bug: trait-system-refactor-initiative#8
+#![crate_type = "lib"]
+#![allow(unused)]
+trait Unnormalizable {
+ type Assoc;
+}
+
+trait Id<T> {
+ type Id;
+}
+impl<T, U> Id<T> for U {
+ type Id = U;
+}
+
+struct Inv<T>(*mut T);
+
+fn unconstrained<T>() -> T {
+ todo!()
+}
+
+fn create<T, U: Unnormalizable>(
+ x: &U,
+) -> (Inv<T>, Inv<<<U as Id<T>>::Id as Unnormalizable>::Assoc>) {
+ todo!()
+}
+
+fn foo<T: Unnormalizable>() {
+ let q = unconstrained();
+ let (mut x, y) = create::<_, _>(&q);
+ x = y;
+ drop::<T>(q);
+}
diff --git a/tests/ui/traits/next-solver/higher-ranked-dyn-bounds.rs b/tests/ui/traits/next-solver/higher-ranked-dyn-bounds.rs
new file mode 100644
index 000000000..b87210d7f
--- /dev/null
+++ b/tests/ui/traits/next-solver/higher-ranked-dyn-bounds.rs
@@ -0,0 +1,17 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+trait Trait<'a> {
+ type Item: for<'b> Trait2<'b>;
+}
+
+trait Trait2<'a> {}
+impl Trait2<'_> for () {}
+
+fn needs_trait(_: Box<impl for<'a> Trait<'a> + ?Sized>) {}
+
+fn foo(x: Box<dyn for<'a> Trait<'a, Item = ()>>) {
+ needs_trait(x);
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/int-var-alias-eq.rs b/tests/ui/traits/next-solver/int-var-alias-eq.rs
new file mode 100644
index 000000000..26ba7f8e5
--- /dev/null
+++ b/tests/ui/traits/next-solver/int-var-alias-eq.rs
@@ -0,0 +1,18 @@
+// check-pass
+// compile-flags: -Znext-solver
+
+// HIR typeck ends up equating `<?0i as Add>::Output == ?0i`.
+// Want to make sure that we emit an alias-eq goal for this,
+// instead of treating it as a type error and bailing.
+
+fn test() {
+ // fallback
+ let x = 1 + 2;
+}
+
+fn test2() -> u32 {
+ // expectation from return ty
+ 1 + 2
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/int-var-is-send.rs b/tests/ui/traits/next-solver/int-var-is-send.rs
new file mode 100644
index 000000000..d8b963f20
--- /dev/null
+++ b/tests/ui/traits/next-solver/int-var-is-send.rs
@@ -0,0 +1,8 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+fn needs_send(_: impl Send) {}
+
+fn main() {
+ needs_send(1);
+}
diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.rs b/tests/ui/traits/next-solver/issue-118950-root-region.rs
new file mode 100644
index 000000000..10fb7d525
--- /dev/null
+++ b/tests/ui/traits/next-solver/issue-118950-root-region.rs
@@ -0,0 +1,22 @@
+// compile-flags: -Znext-solver
+//
+// This is a gnarly test but I don't know how to minimize it, frankly.
+
+#![feature(lazy_type_alias)]
+//~^ WARN the feature `lazy_type_alias` is incomplete
+
+trait ToUnit<'a> {
+ type Unit;
+}
+
+trait Overlap<T> {}
+
+type Assoc<'a, T> = <*const T as ToUnit<'a>>::Unit;
+
+impl<T> Overlap<T> for T {}
+
+impl<T> Overlap<for<'a> fn(Assoc<'a, T>)> for T where Missing: Overlap<T> {}
+//~^ ERROR conflicting implementations of trait `Overlap<fn(_)>` for type `fn(_)`
+//~| ERROR cannot find type `Missing` in this scope
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.stderr b/tests/ui/traits/next-solver/issue-118950-root-region.stderr
new file mode 100644
index 000000000..c16a48d5f
--- /dev/null
+++ b/tests/ui/traits/next-solver/issue-118950-root-region.stderr
@@ -0,0 +1,36 @@
+error[E0412]: cannot find type `Missing` in this scope
+ --> $DIR/issue-118950-root-region.rs:18:55
+ |
+LL | impl<T> Overlap<for<'a> fn(Assoc<'a, T>)> for T where Missing: Overlap<T> {}
+ | ^^^^^^^ not found in this scope
+
+warning: the feature `lazy_type_alias` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/issue-118950-root-region.rs:5:12
+ |
+LL | #![feature(lazy_type_alias)]
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
+ = note: `#[warn(incomplete_features)]` on by default
+
+WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Weak, AliasTy { args: [ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), 'a) }), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) })
+WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Weak, AliasTy { args: [RePlaceholder(!1_BoundRegion { var: 0, kind: BrNamed(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), 'a) }), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) })
+WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Weak, AliasTy { args: [ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), 'a) }), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) })
+WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Weak, AliasTy { args: [RePlaceholder(!1_BoundRegion { var: 0, kind: BrNamed(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), 'a) }), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) })
+WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Weak, AliasTy { args: [ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), 'a) }), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) })
+WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Weak, AliasTy { args: [RePlaceholder(!1_BoundRegion { var: 0, kind: BrNamed(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), 'a) }), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) })
+WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Weak, AliasTy { args: [ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), 'a) }), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) })
+WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Weak, AliasTy { args: [RePlaceholder(!1_BoundRegion { var: 0, kind: BrNamed(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), 'a) }), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) })
+error[E0119]: conflicting implementations of trait `Overlap<fn(_)>` for type `fn(_)`
+ --> $DIR/issue-118950-root-region.rs:18:1
+ |
+LL | impl<T> Overlap<T> for T {}
+ | ------------------------ first implementation here
+LL |
+LL | impl<T> Overlap<for<'a> fn(Assoc<'a, T>)> for T where Missing: Overlap<T> {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `fn(_)`
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+Some errors have detailed explanations: E0119, E0412.
+For more information about an error, try `rustc --explain E0119`.
diff --git a/tests/ui/traits/next-solver/iter-filter-projection.rs b/tests/ui/traits/next-solver/iter-filter-projection.rs
new file mode 100644
index 000000000..f948831ad
--- /dev/null
+++ b/tests/ui/traits/next-solver/iter-filter-projection.rs
@@ -0,0 +1,12 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+use std::{iter, slice};
+
+struct Attr;
+
+fn test<'a, T: Iterator<Item = &'a Attr>>() {}
+
+fn main() {
+ test::<iter::Filter<slice::Iter<'_, Attr>, fn(&&Attr) -> bool>>();
+}
diff --git a/tests/ui/traits/next-solver/lazy-nested-obligations-1.rs b/tests/ui/traits/next-solver/lazy-nested-obligations-1.rs
new file mode 100644
index 000000000..f9e73a93c
--- /dev/null
+++ b/tests/ui/traits/next-solver/lazy-nested-obligations-1.rs
@@ -0,0 +1,13 @@
+// check-pass
+// compile-flags: -Znext-solver
+// Issue 94358
+
+fn foo<C>(_: C)
+where
+ for <'a> &'a C: IntoIterator,
+ for <'a> <&'a C as IntoIterator>::IntoIter: ExactSizeIterator,
+{}
+
+fn main() {
+ foo::<_>(vec![true, false]);
+}
diff --git a/tests/ui/traits/next-solver/lazy-nested-obligations-2.rs b/tests/ui/traits/next-solver/lazy-nested-obligations-2.rs
new file mode 100644
index 000000000..b85f9d973
--- /dev/null
+++ b/tests/ui/traits/next-solver/lazy-nested-obligations-2.rs
@@ -0,0 +1,22 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+pub trait With {
+ type F;
+}
+
+impl With for i32 {
+ type F = fn(&str);
+}
+
+fn f(_: &str) {}
+
+fn main() {
+ let _: V<i32> = V(f);
+ pub struct V<T: With>(<T as With>::F);
+
+ pub enum E3<T: With> {
+ Var(<T as With>::F),
+ }
+ let _: E3<i32> = E3::Var(f);
+}
diff --git a/tests/ui/traits/next-solver/lazy-nested-obligations-3.rs b/tests/ui/traits/next-solver/lazy-nested-obligations-3.rs
new file mode 100644
index 000000000..5fb4832dd
--- /dev/null
+++ b/tests/ui/traits/next-solver/lazy-nested-obligations-3.rs
@@ -0,0 +1,38 @@
+// check-pass
+// compile-flags: -Znext-solver
+// Issue 96750
+
+use std::marker::PhantomData;
+
+trait AsyncFn<Arg> {
+ type Output;
+}
+trait RequestFamily {
+ type Type<'a>;
+}
+trait Service {}
+
+struct MyFn;
+impl AsyncFn<String> for MyFn {
+ type Output = ();
+}
+
+impl RequestFamily for String {
+ type Type<'a> = String;
+}
+
+struct ServiceFromAsyncFn<F, Req>(F, PhantomData<Req>);
+
+impl<F, Req, O> Service for ServiceFromAsyncFn<F, Req>
+where
+ Req: RequestFamily,
+ F: AsyncFn<Req>,
+ F: for<'a> AsyncFn<Req::Type<'a>, Output = O>,
+{
+}
+
+fn assert_service() -> impl Service {
+ ServiceFromAsyncFn(MyFn, PhantomData)
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/member-constraints-in-root-universe.rs b/tests/ui/traits/next-solver/member-constraints-in-root-universe.rs
new file mode 100644
index 000000000..16e95e94c
--- /dev/null
+++ b/tests/ui/traits/next-solver/member-constraints-in-root-universe.rs
@@ -0,0 +1,17 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+trait Trait {
+ type Ty;
+}
+
+impl Trait for for<'a> fn(&'a u8, &'a u8) {
+ type Ty = ();
+}
+
+// argument is necessary to create universes before registering the hidden type.
+fn test<'a>(_: <fn(&u8, &u8) as Trait>::Ty) -> impl Sized {
+ "hidden type is `&'?0 str` with '?0 member of ['static,]"
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/more-object-bound.rs b/tests/ui/traits/next-solver/more-object-bound.rs
new file mode 100644
index 000000000..8522f034d
--- /dev/null
+++ b/tests/ui/traits/next-solver/more-object-bound.rs
@@ -0,0 +1,27 @@
+// compile-flags: -Znext-solver
+// From #80800
+
+trait SuperTrait {
+ type A;
+ type B;
+}
+
+trait Trait: SuperTrait<A = <Self as SuperTrait>::B> {}
+
+fn transmute<A, B>(x: A) -> B {
+ foo::<A, B, dyn Trait<A = A, B = B>>(x)
+ //~^ ERROR the trait bound `dyn Trait<A = A, B = B>: Trait` is not satisfied
+}
+
+fn foo<A, B, T: ?Sized>(x: T::A) -> B
+where
+ T: Trait<B = B>,
+{
+ x
+}
+
+static X: u8 = 0;
+fn main() {
+ let x = transmute::<&u8, &[u8; 1_000_000]>(&X);
+ println!("{:?}", x[100_000]);
+}
diff --git a/tests/ui/traits/next-solver/more-object-bound.stderr b/tests/ui/traits/next-solver/more-object-bound.stderr
new file mode 100644
index 000000000..e3be2931e
--- /dev/null
+++ b/tests/ui/traits/next-solver/more-object-bound.stderr
@@ -0,0 +1,22 @@
+error[E0277]: the trait bound `dyn Trait<A = A, B = B>: Trait` is not satisfied
+ --> $DIR/more-object-bound.rs:12:5
+ |
+LL | foo::<A, B, dyn Trait<A = A, B = B>>(x)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `dyn Trait<A = A, B = B>`
+ |
+note: required by a bound in `foo`
+ --> $DIR/more-object-bound.rs:18:8
+ |
+LL | fn foo<A, B, T: ?Sized>(x: T::A) -> B
+ | --- required by a bound in this function
+LL | where
+LL | T: Trait<B = B>,
+ | ^^^^^^^^^^^^ required by this bound in `foo`
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+ |
+LL | fn transmute<A, B>(x: A) -> B where dyn Trait<A = A, B = B>: Trait {
+ | ++++++++++++++++++++++++++++++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/next-solver/negative-coherence-bounds.rs b/tests/ui/traits/next-solver/negative-coherence-bounds.rs
new file mode 100644
index 000000000..5436b02c3
--- /dev/null
+++ b/tests/ui/traits/next-solver/negative-coherence-bounds.rs
@@ -0,0 +1,40 @@
+// check-pass
+
+// This test verifies that negative trait predicate cannot be satisfied from a
+// positive param-env candidate.
+
+// Negative coherence is one of the only places where we actually construct and
+// evaluate negative predicates. Specifically, when verifying whether the first
+// and second impls below overlap, we do not want to consider them disjoint,
+// otherwise the second impl would be missing an associated type `type Item`
+// which is provided by the first impl that it is specializing.
+
+#![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
+#![feature(with_negative_coherence)]
+
+trait BoxIter {
+ type Item;
+
+ fn last(self) -> Option<Self::Item>;
+}
+
+impl<I: Iterator + ?Sized> BoxIter for Box<I> {
+ type Item = I::Item;
+
+ default fn last(self) -> Option<I::Item> {
+ todo!()
+ }
+}
+
+// When checking that this impl does/doesn't overlap the one above, we evaluate
+// a negative version of all of the where-clause predicates of the impl below.
+// For `I: !Iterator`, we should make sure that the param-env clause `I: Iterator`
+// from above doesn't satisfy this predicate.
+impl<I: Iterator> BoxIter for Box<I> {
+ fn last(self) -> Option<I::Item> {
+ (*self).last()
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/negative-coherence-bounds.stderr b/tests/ui/traits/next-solver/negative-coherence-bounds.stderr
new file mode 100644
index 000000000..4127f51f5
--- /dev/null
+++ b/tests/ui/traits/next-solver/negative-coherence-bounds.stderr
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/negative-coherence-bounds.rs:12:12
+ |
+LL | #![feature(specialization)]
+ | ^^^^^^^^^^^^^^
+ |
+ = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+ = help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/traits/next-solver/nested-alias-bound.rs b/tests/ui/traits/next-solver/nested-alias-bound.rs
new file mode 100644
index 000000000..2e3de0ac6
--- /dev/null
+++ b/tests/ui/traits/next-solver/nested-alias-bound.rs
@@ -0,0 +1,20 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+trait A {
+ type A: B;
+}
+
+trait B {
+ type B: C;
+}
+
+trait C {}
+
+fn needs_c<T: C>() {}
+
+fn test<T: A>() {
+ needs_c::<<T::A as B>::B>();
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/nested-obligations-with-bound-vars-gat.rs b/tests/ui/traits/next-solver/nested-obligations-with-bound-vars-gat.rs
new file mode 100644
index 000000000..94c6c2856
--- /dev/null
+++ b/tests/ui/traits/next-solver/nested-obligations-with-bound-vars-gat.rs
@@ -0,0 +1,43 @@
+// check-pass
+// compile-flags: -Znext-solver
+// Issue 96230
+
+use std::fmt::Debug;
+
+trait Classic {
+ type Assoc;
+}
+
+trait Gat {
+ type Assoc<'a>;
+}
+
+struct Foo;
+
+impl Classic for Foo {
+ type Assoc = ();
+}
+
+impl Gat for Foo {
+ type Assoc<'i> = ();
+}
+
+fn classic_debug<T: Classic>(_: T)
+where
+ T::Assoc: Debug,
+{
+}
+
+fn gat_debug<T: Gat>(_: T)
+where
+ for<'a> T::Assoc<'a>: Debug,
+{
+}
+
+fn main() {
+ classic_debug::<Foo>(Foo); // fine
+ classic_debug(Foo); // fine
+
+ gat_debug::<Foo>(Foo); // fine
+ gat_debug(Foo); // boom
+}
diff --git a/tests/ui/traits/next-solver/normalize-async-closure-in-trait.rs b/tests/ui/traits/next-solver/normalize-async-closure-in-trait.rs
new file mode 100644
index 000000000..b58db2be8
--- /dev/null
+++ b/tests/ui/traits/next-solver/normalize-async-closure-in-trait.rs
@@ -0,0 +1,9 @@
+// compile-flags: -Znext-solver
+// check-pass
+// edition:2021
+
+trait Foo {
+ async fn bar() {}
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/normalize-param-env-1.rs b/tests/ui/traits/next-solver/normalize-param-env-1.rs
new file mode 100644
index 000000000..92d405137
--- /dev/null
+++ b/tests/ui/traits/next-solver/normalize-param-env-1.rs
@@ -0,0 +1,40 @@
+// check-pass
+// compile-flags: -Znext-solver
+// Issue 108933
+
+trait Add<Rhs> {
+ type Sum;
+}
+
+impl Add<()> for () {
+ type Sum = ();
+}
+
+type Unit = <() as Add<()>>::Sum;
+
+trait Trait<C> {
+ type Output;
+}
+
+fn f<T>()
+where
+ T: Trait<()>,
+ <T as Trait<()>>::Output: Sized,
+{
+}
+
+fn g<T>()
+where
+ T: Trait<Unit>,
+ <T as Trait<()>>::Output: Sized,
+{
+}
+
+fn h<T>()
+where
+ T: Trait<()>,
+ <T as Trait<Unit>>::Output: Sized,
+{
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/normalize-param-env-2.rs b/tests/ui/traits/next-solver/normalize-param-env-2.rs
new file mode 100644
index 000000000..ce084651b
--- /dev/null
+++ b/tests/ui/traits/next-solver/normalize-param-env-2.rs
@@ -0,0 +1,26 @@
+// check-pass
+// compile-flags: -Znext-solver
+// Issue 92505
+
+trait A<T> {
+ type I;
+
+ fn f()
+ where
+ Self::I: A<T>,
+ {
+ }
+}
+
+impl<T> A<T> for () {
+ type I = ();
+
+ fn f()
+ where
+ Self::I: A<T>,
+ {
+ <() as A<T>>::f();
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/normalize-param-env-3.rs b/tests/ui/traits/next-solver/normalize-param-env-3.rs
new file mode 100644
index 000000000..e15e1155a
--- /dev/null
+++ b/tests/ui/traits/next-solver/normalize-param-env-3.rs
@@ -0,0 +1,32 @@
+// check-pass
+// compile-flags: -Znext-solver
+// Issue 100177
+
+trait GenericTrait<T> {}
+
+trait Channel<I>: GenericTrait<Self::T> {
+ type T;
+}
+
+trait Sender {
+ type Msg;
+
+ fn send<C>()
+ where
+ C: Channel<Self::Msg>;
+}
+
+impl<T> Sender for T {
+ type Msg = ();
+
+ fn send<C>()
+ where
+ C: Channel<Self::Msg>,
+ {
+ }
+}
+
+// This works
+fn foo<I, C>(ch: C) where C: Channel<I> {}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/normalize-rcvr-for-inherent.rs b/tests/ui/traits/next-solver/normalize-rcvr-for-inherent.rs
new file mode 100644
index 000000000..d308b1695
--- /dev/null
+++ b/tests/ui/traits/next-solver/normalize-rcvr-for-inherent.rs
@@ -0,0 +1,25 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+// Verify that we can assemble inherent impl candidates on a possibly
+// unnormalized self type.
+
+trait Foo {
+ type Assoc;
+}
+impl Foo for i32 {
+ type Assoc = Bar;
+}
+
+struct Bar;
+impl Bar {
+ fn method(&self) {}
+}
+
+fn build<T: Foo>(_: T) -> T::Assoc {
+ todo!()
+}
+
+fn main() {
+ build(1i32).method();
+}
diff --git a/tests/ui/traits/next-solver/normalize-unsize-rhs.rs b/tests/ui/traits/next-solver/normalize-unsize-rhs.rs
new file mode 100644
index 000000000..08bb0cf42
--- /dev/null
+++ b/tests/ui/traits/next-solver/normalize-unsize-rhs.rs
@@ -0,0 +1,22 @@
+// compile-flags: -Znext-solver
+// check-pass
+#![feature(trait_upcasting)]
+
+trait A {}
+trait B: A {}
+
+impl A for usize {}
+impl B for usize {}
+
+trait Mirror {
+ type Assoc: ?Sized;
+}
+
+impl<T: ?Sized> Mirror for T {
+ type Assoc = T;
+}
+
+fn main() {
+ let x = Box::new(1usize) as Box<<dyn B as Mirror>::Assoc>;
+ let y = x as Box<<dyn A as Mirror>::Assoc>;
+}
diff --git a/tests/ui/traits/next-solver/normalized-const-built-in-op.rs b/tests/ui/traits/next-solver/normalized-const-built-in-op.rs
new file mode 100644
index 000000000..0fffe7b43
--- /dev/null
+++ b/tests/ui/traits/next-solver/normalized-const-built-in-op.rs
@@ -0,0 +1,11 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+const fn foo() {
+ let mut x = [1, 2, 3];
+ // We need to fix up `<<[i32; 3] as Index<usize>>::Output as AddAssign>`
+ // to be treated like a built-in operation.
+ x[1] += 5;
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/normalizes_to_ignores_unnormalizable_candidate.rs b/tests/ui/traits/next-solver/normalizes_to_ignores_unnormalizable_candidate.rs
new file mode 100644
index 000000000..7dc87dacc
--- /dev/null
+++ b/tests/ui/traits/next-solver/normalizes_to_ignores_unnormalizable_candidate.rs
@@ -0,0 +1,40 @@
+// [no_self_infer] check-pass
+// compile-flags: -Znext-solver
+// revisions: self_infer no_self_infer
+
+// checks that the new solver is smart enough to infer `?0 = U` when solving:
+// `normalizes-to(<Vec<?0> as Trait>::Assoc, u8)`
+// with `normalizes-to(<Vec<U> as Trait>::Assoc, u8)` in the paramenv even when
+// there is a separate `Vec<T>: Trait` bound in the paramenv.
+//
+// FIXME(-Znext-solver)
+// This could also compile for `normalizes-to(<?0 as Trait>::Assoc, u8)` but
+// we currently immediately consider a goal ambiguous if the self type is an
+// inference variable.
+
+trait Trait {
+ type Assoc;
+}
+
+fn foo<T: Trait<Assoc = u8>>(x: T) {}
+
+#[cfg(self_infer)]
+fn unconstrained<T>() -> T {
+ todo!()
+}
+
+#[cfg(no_self_infer)]
+fn unconstrained<T>() -> Vec<T> {
+ todo!()
+}
+
+fn bar<T, U>()
+where
+ Vec<T>: Trait,
+ Vec<U>: Trait<Assoc = u8>,
+{
+ foo(unconstrained())
+ //[self_infer]~^ ERROR type annotations needed
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/normalizes_to_ignores_unnormalizable_candidate.self_infer.stderr b/tests/ui/traits/next-solver/normalizes_to_ignores_unnormalizable_candidate.self_infer.stderr
new file mode 100644
index 000000000..c1a8b74df
--- /dev/null
+++ b/tests/ui/traits/next-solver/normalizes_to_ignores_unnormalizable_candidate.self_infer.stderr
@@ -0,0 +1,22 @@
+error[E0283]: type annotations needed
+ --> $DIR/normalizes_to_ignores_unnormalizable_candidate.rs:36:5
+ |
+LL | foo(unconstrained())
+ | ^^^ --------------- type must be known at this point
+ | |
+ | cannot infer type of the type parameter `T` declared on the function `foo`
+ |
+ = note: cannot satisfy `_: Trait`
+note: required by a bound in `foo`
+ --> $DIR/normalizes_to_ignores_unnormalizable_candidate.rs:19:11
+ |
+LL | fn foo<T: Trait<Assoc = u8>>(x: T) {}
+ | ^^^^^^^^^^^^^^^^^ required by this bound in `foo`
+help: consider specifying the generic argument
+ |
+LL | foo::<T>(unconstrained())
+ | +++++
+
+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/object-soundness-requires-generalization.rs b/tests/ui/traits/next-solver/object-soundness-requires-generalization.rs
new file mode 100644
index 000000000..6e709d9ae
--- /dev/null
+++ b/tests/ui/traits/next-solver/object-soundness-requires-generalization.rs
@@ -0,0 +1,20 @@
+// compile-flags: -Znext-solver
+// ignore-test
+
+trait Trait {
+ type Gat<'lt>;
+}
+impl Trait for u8 {
+ type Gat<'lt> = u8;
+}
+
+fn test<T: Trait, F: FnOnce(<T as Trait>::Gat<'_>) -> S + ?Sized, S>() {}
+
+fn main() {
+ // Proving `dyn FnOnce: FnOnce` requires making sure that all of the supertraits
+ // of the trait and associated type bounds hold. We check this in
+ // `predicates_for_object_candidate`, and eagerly replace projections using equality
+ // which may generalize a type and emit a nested AliasRelate goal. Make sure that
+ // we don't ICE in that case, and bubble that goal up to the caller.
+ test::<u8, dyn FnOnce(<u8 as Trait>::Gat<'_>) + 'static, _>();
+}
diff --git a/tests/ui/traits/next-solver/object-unsafety.rs b/tests/ui/traits/next-solver/object-unsafety.rs
new file mode 100644
index 000000000..cfa53948b
--- /dev/null
+++ b/tests/ui/traits/next-solver/object-unsafety.rs
@@ -0,0 +1,27 @@
+// compile-flags: -Znext-solver
+
+trait Setup {
+ type From: Copy;
+}
+
+fn copy<U: Setup + ?Sized>(from: &U::From) -> U::From {
+ *from
+}
+
+pub fn copy_any<T>(t: &T) -> T {
+ copy::<dyn Setup<From=T>>(t)
+ //~^ ERROR the type `&<dyn Setup<From = T> as Setup>::From` is not well-formed
+ //~| ERROR the trait bound `dyn Setup<From = T>: Setup` is not satisfied
+ //~| ERROR mismatched types
+ //~| ERROR the type `<dyn Setup<From = T> as Setup>::From` is not well-formed
+ //~| ERROR the size for values of type `<dyn Setup<From = T> as Setup>::From` cannot be known at compilation time
+
+ // FIXME(-Znext-solver): These error messages are horrible and some of them
+ // are even simple fallout from previous error.
+}
+
+fn main() {
+ let x = String::from("Hello, world");
+ let y = copy_any(&x);
+ println!("{y}");
+}
diff --git a/tests/ui/traits/next-solver/object-unsafety.stderr b/tests/ui/traits/next-solver/object-unsafety.stderr
new file mode 100644
index 000000000..ee38c256e
--- /dev/null
+++ b/tests/ui/traits/next-solver/object-unsafety.stderr
@@ -0,0 +1,64 @@
+error[E0277]: the trait bound `dyn Setup<From = T>: Setup` is not satisfied
+ --> $DIR/object-unsafety.rs:12:12
+ |
+LL | copy::<dyn Setup<From=T>>(t)
+ | ^^^^^^^^^^^^^^^^^ the trait `Setup` is not implemented for `dyn Setup<From = T>`
+ |
+note: required by a bound in `copy`
+ --> $DIR/object-unsafety.rs:7:12
+ |
+LL | fn copy<U: Setup + ?Sized>(from: &U::From) -> U::From {
+ | ^^^^^ required by this bound in `copy`
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+ |
+LL | pub fn copy_any<T>(t: &T) -> T where dyn Setup<From = T>: Setup {
+ | ++++++++++++++++++++++++++++++++
+
+error: the type `&<dyn Setup<From = T> as Setup>::From` is not well-formed
+ --> $DIR/object-unsafety.rs:12:31
+ |
+LL | copy::<dyn Setup<From=T>>(t)
+ | ^
+
+error[E0308]: mismatched types
+ --> $DIR/object-unsafety.rs:12:31
+ |
+LL | copy::<dyn Setup<From=T>>(t)
+ | ------------------------- ^ types differ
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected reference `&<dyn Setup<From = T> as Setup>::From`
+ found reference `&T`
+note: function defined here
+ --> $DIR/object-unsafety.rs:7:4
+ |
+LL | fn copy<U: Setup + ?Sized>(from: &U::From) -> U::From {
+ | ^^^^ --------------
+
+error: the type `<dyn Setup<From = T> as Setup>::From` is not well-formed
+ --> $DIR/object-unsafety.rs:12:5
+ |
+LL | copy::<dyn Setup<From=T>>(t)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the size for values of type `<dyn Setup<From = T> as Setup>::From` cannot be known at compilation time
+ --> $DIR/object-unsafety.rs:12:5
+ |
+LL | copy::<dyn Setup<From=T>>(t)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^---
+ | |
+ | doesn't have a size known at compile-time
+ | this returned value is of type `<dyn Setup<From = T> as Setup>::From`
+ |
+ = help: the trait `Sized` is not implemented for `<dyn Setup<From = T> as Setup>::From`
+ = note: the return type of a function must have a statically known size
+help: consider further restricting the associated type
+ |
+LL | pub fn copy_any<T>(t: &T) -> T where <dyn Setup<From = T> as Setup>::From: Sized {
+ | +++++++++++++++++++++++++++++++++++++++++++++++++
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/next-solver/opportunistic-region-resolve.rs b/tests/ui/traits/next-solver/opportunistic-region-resolve.rs
new file mode 100644
index 000000000..d852332d0
--- /dev/null
+++ b/tests/ui/traits/next-solver/opportunistic-region-resolve.rs
@@ -0,0 +1,19 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+#![feature(rustc_attrs)]
+
+#[rustc_coinductive]
+trait Trait {}
+
+#[rustc_coinductive]
+trait Indirect {}
+impl<T: Trait + ?Sized> Indirect for T {}
+
+impl<'a> Trait for &'a () where &'a (): Indirect {}
+
+fn impls_trait<T: Trait>() {}
+
+fn main() {
+ impls_trait::<&'static ()>();
+}
diff --git a/tests/ui/traits/next-solver/overflow/exponential-trait-goals.rs b/tests/ui/traits/next-solver/overflow/exponential-trait-goals.rs
new file mode 100644
index 000000000..a465bcecf
--- /dev/null
+++ b/tests/ui/traits/next-solver/overflow/exponential-trait-goals.rs
@@ -0,0 +1,19 @@
+// compile-flags: -Znext-solver
+
+trait Trait {}
+
+struct W<T>(T);
+
+impl<T, U> Trait for W<(W<T>, W<U>)>
+where
+ W<T>: Trait,
+ W<U>: Trait,
+{
+}
+
+fn impls<T: Trait>() {}
+
+fn main() {
+ impls::<W<_>>();
+ //~^ ERROR overflow evaluating the requirement `W<_>: Trait`
+}
diff --git a/tests/ui/traits/next-solver/overflow/exponential-trait-goals.stderr b/tests/ui/traits/next-solver/overflow/exponential-trait-goals.stderr
new file mode 100644
index 000000000..90b54b1e7
--- /dev/null
+++ b/tests/ui/traits/next-solver/overflow/exponential-trait-goals.stderr
@@ -0,0 +1,16 @@
+error[E0275]: overflow evaluating the requirement `W<_>: Trait`
+ --> $DIR/exponential-trait-goals.rs:17:13
+ |
+LL | impls::<W<_>>();
+ | ^^^^
+ |
+ = 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<T: Trait>() {}
+ | ^^^^^ required by this bound in `impls`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/next-solver/overflow/global-cache.rs b/tests/ui/traits/next-solver/overflow/global-cache.rs
new file mode 100644
index 000000000..fe4032ca6
--- /dev/null
+++ b/tests/ui/traits/next-solver/overflow/global-cache.rs
@@ -0,0 +1,23 @@
+// compile-flags: -Znext-solver
+
+// Check that we consider the reached depth of global cache
+// entries when detecting overflow. We would otherwise be unstable
+// wrt to incremental compilation.
+#![recursion_limit = "9"]
+
+trait Trait {}
+
+struct Inc<T>(T);
+
+impl<T: Trait> Trait for Inc<T> {}
+impl Trait for () {}
+
+fn impls_trait<T: Trait>() {}
+
+type Four<T> = Inc<Inc<Inc<Inc<T>>>>;
+
+fn main() {
+ impls_trait::<Four<Four<()>>>();
+ impls_trait::<Four<Four<Four<Four<()>>>>>();
+ //~^ ERROR overflow evaluating the requirement
+}
diff --git a/tests/ui/traits/next-solver/overflow/global-cache.stderr b/tests/ui/traits/next-solver/overflow/global-cache.stderr
new file mode 100644
index 000000000..676166193
--- /dev/null
+++ b/tests/ui/traits/next-solver/overflow/global-cache.stderr
@@ -0,0 +1,16 @@
+error[E0275]: overflow evaluating the requirement `Inc<Inc<Inc<Inc<Inc<Inc<Inc<...>>>>>>>: Trait`
+ --> $DIR/global-cache.rs:21:19
+ |
+LL | impls_trait::<Four<Four<Four<Four<()>>>>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: consider increasing the recursion limit by adding a `#![recursion_limit = "18"]` attribute to your crate (`global_cache`)
+note: required by a bound in `impls_trait`
+ --> $DIR/global-cache.rs:15:19
+ |
+LL | fn impls_trait<T: Trait>() {}
+ | ^^^^^ required by this bound in `impls_trait`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/next-solver/overflow/recursion-limit-normalizes-to-constraints.rs b/tests/ui/traits/next-solver/overflow/recursion-limit-normalizes-to-constraints.rs
new file mode 100644
index 000000000..03ef93dc2
--- /dev/null
+++ b/tests/ui/traits/next-solver/overflow/recursion-limit-normalizes-to-constraints.rs
@@ -0,0 +1,25 @@
+// compile-flags: -Znext-solver=coherence
+// check-pass
+
+// A regression test for trait-system-refactor-initiative#70.
+
+trait Trait {
+ type Assoc;
+}
+
+struct W<T: ?Sized>(*mut T);
+impl<T: ?Sized> Trait for W<W<T>>
+where
+ W<T>: Trait,
+{
+ type Assoc = ();
+}
+
+trait NoOverlap {}
+impl<T: Trait<Assoc = u32>> NoOverlap for T {}
+// `Projection(<W<_> as Trait>::Assoc, u32)` should result in error even
+// though applying the impl results in overflow. This is necessary to match
+// the behavior of the old solver.
+impl<T: ?Sized> NoOverlap for W<T> {}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/overflow/recursion-limit-zero-issue-115351.rs b/tests/ui/traits/next-solver/overflow/recursion-limit-zero-issue-115351.rs
new file mode 100644
index 000000000..52a17a142
--- /dev/null
+++ b/tests/ui/traits/next-solver/overflow/recursion-limit-zero-issue-115351.rs
@@ -0,0 +1,12 @@
+//~ ERROR overflow evaluating the requirement `Self well-formed`
+//~| ERROR overflow evaluating the requirement `Self: Trait`
+
+// This is a non-regression test for issue #115351, where a recursion limit of 0 caused an ICE.
+// compile-flags: -Znext-solver --crate-type=lib
+// check-fail
+
+#![recursion_limit = "0"]
+trait Trait {}
+impl Trait for u32 {}
+//~^ ERROR overflow evaluating the requirement `u32: Trait`
+//~| ERROR overflow evaluating the requirement `u32 well-formed`
diff --git a/tests/ui/traits/next-solver/overflow/recursion-limit-zero-issue-115351.stderr b/tests/ui/traits/next-solver/overflow/recursion-limit-zero-issue-115351.stderr
new file mode 100644
index 000000000..16b25d90a
--- /dev/null
+++ b/tests/ui/traits/next-solver/overflow/recursion-limit-zero-issue-115351.stderr
@@ -0,0 +1,27 @@
+error[E0275]: overflow evaluating the requirement `Self: Trait`
+ |
+ = help: consider increasing the recursion limit by adding a `#![recursion_limit = "2"]` attribute to your crate (`recursion_limit_zero_issue_115351`)
+
+error[E0275]: overflow evaluating the requirement `Self well-formed`
+ |
+ = help: consider increasing the recursion limit by adding a `#![recursion_limit = "2"]` attribute to your crate (`recursion_limit_zero_issue_115351`)
+
+error[E0275]: overflow evaluating the requirement `u32: Trait`
+ --> $DIR/recursion-limit-zero-issue-115351.rs:10:16
+ |
+LL | impl Trait for u32 {}
+ | ^^^
+ |
+ = help: consider increasing the recursion limit by adding a `#![recursion_limit = "2"]` attribute to your crate (`recursion_limit_zero_issue_115351`)
+
+error[E0275]: overflow evaluating the requirement `u32 well-formed`
+ --> $DIR/recursion-limit-zero-issue-115351.rs:10:16
+ |
+LL | impl Trait for u32 {}
+ | ^^^
+ |
+ = help: consider increasing the recursion limit by adding a `#![recursion_limit = "2"]` attribute to your crate (`recursion_limit_zero_issue_115351`)
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs
new file mode 100644
index 000000000..327ef865d
--- /dev/null
+++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs
@@ -0,0 +1,20 @@
+// compile-flags: -Znext-solver
+
+trait Foo1 {
+ type Assoc1;
+}
+
+trait Foo2 {
+ type Assoc2;
+}
+
+trait Bar {}
+fn needs_bar<S: Bar>() {}
+
+fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() {
+ needs_bar::<T::Assoc1>();
+ //~^ ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1: Bar`
+ //~| ERROR overflow evaluating the requirement `<T as Foo2>::Assoc2`
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr
new file mode 100644
index 000000000..eda62b99c
--- /dev/null
+++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr
@@ -0,0 +1,24 @@
+error[E0275]: overflow evaluating the requirement `<T as Foo1>::Assoc1: Bar`
+ --> $DIR/recursive-self-normalization-2.rs:15:17
+ |
+LL | needs_bar::<T::Assoc1>();
+ | ^^^^^^^^^
+ |
+ = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization_2`)
+note: required by a bound in `needs_bar`
+ --> $DIR/recursive-self-normalization-2.rs:12:17
+ |
+LL | fn needs_bar<S: Bar>() {}
+ | ^^^ required by this bound in `needs_bar`
+
+error[E0275]: overflow evaluating the requirement `<T as Foo2>::Assoc2`
+ --> $DIR/recursive-self-normalization-2.rs:15:5
+ |
+LL | needs_bar::<T::Assoc1>();
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization_2`)
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs
new file mode 100644
index 000000000..f45d208e6
--- /dev/null
+++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs
@@ -0,0 +1,16 @@
+// compile-flags: -Znext-solver
+
+trait Foo {
+ type Assoc;
+}
+
+trait Bar {}
+fn needs_bar<S: Bar>() {}
+
+fn test<T: Foo<Assoc = <T as Foo>::Assoc>>() {
+ needs_bar::<T::Assoc>();
+ //~^ ERROR overflow evaluating the requirement `<T as Foo>::Assoc: Bar`
+ //~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc` [E0275]
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr
new file mode 100644
index 000000000..b0a0a6976
--- /dev/null
+++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr
@@ -0,0 +1,24 @@
+error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc: Bar`
+ --> $DIR/recursive-self-normalization.rs:11:17
+ |
+LL | needs_bar::<T::Assoc>();
+ | ^^^^^^^^
+ |
+ = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization`)
+note: required by a bound in `needs_bar`
+ --> $DIR/recursive-self-normalization.rs:8:17
+ |
+LL | fn needs_bar<S: Bar>() {}
+ | ^^^ required by this bound in `needs_bar`
+
+error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc`
+ --> $DIR/recursive-self-normalization.rs:11:5
+ |
+LL | needs_bar::<T::Assoc>();
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization`)
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/next-solver/param-candidate-doesnt-shadow-project.rs b/tests/ui/traits/next-solver/param-candidate-doesnt-shadow-project.rs
new file mode 100644
index 000000000..f67b073c5
--- /dev/null
+++ b/tests/ui/traits/next-solver/param-candidate-doesnt-shadow-project.rs
@@ -0,0 +1,25 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+trait Foo {
+ type Assoc;
+}
+
+trait Bar {}
+
+impl<T> Foo for T {
+ type Assoc = i32;
+}
+
+impl<T> Bar for T where T: Foo<Assoc = i32> {}
+
+fn require_bar<T: Bar>() {}
+
+fn foo<T: Foo>() {
+ // Unlike the classic solver, `<T as Foo>::Assoc = _` will still project
+ // down to `i32` even though there's a param-env candidate here, since we
+ // don't assemble any param-env projection candidates for `T: Foo` alone.
+ require_bar::<T>();
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/param-discr-kind.rs b/tests/ui/traits/next-solver/param-discr-kind.rs
new file mode 100644
index 000000000..c66b0b9f4
--- /dev/null
+++ b/tests/ui/traits/next-solver/param-discr-kind.rs
@@ -0,0 +1,8 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+fn foo<T>(x: T) {
+ std::mem::discriminant(&x);
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/pointee.rs b/tests/ui/traits/next-solver/pointee.rs
new file mode 100644
index 000000000..a56df549a
--- /dev/null
+++ b/tests/ui/traits/next-solver/pointee.rs
@@ -0,0 +1,21 @@
+// compile-flags: -Znext-solver
+// check-pass
+#![feature(ptr_metadata)]
+
+use std::ptr::{DynMetadata, Pointee};
+
+trait Trait<U> {}
+struct MyDst<T: ?Sized>(T);
+
+fn meta_is<T: Pointee<Metadata = U> + ?Sized, U>() {}
+
+fn works<T>() {
+ meta_is::<T, ()>();
+ meta_is::<[T], usize>();
+ meta_is::<str, usize>();
+ meta_is::<dyn Trait<T>, DynMetadata<dyn Trait<T>>>();
+ meta_is::<MyDst<T>, ()>();
+ meta_is::<((((([u8],),),),),), usize>();
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/pointer-like.rs b/tests/ui/traits/next-solver/pointer-like.rs
new file mode 100644
index 000000000..f6cc718c6
--- /dev/null
+++ b/tests/ui/traits/next-solver/pointer-like.rs
@@ -0,0 +1,14 @@
+// compile-flags: -Znext-solver
+
+#![feature(pointer_like_trait)]
+
+use std::marker::PointerLike;
+
+fn require_(_: impl PointerLike) {}
+
+fn main() {
+ require_(1usize);
+ require_(1u16);
+ //~^ ERROR `u16` needs to have the same ABI as a pointer
+ require_(&1i16);
+}
diff --git a/tests/ui/traits/next-solver/pointer-like.stderr b/tests/ui/traits/next-solver/pointer-like.stderr
new file mode 100644
index 000000000..4b624fd0d
--- /dev/null
+++ b/tests/ui/traits/next-solver/pointer-like.stderr
@@ -0,0 +1,24 @@
+error[E0277]: `u16` needs to have the same ABI as a pointer
+ --> $DIR/pointer-like.rs:11:14
+ |
+LL | require_(1u16);
+ | -------- ^^^^ the trait `PointerLike` is not implemented for `u16`
+ | |
+ | required by a bound introduced by this call
+ |
+ = note: the trait bound `u16: PointerLike` is not satisfied
+note: required by a bound in `require_`
+ --> $DIR/pointer-like.rs:7:21
+ |
+LL | fn require_(_: impl PointerLike) {}
+ | ^^^^^^^^^^^ required by this bound in `require_`
+help: consider borrowing here
+ |
+LL | require_(&1u16);
+ | +
+LL | require_(&mut 1u16);
+ | ++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/next-solver/prefer-candidate-no-constraints.rs b/tests/ui/traits/next-solver/prefer-candidate-no-constraints.rs
new file mode 100644
index 000000000..a47f819f1
--- /dev/null
+++ b/tests/ui/traits/next-solver/prefer-candidate-no-constraints.rs
@@ -0,0 +1,22 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+trait Foo {}
+
+impl<T> Foo for T {}
+
+trait Bar {}
+
+struct Wrapper<'a, T>(&'a T);
+
+impl<'a, T> Bar for Wrapper<'a, T> where &'a T: Foo {}
+// We need to satisfy `&'a T: Foo` when checking that this impl is WF
+// that can either be satisfied via the param-env, or via an impl.
+//
+// When satisfied via the param-env, since each lifetime is canonicalized
+// separately, we end up getting extra region constraints.
+//
+// However, when satisfied via the impl, there are no region constraints,
+// and we can short-circuit a response with no external constraints.
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/prefer-param-env-on-ambiguity.rs b/tests/ui/traits/next-solver/prefer-param-env-on-ambiguity.rs
new file mode 100644
index 000000000..f8c0223e1
--- /dev/null
+++ b/tests/ui/traits/next-solver/prefer-param-env-on-ambiguity.rs
@@ -0,0 +1,10 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+trait Foo<'a> {}
+trait Bar<'a> {}
+
+impl<'a, T: Bar<'a>> Foo<'a> for T {}
+impl<T> Bar<'static> for T {}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/projection-discr-kind.rs b/tests/ui/traits/next-solver/projection-discr-kind.rs
new file mode 100644
index 000000000..bf557f863
--- /dev/null
+++ b/tests/ui/traits/next-solver/projection-discr-kind.rs
@@ -0,0 +1,18 @@
+// compile-flags: -Znext-solver
+
+// Check that `<T::Assoc as DiscriminantKind>::Discriminant` doesn't normalize
+// to itself and cause overflow/ambiguity.
+
+trait Foo {
+ type Assoc;
+}
+
+trait Bar {}
+fn needs_bar(_: impl Bar) {}
+
+fn foo<T: Foo>(x: T::Assoc) {
+ needs_bar(std::mem::discriminant(&x));
+ //~^ ERROR the trait bound `Discriminant<<T as Foo>::Assoc>: Bar` is not satisfied
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/projection-discr-kind.stderr b/tests/ui/traits/next-solver/projection-discr-kind.stderr
new file mode 100644
index 000000000..69999c755
--- /dev/null
+++ b/tests/ui/traits/next-solver/projection-discr-kind.stderr
@@ -0,0 +1,22 @@
+error[E0277]: the trait bound `Discriminant<<T as Foo>::Assoc>: Bar` is not satisfied
+ --> $DIR/projection-discr-kind.rs:14:15
+ |
+LL | needs_bar(std::mem::discriminant(&x));
+ | --------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `Discriminant<<T as Foo>::Assoc>`
+ | |
+ | required by a bound introduced by this call
+ |
+help: this trait has no implementations, consider adding one
+ --> $DIR/projection-discr-kind.rs:10:1
+ |
+LL | trait Bar {}
+ | ^^^^^^^^^
+note: required by a bound in `needs_bar`
+ --> $DIR/projection-discr-kind.rs:11:22
+ |
+LL | fn needs_bar(_: impl Bar) {}
+ | ^^^ required by this bound in `needs_bar`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/next-solver/projection/param-env-trait-candidate-1.rs b/tests/ui/traits/next-solver/projection/param-env-trait-candidate-1.rs
new file mode 100644
index 000000000..b337c0673
--- /dev/null
+++ b/tests/ui/traits/next-solver/projection/param-env-trait-candidate-1.rs
@@ -0,0 +1,14 @@
+// check-pass
+// compile-flags: -Znext-solver
+
+// See https://github.com/rust-lang/trait-system-refactor-initiative/issues/1
+// a minimization of a pattern in core.
+fn next<T: Iterator<Item = U>, U>(t: &mut T) -> Option<U> {
+ t.next()
+}
+
+fn foo<T: Iterator>(t: &mut T) {
+ let _: Option<T::Item> = next(t);
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/projection/param-env-trait-candidate-2.rs b/tests/ui/traits/next-solver/projection/param-env-trait-candidate-2.rs
new file mode 100644
index 000000000..db8dc1eb9
--- /dev/null
+++ b/tests/ui/traits/next-solver/projection/param-env-trait-candidate-2.rs
@@ -0,0 +1,29 @@
+// check-pass
+// compile-flags: -Znext-solver
+
+// See https://github.com/rust-lang/trait-system-refactor-initiative/issues/1,
+// a minimization of a pattern in core.
+
+trait Iterator {
+ type Item;
+}
+
+struct Flatten<I>(I);
+
+impl<I, U> Iterator for Flatten<I>
+where
+ I: Iterator<Item = U>,
+{
+ type Item = U;
+}
+
+fn needs_iterator<I: Iterator>() {}
+
+fn environment<J>()
+where
+ J: Iterator,
+{
+ needs_iterator::<Flatten<J>>();
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/slice-match-byte-lit.rs b/tests/ui/traits/next-solver/slice-match-byte-lit.rs
new file mode 100644
index 000000000..1edc9f1e8
--- /dev/null
+++ b/tests/ui/traits/next-solver/slice-match-byte-lit.rs
@@ -0,0 +1,11 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+fn test(s: &[u8]) {
+ match &s[0..3] {
+ b"uwu" => {}
+ _ => {}
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/specialization-transmute.rs b/tests/ui/traits/next-solver/specialization-transmute.rs
new file mode 100644
index 000000000..58b62f52d
--- /dev/null
+++ b/tests/ui/traits/next-solver/specialization-transmute.rs
@@ -0,0 +1,28 @@
+// compile-flags: -Znext-solver
+
+#![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
+
+trait Default {
+ type Id;
+
+ fn intu(&self) -> &Self::Id;
+}
+
+impl<T> Default for T {
+ default type Id = T; //~ ERROR type annotations needed
+ // This will be fixed by #111994
+ fn intu(&self) -> &Self::Id { //~ ERROR type annotations needed
+ self
+ }
+}
+
+fn transmute<T: Default<Id = U>, U: Copy>(t: T) -> U {
+ *t.intu()
+}
+
+use std::num::NonZeroU8;
+fn main() {
+ let s = transmute::<u8, Option<NonZeroU8>>(0); // this call should then error
+ assert_eq!(s, None);
+}
diff --git a/tests/ui/traits/next-solver/specialization-transmute.stderr b/tests/ui/traits/next-solver/specialization-transmute.stderr
new file mode 100644
index 000000000..eaf32a475
--- /dev/null
+++ b/tests/ui/traits/next-solver/specialization-transmute.stderr
@@ -0,0 +1,26 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/specialization-transmute.rs:3:12
+ |
+LL | #![feature(specialization)]
+ | ^^^^^^^^^^^^^^
+ |
+ = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+ = help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
+
+error[E0284]: type annotations needed: cannot satisfy `<T as Default>::Id normalizes-to _`
+ --> $DIR/specialization-transmute.rs:15:23
+ |
+LL | fn intu(&self) -> &Self::Id {
+ | ^^^^^^^^^ cannot satisfy `<T as Default>::Id normalizes-to _`
+
+error[E0282]: type annotations needed
+ --> $DIR/specialization-transmute.rs:13:23
+ |
+LL | default type Id = T;
+ | ^ cannot infer type for associated type `<T as Default>::Id`
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+Some errors have detailed explanations: E0282, E0284.
+For more information about an error, try `rustc --explain E0282`.
diff --git a/tests/ui/traits/next-solver/specialization-unconstrained.rs b/tests/ui/traits/next-solver/specialization-unconstrained.rs
new file mode 100644
index 000000000..950fb1512
--- /dev/null
+++ b/tests/ui/traits/next-solver/specialization-unconstrained.rs
@@ -0,0 +1,22 @@
+// compile-flags: -Znext-solver
+
+#![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
+
+// Do not treat the RHS of a projection-goal as an unconstrained `Certainty::Yes` response
+// if the impl is still further specializable.
+
+trait Default {
+ type Id;
+}
+
+impl<T> Default for T {
+ default type Id = T; //~ ERROR type annotations needed
+}
+
+fn test<T: Default<Id = U>, U>() {}
+
+fn main() {
+ test::<u32, ()>();
+ //~^ ERROR cannot satisfy `<u32 as Default>::Id == ()`
+}
diff --git a/tests/ui/traits/next-solver/specialization-unconstrained.stderr b/tests/ui/traits/next-solver/specialization-unconstrained.stderr
new file mode 100644
index 000000000..ed4dafa14
--- /dev/null
+++ b/tests/ui/traits/next-solver/specialization-unconstrained.stderr
@@ -0,0 +1,32 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/specialization-unconstrained.rs:3:12
+ |
+LL | #![feature(specialization)]
+ | ^^^^^^^^^^^^^^
+ |
+ = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+ = help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
+
+error[E0284]: type annotations needed: cannot satisfy `<u32 as Default>::Id == ()`
+ --> $DIR/specialization-unconstrained.rs:20:5
+ |
+LL | test::<u32, ()>();
+ | ^^^^^^^^^^^^^^^ cannot satisfy `<u32 as Default>::Id == ()`
+ |
+note: required by a bound in `test`
+ --> $DIR/specialization-unconstrained.rs:17:20
+ |
+LL | fn test<T: Default<Id = U>, U>() {}
+ | ^^^^^^ required by this bound in `test`
+
+error[E0282]: type annotations needed
+ --> $DIR/specialization-unconstrained.rs:14:22
+ |
+LL | default type Id = T;
+ | ^ cannot infer type for associated type `<T as Default>::Id`
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+Some errors have detailed explanations: E0282, E0284.
+For more information about an error, try `rustc --explain E0282`.
diff --git a/tests/ui/traits/next-solver/stall-num-var-auto-trait.fallback.stderr b/tests/ui/traits/next-solver/stall-num-var-auto-trait.fallback.stderr
new file mode 100644
index 000000000..2e3c22c8d
--- /dev/null
+++ b/tests/ui/traits/next-solver/stall-num-var-auto-trait.fallback.stderr
@@ -0,0 +1,17 @@
+error[E0277]: the trait bound `i32: Foo` is not satisfied
+ --> $DIR/stall-num-var-auto-trait.rs:18:15
+ |
+LL | needs_foo(x);
+ | --------- ^ the trait `Foo` is not implemented for `i32`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `needs_foo`
+ --> $DIR/stall-num-var-auto-trait.rs:14:22
+ |
+LL | fn needs_foo(x: impl Foo) {}
+ | ^^^ required by this bound in `needs_foo`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/next-solver/stall-num-var-auto-trait.rs b/tests/ui/traits/next-solver/stall-num-var-auto-trait.rs
new file mode 100644
index 000000000..f5bf985cd
--- /dev/null
+++ b/tests/ui/traits/next-solver/stall-num-var-auto-trait.rs
@@ -0,0 +1,25 @@
+// compile-flags: -Znext-solver
+// revisions: fallback constrain
+//[constrain] check-pass
+
+// Tests that we stall the `{integer}: Foo` obligation until after we
+// constrain the int type (or fallback occurs).
+
+#![feature(negative_impls, auto_traits)]
+
+auto trait Foo {}
+
+impl !Foo for i32 {}
+
+fn needs_foo(x: impl Foo) {}
+
+fn main() {
+ let mut x = 0;
+ needs_foo(x);
+ //[fallback]~^ ERROR the trait bound `i32: Foo` is not satisfied
+
+ #[cfg(constrain)]
+ {
+ x = 1u64;
+ }
+}
diff --git a/tests/ui/traits/next-solver/structural-resolve-field.rs b/tests/ui/traits/next-solver/structural-resolve-field.rs
new file mode 100644
index 000000000..b247e2375
--- /dev/null
+++ b/tests/ui/traits/next-solver/structural-resolve-field.rs
@@ -0,0 +1,13 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+#[derive(Default)]
+struct Foo {
+ x: i32,
+}
+
+fn main() {
+ let mut xs = <[Foo; 1]>::default();
+ xs[0].x = 1;
+ (&mut xs[0]).x = 2;
+}
diff --git a/tests/ui/traits/next-solver/tait-eq-proj-2.rs b/tests/ui/traits/next-solver/tait-eq-proj-2.rs
new file mode 100644
index 000000000..a3df053dd
--- /dev/null
+++ b/tests/ui/traits/next-solver/tait-eq-proj-2.rs
@@ -0,0 +1,23 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+
+// Similar to tests/ui/traits/next-solver/tait-eq-proj.rs
+// but check the alias-sub relation in the other direction.
+
+type Tait = impl Iterator<Item = impl Sized>;
+
+fn mk<T>() -> T {
+ todo!()
+}
+
+fn a(_: Tait) {
+ let x: Tait = mk();
+ let mut array = mk();
+ let mut z = IntoIterator::into_iter(array);
+ z = x;
+ array = [0i32; 32];
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/tait-eq-proj.rs b/tests/ui/traits/next-solver/tait-eq-proj.rs
new file mode 100644
index 000000000..871e8e1e9
--- /dev/null
+++ b/tests/ui/traits/next-solver/tait-eq-proj.rs
@@ -0,0 +1,35 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+
+type Tait = impl Iterator<Item = impl Sized>;
+
+/*
+
+Consider the goal - AliasRelate(Tait, <[i32; 32] as IntoIterator>::IntoIter)
+which is registered on the line above.
+
+A. SubstRelate - fails (of course).
+
+B. NormalizesToRhs - Tait normalizes-to <[i32; 32] as IntoIterator>::IntoIter
+ * infer definition - Tait := <[i32; 32] as IntoIterator>::IntoIter
+
+C. NormalizesToLhs - <[i32; 32] as IntoIterator>::IntoIter normalizes-to Tait
+ * Find impl candidate, after substitute - std::array::IntoIter<i32, 32>
+ * Equate std::array::IntoIter<i32, 32> and Tait
+ * infer definition - Tait := std::array::IntoIter<i32, 32>
+
+B and C are not equal, but they are equivalent modulo normalization.
+
+We get around this by evaluating both the NormalizesToRhs and NormalizesToLhs
+goals together. Essentially:
+ A alias-relate B if A normalizes-to B and B normalizes-to A.
+
+*/
+
+fn a(_: Tait) {
+ let _: Tait = IntoIterator::into_iter([0i32; 32]);
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/tait-eq-tait.rs b/tests/ui/traits/next-solver/tait-eq-tait.rs
new file mode 100644
index 000000000..2629a124c
--- /dev/null
+++ b/tests/ui/traits/next-solver/tait-eq-tait.rs
@@ -0,0 +1,18 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+// Not exactly sure if this is the inference behavior we *want*,
+// but it is a side-effect of the lazy normalization of TAITs.
+
+#![feature(type_alias_impl_trait)]
+
+fn mk<T>() -> T {
+ todo!()
+}
+
+fn main() {
+ type Tait = impl Sized;
+ type Tait2 = impl Sized;
+ let x: Tait = 1u32;
+ let y: Tait2 = x;
+}
diff --git a/tests/ui/traits/next-solver/temporary-ambiguity.rs b/tests/ui/traits/next-solver/temporary-ambiguity.rs
new file mode 100644
index 000000000..6102de7e4
--- /dev/null
+++ b/tests/ui/traits/next-solver/temporary-ambiguity.rs
@@ -0,0 +1,22 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+// Checks that we don't explode when we assemble >1 candidate for a goal.
+
+struct Wrapper<T>(T);
+
+trait Foo {}
+
+impl Foo for Wrapper<i32> {}
+
+impl Foo for Wrapper<()> {}
+
+fn needs_foo(_: impl Foo) {}
+
+fn main() {
+ let mut x = Default::default();
+ let w = Wrapper(x);
+ needs_foo(w);
+ x = 1;
+ let _ = x;
+}
diff --git a/tests/ui/traits/next-solver/trait-upcast-lhs-needs-normalization.rs b/tests/ui/traits/next-solver/trait-upcast-lhs-needs-normalization.rs
new file mode 100644
index 000000000..8e0378e94
--- /dev/null
+++ b/tests/ui/traits/next-solver/trait-upcast-lhs-needs-normalization.rs
@@ -0,0 +1,19 @@
+// check-pass
+// compile-flags: -Znext-solver
+#![feature(trait_upcasting)]
+
+pub trait A {}
+pub trait B: A {}
+
+pub trait Mirror {
+ type Assoc: ?Sized;
+}
+impl<T: ?Sized> Mirror for T {
+ type Assoc = T;
+}
+
+pub fn foo<'a>(x: &'a <dyn B + 'static as Mirror>::Assoc) -> &'a (dyn A + 'static) {
+ x
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/try-example.rs b/tests/ui/traits/next-solver/try-example.rs
new file mode 100644
index 000000000..92b0b5978
--- /dev/null
+++ b/tests/ui/traits/next-solver/try-example.rs
@@ -0,0 +1,28 @@
+// check-pass
+// compile-flags: -Znext-solver
+
+use std::error::Error;
+
+fn main() -> Result<(), Box<dyn Error>> {
+ let x: i32 = parse()?;
+ Ok(())
+}
+
+trait Parse {}
+
+impl Parse for i32 {}
+
+#[derive(Debug)]
+struct ParseError;
+
+impl std::fmt::Display for ParseError {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(f, "ParseError")
+ }
+}
+
+impl Error for ParseError {}
+
+fn parse<T: Parse>() -> Result<T, ParseError> {
+ todo!()
+}
diff --git a/tests/ui/traits/next-solver/two-projection-param-candidates-are-ambiguous.rs b/tests/ui/traits/next-solver/two-projection-param-candidates-are-ambiguous.rs
new file mode 100644
index 000000000..d25e372b5
--- /dev/null
+++ b/tests/ui/traits/next-solver/two-projection-param-candidates-are-ambiguous.rs
@@ -0,0 +1,30 @@
+// compile-flags: -Znext-solver
+
+// When we're solving `<T as Foo>::Assoc = i32`, we actually first solve
+// `<T as Foo>::Assoc = ?1t`, then unify `?1t` with `i32`. That goal
+// with the inference variable is ambiguous when there are >1 param-env
+// candidates.
+
+// We don't unify the RHS of a projection goal eagerly when solving, both
+// for caching reasons and partly to make sure that we don't make the new
+// trait solver smarter than it should be.
+
+// This is (as far as I can tell) a forwards-compatible decision, but if you
+// make this test go from fail to pass, be sure you understand the implications!
+
+trait Foo {
+ type Assoc;
+}
+
+trait Bar {}
+
+impl<T> Bar for T where T: Foo<Assoc = i32> {}
+
+fn needs_bar<T: Bar>() {}
+
+fn foo<T: Foo<Assoc = i32> + Foo<Assoc = u32>>() {
+ needs_bar::<T>();
+ //~^ ERROR type annotations needed: cannot satisfy `T: Bar`
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/two-projection-param-candidates-are-ambiguous.stderr b/tests/ui/traits/next-solver/two-projection-param-candidates-are-ambiguous.stderr
new file mode 100644
index 000000000..dfff9f11b
--- /dev/null
+++ b/tests/ui/traits/next-solver/two-projection-param-candidates-are-ambiguous.stderr
@@ -0,0 +1,17 @@
+error[E0283]: type annotations needed: cannot satisfy `T: Bar`
+ --> $DIR/two-projection-param-candidates-are-ambiguous.rs:26:17
+ |
+LL | needs_bar::<T>();
+ | ^
+ |
+ = note: cannot satisfy `T: Bar`
+ = help: the trait `Bar` is implemented for `T`
+note: required by a bound in `needs_bar`
+ --> $DIR/two-projection-param-candidates-are-ambiguous.rs:23:17
+ |
+LL | fn needs_bar<T: Bar>() {}
+ | ^^^ required by this bound in `needs_bar`
+
+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/unevaluated-const-impl-trait-ref.fails.stderr b/tests/ui/traits/next-solver/unevaluated-const-impl-trait-ref.fails.stderr
new file mode 100644
index 000000000..4be90c702
--- /dev/null
+++ b/tests/ui/traits/next-solver/unevaluated-const-impl-trait-ref.fails.stderr
@@ -0,0 +1,18 @@
+error[E0277]: the trait bound `(): Trait<1>` is not satisfied
+ --> $DIR/unevaluated-const-impl-trait-ref.rs:20:13
+ |
+LL | needs::<1>();
+ | ^ the trait `Trait<1>` is not implemented for `()`
+ |
+ = help: the following other types implement trait `Trait<N>`:
+ <() as Trait<0>>
+ <() as Trait<2>>
+note: required by a bound in `needs`
+ --> $DIR/unevaluated-const-impl-trait-ref.rs:10:38
+ |
+LL | fn needs<const N: usize>() where (): Trait<N> {}
+ | ^^^^^^^^ required by this bound in `needs`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/next-solver/unevaluated-const-impl-trait-ref.rs b/tests/ui/traits/next-solver/unevaluated-const-impl-trait-ref.rs
new file mode 100644
index 000000000..77a169d48
--- /dev/null
+++ b/tests/ui/traits/next-solver/unevaluated-const-impl-trait-ref.rs
@@ -0,0 +1,22 @@
+// compile-flags: -Znext-solver
+// revisions: works fails
+//[works] check-pass
+
+trait Trait<const N: usize> {}
+
+impl Trait<{ 1 - 1 }> for () {}
+impl Trait<{ 1 + 1 }> for () {}
+
+fn needs<const N: usize>() where (): Trait<N> {}
+
+#[cfg(works)]
+fn main() {
+ needs::<0>();
+ needs::<2>();
+}
+
+#[cfg(fails)]
+fn main() {
+ needs::<1>();
+ //[fails]~^ ERROR the trait bound `(): Trait<1>` is not satisfied
+}
diff --git a/tests/ui/traits/next-solver/unsafe-auto-trait-impl.rs b/tests/ui/traits/next-solver/unsafe-auto-trait-impl.rs
new file mode 100644
index 000000000..f66bf0b87
--- /dev/null
+++ b/tests/ui/traits/next-solver/unsafe-auto-trait-impl.rs
@@ -0,0 +1,8 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+struct Foo(*mut ());
+
+unsafe impl Sync for Foo {}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/unsize-although-ambiguous.rs b/tests/ui/traits/next-solver/unsize-although-ambiguous.rs
new file mode 100644
index 000000000..8217701b9
--- /dev/null
+++ b/tests/ui/traits/next-solver/unsize-although-ambiguous.rs
@@ -0,0 +1,13 @@
+// check-pass
+// compile-flags: -Znext-solver
+
+use std::fmt::Display;
+
+fn box_dyn_display(_: Box<dyn Display>) {}
+
+fn main() {
+ // During coercion, we don't necessarily know whether `{integer}` implements
+ // `Display`. Before, that would cause us to bail out in the coercion loop when
+ // checking `{integer}: Unsize<dyn Display>`.
+ box_dyn_display(Box::new(1));
+}
diff --git a/tests/ui/traits/next-solver/unsize-good.rs b/tests/ui/traits/next-solver/unsize-good.rs
new file mode 100644
index 000000000..04ebe66f2
--- /dev/null
+++ b/tests/ui/traits/next-solver/unsize-good.rs
@@ -0,0 +1,25 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+#![feature(unsized_tuple_coercion)]
+
+trait Foo {}
+
+impl Foo for i32 {}
+
+fn main() {
+ // Unsizing via struct
+ let _: Box<dyn Foo> = Box::new(1i32);
+
+ // Slice unsizing
+ let y = [1, 2, 3];
+ let _: &[i32] = &y;
+
+ // Tuple unsizing
+ let hi = (1i32,);
+ let _: &(dyn Foo,) = &hi;
+
+ // Dropping auto traits
+ let a: &(dyn Foo + Send) = &1;
+ let _: &dyn Foo = a;
+}
diff --git a/tests/ui/traits/next-solver/upcast-right-substs.rs b/tests/ui/traits/next-solver/upcast-right-substs.rs
new file mode 100644
index 000000000..5b4f6d4be
--- /dev/null
+++ b/tests/ui/traits/next-solver/upcast-right-substs.rs
@@ -0,0 +1,13 @@
+// compile-flags: -Znext-solver
+// check-pass
+#![feature(trait_upcasting)]
+
+trait Foo: Bar<i32> + Bar<u32> {}
+
+trait Bar<T> {}
+
+fn main() {
+ let x: &dyn Foo = todo!();
+ let y: &dyn Bar<i32> = x;
+ let z: &dyn Bar<u32> = x;
+}
diff --git a/tests/ui/traits/next-solver/upcast-wrong-substs.rs b/tests/ui/traits/next-solver/upcast-wrong-substs.rs
new file mode 100644
index 000000000..0cd253007
--- /dev/null
+++ b/tests/ui/traits/next-solver/upcast-wrong-substs.rs
@@ -0,0 +1,11 @@
+// compile-flags: -Znext-solver
+
+trait Foo: Bar<i32> + Bar<u32> {}
+
+trait Bar<T> {}
+
+fn main() {
+ let x: &dyn Foo = todo!();
+ let y: &dyn Bar<usize> = x;
+ //~^ ERROR mismatched types
+}
diff --git a/tests/ui/traits/next-solver/upcast-wrong-substs.stderr b/tests/ui/traits/next-solver/upcast-wrong-substs.stderr
new file mode 100644
index 000000000..00ba1ef67
--- /dev/null
+++ b/tests/ui/traits/next-solver/upcast-wrong-substs.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+ --> $DIR/upcast-wrong-substs.rs:9:30
+ |
+LL | let y: &dyn Bar<usize> = x;
+ | --------------- ^ expected trait `Bar`, found trait `Foo`
+ | |
+ | expected due to this
+ |
+ = note: expected reference `&dyn Bar<usize>`
+ found reference `&dyn Foo`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/traits/next-solver/winnow-specializing-impls.rs b/tests/ui/traits/next-solver/winnow-specializing-impls.rs
new file mode 100644
index 000000000..d70a91596
--- /dev/null
+++ b/tests/ui/traits/next-solver/winnow-specializing-impls.rs
@@ -0,0 +1,22 @@
+// build-pass
+// compile-flags: -Znext-solver
+
+// Tests that the specializing impl `<() as Foo>` holds during codegen.
+
+#![feature(min_specialization)]
+
+trait Foo {
+ fn bar();
+}
+
+impl<T> Foo for T {
+ default fn bar() {}
+}
+
+impl Foo for () {
+ fn bar() {}
+}
+
+fn main() {
+ <() as Foo>::bar();
+}