tests: add #![rustc_no_implicit_bounds]

After reviewing all tests with `?Sized` and discussing with lcnr, these
tests seem like they could probably benefit from
`#![rustc_no_implicit_bounds]`.
This commit is contained in:
David Wood 2025-06-27 05:34:08 +00:00
parent b93020257e
commit 1fd13fddba
No known key found for this signature in database
18 changed files with 109 additions and 89 deletions

View file

@ -1,15 +1,17 @@
//@ compile-flags: -Znext-solver=coherence
#![feature(rustc_attrs)]
#![rustc_no_implicit_bounds]
#![recursion_limit = "10"]
trait Trait {}
struct W<T: ?Sized>(*const T);
struct W<T>(*const T);
trait TwoW {}
impl<T: ?Sized + TwoW> TwoW for W<W<T>> {}
impl<T: TwoW> TwoW for W<W<T>> {}
impl<T: ?Sized + TwoW> Trait for W<T> {}
impl<T: ?Sized + TwoW> Trait for T {}
impl<T: TwoW> Trait for W<T> {}
impl<T: TwoW> Trait for T {}
//~^ ERROR conflicting implementations of trait `Trait` for type `W
fn main() {}

View file

@ -1,10 +1,10 @@
error[E0119]: conflicting implementations of trait `Trait` for type `W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<_>>>>>>>>>>>>>>>>>>>>>>>`
--> $DIR/coherence-fulfill-overflow.rs:12:1
--> $DIR/coherence-fulfill-overflow.rs:14:1
|
LL | impl<T: ?Sized + TwoW> Trait for W<T> {}
| ------------------------------------- first implementation here
LL | impl<T: ?Sized + TwoW> Trait for T {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<_>>>>>>>>>>>>>>>>>>>>>>>`
LL | impl<T: TwoW> Trait for W<T> {}
| ---------------------------- first implementation here
LL | impl<T: TwoW> Trait for T {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<_>>>>>>>>>>>>>>>>>>>>>>>`
error: aborting due to 1 previous error

View file

@ -1,6 +1,7 @@
//@ revisions: with without
//@ compile-flags: -Znext-solver
#![feature(rustc_attrs)]
#![rustc_no_implicit_bounds]
// 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
@ -17,20 +18,20 @@
// 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 Trait<T, V, D> {}
struct A<T>(*const T);
struct B<T>(*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 IncompleteGuidance<T, V> {}
impl<T, U: 'static> IncompleteGuidance<U, u8> for T {}
impl<T, U: 'static> IncompleteGuidance<U, i8> for T {}
impl<T, U: '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 {}
trait ImplGuidance<T, V> {}
impl<T> ImplGuidance<u32, u8> for T {}
impl<T> ImplGuidance<i32, i8> for T {}
impl<T: ?Sized, U: ?Sized, V: ?Sized, D: ?Sized> Trait<U, V, D> for A<T>
impl<T, U, V, D> Trait<U, V, D> for A<T>
where
T: IncompleteGuidance<U, V>,
A<T>: Trait<U, D, V>,
@ -39,17 +40,17 @@ where
{
}
trait ToU8<T: ?Sized> {}
trait ToU8<T> {}
impl ToU8<u8> for () {}
impl<T: ?Sized, U: ?Sized, V: ?Sized, D: ?Sized> Trait<U, V, D> for B<T>
impl<T, U, V, D> 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 impls_trait<T: Trait<U, V, D>, U, V, D>() {}
fn with_bound<X>()
where

View file

@ -1,25 +1,25 @@
error[E0277]: the trait bound `A<X>: Trait<_, _, _>` is not satisfied
--> $DIR/incompleteness-unstable-result.rs:65:19
--> $DIR/incompleteness-unstable-result.rs:66: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 for `A<X>` to implement `Trait<_, _, _>`
--> $DIR/incompleteness-unstable-result.rs:33:50
--> $DIR/incompleteness-unstable-result.rs:34:18
|
LL | impl<T: ?Sized, U: ?Sized, V: ?Sized, D: ?Sized> Trait<U, V, D> for A<T>
| ^^^^^^^^^^^^^^ ^^^^
LL | impl<T, U, V, D> Trait<U, V, D> for A<T>
| ^^^^^^^^^^^^^^ ^^^^
...
LL | A<T>: Trait<U, D, V>,
| -------------- unsatisfied trait bound introduced here
= note: 8 redundant requirements hidden
= note: required for `A<X>` to implement `Trait<_, _, _>`
note: required by a bound in `impls_trait`
--> $DIR/incompleteness-unstable-result.rs:52:28
--> $DIR/incompleteness-unstable-result.rs:53:19
|
LL | fn impls_trait<T: ?Sized + Trait<U, V, D>, U: ?Sized, V: ?Sized, D: ?Sized>() {}
| ^^^^^^^^^^^^^^ required by this bound in `impls_trait`
LL | fn impls_trait<T: Trait<U, V, D>, U, V, D>() {}
| ^^^^^^^^^^^^^^ required by this bound in `impls_trait`
error: aborting due to 1 previous error

View file

@ -1,25 +1,25 @@
error[E0277]: the trait bound `A<X>: Trait<_, _, _>` is not satisfied
--> $DIR/incompleteness-unstable-result.rs:65:19
--> $DIR/incompleteness-unstable-result.rs:66: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 for `A<X>` to implement `Trait<_, _, _>`
--> $DIR/incompleteness-unstable-result.rs:33:50
--> $DIR/incompleteness-unstable-result.rs:34:18
|
LL | impl<T: ?Sized, U: ?Sized, V: ?Sized, D: ?Sized> Trait<U, V, D> for A<T>
| ^^^^^^^^^^^^^^ ^^^^
LL | impl<T, U, V, D> Trait<U, V, D> for A<T>
| ^^^^^^^^^^^^^^ ^^^^
...
LL | A<T>: Trait<U, D, V>,
| -------------- unsatisfied trait bound introduced here
= note: 8 redundant requirements hidden
= note: required for `A<X>` to implement `Trait<_, _, _>`
note: required by a bound in `impls_trait`
--> $DIR/incompleteness-unstable-result.rs:52:28
--> $DIR/incompleteness-unstable-result.rs:53:19
|
LL | fn impls_trait<T: ?Sized + Trait<U, V, D>, U: ?Sized, V: ?Sized, D: ?Sized>() {}
| ^^^^^^^^^^^^^^ required by this bound in `impls_trait`
LL | fn impls_trait<T: Trait<U, V, D>, U, V, D>() {}
| ^^^^^^^^^^^^^^ required by this bound in `impls_trait`
error: aborting due to 1 previous error

View file

@ -1,23 +1,24 @@
//@ compile-flags: -Znext-solver
#![feature(rustc_attrs)]
#![rustc_no_implicit_bounds]
// 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);
struct A<T>(*const T);
struct B<T>(*const T);
struct C<T>(*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> {}
impl<'a, 'b, T> 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>
impl<'a, 'b, T> Trait<'a, 'b> for B<T>
where
A<T>: Trait<'a, 'b>,
A<T>: NotImplemented,
@ -31,7 +32,7 @@ where
// use the impl itself to prove that adds region constraints as we uniquified the
// regions in the `A<T>: Trait<'a, 'b>` where-bound. As both the impl above
// and the impl below now apply with some constraints, we failed with ambiguity.
impl<'a, 'b, T: ?Sized> Trait<'a, 'b> for B<T>
impl<'a, 'b, T> Trait<'a, 'b> for B<T>
where
A<T>: NotImplemented,
{}
@ -40,7 +41,7 @@ where
//
// 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>
impl<'a, T> Trait<'a, 'static> for B<T>
where
C<T>: Trait<'a, 'a>,
{}
@ -48,14 +49,14 @@ where
// 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>
impl<'a, 'b, T> Trait<'a, 'b> for C<T>
where
B<T>: Trait<'a, 'b>,
{}
fn impls_trait<'a, 'b, T: Trait<'a, 'b> + ?Sized>() {}
fn impls_trait<'a, 'b, T: Trait<'a, 'b>>() {}
fn check<'a, T: ?Sized>() {
fn check<'a, T>() {
impls_trait::<'a, 'static, A<T>>();
//~^ ERROR lifetime may not live long enough
}

View file

@ -1,7 +1,7 @@
error: lifetime may not live long enough
--> $DIR/fixpoint-rerun-all-cycle-heads.rs:59:5
--> $DIR/fixpoint-rerun-all-cycle-heads.rs:60:5
|
LL | fn check<'a, T: ?Sized>() {
LL | fn check<'a, T>() {
| -- lifetime `'a` defined here
LL | impls_trait::<'a, 'static, A<T>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`

View file

@ -1,4 +1,6 @@
//@ compile-flags: -Znext-solver
#![feature(rustc_attrs)]
#![rustc_no_implicit_bounds]
// This currently hangs if we do not erase constraints from
// overflow.
@ -17,9 +19,9 @@
// the solver to hang without hitting the recursion limit.
trait Trait {}
struct W<T: ?Sized>(*const T);
struct W<T>(*const T);
impl<T: ?Sized> Trait for W<W<T>>
impl<T> Trait for W<W<T>>
where
W<T>: Trait,
W<T>: Trait,

View file

@ -1,11 +1,11 @@
error[E0275]: overflow evaluating the requirement `W<_>: Trait`
--> $DIR/inductive-fixpoint-hang.rs:31:19
--> $DIR/inductive-fixpoint-hang.rs:33:19
|
LL | impls_trait::<W<_>>();
| ^^^^
|
note: required by a bound in `impls_trait`
--> $DIR/inductive-fixpoint-hang.rs:28:19
--> $DIR/inductive-fixpoint-hang.rs:30:19
|
LL | fn impls_trait<T: Trait>() {}
| ^^^^^ required by this bound in `impls_trait`

View file

@ -1,6 +1,7 @@
//@ compile-flags: -Znext-solver
//@ check-pass
#![feature(rustc_attrs)]
#![rustc_no_implicit_bounds]
// A test showcasing that using a provisional cache can differ
// from only tracking stack entries.
@ -59,9 +60,9 @@ trait B {}
#[rustc_coinductive]
trait C {}
impl<T: ?Sized + B + C> A for T {}
impl<T: ?Sized + A + C> B for T {}
impl<T: ?Sized + B> C for T {}
impl<T: B + C> A for T {}
impl<T: A + C> B for T {}
impl<T: B> C for T {}
fn impls_a<T: A>() {}

View file

@ -1,4 +1,6 @@
//@ compile-flags: -Znext-solver
#![feature(rustc_attrs)]
#![rustc_no_implicit_bounds]
trait Tr<'a> {}
@ -16,9 +18,9 @@ trait Tr<'a> {}
// Then, when we recompute the goal `W<?0>: Constrain<'error>`, when
// collecting ambiguities and overflows, we end up assembling a default
// error candidate w/o ambiguity, which causes the goal to pass, and ICE.
impl<'a, A: ?Sized> Tr<'a> for W<A> {}
struct W<A: ?Sized>(A);
impl<'a, A: ?Sized> Tr<'a> for A where A: Constrain<'a> {}
impl<'a, A> Tr<'a> for W<A> {}
struct W<A>(A);
impl<'a, A> Tr<'a> for A where A: Constrain<'a> {}
//~^ ERROR conflicting implementations of trait `Tr<'_>` for type `W<_>`
trait Constrain<'a> {}

View file

@ -1,5 +1,5 @@
error[E0261]: use of undeclared lifetime name `'missing`
--> $DIR/dont-canonicalize-re-error.rs:25:26
--> $DIR/dont-canonicalize-re-error.rs:27:26
|
LL | impl<A: Sized> Constrain<'missing> for W<A> {}
| - ^^^^^^^^ undeclared lifetime
@ -7,13 +7,13 @@ LL | impl<A: Sized> Constrain<'missing> for W<A> {}
| help: consider introducing lifetime `'missing` here: `'missing,`
error[E0119]: conflicting implementations of trait `Tr<'_>` for type `W<_>`
--> $DIR/dont-canonicalize-re-error.rs:21:1
--> $DIR/dont-canonicalize-re-error.rs:23:1
|
LL | impl<'a, A: ?Sized> Tr<'a> for W<A> {}
| ----------------------------------- first implementation here
LL | struct W<A: ?Sized>(A);
LL | impl<'a, A: ?Sized> Tr<'a> for A where A: Constrain<'a> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `W<_>`
LL | impl<'a, A> Tr<'a> for W<A> {}
| --------------------------- first implementation here
LL | struct W<A>(A);
LL | impl<'a, A> Tr<'a> for A where A: Constrain<'a> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `W<_>`
error: aborting due to 2 previous errors

View file

@ -1,6 +1,8 @@
//@ revisions: normalize_param_env normalize_obligation hrtb
//@ check-pass
//@ compile-flags: -Znext-solver
#![feature(rustc_attrs)]
#![rustc_no_implicit_bounds]
trait Foo {
#[cfg(normalize_param_env)]
@ -11,11 +13,11 @@ trait Foo {
type Gat<'b> where for<'a> <Self as MirrorRegion<'a>>::Assoc: 'b;
}
trait Mirror { type Assoc: ?Sized; }
impl<T: ?Sized> Mirror for T { type Assoc = T; }
trait Mirror { type Assoc; }
impl<T> Mirror for T { type Assoc = T; }
trait MirrorRegion<'a> { type Assoc: ?Sized; }
impl<'a, T: ?Sized> MirrorRegion<'a> for T { type Assoc = T; }
trait MirrorRegion<'a> { type Assoc; }
impl<'a, T> MirrorRegion<'a> for T { type Assoc = T; }
impl<T> Foo for T {
#[cfg(normalize_param_env)]

View file

@ -4,16 +4,18 @@
// Regression test for nalgebra hang <https://github.com/rust-lang/rust/issues/130056>.
#![feature(lazy_type_alias)]
#![feature(rustc_attrs)]
#![rustc_no_implicit_bounds]
#![allow(incomplete_features)]
type Id<T: ?Sized> = T;
type Id<T> = T;
trait NotImplemented {}
struct W<T: ?Sized, U: ?Sized>(*const T, *const U);
struct W<T, U>(*const T, *const U);
trait Trait {
type Assoc: ?Sized;
type Assoc;
}
impl<T: ?Sized + Trait> Trait for W<T, T> {
impl<T: Trait> Trait for W<T, T> {
#[cfg(ai)]
type Assoc = W<T::Assoc, Id<T::Assoc>>;
#[cfg(ia)]
@ -22,8 +24,8 @@ impl<T: ?Sized + Trait> Trait for W<T, T> {
type Assoc = W<Id<T::Assoc>, Id<T::Assoc>>;
}
trait Overlap<T: ?Sized> {}
impl<T: ?Sized> Overlap<T> for W<T, T> {}
impl<T: ?Sized + Trait + NotImplemented> Overlap<T::Assoc> for T {}
trait Overlap<T> {}
impl<T> Overlap<T> for W<T, T> {}
impl<T: Trait + NotImplemented> Overlap<T::Assoc> for T {}
fn main() {}

View file

@ -1,5 +1,7 @@
//@ compile-flags: -Znext-solver=coherence
//@ check-pass
#![feature(rustc_attrs)]
#![rustc_no_implicit_bounds]
// A regression test for trait-system-refactor-initiative#70.
@ -7,8 +9,8 @@ trait Trait {
type Assoc;
}
struct W<T: ?Sized>(*mut T);
impl<T: ?Sized> Trait for W<W<T>>
struct W<T>(*mut T);
impl<T> Trait for W<W<T>>
where
W<T>: Trait,
{
@ -20,6 +22,6 @@ 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> {}
impl<T> NoOverlap for W<T> {}
fn main() {}

View file

@ -1,5 +1,7 @@
//@ compile-flags: -Znext-solver
//@ check-pass
#![feature(rustc_attrs)]
#![rustc_no_implicit_bounds]
// Regression test for <https://github.com/rust-lang/trait-system-refactor-initiative/issues/171>.
// Tests that we don't try to replace `<V as Super>::Output` when replacing projections in the
@ -13,9 +15,9 @@ pub trait Super {
type Output;
}
fn bound<T: Trait + ?Sized>() {}
fn bound<T: Trait>() {}
fn visit_simd_operator<V: Super + ?Sized>() {
fn visit_simd_operator<V: Super>() {
bound::<dyn Trait<Output = <V as Super>::Output>>();
}

View file

@ -1,12 +1,15 @@
#![feature(rustc_attrs)]
#![rustc_no_implicit_bounds]
trait Hello {}
struct Foo<'a, T: ?Sized>(&'a T);
struct Foo<'a, T>(&'a T);
impl<'a, T: ?Sized> Hello for Foo<'a, &'a T> where Foo<'a, T>: Hello {}
impl<'a, T> Hello for Foo<'a, &'a T> where Foo<'a, T>: Hello {}
impl Hello for Foo<'static, i32> {}
fn hello<T: ?Sized + Hello>() {}
fn hello<T: Hello>() {}
fn main() {
hello();

View file

@ -1,5 +1,5 @@
error[E0283]: type annotations needed
--> $DIR/overflow-computing-ambiguity.rs:12:5
--> $DIR/overflow-computing-ambiguity.rs:15:5
|
LL | hello();
| ^^^^^ cannot infer type of the type parameter `T` declared on the function `hello`
@ -9,10 +9,10 @@ LL | hello();
Foo<'a, &'a T>
Foo<'static, i32>
note: required by a bound in `hello`
--> $DIR/overflow-computing-ambiguity.rs:9:22
--> $DIR/overflow-computing-ambiguity.rs:12:13
|
LL | fn hello<T: ?Sized + Hello>() {}
| ^^^^^ required by this bound in `hello`
LL | fn hello<T: Hello>() {}
| ^^^^^ required by this bound in `hello`
help: consider specifying the generic argument
|
LL | hello::<T>();