Crate with a type with interior mutability that you can make it read only?

I was wondering if there's a crate that implements a type with interior mutability, but you can lock it once and it's immutable forever? Sorta like this:

fn main() {
    let three = OnceRefCell::new(3);

    // in the real code you'd most likely use try_borrow_mut()
    *three.borrow_mut() += 8; // allowed
    *three.borrow_mut() += 7;

    println!("{}", three.borrow()); //  prints 18

    three.make_read_only();

//  *three.borrow_mut() += 3; // not allowed
    println!("{}", three.borrow()); //  prints 18, still allowed!
}

I guess I could replicate this behavior using RefCell<(T, bool)>, where the boolean is used to keep track of mutability, but I'm wondering if there's a crate or something that implements this in a more robust manner?

I guess this is essentially RefCell::into_inner in some disguise?

Similar behavior, but the difference is that the value can still be read after doing it

Of course it can be read, if it is owned.

Well the idea was that I'd have these in struct fields.

Well, if you want to have a single type which can be used as both RefCell<T> and T (i.e. if you want this make_read_only to operate in-place, not changing the type), you probably can't do much better then the equivalent of RefCell<(T, bool)>, since this "readonly" state will have to be runtime-checked anyway.

that's fair, that makes sense

You could do std::mem::forget(refcell.borrow()), which will leave the RefCell in a permanently borrowed state that will make .borrow_mut() calls fail but still allow .borrow() calls to succeed.

5 Likes

A cell that was aware of its read-only state could start offering unguarded &T references since it knows the T won't be further mutated. That's additional functionality, not additional performance, but there are applications for it (it's a sort of more general OnceCell).

You could build that using a { frozen: Cell<bool>, data: RefCell<T> } and RefCell::try_borrow_unguarded().

4 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.