For what it's worth, my thought was that "immovable types" are unnecessary to design in explicitly: we can rely on the borrow-checker's existing behavior to prevent moves of borrowed values, and use uninit
pointers to allow constructing a structure containing a self-borrow:
struct Immovable<'a, T> {
value: T,
anchor: PhantomData<&'a mut T>,
}
impl Immovable<'a, T> {
fn create(storage: &'a uninit Immovable, value: T) {
*storage = {
value: value,
anchor: PhantomData,
};
}
}
I do take some issue with:
Immovable types can be used to resolve a significant issue with current Rust that prevents simple translation from other mainstream languages in Rust's target market: they could allow reasonable construction of self-referential structures. (I appreciate the approaches @reem described in that link, but I don't think forcing a user to call a freeze
method to work with a structure is an ergonomic solution.)
Making immovable types useful in Rust probably requires &move
and &uninit
pointers. (As @reem's contribution to the question above showed, Rust already supports immovable types, they just aren't that easy to construct or work with.) &move
pointers also solve the issue with generics. (Option<Immovable<_, T>>
is difficult or impossible to make work, but Option<&move Immovable<_, T>>
should be OK, even without &move
being precisely defined: &move
is a pointer and its referent is not moving. To try to preempt a potential argument, I don't know if Box<>
is changing meaning from meaning "heap-allocated value" to something else, maybe new Box<>
obsoletes &move
. If so, I think this discussion would still apply with some names changed.)
For what it's worth, it wasn't my intention to argue against your proposal. But I don't yet share your belief that immovable types would be useless or impractical in Rust.
(For reference, previous discussion about &uninit
and &move
pointer types.)