@@ -31,36 +31,31 @@ impl std::fmt::Display for AlignedBoxError {
31
31
/// `AlignedBox<T>` consists of a `Box<T>` and the `std::alloc::Layout` that has been used to
32
32
/// allocate the referenced memory.
33
33
pub struct AlignedBox < T : ?Sized > {
34
- // container is not a Box<T> but an Option<Box<T>> for purely technical reasons:
35
- // When drop(&mut self) is called, we need to be able to get the raw pointer from the Box.
36
- // Therefore we need to be able to take ownership of the Box. Option::take() allows that.
37
- // The Option is Some as long as the AlignedBox exist. It is only set to None during drop()
38
- // and into_raw_parts(). In both cases, the AlignedBox is destroyed directly afterwards.
39
- container : std:: option:: Option < std:: boxed:: Box < T > > ,
34
+ container : std:: mem:: ManuallyDrop < std:: boxed:: Box < T > > ,
40
35
layout : std:: alloc:: Layout ,
41
36
}
42
37
43
38
impl < T : ?Sized > std:: ops:: Deref for AlignedBox < T > {
44
39
type Target = T ;
45
40
46
41
fn deref ( & self ) -> & T {
47
- // self.container is always Some, so we can just unwrap
48
- self . container . as_deref ( ) . unwrap ( )
42
+ & self . container
49
43
}
50
44
}
51
45
52
46
impl < T : ?Sized > std:: ops:: DerefMut for AlignedBox < T > {
53
47
fn deref_mut ( & mut self ) -> & mut T {
54
- // self.container is always Some, so we can just unwrap
55
- self . container . as_deref_mut ( ) . unwrap ( )
48
+ & mut self . container
56
49
}
57
50
}
58
51
59
52
impl < T : ?Sized > Drop for AlignedBox < T > {
60
53
fn drop ( & mut self ) {
61
- // self.container is always Some, so we can just unwrap
62
- let container = self . container . take ( ) . unwrap ( ) ;
54
+ // SAFETY:
55
+ // * self.container is not used after taking the Box out of it
56
+ // * dealloc is called with layout that has been used for allocation earlier
63
57
unsafe {
58
+ let container = std:: mem:: ManuallyDrop :: take ( & mut self . container ) ;
64
59
std:: alloc:: dealloc ( std:: boxed:: Box :: into_raw ( container) as * mut u8 , self . layout ) ;
65
60
}
66
61
}
@@ -80,10 +75,9 @@ impl<T: Clone + ?Sized> Clone for AlignedBox<T> {
80
75
81
76
// *b is not a valid instance of T but uninitialized memory. We have to write to it without
82
77
// dropping the old (invalid) value. Also the original value must not be dropped.
83
- // self.container is always Some, so we can just unwrap.
84
78
// SAFETY: *b points to valid and properly aligned memory and clone() also provides us with
85
79
// a valid value.
86
- unsafe { std:: ptr:: write ( & mut * b, ( * self . container . as_deref ( ) . unwrap ( ) ) . clone ( ) ) } ;
80
+ unsafe { std:: ptr:: write ( & mut * b, ( * * self . container ) . clone ( ) ) } ;
87
81
88
82
b
89
83
}
@@ -95,8 +89,8 @@ impl<T: ?Sized> AlignedBox<T> {
95
89
/// behind the pointer. This can for example be done by reconstructing the `AlignedBox` using
96
90
/// `AlignedBox::from_raw_parts`.
97
91
pub fn into_raw_parts ( mut from : AlignedBox < T > ) -> ( * mut T , std:: alloc:: Layout ) {
98
- // self .container is always Some, so we can just unwrap
99
- let container = from. container . take ( ) . unwrap ( ) ;
92
+ // SAFETY: from .container is not used anymore afterwards
93
+ let container = unsafe { std :: mem :: ManuallyDrop :: take ( & mut from. container ) } ;
100
94
let ptr = std:: boxed:: Box :: into_raw ( container) ;
101
95
let layout = from. layout ;
102
96
std:: mem:: forget ( from) ; // AlignedBox::drop() must not be called
@@ -114,7 +108,7 @@ impl<T: ?Sized> AlignedBox<T> {
114
108
/// behavior is undefined if the given layout does not correspond to the one used for
115
109
/// allocation.
116
110
pub unsafe fn from_raw_parts ( ptr : * mut T , layout : std:: alloc:: Layout ) -> AlignedBox < T > {
117
- let container = Some ( std:: boxed:: Box :: from_raw ( ptr) ) ;
111
+ let container = std :: mem :: ManuallyDrop :: new ( std:: boxed:: Box :: from_raw ( ptr) ) ;
118
112
AlignedBox :: < T > { container, layout }
119
113
}
120
114
}
0 commit comments