Skip to content

make Sized predicates coinductive #83647

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
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 compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -843,7 +843,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {

fn coinductive_predicate(&self, predicate: ty::Predicate<'tcx>) -> bool {
let result = match predicate.kind().skip_binder() {
ty::PredicateKind::Trait(ref data, _) => self.tcx().trait_is_auto(data.def_id()),
ty::PredicateKind::Trait(ref data, _) => {
self.tcx().trait_is_auto(data.def_id())
|| self.tcx().lang_items().sized_trait() == Some(data.def_id())
}
_ => false,
};
debug!(?predicate, ?result, "coinductive_predicate");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ impl<T> Foo for Number<T> {
// ```
// which it is :)
type Item where [T]: Sized = [T];
//~^ ERROR overflow evaluating the requirement `<Number<T> as Foo>::Item == _
}

struct OnlySized<T> where T: Sized { f: T }
Expand All @@ -43,7 +44,6 @@ impl<T> Bar for T where T: Foo {
// 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: Sized`
}

fn foo<T: Print>() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,11 @@ 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: Sized`
--> $DIR/projection-bound-cycle-generic.rs:45:5
error[E0275]: overflow evaluating the requirement `<Number<T> as Foo>::Item == _`
--> $DIR/projection-bound-cycle-generic.rs:26:5
|
LL | struct OnlySized<T> where T: Sized { f: T }
| - required by this bound in `OnlySized`
...
LL | type Assoc = OnlySized<<T as Foo>::Item>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | type Item where [T]: Sized = [T];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error; 1 warning emitted

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ impl Foo for Number {
// ```
// which it is :)
type Item where str: Sized = str;
//~^ ERROR overflow evaluating the requirement `<Number as Foo>::Item == _
}

struct OnlySized<T> where T: Sized { f: T }
Expand All @@ -45,7 +46,6 @@ impl<T> Bar for T where T: Foo {
// 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: Sized`
}

fn foo<T: Print>() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,11 @@ 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: Sized`
--> $DIR/projection-bound-cycle.rs:47:5
error[E0275]: overflow evaluating the requirement `<Number as Foo>::Item == _`
--> $DIR/projection-bound-cycle.rs:28:5
|
LL | struct OnlySized<T> where T: Sized { f: T }
| - required by this bound in `OnlySized`
...
LL | type Assoc = OnlySized<<T as Foo>::Item>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | type Item where str: Sized = str;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error; 1 warning emitted

Expand Down
14 changes: 14 additions & 0 deletions src/test/ui/sized/coinductive-1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// check-pass
struct Node<C: Trait<Self>>(C::Assoc);

trait Trait<T> {
type Assoc;
}

impl<T> Trait<T> for Vec<()> {
type Assoc = Vec<T>;
}

fn main() {
let _ = Node::<Vec<()>>(Vec::new());
}
28 changes: 28 additions & 0 deletions src/test/ui/sized/coinductive-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// run-pass
struct Node<C: CollectionFactory<Self>> {
_children: C::Collection,
}

trait CollectionFactory<T> {
type Collection;
}

impl<T> CollectionFactory<T> for Vec<()> {
type Collection = Vec<T>;
}

trait Collection<T>: Sized {
fn push(&mut self, v: T);
}

impl<T> Collection<T> for Vec<T> {
fn push(&mut self, v: T) {
self.push(v)
}
}

fn main() {
let _ = Node::<Vec<()>> {
_children: Vec::new(),
};
}
10 changes: 10 additions & 0 deletions src/test/ui/sized/recursive-type-1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// check-pass
trait A { type Assoc; }

impl A for () {
// FIXME: it would be nice for this to at least cause a warning.
type Assoc = Foo<()>;
}
struct Foo<T: A>(T::Assoc);

fn main() {}
13 changes: 13 additions & 0 deletions src/test/ui/sized/recursive-type-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// build-fail
//~^ ERROR cycle detected when computing layout of `Foo<()>`

trait A { type Assoc: ?Sized; }

impl A for () {
type Assoc = Foo<()>;
}
struct Foo<T: A>(T::Assoc);

fn main() {
let x: Foo<()>;
}
12 changes: 12 additions & 0 deletions src/test/ui/sized/recursive-type-2.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
error[E0391]: cycle detected when computing layout of `Foo<()>`
|
= note: ...which again requires computing layout of `Foo<()>`, completing the cycle
note: cycle used when optimizing MIR for `main`
--> $DIR/recursive-type-2.rs:11:1
|
LL | fn main() {
| ^^^^^^^^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0391`.