diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 45680c90cdc17..96461940c2399 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -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"); diff --git a/src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs b/src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs index 0cd676a9b37f3..b5a2370fcb917 100644 --- a/src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs +++ b/src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs @@ -24,6 +24,7 @@ impl Foo for Number { // ``` // which it is :) type Item where [T]: Sized = [T]; + //~^ ERROR overflow evaluating the requirement ` as Foo>::Item == _ } struct OnlySized where T: Sized { f: T } @@ -43,7 +44,6 @@ impl Bar for T where T: Foo { // can use the bound on `Foo::Item` for this, but that requires // `wf(::Item)`, which is an invalid cycle. type Assoc = OnlySized<::Item>; - //~^ ERROR overflow evaluating the requirement `::Item: Sized` } fn foo() { diff --git a/src/test/ui/generic-associated-types/projection-bound-cycle-generic.stderr b/src/test/ui/generic-associated-types/projection-bound-cycle-generic.stderr index d27e46f6836df..690178a13b17c 100644 --- a/src/test/ui/generic-associated-types/projection-bound-cycle-generic.stderr +++ b/src/test/ui/generic-associated-types/projection-bound-cycle-generic.stderr @@ -7,14 +7,11 @@ LL | #![feature(generic_associated_types)] = note: `#[warn(incomplete_features)]` on by default = note: see issue #44265 for more information -error[E0275]: overflow evaluating the requirement `::Item: Sized` - --> $DIR/projection-bound-cycle-generic.rs:45:5 +error[E0275]: overflow evaluating the requirement ` as Foo>::Item == _` + --> $DIR/projection-bound-cycle-generic.rs:26:5 | -LL | struct OnlySized where T: Sized { f: T } - | - required by this bound in `OnlySized` -... -LL | type Assoc = OnlySized<::Item>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | type Item where [T]: Sized = [T]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/generic-associated-types/projection-bound-cycle.rs b/src/test/ui/generic-associated-types/projection-bound-cycle.rs index 5043fe5c08f51..9f1fa1b9ac105 100644 --- a/src/test/ui/generic-associated-types/projection-bound-cycle.rs +++ b/src/test/ui/generic-associated-types/projection-bound-cycle.rs @@ -26,6 +26,7 @@ impl Foo for Number { // ``` // which it is :) type Item where str: Sized = str; + //~^ ERROR overflow evaluating the requirement `::Item == _ } struct OnlySized where T: Sized { f: T } @@ -45,7 +46,6 @@ impl Bar for T where T: Foo { // can use the bound on `Foo::Item` for this, but that requires // `wf(::Item)`, which is an invalid cycle. type Assoc = OnlySized<::Item>; - //~^ ERROR overflow evaluating the requirement `::Item: Sized` } fn foo() { diff --git a/src/test/ui/generic-associated-types/projection-bound-cycle.stderr b/src/test/ui/generic-associated-types/projection-bound-cycle.stderr index 400b664f97ca9..bc36a828a13fe 100644 --- a/src/test/ui/generic-associated-types/projection-bound-cycle.stderr +++ b/src/test/ui/generic-associated-types/projection-bound-cycle.stderr @@ -7,14 +7,11 @@ LL | #![feature(generic_associated_types)] = note: `#[warn(incomplete_features)]` on by default = note: see issue #44265 for more information -error[E0275]: overflow evaluating the requirement `::Item: Sized` - --> $DIR/projection-bound-cycle.rs:47:5 +error[E0275]: overflow evaluating the requirement `::Item == _` + --> $DIR/projection-bound-cycle.rs:28:5 | -LL | struct OnlySized where T: Sized { f: T } - | - required by this bound in `OnlySized` -... -LL | type Assoc = OnlySized<::Item>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | type Item where str: Sized = str; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/sized/coinductive-1.rs b/src/test/ui/sized/coinductive-1.rs new file mode 100644 index 0000000000000..7bcd0f1fdaf6d --- /dev/null +++ b/src/test/ui/sized/coinductive-1.rs @@ -0,0 +1,14 @@ +// check-pass +struct Node>(C::Assoc); + +trait Trait { + type Assoc; +} + +impl Trait for Vec<()> { + type Assoc = Vec; +} + +fn main() { + let _ = Node::>(Vec::new()); +} diff --git a/src/test/ui/sized/coinductive-2.rs b/src/test/ui/sized/coinductive-2.rs new file mode 100644 index 0000000000000..212274d2e4b6c --- /dev/null +++ b/src/test/ui/sized/coinductive-2.rs @@ -0,0 +1,28 @@ +// run-pass +struct Node> { + _children: C::Collection, +} + +trait CollectionFactory { + type Collection; +} + +impl CollectionFactory for Vec<()> { + type Collection = Vec; +} + +trait Collection: Sized { + fn push(&mut self, v: T); +} + +impl Collection for Vec { + fn push(&mut self, v: T) { + self.push(v) + } +} + +fn main() { + let _ = Node::> { + _children: Vec::new(), + }; +} diff --git a/src/test/ui/sized/recursive-type-1.rs b/src/test/ui/sized/recursive-type-1.rs new file mode 100644 index 0000000000000..cd6805967e524 --- /dev/null +++ b/src/test/ui/sized/recursive-type-1.rs @@ -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::Assoc); + +fn main() {} diff --git a/src/test/ui/sized/recursive-type-2.rs b/src/test/ui/sized/recursive-type-2.rs new file mode 100644 index 0000000000000..7d95417a6ffd9 --- /dev/null +++ b/src/test/ui/sized/recursive-type-2.rs @@ -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::Assoc); + +fn main() { + let x: Foo<()>; +} diff --git a/src/test/ui/sized/recursive-type-2.stderr b/src/test/ui/sized/recursive-type-2.stderr new file mode 100644 index 0000000000000..2102c934da36f --- /dev/null +++ b/src/test/ui/sized/recursive-type-2.stderr @@ -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`.