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
Change LruCache.map to hold a pointer, rather than owned LruEntry
.
#161
Conversation
Remove unnecessary use of unsafe block
Hi @emilHof 👋 This is an interesting proposal and I think it could be worth it if it makes the code safer since the module has a fair bit of |
Hey @jeromefroe, thank you for taking your time to look over it! You are right, if it makes it safer and reduces The code has actually changed a slight bit since this pull request and now uses Should I merge this change into the pull request, as it likely also contributes to more soundness in the overall code? |
Change `*mut LruEntry<K,V>` to `NonNull<LruEntry<K,V>>`
Hey @emilHof! Thanks for updating the PR and sorry for the delayed response. The code looks good to me, especially with the use of |
fix clippy lint by dereferencing ptr explicitly before swapping mem
Hi @jeromefroe, no worries at all, I am quite sure you are busy and this pull request really is not the most urgent thing haha! the lint error should be fixed now! :D |
This is awesome! Thanks for the contribution @emilHof! |
Of course ! thank you for taking time to look over it!! :D |
This is meant as more of rough proposal, and I do not expect this to be merged in its current form. The aim of this pull request is to showcase a potential fix to an
miri
error that is inherent to the existing design.Running the current
master
branch againstcargo-miri
,miri
detects potential UB from an attempted retag of aSharedReadOnly
pointer. The specific error follows:In particular, this results from the combination of the
Hash
trait implementation ofKeyRef<K>
which holds a*const K
. In the case ofLruEntry
it acutally holds the key that*const K
points to. The problem is that this pointer is created before the ownedBox<LruEntry>
is inserted into the map asKeyRef<K>
is inserted alongside with it. This invalidates theSharedReadOnly
borrow through*const K
, as passing an owned value is aUnique
retag. See also miri-docs.To curb this issue, one possibility is saving
*mut LruEntry
's inmap
, rather than owned ones, which are constructed throughBox::into_raw(Box::new(LruEntry::new(k, v)))
. To prevent memory leaks, pointers are turned back intoBox<LruEntry>
when popping entries. TheDrop
implementation follows a similar pattern.When the original
owned
implementation is benched against the one that uses a*mut
these are the results:This is of course a huge change and maybe one that is too drastic, considering this only fixes an experimental
miri
error. There may also be much simpler and cleaner fixes that I am not aware of with my limited knowledge. I am still a bit new to OS Rust, so general feedback and tips for improvement would already be much more than I could ask for!