-
Notifications
You must be signed in to change notification settings - Fork 58
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
What about: "container_of"-style pointer arithmetic? #243
Comments
This is used in allocators, among other things, so it needs to be supported. |
Even if both references are immutable, or only if one is mutable? For what it's worth, I think it would be nice if the compiler could do scalar-replacement-of-aggregates (i.e. splitting a structure-typed variable into individual variables for each of the fields, which can then potentially be stored in registers rather than memory) even when a reference to one of the fields escapes. This would break In theory there could be a per-struct switch for whether to allow that kind of optimization or allow |
I think the natural answer is that repr(Rust) assures nothing (allowing the optimization) and repr(C) makes it more like C (blocking the optimization). I'll note that this very day I saw at least one "libc shim" that offers malloc/realloc/free and is totally broken when the ability to do a "container_of" maneuver isn't allowed. |
Certainly yes to the second. A mutable reference is a unique pointer, it must not alias with any other reference.
Can and do allocators ensure that only raw pointers are used when computing the "field pointer" (the argument to |
Hm, that is a separate concern. Note that |
No. drop(Box::from_raw(Box::leak(b))); Here the box becomes a &mut briefly before becoming a box again. This is supposed to be sound according to all the conventions of the standard library. |
According to all aliasing models proposed so far, it is not sound for the allocator to use Seems like this will be interesting.^^ |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
The allocator on Windows already does something similar: https://github.com/rust-lang/rust/blob/7f5a42b073dc2bee2aa625052eb066ee07072048/library/std/src/sys/windows/alloc.rs#L8-L10 So uh, sure would be great to have a solution! |
Also see #256 for a related discussion. |
Closing as a duplicate of #256. |
On unstable Rust, we can finally have a sound unrestricted
offset_of!
macro (as already implemented in the memoffset crate). But one interesting open question remains: what about a macro like what @Amanieu calledcontainer_of!
in Gilnaa/memoffset#21? That macro compute a pointer to the "outer object" given a pointer to some field.The problem with that macro is that it is very hard to use with aliasing rules as strict as Stacked Borrows, but I also see no good way to adjust Stacked Borrows to support this without losing many optimizations. Basically, the restriction is that only raw pointers may be used when computing the field pointer from the "outer object pointer". Any intermediate reference asserts that this and all derived pointers may only be used for the memory range covered by this reference, making
container_of!
incorrect.I don't see a fundamental reason why a Rust aliasing model has to constrain pointers like that. However, I do think it is crucial that we may not just use a reference to one field for a sibling field if a reference to the sibling field exists. That would be illegal aliasing with that sibling reference. So we might be able to relax Stacked Borrows a bit, but not a lot.
I am not sure if a
container_of!
macro is still useful with all these restrictions, it certainly is non-trivial to use.The text was updated successfully, but these errors were encountered: