0
fn test<T: Unpin>(t: T) {

}

fn main() {
    let a = 1;
    let b = async {
        1
    };
    test(b) // the trait `Unpin` is not implemented for `[async block]`
}

Future is not Unpin, so why does pinning it (pin_mut, Box::pin, etc., which wrap it with Pin<..>) make it implement Unpin?

Jimmy
  • 35,686
  • 13
  • 80
  • 98
BugMaker
  • 111
  • 1
  • 3
  • 1
    Because `Pin` [implements](https://doc.rust-lang.org/std/pin/struct.Pin.html#impl-Unpin-for-Pin%3CP%3E) `Unpin` if the value inside `Pin` implements `Unpin`, which is the case for [`&mut`](https://doc.rust-lang.org/std/marker/trait.Unpin.html#impl-Unpin-for-%26%27a%20mut%20T) and [`Box`](https://doc.rust-lang.org/std/boxed/struct.Box.html#impl-Unpin-for-Box%3CT%2C%20A%3E) and all other pointer types in the standard library – Jonas Fassbender Mar 10 '23 at 09:42
  • As a side note, here's a great read on why futures must be pinned: https://rust-lang.github.io/async-book/04_pinning/01_chapter.html with a lot of information about `Pin` and `Unpin` in Rust – Jonas Fassbender Mar 10 '23 at 09:51
  • @JonasFassbender why don't you put that answer (your first comment) in the answer box below? – cafce25 Mar 10 '23 at 09:54
  • @cafce25 Because I feel like though I answer OPs question in theory, I provide very little original content and no real explanation other than "look at the trait implementations" and "here is a good reference on how pinning in Rust works". Does this qualify as a full answer in your opinion? Sorry I'm still new to SO and still figuring out when to post what and where – Jonas Fassbender Mar 10 '23 at 09:59
  • 1
    You can quote the original documentation. Comments are not the place for answers even if short. – cafce25 Mar 10 '23 at 10:00

1 Answers1

2

Because Pin<T> implements Unpin if the inner value T implements Unpin, which is the case for &mut F (from pin_mut!) and Box<F> (from Box::pin) and all other pointer types in the standard library. Pointers implement Unpin, because they can be moved safely, since moving the pointer does not affect the pointee. See the std::pin module's documentation.

A great read on how pinning in Rust works and why we need to pin Future types can be found in the async book.

Jonas Fassbender
  • 2,371
  • 1
  • 3
  • 19