# Pin ergonomics

**URL:** <https://internals.rust-lang.org/t/pin-ergonomics/21172>\
**Category:** Uncategorized\
**Created:** [July 14, 2024, 12:53pm UTC](https://internals.rust-lang.org/t/pin-ergonomics/21172 "2024-07-14T12:53:30Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![withoutboats](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/withoutboats/32/4560_2.png) [@withoutboats](https://internals.rust-lang.org/u/withoutboats)\
**Post date:** [July 14, 2024, 12:53pm UTC](https://internals.rust-lang.org/t/pin-ergonomics/21172/1 "2024-07-14T12:53:30Z")

</div>

(NOT A CONTRIBUTION)

The attached gist contains a set of features which would work to make Pin more ergonomic.

The features specifically are:

1. New pinned reference operators `&pinned [place]` and `&pinned mut [place]`
2. Adding pinned references to method resolution.
3. Assigning to pinned references.
4. Pinned method receiver parameters (`&pinned self` and `&pinned mut self`).
5. Supported pinned field projections with `#[pinned_fields]` attribute.
6. [optional] `DerefPinned` operator trait.
7. [optional] native syntax `&pinned T` and `&pinned mut T` types.

The only semi-breaking change would be the need to select a keyword for the new reference operators; I chose `pinned` in this gist because `pin` is used frequently in std APIs.

I may have made mistakes in my reasoning or understanding of e.g. method resolution; very eager to receive corrections.

My opinion is that adding some of these features would be a much easier way to solve the problem of pin ergonomics than trying to deprecate pin and add a new trait like `Move`. The biggest problem with `Move` is that it is not backward compatible to add either as an auto trait or as a `?Trait`. I wrote about this in a blog post last year: [Changing the rules of Rust](https://without.boats/blog/changing-the-rules-of-rust/)

> <https://gist.github.com/withoutboats/b5b16988e32f49a02733b668cf892711>

---

<div class="post-metadata">

**Author:** ![pitaj](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/pitaj/32/11262_2.png) [@pitaj](https://internals.rust-lang.org/u/pitaj)\
**Post date:** [July 14, 2024, 2:27pm UTC](https://internals.rust-lang.org/t/pin-ergonomics/21172/2 "2024-07-14T14:27:48Z")

</div>

Isn't `DerefPinned` redundant? Isn't that always covered by the unconditional `Deref` impl on `Pin`?

---

<div class="post-metadata">

**Author:** ![withoutboats](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/withoutboats/32/4560_2.png) [@withoutboats](https://internals.rust-lang.org/u/withoutboats)\
**Post date:** [July 14, 2024, 2:33pm UTC](https://internals.rust-lang.org/t/pin-ergonomics/21172/3 "2024-07-14T14:33:08Z")

</div>

(NOT A CONTRIBUTION)

Yea, that's probably true, because you can get there with the other change to method resolution by doing the normal deref on `Pin<P>` to get `P::Target` and then adding the `&pinned` operator.

EDIT: Updated the gist to reflect this. For those reading this conversation later, there were previously both `DerefPinned` and `DerefPinnedMut` in the gist; since the immutable one was unneeded, I rewrote the gist to add only the mutable version under the name `DerefPinned`.

---

<div class="post-metadata">

**Author:** ![Jules-Bertholet](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jules-bertholet/32/10671_2.png) [@Jules-Bertholet](https://internals.rust-lang.org/u/Jules-Bertholet)\
**Post date:** [July 14, 2024, 5:07pm UTC](https://internals.rust-lang.org/t/pin-ergonomics/21172/4 "2024-07-14T17:07:28Z")

</div>

Previously by me: [Pin projection with lots of language support](https://internals.rust-lang.org/t/pin-projection-with-lots-of-language-support/20525)

---

<div class="post-metadata">

**Author:** ![withoutboats](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/withoutboats/32/4560_2.png) [@withoutboats](https://internals.rust-lang.org/u/withoutboats)\
**Post date:** [July 14, 2024, 5:16pm UTC](https://internals.rust-lang.org/t/pin-ergonomics/21172/5 "2024-07-14T17:16:48Z")

</div>

(NOT A CONTRIBUTION)

I guess I forgot about your post; other than syntax there doesn't seem to be a lot of difference between the two.

---

<div class="post-metadata">

**Author:** ![withoutboats](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/withoutboats/32/4560_2.png) [@withoutboats](https://internals.rust-lang.org/u/withoutboats)\
**Post date:** [July 23, 2024, 7:42pm UTC](https://internals.rust-lang.org/t/pin-ergonomics/21172/6 "2024-07-23T19:42:10Z")

</div>

(NOT A CONTRIBUTION)

Iterated on the ideas in this gist into a blog post here: [Pinned places](https://without.boats/blog/pinned-places/)

---

<div class="post-metadata">

**Author:** ![TOETOE55](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/toetoe55/32/7976_2.png) [@TOETOE55](https://internals.rust-lang.org/u/TOETOE55)\
**Post date:** [July 24, 2024, 6:47am UTC](https://internals.rust-lang.org/t/pin-ergonomics/21172/7 "2024-07-24T06:47:32Z")

</div>

How to construct a place that is both boxing and pinned, something like `Box<#[pinned] T>`, and how to construct this value (this still cannot avoid the issue of placement).

---

<div class="post-metadata">

**Author:** ![parasyte](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/parasyte/32/8925_2.png) [@parasyte](https://internals.rust-lang.org/u/parasyte)\
**Post date:** [July 24, 2024, 8:37am UTC](https://internals.rust-lang.org/t/pin-ergonomics/21172/8 "2024-07-24T08:37:34Z")

</div>

It avoids the issue of placement because `T` can always be moved until it is moved into a pinned place (and it doesn’t implement `Unpin`). `T` is not a place.

```rust
let pinned mut stream = Box::new(make_stream());

```

---

<div class="post-metadata">

**Author:** ![fbstj](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/fbstj/32/424_2.png) [@fbstj](https://internals.rust-lang.org/u/fbstj)\
**Post date:** [July 24, 2024, 8:47am UTC](https://internals.rust-lang.org/t/pin-ergonomics/21172/9 "2024-07-24T08:47:12Z")

</div>

thank you for your recent posts, they've helped me comprehend pinning to the point I have questions 😅

I might just not have read up enough and comprehended things, but I don't understand what a non-mut `&pinned x` reference can do?

---

<div class="post-metadata">

**Author:** ![withoutboats](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/withoutboats/32/4560_2.png) [@withoutboats](https://internals.rust-lang.org/u/withoutboats)\
**Post date:** [July 24, 2024, 10:02am UTC](https://internals.rust-lang.org/t/pin-ergonomics/21172/10 "2024-07-24T10:02:33Z")

</div>

(NOT A CONTRIBUTION)

> [@TOETOE55](#):
>
> How to construct a place that is both boxing and pinned, something like `Box<#[pinned] T>`, and how to construct this value (this still cannot avoid the issue of placement).

You still use `Box::pin` (or `Pin<Box<T>>::from`) to construct `Pin<Box<T>>`. This part of the Pin API is unchanged.

> [@parasyte](#):
>
> It avoids the issue of placement because `T` can always be moved until it is moved into a pinned place (and it doesn’t implement `Unpin`). `T` is not a place.
> 
> ```rust
> let pinned mut stream = Box::new(make_stream());
> 
> ```

Unfortunately this doesn't work because the Unpin impl on Box means that pinning a box doesn't pin its content. This impl was probably a mistake, but one that can't be rolled back now.

> [@fbstj](#):
>
> I might just not have read up enough and comprehended things, but I don't understand what a non-mut `&pinned x` reference can do?

Very little. The only use case I know is the pin-cell crate, which I wrote a long time ago: [crates.io: Rust Package Registry](https://crates.io/crates/pin-cell)

You can't pin-project through a `RefCell`, because it gives you full mutable access to the interior. PinCell is an alternative cell which only gives you pinned mutable access to the interior. `&pinned T` is used in the API because it proves you can never move `T` again.

---

<div class="post-metadata">

**Author:** ![Vorpal](https://avatars.discourse-cdn.com/v4/letter/v/aca169/32.png) [@Vorpal](https://internals.rust-lang.org/u/Vorpal)\
**Post date:** [July 24, 2024, 10:14am UTC](https://internals.rust-lang.org/t/pin-ergonomics/21172/11 "2024-07-24T10:14:11Z")

</div>

> [@withoutboats](#):
>
> You can't pin-project through a `RefCell`, because it gives you full mutable access to the interior. PinCell is an alternative cell which only gives you pinned mutable access to the interior.

Hm, doesn't seem like a very popular thing to do based on looking at the reverse dependencies on that crate.

But this means that _in theory_ you need a PinCell and a PinMutex (and they should arguably be in the standard library). But since I haven't really heard complaints about the lack of those I assume they are just very uncommon operations.

(I haven't really had to do much with pin yet, but I found your two most recent posts very enlightening, thank you)

---

<div class="post-metadata">

**Author:** ![kpreid](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kpreid/32/8484_2.png) [@kpreid](https://internals.rust-lang.org/u/kpreid)\
**Post date:** [July 24, 2024, 3:36pm UTC](https://internals.rust-lang.org/t/pin-ergonomics/21172/12 "2024-07-24T15:36:05Z")

</div>

> [@Vorpal](#):
>
> Hm, doesn't seem like a very popular thing to do based on looking at the reverse dependencies on that crate.

I suspect that, out of all the possible uses of pinning, almost all of the ones actually written so far are `Future`s (and related traits like `Stream` or `AsyncRead` that aren't strictly futures themselves), because it has been difficult to actually define a type that directly benefits from pinning (and is sound) _other than_ a compiler-generated `async` block type.

And, in particular, putting a `Future` in a `PinCell` only makes sense if you want to share ownership and polling of the future, which is already provided by [`FutureExt::shared()`](https://docs.rs/futures/latest/futures/future/trait.FutureExt.html#method.shared). There's not a lot of opportunity for variety in exactly what you do with the `Future`, since it only has the one operation which has (from an application rather than scheduling perspective) zero inputs and one output.

Hopefully, [`UnsafePinned`](https://github.com/rust-lang/rust/issues/125735) will help with that, by giving a well-defined foundation for “how do I soundly make use of my data being pinned”, and we’ll have a wider variety of uses of `Pin` in the future, and more reasons to use tools like `pin-cell`.

---

<div class="post-metadata">

**Author:** ![TOETOE55](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/toetoe55/32/7976_2.png) [@TOETOE55](https://internals.rust-lang.org/u/TOETOE55)\
**Post date:** [July 27, 2024, 5:10pm UTC](https://internals.rust-lang.org/t/pin-ergonomics/21172/14 "2024-07-27T17:10:02Z")

</div>

> [@parasyte](#):
>
> It avoids the issue of placement because `T` can always be moved until it is moved into a pinned place (and it doesn’t implement `Unpin`). `T` is not a place.
> 
> ```rust
> let pinned mut stream = Box::new(make_stream());
> 
> ```

Pin doesn’t have transitivity.🤔

---

<div class="post-metadata">

**Author:** ![TOETOE55](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/toetoe55/32/7976_2.png) [@TOETOE55](https://internals.rust-lang.org/u/TOETOE55)\
**Post date:** [July 27, 2024, 5:27pm UTC](https://internals.rust-lang.org/t/pin-ergonomics/21172/15 "2024-07-27T17:27:26Z")

</div>

> [@withoutboats](#):
>
> > [@TOETOE55](#):
> >
> > How to construct a place that is both boxing and pinned, something like `Box<#[pinned] T>`, and how to construct this value (this still cannot avoid the issue of placement).
> 
> You still use `Box::pin` (or `Pin<Box<T>>::from`) to construct `Pin<Box<T>>`. This part of the Pin API is unchanged.

So, we still need to use the Pin API, but introduce a new operator and build-in type `&pinned {mut}` makes the Pin API more user-friendly.

I guess:

```rust
let old_pinned_ref: Pin<&mut T> = blahblah;
let new_pinned_ref: &pinned mut T = &pinned mut * old_pinned_ref; // reborrowing by DerefPinnedMut.

```

---

<div class="post-metadata">

**Author:** ![dlight](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dlight/32/8462_2.png) [@dlight](https://internals.rust-lang.org/u/dlight)\
**Post date:** [July 27, 2024, 5:30pm UTC](https://internals.rust-lang.org/t/pin-ergonomics/21172/16 "2024-07-27T17:30:40Z")

</div>

> [@kpreid](#):
>
> I suspect that, out of all the possible uses of pinning, almost all of the ones actually written so far are `Future`s (and related traits like `Stream` or `AsyncRead` that aren't strictly futures themselves), because it has been difficult to actually define a type that directly benefits from pinning (and is sound) _other than_ a compiler-generated `async` block type.

Pinning is also widely used by crates that implement self referential structures. They use lots of unsafe, and it's indeed difficult for them to produce sound code (lots of crates in this space had their share of soundness issues), but it's theoretically possible to write sound self-referential structures in Rust using `Pin`.

it's hard to come up with a use for pinning that isn't related to self-referential data types in some way though (either compiler generated like async rust, or provided by a library using unsafe code)

edit: oh here's a cool use for pinning: the [moveit](https://crates.io/crates/moveit/) crate implements C++-style move constructors, by forcing your objects to be pinned and then "moving" them logically using a move constructor (which is not a Rust move, since in Rust moves are always a memcpy; so to represent C++ move semantics in Rust you must use `Pin`)

---

<div class="post-metadata">

**Author:** ![kpreid](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kpreid/32/8484_2.png) [@kpreid](https://internals.rust-lang.org/u/kpreid)\
**Post date:** [July 27, 2024, 5:43pm UTC](https://internals.rust-lang.org/t/pin-ergonomics/21172/17 "2024-07-27T17:43:14Z")

</div>

> [@dlight](#):
>
> Pinning is also widely used by crates that implement self referential structures.

Is it? As far as I know, none of `ouroboros`, `yoke`, or `self_cell` (the maintained self-reference crates I am aware of) use `Pin` in their API or implementation. They arrange for things to be immovable, but they don't expose this guarantee via `Pin`, only via borrow lifetimes. (And therefore, they all involve the referenced data being in some heap-allocated container internal to the self-referential struct, whereas `Pin` has the potential for zero internal allocation.)

I'd certainly like to see that happen, but as far as I've heard, it hasn't.

---

<div class="post-metadata">

**Author:** ![Ddystopia](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ddystopia/32/10915_2.png) [@Ddystopia](https://internals.rust-lang.org/u/Ddystopia)\
**Post date:** [July 29, 2024, 8:11am UTC](https://internals.rust-lang.org/t/pin-ergonomics/21172/18 "2024-07-29T08:11:08Z")

</div>

I think it is fine for futures alone, but Pin problem is not a futures problem. From my experience of writing pinned (not always self-referential) structs, is that you want them to pinned _immediately_ after creation. With today's Pin you need to first create it, then pin, then initialize. The problem is, how to differentiate is a type initialized or not? You cannot change it's type after it's pinned. I'm transmuting references to a new type sometimes, but it has a cost - you cannot rely on drop. Maybe with some kind of `&own` this might work out. But again, for me main problem with Pin is _not_ syntax and _not_ unsafe code, but that you cannot create a good api with it.

Example:

```rust
use os_sys::RawSemaphore;
use os_sys::create_semaphore;

struct Semaphore {
    raw: UnsafeCell<MaybeUninit<RawSemaphore>>,
}

unsafe impl Sync for Semaphore {}
unsafe impl Send for Semaphore {}

impl Semaphore {
    const fun new() -> Semaphore { ... }
    fn initialize(self: &pin mut Self) {
          unsafe { create_semaphore(self.raw.as_mut_ptr())
    }
    fn get(&pin self) {
        // How to ensure that it is called after `initialize`? 
        // We cannot use typestate pattern and consume `self` in `initialize` to return new type. 
        // Maybe we can have signature like `init(&pin mut UninitSem) -> &pin mut Sem` but there a 2 problems:
    // 1. You cannot have Drop to delete semaphore - should I have a bool inside? Meh
    // 2. You would cry if would like to have semaphore inside another struct with this appoach
// !Move types solve that problem *perfectly*
    }
}
```

---

<div class="post-metadata">

**Author:** ![amab8901](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/amab8901/32/11244_2.png) [@amab8901](https://internals.rust-lang.org/u/amab8901)\
**Post date:** [July 30, 2024, 1:50pm UTC](https://internals.rust-lang.org/t/pin-ergonomics/21172/19 "2024-07-30T13:50:33Z")

</div>

why do you write "(NOT A CONTRIBUTION)"?

---

<div class="post-metadata">

**Author:** ![hjr3](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/hjr3/32/263_2.png) [@hjr3](https://internals.rust-lang.org/u/hjr3)\
**Post date:** [July 30, 2024, 3:13pm UTC](https://internals.rust-lang.org/t/pin-ergonomics/21172/20 "2024-07-30T15:13:27Z")

</div>

> [@Problems with "dyn\* Trait"](https://internals.rust-lang.org/t/problems-with-dyn-trait/16420/3):
>
> (NOT A CONTRIBUTION) Required by my employer. Here is Niko's blog post: [dyn\*: can we make dyn sized? · baby steps](https://smallcultfollowing.com/babysteps//blog/2022/03/29/dyn-can-we-make-dyn-sized/)

---

<div class="post-metadata">

**Author:** ![Vorpal](https://avatars.discourse-cdn.com/v4/letter/v/aca169/32.png) [@Vorpal](https://internals.rust-lang.org/u/Vorpal)\
**Post date:** [July 30, 2024, 3:51pm UTC](https://internals.rust-lang.org/t/pin-ergonomics/21172/21 "2024-07-30T15:51:12Z")

</div>

To expand on this, I seem to remember hearing that all communication to a project using Apache 2 as licence is automatically licensed under Apache 2 unless otherwise marked. (So yes, everything we write here is licensed under Apache 2 and could be reused by the Rust project.)

I may have misunderstood / misremember though.

[Next page](https://internals.rust-lang.org/t/pin-ergonomics/21172.md?page=2)
