@@ -2536,10 +2536,19 @@ For more information about an error, try `rustc --explain E0277`.
25362536When we read this error message carefully, it not only tells us that we need to
25372537pin the values, but also tells us why pinning is required. The ` trpl::join_all `
25382538function returns a struct called ` JoinAll ` . That struct is generic over a type
2539- ` F ` , which is constrained to implement the ` Future ` trait. Finally, directly
2540- awaiting a Future requires that the future in question implement the ` Unpin `
2541- trait. That’s a lot! But we can understand it, if we dive a little further into
2542- how the ` Future ` type actually works, in particular around * pinning* .
2539+ ` F ` , which is constrained to implement the ` Future ` trait. Directly awaiting a
2540+ future with ` await ` pins the future implicitly. That’s why we don’t need to use
2541+ ` pin! ` everywhere we want to await futures.
2542+
2543+ However, we’re not directly awaiting a future here. Instead, we construct a new
2544+ future, ` JoinAll ` , by passing a collection of futures to the ` join_all `
2545+ function. The signature for ` join_all ` produces requires that the type of the
2546+ items in the collection all implement the ` Future ` trait, and ` Box<T> ` only
2547+ implements ` Future ` if the ` T ` that it wraps is a future which implements the
2548+ ` Unpin ` trait.
2549+
2550+ That’s a lot! But we can understand it, if we dive a little further into how the
2551+ ` Future ` type actually works, in particular around * pinning* .
25432552
25442553Let’s look again at the definition of ` Future ` :
25452554
@@ -2683,24 +2692,32 @@ that a given type does *not* need to uphold any particular guarantees about
26832692whether the value in question can be moved.
26842693
26852694Just as with ` Send ` and ` Sync ` , the compiler implements ` Unpin ` automatically
2686- for all types where it can prove it is safe. Implementing ` Unpin ` manually is
2687- unsafe because it requires * you* to uphold all the guarantees which make ` Pin `
2688- and ` Unpin ` safe yourself for a type with internal references. In practice,
2689- this is a very rare thing to implement yourself!
2695+ for all types where it can prove it is safe. The special case, again similar to
2696+ ` Send ` and ` Sync ` , is the case where ` Unpin ` is * not* implemented for a type.
2697+ The notation for this is ` impl !Unpin for SomeType ` , where ` SomeType ` is the
2698+ name of a type which * does* need to uphold those guarantees to be safe whenever
2699+ a pointer to that type it is used in a ` Pin ` .
2700+
2701+ In other words, there are two things to keep in mind about the relationship
2702+ between ` Pin ` and ` Unpin ` . First, ` Unpin ` is the “normal” case, and ` !Unpin ` is
2703+ the special case. Second, whether a type implements ` Unpin ` or ` !Unpin ` * only*
2704+ matters when using a pinned pointer to that type like ` Pin<&mut SomeType> ` .
26902705
26912706To make that concrete, think about a ` String ` : it has a length and the Unicode
26922707characters which make it up. We can wrap a ` String ` in ` Pin ` , as seen in Figure
2693- 17-7. However
2708+ 17-8. However, ` String ` automatically implements ` Unpin ` , the same as most other
2709+ types in Rust.
26942710
26952711<img alt =" Concurrent work flow " src =" img/trpl17-08.svg " />
26962712
26972713Figure 17-8: Pinning a String, with a dotted line indicating that the String
26982714implements the ` Unpin ` trait, so it is not pinned.
26992715
2700- This means that we can do things such as replace one string with another at the
2701- exact same location in memory as in Figure 17-9. This doesn’t violate the ` Pin `
2702- contract because ` String ` —like most other types in Rust—implements ` Unpin ` ,
2703- because it has no internal references that make it unsafe to move around!
2716+ As a result, we can do things which would be illegal if ` String ` implemented
2717+ ` !Unpin ` instead, such as replace one string with another at the exact same
2718+ location in memory as in Figure 17-9. This doesn’t violate the ` Pin ` contract,
2719+ because ` String ` has no internal references that make it unsafe to move around!
2720+ That is precisely why it implements ` Unpin ` rather than ` !Unpin ` .
27042721
27052722<img alt =" Concurrent work flow " src =" img/trpl17-09.svg " />
27062723
@@ -2709,9 +2726,10 @@ Figure 17-9: Replacing the String with an entirely different String in memory.
27092726Now we know enough to understand the errors reported for that ` join_all ` call
27102727from back in Listing 17-17. We originally tried to move the futures produced by
27112728async blocks into a ` Vec<Box<dyn Future<Output = ()>>> ` , but as we’ve seen,
2712- those futures may have internal references, so they don’t implement ` Unpin ` .
2713- They need to be pinned, and then we can pass the ` Pin ` type into the ` Vec ` ,
2714- confident that the underlying data in the futures will * not* be moved.
2729+ those futures may have internal references, so they don’t automatically
2730+ implement ` Unpin ` . Once we pin them, we can pass the resulting ` Pin ` type into
2731+ the ` Vec ` , confident that the underlying data in the futures will * not* be
2732+ moved.
27152733
27162734` Pin ` and ` Unpin ` are mostly important for building lower-level libraries, or
27172735when you’re building a runtime itself, rather than for day to day Rust code.
0 commit comments