Skip to content

fix(rwlock): remove downgrade from mapped write guards - #365

Open
orthur2 wants to merge 1 commit into
apache:mainfrom
orthur2:fix/rwlock-mapped-downgrade
Open

orthur2 wants to merge 1 commit into
apache:mainfrom
orthur2:fix/rwlock-mapped-downgrade

Conversation

@orthur2

@orthur2 orthur2 commented Oct 11, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #362.

Remove MappedRwLockWriteGuard::downgrade and OwnedMappedRwLockWriteGuard::downgrade, which are unsound. They were added in #65, first shipped in mea 0.4.2, and are still in 0.7.3. To keep shared access to a component, downgrade the original write guard first and then map it with RwLockReadGuard::map or OwnedRwLockReadGuard::map. The docs and the changelog describe this migration.

Design Notes

The projection of a mapped write guard can go through interior mutability using exclusive access, as Mutex::get_mut does. After a downgrade, another reader can lock the same mutex and change that data while the guard still hands out &U. With a RefCell<Box<_>> it is even a use-after-free in single-threaded safe code. No bound on the types rules this out, and keeping the write permits would make the method pointless, so this follows tokio and lock_api in not offering it. A downgrade_map taking FnOnce(&T) -> &U would only shorten the migration above, so it can wait until someone needs it. The reproducers and discussion are in #358 and #362.

Two compile-fail doctests keep the removed methods from coming back. Two Miri tests in unsafe_paths_test take the migration path while a second reader locks a mutex inside the projection. No other Miri test keeps a projected read guard alive while another reader uses the lock, so these would catch a read projection derived through &mut.

Comment thread CHANGELOG.md

## Unreleased

### Breaking changes

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm considering to release a 0.7.4 recently to include fixes like #361

Then we will merge this PR that includes breaking changes.

@QwQBiG do you happen to have some time the following week to handle this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good. @QwQBiG, the release skill covers the whole process, from the tracking issue through the ATR vote to publication. Feel free to ask me if anything is unclear. I went through it for 0.7.3.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry I actually don't know much related to the releasing process. But I think it would be better to add a flag like #[deprecated(note = "unsound, fixed in #365")]? (just to avoid the bug from releasing)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I can handle the 0.7.4 release. I'll confirm the release scope and follow the release skill.

Thanks @orthur2 for offering to help!

@orthur2

orthur2 commented Oct 11, 2026

Copy link
Copy Markdown
Contributor Author

@jeffoodchain @Soumya2004-java could you take a look when you have time?

GitHub only lets me request reviews from collaborators, so I couldn’t add you as reviewers, but you can still leave a review on the PR directly.

@jeffoodchain

Copy link
Copy Markdown
Contributor

yes ofc, would be happy to review. I will do this tomorrow. 🙏

@Soumya2004-java

Copy link
Copy Markdown

I reviewed the fix and it looks good to me. Removing both methods seems to address the issue, and the migration approach makes sense.

I saw the discussion about releasing v0.7.4 before merging this breaking change. That sounds reasonable.

I couldn't run the full test suite locally because Cargo couldn't resolve the crates.io download host, so I haven't independently verified the new tests under Miri.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Investigate unsound mapped RwLock write guard downgrading

5 participants