Skip to content

Commit

Permalink
Rollup merge of #100386 - compiler-errors:sized-coinductive-redux, r=…
Browse files Browse the repository at this point in the history
…lcnr

Make `Sized` coinductive, again

A revival of #83647

---

What exactly makes co-induction sound? Better question: are there any unsoundness risks from this? `Sized` can't be implemented by custom `impl` blocks, nor can it be conditionally implemented based on anything other than child fields being `Sized`, right?

r? `@nikomatsakis` for whenever he gets back from vacation
  • Loading branch information
Manishearth authored Nov 11, 2022
2 parents cd30ccf + fea8d0e commit 76ce198
Show file tree
Hide file tree
Showing 18 changed files with 118 additions and 70 deletions.
4 changes: 4 additions & 0 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>> {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down
7 changes: 2 additions & 5 deletions src/test/ui/generic-associated-types/bugs/issue-80626.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
// check-fail
// known-bug: #80626

// This should pass, but it requires `Sized` to be coinductive.
// check-pass

trait Allocator {
type Allocated<T>;
}

enum LinkedList<A: Allocator> {
Head,
Next(A::Allocated<Self>)
Next(A::Allocated<Self>),
}

fn main() {}
15 changes: 0 additions & 15 deletions src/test/ui/generic-associated-types/bugs/issue-80626.stderr

This file was deleted.

8 changes: 6 additions & 2 deletions src/test/ui/generic-associated-types/issue-87750.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// check-pass

trait PointerFamily {
type Pointer<T>;
}
Expand All @@ -10,11 +12,13 @@ impl PointerFamily for RcFamily {
}

#[allow(dead_code)]
enum Node<T, P: PointerFamily> where P::Pointer<Node<T, P>>: Sized {
enum Node<T, P: PointerFamily>
where
P::Pointer<Node<T, P>>: Sized,
{
Cons(P::Pointer<Node<T, P>>),
}

fn main() {
let _list: <RcFamily as PointerFamily>::Pointer<Node<i32, RcFamily>>;
//~^ ERROR overflow evaluating the requirement `Node<i32, RcFamily>: Sized`
}
9 changes: 0 additions & 9 deletions src/test/ui/generic-associated-types/issue-87750.stderr

This file was deleted.

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

struct OnlySized<T> where T: Sized { f: T }
Expand All @@ -40,7 +41,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
@@ -1,14 +1,8 @@
error[E0275]: overflow evaluating the requirement `<T as Foo>::Item: Sized`
--> $DIR/projection-bound-cycle-generic.rs:42:18
error[E0275]: overflow evaluating the requirement `<Number<T> as Foo>::Item == _`
--> $DIR/projection-bound-cycle-generic.rs:23:5
|
LL | type Assoc = OnlySized<<T as Foo>::Item>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: required by a bound in `OnlySized`
--> $DIR/projection-bound-cycle-generic.rs:26:18
|
LL | struct OnlySized<T> where T: Sized { f: T }
| ^ required by this bound in `OnlySized`
LL | type Item = [T] where [T]: Sized;
| ^^^^^^^^^

error: aborting due to previous error

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ impl Foo for Number {
// ```
// which it is :)
type Item = str where str: Sized;
//~^ ERROR overflow evaluating the requirement `<Number 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
14 changes: 4 additions & 10 deletions src/test/ui/generic-associated-types/projection-bound-cycle.stderr
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
error[E0275]: overflow evaluating the requirement `<T as Foo>::Item: Sized`
--> $DIR/projection-bound-cycle.rs:45:18
error[E0275]: overflow evaluating the requirement `<Number as Foo>::Item == _`
--> $DIR/projection-bound-cycle.rs:26:5
|
LL | type Assoc = OnlySized<<T as Foo>::Item>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: required by a bound in `OnlySized`
--> $DIR/projection-bound-cycle.rs:29:18
|
LL | struct OnlySized<T> where T: Sized { f: T }
| ^ required by this bound in `OnlySized`
LL | type Item = str where str: Sized;
| ^^^^^^^^^

error: aborting due to previous error

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

trait Trait {
type Assoc<T>;
}

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

fn main() {
let _ = Node::<Vec<()>>(Vec::new());
}
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<()>;
}
13 changes: 13 additions & 0 deletions src/test/ui/sized/recursive-type-2.stderr
Original file line number Diff line number Diff line change
@@ -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`.
4 changes: 3 additions & 1 deletion src/test/ui/traits/issue-82830.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
// check-pass

trait A<Y, N> {
type B;
}

type MaybeBox<T> = <T as A<T, Box<T>>>::B;
struct P {
t: MaybeBox<P>, //~ ERROR: overflow evaluating the requirement `P: Sized`
t: MaybeBox<P>,
}

impl<Y, N> A<Y, N> for P {
Expand Down
15 changes: 0 additions & 15 deletions src/test/ui/traits/issue-82830.stderr

This file was deleted.

0 comments on commit 76ce198

Please sign in to comment.