Open ldr709 opened 3 years ago
Hi,
I'm currently building stabby
an alternative to abi_stable
(with added values: use niches in sum types and stable multi-trait objects).
My proc-macro generates v-tables (with auto-generated identifiers) and makes them accessible through a trait which roughly looks like this:
impl<Assoc1> VtProvider for dyn MyTrait<Assoc=Assoc1> {
type Vt = AutoGeneratedVtForMyTrait<Assoc1>;
}
allowing the user to refer to AutoGeneratedVtForMyTrait<Assoc1>
by vtable!(MyTrait<Assoc=Assoc1>)
, which resolves to <dyn MyTrait<Assoc=Assoc1> as VtProvider>::Vt
.
This bug prevents this trick from working when associated types are constrained.
Is anyone willing to look into it? Or provide mentoring so that I could try? (I don't have any experience working with the compiler)
I'll trade you a stable ABI that keeps enums small in stable Rust for fixing this bug :)
Is this the same issue or should I file it separately?
use std::ops::Deref;
use std::borrow::Borrow;
trait Guard: Deref + Borrow<Self::Target> {}
fn foo(_: &dyn Guard<Target = i32>) {}
error[E0038]: the trait `Guard` cannot be made into an object
--> src/main.rs:7:12
|
7 | fn foo(_: &dyn Guard<Target = i32>) {}
| ^^^^^^^^^^^^^^^^^^^^^^^ `Guard` 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>
--> src/main.rs:5:22
|
5 | trait Guard: Deref + Borrow<Self::Target> {}
| ----- ^^^^^^^^^^^^^^^^^^^^ ...because it uses `Self` as a type parameter
| |
| this trait cannot be made into an object...
help: consider using an opaque type instead
|
7 | fn foo(_: &impl Guard<Target = i32>) {}
| ~~~~
For more information about this error, try `rustc --explain E0038`.
(Thanks to Helix in the Community Discord for constructing the example.)
I ran into both versions of this in a project of mine, and while it's easy to work around by making the trait generic, that doesn't seem ideal with my Guard
example here, as it's implicitly exclusive.
Edit: This might be #65078 instead.
A simplified example where this shows up is the following trait.
(Full code)
If you try to make a trait object, say
&dyn Conversion<Source = String, Target = Box<str>>
, then Rust errors:If the bound was something like
Source: Into<Self>
this error would make sense, but instead the bound references another associated type, which all must be fully specified when making a trait object type anyway.This problem does not seem to occur when associated types are used to define functions in the trait, as creating a
&dyn Deref<Target = ...>
trait object works.