Skip to content

Commit 324e275

Browse files
author
boats
committed
Pin/Move/etc RFC.
1 parent 166f02d commit 324e275

File tree

1 file changed

+74
-8
lines changed

1 file changed

+74
-8
lines changed

text/0000-pin_and_move.md

Lines changed: 74 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,17 @@ which cannot be safely moved around.
1212
# Motivation
1313
[motivation]: #motivation
1414

15-
Why are we doing this? What use cases does it support? What is the expected outcome?
15+
A longstanding problem for Rust has been dealing with types that should not be
16+
moved. A common motivation for this is when a struct contains a pointer into
17+
its own representation - moving that struct would invalidate that pointer. This
18+
use case has become especially important recently with work on generators.
19+
Because generators essentially reify a stackframe into an object that can be
20+
manipulated in code, it is likely for idiomatic usage of a generator to result
21+
in such a self-referential type, if it is allowed.
22+
23+
This proposal adds an API to std which would allow you to guarantee that a
24+
particular value will never move again, enabling safe APIs that rely on
25+
self-references to exist.
1626

1727
# Explanation
1828
[explanation]: #explanation
@@ -296,18 +306,74 @@ separate feature flags, which can be stabilized in stages:
296306
# Drawbacks
297307
[drawbacks]: #drawbacks
298308
299-
Why should we *not* do this?
309+
This adds additional APIs to std, including several marker traits and an auto
310+
trait. Such additions should not be taken lightly, and only included if they
311+
are well-justified by the abstractions they express.
300312
301313
# Rationale and alternatives
302314
[alternatives]: #alternatives
303315
304-
- Why is this design the best in the space of possible designs?
305-
- What other designs have been considered and what is the rationale for not choosing them?
306-
- What is the impact of not doing this?
316+
## Comparison to `?Move`
317+
318+
One previous proposal was to add a built-in `Move` trait, similar to `Sized`. A
319+
type that did not implement `Move` could not be moved after it had been
320+
referenced.
321+
322+
This solution had some problems. First, the `?Move` bound ended up "infecting"
323+
many different APIs where it wasn't relevant, and introduced a breaking change
324+
in several cases where the API bound changed in a non-backwards compatible way.
325+
326+
In a certain sense, this proposal is a much more narrowly scoped version of
327+
`?Move`. With `?Move`, *any* reference could act as the "Pin" reference does
328+
here. However, because of this flexibility, the negative consequences of having
329+
a type that can't be moved had a much broader impact.
330+
331+
Instead, we require APIs to opt into supporting immovability (a niche case) by
332+
operating with the `Pin` type, avoiding "infecting" the basic reference type
333+
with concerns around immovable types.
334+
335+
## Comparison to using `unsafe` APIs
336+
337+
Another alternative we've considered was to just have the APIs which require
338+
immovability be `unsafe`. It would be up to the users of these APIs to review
339+
and guarantee that they never moved the self-referential types. For example,
340+
generator would look like this:
341+
342+
```rust
343+
trait Generator {
344+
type Yield;
345+
type Return;
346+
347+
unsafe fn resume(&mut self) -> CoResult<Self::Yield, Self::Return>;
348+
}
349+
```
350+
351+
This would require no extensions to the standard library, but would place the
352+
burden on every user who wants to call resume to guarantee (at the risk of
353+
memory insafety) that their types were not moved, or that they were moveable.
354+
This seemed like a worse trade off than adding these APIs.
355+
356+
## Relationship to owning-ref & rental
357+
358+
Existing crates like owning-ref and rental make some use of "self-referential"
359+
types. Unlike the generators this RFC is designed to support, their references
360+
always point into the heap - making it acceptable to move their types around.
361+
362+
However, some of this infrastructure is still useful to those crates. In
363+
particular, the stable deref hierarchy is related to the existing hierarchy in
364+
the stable_deref crate, which those other crates depend on. By uplifting those
365+
markers into the standard library, we create a shared, endorsed, and guaranteed
366+
set of markers for the invariants those libraries care about.
367+
368+
In order to be implemented in safe code, those library need additional features
369+
connecting to "existential" or "generative" lifetimes. These language changes
370+
are out of scope for this RFC.
307371
308372
# Unresolved questions
309373
[unresolved]: #unresolved-questions
310374
311-
- What parts of the design do you expect to resolve through the RFC process before this gets merged?
312-
- What parts of the design do you expect to resolve through the implementation of this feature before stabilization?
313-
- What related issues do you consider out of scope for this RFC that could be addressed in the future independently of the solution that comes out of this RFC?
375+
The names used in this RFC are all entirely up for debate. Some of the items
376+
introduced (especially the `Move` trait) have evolved away from their original
377+
design, making the names a bit of a misnomer (`Move` really means that its safe
378+
to convert between `Pin<T>` and `&mut T`, for example). We want to make sure we
379+
have adequate names before stabilizing these APIs.

0 commit comments

Comments
 (0)