@@ -20,6 +20,7 @@ use fmt;
2020use mem;
2121use usize;
2222use ptr:: { self , NonNull } ;
23+ use num:: NonZeroUsize ;
2324
2425extern {
2526 /// An opaque, unsized type. Used for pointers to allocated memory.
@@ -66,7 +67,7 @@ fn size_align<T>() -> (usize, usize) {
6667#[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
6768pub struct Layout {
6869 // size of the requested block of memory, measured in bytes.
69- size : usize ,
70+ size_ : usize ,
7071
7172 // alignment of the requested block of memory, measured in bytes.
7273 // we ensure that this is always a power-of-two, because API's
@@ -75,17 +76,12 @@ pub struct Layout {
7576 //
7677 // (However, we do not analogously require `align >= sizeof(void*)`,
7778 // even though that is *also* a requirement of `posix_memalign`.)
78- align : usize ,
79+ align_ : NonZeroUsize ,
7980}
8081
81-
82- // FIXME: audit default implementations for overflow errors,
83- // (potentially switching to overflowing_add and
84- // overflowing_mul as necessary).
85-
8682impl Layout {
8783 /// Constructs a `Layout` from a given `size` and `align`,
88- /// or returns `None ` if either of the following conditions
84+ /// or returns `LayoutErr ` if either of the following conditions
8985 /// are not met:
9086 ///
9187 /// * `align` must be a power of two,
@@ -126,23 +122,23 @@ impl Layout {
126122 ///
127123 /// # Safety
128124 ///
129- /// This function is unsafe as it does not verify that `align` is
130- /// a power-of-two nor `size` aligned to `align` fits within the
131- /// address space (i.e. the `Layout::from_size_align` preconditions).
125+ /// This function is unsafe as it does not verify the preconditions from
126+ /// [`Layout::from_size_align`](#method.from_size_align).
132127 #[ inline]
133128 pub unsafe fn from_size_align_unchecked ( size : usize , align : usize ) -> Self {
134- Layout { size : size, align : align }
129+ Layout { size_ : size, align_ : NonZeroUsize :: new_unchecked ( align) }
135130 }
136131
137132 /// The minimum size in bytes for a memory block of this layout.
138133 #[ inline]
139- pub fn size ( & self ) -> usize { self . size }
134+ pub fn size ( & self ) -> usize { self . size_ }
140135
141136 /// The minimum byte alignment for a memory block of this layout.
142137 #[ inline]
143- pub fn align ( & self ) -> usize { self . align }
138+ pub fn align ( & self ) -> usize { self . align_ . get ( ) }
144139
145140 /// Constructs a `Layout` suitable for holding a value of type `T`.
141+ #[ inline]
146142 pub fn new < T > ( ) -> Self {
147143 let ( size, align) = size_align :: < T > ( ) ;
148144 // Note that the align is guaranteed by rustc to be a power of two and
@@ -158,6 +154,7 @@ impl Layout {
158154 /// Produces layout describing a record that could be used to
159155 /// allocate backing structure for `T` (which could be a trait
160156 /// or other unsized type like a slice).
157+ #[ inline]
161158 pub fn for_value < T : ?Sized > ( t : & T ) -> Self {
162159 let ( size, align) = ( mem:: size_of_val ( t) , mem:: align_of_val ( t) ) ;
163160 // See rationale in `new` for why this us using an unsafe variant below
@@ -181,18 +178,19 @@ impl Layout {
181178 ///
182179 /// # Panics
183180 ///
184- /// Panics if the combination of `self.size` and the given `align`
185- /// violates the conditions listed in `from_size_align`.
181+ /// Panics if the combination of `self.size()` and the given `align`
182+ /// violates the conditions listed in
183+ /// [`Layout::from_size_align`](#method.from_size_align).
186184 #[ inline]
187185 pub fn align_to ( & self , align : usize ) -> Self {
188- Layout :: from_size_align ( self . size , cmp:: max ( self . align , align) ) . unwrap ( )
186+ Layout :: from_size_align ( self . size ( ) , cmp:: max ( self . align ( ) , align) ) . unwrap ( )
189187 }
190188
191189 /// Returns the amount of padding we must insert after `self`
192190 /// to ensure that the following address will satisfy `align`
193191 /// (measured in bytes).
194192 ///
195- /// E.g. if `self.size` is 9, then `self.padding_needed_for(4)`
193+ /// E.g. if `self.size() ` is 9, then `self.padding_needed_for(4)`
196194 /// returns 3, because that is the minimum number of bytes of
197195 /// padding required to get a 4-aligned address (assuming that the
198196 /// corresponding memory block starts at a 4-aligned address).
@@ -203,7 +201,7 @@ impl Layout {
203201 /// Note that the utility of the returned value requires `align`
204202 /// to be less than or equal to the alignment of the starting
205203 /// address for the whole allocated block of memory. One way to
206- /// satisfy this constraint is to ensure `align <= self.align`.
204+ /// satisfy this constraint is to ensure `align <= self.align() `.
207205 #[ inline]
208206 pub fn padding_needed_for ( & self , align : usize ) -> usize {
209207 let len = self . size ( ) ;
@@ -227,7 +225,8 @@ impl Layout {
227225 // size and padding overflow in the above manner should cause
228226 // the allocator to yield an error anyway.)
229227
230- let len_rounded_up = len. wrapping_add ( align) . wrapping_sub ( 1 ) & !align. wrapping_sub ( 1 ) ;
228+ let len_rounded_up = len. wrapping_add ( align) . wrapping_sub ( 1 )
229+ & !align. wrapping_sub ( 1 ) ;
231230 return len_rounded_up. wrapping_sub ( len) ;
232231 }
233232
@@ -238,14 +237,19 @@ impl Layout {
238237 /// layout of the array and `offs` is the distance between the start
239238 /// of each element in the array.
240239 ///
241- /// On arithmetic overflow, returns `None `.
240+ /// On arithmetic overflow, returns `LayoutErr `.
242241 #[ inline]
243242 pub fn repeat ( & self , n : usize ) -> Result < ( Self , usize ) , LayoutErr > {
244- let padded_size = self . size . checked_add ( self . padding_needed_for ( self . align ) )
243+ let padded_size = self . size ( ) . checked_add ( self . padding_needed_for ( self . align ( ) ) )
245244 . ok_or ( LayoutErr { private : ( ) } ) ?;
246245 let alloc_size = padded_size. checked_mul ( n)
247246 . ok_or ( LayoutErr { private : ( ) } ) ?;
248- Ok ( ( Layout :: from_size_align ( alloc_size, self . align ) ?, padded_size) )
247+
248+ unsafe {
249+ // self.align is already known to be valid and alloc_size has been
250+ // padded already.
251+ Ok ( ( Layout :: from_size_align_unchecked ( alloc_size, self . align ( ) ) , padded_size) )
252+ }
249253 }
250254
251255 /// Creates a layout describing the record for `self` followed by
@@ -258,16 +262,15 @@ impl Layout {
258262 /// start of the `next` embedded within the concatenated record
259263 /// (assuming that the record itself starts at offset 0).
260264 ///
261- /// On arithmetic overflow, returns `None`.
265+ /// On arithmetic overflow, returns `LayoutErr`.
266+ #[ inline]
262267 pub fn extend ( & self , next : Self ) -> Result < ( Self , usize ) , LayoutErr > {
263- let new_align = cmp:: max ( self . align , next. align ) ;
264- let realigned = Layout :: from_size_align ( self . size , new_align) ?;
265-
266- let pad = realigned. padding_needed_for ( next. align ) ;
268+ let new_align = cmp:: max ( self . align ( ) , next. align ( ) ) ;
269+ let pad = self . padding_needed_for ( next. align ( ) ) ;
267270
268- let offset = self . size . checked_add ( pad)
271+ let offset = self . size ( ) . checked_add ( pad)
269272 . ok_or ( LayoutErr { private : ( ) } ) ?;
270- let new_size = offset. checked_add ( next. size )
273+ let new_size = offset. checked_add ( next. size ( ) )
271274 . ok_or ( LayoutErr { private : ( ) } ) ?;
272275
273276 let layout = Layout :: from_size_align ( new_size, new_align) ?;
@@ -285,10 +288,11 @@ impl Layout {
285288 /// guaranteed that all elements in the array will be properly
286289 /// aligned.
287290 ///
288- /// On arithmetic overflow, returns `None`.
291+ /// On arithmetic overflow, returns `LayoutErr`.
292+ #[ inline]
289293 pub fn repeat_packed ( & self , n : usize ) -> Result < Self , LayoutErr > {
290294 let size = self . size ( ) . checked_mul ( n) . ok_or ( LayoutErr { private : ( ) } ) ?;
291- Layout :: from_size_align ( size, self . align )
295+ Layout :: from_size_align ( size, self . align ( ) )
292296 }
293297
294298 /// Creates a layout describing the record for `self` followed by
@@ -305,17 +309,19 @@ impl Layout {
305309 /// signature out of convenience in matching the signature of
306310 /// `extend`.)
307311 ///
308- /// On arithmetic overflow, returns `None`.
312+ /// On arithmetic overflow, returns `LayoutErr`.
313+ #[ inline]
309314 pub fn extend_packed ( & self , next : Self ) -> Result < ( Self , usize ) , LayoutErr > {
310315 let new_size = self . size ( ) . checked_add ( next. size ( ) )
311316 . ok_or ( LayoutErr { private : ( ) } ) ?;
312- let layout = Layout :: from_size_align ( new_size, self . align ) ?;
317+ let layout = Layout :: from_size_align ( new_size, self . align ( ) ) ?;
313318 Ok ( ( layout, self . size ( ) ) )
314319 }
315320
316321 /// Creates a layout describing the record for a `[T; n]`.
317322 ///
318- /// On arithmetic overflow, returns `None`.
323+ /// On arithmetic overflow, returns `LayoutErr`.
324+ #[ inline]
319325 pub fn array < T > ( n : usize ) -> Result < Self , LayoutErr > {
320326 Layout :: new :: < T > ( )
321327 . repeat ( n)
@@ -842,7 +848,7 @@ pub unsafe trait Alloc {
842848 layout : Layout ,
843849 new_size : usize ) -> Result < ( ) , CannotReallocInPlace > {
844850 let _ = ptr; // this default implementation doesn't care about the actual address.
845- debug_assert ! ( new_size >= layout. size) ;
851+ debug_assert ! ( new_size >= layout. size( ) ) ;
846852 let ( _l, u) = self . usable_size ( & layout) ;
847853 // _l <= layout.size() [guaranteed by usable_size()]
848854 // layout.size() <= new_layout.size() [required by this method]
@@ -897,7 +903,7 @@ pub unsafe trait Alloc {
897903 layout : Layout ,
898904 new_size : usize ) -> Result < ( ) , CannotReallocInPlace > {
899905 let _ = ptr; // this default implementation doesn't care about the actual address.
900- debug_assert ! ( new_size <= layout. size) ;
906+ debug_assert ! ( new_size <= layout. size( ) ) ;
901907 let ( l, _u) = self . usable_size ( & layout) ;
902908 // layout.size() <= _u [guaranteed by usable_size()]
903909 // new_layout.size() <= layout.size() [required by this method]
0 commit comments