Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

It’s not clear to me that the compiler couldn’t detect when you try to move a self referential string and prevent it. It basically does if you use pin.


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?


I'm not saying a theoretical language couldn't be made that allows this, but in Rust it would be breaking backwards compatibility.

For example [T]::sort (obviously) needs to be able to move the elements in the passed array, but there is no Move bound on T or something similar.

> It basically does if you use pin.

And we have Pin today, but I assumed the OP meant 'self-referential struct' as in, without using Pin.


It would have to be introduced by making it default, so all existing generic items would have Move bound on all generic parameters.

Only in a new edition the default can then be swapped.


> And we have Pin today, but I assumed the OP meant 'self-referential struct' as in, without using Pin.

I did, but with Pin would be fine as well




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

Search: