-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Deref coercion from &DST to &TraitObject #2239
Comments
Isn’t that autoref rather than auto-deref? If I remember correctly so far we only have autoref in method calls. |
I meant coercion just in that the caller writes an expression that looks like it has type &U but the callee accepts it as type &T. In this case U=str and T=Debug. The autoref aspect of it is an implementation detail, unlike in method calls. From the language point of view the caller passes a &DST and the callee receives a &TraitObject, exactly as it would have worked for passing a sized type. |
@dtolnay But |
@eddyb does that make it hopeless? Maybe "equivalent to doing &&DST as &TraitObject" is oversimplifying but "insert an extra & to eliminate the papercut" still seems promising to me. struct TraitObject {
data: *const (),
// fn(&self)
vtable: fn(*const ()),
}
fn callee(trait_object: &TraitObject) {
(trait_object.vtable)(trait_object.data)
}
fn main() {
// callee("str")
callee(&TraitObject { data: &"str" as *const &str as *const (), vtable: impl_trait_for_str });
// callee(&"str")
callee(&TraitObject { data: &"str" as *const &str as *const (), vtable: impl_trait_for_ref_str });
}
// impl Trait for str {}
fn impl_trait_for_str(data: *const ()) {
let s = unsafe { &**(data as *const *const str) };
assert!(s.chars().next().unwrap() == 's');
println!("impl Trait for str");
}
// impl Trait for &str {}
fn impl_trait_for_ref_str(data: *const ()) {
let s = unsafe { &**(data as *const *const str) };
assert!(s.chars().next().unwrap() == 's');
println!("impl Trait for &str");
} |
Note that the existing coercion doesn't distinguish between |
The places we have had trouble with this (in std::fmt and Serde) would be resolved if the change only applies to &T, not Box or Rc. |
I think the argument against pervasive autoref was to avoid a situation where a value looks like it is moved but it is in fact borrowed. However borrowing implicitly is not a problem when the value is already a This is a long way to say 👍 |
I don't think I have bandwidth to pursue this in the near term. @GuillaumeGomez would you be interested in putting together a full RFC? |
I actually have no idea how such a feature could be implemented so I don't think I'm the one to pick for this task. |
A dynamically sized type cannot currently be passed as a trait object.
In such cases the &DST should perform a deref coercion, equivalent to doing
&&DST as &TraitObject
.We hit this in rust-lang/rust#46445 in which a slice cannot be passed to
DebugStruct::field
. I have also hit this in Serde with theExpected
trait object, which commonly requires passing an argument that looks like&"message"
.The text was updated successfully, but these errors were encountered: