Fix Stacked Borrow violations in BptreeMap
#125
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Background
This PR fixes numerous violations of
Miri
's Stacked Borrow checker inBptreeMap
.In almost all cases, these violations appear to be inconsequential. Casting back-and-forth between
* const T
and&T
appears to interfere with Miri's analysis even though such casts should not be able to introduce data races. Unfortunately, fixing the obvious violations of Stacked Borrows lead to the discovery of one instance of possible UB inRangeMutIter
. This PR does not fix that behavior - it merely fixes enough violations to make that behavior discoverable via Miri. Further analysis is required to determine ifRangeMutIter
is actually sound.This PR also does not fix any violations of Stacked Borrows in types other than
BptreeMap
. In the short term, I'm maintaining a fork of the crate which exposes only the functionality that I've been able to show is free from UB.Description of Changes
This PR introduces no net new functionality. Instead, changes can be grouped into 3 buckets:
Removing unneeded conversions between shared and mutable references which could trigger UB or cause spurious Stacked Borrows violations.
leaf_ref
andbranch_ref
macros, which returned&mut T
but were nearly always coerced to&T
immediately afterward. Since creating an aliased&mut T
is UB even if the alias is never dereferenced, this behavior was very dangerous. And indeed, it dig triggerMiri
's anlysis in several cases. In this PR, I've added parallel versions of these macros which directly yield&T
.Adding variants of existing functions that operate on raw pointers instead of shared references. These new functions allow us to avoid casts between
&T
and*const T
.min_raw
function, which is exactly likemin
except that it takes a*const Self
instead of&self
and returns a*const K
instead of&K
.Restructuring tests to avoid coercing from
*const T
to&T
and back by simply storing the*const T
in a separate variable rather than shadowing it.test_bptree2_node_leaf_remove_order
.