-
Notifications
You must be signed in to change notification settings - Fork 59
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
Using a ZST reference like a raw pointer to avoid asserting aliasing #314
Comments
The underlying issue is a duplicate of #303. |
And indeed the ZST-based proposal fails under current Stacked Borrows since the |
The primary difference I see between this and #134 is that in that case, the pointer is initially derived from a part of the object. In this case, the initial pointer is derived from the entire object. This seems to be pretty similar to #256, though, agreed. Would
I'm a bit confused about this, and about raw pointer tagging in general. If raw pointers are truly untagged as stated here, then two raw pointers in the same allocation with the same permission/protector should be equivalent, right? The If the problem is incorrect provenance information deriving a (apologies on the accidental close/reopen, cat walked on keyboard) |
It's more that whatever needs to be done to support extern type will probably let us fix or at least greatly improve the other issues as well and hence might fix the problem here.
Indeed, with untagged raw pointers, Stacked Borrows gets "sufficiently confused" that this works out, But raw pointers being untagged is just a cheap way to support ptr-int-ptr roundtrips; to match what LLVM does, raw pointers do need to be tagged.
|
In my opinion, it's reasonably safe to assume that #303 is a spec bug and transmuting The same can't be said of accessing references beyond the bounds of the type, which is very intentionally UB (or at least potential UB) to enable specific optimizations. I think there should be an opt-out of some sort, but, other than |
I tend to agree.
I don't think this actually enables any optimizations. What is important is that you cannot access things that are in-bounds of other references in conflicting ways, but accessing "unclaimed memory" that does not really belong to any currently active reference should be fine. Stacked Borrows is IMO unnecessarily restrictive here. |
Hrm… I agree that forbidding accessing "unclaimed memory" is not necessary for the main optimizations in question, and it would be nice not to forbid it, but I'm hesitant to guarantee it won't end up being forbidden anyway for implementation convenience. For example, imagine enforcing reference bounds on slice indexing by adding the
The LangRef does go on to mention some things that disqualify
But suppose those restrictions were hypothetically loosened, and we started to use Perhaps this drawback would be enough to disqualify |
I'm working on possible solutions for tock/tock#2882, where kernel code needs to handle buffers as possibly mutating when shared with an application, even if derived from a
&[u8]
. Currently, it transmutes a&[u8]
to&[Cell<u8>]
, which is UB.The obvious solution to this is to only use raw pointers. A
*const [u8]
can soundly read from either a&[u8]
or&[Cell<u8>]
. However, this would involve non-trivial code changes and would preclude using useful traits likeIndex
.One solution I was thinking of is to use a reference to ZST as a sort of "medium-rare pointer", somewhere between a
&T
and*const T
. Since ZST references don't assert the aliasing properties of any memory, they could theoretically be used to hold an address and be read/written from from like a raw pointer, while erasing the difference between&T
and&Cell<T>
. I developed this idea into an experimental ZST type that I call "existential references", implemented in this crate. Example usage:However, I'm not entirely confident in the soundness of this design. This passes under Miri, but only with raw pointer tagging disabled:
So this leads to the question: how sound is this pattern? Are existential references a pipe dream?
&T
to*const T
to&()
, and then back to&T
, wheresize_of::<T>() > 0
?-Zmiri-tag-raw-pointers
, which declares the above invalid due to a retag? Or does it treat the provenance of raw pointers as less strict than for references?-Zmiri-tag-raw-pointers
to always fail.The text was updated successfully, but these errors were encountered: