diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index b509ae6dd3b85..18eb06b83c9df 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2506,6 +2506,10 @@ impl<'tcx> TyCtxt<'tcx> { self.trait_def(trait_def_id).has_auto_impl } + pub fn trait_is_coinductive(self, trait_def_id: DefId) -> bool { + self.trait_is_auto(trait_def_id) || self.lang_items().sized_trait() == Some(trait_def_id) + } + /// Returns layout of a generator. Layout might be unavailable if the /// generator is tainted by errors. pub fn generator_layout(self, def_id: DefId) -> Option<&'tcx GeneratorLayout<'tcx>> { diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index de158a15d54b8..a12f67125bbc0 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -959,7 +959,7 @@ 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_coinductive(data.def_id()), ty::PredicateKind::WellFormed(_) => true, _ => false, }; diff --git a/src/test/ui/generic-associated-types/bugs/issue-80626.rs b/src/test/ui/generic-associated-types/bugs/issue-80626.rs index f6aa6b36e13dc..d6e18010f3b27 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-80626.rs +++ b/src/test/ui/generic-associated-types/bugs/issue-80626.rs @@ -1,7 +1,4 @@ -// check-fail -// known-bug: #80626 - -// This should pass, but it requires `Sized` to be coinductive. +// check-pass trait Allocator { type Allocated; @@ -9,7 +6,7 @@ trait Allocator { enum LinkedList { Head, - Next(A::Allocated) + Next(A::Allocated), } fn main() {} diff --git a/src/test/ui/generic-associated-types/bugs/issue-80626.stderr b/src/test/ui/generic-associated-types/bugs/issue-80626.stderr deleted file mode 100644 index 9a0f332ed4736..0000000000000 --- a/src/test/ui/generic-associated-types/bugs/issue-80626.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0275]: overflow evaluating the requirement `LinkedList: Sized` - --> $DIR/issue-80626.rs:12:10 - | -LL | Next(A::Allocated) - | ^^^^^^^^^^^^^^^^^^ - | -note: required by a bound in `Allocator::Allocated` - --> $DIR/issue-80626.rs:7:20 - | -LL | type Allocated; - | ^ required by this bound in `Allocator::Allocated` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/generic-associated-types/issue-87750.rs b/src/test/ui/generic-associated-types/issue-87750.rs index 0a11a0f3ae0e4..b35657989efb9 100644 --- a/src/test/ui/generic-associated-types/issue-87750.rs +++ b/src/test/ui/generic-associated-types/issue-87750.rs @@ -1,3 +1,5 @@ +// check-pass + trait PointerFamily { type Pointer; } @@ -10,11 +12,13 @@ impl PointerFamily for RcFamily { } #[allow(dead_code)] -enum Node where P::Pointer>: Sized { +enum Node +where + P::Pointer>: Sized, +{ Cons(P::Pointer>), } fn main() { let _list: ::Pointer>; - //~^ ERROR overflow evaluating the requirement `Node: Sized` } diff --git a/src/test/ui/generic-associated-types/issue-87750.stderr b/src/test/ui/generic-associated-types/issue-87750.stderr deleted file mode 100644 index b358ca273ca79..0000000000000 --- a/src/test/ui/generic-associated-types/issue-87750.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0275]: overflow evaluating the requirement `Node: Sized` - --> $DIR/issue-87750.rs:18:16 - | -LL | let _list: ::Pointer>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0275`. 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 58d57df63c1bd..ecf6f69c9fa7e 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 @@ -21,6 +21,7 @@ impl Foo for Number { // ``` // which it is :) type Item = [T] where [T]: Sized; + //~^ ERROR overflow evaluating the requirement ` as Foo>::Item == _` } struct OnlySized where T: Sized { f: T } @@ -40,7 +41,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 27c1a82994a53..aae9a56bb6128 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 @@ -1,14 +1,8 @@ -error[E0275]: overflow evaluating the requirement `::Item: Sized` - --> $DIR/projection-bound-cycle-generic.rs:42:18 +error[E0275]: overflow evaluating the requirement ` as Foo>::Item == _` + --> $DIR/projection-bound-cycle-generic.rs:23:5 | -LL | type Assoc = OnlySized<::Item>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: required by a bound in `OnlySized` - --> $DIR/projection-bound-cycle-generic.rs:26:18 - | -LL | struct OnlySized where T: Sized { f: T } - | ^ required by this bound in `OnlySized` +LL | type Item = [T] where [T]: Sized; + | ^^^^^^^^^ error: aborting due to previous error 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 4cad1f61319ef..b51ae7ef20186 100644 --- a/src/test/ui/generic-associated-types/projection-bound-cycle.rs +++ b/src/test/ui/generic-associated-types/projection-bound-cycle.rs @@ -24,6 +24,7 @@ impl Foo for Number { // ``` // which it is :) type Item = str where str: Sized; + //~^ ERROR overflow evaluating the requirement `::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.stderr b/src/test/ui/generic-associated-types/projection-bound-cycle.stderr index a46518c80da76..b1b8afeecd02f 100644 --- a/src/test/ui/generic-associated-types/projection-bound-cycle.stderr +++ b/src/test/ui/generic-associated-types/projection-bound-cycle.stderr @@ -1,14 +1,8 @@ -error[E0275]: overflow evaluating the requirement `::Item: Sized` - --> $DIR/projection-bound-cycle.rs:45:18 +error[E0275]: overflow evaluating the requirement `::Item == _` + --> $DIR/projection-bound-cycle.rs:26:5 | -LL | type Assoc = OnlySized<::Item>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: required by a bound in `OnlySized` - --> $DIR/projection-bound-cycle.rs:29:18 - | -LL | struct OnlySized where T: Sized { f: T } - | ^ required by this bound in `OnlySized` +LL | type Item = str where str: Sized; + | ^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/sized/coinductive-1-gat.rs b/src/test/ui/sized/coinductive-1-gat.rs new file mode 100644 index 0000000000000..cdf70920f0095 --- /dev/null +++ b/src/test/ui/sized/coinductive-1-gat.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-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..d0e6e9db07e9b --- /dev/null +++ b/src/test/ui/sized/recursive-type-2.stderr @@ -0,0 +1,13 @@ +error[E0391]: cycle detected when computing layout of `Foo<()>` + | + = note: ...which requires computing layout of `<() as A>::Assoc`... + = note: ...which again requires computing layout of `Foo<()>`, completing the cycle +note: cycle used when elaborating drops 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`. diff --git a/src/test/ui/traits/issue-82830.rs b/src/test/ui/traits/issue-82830.rs index c8289b2e30b4d..37bae2e90a595 100644 --- a/src/test/ui/traits/issue-82830.rs +++ b/src/test/ui/traits/issue-82830.rs @@ -1,10 +1,12 @@ +// check-pass + trait A { type B; } type MaybeBox = >>::B; struct P { - t: MaybeBox

, //~ ERROR: overflow evaluating the requirement `P: Sized` + t: MaybeBox

, } impl A for P { diff --git a/src/test/ui/traits/issue-82830.stderr b/src/test/ui/traits/issue-82830.stderr deleted file mode 100644 index 6a597a402156f..0000000000000 --- a/src/test/ui/traits/issue-82830.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0275]: overflow evaluating the requirement `P: Sized` - --> $DIR/issue-82830.rs:7:8 - | -LL | t: MaybeBox

, - | ^^^^^^^^^^^ - | -note: required for `P` to implement `A>` - --> $DIR/issue-82830.rs:10:12 - | -LL | impl A for P { - | ^^^^^^^ ^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0275`.