Check projections are well-formed when using projection candidates

This commit is contained in:
Matthew Jasper 2020-06-28 12:41:46 +01:00
parent 87f2f42dc2
commit b3057f4d5f
13 changed files with 278 additions and 30 deletions

View file

@ -0,0 +1,62 @@
// Like `projection-bound-cycle.rs` but this avoids using
// `feature(trivial_bounds)`.
#![feature(generic_associated_types)]
//~^ WARNING the feature `generic_associated_types` is incomplete
trait Print {
fn print();
}
trait Foo {
type Item: Sized where <Self as Foo>::Item: Sized;
}
struct Number<T> { t: T }
impl<T> Foo for Number<T> {
// Well-formedness checks require that the following
// goal is true:
// ```
// if ([T]: Sized) { # if the where clauses hold
// [T]: Sized # then the bound on the associated type hold
// }
// ```
// which it is :)
type Item where [T]: Sized = [T];
}
struct OnlySized<T> where T: Sized { f: T }
impl<T> Print for OnlySized<T> {
fn print() {
println!("{}", std::mem::size_of::<T>());
}
}
trait Bar {
type Assoc: Print;
}
impl<T> Bar for T where T: Foo {
// This is not ok, we need to prove `wf(<T as Foo>::Item)`, which requires
// knowing that `<T as Foo>::Item: Sized` to satisfy the where clause. We
// can use the bound on `Foo::Item` for this, but that requires
// `wf(<T as Foo>::Item)`, which is an invalid cycle.
type Assoc = OnlySized<<T as Foo>::Item>;
//~^ ERROR overflow evaluating the requirement `<T as Foo>::Item: std::marker::Sized`
}
fn foo<T: Print>() {
T::print() // oops, in fact `T = OnlySized<str>` which is ill-formed
}
fn bar<T: Bar>() {
// we have `FromEnv(T: Bar)` hence
// `<T as Bar>::Assoc` is well-formed and
// `Implemented(<T as Bar>::Assoc: Print)` hold
foo::<<T as Bar>::Assoc>()
}
fn main() {
bar::<Number<u8>>()
}

View file

@ -0,0 +1,21 @@
warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/projection-bound-cycle-generic.rs:4:12
|
LL | #![feature(generic_associated_types)]
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
error[E0275]: overflow evaluating the requirement `<T as Foo>::Item: std::marker::Sized`
--> $DIR/projection-bound-cycle-generic.rs:45:5
|
LL | struct OnlySized<T> where T: Sized { f: T }
| - required by this bound in `OnlySized`
...
LL | type Assoc = OnlySized<<T as Foo>::Item>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0275`.

View file

@ -0,0 +1,64 @@
// Test case from Chalk.
// Make sure that we make sure that we don't allow arbitrary bounds to be
// proven when a bound and a where clause of an associated type are the same.
#![feature(generic_associated_types)]
//~^ WARNING the feature `generic_associated_types` is incomplete
#![feature(trivial_bounds)]
trait Print {
fn print();
}
trait Foo {
type Item: Sized where <Self as Foo>::Item: Sized;
}
struct Number { }
impl Foo for Number {
// Well-formedness checks require that the following
// goal is true:
// ```
// if (str: Sized) { # if the where clauses hold
// str: Sized # then the bound on the associated type hold
// }
// ```
// which it is :)
type Item where str: Sized = str;
}
struct OnlySized<T> where T: Sized { f: T }
impl<T> Print for OnlySized<T> {
fn print() {
println!("{}", std::mem::size_of::<T>());
}
}
trait Bar {
type Assoc: Print;
}
impl<T> Bar for T where T: Foo {
// This is not ok, we need to prove `wf(<T as Foo>::Item)`, which requires
// knowing that `<T as Foo>::Item: Sized` to satisfy the where clause. We
// can use the bound on `Foo::Item` for this, but that requires
// `wf(<T as Foo>::Item)`, which is an invalid cycle.
type Assoc = OnlySized<<T as Foo>::Item>;
//~^ ERROR overflow evaluating the requirement `<T as Foo>::Item: std::marker::Sized`
}
fn foo<T: Print>() {
T::print() // oops, in fact `T = OnlySized<str>` which is ill-formed
}
fn bar<T: Bar>() {
// we have `FromEnv(T: Bar)` hence
// `<T as Bar>::Assoc` is well-formed and
// `Implemented(<T as Bar>::Assoc: Print)` hold
foo::<<T as Bar>::Assoc>()
}
fn main() {
bar::<Number>()
}

View file

@ -0,0 +1,21 @@
warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/projection-bound-cycle.rs:5:12
|
LL | #![feature(generic_associated_types)]
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
error[E0275]: overflow evaluating the requirement `<T as Foo>::Item: std::marker::Sized`
--> $DIR/projection-bound-cycle.rs:47:5
|
LL | struct OnlySized<T> where T: Sized { f: T }
| - required by this bound in `OnlySized`
...
LL | type Assoc = OnlySized<<T as Foo>::Item>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0275`.

View file

@ -0,0 +1,23 @@
#![feature(specialization)]
//~^ WARN the feature `specialization` is incomplete
trait Iterate<'a> {
type Ty: Valid;
fn iterate(self);
}
impl<'a, T> Iterate<'a> for T where T: Check {
default type Ty = ();
default fn iterate(self) {}
}
trait Check {}
impl<'a, T> Check for T where <T as Iterate<'a>>::Ty: Valid {}
trait Valid {}
impl Valid for () {}
fn main() {
Iterate::iterate(0);
//~^ ERROR overflow evaluating the requirement `{integer}: Check`
}

View file

@ -0,0 +1,23 @@
warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/issue-38091-2.rs:1:12
|
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
error[E0275]: overflow evaluating the requirement `{integer}: Check`
--> $DIR/issue-38091-2.rs:21:5
|
LL | fn iterate(self);
| ----------------- required by `Iterate::iterate`
...
LL | Iterate::iterate(0);
| ^^^^^^^^^^^^^^^^
|
= note: required because of the requirements on the impl of `Iterate<'_>` for `{integer}`
error: aborting due to previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0275`.

View file

@ -18,4 +18,5 @@ trait Valid {}
fn main() {
Iterate::iterate(0);
//~^ ERROR overflow evaluating the requirement `{integer}: Check`
}

View file

@ -16,6 +16,18 @@ LL | type Ty: Valid;
LL | default type Ty = ();
| ^^^^^^^^^^^^^^^^^^^^^ the trait `Valid` is not implemented for `()`
error: aborting due to previous error; 1 warning emitted
error[E0275]: overflow evaluating the requirement `{integer}: Check`
--> $DIR/issue-38091.rs:20:5
|
LL | fn iterate(self);
| ----------------- required by `Iterate::iterate`
...
LL | Iterate::iterate(0);
| ^^^^^^^^^^^^^^^^
|
= note: required because of the requirements on the impl of `Iterate<'_>` for `{integer}`
For more information about this error, try `rustc --explain E0277`.
error: aborting due to 2 previous errors; 1 warning emitted
Some errors have detailed explanations: E0275, E0277.
For more information about an error, try `rustc --explain E0275`.