Hacker News new | past | comments | ask | show | jobs | submit login

Right. Pin is the canonical way to have objects that can't be moved, and it was invented in order to support objects with self-references (namely, futures). However, Pin's design is pretty hacky, being implemented purely 'in userspace' without any language support.

There's widespread desire to add some form of language support for pinning someday, if only to make the ergonomics a bit nicer (e.g. not needing a method call to reborrow mutable pinned references). This would probably also be needed in order for the compiler to support self-referential structs. From I've seen there are two quite different proposals for how to add language support for pinning. One is to add sugar to `Pin` while keeping the design mostly the same. For example, `Pin<&mut T>` could turn into `&pin mut T` or something. The other is to essentially throw away `Pin` and replace it with a `Move` auto trait: instead of `Pin<&mut T>` you would just have `&mut T` where `T: !Move`.

A `Move` trait would be quite disruptive, but would also have many benefits and ultimately simplify the language. For example, with `Pin`, every type has two possible kinds of mutable references to it: `Pin<&mut T>` and `&mut T`. In the case of self-referential structs, how would a non-pinned reference to one work? And how would that interact with `Drop`, which always takes `&mut self`? You could answer these questions one way or another, just like they're answered for futures (although futures have it easier because they always start in a non-self-referential state). But it all becomes simpler if you take the `Move` approach, where `&mut T` is pinned if `T` is `!Move`, and there is no second reference type to worry about.




Rust already has the `Unpin` trait, which is identical to `Move` except that it doesn’t pin `&mut T`. I’ve never understood why Rust doesn’t require the `Unpin` trait in `mem::swap` and derivatives instead of having `Pin`.

I also don’t really know of any other methods / cases besides those using `mem::swap` where `Pin` and `Unpin` are relevant. It works for `swap` because if you have a self-referential data structure, there’s never a good reason you want to tangle the references.

Lastly, normally a mutable reference guarantees there aren’t other references, but a mutable reference to a self-referential data-structure doesn’t have this guarantee because it references itself. Is this why `Pin<&mut T>` is necessary, because a real mutable reference to a set-referential data-structure violates Rust’s not-fully-defined “borrowing rules”? And do we want to keep that specific rule (since we’re mutable borrowing the entire region including the self-referential borrow, and self-referential structures are already unsafe, I doubt it would cause any issues)? Maybe `&pin mut T` should be added, but as its own kind of reference instead of syntax sugar…


> I’ve never understood why Rust doesn’t require the `Unpin` trait in `mem::swap` and derivatives instead of having `Pin`

Pin and Unpin came years after Rust had reached 1.0; wouldn't adding a new bound to an existing function be a breaking change?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: