{"action":"created","issue":{"url":"https://api.github.com/repos/rust-lang/rust/issues/55766","repository_url":"https://api.github.com/repos/rust-lang/rust","labels_url":"https://api.github.com/repos/rust-lang/rust/issues/55766/labels{/name}","comments_url":"https://api.github.com/repos/rust-lang/rust/issues/55766/comments","events_url":"https://api.github.com/repos/rust-lang/rust/issues/55766/events","html_url":"https://github.com/rust-lang/rust/issues/55766","id":378417538,"node_id":"MDU6SXNzdWUzNzg0MTc1Mzg=","number":55766,"title":"[Stabilization] Pin APIs","user":{"login":"withoutboats","id":9063376,"node_id":"MDQ6VXNlcjkwNjMzNzY=","avatar_url":"https://avatars2.githubusercontent.com/u/9063376?v=4","gravatar_id":"","url":"https://api.github.com/users/withoutboats","html_url":"https://github.com/withoutboats","followers_url":"https://api.github.com/users/withoutboats/followers","following_url":"https://api.github.com/users/withoutboats/following{/other_user}","gists_url":"https://api.github.com/users/withoutboats/gists{/gist_id}","starred_url":"https://api.github.com/users/withoutboats/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/withoutboats/subscriptions","organizations_url":"https://api.github.com/users/withoutboats/orgs","repos_url":"https://api.github.com/users/withoutboats/repos","events_url":"https://api.github.com/users/withoutboats/events{/privacy}","received_events_url":"https://api.github.com/users/withoutboats/received_events","type":"User","site_admin":false},"labels":[{"id":211668062,"node_id":"MDU6TGFiZWwyMTE2NjgwNjI=","url":"https://api.github.com/repos/rust-lang/rust/labels/T-libs","name":"T-libs","color":"bfd4f2","default":false},{"id":919710011,"node_id":"MDU6TGFiZWw5MTk3MTAwMTE=","url":"https://api.github.com/repos/rust-lang/rust/labels/disposition-merge","name":"disposition-merge","color":"008800","default":false},{"id":638321554,"node_id":"MDU6TGFiZWw2MzgzMjE1NTQ=","url":"https://api.github.com/repos/rust-lang/rust/labels/proposed-final-comment-period","name":"proposed-final-comment-period","color":"ededed","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":53,"created_at":"2018-11-07T18:39:12Z","updated_at":"2018-11-14T20:07:34Z","closed_at":null,"author_association":"CONTRIBUTOR","body":"@rfcbot fcp merge\r\nFeature name: `pin`\r\nStabilization target: 1.32.0\r\nTracking issue: #49150\r\nRelated RFCs: rust-lang/rfcs#2349\r\n\r\nThis is a proposal to stabilize the `pin` library feature, making the \"pinning\"\r\nAPIs for manipulating pinned memory usable on stable.\r\n\r\n(I've tried to write this proposal as a comprehensive \"stabilization report.\")\r\n\r\n## Stabilized feature or APIs\r\n\r\n### `[std|core]::pin::Pin`\r\n\r\nThis stabilizes the `Pin` type in the `pin` submodule of `std`/`core`. `Pin` is\r\na fundamental, transparent wrapper around a generic type `P`, which is intended\r\nto be a pointer type (for example, `Pin<&mut T>` and `Pin<Box<T>>` are both\r\nvalid, intended constructs). The `Pin` wrapper modifies the pointer to \"pin\"\r\nthe memory it refers to in place, preventing the user from moving objects out\r\nof that memory.\r\n\r\nThe usual way to use the `Pin` type is to construct a pinned variant of some\r\nkind of owning pointer (`Box`, `Rc`, etc). The std library owning pointers all\r\nprovide a `pinned` constructor which returns this. Then, to manipulate the\r\nvalue inside, all of these pointers provide a way to degrade toward `Pin<&T>`\r\nand `Pin<&mut T>`. Pinned pointers can deref, giving you back `&T`, but cannot\r\nsafely mutably deref: this is only possible using the unsafe `get_mut`\r\nfunction.\r\n\r\nAs a result, anyone mutating data through a pin will be required to uphold the\r\ninvariant that they never move out of that data. This allows other code to\r\nsafely assume that the data is never moved, allowing it to contain (for\r\nexample) self references.\r\n\r\nThe `Pin` type will have these stabilized APIs:\r\n\r\n#### `impl<P> Pin<P> where P: Deref, P::Target: Unpin`\r\n\r\n* **`fn new(pointer: P) -> Pin<P>`**\r\n\r\n#### `impl<P> Pin<P> where P: Deref`\r\n\r\n* **`unsafe fn new_unchecked(pointer: P) -> Pin<P>`**\r\n* **`fn as_ref(&self) -> Pin<&P::Target>`**\r\n\r\n#### `impl<P> Pin<P> where P: DerefMut`\r\n\r\n* **`fn as_mut(&mut self) -> Pin<&mut P::Target>`**\r\n* **`fn set(&mut self, P::Target);`**\r\n\r\n#### `impl<'a, T: ?Sized> Pin<&'a T>`\r\n\r\n* **`unsafe fn map_unchecked<U, F: FnOnce(&T) -> &U>(self, f: F) -> Pin<&'a U>`**\r\n* **`fn get_ref(self) -> &'a T`**\r\n\r\n#### `impl<'a, T: ?Sized> Pin<&'a mut T>`\r\n\r\n* **`fn into_ref(self) -> Pin<&'a T>`**\r\n* **`unsafe fn get_unchecked_mut(self) -> &'a mut T`**\r\n* **`unsafe fn map_unchecked_mut<U, F: FnOnce(&mut T) -> &mut U>(self, f: F) -> Pin<&'a mut U>`**\r\n\r\n#### `impl<'a, T: ?Sized> Pin<&'a mut T> where T: Unpin`\r\n\r\n* **`fn get_mut(self) -> &'a mut T`**\r\n\r\n#### Trait impls\r\n\r\nMost of the trait impls on `Pin` are fairly rote, these two are important to\r\nits operation:\r\n\r\n* **`impl<P: Deref> Deref for Pin<P> { type Target = P::Target }`**\r\n* **`impl<P: DerefMut> DerefMut for Pin<P> where P::Target: Unpin { }`**\r\n\r\n### `std::marker::Unpin`\r\n\r\nUnpin is a safe auto trait which opts out of the guarantees of pinning. If the\r\ntarget of a pinned pointer implements `Unpin`, it is safe to mutably\r\ndereference to it. `Unpin` types do not have any guarantees that they will not\r\nbe moved out of a `Pin`.\r\n\r\nThis makes it as ergonomic to deal with a pinned reference to something that\r\ndoes not contain self-references as it would be to deal with a non-pinned\r\nreference. The guarantees of `Pin` only matter for special case types like\r\nself-referential structures: those types do not implement `Unpin`, so they have\r\nthe restrictions of the `Pin` type.\r\n\r\nNotable implementations of `Unpin` in std:\r\n\r\n* **`impl<'a, T: ?Sized> Unpin for &'a T`**\r\n* **`impl<'a, T: ?Sized> Unpin for &'a mut T`**\r\n* **`impl<T: ?Sized> Unpin for Box<T>`**\r\n* **`impl<T: ?Sized> Unpin for Rc<T>`**\r\n* **`impl<T: ?Sized> Unpin for Arc<T>`**\r\n\r\nThese codify the notion that pinnedness is not transitive across pointers. That\r\nis, a `Pin<&T>` *only* pins the actual memory block represented by `T` in a\r\nplace. Users have occassionally been confused by this and expected that a type\r\nlike `Pin<&mut Box<T>>` pins the data of `T` in place, but it only pins the\r\nmemory the pinned reference actually refers to: in this case, the `Box`'s\r\nrepresentation, which a pointer into the heap.\r\n\r\n### `std::marker::Pinned`\r\n\r\nThe `Pinned` type is a ZST which does not implement `Unpin`; it allows you to\r\nsupress the auto-implementation of `Unpin` on stable, where `!Unpin` impls\r\nwould not be stable yet.\r\n\r\n### Smart pointer constructors\r\n\r\nConstructors are added to the std smart pointers to create pinned references:\r\n\r\n* **`Box::pinned(data: T) -> Pin<Box<T>>`**\r\n* **`Rc::pinned(data: T) -> Pin<Rc<T>>`**\r\n* **`Arc::pinned(data: T) -> Pin<Arc<T>>`**\r\n\r\n### Notes on pinning & safety\r\n\r\nOver the last 9 months the pinning APIs have gone through several iterations as\r\nwe have investigated their expressive power and also the soundness of their\r\nguarantees. I would now say confidently that the pinning APIs stabilized here\r\nare sound and close enough to the local maxima in ergonomics and\r\nexpressiveness; that is, ready for stabilization.\r\n\r\nOne of the trickier issues of pinning is determining when it is safe to perform\r\na **pin projection**: that is, to go from a `Pin<P<Target = Foo>>` to a\r\n`Pin<P<Target = Bar>>`, where `Bar` is a field of `Foo`. Fortunately, we have\r\nbeen able to codify a set of rules which can help users determine if such a\r\nprojection is safe:\r\n\r\n1. It is only safe to pin project if `(Foo: Unpin) implies (Bar: Unpin)`: that\r\nis, if it is never the case that `Foo` (the containing type) is `Unpin` while\r\n`Bar` (the projected type) is not `Unpin`.\r\n2. It is only safe if `Bar` is never moved during the destruction of `Foo`,\r\nmeaning that either `Foo` has no destructor, or the destructor is carefully\r\nchecked to make sure that it never moves out of the field being projected to.\r\n3. It is only safe if `Foo` (the containing type) is not `repr(packed)`,\r\nbecause this causes fields to be moved around to realign them.\r\n\r\nAdditionally, the std APIs provide no safe way to pin objects to the stack.\r\nThis is because there is no way to implement that safely using a function API.\r\nHowever, users can unsafely pin things to the stack by guaranteeing that they\r\nnever move the object again after creating the pinned reference.\r\n\r\nThe `pin-utils` crate on crates.io contains macros to assist with both stack\r\npinning and pin projection. The stack pinning macro safely pins objects to the\r\nstack using a trick involving shadowing, whereas a macro for projection exists\r\nwhich is unsafe, but avoids you having to write the projection boilerplate in\r\nwhich you could possibly introduce other incorrect unsafe code.\r\n\r\n## Implementation changes prior to stabilization\r\n\r\n- [ ] Export `Unpin` from the prelude, remove `pin::Unpin` re-export\r\n\r\nAs a general rule, we don't re-export things from multiple places in std unless\r\none is a supermodule of the real definition (e.g. shortening\r\n`std::collections::hash_map::HashMap` to `std::collections::HashMap`). For this\r\nreason, the re-export of `std::marker::Unpin` from `std::pin::Unpin` is out of\r\nplace.\r\n\r\nAt the same time, other important marker traits like Send and Sync are included\r\nin the prelude. So instead of re-exporting `Unpin` from the `pin` module, by\r\nputting in the prelude we make it unnecessary to import `std::marker::Unpin`,\r\nthe same reason it was put into `pin`.\r\n\r\n- [ ] Change associated functions to methods\r\n\r\nCurrently, a lot of the associated function of `Pin` do not use method syntax.\r\nIn theory, this is to avoid conflicting with derefable inner methods. However,\r\nthis rule has not been applied consistently, and in our experience has mostly\r\njust made things more inconvenient. Pinned pointers only implement immutable\r\nderef, not mutable deref or deref by value, limiting the ability to deref\r\nanyway. Moreover, many of these names are fairly unique (e.g. `map_unchecked`)\r\nand unlikely to conflict.\r\n\r\nInstead, we prefer to give the `Pin` methods their due precedence; users who\r\nneed to access an interior method always can using UFCS, just as they would be\r\nrequired to to access the Pin methods if we did not use method syntax.\r\n\r\n- [ ] Rename `get_mut_unchecked` to `get_unchecked_mut`\r\n\r\nThe current ordering is inconsistent with other uses in the standard library.\r\n\r\n- [ ] Remove `impl<P> Unpin for Pin<P>`\r\n\r\nThis impl is not justified by our standard justification for unpin impls: there is no pointer direction between `Pin<P>` and `P`. Its usefulness is covered by the impls for pointers themselves.\r\n\r\n[This futures impl](https://github.com/rust-lang/rust/blob/master/src/libcore/future/future.rs#L120) will need to change to add a `P: Unpin` bound.\r\n\r\n- [ ] Mark `Pin` as `repr(transparent)`\r\n\r\nPin should be a transparent wrapper around the pointer inside of it, with the same representation.\r\n\r\n## Connected features and larger milestones\r\n\r\nThe pin APIs are important to safely manipulating sections of memory which can\r\nbe guaranteed not to be moved out. If the objects in that memory do not\r\nimplement `Unpin`, their address will never change. This is necessary for\r\ncreating self-referential generators and asynchronous functions. As a result,\r\nthe `Pin` type appears in the standard library `future` APIs and will soon\r\nappear in the APIs for generators as well (#55704).\r\n\r\nStabilizing the `Pin` type and its APIs is a necessary precursor to stabilizing\r\nthe `Future` APIs, which is itself a necessary precursor to stabilizing the\r\n`async/await` syntax and moving the entire `futures 0.3` async IO ecosystem\r\nonto stable Rust.\r\n\r\ncc @cramertj @RalfJung"},"comment":{"url":"https://api.github.com/repos/rust-lang/rust/issues/comments/438800531","html_url":"https://github.com/rust-lang/rust/issues/55766#issuecomment-438800531","issue_url":"https://api.github.com/repos/rust-lang/rust/issues/55766","id":438800531,"node_id":"MDEyOklzc3VlQ29tbWVudDQzODgwMDUzMQ==","user":{"login":"tikue","id":2915777,"node_id":"MDQ6VXNlcjI5MTU3Nzc=","avatar_url":"https://avatars1.githubusercontent.com/u/2915777?v=4","gravatar_id":"","url":"https://api.github.com/users/tikue","html_url":"https://github.com/tikue","followers_url":"https://api.github.com/users/tikue/followers","following_url":"https://api.github.com/users/tikue/following{/other_user}","gists_url":"https://api.github.com/users/tikue/gists{/gist_id}","starred_url":"https://api.github.com/users/tikue/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tikue/subscriptions","organizations_url":"https://api.github.com/users/tikue/orgs","repos_url":"https://api.github.com/users/tikue/repos","events_url":"https://api.github.com/users/tikue/events{/privacy}","received_events_url":"https://api.github.com/users/tikue/received_events","type":"User","site_admin":false},"created_at":"2018-11-14T20:07:34Z","updated_at":"2018-11-14T20:07:34Z","author_association":"CONTRIBUTOR","body":"@jonhoo I think the main reason I prefer the opposite is because `Pinned` prevents a trait from being implemented, so that is, in the plainest sense to me, the true negative."}}
{"actor":{"display_login":"tikue"}}