Hm, good point. As far as I can tell, all of these trait impls also have to be sufficiently well-behaved.
But this means our docs for Pin::new_unchecked
are incomplete! They should list all the trait impls that users have to promise are "well-behaved" (whatever that means). So in particular, given the derive
, we should explicitly list Clone, Hash, PartialEq, Eq, PartialOrd, Ord
. Your proposal doesn't free users from having to check all of them, it just changes when they have to check it and how this is expressed in the type system.
Clone
is the only one here that returns a new Pin
... but also the others get access to &Ptr<T>
when really everybody should only be able to access Pin<Ptr<T>>
. I cannot come up with a solid correctness argument here, but I also cannot come up with a counterexample.
I don't understand the question. What if the way we implement Vec
is unsound? Then we have a bug. But the bug cannot involve reasoning about surprising trait impls, because there is nothing in the correctness argument that would interact with the trait system in interesting ways.
The marker traits make arguing for correctness much simpler by excluding a huge and subtle subsystem of Rust entirely from the discussion. Of course, it doesn't make bugs impossible. Nobody would say that...
Part of why this feels so different for me is likely that we actually have a framework for formally verifying things like Vec
or the old separate-ptr-type pinning API. We do not have a formal framework for verifying anything that interacts with the trait system in interesting ways, like Pin
. So there is a huge cliff here in terms of what is formally understood and what not, and for me, that makes a big difference. Also empirically, I feel this bug shows that there is a complexity cliff here. This is not to say that it is impossible to get the complex thing right, just that is is harder.
Now I am even more confused. I agree that stating abstractly the requirements is hard, but adding the unsafe marker traits would make it much simpler! Then we can concretely refer to them in all Pin
methods that need to rely on anything.
This is exactly why I am proposing the unsafe marker traits -- they make these requirements basically "fall out" of a solid correctness argument for Pin
.
The fact that not even you can state the abstract correctness argument is a big warning bell IMO. I thought you had a very concrete idea for those in your mind and we only got a small part of that out for the new_unchecked
docs. Had I known that I would have opposed stabilization -- we shouldn't stabilize APIs of which we cannot state the soundness requirement.
De facto, right now Pin
for user-defined ptr types is "unstable" in the sense that the contract for that is in flux and might change -- and there likely exist multiple, mutually incompatible interpretations, such that code relying on one combined with code relying on the other is unsound. We have seen that before (Leakpocalypse is an instance of this).
Interesting. On first sight, this is a good argument for @withoutboats' proposal to rule out certain DerefMut
impls.