#Pin for Box<T> task that frustrates me

50 messages · Page 1 of 1 (latest)

pure ravine
#

Hi guys, maybe some of you faced this repo at the beginning or maybe it will be helpful for those, who like me, genuinely confused with this task. Since you are more skilled maybe you can explain me the spirit of this task or what intended to be done.

https://github.com/instrumentisto/rust-incubator/blob/main/1_concepts/1_2_box_pin/README.md .

General premise is understandable : i pinned the value-> value is moved -> I cannot call trait method on the value + it's not matching by self parameter.

Other pitfall that I can see is to avoid of pinning the reference, it will match SayHi trait parameter demand but will not actually pin value so I will be able to move it .

Other part is to show that some of the traits are working with pinned values to guarantee that value will not be moved out, some async parts dunno too stupid for that.

But I genuinely confused how can I squeeze out Pin to be able to call say_hi() on it and do not break pin semantic. I will really appreciate if you will take a look. Thanks a lot


fn main(){

 let pinned = Box::pin(String::from("Hello"));
 let as_ref = pinned.as_ref().say_hi();
}

trait SayHi: fmt::Debug {
 fn say_hi(self: Pin<&Self>) {
     println!("Hi from {:?}", self)
 }
}

impl<T> SayHi for Box<T> where T: Debug{}
GitHub

Learning Rust step-by-step. Contribute to instrumentisto/rust-incubator development by creating an account on GitHub.

night robin
#

You've correctly constructed a pinned boxed string (which is a unique pointer to an immovable string on the heap).
You're also correctly calling .say_hi() on the underlying string (albeit through a reference).
Try using a more generic implementation.

#

spoilers:
||```rs
impl<T: Debug> SayHi for T {}

#

Hope this helps 🙂

#

pinning is confusing sometimes XD

pure ravine
pure ravine
#

Lets assume I even defined SayHi for Box<T> trait to work specifically with values that pinned on the heap, but Pin<&T> does not guarantee that value behind &T is on heap, or am I wrong ?

nocturne pendant
nocturne pendant
# pure ravine Lets assume I even defined SayHi for Box<T> trait to work specifically with valu...

a value doesn't have to be on the heap to be pinned. Pin is just a way to promise that a value will not be moved until it is dropped, but moving it to the heap isn't the only way to do that. for example, the pin! macro pins a value on the stack; the way it does that is that the macro takes ownership of the value and returns a Pin<&mut T> reference type, so you don't have direct access to the original owned value and you're no longer able to move it until it's dropped at the end of the scope

pure ravine
#

yeah, it is the source of my confusion, Box::pin.as_ref(), skips Box part but I want to know where pinned part is allocated(

meager flax
#

Specifically, Box::pin(x) is shorthand for Box::into_pin(Box::new(x))

#

Which is a safe wrapper for Pin::new_unchecked(Box::new(x))

pure ravine
#

wait is
Box::into_pin(Box::new(x)) is the same as
Pin::new(Box::new(x)) ?

#

because all my thoughts was that Box::pin is equals to Pin::new(Box::new(x))

#

nvm let me read answers carefully

meager flax
#

However, Pin::new requires the type of x to be Unpin, whereas Box::pin has no such requirement

#

(it's not actually needed, since the API of Pin<Box<T>> never lets you move the value)

#

The real equivalence is that Box::pin(x) is a safe version of unsafe { Pin::new_unchecked(Box::new(x)) }

pure ravine
#

ok let me back to initial question, as far as I understood semantic of Pin::as_ref implies that it will return Pin object which contains derefed value, since deref of box will return &T, then Pin will be Pin<&T> right?

#

but Pin<T> was created with Box<T>, so in my head Pin type is Pin<Box<T>>, so how can i get reference (Pin<&Box<T>>)

meager flax
meager flax
#

This type would actually mean something different

#

Pin<&Box<T>> would mean that the box is pinned. Not its contents. The box itself.

pure ravine
#

got you

meager flax
#

Which, since Box<T>: Unpin for all T, is very useless. It does also mean you actually can make that type, via Pin::new(&boxed_value)

unreal lily
#

the syntax of Pin is Pin<Ptr<T>>, where T is pinned through Ptr

#

so Pin<&mut T> pins T, Pin<Box<T>> pins T, etc

#

Pin<Vec<T>> pins [T] btw

#

never thought about it but it makes perfect sense

#

wow, that makes me understand Deref so much better

pure ravine
#

got you, so I will back once more to my initial question. I cannot have SayHi for Box<T> without implementation of SayHi for T.

there is no way to get from Pin Pin<&Box<T>>, to do this I need to pin reference but not the value, right ?

trait SayHi: fmt::Debug {
fn say_hi(self: Pin<&Self>) {
println!("Hi from {:?}", self)
}
}

unreal lily
#

to get from Pin Pin<&Box<T>>
?

#

Box<T> is UnPin for all T

#

a Box cannot be pinned

meager flax
#

Which means you can call get or into_inner

meager flax
unreal lily
#

therefore Pin<Ptr<Box<T>>> is pretty much equivalent to a Ptr<Box<T>>

unreal lily
#

Rc is simillarly Unpin

pure ravine
unreal lily
#

||as is String and &[u8]||

#

||Vec is not Unpin for all T||

pure ravine
#

dont spoil

unreal lily
#

mb

unreal lily