-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
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
Support raw access without lifetimes to UntypedMut #10039
base: main
Are you sure you want to change the base?
Conversation
Welcome, new contributor! Please make sure you've read our contributing guide and we look forward to reviewing your pull request shortly ✨ |
Lifetime transmutation is one of the only acceptable uses of transmute, so this is probably sound. However, arbitrary unscoped lifetime extension is 100% unsound. We do this in TaskPool::scope, but we strictly control the exposed API to make sure that the 'static lifetime is never leaked outside of the scope itself, whereas this openly exposes unbounded lifetimes publicly. |
This is also why I would also appreciate if there's a rigorous source for the soundness of lifetime transmutes to point to. There is the transmute example but it doesn't fill me with a great deal of confidence, as in:
Reading this, do we know for sure that now and in the future the correctness of the transmute doesn't depend on the layout of |
I'm not sure this is the best way to expose the necessary functionality - the data side of the Furthermore, I think it'd be better if neither of these raw options were actually used in bevy, and instead kept only for interfacing with external libraries that can't or won't pipe around the lifetimes, to make as much use of lifetime checking in the bevy codebase as possible and minimize spots where it could get forgotten. |
Objective
UntypedMut
to avoid potentially unsound lifetime casts / transmutes when bevy is used across raw APIs.Raw access through a pointer requires us to shed the lifetime associated with
UntypedMut
to later reconstruct it using a pointer cast, and the only valid option is'static
. I am genuinely not sure whether this is sound. My hunch is that it isn't because Rust is open to decide thatFoo<'a>
is laid out differently toFoo<'static>
, all though in practice I don't think it is. To be super sure though it's better to have a dedicated set of raw APIs which are guaranteed to be sound.Solution
Ticks
andTicksMut
to both utilize a layout equivalent interior struct calledTicksRaw
containing pointers instead of references, and ensures that their lifetype parameters are constrained throughPhantomData
.UntypedMut
gets a new sibling type calledUntypedMutRaw
which you can construct throughUntypedMut::into_raw
.UntypedMutRaw
gets an unsafe function calledas_mut
which translates it into anUntypedMut
with an unbounded lifetime.If this looks good, I'd be happy to build out raw
Ref
access as well since that is also something I'd need. Thank you!