1// Copyright 2017 Robert Grosse
2
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9/*!
10This module defines an unsafe marker trait, StableDeref, for container types that deref to a fixed address which is valid even when the containing type is moved. For example, Box, Vec, Rc, Arc and String implement this trait. Additionally, it defines CloneStableDeref for types like Rc where clones deref to the same address.
11
12It is intended to be used by crates such as [owning_ref](https://crates.io/crates/owning_ref) and [rental](https://crates.io/crates/rental), as well as library authors who wish to make their code interoperable with such crates. For example, if you write a custom Vec type, you can implement StableDeref, and then users will be able to use your custom type together with owning_ref and rental.
13
14no_std support can be enabled by disabling default features (specifically "std"). In this case, the trait will not be implemented for the std types mentioned above, but you can still use it for your own types.
15*/
16
17#![cfg_attr(not(feature = "std"), no_std)]
18
19#[cfg(feature = "std")]
20extern crate core;
21
22#[cfg(feature = "alloc")]
23extern crate alloc;
24
25use core::ops::Deref;
26
27
28/**
29An unsafe marker trait for types that deref to a stable address, even when moved. For example, this is implemented by Box, Vec, Rc, Arc and String, among others. Even when a Box is moved, the underlying storage remains at a fixed location.
30
31More specifically, implementors must ensure that the result of calling deref() is valid for the lifetime of the object, not just the lifetime of the borrow, and that the deref is valid even if the object is moved. Also, it must be valid even after invoking arbitrary &self methods or doing anything transitively accessible from &Self. If Self also implements DerefMut, the same restrictions apply to deref_mut() and it must remain valid if anything transitively accessible from the result of deref_mut() is mutated/called. Additionally, multiple calls to deref, (and deref_mut if implemented) must return the same address. No requirements are placed on &mut self methods other than deref_mut() and drop(), if applicable.
32
33Basically, it must be valid to convert the result of deref() to a pointer, and later dereference that pointer, as long as the original object is still live, even if it has been moved or &self methods have been called on it. If DerefMut is also implemented, it must be valid to get pointers from deref() and deref_mut() and dereference them while the object is live, as long as you don't simultaneously dereference both of them.
34
35Additionally, Deref and DerefMut implementations must not panic, but users of the trait are not allowed to rely on this fact (so that this restriction can be removed later without breaking backwards compatibility, should the need arise).
36
37Here are some examples to help illustrate the requirements for implementing this trait:
38
39```
40# use std::ops::Deref;
41struct Foo(u8);
42impl Deref for Foo {
43 type Target = u8;
44 fn deref(&self) -> &Self::Target { &self.0 }
45}
46```
47
48Foo cannot implement StableDeref because the int will move when Foo is moved, invalidating the result of deref().
49
50```
51# use std::ops::Deref;
52struct Foo(Box<u8>);
53impl Deref for Foo {
54 type Target = u8;
55 fn deref(&self) -> &Self::Target { &*self.0 }
56}
57```
58
59Foo can safely implement StableDeref, due to the use of Box.
60
61
62```
63# use std::ops::Deref;
64# use std::ops::DerefMut;
65# use std::rc::Rc;
66#[derive(Clone)]
67struct Foo(Rc<u8>);
68impl Deref for Foo {
69 type Target = u8;
70 fn deref(&self) -> &Self::Target { &*self.0 }
71}
72impl DerefMut for Foo {
73 fn deref_mut(&mut self) -> &mut Self::Target { Rc::make_mut(&mut self.0) }
74}
75```
76
77This is a simple implementation of copy-on-write: Foo's deref_mut will copy the underlying int if it is not uniquely owned, ensuring unique access at the point where deref_mut() returns. However, Foo cannot implement StableDeref because calling deref_mut(), followed by clone().deref() will result in mutable and immutable references to the same location. Note that if the DerefMut implementation were removed, Foo could safely implement StableDeref. Likewise, if the Clone implementation were removed, it would be safe to implement StableDeref, although Foo would not be very useful in that case, (without clones, the rc will always be uniquely owned).
78
79
80```
81# use std::ops::Deref;
82struct Foo;
83impl Deref for Foo {
84 type Target = str;
85 fn deref(&self) -> &Self::Target { &"Hello" }
86}
87```
88Foo can safely implement StableDeref. It doesn't own the data being derefed, but the data is gaurenteed to live long enough, due to it being 'static.
89
90```
91# use std::ops::Deref;
92# use std::cell::Cell;
93struct Foo(Cell<bool>);
94impl Deref for Foo {
95 type Target = str;
96 fn deref(&self) -> &Self::Target {
97 let b = self.0.get();
98 self.0.set(!b);
99 if b { &"Hello" } else { &"World" }
100 }
101}
102```
103Foo cannot safely implement StableDeref, even though every possible result of deref lives long enough. In order to safely implement StableAddress, multiple calls to deref must return the same result.
104
105```
106# use std::ops::Deref;
107# use std::ops::DerefMut;
108struct Foo(Box<(u8, u8)>);
109impl Deref for Foo {
110 type Target = u8;
111 fn deref(&self) -> &Self::Target { &self.0.deref().0 }
112}
113impl DerefMut for Foo {
114 fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0.deref_mut().1 }
115}
116```
117
118Foo cannot implement StableDeref because deref and deref_mut return different addresses.
119
120
121*/
122pub unsafe trait StableDeref: Deref {}
123
124/**
125An unsafe marker trait for types where clones deref to the same address. This has all the requirements of StableDeref, and additionally requires that after calling clone(), both the old and new value deref to the same address. For example, Rc and Arc implement CloneStableDeref, but Box and Vec do not.
126
127Note that a single type should never implement both DerefMut and CloneStableDeref. If it did, this would let you get two mutable references to the same location, by cloning and then calling deref_mut() on both values.
128*/
129pub unsafe trait CloneStableDeref: StableDeref + Clone {}
130
131/////////////////////////////////////////////////////////////////////////////
132// std types integration
133/////////////////////////////////////////////////////////////////////////////
134
135#[cfg(feature = "alloc")]
136use alloc::boxed::Box;
137#[cfg(feature = "alloc")]
138use alloc::rc::Rc;
139#[cfg(feature = "alloc")]
140use alloc::sync::Arc;
141#[cfg(feature = "alloc")]
142use alloc::vec::Vec;
143#[cfg(feature = "alloc")]
144use alloc::string::String;
145
146#[cfg(feature = "std")]
147use std::ffi::{CString, OsString};
148#[cfg(feature = "std")]
149use std::path::PathBuf;
150#[cfg(feature = "std")]
151use std::sync::{MutexGuard, RwLockReadGuard, RwLockWriteGuard};
152
153use core::cell::{Ref, RefMut};
154
155
156#[cfg(feature = "alloc")]
157unsafe impl<T: ?Sized> StableDeref for Box<T> {}
158#[cfg(feature = "alloc")]
159unsafe impl<T> StableDeref for Vec<T> {}
160#[cfg(feature = "alloc")]
161unsafe impl StableDeref for String {}
162#[cfg(feature = "std")]
163unsafe impl StableDeref for CString {}
164#[cfg(feature = "std")]
165unsafe impl StableDeref for OsString {}
166#[cfg(feature = "std")]
167unsafe impl StableDeref for PathBuf {}
168
169#[cfg(feature = "alloc")]
170unsafe impl<T: ?Sized> StableDeref for Rc<T> {}
171#[cfg(feature = "alloc")]
172unsafe impl<T: ?Sized> CloneStableDeref for Rc<T> {}
173#[cfg(feature = "alloc")]
174unsafe impl<T: ?Sized> StableDeref for Arc<T> {}
175#[cfg(feature = "alloc")]
176unsafe impl<T: ?Sized> CloneStableDeref for Arc<T> {}
177
178unsafe impl<'a, T: ?Sized> StableDeref for Ref<'a, T> {}
179unsafe impl<'a, T: ?Sized> StableDeref for RefMut<'a, T> {}
180#[cfg(feature = "std")]
181unsafe impl<'a, T: ?Sized> StableDeref for MutexGuard<'a, T> {}
182#[cfg(feature = "std")]
183unsafe impl<'a, T: ?Sized> StableDeref for RwLockReadGuard<'a, T> {}
184#[cfg(feature = "std")]
185unsafe impl<'a, T: ?Sized> StableDeref for RwLockWriteGuard<'a, T> {}
186
187unsafe impl<'a, T: ?Sized> StableDeref for &'a T {}
188unsafe impl<'a, T: ?Sized> CloneStableDeref for &'a T {}
189unsafe impl<'a, T: ?Sized> StableDeref for &'a mut T {}
190