-
Notifications
You must be signed in to change notification settings - Fork 48
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
Update seize
to 0.3
#123
Update seize
to 0.3
#123
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files
|
It looks like the |
Hmm, I think what we're running into here is actually this property, where the expectation is that a Moving to passing in a raw pointer does avoid this problem since it means What's super interesting is that using the new tree borrows model Would you mind splitting out the I'm going to be bold and tag in @RalfJung and @Vanille-N here, just in case they can shed some light on the situation. Very briefly, the question is: is it okay to have a function that does this: Lines 244 to 246 in 48ff2e6
and then immediately makes the |
Unless I misunderstand, the situation you describe isn't actually "aliased memory". At least it definitely doesn't violate That doesn't answer why SB complains about the code, but at least (unless |
Thank you, that's helpful! You are indeed right, we never create cousins of the Yeah, no idea why SB and TB disagree here. @ibraheemdev I think I'd recommend undoing the |
As long as the other threads are using the pointer that was created by
Yes that seems totally fine, as Neven said. The error indicates that you are using a pointer that is not derived from that The error makes it look like some unknown old pointer X is used to construct the TB is more tolerant of read-only aliasing with unique pointer (mutable references and Box), so if this |
Yeah, the issue that we are actually aliasing pointers. The outside is constructing a tree and giving it's children back pointers to the root node. It's then turning the root pointer into a Box and passing it to @jonhoo I'm not sure we should be switching to tree borrows semantics to avoid an issue like this because once the tree is constructed the pointers are aliased, so we shouldn't really be using |
Ahhh, yes, you're right @ibraheemdev. Although the problem isn't the aliasing (I think we're actually doing that part right), it's the provenance. And concurrency isn't part of the problem. To give a bit more detail for Ralf/Neven since this is interesting (and possibly just a shortcoming of SB): The heap allocated value is originally constructed here: Lines 2780 to 2781 in 48ff2e6
This happens as part of constructing a doubly-linked list just prior to the call with the On the first iteration through, Line 2779 in 48ff2e6
After the linked list construction, we now turn Lines 2801 to 2806 in 48ff2e6
From an aliasing perspective, not a problem — we have another raw pointer to it, but as long as it isn't dereferenced, things are fine. The We then pass that Once we now go to use this tree for anything, we hit the problem (at least for SB). I think what happens is that Miri sees the (read) access of the root, and concludes that this is access via the provenance of the Why TB allows this I'm not entirely sure, but it sounds like you're onto something @RalfJung in that it may have sufficient information about the provenance tree here to conclude that it's okay for these provenances to co-exist when all the accesses are reads? In terms of where we go from here, I suppose I'm okay switching to the |
There's no difference between these. Provenance is how aliasing is defined. So I don't know what you mean by this. If you have a long-lived If there are truly only
My theory is that in the testcase, everything is read-only. TB allows aliasing of
then there should be UB with TB as well. |
I think it's probably a mistake to use these terms interchangeably. While we may define aliasing in terms of provenance, that doesn't mean they are synonyms. Semi-formally, at least in my head, provenance is "knowledge of ow we got here", while aliasing is "a statement about the provenance graph". But in this case, I was using the less-formal meaning of aliasing, namely "are two pointers pointing to the same address" (which yes, I know, is an overly-simple way of looking at the world 😅). So what I meant was that the problem isn't that we have two
Yes, I think that's right. The various "states of the world" are, in order:
I think the question is whether this means "the I suppose TB in this case allows it because it realizes that
Yep, see above. |
what I meant was that the problem isn't that we have two *mut to the allocation behind a Box while the Box lives (which was my read ***@***.***'s comment)
I would say that is exactly the problem. The point is that the Box is live as long as at least one pointer derived from it is live. That is a fundamental ingredient of both Stacked Borrows and Tree Borrows.
|
I suppose TB in this case allows it because it realizes that Box::into_raw and Box::from_raw don't do that? Maybe?
No, TB allows it because there are no writes.
|
Oh interesting, I hadn't thought about it that way. If that is indeed the rule, then yes, totally agree that we violate
Ah, yes, I suppose "relocating" is really just one example of a write, but any write indeed. |
src/map.rs
Outdated
// safety: we have just created `low` and its `next` | ||
// nodes and have never shared them | ||
let low_bin = unsafe { | ||
BinEntry::Tree(TreeBin::new(Box::into_raw(low.into_box()), guard)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on my read of the discussion, I think we shouldn't Box::into_raw(low.into_box())
here (and elsewhere) — we shouldn't be re-constructing a Box
at all. Instead, we should grab the raw pointer directly with low.0.into_inner()
so that we preserve the right provenance. In fact, we should probably remove fn into_box
entirely.
Follow-up question on this: how does this work when you have code like this: let a = Box::new(42);
let b = Box::into_raw(a);
let c = unsafe { Box::from_raw(b) };
drop(c);
|
Okay looks we found the cause of the misunderstanding then. :)
No, this is fine for the same reason reborrowing is fine with |
b34292c
to
a04005c
Compare
The new Miri failures are unrelated and caused by a recent nightly regression (rust-lang/rust#124013). Everything passes running locally an older Miri. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent, this looks good to me, thanks!
One interesting question here is whether we can now remove into_box
entirely?
Releasing in #124 |
This change is