rust-lang/rust

Trait objects do not work with generic associated types

matthewjasper opened this issue · 12 comments

I tried this code:

#![feature(generic_associated_types)]

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 {
    x.size_hint().0
}

I expected to see this happen: either code compiles or an error message is emitted for any use of a trait object with generic associated types

Instead, this happened: code produces inconsistent error messages:

error[E0038]: the trait `StreamingIterator` cannot be made into an object
  --> <source>:18:16
   |
18 | fn min_size(x: &mut dyn for<'a> StreamingIterator<Item<'a> = &'a i32>) -> usize {
   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `StreamingIterator` cannot be made into an object
   |
   = help: consider moving `next` 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>
  --> <source>:15:26
   |
11 | trait StreamingIterator {
   |       ----------------- this trait cannot be made into an object...
...
15 |    fn next(&mut self) -> Self::Item<'_>;
   |                          ^^^^^^^^^^^^^^ ...because method `next` references the `Self` type in its return type

error: aborting due to previous error
error: generic associated types in trait objects are not supported yet
  --> <source>:19:7
   |
19 |     x.size_hint().0
   |       ^^^^^^^^^

error: aborting due to previous error

Compiler returned: 1

I've found the cause of this; working on it locally.

Edit: probably nevermind

I did some digging... Is it possible that Self::Item<'a> isn't being desugared into a projection?

Edit: Nope. DEBUG rustc_trait_selection::traits::object_safety contains_illegal_self_type_reference: t=<Self as StreamingIterator>::Item<'_>

DEBUG rustc_trait_selection::traits::object_safety contains_illegal_self_type_reference: supertrait def_id=DefId(0:7 ~ gattest[8787]::StreamingIterator) substs=[Self]
DEBUG rustc_trait_selection::traits::object_safety contains_illegal_self_type_reference: projection_trait_ref def_id=DefId(0:7 ~ gattest[8787]::StreamingIterator)  substs=[Self, ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrAnon(0) })]

I'm just a noob at this, but that extra subst is why we're not detecting the supertype reference..

@taralx there's a couple different bits here

Part of this (and I think what you're finding) is fixed in #82066 (see https://github.com/rust-lang/rust/pull/82066/files#diff-446fe5fbcfeb9d0936f1774f53b64d2835bc9dd5ece97b9164d12c635d64a505L26)

The other bit is here:

// FIXME(generic_associated_types) generate placeholders to

Sure, but IIUC this issue is just about the confusing (and inaccurate) error message, which is fixed in 82066?

Sure, but IIUC this issue is just about the confusing (and inaccurate) error message, which is fixed in 82066?

I just tested this theory, the confusing error message is gone. The TODO remains.

cargo run                                                                                                                                                       18:56:41
   Compiling gats v0.1.0 (/home/jono/Repos/gats)
error: generic associated types in trait objects are not supported yet
  --> src/main.rs:12:7
   |
12 |     x.size_hint().0
   |       ^^^^^^^^^

error: aborting due to previous error

error: could not compile `gats`

😢

As the blog post on GAT stabilization mentions:

... Also, GATs without object safety are still very powerful, so we don't lose much by defering this. ...

#44265 is linked to this issue as the tracking issue for GATs in general, but that thread does not mention anything on this deferral, instead simply marking this issue as Closed.

This work item (81823) appears to have been the tracking issue for such future functionality; with its closing, do we have any followup item to track current prioritization and/or blockers for GAT Object Safety?

I'm reopening this, since GATs are not object-safe currently (with no plans to make them so for initial stabilization) but we want them to be eventually.

GATs issue triage: not blocking. Not planned for initial stabilization.

Does someone can explain to me why GAT isn't object-safe?