Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion tests/crashes/126268.rs → tests/crashes/102252-2.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//@ known-bug: #126268
//@ known-bug: #102252

#![feature(min_specialization)]

trait Trait {}
Expand All @@ -16,3 +17,5 @@ struct DatasetIter<'a, R: Data> {
pub struct ArrayBase {}

impl<'a> Trait for DatasetIter<'a, ArrayBase> {}

fn main() {}
17 changes: 0 additions & 17 deletions tests/crashes/125014.rs

This file was deleted.

18 changes: 18 additions & 0 deletions tests/ui/specialization/associated-types-in-default-impl-bounds.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//@ check-pass

#![allow(incomplete_features)]
#![feature(specialization)]

// Tests that you can use a trait's associated types in the bounds of a default impl.
// Regression test for #52396.

trait Foo {
type Baz;
fn bar(&self, _: Self::Baz);
}

default impl<A: Foo<Baz = isize>> Foo for A {
fn bar(&self, _: isize) { }
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//@ check-pass

#![feature(specialization)]
#![allow(incomplete_features)]

// Tests that a blanket impl supplying a `default type` does not make a
// recursive trait requirement diverge.
// Regression test for #80700.

use std::marker::PhantomData;

struct Nil;
struct Cons<Head, Tail>(PhantomData<(Head, Tail)>);
struct Error;

trait GetLast {
type Output;
}

impl<T> GetLast for T {
default type Output = Error;
}

impl<Head> GetLast for Cons<Head, Nil> {
type Output = Nil;
}

impl<Head, Head2, Tail2> GetLast for Cons<Head, Cons<Head2, Tail2>>
where
Cons<Head2, Tail2>: GetLast,
{
type Output = <Cons<Head2, Tail2> as GetLast>::Output;
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//@ check-fail

#![feature(specialization)]
#![allow(incomplete_features)]

// `default impl` still participates in coherence. However, we shouldn't get an overflow here.
// Regresion test for #77026.

pub enum Either<L, R> {
Left(L),
Right(R),
}

default impl<L, R> From<L> for Either<L, R> {
fn from(l: L) -> Self {
Either::Left(l)
}
}

impl<L, R> From<R> for Either<L, R> {
//~^ ERROR conflicting implementations of trait `From<_>` for type `Either<_, _>`
fn from(r: R) -> Self {
Either::Right(r)
}
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
error[E0119]: conflicting implementations of trait `From<_>` for type `Either<_, _>`
--> $DIR/default-impl-coherence-overlap-issue-77026.rs:20:1
|
LL | default impl<L, R> From<L> for Either<L, R> {
| ------------------------------------------- first implementation here
...
LL | impl<L, R> From<R> for Either<L, R> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Either<_, _>`

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0119`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
//@ check-fail

#![feature(specialization)]
#![allow(incomplete_features)]

// Tests that we don't overflow when using `default impl`.
// Regression test for #48515, #98478, and #117909.

// #48515

trait TypeString {
fn type_string() -> &'static str;
}

default impl<T> TypeString for T {
fn type_string() -> &'static str {
"unknown type"
}
}

impl TypeString for () {
fn type_string() -> &'static str {
"()"
}
}

// #98478

trait Spam {}

trait SpamMore: Spam {}

default impl<T> Spam for T where T: SpamMore {}

struct A;

impl SpamMore for A {}
//~^ ERROR the trait bound `A: Spam` is not satisfied

fn needs_spam<T: Spam>() {}

// #117909

trait Set<T> {
fn contains(&self, bit: T);
}

default impl<T, S> Set<&T> for S
where
S: Set<T>,
{
fn contains(&self, _: &T) {}
}

fn main() {
let _ = <usize as TypeString>::type_string();
//~^ ERROR the trait bound `usize: TypeString` is not satisfied

needs_spam::<A>();
//~^ ERROR the trait bound `A: Spam` is not satisfied

0u32.contains(());
//~^ ERROR no method named `contains` found for type `u32` in the current scope
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
error[E0277]: the trait bound `A: Spam` is not satisfied
--> $DIR/default-impl-not-a-candidate-issue-48515.rs:37:19
|
LL | impl SpamMore for A {}
| ^ unsatisfied trait bound
|
help: the trait `Spam` is not implemented for `A`
--> $DIR/default-impl-not-a-candidate-issue-48515.rs:35:1
|
LL | struct A;
| ^^^^^^^^
note: required by a bound in `SpamMore`
--> $DIR/default-impl-not-a-candidate-issue-48515.rs:31:17
|
LL | trait SpamMore: Spam {}
| ^^^^ required by this bound in `SpamMore`

error[E0277]: the trait bound `usize: TypeString` is not satisfied
--> $DIR/default-impl-not-a-candidate-issue-48515.rs:56:14
|
LL | let _ = <usize as TypeString>::type_string();
| ^^^^^ the trait `TypeString` is not implemented for `usize`
|
help: the trait `TypeString` is implemented for `()`
--> $DIR/default-impl-not-a-candidate-issue-48515.rs:21:1
|
LL | impl TypeString for () {
| ^^^^^^^^^^^^^^^^^^^^^^

error[E0277]: the trait bound `A: Spam` is not satisfied
--> $DIR/default-impl-not-a-candidate-issue-48515.rs:59:18
|
LL | needs_spam::<A>();
| ^ unsatisfied trait bound
|
help: the trait `Spam` is not implemented for `A`
--> $DIR/default-impl-not-a-candidate-issue-48515.rs:35:1
|
LL | struct A;
| ^^^^^^^^
note: required by a bound in `needs_spam`
--> $DIR/default-impl-not-a-candidate-issue-48515.rs:40:18
|
LL | fn needs_spam<T: Spam>() {}
| ^^^^ required by this bound in `needs_spam`

error[E0599]: no method named `contains` found for type `u32` in the current scope
--> $DIR/default-impl-not-a-candidate-issue-48515.rs:62:10
|
LL | 0u32.contains(());
| ^^^^^^^^ method not found in `u32`
|
= help: items from traits can only be used if the trait is implemented and in scope
note: `Set` defines an item `contains`, perhaps you need to implement it
--> $DIR/default-impl-not-a-candidate-issue-48515.rs:44:1
|
LL | trait Set<T> {
| ^^^^^^^^^^^^

error: aborting due to 4 previous errors

Some errors have detailed explanations: E0277, E0599.
For more information about an error, try `rustc --explain E0277`.
71 changes: 71 additions & 0 deletions tests/ui/specialization/default-impl-not-an-impl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
//@ check-fail

#![feature(specialization)]
#![allow(incomplete_features)]

// Tests that a `default impl` does not count as an *actual* impl, so it cannot
// be used to satisfy trait bounds.

// A `default impl` may omit trait items, but a real impl may not.

trait Gapped {
fn a(&self) -> u32;
fn b(&self) -> u32;
}

default impl<T> Gapped for T {
fn a(&self) -> u32 {
1
}
}

impl Gapped for u8 {}
//~^ ERROR not all trait items implemented, missing: `b`

// A `default impl` that defines *every* trait item is still not an impl.

trait Foo {
fn f(&self) -> u32;
}

default impl<T> Foo for T {
fn f(&self) -> u32 {
1
}
}

fn need_foo<T: Foo>(t: &T) -> u32 {
t.f()
}

trait Bar {
fn b(&self) -> u32;
}

impl<T: Foo> Bar for T {
fn b(&self) -> u32 {
self.f()
}
}

fn need_bar<T: Bar>(t: &T) -> u32 {
t.b()
}

fn main() {
// as a bound (UFCS `<u32 as Foo>::f` is the same trait-selection path, omitted)
need_foo(&0u32);
//~^ ERROR the trait bound `u32: Foo` is not satisfied

// as a method-probe candidate
0u32.f();
//~^ ERROR no method named `f` found for type `u32` in the current scope

// when building a vtable
let _: &dyn Foo = &0u32;
//~^ ERROR the trait bound `u32: Foo` is not satisfied

// transitively, as another impl's where-clause
need_bar(&0i64);
//~^ ERROR the trait bound `i64: Bar` is not satisfied
}
69 changes: 69 additions & 0 deletions tests/ui/specialization/default-impl-not-an-impl.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
error[E0046]: not all trait items implemented, missing: `b`
--> $DIR/default-impl-not-an-impl.rs:22:1
|
LL | fn b(&self) -> u32;
| ------------------- `b` from trait
...
LL | impl Gapped for u8 {}
| ^^^^^^^^^^^^^^^^^^ missing `b` in implementation

error[E0277]: the trait bound `u32: Foo` is not satisfied
--> $DIR/default-impl-not-an-impl.rs:57:14
|
LL | need_foo(&0u32);
| -------- ^^^^^ the trait `Foo` is not implemented for `u32`
| |
| required by a bound introduced by this call
|
note: required by a bound in `need_foo`
--> $DIR/default-impl-not-an-impl.rs:37:16
|
LL | fn need_foo<T: Foo>(t: &T) -> u32 {
| ^^^ required by this bound in `need_foo`

error[E0599]: no method named `f` found for type `u32` in the current scope
--> $DIR/default-impl-not-an-impl.rs:61:10
|
LL | 0u32.f();
| ^ method not found in `u32`
|
= help: items from traits can only be used if the trait is implemented and in scope
note: `Foo` defines an item `f`, perhaps you need to implement it
--> $DIR/default-impl-not-an-impl.rs:27:1
|
LL | trait Foo {
| ^^^^^^^^^

error[E0277]: the trait bound `u32: Foo` is not satisfied
--> $DIR/default-impl-not-an-impl.rs:65:23
|
LL | let _: &dyn Foo = &0u32;
| ^^^^^ the trait `Foo` is not implemented for `u32`
|
= note: required for the cast from `&u32` to `&dyn Foo`

error[E0277]: the trait bound `i64: Bar` is not satisfied
--> $DIR/default-impl-not-an-impl.rs:69:14
|
LL | need_bar(&0i64);
| -------- ^^^^^ the trait `Foo` is not implemented for `i64`
| |
| required by a bound introduced by this call
|
note: required for `i64` to implement `Bar`
--> $DIR/default-impl-not-an-impl.rs:45:14
|
LL | impl<T: Foo> Bar for T {
| --- ^^^ ^
| |
| unsatisfied trait bound introduced here
note: required by a bound in `need_bar`
--> $DIR/default-impl-not-an-impl.rs:51:16
|
LL | fn need_bar<T: Bar>(t: &T) -> u32 {
| ^^^ required by this bound in `need_bar`

error: aborting due to 5 previous errors

Some errors have detailed explanations: E0046, E0277, E0599.
For more information about an error, try `rustc --explain E0046`.
Loading
Loading