Constant values with interior mutability


#1

We can define const values with Cell types now.

#![feature(const_fn)]
use std::cell::Cell;

const G: Cell<i32> = Cell::new(1);

fn main() {
    G.set(2);
    drop(G);
    println!("{}", G.get());
}

But compiler still allows to call methods which can modify its internal value. Of course these methods take no effect. I think this behavior is counter-intuitive in my mental model. Why not trigger a compile error to forbid these methods?

Some may argue that this rule could be added in clippy, but I think it’s better to do it in compiler itself.


#2

But compiler still allows to call methods which can modify its internal value.

I’m not sure the compiler can easily tell. It’s not visible in the type signature: fn my_func(&self) tells me nothing about whether it will mutate the contents of self. So you have to force the compiler to inspect the function’s body (and all of its dependencies) to tell whether the function actually modifies anything. This solution introduces an invisible flag in the API that’s not visible in the types.

The remaining choices are to either ban all methods that accept &self, or ban all const data types that contain a Cell. The latter solution too introduces an invisible API on the data types.

Best you can do is probably introduce a lint, which probably won’t catch all cases.


#3

See also https://users.rust-lang.org/t/broken-atomics-puzzle/9533


#4

Thanks for your example code. I didn’t realize that it isn’t even specific to interior mutability. Your code is pasted here for reference:

fn main() {
    use std::ops::AddAssign;
    const NUMBER: u8 = 5;
    NUMBER.add_assign(1);
    println!("{}", NUMBER); // prints 5
}

It is not dangerous if we are taught correctly, but still confusing. Is there someone could confirm that this is by design?


#5

The issue is https://github.com/rust-lang/rust/issues/40543