Skip to content

Commit

Permalink
add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
lcnr committed Nov 29, 2024
1 parent 26b5f76 commit ec553cd
Show file tree
Hide file tree
Showing 7 changed files with 151 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
//@ 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() {}
21 changes: 21 additions & 0 deletions tests/ui/traits/winnowing/global-non-global-env-1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
//@ 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() {}
17 changes: 17 additions & 0 deletions tests/ui/traits/winnowing/global-non-global-env-2.current.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
error[E0308]: mismatched types
--> $DIR/global-non-global-env-2.rs:20: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`.
23 changes: 23 additions & 0 deletions tests/ui/traits/winnowing/global-non-global-env-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// 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.

//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
//@[next] check-pass

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(()) //[current]~ ERROR mismatched types
}

fn main() {}
23 changes: 23 additions & 0 deletions tests/ui/traits/winnowing/global-non-global-env-3.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
//@ 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() {}
17 changes: 17 additions & 0 deletions tests/ui/traits/winnowing/global-non-global-env-4.current.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
error[E0308]: mismatched types
--> $DIR/global-non-global-env-4.rs:21: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`.
24 changes: 24 additions & 0 deletions tests/ui/traits/winnowing/global-non-global-env-4.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// 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.

//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
//@[next] check-pass

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(()) //[current]~ ERROR mismatched types
}

fn main() {}

0 comments on commit ec553cd

Please sign in to comment.