Skip to content

Commit 76ce198

Browse files
authored
Rollup merge of rust-lang#100386 - compiler-errors:sized-coinductive-redux, r=lcnr
Make `Sized` coinductive, again A revival of rust-lang#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
2 parents cd30ccf + fea8d0e commit 76ce198

18 files changed

+118
-70
lines changed

compiler/rustc_middle/src/ty/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -2506,6 +2506,10 @@ impl<'tcx> TyCtxt<'tcx> {
25062506
self.trait_def(trait_def_id).has_auto_impl
25072507
}
25082508

2509+
pub fn trait_is_coinductive(self, trait_def_id: DefId) -> bool {
2510+
self.trait_is_auto(trait_def_id) || self.lang_items().sized_trait() == Some(trait_def_id)
2511+
}
2512+
25092513
/// Returns layout of a generator. Layout might be unavailable if the
25102514
/// generator is tainted by errors.
25112515
pub fn generator_layout(self, def_id: DefId) -> Option<&'tcx GeneratorLayout<'tcx>> {

compiler/rustc_trait_selection/src/traits/select/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -959,7 +959,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
959959

960960
fn coinductive_predicate(&self, predicate: ty::Predicate<'tcx>) -> bool {
961961
let result = match predicate.kind().skip_binder() {
962-
ty::PredicateKind::Trait(ref data) => self.tcx().trait_is_auto(data.def_id()),
962+
ty::PredicateKind::Trait(ref data) => self.tcx().trait_is_coinductive(data.def_id()),
963963
ty::PredicateKind::WellFormed(_) => true,
964964
_ => false,
965965
};
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
1-
// check-fail
2-
// known-bug: #80626
3-
4-
// This should pass, but it requires `Sized` to be coinductive.
1+
// check-pass
52

63
trait Allocator {
74
type Allocated<T>;
85
}
96

107
enum LinkedList<A: Allocator> {
118
Head,
12-
Next(A::Allocated<Self>)
9+
Next(A::Allocated<Self>),
1310
}
1411

1512
fn main() {}

src/test/ui/generic-associated-types/bugs/issue-80626.stderr

-15
This file was deleted.

src/test/ui/generic-associated-types/issue-87750.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// check-pass
2+
13
trait PointerFamily {
24
type Pointer<T>;
35
}
@@ -10,11 +12,13 @@ impl PointerFamily for RcFamily {
1012
}
1113

1214
#[allow(dead_code)]
13-
enum Node<T, P: PointerFamily> where P::Pointer<Node<T, P>>: Sized {
15+
enum Node<T, P: PointerFamily>
16+
where
17+
P::Pointer<Node<T, P>>: Sized,
18+
{
1419
Cons(P::Pointer<Node<T, P>>),
1520
}
1621

1722
fn main() {
1823
let _list: <RcFamily as PointerFamily>::Pointer<Node<i32, RcFamily>>;
19-
//~^ ERROR overflow evaluating the requirement `Node<i32, RcFamily>: Sized`
2024
}

src/test/ui/generic-associated-types/issue-87750.stderr

-9
This file was deleted.

src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ impl<T> Foo for Number<T> {
2121
// ```
2222
// which it is :)
2323
type Item = [T] where [T]: Sized;
24+
//~^ ERROR overflow evaluating the requirement `<Number<T> as Foo>::Item == _`
2425
}
2526

2627
struct OnlySized<T> where T: Sized { f: T }
@@ -40,7 +41,6 @@ impl<T> Bar for T where T: Foo {
4041
// can use the bound on `Foo::Item` for this, but that requires
4142
// `wf(<T as Foo>::Item)`, which is an invalid cycle.
4243
type Assoc = OnlySized<<T as Foo>::Item>;
43-
//~^ ERROR overflow evaluating the requirement `<T as Foo>::Item: Sized`
4444
}
4545

4646
fn foo<T: Print>() {

src/test/ui/generic-associated-types/projection-bound-cycle-generic.stderr

+4-10
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,8 @@
1-
error[E0275]: overflow evaluating the requirement `<T as Foo>::Item: Sized`
2-
--> $DIR/projection-bound-cycle-generic.rs:42:18
1+
error[E0275]: overflow evaluating the requirement `<Number<T> as Foo>::Item == _`
2+
--> $DIR/projection-bound-cycle-generic.rs:23:5
33
|
4-
LL | type Assoc = OnlySized<<T as Foo>::Item>;
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
6-
|
7-
note: required by a bound in `OnlySized`
8-
--> $DIR/projection-bound-cycle-generic.rs:26:18
9-
|
10-
LL | struct OnlySized<T> where T: Sized { f: T }
11-
| ^ required by this bound in `OnlySized`
4+
LL | type Item = [T] where [T]: Sized;
5+
| ^^^^^^^^^
126

137
error: aborting due to previous error
148

src/test/ui/generic-associated-types/projection-bound-cycle.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ impl Foo for Number {
2424
// ```
2525
// which it is :)
2626
type Item = str where str: Sized;
27+
//~^ ERROR overflow evaluating the requirement `<Number as Foo>::Item == _`
2728
}
2829

2930
struct OnlySized<T> where T: Sized { f: T }
@@ -43,7 +44,6 @@ impl<T> Bar for T where T: Foo {
4344
// can use the bound on `Foo::Item` for this, but that requires
4445
// `wf(<T as Foo>::Item)`, which is an invalid cycle.
4546
type Assoc = OnlySized<<T as Foo>::Item>;
46-
//~^ ERROR overflow evaluating the requirement `<T as Foo>::Item: Sized`
4747
}
4848

4949
fn foo<T: Print>() {

src/test/ui/generic-associated-types/projection-bound-cycle.stderr

+4-10
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,8 @@
1-
error[E0275]: overflow evaluating the requirement `<T as Foo>::Item: Sized`
2-
--> $DIR/projection-bound-cycle.rs:45:18
1+
error[E0275]: overflow evaluating the requirement `<Number as Foo>::Item == _`
2+
--> $DIR/projection-bound-cycle.rs:26:5
33
|
4-
LL | type Assoc = OnlySized<<T as Foo>::Item>;
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
6-
|
7-
note: required by a bound in `OnlySized`
8-
--> $DIR/projection-bound-cycle.rs:29:18
9-
|
10-
LL | struct OnlySized<T> where T: Sized { f: T }
11-
| ^ required by this bound in `OnlySized`
4+
LL | type Item = str where str: Sized;
5+
| ^^^^^^^^^
126

137
error: aborting due to previous error
148

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// check-pass
2+
struct Node<C: Trait>(C::Assoc::<Self>);
3+
4+
trait Trait {
5+
type Assoc<T>;
6+
}
7+
8+
impl Trait for Vec<()> {
9+
type Assoc<T> = Vec<T>;
10+
}
11+
12+
fn main() {
13+
let _ = Node::<Vec<()>>(Vec::new());
14+
}

src/test/ui/sized/coinductive-1.rs

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// check-pass
2+
struct Node<C: Trait<Self>>(C::Assoc);
3+
4+
trait Trait<T> {
5+
type Assoc;
6+
}
7+
8+
impl<T> Trait<T> for Vec<()> {
9+
type Assoc = Vec<T>;
10+
}
11+
12+
fn main() {
13+
let _ = Node::<Vec<()>>(Vec::new());
14+
}

src/test/ui/sized/coinductive-2.rs

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// run-pass
2+
struct Node<C: CollectionFactory<Self>> {
3+
_children: C::Collection,
4+
}
5+
6+
trait CollectionFactory<T> {
7+
type Collection;
8+
}
9+
10+
impl<T> CollectionFactory<T> for Vec<()> {
11+
type Collection = Vec<T>;
12+
}
13+
14+
trait Collection<T>: Sized {
15+
fn push(&mut self, v: T);
16+
}
17+
18+
impl<T> Collection<T> for Vec<T> {
19+
fn push(&mut self, v: T) {
20+
self.push(v)
21+
}
22+
}
23+
24+
fn main() {
25+
let _ = Node::<Vec<()>> {
26+
_children: Vec::new(),
27+
};
28+
}

src/test/ui/sized/recursive-type-1.rs

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// check-pass
2+
trait A { type Assoc; }
3+
4+
impl A for () {
5+
// FIXME: it would be nice for this to at least cause a warning.
6+
type Assoc = Foo<()>;
7+
}
8+
struct Foo<T: A>(T::Assoc);
9+
10+
fn main() {}

src/test/ui/sized/recursive-type-2.rs

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// build-fail
2+
//~^ ERROR cycle detected when computing layout of `Foo<()>`
3+
4+
trait A { type Assoc: ?Sized; }
5+
6+
impl A for () {
7+
type Assoc = Foo<()>;
8+
}
9+
struct Foo<T: A>(T::Assoc);
10+
11+
fn main() {
12+
let x: Foo<()>;
13+
}
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error[E0391]: cycle detected when computing layout of `Foo<()>`
2+
|
3+
= note: ...which requires computing layout of `<() as A>::Assoc`...
4+
= note: ...which again requires computing layout of `Foo<()>`, completing the cycle
5+
note: cycle used when elaborating drops for `main`
6+
--> $DIR/recursive-type-2.rs:11:1
7+
|
8+
LL | fn main() {
9+
| ^^^^^^^^^
10+
11+
error: aborting due to previous error
12+
13+
For more information about this error, try `rustc --explain E0391`.

src/test/ui/traits/issue-82830.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
// check-pass
2+
13
trait A<Y, N> {
24
type B;
35
}
46

57
type MaybeBox<T> = <T as A<T, Box<T>>>::B;
68
struct P {
7-
t: MaybeBox<P>, //~ ERROR: overflow evaluating the requirement `P: Sized`
9+
t: MaybeBox<P>,
810
}
911

1012
impl<Y, N> A<Y, N> for P {

src/test/ui/traits/issue-82830.stderr

-15
This file was deleted.

0 commit comments

Comments
 (0)