-
Notifications
You must be signed in to change notification settings - Fork 14k
DispatchFromDyn: require additional checks #149068
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
base: main
Are you sure you want to change the base?
DispatchFromDyn: require additional checks #149068
Conversation
|
rustbot has assigned @WaffleLapkin. Use |
This comment has been minimized.
This comment has been minimized.
|
@theemathas What do you think? Can we break |
75de383 to
88de0f9
Compare
This comment has been minimized.
This comment has been minimized.
88de0f9 to
b7f84d2
Compare
|
This code causes an ICE with this PR: #![feature(dispatch_from_dyn, unsize, arbitrary_self_types)]
use std::{
marker::{PhantomData, Unsize},
ops::{DispatchFromDyn, Receiver},
};
struct Ptr<T: ?Sized>(PhantomData<T>, Box<T>);
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<&'a Ptr<U>> for &'a Ptr<T> {}
impl<T: ?Sized> Receiver for Ptr<T> {
type Target = T;
}
trait Trait {
fn method(self: &Ptr<Self>) {}
}
struct Thing;
impl Trait for Thing {}
fn main() {
let x: Ptr<dyn Trait> = Ptr(PhantomData, Box::new(Thing));
x.method();
}The compiler is probably attempting to do an dyn dispatch through two pointers, which is not possible Error output |
|
The documentation for DispatchFromDyn also needs to be changed. |
I am not sure. We have an option to make it possible. The question is, would it be a bad idea? In any case, let me add a stop-gap to disallow this case. |
b7f84d2 to
8c95fd8
Compare
This comment has been minimized.
This comment has been minimized.
8c95fd8 to
fdf32a0
Compare
|
r? types |
|
Discussion under t-lang: #t-lang > Should we support dyn dispatch on `&Adt<_>`? I think we are quite convinced that |
| impl<'a, T: ?Sized, U: ?Sized> DispatchFromDyn<&'a Ptr<U>> for &'a Ptr<T> {} | ||
| //~^ ERROR the trait `DispatchFromDyn` does not allow dispatch through references |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mentioning references here seems awfully specific. What about Box<Ptr<U>> or similar?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am in the middle of updating the documentation on this trait.
Box<Ptr<U>> falls in the second case of the new documentation. We would foremost require Ptr<T>: DispatchFromDyn<Ptr<U>> among the other requirements.
| .label = can't implement cross-crate trait for type in another crate | ||
| hir_analysis_dispatch_from_dyn_multiple_refs = the trait `DispatchFromDyn` does not allow dispatch through references | ||
| .note = the trait `DispatchFromDyn` may only be implemented when dispatch goes through at most one reference to a generic |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does this text not show up in the test error output?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I forgot about a #[note] attribute on the error type. Now it should work.
|
This code doesn't compile with this PR. Should it? #![feature(dispatch_from_dyn, arbitrary_self_types, unsize)]
use std::marker::{PhantomData, Unsize};
use std::ops::{DispatchFromDyn, Receiver};
pub struct Inner<T: ?Sized>(T);
#[repr(transparent)]
pub struct Outer<T: ?Sized>(PhantomData<T>, Inner<T>);
fn wrap<T: ?Sized>(x: &Inner<T>) -> &Outer<T> {
// SAFETY: We're using repr(transparent)
unsafe { &*(x as *const Inner<T> as *const Outer<T>) }
}
impl<'a, T: Unsize<U> + ?Sized, U: ?Sized> DispatchFromDyn<&'a Outer<U>> for &'a Outer<T> {}
impl<T: ?Sized> Receiver for Outer<T> {
type Target = T;
}
pub trait Trait {
fn method(self: &Outer<Self>);
}
struct Thing(i32);
impl Trait for Thing {
fn method(self: &Outer<Self>) {
println!("{}", self.1.0.0);
}
}
fn main() {
let inner: &Inner<dyn Trait> = &Inner(Thing(1));
let x: &Outer<dyn Trait> = wrap(inner);
x.method();
} |
The new checks are we check the pair of constituent types for same shapes structurally, and demand capability for dispatch for ADTs as usual; and we demand source generic parameter to be unsized of another for sanity. Signed-off-by: Xiangfei Ding <[email protected]>
fdf32a0 to
e0eee5f
Compare
|
This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed. Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers. |
Signed-off-by: Xiangfei Ding <[email protected]>
|
To answer the comment I have jotted down the reason that we do not want to compile the example in the trait documentation. |
|
The job Click to see the possible cause of the failure (guessed by this bot) |
|
@dingxiangfei2009 Your comment in the code unfortunately does not answer my latest comment in this PR. My comment does not involve a double pointer indirection. |
The new checks are we check the pair of constituent types for same shapes structurally, and demand capability for dispatch for ADTs as usual; and we demand source generic parameter to be unsized of another for sanity.
Fix #148727
cc @theemathas