3

I am unable to locate the documentation for !Unpin referred to here in the docs.

More generally, the ! operator seem to lack corresponding documentation regarding traits. Specifically, it seems to represent Not as in Not Unpin or perhaps Not Unpinable in this case. I suppose it is different from Pin in some way otherwise it would be redundant. Currently, searching for the documentation is challenging since ! occurs so frequently otherwise.

It would be good if the operator behavior of ! on traits could be included in Appendix B: Operators and Symbols of the docs.

George
  • 2,451
  • 27
  • 37
  • 2
    This is a negative implementation for an auto trait. Documentation is here: https://doc.rust-lang.org/stable/reference/special-types-and-traits.html#auto-traits – Sven Marnach Jun 09 '22 at 18:30
  • I admit this is hard to find without knowing the term "auto trait". – Sven Marnach Jun 09 '22 at 18:31
  • @SvenMarnach on the other hand, it's probably not that useful if you don't already know of auto traits. – jthulhu Jun 09 '22 at 19:41

1 Answers1

1

Unpin is one of several auto-traits, which are implemented automatically for any type that's compatible with it. And in the case of Unpin, that's, well, basically all of the types.

Auto-traits (and only auto-traits) can have negative implementations written by preceding the trait name with a !.

// By default, A implements Unpin
struct A {}

// But wait! Don't do that! I know something you don't, compiler.
impl !Unpin for A {}

Unpin, specifically, indicates to Rust that it is safe to move values of the implementing type T out of a Pin. Normally, Pin indicates that the thing inside shall not be moved. Unpin is the sort of opposite of that, which says "I know we just pinned this value, but I, as the writer of this type, know it's safe to move it anyway".

Generally, anything in Safe Rust is Unpin. The only time you'd want to mark something as !Unpin is if it's interfacing with something in another language like C. If you have a datatype that you're storing pointers to in C, for instance, then the C code may be written on the assumption that the data never changes addresses. In that case, you'd want to negate the Unpin implementation.

Silvio Mayolo
  • 62,821
  • 6
  • 74
  • 116
  • So, the traits `Unpin` means "safe" to move while `!Unpin` is "not safe" to move. However, the struct `Pin` indicates that something will "not" be moved in either case. Finally, `!` negates implicit traits such as `Unpin`. Is that right? – George Jun 09 '22 at 19:09
  • The only way to mark something "not safe to move" in Rust is to `Pin` it *and* have it be `!Unpin`. If something isn't inside a `Pin`, then it can be moved whenever. And if something implements `Unpin`, then it can be moved, even inside a `Pin`. – Silvio Mayolo Jun 09 '22 at 20:07
  • Does everything implements Unpin? Per the documentation: [This trait is automatically implemented for almost every type.](https://doc.rust-lang.org/stable/std/marker/trait.Unpin.html) Is it that it isn't implemented for `&mut T`? – George Jun 09 '22 at 20:27
  • 1
    @SilvioMayolo Nothing can be moved whilst inside a `Pin`. But `Unpin` specifies that you can can convert the object back to a movable variant with `Pin::into_inner()`. Which consumes the `Pin`. – Finomnis Jun 09 '22 at 21:30
  • To my knowledge `PhantomPinned` is preferred to the hard-coded `impl !Unpin`. But maybe I'm wrong. – Finomnis Jun 09 '22 at 21:32