Add comments and tests explaining the shallow substitution rule

This commit is contained in:
Jonas Schievink 2019-06-16 20:53:35 +02:00
parent 5e9317a023
commit ff5d11e043
3 changed files with 76 additions and 52 deletions

View file

@ -66,28 +66,43 @@ trait D where
type Assoc = NotClone;
}
trait Foo2<T> where
<Self as Foo2<T>>::Bar: Clone,
// Test behavior of the check when defaults refer to other defaults:
// Shallow substitution rejects this trait since `Baz` isn't guaranteed to be
// `Clone`.
trait Foo2<T> {
type Bar: Clone = Vec<Self::Baz>;
//~^ ERROR the trait bound `<Self as Foo2<T>>::Baz: std::clone::Clone` is not satisfied
{
type Bar = Vec<Self::Baz>;
type Baz = T;
}
trait Foo3<T: Clone> where
<Self as Foo3<T>>::Bar: Clone,
//~^ ERROR the trait bound `<Self as Foo3<T>>::Baz: std::clone::Clone` is not satisfied
{
type Bar = Vec<Self::Baz>;
// Adding a `T: Clone` bound doesn't help since the requirement doesn't see `T`
// because of the shallow substitution. If we did a deep substitution instead,
// this would be accepted.
trait Foo25<T: Clone> {
type Bar: Clone = Vec<Self::Baz>;
//~^ ERROR the trait bound `<Self as Foo25<T>>::Baz: std::clone::Clone` is not satisfied
type Baz = T;
}
trait Foo4<T> where
<Self as Foo4<T>>::Bar: Clone,
{
type Bar = Vec<Self::Baz>;
type Baz: Clone = T;
// Adding the `Baz: Clone` bound isn't enough since the default is type
// parameter `T`, which also might not be `Clone`.
trait Foo3<T> where
Self::Bar: Clone,
Self::Baz: Clone,
//~^ ERROR the trait bound `T: std::clone::Clone` is not satisfied
{
type Bar = Vec<Self::Baz>;
type Baz = T;
}
// This one finally works, with `Clone` bounds on all assoc. types and the type
// parameter.
trait Foo4<T> where
T: Clone,
{
type Bar: Clone = Vec<Self::Baz>;
type Baz: Clone = T;
}
fn main() {}

View file

@ -104,61 +104,49 @@ LL | | }
| |_^
error[E0277]: the trait bound `<Self as Foo2<T>>::Baz: std::clone::Clone` is not satisfied
--> $DIR/defaults-suitability.rs:70:29
--> $DIR/defaults-suitability.rs:74:15
|
LL | <Self as Foo2<T>>::Bar: Clone,
| ^^^^^ the trait `std::clone::Clone` is not implemented for `<Self as Foo2<T>>::Baz`
LL | type Bar: Clone = Vec<Self::Baz>;
| ^^^^^ the trait `std::clone::Clone` is not implemented for `<Self as Foo2<T>>::Baz`
|
= help: consider adding a `where <Self as Foo2<T>>::Baz: std::clone::Clone` bound
= note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec<<Self as Foo2<T>>::Baz>`
note: required by `Foo2`
--> $DIR/defaults-suitability.rs:69:1
--> $DIR/defaults-suitability.rs:73:1
|
LL | / trait Foo2<T> where
LL | | <Self as Foo2<T>>::Bar: Clone,
LL | |
LL | | {
LL | | type Bar = Vec<Self::Baz>;
LL | | type Baz = T;
LL | | }
| |_^
LL | trait Foo2<T> {
| ^^^^^^^^^^^^^
error[E0277]: the trait bound `<Self as Foo3<T>>::Baz: std::clone::Clone` is not satisfied
--> $DIR/defaults-suitability.rs:78:29
error[E0277]: the trait bound `<Self as Foo25<T>>::Baz: std::clone::Clone` is not satisfied
--> $DIR/defaults-suitability.rs:83:15
|
LL | <Self as Foo3<T>>::Bar: Clone,
| ^^^^^ the trait `std::clone::Clone` is not implemented for `<Self as Foo3<T>>::Baz`
LL | type Bar: Clone = Vec<Self::Baz>;
| ^^^^^ the trait `std::clone::Clone` is not implemented for `<Self as Foo25<T>>::Baz`
|
= help: consider adding a `where <Self as Foo3<T>>::Baz: std::clone::Clone` bound
= note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec<<Self as Foo3<T>>::Baz>`
note: required by `Foo3`
--> $DIR/defaults-suitability.rs:77:1
= help: consider adding a `where <Self as Foo25<T>>::Baz: std::clone::Clone` bound
= note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec<<Self as Foo25<T>>::Baz>`
note: required by `Foo25`
--> $DIR/defaults-suitability.rs:82:1
|
LL | / trait Foo3<T: Clone> where
LL | | <Self as Foo3<T>>::Bar: Clone,
LL | |
LL | | {
LL | | type Bar = Vec<Self::Baz>;
LL | | type Baz = T;
LL | | }
| |_^
LL | trait Foo25<T: Clone> {
| ^^^^^^^^^^^^^^^^^^^^^
error[E0277]: the trait bound `T: std::clone::Clone` is not satisfied
--> $DIR/defaults-suitability.rs:89:15
--> $DIR/defaults-suitability.rs:92:16
|
LL | type Baz: Clone = T;
| ^^^^^ the trait `std::clone::Clone` is not implemented for `T`
LL | Self::Baz: Clone,
| ^^^^^ the trait `std::clone::Clone` is not implemented for `T`
|
= help: consider adding a `where T: std::clone::Clone` bound
note: required by `Foo4`
--> $DIR/defaults-suitability.rs:85:1
note: required by `Foo3`
--> $DIR/defaults-suitability.rs:90:1
|
LL | / trait Foo4<T> where
LL | | <Self as Foo4<T>>::Bar: Clone,
LL | | {
LL | | type Bar = Vec<Self::Baz>;
LL | | type Baz: Clone = T;
LL | / trait Foo3<T> where
LL | | Self::Bar: Clone,
LL | | Self::Baz: Clone,
LL | |
... |
LL | | type Baz = T;
LL | | }
| |_^