Skip to content

Commit 35eac42

Browse files
authored
Rollup merge of #84622 - jackh726:gats-trait-object, r=nikomatsakis
Make traits with GATs not object safe Closes #81823 r? `@nikomatsakis`
2 parents 54ad5cb + 857cb4d commit 35eac42

15 files changed

+179
-25
lines changed

compiler/rustc_middle/src/traits/mod.rs

+8
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,9 @@ pub enum ObjectSafetyViolation {
670670

671671
/// Associated const.
672672
AssocConst(Symbol, Span),
673+
674+
/// GAT
675+
GAT(Symbol, Span),
673676
}
674677

675678
impl ObjectSafetyViolation {
@@ -715,6 +718,9 @@ impl ObjectSafetyViolation {
715718
format!("it contains associated `const` `{}`", name).into()
716719
}
717720
ObjectSafetyViolation::AssocConst(..) => "it contains this associated `const`".into(),
721+
ObjectSafetyViolation::GAT(name, _) => {
722+
format!("it contains the generic associated type `{}`", name).into()
723+
}
718724
}
719725
}
720726

@@ -773,6 +779,7 @@ impl ObjectSafetyViolation {
773779
);
774780
}
775781
ObjectSafetyViolation::AssocConst(name, _)
782+
| ObjectSafetyViolation::GAT(name, _)
776783
| ObjectSafetyViolation::Method(name, ..) => {
777784
err.help(&format!("consider moving `{}` to another trait", name));
778785
}
@@ -786,6 +793,7 @@ impl ObjectSafetyViolation {
786793
ObjectSafetyViolation::SupertraitSelf(spans)
787794
| ObjectSafetyViolation::SizedSelf(spans) => spans.clone(),
788795
ObjectSafetyViolation::AssocConst(_, span)
796+
| ObjectSafetyViolation::GAT(_, span)
789797
| ObjectSafetyViolation::Method(_, _, span)
790798
if *span != DUMMY_SP =>
791799
{

compiler/rustc_trait_selection/src/traits/object_safety.rs

+8
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,14 @@ fn object_safety_violations_for_trait(
132132
.map(|item| ObjectSafetyViolation::AssocConst(item.ident.name, item.ident.span)),
133133
);
134134

135+
violations.extend(
136+
tcx.associated_items(trait_def_id)
137+
.in_definition_order()
138+
.filter(|item| item.kind == ty::AssocKind::Type)
139+
.filter(|item| !tcx.generics_of(item.def_id).params.is_empty())
140+
.map(|item| ObjectSafetyViolation::GAT(item.ident.name, item.ident.span)),
141+
);
142+
135143
debug!(
136144
"object_safety_violations_for_trait(trait_def_id={:?}) = {:?}",
137145
trait_def_id, violations

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

+3-4
Original file line numberDiff line numberDiff line change
@@ -462,12 +462,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
462462

463463
for assoc_type in assoc_types {
464464
if !tcx.generics_of(assoc_type).params.is_empty() {
465-
// FIXME(generic_associated_types) generate placeholders to
466-
// extend the trait substs.
467-
tcx.sess.span_fatal(
465+
tcx.sess.delay_span_bug(
468466
obligation.cause.span,
469-
"generic associated types in trait objects are not supported yet",
467+
"GATs in trait object shouldn't have been considered",
470468
);
469+
return Err(SelectionError::Unimplemented);
471470
}
472471
// This maybe belongs in wf, but that can't (doesn't) handle
473472
// higher-ranked things.

src/test/ui/generic-associated-types/gat-in-trait-path.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
// check-pass
2-
31
#![feature(generic_associated_types)]
42
//~^ WARNING: the feature `generic_associated_types` is incomplete
53
#![feature(associated_type_defaults)]
@@ -22,6 +20,7 @@ impl<T> Foo for Fooer<T> {
2220
}
2321

2422
fn f(_arg : Box<dyn for<'a> Foo<A<'a> = &'a ()>>) {}
23+
//~^ the trait `Foo` cannot be made into an object
2524

2625

2726
fn main() {
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,27 @@
11
warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
2-
--> $DIR/gat-in-trait-path.rs:3:12
2+
--> $DIR/gat-in-trait-path.rs:1:12
33
|
44
LL | #![feature(generic_associated_types)]
55
| ^^^^^^^^^^^^^^^^^^^^^^^^
66
|
77
= note: `#[warn(incomplete_features)]` on by default
88
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
99

10-
warning: 1 warning emitted
10+
error[E0038]: the trait `Foo` cannot be made into an object
11+
--> $DIR/gat-in-trait-path.rs:22:13
12+
|
13+
LL | fn f(_arg : Box<dyn for<'a> Foo<A<'a> = &'a ()>>) {}
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object
15+
|
16+
= help: consider moving `A` to another trait
17+
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
18+
--> $DIR/gat-in-trait-path.rs:6:10
19+
|
20+
LL | trait Foo {
21+
| --- this trait cannot be made into an object...
22+
LL | type A<'a> where Self: 'a;
23+
| ^ ...because it contains the generic associated type `A`
24+
25+
error: aborting due to previous error; 1 warning emitted
1126

27+
For more information about this error, try `rustc --explain E0038`.
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
// check-pass
2-
31
#![feature(generic_associated_types)]
42
//~^ WARNING: the feature `generic_associated_types` is incomplete
53

@@ -8,5 +6,6 @@ trait X {
86
}
97

108
fn _func1<'a>(_x: Box<dyn X<Y<'a>=&'a ()>>) {}
9+
//~^ ERROR the trait `X` cannot be made into an object
1110

1211
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,27 @@
11
warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
2-
--> $DIR/issue-67510-pass.rs:3:12
2+
--> $DIR/issue-67510-pass.rs:1:12
33
|
44
LL | #![feature(generic_associated_types)]
55
| ^^^^^^^^^^^^^^^^^^^^^^^^
66
|
77
= note: `#[warn(incomplete_features)]` on by default
88
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
99

10-
warning: 1 warning emitted
10+
error[E0038]: the trait `X` cannot be made into an object
11+
--> $DIR/issue-67510-pass.rs:8:19
12+
|
13+
LL | fn _func1<'a>(_x: Box<dyn X<Y<'a>=&'a ()>>) {}
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object
15+
|
16+
= help: consider moving `Y` to another trait
17+
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
18+
--> $DIR/issue-67510-pass.rs:5:10
19+
|
20+
LL | trait X {
21+
| - this trait cannot be made into an object...
22+
LL | type Y<'a>;
23+
| ^ ...because it contains the generic associated type `Y`
24+
25+
error: aborting due to previous error; 1 warning emitted
1126

27+
For more information about this error, try `rustc --explain E0038`.

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

+2
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,6 @@ impl SuperTrait for SuperStruct {
3636

3737
fn main() {
3838
let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
39+
//~^ ERROR the trait `SuperTrait` cannot be made into an object
40+
//~^^ ERROR the trait `SuperTrait` cannot be made into an object
3941
}

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

+35-2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,39 @@ help: use angle brackets to add missing lifetime argument
2323
LL | type SubType<'a><'a>: SubTrait;
2424
| ^^^^
2525

26-
error: aborting due to previous error; 1 warning emitted
26+
error[E0038]: the trait `SuperTrait` cannot be made into an object
27+
--> $DIR/issue-76535.rs:38:14
28+
|
29+
LL | let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
30+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object
31+
|
32+
= help: consider moving `SubType` to another trait
33+
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
34+
--> $DIR/issue-76535.rs:7:10
35+
|
36+
LL | pub trait SuperTrait {
37+
| ---------- this trait cannot be made into an object...
38+
LL | type SubType<'a>: SubTrait;
39+
| ^^^^^^^ ...because it contains the generic associated type `SubType`
40+
41+
error[E0038]: the trait `SuperTrait` cannot be made into an object
42+
--> $DIR/issue-76535.rs:38:57
43+
|
44+
LL | let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
45+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object
46+
|
47+
= help: consider moving `SubType` to another trait
48+
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
49+
--> $DIR/issue-76535.rs:7:10
50+
|
51+
LL | pub trait SuperTrait {
52+
| ---------- this trait cannot be made into an object...
53+
LL | type SubType<'a>: SubTrait;
54+
| ^^^^^^^ ...because it contains the generic associated type `SubType`
55+
= note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn SuperTrait<SubType = SubStruct<'_>>>>` for `Box<SuperStruct>`
56+
= note: required by cast to type `Box<dyn SuperTrait<SubType = SubStruct<'_>>>`
57+
58+
error: aborting due to 3 previous errors; 1 warning emitted
2759

28-
For more information about this error, try `rustc --explain E0107`.
60+
Some errors have detailed explanations: E0038, E0107.
61+
For more information about an error, try `rustc --explain E0038`.

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

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ trait CollectionFamily {
77
}
88
fn floatify() {
99
Box::new(Family) as &dyn CollectionFamily<Member=usize>
10+
//~^ the trait `CollectionFamily` cannot be made into an object
1011
}
1112

1213
struct Family;

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

+18-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,22 @@ help: use angle brackets to add missing type argument
1414
LL | type Member<T><T>;
1515
| ^^^
1616

17-
error: aborting due to previous error
17+
error[E0038]: the trait `CollectionFamily` cannot be made into an object
18+
--> $DIR/issue-78671.rs:9:25
19+
|
20+
LL | Box::new(Family) as &dyn CollectionFamily<Member=usize>
21+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `CollectionFamily` cannot be made into an object
22+
|
23+
= help: consider moving `Member` to another trait
24+
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
25+
--> $DIR/issue-78671.rs:5:10
26+
|
27+
LL | trait CollectionFamily {
28+
| ---------------- this trait cannot be made into an object...
29+
LL | type Member<T>;
30+
| ^^^^^^ ...because it contains the generic associated type `Member`
31+
32+
error: aborting due to 2 previous errors
1833

19-
For more information about this error, try `rustc --explain E0107`.
34+
Some errors have detailed explanations: E0038, E0107.
35+
For more information about an error, try `rustc --explain E0038`.

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -42,5 +42,6 @@ impl<K, V: Default> MapLike<K, V> for Source {
4242
fn main() {
4343
let m = Box::new(std::collections::BTreeMap::<u8, u8>::new())
4444
as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>;
45-
//~^^ ERROR type mismatch resolving
45+
//~^^ the trait `MapLike` cannot be made into an object
46+
//~^^ the trait `MapLike` cannot be made into an object
4647
}

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

+30-8
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,39 @@ help: use angle brackets to add missing lifetime argument
1414
LL | type VRefCont<'a><'a>: RefCont<'a, V>;
1515
| ^^^^
1616

17-
error[E0271]: type mismatch resolving `<BTreeMap<u8, u8> as MapLike<u8, u8>>::VRefCont<'static> == (dyn RefCont<'_, u8> + 'static)`
17+
error[E0038]: the trait `MapLike` cannot be made into an object
18+
--> $DIR/issue-79422.rs:44:12
19+
|
20+
LL | as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>;
21+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object
22+
|
23+
= help: consider moving `VRefCont` to another trait
24+
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
25+
--> $DIR/issue-79422.rs:21:10
26+
|
27+
LL | trait MapLike<K, V> {
28+
| ------- this trait cannot be made into an object...
29+
LL | type VRefCont<'a>: RefCont<'a, V>;
30+
| ^^^^^^^^ ...because it contains the generic associated type `VRefCont`
31+
32+
error[E0038]: the trait `MapLike` cannot be made into an object
1833
--> $DIR/issue-79422.rs:43:13
1934
|
2035
LL | let m = Box::new(std::collections::BTreeMap::<u8, u8>::new())
21-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn RefCont`, found reference
36+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object
37+
|
38+
= help: consider moving `VRefCont` to another trait
39+
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
40+
--> $DIR/issue-79422.rs:21:10
2241
|
23-
= note: expected trait object `(dyn RefCont<'_, u8> + 'static)`
24-
found reference `&'static u8`
25-
= note: required for the cast to the object type `dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>`
42+
LL | trait MapLike<K, V> {
43+
| ------- this trait cannot be made into an object...
44+
LL | type VRefCont<'a>: RefCont<'a, V>;
45+
| ^^^^^^^^ ...because it contains the generic associated type `VRefCont`
46+
= note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>>` for `Box<BTreeMap<u8, u8>>`
47+
= note: required by cast to type `Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>`
2648

27-
error: aborting due to 2 previous errors
49+
error: aborting due to 3 previous errors
2850

29-
Some errors have detailed explanations: E0107, E0271.
30-
For more information about an error, try `rustc --explain E0107`.
51+
Some errors have detailed explanations: E0038, E0107.
52+
For more information about an error, try `rustc --explain E0038`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#![feature(generic_associated_types)]
2+
#![allow(incomplete_features)]
3+
4+
trait StreamingIterator {
5+
type Item<'a> where Self: 'a;
6+
fn size_hint(&self) -> (usize, Option<usize>);
7+
// Uncommenting makes `StreamingIterator` not object safe
8+
// fn next(&mut self) -> Self::Item<'_>;
9+
}
10+
11+
fn min_size(x: &mut dyn for<'a> StreamingIterator<Item<'a> = &'a i32>) -> usize {
12+
//~^ the trait `StreamingIterator` cannot be made into an object
13+
x.size_hint().0
14+
}
15+
16+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error[E0038]: the trait `StreamingIterator` cannot be made into an object
2+
--> $DIR/trait-objects.rs:11:16
3+
|
4+
LL | fn min_size(x: &mut dyn for<'a> StreamingIterator<Item<'a> = &'a i32>) -> usize {
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `StreamingIterator` cannot be made into an object
6+
|
7+
= help: consider moving `Item` to another trait
8+
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
9+
--> $DIR/trait-objects.rs:5:10
10+
|
11+
LL | trait StreamingIterator {
12+
| ----------------- this trait cannot be made into an object...
13+
LL | type Item<'a> where Self: 'a;
14+
| ^^^^ ...because it contains the generic associated type `Item`
15+
16+
error: aborting due to previous error
17+
18+
For more information about this error, try `rustc --explain E0038`.

0 commit comments

Comments
 (0)