-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
BTreeMap mutable iterators should not take any reference to visited nodes during iteration #73971
Conversation
benchcmp old newer --threshold 5
This compares the best over 10 runs each. Still not particularly clear, but not quite hopeful. Using |
Your "only way to do this currently" works too, and says basically no change in performance: benchcmp old newest --threshold 5
Thanks to baby steps, I think I understand that code better than anything before, but I think you'll agree it's not great to have (more of) this sort of code written out in btree directly. But I couldn't even write a generic function reusable for keys and vals. |
Btw, what are "alies" (in the PR title)? Probably you meant "allies" but even then I don't get it.^^ |
Indeed, what we should have is #60639 so you can just index the raw slice directly. #73987 makes that hard though. |
Good question, who are these allies? I was thinking of Which takes us back to your comment "Doing the descend [...] invalidates the references returned by |
Sigh... I just checked if "Miri is too slow" to check 144 references, i.e. 3 levels. It is not. It is, in fact, very fast to point out that something is still broken. It's not due to the last "Try disturbing the past" commit. It happens if I have no idea how to figure out what Miri is upset about. The 19th element, for inserts with increasing values and |
About the original code:
|
The way I understand the issue now, it seems very likely this would fail for any other mutable iterator implementation that doesn't apply social distancing to its elements, so everything but linked lists. It's definitely not hard to make Miri mad at VecDeque::iter_mut. |
Which special case? Fixing
The crucial part is that it is without references: the only reference being created here is to
This is the same. The other two create a reference to the entire
Uh-oh.^^ I was going to apply that mutable-iterator testcase to other collections, didn't expect issues to show up so quickly though. Do you want to open an issue for |
The one I thought I had reverted by commit aa0681fef26beb812884de5f0a92b6f5aab4a006... but looking closer, this doesn't revert the order you set in in #58431, but merely stores the result of navigation later and obfuscates the important order. When I try to really swap the order, Miri complains again (on the 12 element test that's currently committed). |
Sure, you'll soon get #74029 on your plate. |
So is |
It's still broken from 19 elements on. I only changed the code backing immutable iterators. |
The original mutable iterator testcase failed for 2 elements, so something presumably also changed there? Do you know what is the problem with 19 elements or do you want me to take a look? |
Well, what changed is most of this PR? You handled No, I have no idea what the problem is and I see you write it's quite awful to debug so definitely have a look. (*) The threshold is 19 elements if inserted in ascending order, like the test case does. In addition, one can insert up to 5 more smaller (negative) keys (which should land in the first child node). |
I think I got there through reasoning: 19 elements is indeed the first tree with children and two elements at the root and the first tree where |
☔ The latest upstream changes (presumably #76217) made this pull request unmergeable. Please resolve the merge conflicts. |
fdaaca0
to
8158d56
Compare
Rebased and reviewed locally -- this seems good to me. I didn't re-run tests or miri tests, though -- will wait on PR CI to pass, but r=me with that done. |
Looks like this PR does not add the Miri testcase from #73915, but I can do that in a follow-up PR (after verifying that it indeed works in Miri). |
Oh never mind, this removes the I'll submit a test based on |
@bors r+ |
📌 Commit 8158d56 has been approved by |
☀️ Test successful - checks-actions, checks-azure |
Oh, those tests already landed, great. :) |
…ark-Simulacrum BTreeMap: move up reference to map's root from NodeRef Since the introduction of `NodeRef` years ago, it also contained a mutable reference to the owner of the root node of the tree (somewhat disguised as *const). Its intent is to be used only when the rest of the `NodeRef` is no longer needed. Moving this to where it's actually used, thought me 2 things: - Some sort of "postponed mutable reference" is required in most places that it is/was used, and that's exactly where we also need to store a reference to the length (number of elements) of the tree, for the same reason. The length reference can be a normal reference, because the tree code does not care about tree length (just length per node). - It's downright obfuscation in `from_sorted_iter` (transplanted to rust-lang#75329) - It's one of the reasons for the scary notice on `reborrow_mut`, the other one being addressed in rust-lang#73971. This does repeat the raw pointer code in a few places, but it could be bundled up with the length reference. r? `@Mark-Simulacrum`
This looks like it was a small performance improvement on token-stream-stress-check of around 1.2%. Not really expected but nice anyway :) |
…r=Mark-Simulacrum BTreeMap: avoid slices even more Epilogue to rust-lang#73971: it seems the compiler is unable to realize that creating a slice and `get_unchecked`-ing one element is a simple fetch. So try to spell it out for the only remaining but often invoked case. Also, the previous code doesn't seem fair game to me, using `get_unchecked` to reach beyond the end of a slice. Although the local function `slice_insert` also does that. r? `@Mark-Simulacrum`
…=Mark-Simulacrum BTreeMap: bring back the key slice for immutable lookup Pave the way for binary search, by reverting a bit of rust-lang#73971, which banned `keys` for misbehaving while it was defined for every `BorrowType`. Adding some `debug_assert`s along the way. r? `@Mark-Simulacrum`
Fixes #73915, overlapping mutable references during BTreeMap iteration
r? @RalfJung