Do not require associated types with Self: Sized to uphold bounds when confirming object candidate

This commit is contained in:
Michael Goulet 2023-09-02 05:06:21 +00:00
parent 7a6b52bf0d
commit 07fc644132
7 changed files with 54 additions and 28 deletions

View File

@ -354,9 +354,9 @@ pub(in crate::solve) fn predicates_for_object_candidate<'tcx>(
// FIXME(associated_const_equality): Also add associated consts to // FIXME(associated_const_equality): Also add associated consts to
// the requirements here. // the requirements here.
if item.kind == ty::AssocKind::Type { if item.kind == ty::AssocKind::Type {
// RPITITs are not checked here, since they are not (currently) object-safe // associated types that require `Self: Sized` do not show up in the built-in
// and cannot be named from a non-`Self: Sized` method. // implementation of `Trait for dyn Trait`, and can be dropped here.
if item.is_impl_trait_in_trait() { if tcx.generics_require_sized_self(item.def_id) {
continue; continue;
} }

View File

@ -535,9 +535,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let assoc_types: Vec<_> = tcx let assoc_types: Vec<_> = tcx
.associated_items(trait_predicate.def_id()) .associated_items(trait_predicate.def_id())
.in_definition_order() .in_definition_order()
// RPITITs are not checked here, since they are not (currently) object-safe // Associated types that require `Self: Sized` do not show up in the built-in
// and cannot be named from a non-`Self: Sized` method. // implementation of `Trait for dyn Trait`, and can be dropped here.
.filter(|item| !item.is_impl_trait_in_trait()) .filter(|item| !tcx.generics_require_sized_self(item.def_id))
.filter_map( .filter_map(
|item| if item.kind == ty::AssocKind::Type { Some(item.def_id) } else { None }, |item| if item.kind == ty::AssocKind::Type { Some(item.def_id) } else { None },
) )

View File

@ -19,4 +19,5 @@ fn main() {
//~| ERROR the trait `Foo` cannot be made into an object //~| ERROR the trait `Foo` cannot be made into an object
let s = i.baz(); let s = i.baz();
//~^ ERROR the trait `Foo` cannot be made into an object //~^ ERROR the trait `Foo` cannot be made into an object
//~| ERROR the trait `Foo` cannot be made into an object
} }

View File

@ -13,6 +13,21 @@ LL | fn baz(&self) -> impl Debug;
| ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type | ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type
= help: consider moving `baz` to another trait = help: consider moving `baz` to another trait
error[E0038]: the trait `Foo` cannot be made into an object
--> $DIR/object-safety.rs:20:15
|
LL | let s = i.baz();
| ^^^ `Foo` cannot be made into an object
|
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/object-safety.rs:7:22
|
LL | trait Foo {
| --- this trait cannot be made into an object...
LL | fn baz(&self) -> impl Debug;
| ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type
= help: consider moving `baz` to another trait
error[E0038]: the trait `Foo` cannot be made into an object error[E0038]: the trait `Foo` cannot be made into an object
--> $DIR/object-safety.rs:20:13 --> $DIR/object-safety.rs:20:13
| |
@ -44,6 +59,6 @@ LL | fn baz(&self) -> impl Debug;
= help: consider moving `baz` to another trait = help: consider moving `baz` to another trait
= note: required for the cast from `Box<u32>` to `Box<dyn Foo>` = note: required for the cast from `Box<u32>` to `Box<dyn Foo>`
error: aborting due to 3 previous errors error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0038`. For more information about this error, try `rustc --explain E0038`.

View File

@ -1,6 +1,5 @@
//! This test checks that even if some associated types have //! This test checks that associated types with `Self: Sized` cannot be projected
//! `where Self: Sized` bounds, those without still need to be //! from a `dyn Trait`.
//! mentioned in trait objects.
trait Bop { trait Bop {
type Bar: Default type Bar: Default
@ -16,5 +15,4 @@ fn bop<T: Bop + ?Sized>() {
fn main() { fn main() {
bop::<dyn Bop>(); bop::<dyn Bop>();
//~^ ERROR: the size for values of type `dyn Bop` cannot be known at compilation time
} }

View File

@ -1,5 +1,5 @@
error[E0599]: the function or associated item `default` exists for associated type `<T as Bop>::Bar`, but its trait bounds were not satisfied error[E0599]: the function or associated item `default` exists for associated type `<T as Bop>::Bar`, but its trait bounds were not satisfied
--> $DIR/assoc_type_bounds_sized_used.rs:12:30 --> $DIR/assoc_type_bounds_sized_used.rs:11:30
| |
LL | let _ = <T as Bop>::Bar::default(); LL | let _ = <T as Bop>::Bar::default();
| ^^^^^^^ function or associated item cannot be called on `<T as Bop>::Bar` due to unsatisfied trait bounds | ^^^^^^^ function or associated item cannot be called on `<T as Bop>::Bar` due to unsatisfied trait bounds
@ -13,7 +13,7 @@ LL | fn bop<T: Bop + ?Sized>() where T: Sized {
| ++++++++++++++ | ++++++++++++++
error[E0277]: the size for values of type `T` cannot be known at compilation time error[E0277]: the size for values of type `T` cannot be known at compilation time
--> $DIR/assoc_type_bounds_sized_used.rs:12:14 --> $DIR/assoc_type_bounds_sized_used.rs:11:14
| |
LL | fn bop<T: Bop + ?Sized>() { LL | fn bop<T: Bop + ?Sized>() {
| - this type parameter needs to be `Sized` | - this type parameter needs to be `Sized`
@ -21,7 +21,7 @@ LL | let _ = <T as Bop>::Bar::default();
| ^ doesn't have a size known at compile-time | ^ doesn't have a size known at compile-time
| |
note: required by a bound in `Bop::Bar` note: required by a bound in `Bop::Bar`
--> $DIR/assoc_type_bounds_sized_used.rs:8:15 --> $DIR/assoc_type_bounds_sized_used.rs:7:15
| |
LL | type Bar: Default LL | type Bar: Default
| --- required by a bound in this associated type | --- required by a bound in this associated type
@ -34,20 +34,7 @@ LL - fn bop<T: Bop + ?Sized>() {
LL + fn bop<T: Bop>() { LL + fn bop<T: Bop>() {
| |
error[E0277]: the size for values of type `dyn Bop` cannot be known at compilation time error: aborting due to 2 previous errors
--> $DIR/assoc_type_bounds_sized_used.rs:18:11
|
LL | bop::<dyn Bop>();
| ^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `dyn Bop`
note: required by a bound in `bop`
--> $DIR/assoc_type_bounds_sized_used.rs:11:11
|
LL | fn bop<T: Bop + ?Sized>() {
| ^^^ required by this bound in `bop`
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0277, E0599. Some errors have detailed explanations: E0277, E0599.
For more information about an error, try `rustc --explain E0277`. For more information about an error, try `rustc --explain E0277`.

View File

@ -0,0 +1,25 @@
// check-pass
// revisions: current next
//[next] compile-flags: -Ztrait-solver=next
trait Foo {
type Bar<'a>
where
Self: Sized;
fn test(&self);
}
impl Foo for () {
type Bar<'a> = () where Self: Sized;
fn test(&self) {}
}
fn test(x: &dyn Foo) {
x.test();
}
fn main() {
test(&());
}