77 alloc_mut:: BasicAllocMut ,
88 data:: {
99 marker:: UnsizedCopy ,
10- type_props:: { PtrProps , SizedProps , VarSized , varsized_nonnull_from_parts}
10+ type_props:: {
11+ KnownAlign ,
12+ PtrProps ,
13+ SizedProps ,
14+ VarSized ,
15+ varsized_nonnull_from_parts
16+ }
1117 }
1218 }
1319 } ,
1622 default:: Default ,
1723 fmt:: { Debug , Display , Formatter , Result as FmtResult } ,
1824 marker:: { PhantomData , Send , Sized , Sync } ,
19- mem:: MaybeUninit ,
25+ mem:: { ManuallyDrop , MaybeUninit } ,
2026 ops:: { Deref , DerefMut , Drop } ,
2127 panic,
2228 ptr:: { self , NonNull } ,
@@ -25,15 +31,20 @@ use {
2531 }
2632} ;
2733
34+ // TODO: box_all_unsized which adds support for trait objects and all unsized types, even those that
35+ // don't implement VarSized.
36+
2837#[ inline]
29- fn unwrap_fail < T : ?Sized , A : BasicAllocMut , E : Display > ( r : Result < Box < T , A > , E > ) -> Box < T , A > {
38+ fn unwrap_fail < T : ?Sized + KnownAlign , A : BasicAllocMut , E : Display > (
39+ r : Result < Box < T , A > , E >
40+ ) -> Box < T , A > {
3041 match r {
3142 Ok ( b) => b,
3243 Err ( e) => panic ! ( "allocation for `Box` failed: {}" , e)
3344 }
3445}
3546
36- pub struct Box < T : ?Sized , A : BasicAllocMut = DefaultAlloc > {
47+ pub struct Box < T : ?Sized + KnownAlign , A : BasicAllocMut = DefaultAlloc > {
3748 ptr : NonNull < T > ,
3849 alloc : A ,
3950 _marker : PhantomData < T >
@@ -42,10 +53,12 @@ pub struct Box<T: ?Sized, A: BasicAllocMut = DefaultAlloc> {
4253pub enum BoxErr < E : Debug + Display + From < Error > > {
4354 AllocError ( E ) ,
4455 NullPtr ,
45- DanglingPtr ( * const ( ) )
56+ DanglingPtr ( usize )
4657}
4758
59+ // SAFETY: we own the `T` instance/as `Unique` puts it, "the data [this points to] is unaliased."
4860unsafe impl < T : Send , A : BasicAllocMut + Send > Send for Box < T , A > { }
61+ // SAFETY: above
4962unsafe impl < T : Sync , A : BasicAllocMut + Sync > Sync for Box < T , A > { }
5063
5164impl < E : Debug + Display + From < Error > > Display for BoxErr < E > {
@@ -94,12 +107,13 @@ impl<T, A: BasicAllocMut> Box<T, A> {
94107 data : T ,
95108 alloc : A
96109 ) -> Result < Box < T , A > , BoxErr < <A as AllocDescriptor >:: Error > > {
97- let mut alloc = alloc;
98- let ptr = tri ! ( wrap ( BoxErr :: AllocError ) alloc. alloc_mut ( T :: LAYOUT ) ) . cast ( ) ;
110+ let mut boxed = tri ! ( do Box :: try_new_uninit_in ( alloc) ) ;
111+ // SAFETY: alloc traits always return a valid pointer.
99112 unsafe {
100- ptr:: write ( ptr . as_ptr ( ) , data) ;
113+ ptr:: write ( boxed . as_mut_ptr ( ) , data) ;
101114 }
102- Ok ( Box { ptr, alloc, _marker : PhantomData } )
115+ // SAFETY: we just initialized the box
116+ Ok ( unsafe { boxed. assume_init ( ) } )
103117 }
104118 pub fn try_new_uninit_in (
105119 alloc : A
@@ -110,9 +124,18 @@ impl<T, A: BasicAllocMut> Box<T, A> {
110124 }
111125}
112126
113- impl < T : ?Sized > Box < T > {
127+ impl < T : KnownAlign , A : BasicAllocMut > Box < MaybeUninit < T > , A > {
128+ // at least for now, this has no reason to be const
129+ pub unsafe fn assume_init ( self ) -> Box < T , A > {
130+ let no_drop = ManuallyDrop :: new ( self ) ;
131+ Box { ptr : no_drop. ptr . cast ( ) , alloc : ptr:: read ( & no_drop. alloc ) , _marker : PhantomData }
132+ }
133+ }
134+
135+ impl < T : ?Sized + KnownAlign > Box < T > {
136+ #[ :: rustversion:: attr( since( 1.61 ) , const ) ]
114137 #[ allow( clippy:: must_use_candidate) ]
115- pub const unsafe fn from_raw ( ptr : NonNull < T > ) -> Box < T > {
138+ pub unsafe fn from_raw ( ptr : NonNull < T > ) -> Box < T > {
116139 Box :: from_raw_in ( ptr, DefaultAlloc )
117140 }
118141
@@ -134,19 +157,22 @@ impl<T: ?Sized> Box<T> {
134157 where
135158 T : UnsizedCopy + VarSized
136159 {
160+ // SAFETY: caller guarantee
137161 unsafe { Box :: copy_from_ptr_in ( p, DefaultAlloc ) }
138162 }
139163
140164 pub unsafe fn try_copy_from_ptr ( p : * const T ) -> Result < Box < T > , BoxErr < Error > >
141165 where
142166 T : UnsizedCopy + VarSized
143167 {
168+ // SAFETY: caller guarantee
144169 unsafe { Box :: try_copy_from_ptr_in ( p, DefaultAlloc ) }
145170 }
146171}
147172
148- impl < T : ?Sized , A : BasicAllocMut > Box < T , A > {
149- pub const unsafe fn from_raw_in ( ptr : NonNull < T > , alloc : A ) -> Box < T , A > {
173+ impl < T : ?Sized + KnownAlign , A : BasicAllocMut > Box < T , A > {
174+ #[ :: rustversion:: attr( since( 1.61 ) , const ) ]
175+ pub unsafe fn from_raw_in ( ptr : NonNull < T > , alloc : A ) -> Box < T , A > {
150176 Box { ptr, alloc, _marker : PhantomData }
151177 }
152178
@@ -158,19 +184,20 @@ impl<T: ?Sized, A: BasicAllocMut> Box<T, A> {
158184 }
159185
160186 pub fn try_copy_from_ref_in (
161- r : & T ,
162- alloc : A
187+ _r : & T ,
188+ _alloc : A
163189 ) -> Result < Box < T , A > , BoxErr < <A as AllocDescriptor >:: Error > >
164190 where
165191 T : UnsizedCopy + VarSized
166192 {
167- unsafe { Box :: try_copy_from_ptr_in ( r , alloc ) }
193+ :: core :: todo! ( )
168194 }
169195
170196 pub unsafe fn copy_from_ptr_in ( p : * const T , alloc : A ) -> Box < T , A >
171197 where
172198 T : UnsizedCopy + VarSized
173199 {
200+ // SAFETY: caller guarantee
174201 unwrap_fail ( unsafe { Box :: try_copy_from_ptr_in ( p, alloc) } )
175202 }
176203
@@ -181,40 +208,61 @@ impl<T: ?Sized, A: BasicAllocMut> Box<T, A> {
181208 where
182209 T : UnsizedCopy + VarSized
183210 {
211+ let p_addr = p. cast :: < ( ) > ( ) as usize ;
212+ if p. is_null ( ) {
213+ return Err ( BoxErr :: NullPtr ) ;
214+ } else if p_addr == T :: ALN {
215+ return Err ( BoxErr :: DanglingPtr ( p_addr) ) ;
216+ } // we purposefully don't check for alignment here.
217+
184218 let mut alloc = alloc;
185219
220+ // SAFETY: caller guarantee
186221 let sz = unsafe { p. sz ( ) } ;
187222 let ptr = tri ! ( wrap( BoxErr :: AllocError ) alloc. alloc_mut( p. layout( ) ) ) ;
188-
223+ // SAFETY: `alloc` returns a pointer to at least the `p.sz()` bytes
189224 unsafe {
190225 ptr:: copy_nonoverlapping ( p. cast :: < u8 > ( ) , ptr. as_ptr ( ) , sz) ;
191226 }
192227 Ok ( Box { ptr : varsized_nonnull_from_parts ( ptr, sz) , alloc, _marker : PhantomData } )
193228 }
194229}
195230
196- impl < T : ?Sized , A : BasicAllocMut > Deref for Box < T , A > {
231+ impl < T : ?Sized + KnownAlign , A : BasicAllocMut > Deref for Box < T , A > {
197232 type Target = T ;
198233
199234 fn deref ( & self ) -> & T {
235+ // SAFETY: `self.ptr` is always a pointer to a valid `T` unless a `from_raw` function had
236+ // its safety contract broken.
200237 unsafe { & * self . ptr . as_ptr ( ) }
201238 }
202239}
203240
204- impl < T : ?Sized , A : BasicAllocMut > DerefMut for Box < T , A > {
241+ impl < T : ?Sized + KnownAlign , A : BasicAllocMut > DerefMut for Box < T , A > {
205242 fn deref_mut ( & mut self ) -> & mut T {
243+ // SAFETY: `self.ptr` is always a pointer to a valid `T` unless a `from_raw` function had
244+ // its safety contract broken; we own the `T`.
206245 unsafe { & mut * self . ptr . as_ptr ( ) }
207246 }
208247}
209248
210- impl < T : ?Sized , A : BasicAllocMut > Drop for Box < T , A > {
249+ impl < T : ?Sized + KnownAlign , A : BasicAllocMut > Drop for Box < T , A > {
211250 fn drop ( & mut self ) {
251+ // SAFETY: `self.ptr` is always a pointer to a valid `T` unless a `from_raw` function had
252+ // its safety contract broken; we own the `T`
212253 unsafe {
213254 ptr:: drop_in_place ( self . ptr . as_ptr ( ) ) ;
214255 }
215- let layout = unsafe { self . ptr . layout ( ) } ;
216- unsafe {
217- self . alloc . dealloc_mut ( self . ptr . cast ( ) , layout) ;
256+ // TODO: we can make PtrProps functions like layout() fallible and safe with the new
257+ // KnownAlign::ALN
258+ if self . ptr . as_ptr ( ) . cast :: < ( ) > ( ) as usize != T :: ALN {
259+ // SAFETY: the pointer is non-null, we just validated it isn't dangling, and `alloc`
260+ // only returns aligned memory.
261+ let layout = unsafe { self . ptr . layout ( ) } ;
262+ // SAFETY: we allocated the pointer
263+ unsafe {
264+ self . alloc . dealloc_mut ( self . ptr . cast ( ) , layout) ;
265+ }
218266 }
219267 }
220268}
0 commit comments