about summary refs log tree commit diff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/ui/const-generics/min_const_generics/param-env-eager-norm-dedup.rs23
-rw-r--r--tests/ui/traits/winnowing/global-non-global-env-1.rs18
-rw-r--r--tests/ui/traits/winnowing/global-non-global-env-2.rs18
-rw-r--r--tests/ui/traits/winnowing/global-non-global-env-2.stderr17
-rw-r--r--tests/ui/traits/winnowing/global-non-global-env-3.rs20
-rw-r--r--tests/ui/traits/winnowing/global-non-global-env-4.rs19
-rw-r--r--tests/ui/traits/winnowing/global-non-global-env-4.stderr17
7 files changed, 132 insertions, 0 deletions
diff --git a/tests/ui/const-generics/min_const_generics/param-env-eager-norm-dedup.rs b/tests/ui/const-generics/min_const_generics/param-env-eager-norm-dedup.rs
new file mode 100644
index 00000000000..9600b3875ba
--- /dev/null
+++ b/tests/ui/const-generics/min_const_generics/param-env-eager-norm-dedup.rs
@@ -0,0 +1,23 @@
+//@ check-pass
+
+// This caused a regression in a crater run in #132325.
+//
+// The underlying issue is a really subtle implementation detail.
+//
+// When building the `param_env` for `Trait` we start out with its
+// explicit predicates `Self: Trait` and `Self: for<'a> Super<'a, { 1 + 1 }>`.
+//
+// When normalizing the environment we also elaborate. This implicitly
+// deduplicates its returned predicates. We currently first eagerly
+// normalize constants in the unnormalized param env to avoid issues
+// caused by our lack of deferred alias equality.
+//
+// So we actually elaborate `Self: Trait` and `Self: for<'a> Super<'a, 2>`,
+// resulting in a third `Self: for<'a> Super<'a, { 1 + 1 }>` predicate which
+// then gets normalized to  `Self: for<'a> Super<'a, 2>` at which point we
+// do not deduplicate however. By failing to handle equal where-bounds in
+// candidate selection, this caused ambiguity when checking that `Trait` is
+// well-formed.
+trait Super<'a, const N: usize> {}
+trait Trait: for<'a> Super<'a, { 1 + 1 }> {}
+fn main() {}
diff --git a/tests/ui/traits/winnowing/global-non-global-env-1.rs b/tests/ui/traits/winnowing/global-non-global-env-1.rs
new file mode 100644
index 00000000000..d232d32dddf
--- /dev/null
+++ b/tests/ui/traits/winnowing/global-non-global-env-1.rs
@@ -0,0 +1,18 @@
+//@ check-pass
+
+// A regression test for an edge case of candidate selection
+// in the old trait solver, see #132325 for more details.
+
+trait Trait<T> {}
+impl<T> Trait<T> for () {}
+
+fn impls_trait<T: Trait<U>, U>(_: T) -> U { todo!() }
+fn foo<T>() -> u32
+where
+    (): Trait<u32>,
+    (): Trait<T>,
+{
+    impls_trait(())
+}
+
+fn main() {}
diff --git a/tests/ui/traits/winnowing/global-non-global-env-2.rs b/tests/ui/traits/winnowing/global-non-global-env-2.rs
new file mode 100644
index 00000000000..16476069346
--- /dev/null
+++ b/tests/ui/traits/winnowing/global-non-global-env-2.rs
@@ -0,0 +1,18 @@
+// A regression test for an edge case of candidate selection
+// in the old trait solver, see #132325 for more details. Unlike
+// the first test, this one has two impl candidates.
+
+trait Trait<T> {}
+impl Trait<u32> for () {}
+impl Trait<u64> for () {}
+
+fn impls_trait<T: Trait<U>, U>(_: T) -> U { todo!() }
+fn foo<T>() -> u32
+where
+    (): Trait<u32>,
+    (): Trait<T>,
+{
+    impls_trait(()) //~ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/tests/ui/traits/winnowing/global-non-global-env-2.stderr b/tests/ui/traits/winnowing/global-non-global-env-2.stderr
new file mode 100644
index 00000000000..dee01c72e48
--- /dev/null
+++ b/tests/ui/traits/winnowing/global-non-global-env-2.stderr
@@ -0,0 +1,17 @@
+error[E0308]: mismatched types
+  --> $DIR/global-non-global-env-2.rs:15:5
+   |
+LL | fn foo<T>() -> u32
+   |        -       --- expected `u32` because of return type
+   |        |
+   |        found this type parameter
+...
+LL |     impls_trait(())
+   |     ^^^^^^^^^^^^^^^ expected `u32`, found type parameter `T`
+   |
+   = note:        expected type `u32`
+           found type parameter `T`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/traits/winnowing/global-non-global-env-3.rs b/tests/ui/traits/winnowing/global-non-global-env-3.rs
new file mode 100644
index 00000000000..008d07e4144
--- /dev/null
+++ b/tests/ui/traits/winnowing/global-non-global-env-3.rs
@@ -0,0 +1,20 @@
+//@ check-pass
+
+// A regression test for an edge case of candidate selection
+// in the old trait solver, see #132325 for more details. Unlike
+// the second test, the where-bounds are in a different order.
+
+trait Trait<T> {}
+impl Trait<u32> for () {}
+impl Trait<u64> for () {}
+
+fn impls_trait<T: Trait<U>, U>(_: T) -> U { todo!() }
+fn foo<T>() -> u32
+where
+    (): Trait<T>,
+    (): Trait<u32>,
+{
+    impls_trait(())
+}
+
+fn main() {}
diff --git a/tests/ui/traits/winnowing/global-non-global-env-4.rs b/tests/ui/traits/winnowing/global-non-global-env-4.rs
new file mode 100644
index 00000000000..1f35cf20f83
--- /dev/null
+++ b/tests/ui/traits/winnowing/global-non-global-env-4.rs
@@ -0,0 +1,19 @@
+// A regression test for an edge case of candidate selection
+// in the old trait solver, see #132325 for more details. Unlike
+// the third test, this one has 3 impl candidates.
+
+trait Trait<T> {}
+impl Trait<u32> for () {}
+impl Trait<u64> for () {}
+impl Trait<u128> for () {}
+
+fn impls_trait<T: Trait<U>, U>(_: T) -> U { todo!() }
+fn foo<T>() -> u32
+where
+    (): Trait<T>,
+    (): Trait<u32>,
+{
+    impls_trait(()) //~ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/tests/ui/traits/winnowing/global-non-global-env-4.stderr b/tests/ui/traits/winnowing/global-non-global-env-4.stderr
new file mode 100644
index 00000000000..6449f3feb08
--- /dev/null
+++ b/tests/ui/traits/winnowing/global-non-global-env-4.stderr
@@ -0,0 +1,17 @@
+error[E0308]: mismatched types
+  --> $DIR/global-non-global-env-4.rs:16:5
+   |
+LL | fn foo<T>() -> u32
+   |        -       --- expected `u32` because of return type
+   |        |
+   |        found this type parameter
+...
+LL |     impls_trait(())
+   |     ^^^^^^^^^^^^^^^ expected `u32`, found type parameter `T`
+   |
+   = note:        expected type `u32`
+           found type parameter `T`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.