You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/vec-layout.md
+7-49Lines changed: 7 additions & 49 deletions
Original file line number
Diff line number
Diff line change
@@ -29,66 +29,24 @@ so we'd like to not use it if possible, though.
29
29
30
30
As a recap, Unique is a wrapper around a raw pointer that declares that:
31
31
32
-
* We are variant over `T`
32
+
* We are covariant over `T`
33
33
* We may own a value of type `T` (for drop check)
34
34
* We are Send/Sync if `T` is Send/Sync
35
35
* Our pointer is never null (so `Option<Vec<T>>` is null-pointer-optimized)
36
36
37
-
We can implement all of the above requirements except for the last
38
-
one in stable Rust:
37
+
We can implement all of the above requirements in stable Rust. To do this, instead of using `Unique<T>` we will use [`NonNull<T>`](https://doc.rust-lang.org/stable/std/ptr/struct.NonNull.html), another wrapper around a raw pointer, which gives us two of the above properties, namely it is covariant over `T` and is declared to never be null. By
38
+
adding a `PhantomData<T>` (for drop check) and implementing Send/Sync if `T` is, we then get the same results as if we had used `Unique<T>`:
39
39
40
40
```rust
41
-
usestd::marker::PhantomData;
42
-
usestd::ops::Deref;
43
-
usestd::mem;
44
-
45
-
structUnique<T> {
46
-
ptr:*constT, // *const for variance
47
-
_marker:PhantomData<T>, // For the drop checker
48
-
}
49
-
50
-
// Deriving Send and Sync is safe because we are the Unique owners
51
-
// of this data. It's like Unique<T> is "just" T.
52
-
unsafeimpl<T:Send> SendforUnique<T> {}
53
-
unsafeimpl<T:Sync> SyncforUnique<T> {}
54
-
55
-
impl<T> Unique<T> {
56
-
pubfnnew(ptr:*mutT) ->Self {
57
-
Unique { ptr:ptr, _marker:PhantomData }
58
-
}
59
-
60
-
pubfnas_ptr(&self) ->*mutT {
61
-
self.ptr as*mutT
62
-
}
63
-
}
64
-
65
-
# fnmain() {}
66
-
```
67
-
68
-
Unfortunately the mechanism for stating that your value is non-zero is
69
-
unstable and unlikely to be stabilized soon. As such we're just going to
70
-
take the hit and use std's Unique:
71
-
72
-
73
-
```rust
74
-
#![feature(ptr_internals)]
75
-
76
-
usestd::ptr::{Unique, self};
77
-
78
41
pubstructVec<T> {
79
-
ptr:Unique<T>,
42
+
ptr:NonNull<T>,
80
43
cap:usize,
81
44
len:usize,
45
+
_marker:PhantomData<T>,
82
46
}
83
47
84
-
# fnmain() {}
48
+
unsafeimpl<T:Send> SendforVec<T> {}
49
+
unsafeimpl<T:Sync> SyncforVec<T> {}
85
50
```
86
51
87
-
If you don't care about the null-pointer optimization, then you can use the
88
-
stable code. However we will be designing the rest of the code around enabling
89
-
this optimization. It should be noted that `Unique::new` is unsafe to call, because
90
-
putting `null` inside of it is Undefined Behavior. Our stable Unique doesn't
91
-
need `new` to be unsafe because it doesn't make any interesting guarantees about
0 commit comments