mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-19 11:12:43 +00:00
Make traits with GATs not object safe
This commit is contained in:
parent
1919b3f227
commit
857cb4de20
@ -670,6 +670,9 @@ pub enum ObjectSafetyViolation {
|
||||
|
||||
/// Associated const.
|
||||
AssocConst(Symbol, Span),
|
||||
|
||||
/// GAT
|
||||
GAT(Symbol, Span),
|
||||
}
|
||||
|
||||
impl ObjectSafetyViolation {
|
||||
@ -715,6 +718,9 @@ impl ObjectSafetyViolation {
|
||||
format!("it contains associated `const` `{}`", name).into()
|
||||
}
|
||||
ObjectSafetyViolation::AssocConst(..) => "it contains this associated `const`".into(),
|
||||
ObjectSafetyViolation::GAT(name, _) => {
|
||||
format!("it contains the generic associated type `{}`", name).into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -773,6 +779,7 @@ impl ObjectSafetyViolation {
|
||||
);
|
||||
}
|
||||
ObjectSafetyViolation::AssocConst(name, _)
|
||||
| ObjectSafetyViolation::GAT(name, _)
|
||||
| ObjectSafetyViolation::Method(name, ..) => {
|
||||
err.help(&format!("consider moving `{}` to another trait", name));
|
||||
}
|
||||
@ -786,6 +793,7 @@ impl ObjectSafetyViolation {
|
||||
ObjectSafetyViolation::SupertraitSelf(spans)
|
||||
| ObjectSafetyViolation::SizedSelf(spans) => spans.clone(),
|
||||
ObjectSafetyViolation::AssocConst(_, span)
|
||||
| ObjectSafetyViolation::GAT(_, span)
|
||||
| ObjectSafetyViolation::Method(_, _, span)
|
||||
if *span != DUMMY_SP =>
|
||||
{
|
||||
|
@ -132,6 +132,14 @@ fn object_safety_violations_for_trait(
|
||||
.map(|item| ObjectSafetyViolation::AssocConst(item.ident.name, item.ident.span)),
|
||||
);
|
||||
|
||||
violations.extend(
|
||||
tcx.associated_items(trait_def_id)
|
||||
.in_definition_order()
|
||||
.filter(|item| item.kind == ty::AssocKind::Type)
|
||||
.filter(|item| !tcx.generics_of(item.def_id).params.is_empty())
|
||||
.map(|item| ObjectSafetyViolation::GAT(item.ident.name, item.ident.span)),
|
||||
);
|
||||
|
||||
debug!(
|
||||
"object_safety_violations_for_trait(trait_def_id={:?}) = {:?}",
|
||||
trait_def_id, violations
|
||||
|
@ -462,12 +462,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
|
||||
for assoc_type in assoc_types {
|
||||
if !tcx.generics_of(assoc_type).params.is_empty() {
|
||||
// FIXME(generic_associated_types) generate placeholders to
|
||||
// extend the trait substs.
|
||||
tcx.sess.span_fatal(
|
||||
tcx.sess.delay_span_bug(
|
||||
obligation.cause.span,
|
||||
"generic associated types in trait objects are not supported yet",
|
||||
"GATs in trait object shouldn't have been considered",
|
||||
);
|
||||
return Err(SelectionError::Unimplemented);
|
||||
}
|
||||
// This maybe belongs in wf, but that can't (doesn't) handle
|
||||
// higher-ranked things.
|
||||
|
@ -1,5 +1,3 @@
|
||||
// check-pass
|
||||
|
||||
#![feature(generic_associated_types)]
|
||||
//~^ WARNING: the feature `generic_associated_types` is incomplete
|
||||
#![feature(associated_type_defaults)]
|
||||
@ -22,6 +20,7 @@ impl<T> Foo for Fooer<T> {
|
||||
}
|
||||
|
||||
fn f(_arg : Box<dyn for<'a> Foo<A<'a> = &'a ()>>) {}
|
||||
//~^ the trait `Foo` cannot be made into an object
|
||||
|
||||
|
||||
fn main() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/gat-in-trait-path.rs:3:12
|
||||
--> $DIR/gat-in-trait-path.rs:1:12
|
||||
|
|
||||
LL | #![feature(generic_associated_types)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -7,5 +7,21 @@ LL | #![feature(generic_associated_types)]
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
|
||||
warning: 1 warning emitted
|
||||
error[E0038]: the trait `Foo` cannot be made into an object
|
||||
--> $DIR/gat-in-trait-path.rs:22:13
|
||||
|
|
||||
LL | fn f(_arg : Box<dyn for<'a> Foo<A<'a> = &'a ()>>) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object
|
||||
|
|
||||
= help: consider moving `A` to another trait
|
||||
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>
|
||||
--> $DIR/gat-in-trait-path.rs:6:10
|
||||
|
|
||||
LL | trait Foo {
|
||||
| --- this trait cannot be made into an object...
|
||||
LL | type A<'a> where Self: 'a;
|
||||
| ^ ...because it contains the generic associated type `A`
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0038`.
|
||||
|
@ -1,5 +1,3 @@
|
||||
// check-pass
|
||||
|
||||
#![feature(generic_associated_types)]
|
||||
//~^ WARNING: the feature `generic_associated_types` is incomplete
|
||||
|
||||
@ -8,5 +6,6 @@ trait X {
|
||||
}
|
||||
|
||||
fn _func1<'a>(_x: Box<dyn X<Y<'a>=&'a ()>>) {}
|
||||
//~^ ERROR the trait `X` cannot be made into an object
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,5 +1,5 @@
|
||||
warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/issue-67510-pass.rs:3:12
|
||||
--> $DIR/issue-67510-pass.rs:1:12
|
||||
|
|
||||
LL | #![feature(generic_associated_types)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -7,5 +7,21 @@ LL | #![feature(generic_associated_types)]
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
|
||||
warning: 1 warning emitted
|
||||
error[E0038]: the trait `X` cannot be made into an object
|
||||
--> $DIR/issue-67510-pass.rs:8:19
|
||||
|
|
||||
LL | fn _func1<'a>(_x: Box<dyn X<Y<'a>=&'a ()>>) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object
|
||||
|
|
||||
= help: consider moving `Y` to another trait
|
||||
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>
|
||||
--> $DIR/issue-67510-pass.rs:5:10
|
||||
|
|
||||
LL | trait X {
|
||||
| - this trait cannot be made into an object...
|
||||
LL | type Y<'a>;
|
||||
| ^ ...because it contains the generic associated type `Y`
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0038`.
|
||||
|
@ -36,4 +36,6 @@ impl SuperTrait for SuperStruct {
|
||||
|
||||
fn main() {
|
||||
let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
|
||||
//~^ ERROR the trait `SuperTrait` cannot be made into an object
|
||||
//~^^ ERROR the trait `SuperTrait` cannot be made into an object
|
||||
}
|
||||
|
@ -23,6 +23,39 @@ help: use angle brackets to add missing lifetime argument
|
||||
LL | type SubType<'a><'a>: SubTrait;
|
||||
| ^^^^
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
error[E0038]: the trait `SuperTrait` cannot be made into an object
|
||||
--> $DIR/issue-76535.rs:38:14
|
||||
|
|
||||
LL | let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object
|
||||
|
|
||||
= help: consider moving `SubType` to another trait
|
||||
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>
|
||||
--> $DIR/issue-76535.rs:7:10
|
||||
|
|
||||
LL | pub trait SuperTrait {
|
||||
| ---------- this trait cannot be made into an object...
|
||||
LL | type SubType<'a>: SubTrait;
|
||||
| ^^^^^^^ ...because it contains the generic associated type `SubType`
|
||||
|
||||
For more information about this error, try `rustc --explain E0107`.
|
||||
error[E0038]: the trait `SuperTrait` cannot be made into an object
|
||||
--> $DIR/issue-76535.rs:38:57
|
||||
|
|
||||
LL | let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object
|
||||
|
|
||||
= help: consider moving `SubType` to another trait
|
||||
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>
|
||||
--> $DIR/issue-76535.rs:7:10
|
||||
|
|
||||
LL | pub trait SuperTrait {
|
||||
| ---------- this trait cannot be made into an object...
|
||||
LL | type SubType<'a>: SubTrait;
|
||||
| ^^^^^^^ ...because it contains the generic associated type `SubType`
|
||||
= note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn SuperTrait<SubType = SubStruct<'_>>>>` for `Box<SuperStruct>`
|
||||
= note: required by cast to type `Box<dyn SuperTrait<SubType = SubStruct<'_>>>`
|
||||
|
||||
error: aborting due to 3 previous errors; 1 warning emitted
|
||||
|
||||
Some errors have detailed explanations: E0038, E0107.
|
||||
For more information about an error, try `rustc --explain E0038`.
|
||||
|
@ -7,6 +7,7 @@ trait CollectionFamily {
|
||||
}
|
||||
fn floatify() {
|
||||
Box::new(Family) as &dyn CollectionFamily<Member=usize>
|
||||
//~^ the trait `CollectionFamily` cannot be made into an object
|
||||
}
|
||||
|
||||
struct Family;
|
||||
|
@ -14,6 +14,22 @@ help: use angle brackets to add missing type argument
|
||||
LL | type Member<T><T>;
|
||||
| ^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0038]: the trait `CollectionFamily` cannot be made into an object
|
||||
--> $DIR/issue-78671.rs:9:25
|
||||
|
|
||||
LL | Box::new(Family) as &dyn CollectionFamily<Member=usize>
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `CollectionFamily` cannot be made into an object
|
||||
|
|
||||
= help: consider moving `Member` to another trait
|
||||
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>
|
||||
--> $DIR/issue-78671.rs:5:10
|
||||
|
|
||||
LL | trait CollectionFamily {
|
||||
| ---------------- this trait cannot be made into an object...
|
||||
LL | type Member<T>;
|
||||
| ^^^^^^ ...because it contains the generic associated type `Member`
|
||||
|
||||
For more information about this error, try `rustc --explain E0107`.
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0038, E0107.
|
||||
For more information about an error, try `rustc --explain E0038`.
|
||||
|
@ -42,5 +42,6 @@ impl<K, V: Default> MapLike<K, V> for Source {
|
||||
fn main() {
|
||||
let m = Box::new(std::collections::BTreeMap::<u8, u8>::new())
|
||||
as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>;
|
||||
//~^^ ERROR type mismatch resolving
|
||||
//~^^ the trait `MapLike` cannot be made into an object
|
||||
//~^^ the trait `MapLike` cannot be made into an object
|
||||
}
|
||||
|
@ -14,17 +14,39 @@ help: use angle brackets to add missing lifetime argument
|
||||
LL | type VRefCont<'a><'a>: RefCont<'a, V>;
|
||||
| ^^^^
|
||||
|
||||
error[E0271]: type mismatch resolving `<BTreeMap<u8, u8> as MapLike<u8, u8>>::VRefCont<'static> == (dyn RefCont<'_, u8> + 'static)`
|
||||
error[E0038]: the trait `MapLike` cannot be made into an object
|
||||
--> $DIR/issue-79422.rs:44:12
|
||||
|
|
||||
LL | as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object
|
||||
|
|
||||
= help: consider moving `VRefCont` to another trait
|
||||
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>
|
||||
--> $DIR/issue-79422.rs:21:10
|
||||
|
|
||||
LL | trait MapLike<K, V> {
|
||||
| ------- this trait cannot be made into an object...
|
||||
LL | type VRefCont<'a>: RefCont<'a, V>;
|
||||
| ^^^^^^^^ ...because it contains the generic associated type `VRefCont`
|
||||
|
||||
error[E0038]: the trait `MapLike` cannot be made into an object
|
||||
--> $DIR/issue-79422.rs:43:13
|
||||
|
|
||||
LL | let m = Box::new(std::collections::BTreeMap::<u8, u8>::new())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn RefCont`, found reference
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object
|
||||
|
|
||||
= note: expected trait object `(dyn RefCont<'_, u8> + 'static)`
|
||||
found reference `&'static u8`
|
||||
= note: required for the cast to the object type `dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>`
|
||||
= help: consider moving `VRefCont` to another trait
|
||||
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>
|
||||
--> $DIR/issue-79422.rs:21:10
|
||||
|
|
||||
LL | trait MapLike<K, V> {
|
||||
| ------- this trait cannot be made into an object...
|
||||
LL | type VRefCont<'a>: RefCont<'a, V>;
|
||||
| ^^^^^^^^ ...because it contains the generic associated type `VRefCont`
|
||||
= 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>>`
|
||||
= note: required by cast to type `Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0107, E0271.
|
||||
For more information about an error, try `rustc --explain E0107`.
|
||||
Some errors have detailed explanations: E0038, E0107.
|
||||
For more information about an error, try `rustc --explain E0038`.
|
||||
|
16
src/test/ui/generic-associated-types/trait-objects.rs
Normal file
16
src/test/ui/generic-associated-types/trait-objects.rs
Normal file
@ -0,0 +1,16 @@
|
||||
#![feature(generic_associated_types)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
trait StreamingIterator {
|
||||
type Item<'a> where Self: 'a;
|
||||
fn size_hint(&self) -> (usize, Option<usize>);
|
||||
// Uncommenting makes `StreamingIterator` not object safe
|
||||
// fn next(&mut self) -> Self::Item<'_>;
|
||||
}
|
||||
|
||||
fn min_size(x: &mut dyn for<'a> StreamingIterator<Item<'a> = &'a i32>) -> usize {
|
||||
//~^ the trait `StreamingIterator` cannot be made into an object
|
||||
x.size_hint().0
|
||||
}
|
||||
|
||||
fn main() {}
|
18
src/test/ui/generic-associated-types/trait-objects.stderr
Normal file
18
src/test/ui/generic-associated-types/trait-objects.stderr
Normal file
@ -0,0 +1,18 @@
|
||||
error[E0038]: the trait `StreamingIterator` cannot be made into an object
|
||||
--> $DIR/trait-objects.rs:11:16
|
||||
|
|
||||
LL | fn min_size(x: &mut dyn for<'a> StreamingIterator<Item<'a> = &'a i32>) -> usize {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `StreamingIterator` cannot be made into an object
|
||||
|
|
||||
= help: consider moving `Item` to another trait
|
||||
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>
|
||||
--> $DIR/trait-objects.rs:5:10
|
||||
|
|
||||
LL | trait StreamingIterator {
|
||||
| ----------------- this trait cannot be made into an object...
|
||||
LL | type Item<'a> where Self: 'a;
|
||||
| ^^^^ ...because it contains the generic associated type `Item`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0038`.
|
Loading…
Reference in New Issue
Block a user