Live data from Hacker News

Pinning in Plain English

blog.schichler.dev

11–20 of 22 posts

Re: Pinning in Plain English

#11
post #6

Earlier quoted context omitted.

> safe from a pinning perspective The reason you can't get &mut T from Pin > is because the mutable reference lets you move the data in safe Rust, e.g. with std::mem::swap. So getting the &mut T from a Pin > is not safe from a pinning perspective.

Fair, but feels like that significantly reduces the utility of pinned types then if for certain values you lose the ability to mutate values when the compiler overwise knows that there is a single mutable reference.

There's a hole or oversight in `Arc`'s API in this regard, annoyingly. The function you're looking for would be something like

pub fn get_mut_pinned(this: &mut Pin>) -> Option>

, which for pinning-aware values should give you enough mutability and for `T: Unpin` can give you `Option` through `Option::as_deref_mut`. Unfortunately, I haven't seen any `Arc` implementations that actually provide it, since almost none of the third-party ones are pinning-aware. (My `tiptoe::Arc`'s `get_mut` has this signature, but that's a specialty container with additional requirements for the contained value.)

The same goes for `make_mut_pinned`, that's missing too (but to be fair would be much less useful, since pinning and `Clone` don't often mix that well).

Re: Pinning in Plain English

#12
post #3

Unfortunately this write-up didn’t help me at all understanding pinning. Alomost feels I need to read the article to the end in order to understand the assumptions at the start. I guess I’m missing some context. - what is ‘trivially moveable’? - why would I want to overload the assignment operator? - what is a move constructor? - why would this make memory safe apis tricky? - what does moving references outside unsaf…

Trivially moveable means that you can move the object by simply copying the bytes to a new location, and non-trivially-moveable objects are those that would be incorrect to move in this manner. A move constructor is a C++ concept for non-trivially-moveable types that lets you do something more complicated than just copying the bytes over when you want to move the value to a new location, and creating a move construct…

Something else that I didn't mention in the post is that `Pin>` is `From>` (so it can be cast directly, and here without reallocation or such), and this could also be implemented for (other) exclusively-owning containers with heap storage.

The standard library collections don't do this because they don't have an API that would make it useful. It suspect it's partly because you can't `self: &mut Pin` in stable, which would be needed to cleanly give them one, but there's also a fair argument for not making them kitchen-sink types while a wrapper could provide this easily.

Re: Pinning in Plain English

#13
post #3

Unfortunately this write-up didn’t help me at all understanding pinning. Alomost feels I need to read the article to the end in order to understand the assumptions at the start. I guess I’m missing some context. - what is ‘trivially moveable’? - why would I want to overload the assignment operator? - what is a move constructor? - why would this make memory safe apis tricky? - what does moving references outside unsaf…

Trivially moveable means that you can move the object by simply copying the bytes to a new location, and non-trivially-moveable objects are those that would be incorrect to move in this manner. A move constructor is a C++ concept for non-trivially-moveable types that lets you do something more complicated than just copying the bytes over when you want to move the value to a new location, and creating a move construct…

This is an amazing summary. Thank you.

Re: Pinning in Plain English

#14
post #7
post #3

Unfortunately this write-up didn’t help me at all understanding pinning. Alomost feels I need to read the article to the end in order to understand the assumptions at the start. I guess I’m missing some context. - what is ‘trivially moveable’? - why would I want to overload the assignment operator? - what is a move constructor? - why would this make memory safe apis tricky? - what does moving references outside unsaf…

"Trivially movable" means anyone can take an instance (that they own) and copy its data (just the plain memory cells) to a new location with a new address, then continue to use that instance at that new location without breaking anything. This is a weaker guarantee than `Copy` because they're not necessarily allowed to use both copies of the data as true instances. They can still delay choosing one, but they can only…

Thanks, this already helps quite a lot! I came to rust from mostly higher level languages, Haskell/JVM/JS. So there is this continuous battle of Rust solving problems that I’m not necessarily sure what they are and why those problems exist in the first place.

Re: Pinning in Plain English

#15
post #3

Unfortunately this write-up didn’t help me at all understanding pinning. Alomost feels I need to read the article to the end in order to understand the assumptions at the start. I guess I’m missing some context. - what is ‘trivially moveable’? - why would I want to overload the assignment operator? - what is a move constructor? - why would this make memory safe apis tricky? - what does moving references outside unsaf…

Trivially moveable means that you can move the object by simply copying the bytes to a new location, and non-trivially-moveable objects are those that would be incorrect to move in this manner. A move constructor is a C++ concept for non-trivially-moveable types that lets you do something more complicated than just copying the bytes over when you want to move the value to a new location, and creating a move construct…

Nearly all my confusion is gone. This is amazing, thanks!

Re: Pinning in Plain English

#16
post #7
post #3

Unfortunately this write-up didn’t help me at all understanding pinning. Alomost feels I need to read the article to the end in order to understand the assumptions at the start. I guess I’m missing some context. - what is ‘trivially moveable’? - why would I want to overload the assignment operator? - what is a move constructor? - why would this make memory safe apis tricky? - what does moving references outside unsaf…

"Trivially movable" means anyone can take an instance (that they own) and copy its data (just the plain memory cells) to a new location with a new address, then continue to use that instance at that new location without breaking anything. This is a weaker guarantee than `Copy` because they're not necessarily allowed to use both copies of the data as true instances. They can still delay choosing one, but they can only…

There was an interesting talk in RustConf 2021 discussing the possibility of adding in-place construction and C++-like "move constructors" for pinned data in Rust. You can find it under the title "Move Constructors: Is It Possible?" by Michel Young de la Sota.

Re: Pinning in Plain English

#17
post #11

Earlier quoted context omitted.

Fair, but feels like that significantly reduces the utility of pinned types then if for certain values you lose the ability to mutate values when the compiler overwise knows that there is a single mutable reference.

There's a hole or oversight in `Arc`'s API in this regard, annoyingly. The function you're looking for would be something like pub fn get_mut_pinned(this: &mut Pin >) -> Option > , which for pinning-aware values should give you enough mutability and for `T: Unpin` can give you `Option ` through `Option::as_deref_mut`. Unfortunately, I haven't seen any `Arc` implementations that actually provide it, since almost none…

Have you tried proposing these API's on the internals.rust-lang.org forum or via posting a proposed RFC? It's not clear to me if they're sound in the general case, but if that's the case they can absolutely be added.

Re: Pinning in Plain English

#19
post #7

Earlier quoted context omitted.

"Trivially movable" means anyone can take an instance (that they own) and copy its data (just the plain memory cells) to a new location with a new address, then continue to use that instance at that new location without breaking anything. This is a weaker guarantee than `Copy` because they're not necessarily allowed to use both copies of the data as true instances. They can still delay choosing one, but they can only…

Thanks, this already helps quite a lot! I came to rust from mostly higher level languages, Haskell/JVM/JS. So there is this continuous battle of Rust solving problems that I’m not necessarily sure what they are and why those problems exist in the first place.

That's understandable, I originally come from about the same position too, with a bit less functional programming background.

I updated the intro to also cover that angle: https://github.com/Tamschi/Abstraction-Haven-Backup/commit/f...

Since it turned out quite a bit longer that way, I was pretty liberal with the bold formatting to make it still easy to skip for those familiar with the issue.

Re: Pinning in Plain English

#20
post #7

Earlier quoted context omitted.

"Trivially movable" means anyone can take an instance (that they own) and copy its data (just the plain memory cells) to a new location with a new address, then continue to use that instance at that new location without breaking anything. This is a weaker guarantee than `Copy` because they're not necessarily allowed to use both copies of the data as true instances. They can still delay choosing one, but they can only…

There was an interesting talk in RustConf 2021 discussing the possibility of adding in-place construction and C++-like "move constructors" for pinned data in Rust. You can find it under the title "Move Constructors: Is It Possible?" by Michel Young de la Sota.

There's actually a direct mention of that in my post already, but it's all the way near the bottom in the "Weakening non-moveability" section. It probably goes a bit too far to link in the intro, so I inlined a quick definition as relative clause there instead.

The `moveit` library is interesting also because it would allow pinning containers to expose a wider mutable API, though there's currently no trait to update instances post-move, which would allow `realloc` use. I filed an issue for it about a week ago: https://github.com/google/moveit/issues/26

That still leaves the issue of callback targets though, which would have to be notified before a possible move to support one-step reallocation.

Post reply on HN