Incomplete mini-guide to self-reference (non-movable objects)


#1

(Based off of https://www.reddit.com/r/rust/comments/49wfej/detecting_when_a_value_is_moved/d0zkfwl?context=1 )

An object containing a self-reference cannot be moved. But it doesn’t need to literally contain the self reference.

Let’s start with https://play.rust-lang.org/?gist=f561191d2885d44777cc&version=stable.
We make a reference to a part of MyLittleImmovableType and store it in MyLittleImmovableType itself. Observe that since MyLittleImmovableType contains a reference, the lifetime of the reference is part of the type (MyLittleImmovableType<'a>).

Let’s factor out the creation of the self-reference into another function, as seen in https://play.rust-lang.org/?gist=bbcd3d7945aa2ff5003c&version=stable. Uncommenting std::mem::drop still leads to a compilation error.

But, the type system tries to avoid relying on the contents of functions to determine what is valid or not. So it must be the type of the function tying things together. And indeed, in https://play.rust-lang.org/?gist=cddb7e5d7ba37aac6642&version=stable we can comment out the assignment of the reference, and you are still unable to move the object, as seen when attempting to uncomment std::mem::drop. It’s the mere action of calling the function with the type that coerces the lifetime in this way.

So we can simplify, as in https://play.rust-lang.org/?gist=c2b12b25ae1b0f4e4d5d&version=stable. There is no literal reference being stored, nor even room for it. It’s just lifetime manipulation.

As a side note, fn immobilize<'a, 'b: 'a>(_pony: &'b mut MyLittleImmovableType<'a>) { works too (the other way around does not work), so the passed in reference lives as long as the type. I can only assume that in actuality the lifetime has to match.


Stable way to prevent moving out of a type