Skip to content

Commit 2c10ecf

Browse files
committed
Support assoc type defaults for assoc type constraints for trait objects
1 parent 3fc3732 commit 2c10ecf

7 files changed

Lines changed: 129 additions & 13 deletions

File tree

compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
234234
.filter(|item| item.is_type() || item.is_const())
235235
// Traits with RPITITs are simply not dyn compatible (for now).
236236
.filter(|item| !item.is_impl_trait_in_trait())
237-
.map(|item| (item.def_id, trait_ref)),
237+
.map(|item| (item, trait_ref)),
238238
);
239239
}
240240
ty::ClauseKind::Projection(pred) => {
@@ -314,14 +314,24 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
314314
let mut missing_assoc_items = FxIndexSet::default();
315315
let projection_bounds: Vec<_> = ordered_associated_items
316316
.into_iter()
317-
.filter_map(|key @ (def_id, _)| {
318-
if let Some(&assoc) = projection_bounds.get(&key) {
317+
.filter_map(|(item, trait_ref)| {
318+
let def_id = item.def_id;
319+
let key = (def_id, trait_ref);
320+
if let Some(&(assoc, _)) = projection_bounds.get(&key) {
319321
return Some(assoc);
320322
}
321-
if !tcx.generics_require_sized_self(def_id) {
323+
let has_default = item.defaultness(tcx).has_value();
324+
if !has_default && !tcx.generics_require_sized_self(def_id) {
322325
missing_assoc_items.insert(key);
323326
}
324-
None
327+
if has_default {
328+
Some(trait_ref.map_bound(|trait_ref| ty::ProjectionPredicate {
329+
projection_term: ty::AliasTerm::new_from_args(tcx, def_id, trait_ref.args),
330+
term: tcx.type_of(def_id).instantiate(tcx, trait_ref.args).into(),
331+
}))
332+
} else {
333+
None
334+
}
325335
})
326336
.collect();
327337

@@ -394,7 +404,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
394404
})
395405
});
396406

397-
let existential_projections = projection_bounds.into_iter().map(|(bound, _)| {
407+
let existential_projections = projection_bounds.into_iter().map(|bound| {
398408
bound.map_bound(|mut b| {
399409
assert_eq!(b.projection_term.self_ty(), dummy_self);
400410

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#![feature(associated_type_defaults)]
2+
3+
trait Foo {
4+
// This causes cycle, as being effectively `Box<dyn Foo<Assoc = Box<dyn Foo<..>>>>`.
5+
type Assoc = Box<dyn Foo>;
6+
//~^ ERROR: cycle detected when computing type of `Foo::Assoc`
7+
}
8+
9+
trait Bar {
10+
// This does not.
11+
type Assoc = Box<dyn Bar<Assoc = ()>>;
12+
}
13+
14+
fn main() {}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error[E0391]: cycle detected when computing type of `Foo::Assoc`
2+
--> $DIR/defaults-on-trait-object-cycle.rs:5:5
3+
|
4+
LL | type Assoc = Box<dyn Foo>;
5+
| ^^^^^^^^^^
6+
|
7+
= note: ...which immediately requires computing type of `Foo::Assoc` again
8+
note: cycle used when checking that `Foo` is well-formed
9+
--> $DIR/defaults-on-trait-object-cycle.rs:3:1
10+
|
11+
LL | trait Foo {
12+
| ^^^^^^^^^
13+
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
14+
15+
error: aborting due to 1 previous error
16+
17+
For more information about this error, try `rustc --explain E0391`.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#![feature(associated_type_defaults)]
2+
3+
trait Foo {
4+
type Assoc: Default = ();
5+
6+
fn foo(&self) -> Self::Assoc {
7+
Default::default()
8+
}
9+
}
10+
11+
// The assoc type constraint can be omitted for the assoc type with a default.
12+
type FooObj = Box<dyn Foo>;
13+
14+
trait Bar {
15+
type Assoc1 = i32;
16+
type Assoc2;
17+
}
18+
19+
// We can't omit assoc type constraints for an assoc type without a default value.
20+
type BarObj1 = Box<dyn Bar>;
21+
//~^ ERROR: the value of the associated type `Assoc2` in `Bar` must be specified
22+
23+
type BarObj2 = Box<dyn Bar<Assoc2 = ()>>;
24+
25+
type BarObj3 = Box<dyn Bar<Assoc1 = u32, Assoc2 = i32>>;
26+
27+
fn check_projs(foo1: &dyn Foo, foo2: &dyn Foo<Assoc = bool>) {
28+
let _: () = foo1.foo();
29+
let _: () = foo2.foo();
30+
//~^ ERROR: mismatched types
31+
}
32+
33+
fn main() {}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
error[E0191]: the value of the associated type `Assoc2` in `Bar` must be specified
2+
--> $DIR/defaults-on-trait-object.rs:20:24
3+
|
4+
LL | type Assoc2;
5+
| ----------- `Assoc2` defined here
6+
...
7+
LL | type BarObj1 = Box<dyn Bar>;
8+
| ^^^
9+
|
10+
help: specify the associated type
11+
|
12+
LL | type BarObj1 = Box<dyn Bar<Assoc2 = /* Type */>>;
13+
| +++++++++++++++++++++
14+
15+
error[E0308]: mismatched types
16+
--> $DIR/defaults-on-trait-object.rs:29:17
17+
|
18+
LL | let _: () = foo2.foo();
19+
| -- ^^^^^^^^^^ expected `()`, found `bool`
20+
| |
21+
| expected due to this
22+
23+
error: aborting due to 2 previous errors
24+
25+
Some errors have detailed explanations: E0191, E0308.
26+
For more information about an error, try `rustc --explain E0191`.

tests/ui/associated-types/issue-23595-1.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ trait Hierarchy {
66
type Value;
77
type ChildKey;
88
type Children = dyn Index<Self::ChildKey, Output = dyn Hierarchy>;
9-
//~^ ERROR: the value of the associated types
9+
//~^ ERROR: cycle detected when computing type of `Hierarchy::Children`
10+
//~| ERROR: the value of the associated types
1011

1112
fn data(&self) -> Option<(Self::Value, Self::Children)>;
1213
}
Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,33 @@
1-
error[E0191]: the value of the associated types `Value`, `ChildKey` and `Children` in `Hierarchy` must be specified
1+
error[E0391]: cycle detected when computing type of `Hierarchy::Children`
2+
--> $DIR/issue-23595-1.rs:8:5
3+
|
4+
LL | type Children = dyn Index<Self::ChildKey, Output = dyn Hierarchy>;
5+
| ^^^^^^^^^^^^^
6+
|
7+
= note: ...which immediately requires computing type of `Hierarchy::Children` again
8+
note: cycle used when checking that `Hierarchy` is well-formed
9+
--> $DIR/issue-23595-1.rs:5:1
10+
|
11+
LL | trait Hierarchy {
12+
| ^^^^^^^^^^^^^^^
13+
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
14+
15+
error[E0191]: the value of the associated types `Value` and `ChildKey` in `Hierarchy` must be specified
216
--> $DIR/issue-23595-1.rs:8:60
317
|
418
LL | type Value;
519
| ---------- `Value` defined here
620
LL | type ChildKey;
721
| ------------- `ChildKey` defined here
822
LL | type Children = dyn Index<Self::ChildKey, Output = dyn Hierarchy>;
9-
| ------------- `Children` defined here ^^^^^^^^^
23+
| ^^^^^^^^^
1024
|
1125
help: specify the associated types
1226
|
13-
LL | type Children = dyn Index<Self::ChildKey, Output = dyn Hierarchy<Value = /* Type */, ChildKey = /* Type */, Children = /* Type */>>;
14-
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
27+
LL | type Children = dyn Index<Self::ChildKey, Output = dyn Hierarchy<Value = /* Type */, ChildKey = /* Type */>>;
28+
| +++++++++++++++++++++++++++++++++++++++++++
1529

16-
error: aborting due to 1 previous error
30+
error: aborting due to 2 previous errors
1731

18-
For more information about this error, try `rustc --explain E0191`.
32+
Some errors have detailed explanations: E0191, E0391.
33+
For more information about an error, try `rustc --explain E0191`.

0 commit comments

Comments
 (0)