-
Notifications
You must be signed in to change notification settings - Fork 2
Remove implicit object lifetime cast #1
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: new-new-devices
Are you sure you want to change the base?
Conversation
|
Hello! Thank you for your pull request. To be honest this is a bit over my head, and if you would be willing to answer a few questions, that would be great.
I'd love to merge and get this resolved if I could get a bit more clarity on the issue it fixes. |
Forbid freely casting lifetime bounds of dyn-types Fixes #136702 Reference PR: - rust-lang/reference#1951 Background reading about VTable calls/dyn compatibility: https://hackmd.io/zUp-sgZ0RFuFgsNfD4JqYw This PR causes us to start enforcing that lifetimes of dyn types are constrained through pointer casts. Currently on stable casting `*mut dyn Trait + 'a` to `*mut dyn Trait + 'b` passes with no requirements on `'a` or `'b`. Under this PR we now require `'a` to outlive `'b`. Even though the pointee of `*mut` pointers is considered to be invariant, we still use subtyping rather than equality. This mirrors how we support coercing `&mut dyn Trait + 'a` to `&mut dyn Trait + 'b` while requiring only `'a: 'b`. I believe this coercion is sound as there is no way for safe code to `mem::swap` two `dyn Trait`'s, and the same is definitely true of raw pointers. See the changes to this test: https://github.com/rust-lang/rust/pull/136776/files#diff-5523f20a800287a89c9f3e92646c887f3f7599be006b29dd9315f734a2137764 We also do not enforce any constraints on the lifetime of the dyn types if there are multiple pointer indirections. For example `*mut *mut dyn Trait + 'a` is allowed to be casted to `*mut *mut dyn Trait + 'b` with no requirements on `'a` or 'b`. This case is just a normal thin pointer cast where we do not care about the pointee type as there is no VTable in play. Test: https://github.com/rust-lang/rust/pull/136776/files#diff-3b6c8da342bb6530524158d686455a545bb8fd6f59cf5ff50d1d991ce74c9649 Finally, this is about *any* cast where the pointee is *unsized* with dyn-type metadata, not just *literally* the pointee type being a dyn-type. E.g. casting `*mut Wrapper<dyn Trait + 'a>` to `*mut Wrapper<dyn Trait + 'b>` requires `'a: 'b` under this PR. Test: https://github.com/rust-lang/rust/pull/136776/files#diff-ca0c44df62ae1ad1be70f892f01a59714336c7baf78602a5887ac1cf81145c96 ### Breakage This is a breaking change. Crater Report Comment: #136776 (comment) Generated Report: https://crater-reports.s3.amazonaws.com/pr-136776-2/index.html The majority of the breakage is caused by the `metrics` crate with 142 of the regressions, and the `may` crate with 14 of the regressions. The `metrics` crate has been fixed and has backported the fix to previous versions of the crate that were also affected. The`may` crate has also been fixed. PRs against affected crates have been opened and can be seen here: - belalang-project/belalang#6 - tyilo/multi-vec#1 - luksan/lox#1 - pfzetto/bring-your-own-memory-demo#1 - vitorhnn/bfr#1 - gipsyh/PPSMC#1 - orengine/orengine#33 - maroider/async_scoped_task#1 - WorldSEnder/scoped_worker_thread#1 - Wind-Corporation/trapiron#5 - Thombrom/snek#1 - Xudong-Huang/may#113 - metrics-rs/metrics#564 - DouglasDwyer/micropool#1 - Magicolo/phylactery#8 - HellButcher/pulz#29 - UxuginPython/rrtk#1 - wvwwvwwv/scalable-delayed-dealloc#4 - ultimaweapon/tsuki#32 There were six regressions I've not filed PRs against: - https://github.com/weiznich/diesel_benches depends on a ~6year old version of diesel (where the regression is) - https://crates.io/crates/cogo/0.1.36 is an old version of cogo, since that release cogo has already been updated to not depend on pattern this PR breaks - https://github.com/cruise-automation/webviz-rust-framework is an archived read only repo so 🤷♀️ - makepad_render, doesn't seem to have source available and is 6 years old 🤷♀️ - outsource-heap - not on github - zaplib - I couldn't get it to compile locally as it failed to compile a dependency r? `@ghost`
Forbid freely casting lifetime bounds of dyn-types Fixes rust-lang/rust#136702 Reference PR: - rust-lang/reference#1951 Background reading about VTable calls/dyn compatibility: https://hackmd.io/zUp-sgZ0RFuFgsNfD4JqYw This PR causes us to start enforcing that lifetimes of dyn types are constrained through pointer casts. Currently on stable casting `*mut dyn Trait + 'a` to `*mut dyn Trait + 'b` passes with no requirements on `'a` or `'b`. Under this PR we now require `'a` to outlive `'b`. Even though the pointee of `*mut` pointers is considered to be invariant, we still use subtyping rather than equality. This mirrors how we support coercing `&mut dyn Trait + 'a` to `&mut dyn Trait + 'b` while requiring only `'a: 'b`. I believe this coercion is sound as there is no way for safe code to `mem::swap` two `dyn Trait`'s, and the same is definitely true of raw pointers. See the changes to this test: https://github.com/rust-lang/rust/pull/136776/files#diff-5523f20a800287a89c9f3e92646c887f3f7599be006b29dd9315f734a2137764 We also do not enforce any constraints on the lifetime of the dyn types if there are multiple pointer indirections. For example `*mut *mut dyn Trait + 'a` is allowed to be casted to `*mut *mut dyn Trait + 'b` with no requirements on `'a` or 'b`. This case is just a normal thin pointer cast where we do not care about the pointee type as there is no VTable in play. Test: https://github.com/rust-lang/rust/pull/136776/files#diff-3b6c8da342bb6530524158d686455a545bb8fd6f59cf5ff50d1d991ce74c9649 Finally, this is about *any* cast where the pointee is *unsized* with dyn-type metadata, not just *literally* the pointee type being a dyn-type. E.g. casting `*mut Wrapper<dyn Trait + 'a>` to `*mut Wrapper<dyn Trait + 'b>` requires `'a: 'b` under this PR. Test: https://github.com/rust-lang/rust/pull/136776/files#diff-ca0c44df62ae1ad1be70f892f01a59714336c7baf78602a5887ac1cf81145c96 ### Breakage This is a breaking change. Crater Report Comment: rust-lang/rust#136776 (comment) Generated Report: https://crater-reports.s3.amazonaws.com/pr-136776-2/index.html The majority of the breakage is caused by the `metrics` crate with 142 of the regressions, and the `may` crate with 14 of the regressions. The `metrics` crate has been fixed and has backported the fix to previous versions of the crate that were also affected. The`may` crate has also been fixed. PRs against affected crates have been opened and can be seen here: - belalang-project/belalang#6 - tyilo/multi-vec#1 - luksan/lox#1 - pfzetto/bring-your-own-memory-demo#1 - vitorhnn/bfr#1 - gipsyh/PPSMC#1 - orengine/orengine#33 - maroider/async_scoped_task#1 - WorldSEnder/scoped_worker_thread#1 - Wind-Corporation/trapiron#5 - Thombrom/snek#1 - Xudong-Huang/may#113 - metrics-rs/metrics#564 - DouglasDwyer/micropool#1 - Magicolo/phylactery#8 - HellButcher/pulz#29 - UxuginPython/rrtk#1 - wvwwvwwv/scalable-delayed-dealloc#4 - ultimaweapon/tsuki#32 There were six regressions I've not filed PRs against: - https://github.com/weiznich/diesel_benches depends on a ~6year old version of diesel (where the regression is) - https://crates.io/crates/cogo/0.1.36 is an old version of cogo, since that release cogo has already been updated to not depend on pattern this PR breaks - https://github.com/cruise-automation/webviz-rust-framework is an archived read only repo so 🤷♀️ - makepad_render, doesn't seem to have source available and is 6 years old 🤷♀️ - outsource-heap - not on github - zaplib - I couldn't get it to compile locally as it failed to compile a dependency r? `@ghost`
Unfortunately this is not the case, it does seem intuitively to make sense but unfortunately this would be unsound. While a raw pointer itself doesn't have a lifetime (unlike references), the pointee type ( For example a value of type
Trait objects ( For example if we were to coerce the type
Writing the type out in full we would say that we coerce the type The type So in summary:
Finally, while raw pointers don't actually have to point to any data, we do require that the wide pointer metadata is valid. In this case that means the VTable stored alongside the raw pointer must be valid. The crux of the issue here is that a wide pointer might have a VTable stored which is only valid for some lifetimes of the pointee, and casting the lifetime in the pointee could affect which methods are accessible through the VTable. Having a VTable in which methods are callable even though the origin type wouldn't have had the methods be callable would constitute an invalid VTable here.
We would generally like for the language to be sound under all editions.
I'm a bit late so the answer now is "the latest nightly"
rust-lang/rust#136776 is part of the 1.94.0 milestone which means that this breaking change will be part of the 1.94.0 stable release. I believe the 1.94.0 release wil go out on the 5th of march but I may be off by a day or so there :) |
Hi there o/
I'm a member of the Rust Language's Types Team; as part of stabilizing the
arbitrary_self_typesandderive_coerce_pointeefeatures we are changing what raw pointer casts are legal (rust-lang/rust#136702). Specifically, casting*const dyn Trait + 'ato*const dyn Trait + 'bwhere it is not able to be proven that'aoutlives'bwill become an error.Without going into too much detail, the justification for this change is that casting trait object's lifetime bound to a lifetime that lives for a longer time could invalidate the VTable of the trait object, allowing for dispatching to methods that should not be callable. See this example from the linked issue:
Unfortunately, going through the usual "future compatibility warning" process turned out to not be possible as checking lifetime constraints without emitting an error is prohibitively difficult to do in the implementation of the borrow checker. This means that you will never receive an FCW and its associated grace period to update your code to be compatible with the new rules.
I have attempted to update your codebase to the new rules for you so that it will still compile when we make this change. I hope this breakage won't cause you too much trouble and that you might even find the post-migration code to be better than how it was previously :-)
If you have any questions about why this change is required please let me know and I'll do my best to further explain the justification.
It wasn't clear to me if the pointer casts here were supposed to be implicitly casting the lifetimes of the trait object to
'static. This is currently happening because writing*mut dyn Traitin the return type of a function signature desguars to*mut dyn Trait + 'static, with this change we now write*mut dyn Trait + '_which introduces a new lifetime parameter.