-
Notifications
You must be signed in to change notification settings - Fork 13.4k
impl Unpin for Pin #49621
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
impl Unpin for Pin #49621
Conversation
No, I could add that as well if you want. |
I thought we'd maybe wait a bit and at least make sure we have consensus on the guarantees provided by Once we are fine with that, we probably want instances for |
I definitely agree with that in general. For the specific case of Maybe one way to state it is: having an instance of Also, deciding whether this implementation is sound or not (before deciding for other types) is going to greatly affect those of us experimenting with As I briefly mentioned in the tracking issue this is important for ergonomics. Similar to most object safe traits (presuming that trait Foo {
fn foo(self: Pin<Self>);
} then you want to provide an implementation for references to the trait, currently that requires unsafe code to perform the re-borrow (which, if `Pin: !Unpin is presumably unsound), but as I said above I believe that re-borrow to be guaranteed sound so it should be possible to do it with just safe code: impl<'a, T: Foo + ?Sized + 'a> Foo for Pin<'a, T> {
fn foo(mut self: Pin<Self>) {
<T as Foo>::foo(Pin::borrow(unsafe { Pin::get_mut(&mut self) }))
// <T as Foo>::foo(Pin::borrow(&mut *self))
}
} which would then allow functions to take trait objects: fn bar(mut foo: Pin<Foo>) {
Pin::borrow(&mut foo).foo()
} and waaaay in the future if re-borrowing is formalised and made something that custom types can implement (or sooner if re-borrowing of impl<'a, T: Foo + ?Sized + 'a> Foo for Pin<'a, T> {
fn foo(self: Pin<Self>) {
<T as Foo>::foo(*self)
}
}
fn bar(foo: Pin<Foo>) {
foo.foo()
} I realise that arguing from how |
I do not see any fundamental reason why we should not be able to declare that However, I have to agree insofar as I cannot think if any way in which making Concerning your use-case for |
You're right, that use-case does not actually need the forwarding implementation (far too many re-revisions of my examples made that disappear 🙁). There are definitely use-cases that require it though. Reading the API guideline on taking fn bar<F: Foo>(foo: F) {
stack_pinned(foo, |mut foo: Pin<F>| { // When invoked from `baz2` this is `Pin<Pin<baz::F>>`
Pin::borrow(&mut foo).foo();
});
}
fn baz1<F: Foo>(foo: F) {
bar(foo);
bar(foo); // Error: use of moved value
}
fn baz2<F: Foo>(foo: F) {
stack_pinned(foo, |mut foo: Pin<F>| {
bar(Pin::borrow(&mut foo));
bar(Pin::borrow(&mut foo)); // just `bar(foo);` with re-borrowing support
}
}
Writing this out made me realise another important reason for fn bar<F: Foo + Unpin>(mut foo: F) {
Pin::new(&mut foo).foo(); // just `foo.foo()` with `&pin` coercion I think...
}
fn baz<F: Foo>(foo: F) {
stack_pinned(foo, |mut foo: Pin<F>| {
bar(Pin::borrow(&mut foo));
}
} EDIT: Fixed some |
Interesting, I was not aware of this particular API trick. There seems to be a confusion between
This is neat. I somehow feel like you're cheating here because you seem to get a free generalization from a function that requires I guess the reason this works is that If I phrase this in terms of the formalism I started to develop, the question is: What is the pinned typestate invariant for
I somehow though that would make |
I believe (based on my sloppy informal reasoning) that all the smart pointers in libstd can implement |
For now I agree for |
Sorry, I originally had the two examples from that post in one, missed renaming the function in the first from |
@Nemo157 can you add PinBox to this PR? then I'll r+ :D |
bbc20bc
to
a29d4d9
Compare
@bors r+ |
📌 Commit a29d4d9 has been approved by |
r? @withoutboats