-
Notifications
You must be signed in to change notification settings - Fork 13.1k
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
Arbitrary self types v2: avoid dyn, generic ICE #136195
Conversation
Bug rust-lang#57276 (and several duplicates) is an ICE which occurs when a generic type is used as a receiver which implements both Receiver and DispatchFromDyn. This change proposes to detect this error condition and turn it into a regular error rather than an ICE. Future changes could liberalise things here. As this same code path currently produces an ICE, this seems to be strictly better, and it seems defensible to inform the user that their excessively generic type is not dyn-safe. This is somewhat related to the stabilization of arbitrary self types in PR rust-lang#135881, tracked in rust-lang#44874.
r? @fee1-dead rustbot has assigned @fee1-dead. Use |
r? @wesleywiser |
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 don't think this is the right solution.
The DispatchFromDyn
trait should be marked with #[rustc_do_not_implement_via_object]
, since dyn trait object types do not "inherit" DispatchFromDyn
just because they're unsized from a type that is DispatchFromDyn
. This attribute is used for special "structural" traits such as Unsize
and Sized
, which act differently from other traits in that they aren't really implied via a dyn impl.
@compiler-errors Do you literally mean adding that attribute to the trait, like this?
Unfortunately that doesn't solve the ICE. |
Hm, right. I understand the nature of the ICE better now. Still, the error recovery here seems a bit dissatisfying... Especially because Footnotes
|
I agree, but I'll also openly admit that I don't understand all this stuff (remotely) well enough to do any better.
I'd push back gently on that. The docs for
I think as a user of Maybe another way to approach this would be to try to specify the extra bullet point to add to those docs. |
Here's another ICE that isn't fixed by this PR afaict: #![feature(dispatch_from_dyn)]
#![feature(arbitrary_self_types)]
use std::ops::Deref;
use std::ops::DispatchFromDyn;
trait Trait<T: Deref<Target = Self>>
where
for<'a> &'a T: DispatchFromDyn<&'a T>,
{
fn foo(self: &T) -> Box<dyn Trait<T>>;
}
I think in this case, generalizing this fix to say something like "the layout is not ScalarPair" is even worse than saying "the layout is too generic". I feel like philosophically, the underlying problem here is that all of the work that we go through with substituting Now, I'm not totally sure how or if it's possible to reformulate this check to be less weird -- as a side-note, I'm kinda surprised that the trait is dyn compatible at all. Given a trait of
I'm gonna go out on a limb and say that maybe you're more experienced than a random user with this, so of course you're gonna be unsurprised by a layout error. On the contrary, I feel like the whole reason we're using traits like |
Closing in favor of #136520 |
…ssert, r=lcnr Remove unnecessary layout assertions for object-safe receivers The soundness of `DispatchFromDyn` relies on the fact that, like all other built-in marker-like layout traits (e.g. `Sized`, `CoerceUnsized`), the guarantees that they enforce in *generic* code via traits will result in assumptions that we can rely on in codegen. Specifically, `DispatchFromDyn` ensures that we end up with a receiver that is a valid pointer type, and its implementation validity recursively ensures that the ABI of that pointer type upholds the `Scalar` or `ScalarPair` representation for sized and unsized pointees, respectively. The check that this layout guarantee holds for arbitrary, possibly generic receiver types that also may exist in possibly impossible-to-instantiate where clauses is overkill IMO, and leads to several ICEs due to the fact that computing layouts before monomorphization is going to be fallible at best. This PR removes the check altogether, since it just exists as a sanity check from very long ago, 6f2a161. Fixes rust-lang#125810 Fixes rust-lang#90110 This PR is an alternative to rust-lang#136195. cc `@adetaylor.` I didn't realize in that PR that the layout checks that were being modified were simply *sanity checks*, rather than being actually necessary for soundness.
Rollup merge of rust-lang#136520 - compiler-errors:redundant-layout-assert, r=lcnr Remove unnecessary layout assertions for object-safe receivers The soundness of `DispatchFromDyn` relies on the fact that, like all other built-in marker-like layout traits (e.g. `Sized`, `CoerceUnsized`), the guarantees that they enforce in *generic* code via traits will result in assumptions that we can rely on in codegen. Specifically, `DispatchFromDyn` ensures that we end up with a receiver that is a valid pointer type, and its implementation validity recursively ensures that the ABI of that pointer type upholds the `Scalar` or `ScalarPair` representation for sized and unsized pointees, respectively. The check that this layout guarantee holds for arbitrary, possibly generic receiver types that also may exist in possibly impossible-to-instantiate where clauses is overkill IMO, and leads to several ICEs due to the fact that computing layouts before monomorphization is going to be fallible at best. This PR removes the check altogether, since it just exists as a sanity check from very long ago, 6f2a161. Fixes rust-lang#125810 Fixes rust-lang#90110 This PR is an alternative to rust-lang#136195. cc `@adetaylor.` I didn't realize in that PR that the layout checks that were being modified were simply *sanity checks*, rather than being actually necessary for soundness.
Bug #57276 (and several duplicates) are an ICE which occurs when a generic type is used as a receiver which implements both
Deref
andDispatchFromDyn
.This change proposes to detect this error condition and turn it into a regular error rather than an ICE. Future changes could relax things here. But meanwhile, as this same code path currently produces an ICE, this seems to be strictly better, and it seems defensible to inform the user that their excessively generic type is not dyn-safe.
This is somewhat related to the stabilization of arbitrary self types in PR #135881, tracked in #44874.
Even if we don't want to simply go ahead and make a legitimate error in this case, I'm hoping this PR will provoke discussion of a better solution. We could repeat similar layout checks in
receiver_is_dispatchable
but I'm not sure why that would be better.