4 ms·
> Pin is a way to create self referential structs, by pinning memory and preventing moves. This, exactly. Pin works more or less like a C++ class with a delete
by qalmakka 4y ago
> Pin is a way to create self referential structs, by pinning memory and preventing moves.
This, exactly. Pin works more or less like a C++ class with a deleted move constructor. Copies may be allowed if clone/copy (aka, the implicit/explicit copy constructor) are defined, but move and RVO are not.
Lots of Rust's concepts can often be described in terms of C++'s techniques, but more often than not in C++ it tends to be a hack, while Rust has a formalism for that, like Pin for instance. In C++ you can have moveable self-referencing structs because you can update the self references in the move constructor, but moves in Rust are always memcpy - which is saner IMHO than the whole move constractor and rvalue shenanigans.
- ridiculous_fish 4y agoHow does this work? I want to wrap POSIX semaphores. You call sem_init, passing it the address of an int; later you call sem_destroy and pass it the same address. So the location of the int must not change. In C++ you would delete the move constructor: struct sema { int v; void sema(sema &&) = delete; }; In Rust you might try this, but it doesn't work: struct Sema { v: Pin<i32>, } there is no way to create a "Pin<i32>". The closest you can get is probably to malloc it: struct Sema { v: Pin<Box<i32>> } but now Pin is adding nothing at all (except perhaps a hint to the reader) and may be deleted. The real guarantee is provided by Box, not Pin. It looks to me like Pin is created to support async, and outside of that use case is not very useful, and is a poor replacement for non-movable types.
- Ygg2 4y ago> there is no way to create a "Pin<i32>" Caveat, I haven't worked with Pin that much. Take this with a grain of salt. My understanding is - you really shouldn't put copyable stuff in Pin. Period. If you want something like that wrap i32 in new struct and declare it !Unpin. Since negative traits are unstable, you just write PhantomPinned marker struct NonPinI32 { v: i32, non_pin: PhantomPinned, }
- steveklabnik 4y agopin is purely a property of a pointer, so Pin<i32> doesn’t make sense. While you’re right that Box gives you a stable address, you can still move out of a Box, or swap something into the Box. Pin<Box<P>> prevents that.