Skip to content

Commit 3ab52ff

Browse files
committed
Add support for destructuring unaligned pointers
1 parent f87f407 commit 3ab52ff

File tree

2 files changed

+171
-101
lines changed

2 files changed

+171
-101
lines changed

src/impls.rs

Lines changed: 87 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,73 @@
11
use {
2-
crate::{Aligned, AlignedMut, Destructure, Restructure, StructuralPinning},
2+
crate::{Destructure, Restructure, StructuralPinning},
33
::core::{
44
cell::{Cell, UnsafeCell},
55
mem::{ManuallyDrop, MaybeUninit},
66
pin::Pin,
77
},
88
};
99

10-
// Aligned<T>
10+
// *const T
1111

12-
impl<T: ?Sized> Destructure for Aligned<T> {
12+
// SAFETY: Destructuring `*const T` is safe if and only if destructuring `T` with the same pattern
13+
// is also safe.
14+
unsafe impl<T> Destructure for *const T {
1315
type Underlying = T;
16+
type Test = T;
1417

1518
fn as_mut_ptr(&mut self) -> *mut Self::Underlying {
16-
**self as *mut T
19+
*self as *mut T
1720
}
1821
}
1922

20-
unsafe impl<T: ?Sized, U: ?Sized> Restructure<&Aligned<T>> for U {
21-
type Restructured = Aligned<Self>;
23+
// SAFETY: `restructure` returns a valid `*const U` that upholds the same invariants as a mutably
24+
// borrowed subfield of some `T`.
25+
unsafe impl<T: ?Sized, U: ?Sized> Restructure<&*const T> for U {
26+
type Restructured = *const U;
2227

2328
unsafe fn restructure(ptr: *mut Self) -> Self::Restructured {
24-
// SAFETY: The caller has guaranteed that `ptr` is properly aligned.
25-
unsafe { Aligned::new_unchecked(ptr as *const Self) }
29+
ptr as *const Self
2630
}
2731
}
2832

29-
// AlignedMut<T>
33+
// *mut T
3034

31-
impl<T: ?Sized> Destructure for AlignedMut<T> {
35+
// SAFETY: Destructuring `*mut T` is safe if and only if destructuring `T` with the same pattern is
36+
// also safe.
37+
unsafe impl<T> Destructure for *mut T {
3238
type Underlying = T;
39+
type Test = T;
3340

3441
fn as_mut_ptr(&mut self) -> *mut Self::Underlying {
35-
**self
42+
*self
3643
}
3744
}
3845

39-
unsafe impl<T: ?Sized, U: ?Sized> Restructure<&AlignedMut<T>> for U {
40-
type Restructured = AlignedMut<Self>;
46+
// SAFETY: `restructure` returns a valid `*mut U` that upholds the same invariants as a mutably
47+
// borrowed subfield of some `T`.
48+
unsafe impl<T: ?Sized, U: ?Sized> Restructure<&*mut T> for U {
49+
type Restructured = *mut U;
4150

4251
unsafe fn restructure(ptr: *mut Self) -> Self::Restructured {
43-
// SAFETY: The caller has guaranteed that `ptr` is properly aligned.
44-
unsafe { AlignedMut::new_unchecked(ptr) }
52+
ptr
4553
}
4654
}
4755

48-
// &MaybeUninit
56+
// &MaybeUninit<T>
4957

50-
impl<'a, T> Destructure for &'a MaybeUninit<T> {
58+
// SAFETY: Destructuring `&'a MaybeUninit<T>` is safe if and only if destructuring `&'a T` with the
59+
// same pattern is also safe.
60+
unsafe impl<'a, T> Destructure for &'a MaybeUninit<T> {
5161
type Underlying = T;
62+
type Test = &'a T;
5263

5364
fn as_mut_ptr(&mut self) -> *mut Self::Underlying {
5465
self.as_ptr() as *mut Self::Underlying
5566
}
5667
}
5768

69+
// SAFETY: `restructure` returns a valid `MaybeUninit` reference that upholds the same invariants as
70+
// a mutably borrowed subfield of some `T`.
5871
unsafe impl<'a: 'b, 'b, T, U: 'b> Restructure<&'b &'a MaybeUninit<T>> for U {
5972
type Restructured = &'b MaybeUninit<U>;
6073

@@ -65,16 +78,21 @@ unsafe impl<'a: 'b, 'b, T, U: 'b> Restructure<&'b &'a MaybeUninit<T>> for U {
6578
}
6679
}
6780

68-
// &mut MaybeUninit
81+
// &mut MaybeUninit<T>
6982

70-
impl<'a, T> Destructure for &'a mut MaybeUninit<T> {
83+
// SAFETY: Destructuring `&'a mut MaybeUninit<T>` is safe if and only if destructuring `&'a mut T`
84+
// with the same pattern is also safe.
85+
unsafe impl<'a, T> Destructure for &'a mut MaybeUninit<T> {
7186
type Underlying = T;
87+
type Test = &'a T;
7288

7389
fn as_mut_ptr(&mut self) -> *mut Self::Underlying {
7490
MaybeUninit::as_mut_ptr(self)
7591
}
7692
}
7793

94+
// SAFETY: `restructure` returns a valid `MaybeUninit` reference that upholds the same invariants as
95+
// a mutably borrowed subfield of some `T`.
7896
unsafe impl<'a: 'b, 'b, T, U: 'b> Restructure<&'b &'a mut MaybeUninit<T>> for U {
7997
type Restructured = &'b mut MaybeUninit<U>;
8098

@@ -87,56 +105,78 @@ unsafe impl<'a: 'b, 'b, T, U: 'b> Restructure<&'b &'a mut MaybeUninit<T>> for U
87105

88106
// &Cell<T>
89107

90-
impl<'a, T> Destructure for &'a Cell<T> {
108+
// SAFETY: Destructuring `&'a Cell<T>` is safe if and only if destructuring `&'a T` with the same
109+
// pattern is also safe.
110+
unsafe impl<'a, T: ?Sized> Destructure for &'a Cell<T> {
91111
type Underlying = T;
112+
type Test = &'a T;
92113

93114
fn as_mut_ptr(&mut self) -> *mut Self::Underlying {
94115
self.as_ptr()
95116
}
96117
}
97118

98-
unsafe impl<'a: 'b, 'b, T, U: 'b> Restructure<&'b &'a Cell<T>> for U {
119+
// SAFETY: `restructure` returns a valid `Cell` reference that upholds the same invariants as a
120+
// mutably borrowed subfield of some `T`.
121+
unsafe impl<'a: 'b, 'b, T: ?Sized, U: 'b + ?Sized> Restructure<&'b &'a Cell<T>> for U {
99122
type Restructured = &'b Cell<U>;
100123

101124
unsafe fn restructure(ptr: *mut Self) -> Self::Restructured {
102125
// SAFETY: The caller has guaranteed that `ptr` points to a subfield of some
103-
// `&'b &'a Cell<T>`, so it's safe to dereference for the `'b` lifetime.
104-
unsafe { &*ptr.cast() }
126+
// `&'b &'a Cell<T>`, so it's safe to dereference for the `'b` lifetime. Additionally, `ptr`
127+
// is guaranteed to have the same pointer metadata as a pointer to `Cell<U>`.
128+
unsafe { &*::core::mem::transmute::<*mut Self, *const Cell<U>>(ptr) }
105129
}
106130
}
107131

108132
// &UnsafeCell<T>
109133

110-
impl<'a, T> Destructure for &'a UnsafeCell<T> {
134+
// SAFETY: Destructuring `&'a UnsafeCell<T>` is safe if and only if destructuring `&'a T` with the
135+
// same pattern is also safe.
136+
unsafe impl<'a, T: ?Sized> Destructure for &'a UnsafeCell<T> {
111137
type Underlying = T;
138+
type Test = &'a T;
112139

113140
fn as_mut_ptr(&mut self) -> *mut Self::Underlying {
114141
self.get()
115142
}
116143
}
117144

118-
unsafe impl<'a: 'b, 'b, T, U: 'b> Restructure<&'b &'a UnsafeCell<T>> for U {
145+
// SAFETY: `restructure` returns a valid `UnsafeCell` reference that upholds the same invariants as
146+
// a mutably borrowed subfield of some `T`.
147+
unsafe impl<'a: 'b, 'b, T: ?Sized, U: 'b + ?Sized> Restructure<&'b &'a UnsafeCell<T>> for U {
119148
type Restructured = &'b UnsafeCell<U>;
120149

121150
unsafe fn restructure(ptr: *mut Self) -> Self::Restructured {
122151
// SAFETY: The caller has guaranteed that `ptr` points to a subfield of some
123-
// `&'b &'a UnsafeCell<T>`, so it's safe to dereference for the `'b` lifetime.
124-
unsafe { &*ptr.cast() }
152+
// `&'b &'a UnsafeCell<T>`, so it's safe to dereference for the `'b` lifetime. Additionally,
153+
// `ptr` is guaranteed to have the same pointer metadata as a pointer to `UnsafeCell<U>`.
154+
unsafe { &*::core::mem::transmute::<*mut Self, *const UnsafeCell<U>>(ptr) }
125155
}
126156
}
127157

128158
// Pin<&T> where T: StructuralPinning
129159

130-
impl<'a, T: StructuralPinning> Destructure for Pin<&'a T> {
160+
// SAFETY: Destructuring `Pin<&'a T>` is safe if and only if destructuring `&'a T` with the same
161+
// pattern is also safe.
162+
unsafe impl<'a, T: StructuralPinning + ?Sized> Destructure for Pin<&'a T> {
131163
type Underlying = T;
164+
type Test = &'a T;
132165

133166
fn as_mut_ptr(&mut self) -> *mut Self::Underlying {
134167
// SAFETY: The value pointed to by `self` will continue to be treated as pinned.
135168
unsafe { Pin::into_inner_unchecked(self.as_ref()) as *const T as *mut T }
136169
}
137170
}
138171

139-
unsafe impl<'a: 'b, 'b, T: StructuralPinning, U: 'b> Restructure<&'b Pin<&'a T>> for U {
172+
// SAFETY: `restructure` returns a valid `Pin<&'a T>` that upholds the same invariants as a mutably
173+
// borrowed subfield of some `T`.
174+
unsafe impl<'a, 'b, T, U> Restructure<&'b Pin<&'a T>> for U
175+
where
176+
'a: 'b,
177+
T: StructuralPinning + ?Sized,
178+
U: 'b + ?Sized,
179+
{
140180
type Restructured = Pin<&'b U>;
141181

142182
unsafe fn restructure(ptr: *mut Self) -> Self::Restructured {
@@ -149,16 +189,26 @@ unsafe impl<'a: 'b, 'b, T: StructuralPinning, U: 'b> Restructure<&'b Pin<&'a T>>
149189

150190
// Pin<&mut T> where T: StructuralPinning
151191

152-
impl<'a, T: StructuralPinning> Destructure for Pin<&'a mut T> {
192+
// SAFETY: Destructuring `Pin<&'a mut T>` is safe if and only if destructuring `&'a T` with the same
193+
// pattern is also safe.
194+
unsafe impl<'a, T: StructuralPinning + ?Sized> Destructure for Pin<&'a mut T> {
153195
type Underlying = T;
196+
type Test = &'a T;
154197

155198
fn as_mut_ptr(&mut self) -> *mut Self::Underlying {
156199
// SAFETY: The value pointed to by `self` will continue to be treated as pinned.
157200
unsafe { Pin::into_inner_unchecked(self.as_mut()) as *mut T }
158201
}
159202
}
160203

161-
unsafe impl<'a: 'b, 'b, T: StructuralPinning, U: 'b> Restructure<&'b Pin<&'a mut T>> for U {
204+
// SAFETY: `restructure` returns a valid `Pin<&'a mut T>` that upholds the same invariants as a
205+
// mutably borrowed subfield of some `T`.
206+
unsafe impl<'a, 'b, T, U> Restructure<&'b Pin<&'a mut T>> for U
207+
where
208+
'a: 'b,
209+
T: StructuralPinning + ?Sized,
210+
U: 'b + ?Sized,
211+
{
162212
type Restructured = Pin<&'b mut U>;
163213

164214
unsafe fn restructure(ptr: *mut Self) -> Self::Restructured {
@@ -171,14 +221,19 @@ unsafe impl<'a: 'b, 'b, T: StructuralPinning, U: 'b> Restructure<&'b Pin<&'a mut
171221

172222
// ManuallyDrop<T>
173223

174-
impl<'a, T> Destructure for ManuallyDrop<T> {
224+
// SAFETY: Destructuring `ManuallyDrop<T>` is safe if and only if destructuring `T` with the same
225+
// pattern is also safe.
226+
unsafe impl<'a, T> Destructure for ManuallyDrop<T> {
175227
type Underlying = T;
228+
type Test = T;
176229

177230
fn as_mut_ptr(&mut self) -> *mut Self::Underlying {
178231
&mut **self as *mut Self::Underlying
179232
}
180233
}
181234

235+
// SAFETY: `restructure` returns a valid `ManuallyDrop<T>` that upholds the same invariants as a
236+
// mutably borrowed subfield of some `T`.
182237
unsafe impl<T, U> Restructure<&ManuallyDrop<T>> for U {
183238
type Restructured = ManuallyDrop<U>;
184239

0 commit comments

Comments
 (0)