Skip to content
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

Make RwLockReadGuard covariant over its type parameter #80392

Closed
Kestrer opened this issue Dec 26, 2020 · 2 comments · Fixed by #96820
Closed

Make RwLockReadGuard covariant over its type parameter #80392

Kestrer opened this issue Dec 26, 2020 · 2 comments · Fixed by #96820
Labels
A-concurrency Area: Concurrency related issues. C-enhancement Category: An issue proposing an enhancement or a PR with one. E-help-wanted Call for participation: Help is requested to fix this issue. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@Kestrer
Copy link
Contributor

Kestrer commented Dec 26, 2020

Currently RwLockReadGuard is invariant over its type parameter, meaning that for instance this sound code:

use std::sync::{RwLock, RwLockReadGuard};

fn do_stuff<'a>(_: RwLockReadGuard<'_, &'a i32>, _: &'a i32) {}

fn main() {
    let j: i32 = 5;
    let lock = RwLock::new(&j);
    {
        let i = 6;
        do_stuff(lock.read().unwrap(), &i);
    }
    drop(lock);
}

Will not compile. However, since RwLockReadGuard does not allow for mutation of the inner value, it would be sound to make it covariant, and it would be useful in some circumstances.

See also the same issue in parking_lot.

@LeSeulArtichaut LeSeulArtichaut added T-libs Relevant to the library team, which will review and decide on the PR/issue. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. C-enhancement Category: An issue proposing an enhancement or a PR with one. labels Dec 28, 2020
@the8472 the8472 removed the T-libs Relevant to the library team, which will review and decide on the PR/issue. label Feb 8, 2022
@yaahc yaahc added A-concurrency Area: Concurrency related issues. E-help-wanted Call for participation: Help is requested to fix this issue. labels Feb 8, 2022
@sobolevn
Copy link

I would love to give this a try! 👍
This is my first contribution to rust, so I might ask some questions 🙂

@sobolevn
Copy link

First steps:

  • RwLockReadGuard's second type argument is defined here:
    pub struct RwLockReadGuard<'a, T: ?Sized + 'a> {
    lock: &'a RwLock<T>,
    }
    It is only used for lock: &'a RwLock<T>
  • RwLock is defined here:
    pub struct RwLock<T: ?Sized> {
    inner: sys::MovableRWLock,
    poison: poison::Flag,
    data: UnsafeCell<T>,
    }
    Its type argument is only used for data: UnsafeCell<T> which is the source of invariance according to these rules

JohnTitor added a commit to JohnTitor/rust that referenced this issue Jun 22, 2022
Make RwLockReadGuard covariant

Hi, first time contributor here, if anything is not as expected, please let me know.

`RwLockReadGoard`'s type constructor is invariant. Since it behaves like a smart pointer to an immutable reference, there is no reason that it should not be covariant. Take e.g.

```
fn test_read_guard_covariance() {
    fn do_stuff<'a>(_: RwLockReadGuard<'_, &'a i32>, _: &'a i32) {}
    let j: i32 = 5;
    let lock = RwLock::new(&j);
    {
        let i = 6;
        do_stuff(lock.read().unwrap(), &i);
    }
    drop(lock);
}
```
where the compiler complains that &i doesn't live long enough. If `RwLockReadGuard` is covariant, then the above code is accepted because the lifetime can be shorter than `'a`.

In order for `RwLockReadGuard` to be covariant, it can't contain a full reference to the `RwLock`, which can never be covariant (because it exposes a mutable reference to the underlying data structure). By reducing the data structure to the required pieces of `RwLock`, the rest falls in place.

If there is a better way to do a test that tests successful compilation, please let me know.

Fixes rust-lang#80392
@bors bors closed this as completed in 00ce472 Jun 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-concurrency Area: Concurrency related issues. C-enhancement Category: An issue proposing an enhancement or a PR with one. E-help-wanted Call for participation: Help is requested to fix this issue. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants