Open alexreg opened 4 years ago
This was discussed in triage, so I'll remove the concern @rfcbot resolve ensure-we-discuss-lcnr's-thoughts-in-triage
Were all concerns raised by @WaffleLapkin in this comment ticked/discussed?
(apologies in advance if I missed something, I am slightly struggling to follow the technical details of the discussion)
@apiraino I believe those should be addressed in some form in the stabilization report by the time it's published. I think T-types is now driving this to completion, but a number of other people have contributed to the draft (https://hackmd.io/QggP6SJVTa2jb7DjGq0vrQ?both).
Hi folks, we talked about this in our @rust-lang/types meeting. We all agreed that we'd like to see a better stabilization report that covers the trait system implementation and, ideally, modeling for trait upcasts in a-mir-formality.
I'm up to mentor someone on the latter if anybody has time to commit, please reach out.
EDIT: We decided a write-up suffices, see below.
We talked about this in our rust-lang/types meetup. While I still very much want to see this covered in a-mir-formality, we agreed that we shouldn't block on that. We would be happy to move forward with an improved stabilization report that covered more technical details, included links to the various writeups and decisions we've made. The major piece of missing docs is covering the interaction with trait selection -- @compiler-errors has recently reimplemented this and indicated a willingness to write it up (perhaps for rustc-dev-guide). I believe that the rest is already written and we can compile a stabilization report that links to the various places.
@rfcbot reviewed
@rfcbot concern types-team-sign-off
I am adding a concern that @rust-lang/types wants to be happy with the impl details (and especially @lcnr) -- @compiler-errors covered the details of type system interactions in rust-lang/rustc-dev-guide#1817 though.
I am happy with the impl details. I had some other concerns in https://github.com/rust-lang/rust/issues/65991#issuecomment-1672782595.
While #101336 has still not been closed, everything seems now documented in https://hackmd.io/QggP6SJVTa2jb7DjGq0vrQ, so :+1: from my end.
@rfcbot resolve types-team-sign-off
@rustbot labels +I-lang-nominated
This was discussed in a recent T-types meeting. As @lcnr stated above, the concerns about the stabilization report and documentation have been resolved, so this is now unblocked. @nikomatsakis has proposed that we re-highlight this issue for T-lang, so let's renominate.
Not sure this has been mentioned yet, but seems related: #32220 should be possible now that Rust has upcasting support (at least in nightly)?
Edit: it looks like yes, see https://github.com/rust-lang/rfcs/issues/2035
We discussed @WaffleLapkin's list of unresolved concerns in the rust-lang triage meeting and had this text which I will add to the stabilization report:
*const dyn Tr
with invalid metadata invalid, to support safe coercions (resolved by https://github.com/rust-lang/rust/issues/101336#issuecomment-1250356226)trait A: B
is upcastable, should trait A where Self: B
be? (raised @ https://github.com/rust-lang/rust/issues/65991#issuecomment-1294081137)
trait A: B
as equivalent to trait A where Self: B
.@rfcbot reviewed
:bell: This is now entering its final comment period, as per the review above. :bell:
If the upcasting feature isn't used, can it be optimized out by compiler?
@NobodyXu if a type is not ever coerced to a trait object, then the compiler won't generate a vtable. Otherwise, if a type is coerced, then the compiler will not be able to change the layout of the vtable based on it's usage.
Thanks, it makes sense since it's hard to do that.
@rustbot labels -I-lang-nominated
The proposal to do this is in FCP. Let's remove the nomination until and unless there is something more to do here.
This is a tracking issue for RFC3324. Corresponding MCP is here.
The feature gate for the issue is
#![feature(trait_upcasting)]
.STATUS UPDATE
We are in the process of stabilizing.
About tracking issues
Tracking issues are used to record the overall progress of implementation.
They are also used as hubs connecting to other relevant issues, e.g., bugs or open design questions.
A tracking issue is however not meant for large scale discussion, questions, or bug reports about a feature.
Instead, open a dedicated issue for the specific matter and add the relevant feature gate label.
Steps
[x] Implement the experimental feature behind a feature gate.
[x] Define the semantics explicitly.
[x] Gathering design docs into initiative repo: https://github.com/rust-lang/dyn-upcasting-coercion-initiative
[x] Adjust documentation ([see instructions on rustc-dev-guide][doc-guide]) https://github.com/rust-lang/reference/pull/1259
[x] Gather data about memory usage? https://github.com/rust-lang/rust/issues/112355
[ ] Stabilization PR ([see instructions on rustc-dev-guide][stabilization-guide]) https://github.com/rust-lang/rust/pull/101718
Previous discussions
RFC-issue2765: https://github.com/rust-lang/rfcs/issues/2765
MCP: https://github.com/rust-lang/lang-team/issues/98 (Current lang-team MCP)
Initiative: Dyn upcasting coercion initiative
Unresolved Questions
CurrentlyCoerceUnsized
trait cannot express this case: a smart pointers that wrap a raw pointer and don't guarantee via a custom invariant that it is valid. Maybe a separateCoerceUnsizedUnsafe
trait is needed. (see https://github.com/rust-lang/rust/pull/88010#issuecomment-898893209).Should we make upcasting opt-in in some form to limit vtable size by default? The current inclination of the lang-team is "no", but it would be useful to gather data on how much supporting upcasting contributors to overall binary size.
Before stabilizing it we should check that libs-api is ok with upcasting for all dyn-allowed traits in the library, since those we can't change.(addressed by https://github.com/rust-lang/rust/issues/65991#issuecomment-1369970129)Should we add an opt-out mechanism, and extend library stabilization checklist with "do we want to opt-out for now"?
Implementation history
Initial attempt: #60900
Second attempt:
[X] Preparation refactoring: #86291
[X] Unify vtable building: #86475
[x] Update vtable format: #86461
[x] Feature gate implementation: #86264
[x] Pointer conversion adjustments: #87515
[x] Support multiple occurrence of a target trait with different substsdefs: #88135
[x]
Unsafety checking for raw dyn pointers: #88010 (not prefered approach, likely will need to do nothing here, but need a design meeting discussion with lang-team)Solution: https://rust-lang.zulipchat.com/#narrow/stream/326132-t-types.2Fmeetings/topic/meeting.202022-09-02.20planning/near/296826711, https://github.com/rust-lang/rust/issues/101336[x] Lint for easing migration: https://github.com/rust-lang/rust/issues/89460
[x] Reference changes https://github.com/rust-lang/reference/pull/1259
[x] Mark this feature no longer incomplete and stablize: https://github.com/rust-lang/rust/pull/101718
[x] Make trait upcasting work with supertraits with fewer associated types: #114036
-
The final comment period, with a disposition to merge, as per the review above, is now complete.
As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed.
This will be merged soon.
I just tried using this feature to upcast to Any + Send + Sync
, and it seems to me like this is currently not allowed:
trait DynSized: 'static + Any + Send + Sync + DeepSizeOf {}
impl<T: 'static + Any + Send + Sync + DeepSizeOf> DynSized for T {}
fn main() {
let ptr = Arc::new(()) as Arc<dyn DynSized>;
let ptr_any = ptr as Arc<dyn Any + Send + Sync>;
// my goal:
let res = Arc::<dyn Any + Send + Sync>::downcast::<()>(ptr);
}
With references, the situation does not seem better than with Arc
: this does not compile either
fn main() {
let ptr = &() as &'static dyn DynSized;
let ptr_any = ptr as &'static (dyn Any + Send + Sync);
}
Is this expected? I can't find any reference to this limitation, neither explicitly in the RFC text nor in this tracking issue. The RFC text does mention not supporting upcasting to multiple traits, but I'd have expected lifetimes as well as auto traits to not be included in the limitation.
If it is expected that this feature is stabilized without this support, does anyone know where I should watch, to know of the news on that front?
@Ekleog you can probably do a workaround like:
trait AnySendSync: Any + Send + Sync {}
impl<T: Any + Send + Sync> AnySendSync for T{}
Then upcast to AnySendSync instead of Any + Send + Sync. On my phone though so can’t verify if this actually works
Edit: you’ll also likely have to change your DynSized to be DynSized: AnySendSync + DeepSizeOf 👍
Unfortunately, it looks like [I still cannot downcast, because I need to upcast Arc<dyn AnySendSync>
to Arc<dyn Any + Send + Sync>
in order to be able to downcast, and this still does not compile :/
It's certainly not ideal due to requiring unsafe
, but a downcast_ref
to check followed by a Arc::from_raw(arc.as_raw().cast())
would at least be be a sound workaround.
@Ekleog how about this? this has an extra T: Sized
restriction though, don't know if it can be better.
use std::any::Any;
use std::sync::Arc;
trait DeepSizeOf {} // from deepsize
impl DeepSizeOf for () {}
trait AnySendSync: Any + Send + Sync {
fn explode(self: Arc<Self>) -> Arc<dyn Any + Send + Sync>;
}
impl<T: Any + Send + Sync> AnySendSync for T {
fn explode(self: Arc<T>) -> Arc<dyn Any + Send + Sync> {
self
}
}
trait DynSized: 'static + AnySendSync + DeepSizeOf {}
impl<T: 'static + AnySendSync + DeepSizeOf> DynSized for T {}
fn main() {
let ptr = Arc::new(()) as Arc<dyn DynSized>;
let ptr_anysendsync = ptr as Arc<dyn AnySendSync>; // works fine
let ptr_any = ptr_anysendsync.explode();
let res = ptr_any.downcast::<()>();
}
i guess upcasting coercion exists to solve this kind of inefficiencies... but since upcasting to a group of traits isn't possible right now.
Closed issues are not a good place for discussion, please open a new issue or discuss on Zulip or the forums.
upcasting to a group of traits isn't possible right now
Indeed that's the core here, you can only upcast to a single trait. Could be interesting to discuss extending this to "one trait plus any number of marker traits" but that's an extension which needs a new issue. :)
Let's continue discussion on my upcasting issue on this separate issue opened by @compiler-errors :) Incidentally, it is currently being solved in this PR also by @compiler-errors (lots of thanks :heart:)
@dhardy As for the downcasting you're mentioning, I'm not sure what you're thinking of? But if/when you open a separate issue to discuss it, please tag me!
@Ekleog regarding downcast
, see https://internals.rust-lang.org/t/pre-rfc-make-downcast-user-friendly/20092
I’ve come across some soundness issues with upcasting today. Readers of this thread might be interested ^^
Can we have a status update with regards to the reverted stabilization? The current status update says "We are in the process of stabilizing" since January, with no mention of the recent soundness issues.
The stabilization is currently blocked on the fix of the unsoundness bug tracked in #120222. The fix is in #120248, but needs a bit more work. I've been occupied by the never type stuff which is urgent because some of the changes are edition based. I hope I'll have time soon to finish #120248.
This is also blocked on rust reference PR, which someone needs to take over: https://github.com/rust-lang/reference/pull/1259#issuecomment-1907299080.
It looks like the blocking bug #120222 have been fixed out, and what's next for this stabilization?
@Kish29 the next steps are changing the reference (cc https://github.com/rust-lang/reference/pull/1259) and doing a new stabilization PR :)
I am newbie baffled by the absence of this basic syntax. I got this workaround if anyone is interested. It works all on stable Rust
This is a tracking issue for RFC3324. Corresponding MCP is here. The feature gate for the issue is
#![feature(trait_upcasting)]
.STATUS UPDATE
We are in the process of stabilizing.
About tracking issues
Tracking issues are used to record the overall progress of implementation. They are also used as hubs connecting to other relevant issues, e.g., bugs or open design questions. A tracking issue is however not meant for large scale discussion, questions, or bug reports about a feature. Instead, open a dedicated issue for the specific matter and add the relevant feature gate label.
Steps
https://github.com/rust-lang/rust/pull/101718, https://github.com/rust-lang/rust/pull/118133Previous discussions
Unresolved Questions
CurrentlyCoerceUnsized
trait cannot express this case: a smart pointers that wrap a raw pointer and don't guarantee via a custom invariant that it is valid. Maybe a separateCoerceUnsizedUnsafe
trait is needed. (see https://github.com/rust-lang/rust/pull/88010#issuecomment-898893209).Before stabilizing it we should check that libs-api is ok with upcasting for all dyn-allowed traits in the library, since those we can't change.(addressed by https://github.com/rust-lang/rust/issues/65991#issuecomment-1369970129)Implementation history
Unsafety checking for raw dyn pointers: #88010 (not prefered approach, likely will need to do nothing here, but need a design meeting discussion with lang-team)Solution: https://rust-lang.zulipchat.com/#narrow/stream/326132-t-types.2Fmeetings/topic/meeting.202022-09-02.20planning/near/296826711, https://github.com/rust-lang/rust/issues/101336https://github.com/rust-lang/reference/pull/1259