summaryrefslogtreecommitdiffstats
path: root/tests/ui/traits/new-solver
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:20:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:20:39 +0000
commit1376c5a617be5c25655d0d7cb63e3beaa5a6e026 (patch)
tree3bb8d61aee02bc7a15eab3f36e3b921afc2075d0 /tests/ui/traits/new-solver
parentReleasing progress-linux version 1.69.0+dfsg1-1~progress7.99u1. (diff)
downloadrustc-1376c5a617be5c25655d0d7cb63e3beaa5a6e026.tar.xz
rustc-1376c5a617be5c25655d0d7cb63e3beaa5a6e026.zip
Merging upstream version 1.70.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tests/ui/traits/new-solver')
-rw-r--r--tests/ui/traits/new-solver/alias-eq-in-canonical-response.rs40
-rw-r--r--tests/ui/traits/new-solver/alias-sub.rs34
-rw-r--r--tests/ui/traits/new-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.rs2
-rw-r--r--tests/ui/traits/new-solver/auto-with-drop_tracking_mir.fail.stderr18
-rw-r--r--tests/ui/traits/new-solver/auto-with-drop_tracking_mir.rs26
-rw-r--r--tests/ui/traits/new-solver/canonical-int-var-eq-in-response.rs22
-rw-r--r--tests/ui/traits/new-solver/canonical-ty-var-eq-in-response.rs39
-rw-r--r--tests/ui/traits/new-solver/cast-checks-handling-projections.rs6
-rw-r--r--tests/ui/traits/new-solver/closure-inference-guidance.rs11
-rw-r--r--tests/ui/traits/new-solver/coherence/issue-102048.rs44
-rw-r--r--tests/ui/traits/new-solver/coherence/issue-102048.stderr12
-rw-r--r--tests/ui/traits/new-solver/const-param-placeholder.fail.stderr16
-rw-r--r--tests/ui/traits/new-solver/const-param-placeholder.rs21
-rw-r--r--tests/ui/traits/new-solver/deduce-ty-from-object.rs6
-rw-r--r--tests/ui/traits/new-solver/destruct.rs13
-rw-r--r--tests/ui/traits/new-solver/dont-elaborate-for-projections.rs12
-rw-r--r--tests/ui/traits/new-solver/equating-projection-cyclically.rs24
-rw-r--r--tests/ui/traits/new-solver/equating-projection-cyclically.stderr14
-rw-r--r--tests/ui/traits/new-solver/float-canonical.rs8
-rw-r--r--tests/ui/traits/new-solver/fn-trait.rs21
-rw-r--r--tests/ui/traits/new-solver/fn-trait.stderr124
-rw-r--r--tests/ui/traits/new-solver/int-var-alias-eq.rs18
-rw-r--r--tests/ui/traits/new-solver/int-var-is-send.rs8
-rw-r--r--tests/ui/traits/new-solver/iter-filter-projection.rs12
-rw-r--r--tests/ui/traits/new-solver/lazy-nested-obligations-1.rs13
-rw-r--r--tests/ui/traits/new-solver/lazy-nested-obligations-2.rs23
-rw-r--r--tests/ui/traits/new-solver/lazy-nested-obligations-3.rs38
-rw-r--r--tests/ui/traits/new-solver/more-object-bound.rs2
-rw-r--r--tests/ui/traits/new-solver/more-object-bound.stderr13
-rw-r--r--tests/ui/traits/new-solver/nested-obligations-with-bound-vars-gat.rs43
-rw-r--r--tests/ui/traits/new-solver/normalize-param-env-1.rs40
-rw-r--r--tests/ui/traits/new-solver/normalize-param-env-2.rs26
-rw-r--r--tests/ui/traits/new-solver/normalize-param-env-3.rs32
-rw-r--r--tests/ui/traits/new-solver/param-discr-kind.rs8
-rw-r--r--tests/ui/traits/new-solver/pointee.rs18
-rw-r--r--tests/ui/traits/new-solver/pointer-like.rs2
-rw-r--r--tests/ui/traits/new-solver/pointer-like.stderr2
-rw-r--r--tests/ui/traits/new-solver/prefer-candidate-no-constraints.rs22
-rw-r--r--tests/ui/traits/new-solver/prefer-param-env-on-ambiguity.rs10
-rw-r--r--tests/ui/traits/new-solver/projection-discr-kind.rs18
-rw-r--r--tests/ui/traits/new-solver/projection-discr-kind.stderr17
-rw-r--r--tests/ui/traits/new-solver/recursive-self-normalization-2.rs19
-rw-r--r--tests/ui/traits/new-solver/recursive-self-normalization-2.stderr16
-rw-r--r--tests/ui/traits/new-solver/recursive-self-normalization.rs15
-rw-r--r--tests/ui/traits/new-solver/recursive-self-normalization.stderr16
-rw-r--r--tests/ui/traits/new-solver/runaway-impl-candidate-selection.rs15
-rw-r--r--tests/ui/traits/new-solver/runaway-impl-candidate-selection.stderr9
-rw-r--r--tests/ui/traits/new-solver/specialization-transmute.rs30
-rw-r--r--tests/ui/traits/new-solver/specialization-transmute.stderr31
-rw-r--r--tests/ui/traits/new-solver/specialization-unconstrained.rs22
-rw-r--r--tests/ui/traits/new-solver/specialization-unconstrained.stderr25
-rw-r--r--tests/ui/traits/new-solver/stall-num-var-auto-trait.fallback.stderr17
-rw-r--r--tests/ui/traits/new-solver/stall-num-var-auto-trait.rs25
53 files changed, 1098 insertions, 20 deletions
diff --git a/tests/ui/traits/new-solver/alias-eq-in-canonical-response.rs b/tests/ui/traits/new-solver/alias-eq-in-canonical-response.rs
new file mode 100644
index 000000000..4bfb6323a
--- /dev/null
+++ b/tests/ui/traits/new-solver/alias-eq-in-canonical-response.rs
@@ -0,0 +1,40 @@
+// check-pass
+// compile-flags: -Ztrait-solver=next
+
+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/new-solver/alias-sub.rs b/tests/ui/traits/new-solver/alias-sub.rs
new file mode 100644
index 000000000..30c1981a9
--- /dev/null
+++ b/tests/ui/traits/new-solver/alias-sub.rs
@@ -0,0 +1,34 @@
+// compile-flags: -Ztrait-solver=next
+// 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/new-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.rs b/tests/ui/traits/new-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.rs
index fd5d0e3b1..531203d9c 100644
--- a/tests/ui/traits/new-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.rs
+++ b/tests/ui/traits/new-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.rs
@@ -1,7 +1,7 @@
// compile-flags: -Ztrait-solver=next
// 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
+// 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> {
diff --git a/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.fail.stderr b/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.fail.stderr
new file mode 100644
index 000000000..6a926534e
--- /dev/null
+++ b/tests/ui/traits/new-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:24: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:23:24
+ |
+LL | fn is_send(_: impl Send) {}
+ | ^^^^ required by this bound in `is_send`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.rs b/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.rs
new file mode 100644
index 000000000..a5db7c463
--- /dev/null
+++ b/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.rs
@@ -0,0 +1,26 @@
+// compile-flags: -Ztrait-solver=next -Zdrop-tracking-mir
+// 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;
+ 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/new-solver/canonical-int-var-eq-in-response.rs b/tests/ui/traits/new-solver/canonical-int-var-eq-in-response.rs
new file mode 100644
index 000000000..4b013983a
--- /dev/null
+++ b/tests/ui/traits/new-solver/canonical-int-var-eq-in-response.rs
@@ -0,0 +1,22 @@
+// compile-flags: -Ztrait-solver=next
+// 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/new-solver/canonical-ty-var-eq-in-response.rs b/tests/ui/traits/new-solver/canonical-ty-var-eq-in-response.rs
new file mode 100644
index 000000000..d1c6b1077
--- /dev/null
+++ b/tests/ui/traits/new-solver/canonical-ty-var-eq-in-response.rs
@@ -0,0 +1,39 @@
+// check-pass
+// compile-flags: -Ztrait-solver=next
+
+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/new-solver/cast-checks-handling-projections.rs b/tests/ui/traits/new-solver/cast-checks-handling-projections.rs
new file mode 100644
index 000000000..3b261062f
--- /dev/null
+++ b/tests/ui/traits/new-solver/cast-checks-handling-projections.rs
@@ -0,0 +1,6 @@
+// compile-flags: -Ztrait-solver=next
+// check-pass
+
+fn main() {
+ (0u8 + 0u8) as char;
+}
diff --git a/tests/ui/traits/new-solver/closure-inference-guidance.rs b/tests/ui/traits/new-solver/closure-inference-guidance.rs
new file mode 100644
index 000000000..d2ad0cc03
--- /dev/null
+++ b/tests/ui/traits/new-solver/closure-inference-guidance.rs
@@ -0,0 +1,11 @@
+// compile-flags: -Ztrait-solver=next
+// 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/new-solver/coherence/issue-102048.rs b/tests/ui/traits/new-solver/coherence/issue-102048.rs
new file mode 100644
index 000000000..11636bfeb
--- /dev/null
+++ b/tests/ui/traits/new-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: -Ztrait-solver=next
+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/new-solver/coherence/issue-102048.stderr b/tests/ui/traits/new-solver/coherence/issue-102048.stderr
new file mode 100644
index 000000000..17a43838f
--- /dev/null
+++ b/tests/ui/traits/new-solver/coherence/issue-102048.stderr
@@ -0,0 +1,12 @@
+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)
+ | --------------------------------------------------------------------------------------------------- first implementation here
+...
+LL | impl<T, U> Trait<for<'a> fn(<U as WithAssoc1<'a>>::Assoc, u32)> for (T, U) where
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(_, _)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/traits/new-solver/const-param-placeholder.fail.stderr b/tests/ui/traits/new-solver/const-param-placeholder.fail.stderr
new file mode 100644
index 000000000..4db6e22e5
--- /dev/null
+++ b/tests/ui/traits/new-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 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/new-solver/const-param-placeholder.rs b/tests/ui/traits/new-solver/const-param-placeholder.rs
new file mode 100644
index 000000000..a83102a4c
--- /dev/null
+++ b/tests/ui/traits/new-solver/const-param-placeholder.rs
@@ -0,0 +1,21 @@
+// compile-flags: -Ztrait-solver=next
+// 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/new-solver/deduce-ty-from-object.rs b/tests/ui/traits/new-solver/deduce-ty-from-object.rs
new file mode 100644
index 000000000..7398bce7b
--- /dev/null
+++ b/tests/ui/traits/new-solver/deduce-ty-from-object.rs
@@ -0,0 +1,6 @@
+// check-pass
+// compile-flags: -Ztrait-solver=next
+
+fn main() {
+ let x: Box<dyn Iterator<Item = ()>> = Box::new(std::iter::empty());
+}
diff --git a/tests/ui/traits/new-solver/destruct.rs b/tests/ui/traits/new-solver/destruct.rs
new file mode 100644
index 000000000..30d7777b7
--- /dev/null
+++ b/tests/ui/traits/new-solver/destruct.rs
@@ -0,0 +1,13 @@
+// compile-flags: -Ztrait-solver=next
+// 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/new-solver/dont-elaborate-for-projections.rs b/tests/ui/traits/new-solver/dont-elaborate-for-projections.rs
new file mode 100644
index 000000000..e60825006
--- /dev/null
+++ b/tests/ui/traits/new-solver/dont-elaborate-for-projections.rs
@@ -0,0 +1,12 @@
+// compile-flags: -Ztrait-solver=next
+// 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/new-solver/equating-projection-cyclically.rs b/tests/ui/traits/new-solver/equating-projection-cyclically.rs
new file mode 100644
index 000000000..019c6e81c
--- /dev/null
+++ b/tests/ui/traits/new-solver/equating-projection-cyclically.rs
@@ -0,0 +1,24 @@
+// compile-flags: -Ztrait-solver=next
+// known-bug: unknown
+
+trait Test {
+ type Assoc;
+}
+
+fn transform<T: Test>(x: T) -> T::Assoc {
+ todo!()
+}
+
+impl Test for i32 {
+ type Assoc = i32;
+}
+
+impl Test for String {
+ type Assoc = String;
+}
+
+fn main() {
+ let mut x = Default::default();
+ x = transform(x);
+ x = 1i32;
+}
diff --git a/tests/ui/traits/new-solver/equating-projection-cyclically.stderr b/tests/ui/traits/new-solver/equating-projection-cyclically.stderr
new file mode 100644
index 000000000..57cbc65a1
--- /dev/null
+++ b/tests/ui/traits/new-solver/equating-projection-cyclically.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+ --> $DIR/equating-projection-cyclically.rs:22:19
+ |
+LL | x = transform(x);
+ | ^ expected inferred type, found associated type
+ |
+ = note: expected type `_`
+ found associated type `<_ as Test>::Assoc`
+ = help: consider constraining the associated type `<_ as Test>::Assoc` to `_`
+ = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/traits/new-solver/float-canonical.rs b/tests/ui/traits/new-solver/float-canonical.rs
new file mode 100644
index 000000000..b8748cd43
--- /dev/null
+++ b/tests/ui/traits/new-solver/float-canonical.rs
@@ -0,0 +1,8 @@
+// compile-flags: -Ztrait-solver=next
+// check-pass
+
+fn foo(x: f64) {
+ let y = x + 1.0;
+}
+
+fn main() {}
diff --git a/tests/ui/traits/new-solver/fn-trait.rs b/tests/ui/traits/new-solver/fn-trait.rs
index d566ead10..0599e51d7 100644
--- a/tests/ui/traits/new-solver/fn-trait.rs
+++ b/tests/ui/traits/new-solver/fn-trait.rs
@@ -1,5 +1,4 @@
// compile-flags: -Ztrait-solver=next
-// check-pass
fn require_fn(_: impl Fn() -> i32) {}
@@ -7,7 +6,27 @@ 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/new-solver/fn-trait.stderr b/tests/ui/traits/new-solver/fn-trait.stderr
new file mode 100644
index 000000000..d52bcaf25
--- /dev/null
+++ b/tests/ui/traits/new-solver/fn-trait.stderr
@@ -0,0 +1,124 @@
+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: 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: 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/new-solver/int-var-alias-eq.rs b/tests/ui/traits/new-solver/int-var-alias-eq.rs
new file mode 100644
index 000000000..2da387db4
--- /dev/null
+++ b/tests/ui/traits/new-solver/int-var-alias-eq.rs
@@ -0,0 +1,18 @@
+// check-pass
+// compile-flags: -Ztrait-solver=next
+
+// 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/new-solver/int-var-is-send.rs b/tests/ui/traits/new-solver/int-var-is-send.rs
new file mode 100644
index 000000000..083aa90e1
--- /dev/null
+++ b/tests/ui/traits/new-solver/int-var-is-send.rs
@@ -0,0 +1,8 @@
+// compile-flags: -Ztrait-solver=next
+// check-pass
+
+fn needs_send(_: impl Send) {}
+
+fn main() {
+ needs_send(1);
+}
diff --git a/tests/ui/traits/new-solver/iter-filter-projection.rs b/tests/ui/traits/new-solver/iter-filter-projection.rs
new file mode 100644
index 000000000..8fb62323a
--- /dev/null
+++ b/tests/ui/traits/new-solver/iter-filter-projection.rs
@@ -0,0 +1,12 @@
+// compile-flags: -Ztrait-solver=next
+// 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/new-solver/lazy-nested-obligations-1.rs b/tests/ui/traits/new-solver/lazy-nested-obligations-1.rs
new file mode 100644
index 000000000..af00cbb3b
--- /dev/null
+++ b/tests/ui/traits/new-solver/lazy-nested-obligations-1.rs
@@ -0,0 +1,13 @@
+// check-pass
+// compile-flags: -Ztrait-solver=next
+// 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/new-solver/lazy-nested-obligations-2.rs b/tests/ui/traits/new-solver/lazy-nested-obligations-2.rs
new file mode 100644
index 000000000..32addd829
--- /dev/null
+++ b/tests/ui/traits/new-solver/lazy-nested-obligations-2.rs
@@ -0,0 +1,23 @@
+// check-pass
+// compile-flags: -Ztrait-solver=next
+// Issue 95863
+
+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/new-solver/lazy-nested-obligations-3.rs b/tests/ui/traits/new-solver/lazy-nested-obligations-3.rs
new file mode 100644
index 000000000..baf399572
--- /dev/null
+++ b/tests/ui/traits/new-solver/lazy-nested-obligations-3.rs
@@ -0,0 +1,38 @@
+// check-pass
+// compile-flags: -Ztrait-solver=next
+// 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/new-solver/more-object-bound.rs b/tests/ui/traits/new-solver/more-object-bound.rs
index 712759ef0..bb730b18e 100644
--- a/tests/ui/traits/new-solver/more-object-bound.rs
+++ b/tests/ui/traits/new-solver/more-object-bound.rs
@@ -10,7 +10,7 @@ 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 type annotations needed: cannot satisfy `dyn Trait<A = A, B = B>: Trait`
+ //~^ ERROR the trait bound `dyn Trait<A = A, B = B>: Trait` is not satisfied
}
fn foo<A, B, T: ?Sized>(x: T::A) -> B
diff --git a/tests/ui/traits/new-solver/more-object-bound.stderr b/tests/ui/traits/new-solver/more-object-bound.stderr
index 208fdecb0..4554b8c74 100644
--- a/tests/ui/traits/new-solver/more-object-bound.stderr
+++ b/tests/ui/traits/new-solver/more-object-bound.stderr
@@ -1,10 +1,9 @@
-error[E0283]: type annotations needed: cannot satisfy `dyn Trait<A = A, B = B>: Trait`
- --> $DIR/more-object-bound.rs:12:5
+error[E0277]: the trait bound `dyn Trait<A = A, B = B>: Trait` is not satisfied
+ --> $DIR/more-object-bound.rs:12:17
|
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: cannot satisfy `dyn Trait<A = A, B = B>: Trait`
note: required by a bound in `foo`
--> $DIR/more-object-bound.rs:18:8
|
@@ -13,7 +12,11 @@ LL | fn foo<A, B, T: ?Sized>(x: T::A) -> B
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 previous error
-For more information about this error, try `rustc --explain E0283`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/new-solver/nested-obligations-with-bound-vars-gat.rs b/tests/ui/traits/new-solver/nested-obligations-with-bound-vars-gat.rs
new file mode 100644
index 000000000..92bad9590
--- /dev/null
+++ b/tests/ui/traits/new-solver/nested-obligations-with-bound-vars-gat.rs
@@ -0,0 +1,43 @@
+// check-pass
+// compile-flags: -Ztrait-solver=next
+// 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/new-solver/normalize-param-env-1.rs b/tests/ui/traits/new-solver/normalize-param-env-1.rs
new file mode 100644
index 000000000..b02a5d623
--- /dev/null
+++ b/tests/ui/traits/new-solver/normalize-param-env-1.rs
@@ -0,0 +1,40 @@
+// check-pass
+// compile-flags: -Ztrait-solver=next
+// 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/new-solver/normalize-param-env-2.rs b/tests/ui/traits/new-solver/normalize-param-env-2.rs
new file mode 100644
index 000000000..7c2cebdd2
--- /dev/null
+++ b/tests/ui/traits/new-solver/normalize-param-env-2.rs
@@ -0,0 +1,26 @@
+// check-pass
+// compile-flags: -Ztrait-solver=next
+// 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/new-solver/normalize-param-env-3.rs b/tests/ui/traits/new-solver/normalize-param-env-3.rs
new file mode 100644
index 000000000..ce2974b2a
--- /dev/null
+++ b/tests/ui/traits/new-solver/normalize-param-env-3.rs
@@ -0,0 +1,32 @@
+// check-pass
+// compile-flags: -Ztrait-solver=next
+// 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/new-solver/param-discr-kind.rs b/tests/ui/traits/new-solver/param-discr-kind.rs
new file mode 100644
index 000000000..e319ddea1
--- /dev/null
+++ b/tests/ui/traits/new-solver/param-discr-kind.rs
@@ -0,0 +1,8 @@
+// compile-flags: -Ztrait-solver=next
+// check-pass
+
+fn foo<T>(x: T) {
+ std::mem::discriminant(&x);
+}
+
+fn main() {}
diff --git a/tests/ui/traits/new-solver/pointee.rs b/tests/ui/traits/new-solver/pointee.rs
index fa6ee2e2d..93c0542ac 100644
--- a/tests/ui/traits/new-solver/pointee.rs
+++ b/tests/ui/traits/new-solver/pointee.rs
@@ -7,17 +7,15 @@ use std::ptr::{DynMetadata, Pointee};
trait Trait<U> {}
struct MyDst<T: ?Sized>(T);
-fn works<T>() {
- let _: <T as Pointee>::Metadata = ();
- let _: <[T] as Pointee>::Metadata = 1_usize;
- let _: <str as Pointee>::Metadata = 1_usize;
- let _: <dyn Trait<T> as Pointee>::Metadata = give::<DynMetadata<dyn Trait<T>>>();
- let _: <MyDst<T> as Pointee>::Metadata = ();
- let _: <((((([u8],),),),),) as Pointee>::Metadata = 1_usize;
-}
+fn meta_is<T: Pointee<Metadata = U> + ?Sized, U>() {}
-fn give<U>() -> U {
- loop {}
+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/new-solver/pointer-like.rs b/tests/ui/traits/new-solver/pointer-like.rs
index 3745a075e..986301769 100644
--- a/tests/ui/traits/new-solver/pointer-like.rs
+++ b/tests/ui/traits/new-solver/pointer-like.rs
@@ -9,6 +9,6 @@ fn require_(_: impl PointerLike) {}
fn main() {
require_(1usize);
require_(1u16);
- //~^ ERROR `u16` needs to have the same alignment and size as a pointer
+ //~^ ERROR `u16` needs to have the same ABI as a pointer
require_(&1i16);
}
diff --git a/tests/ui/traits/new-solver/pointer-like.stderr b/tests/ui/traits/new-solver/pointer-like.stderr
index f695e6418..215a81cc2 100644
--- a/tests/ui/traits/new-solver/pointer-like.stderr
+++ b/tests/ui/traits/new-solver/pointer-like.stderr
@@ -1,4 +1,4 @@
-error[E0277]: `u16` needs to have the same alignment and size as a pointer
+error[E0277]: `u16` needs to have the same ABI as a pointer
--> $DIR/pointer-like.rs:11:14
|
LL | require_(1u16);
diff --git a/tests/ui/traits/new-solver/prefer-candidate-no-constraints.rs b/tests/ui/traits/new-solver/prefer-candidate-no-constraints.rs
new file mode 100644
index 000000000..6f8164f3a
--- /dev/null
+++ b/tests/ui/traits/new-solver/prefer-candidate-no-constraints.rs
@@ -0,0 +1,22 @@
+// compile-flags: -Ztrait-solver=next
+// 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/new-solver/prefer-param-env-on-ambiguity.rs b/tests/ui/traits/new-solver/prefer-param-env-on-ambiguity.rs
new file mode 100644
index 000000000..909b33ec3
--- /dev/null
+++ b/tests/ui/traits/new-solver/prefer-param-env-on-ambiguity.rs
@@ -0,0 +1,10 @@
+// compile-flags: -Ztrait-solver=next
+// 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/new-solver/projection-discr-kind.rs b/tests/ui/traits/new-solver/projection-discr-kind.rs
new file mode 100644
index 000000000..20296b287
--- /dev/null
+++ b/tests/ui/traits/new-solver/projection-discr-kind.rs
@@ -0,0 +1,18 @@
+// compile-flags: -Ztrait-solver=next
+
+// 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/new-solver/projection-discr-kind.stderr b/tests/ui/traits/new-solver/projection-discr-kind.stderr
new file mode 100644
index 000000000..03e28f993
--- /dev/null
+++ b/tests/ui/traits/new-solver/projection-discr-kind.stderr
@@ -0,0 +1,17 @@
+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
+ |
+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 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/new-solver/recursive-self-normalization-2.rs b/tests/ui/traits/new-solver/recursive-self-normalization-2.rs
new file mode 100644
index 000000000..8c029f517
--- /dev/null
+++ b/tests/ui/traits/new-solver/recursive-self-normalization-2.rs
@@ -0,0 +1,19 @@
+// compile-flags: -Ztrait-solver=next
+
+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`
+}
+
+fn main() {}
diff --git a/tests/ui/traits/new-solver/recursive-self-normalization-2.stderr b/tests/ui/traits/new-solver/recursive-self-normalization-2.stderr
new file mode 100644
index 000000000..139b0a456
--- /dev/null
+++ b/tests/ui/traits/new-solver/recursive-self-normalization-2.stderr
@@ -0,0 +1,16 @@
+error[E0275]: overflow evaluating the requirement `<T as Foo1>::Assoc1: Bar`
+ --> $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`)
+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: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/new-solver/recursive-self-normalization.rs b/tests/ui/traits/new-solver/recursive-self-normalization.rs
new file mode 100644
index 000000000..06d187b5f
--- /dev/null
+++ b/tests/ui/traits/new-solver/recursive-self-normalization.rs
@@ -0,0 +1,15 @@
+// compile-flags: -Ztrait-solver=next
+
+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`
+}
+
+fn main() {}
diff --git a/tests/ui/traits/new-solver/recursive-self-normalization.stderr b/tests/ui/traits/new-solver/recursive-self-normalization.stderr
new file mode 100644
index 000000000..8e9b9b4b4
--- /dev/null
+++ b/tests/ui/traits/new-solver/recursive-self-normalization.stderr
@@ -0,0 +1,16 @@
+error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc: Bar`
+ --> $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`)
+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: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/new-solver/runaway-impl-candidate-selection.rs b/tests/ui/traits/new-solver/runaway-impl-candidate-selection.rs
new file mode 100644
index 000000000..1dca86d36
--- /dev/null
+++ b/tests/ui/traits/new-solver/runaway-impl-candidate-selection.rs
@@ -0,0 +1,15 @@
+// compile-flags: -Ztrait-solver=next
+
+// 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/new-solver/runaway-impl-candidate-selection.stderr b/tests/ui/traits/new-solver/runaway-impl-candidate-selection.stderr
new file mode 100644
index 000000000..47004821a
--- /dev/null
+++ b/tests/ui/traits/new-solver/runaway-impl-candidate-selection.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+ --> $DIR/runaway-impl-candidate-selection.rs:13:22
+ |
+LL | println!("{:?}", iter::<_>());
+ | ^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `iter`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/traits/new-solver/specialization-transmute.rs b/tests/ui/traits/new-solver/specialization-transmute.rs
new file mode 100644
index 000000000..a54701df4
--- /dev/null
+++ b/tests/ui/traits/new-solver/specialization-transmute.rs
@@ -0,0 +1,30 @@
+// compile-flags: -Ztrait-solver=next
+
+#![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;
+
+ fn intu(&self) -> &Self::Id {
+ self
+ //~^ ERROR cannot satisfy `T <: <T as Default>::Id`
+ }
+}
+
+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);
+ //~^ ERROR cannot satisfy `<u8 as Default>::Id == Option<NonZeroU8>
+ assert_eq!(s, None);
+}
diff --git a/tests/ui/traits/new-solver/specialization-transmute.stderr b/tests/ui/traits/new-solver/specialization-transmute.stderr
new file mode 100644
index 000000000..e67c56afc
--- /dev/null
+++ b/tests/ui/traits/new-solver/specialization-transmute.stderr
@@ -0,0 +1,31 @@
+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 <: <T as Default>::Id`
+ --> $DIR/specialization-transmute.rs:16:9
+ |
+LL | self
+ | ^^^^ cannot satisfy `T <: <T as Default>::Id`
+
+error[E0284]: type annotations needed: cannot satisfy `<u8 as Default>::Id == Option<NonZeroU8>`
+ --> $DIR/specialization-transmute.rs:27:13
+ |
+LL | let s = transmute::<u8, Option<NonZeroU8>>(0);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `<u8 as Default>::Id == Option<NonZeroU8>`
+ |
+note: required by a bound in `transmute`
+ --> $DIR/specialization-transmute.rs:21:25
+ |
+LL | fn transmute<T: Default<Id = U>, U: Copy>(t: T) -> U {
+ | ^^^^^^ required by this bound in `transmute`
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0284`.
diff --git a/tests/ui/traits/new-solver/specialization-unconstrained.rs b/tests/ui/traits/new-solver/specialization-unconstrained.rs
new file mode 100644
index 000000000..02150689e
--- /dev/null
+++ b/tests/ui/traits/new-solver/specialization-unconstrained.rs
@@ -0,0 +1,22 @@
+// compile-flags: -Ztrait-solver=next
+
+#![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;
+}
+
+fn test<T: Default<Id = U>, U>() {}
+
+fn main() {
+ test::<u32, ()>();
+ //~^ ERROR cannot satisfy `<u32 as Default>::Id == ()`
+}
diff --git a/tests/ui/traits/new-solver/specialization-unconstrained.stderr b/tests/ui/traits/new-solver/specialization-unconstrained.stderr
new file mode 100644
index 000000000..910925cba
--- /dev/null
+++ b/tests/ui/traits/new-solver/specialization-unconstrained.stderr
@@ -0,0 +1,25 @@
+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: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0284`.
diff --git a/tests/ui/traits/new-solver/stall-num-var-auto-trait.fallback.stderr b/tests/ui/traits/new-solver/stall-num-var-auto-trait.fallback.stderr
new file mode 100644
index 000000000..a3ab7836c
--- /dev/null
+++ b/tests/ui/traits/new-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 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/new-solver/stall-num-var-auto-trait.rs b/tests/ui/traits/new-solver/stall-num-var-auto-trait.rs
new file mode 100644
index 000000000..0539c3a42
--- /dev/null
+++ b/tests/ui/traits/new-solver/stall-num-var-auto-trait.rs
@@ -0,0 +1,25 @@
+// compile-flags: -Ztrait-solver=next
+// 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;
+ }
+}