Hacker News new | ask | show | jobs
by anderskaseorg 588 days ago
Yes, allowing this to execute would be very unsound:

    let lock = RwLock::new(Box::new(111));
    let r: &i32 = &**lock.read().unwrap(); // points to 111
    *lock.write().unwrap() = Box::new(222); // allocates a new Box and deallocates 111
    println!("{}", *r); // use after free
1 comments

It can be done safely with an upgrade method that requires an owned read guard. The RwLock implementation provided by the parking_lot crate supports this safely:

    let lock = RwLock::new(Box::new(111));
    let read = lock.upgradable_read();
    let r: &i32 = &**read; // points to 111
    *RwLockUpgradableReadGuard::upgrade(read) = Box::new(222); // error[E0505]: cannot move out of `read` because it is borrowed
    println!("{}", *r);
Of course (but that’s not relevant to the original scenario, where the programmer is hypothetically not aware that the read lock is still being held, let alone that they could manually upgrade it after changing to a different lock library).
The problem is that in the 'if let' case, the 'else' block has no access to the read guard. It's out of scope, except that the compiler hasn't dropped it yet.