X-Git-Url: https://git.ralfj.de/web.git/blobdiff_plain/9131d1a0288847311e6d15fb8c0cda54d6815d7f..2c1c756ec793faa5df5a1dd7abfc3f5c92f1f924:/personal/_posts/2018-04-05-a-formal-look-at-pinning.md?ds=sidebyside diff --git a/personal/_posts/2018-04-05-a-formal-look-at-pinning.md b/personal/_posts/2018-04-05-a-formal-look-at-pinning.md index edaf6c6..5e51e7c 100644 --- a/personal/_posts/2018-04-05-a-formal-look-at-pinning.md +++ b/personal/_posts/2018-04-05-a-formal-look-at-pinning.md @@ -34,7 +34,7 @@ The short version is that I view Rust types with private invariants as not havin You may be wondering why sharing is a separate typestate here; shouldn't that just be read-only access to a `T` that someone else owns? However, that clearly doesn't work for `&Cell`; to explain types with interior mutability we *need* sharing as a separate state. I explained this in more detail in the previous post, but as a quick example consider that, if you fully own a `RefCell`, the first field (storing the current count of readers/writers) has no special meaning whatsoever. -This is witnessed by [`RefCell::get_mut`](https://doc.rust-lang.org/beta/std/cell/struct.RefCell.html#method.get_mut) ignoring that field. +This is witnessed by [`RefCell::get_mut`](https://doc.rust-lang.org/stable/std/cell/struct.RefCell.html#method.get_mut) ignoring that field. In fact, it would be sound to add a `RefCell::reset(&mut self)` that just resets this field to `0`. ## Pinning @@ -44,7 +44,7 @@ The core piece of the pinning API is a new reference type `Pin<'a, T>` that guar Crucially, **pinning does not provide immovable types**! Data is only pinned after a `Pin` pointing to it has been created; it can be moved freely before that happens. -The [corresponding RFC](https://github.com/rust-lang/rfcs/blob/master/text/2349-pin.md) explains the entirey new API surface in quite some detail: [`Pin`](https://doc.rust-lang.org/nightly/std/mem/struct.Pin.html), [`PinBox`](https://doc.rust-lang.org/nightly/std/boxed/struct.PinBox.html) and the [`Unpin`](https://doc.rust-lang.org/nightly/std/marker/trait.Unpin.html) marker trait. +The [corresponding RFC](https://github.com/rust-lang/rfcs/blob/master/text/2349-pin.md) explains the entirey new API surface in quite some detail: [`Pin`](https://doc.rust-lang.org/1.27.0/std/mem/struct.Pin.html), [`PinBox`](https://doc.rust-lang.org/1.27.0/std/boxed/struct.PinBox.html) and the [`Unpin`](https://doc.rust-lang.org/1.27.0/std/marker/trait.Unpin.html) marker trait. I will not repeat that here but only show one example of how to use `Pin` references and exploit their guarantees: {% highlight rust %} #![feature(pin, arbitrary_self_types, optin_builtin_traits)] @@ -68,11 +68,11 @@ impl SelfReferential { fn init(mut self: Pin) { let this : &mut SelfReferential = unsafe { Pin::get_mut(&mut self) }; // Set up self_ref to point to this.data. - this.self_ref = &mut this.data as *const i32; + this.self_ref = &this.data as *const i32; } - fn read_ref(mut self: Pin) -> Option { - let this : &mut SelfReferential = unsafe { Pin::get_mut(&mut self) }; + fn read_ref(self: Pin) -> Option { + let this : &SelfReferential = &*self; // Dereference self_ref if it is non-NULL. if this.self_ref == ptr::null() { None