Skip to content

Commit b017742

Browse files
committed
Return Result instead of Option in alloc::Layout constructors
1 parent f9c96d7 commit b017742

File tree

4 files changed

+54
-26
lines changed

4 files changed

+54
-26
lines changed

src/liballoc/raw_vec.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@ impl<T, A: Alloc> RawVec<T, A> {
422422

423423
// Nothing we can really do about these checks :(
424424
let new_cap = used_cap.checked_add(needed_extra_cap).ok_or(CapacityOverflow)?;
425-
let new_layout = Layout::array::<T>(new_cap).ok_or(CapacityOverflow)?;
425+
let new_layout = Layout::array::<T>(new_cap).map_err(|_| CapacityOverflow)?;
426426

427427
alloc_guard(new_layout.size())?;
428428

@@ -530,7 +530,7 @@ impl<T, A: Alloc> RawVec<T, A> {
530530
}
531531

532532
let new_cap = self.amortized_new_size(used_cap, needed_extra_cap)?;
533-
let new_layout = Layout::array::<T>(new_cap).ok_or(CapacityOverflow)?;
533+
let new_layout = Layout::array::<T>(new_cap).map_err(|_| CapacityOverflow)?;
534534

535535
// FIXME: may crash and burn on over-reserve
536536
alloc_guard(new_layout.size())?;

src/libcore/alloc.rs

Lines changed: 41 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,9 @@ impl Layout {
9494
/// must not overflow (i.e. the rounded value must be less than
9595
/// `usize::MAX`).
9696
#[inline]
97-
pub fn from_size_align(size: usize, align: usize) -> Option<Layout> {
97+
pub fn from_size_align(size: usize, align: usize) -> Result<Self, LayoutErr> {
9898
if !align.is_power_of_two() {
99-
return None;
99+
return Err(LayoutErr { private: () });
100100
}
101101

102102
// (power-of-two implies align != 0.)
@@ -114,11 +114,11 @@ impl Layout {
114114
// Above implies that checking for summation overflow is both
115115
// necessary and sufficient.
116116
if size > usize::MAX - (align - 1) {
117-
return None;
117+
return Err(LayoutErr { private: () });
118118
}
119119

120120
unsafe {
121-
Some(Layout::from_size_align_unchecked(size, align))
121+
Ok(Layout::from_size_align_unchecked(size, align))
122122
}
123123
}
124124

@@ -130,7 +130,7 @@ impl Layout {
130130
/// a power-of-two nor `size` aligned to `align` fits within the
131131
/// address space (i.e. the `Layout::from_size_align` preconditions).
132132
#[inline]
133-
pub unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Layout {
133+
pub unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self {
134134
Layout { size: size, align: align }
135135
}
136136

@@ -229,15 +229,17 @@ impl Layout {
229229
///
230230
/// On arithmetic overflow, returns `None`.
231231
#[inline]
232-
pub fn repeat(&self, n: usize) -> Option<(Self, usize)> {
233-
let padded_size = self.size.checked_add(self.padding_needed_for(self.align))?;
234-
let alloc_size = padded_size.checked_mul(n)?;
232+
pub fn repeat(&self, n: usize) -> Result<(Self, usize), LayoutErr> {
233+
let padded_size = self.size.checked_add(self.padding_needed_for(self.align))
234+
.ok_or(LayoutErr { private: () })?;
235+
let alloc_size = padded_size.checked_mul(n)
236+
.ok_or(LayoutErr { private: () })?;
235237

236238
// We can assume that `self.align` is a power-of-two.
237239
// Furthermore, `alloc_size` has already been rounded up
238240
// to a multiple of `self.align`; therefore, the call to
239241
// `Layout::from_size_align` below should never panic.
240-
Some((Layout::from_size_align(alloc_size, self.align).unwrap(), padded_size))
242+
Ok((Layout::from_size_align(alloc_size, self.align).unwrap(), padded_size))
241243
}
242244

243245
/// Creates a layout describing the record for `self` followed by
@@ -251,17 +253,19 @@ impl Layout {
251253
/// (assuming that the record itself starts at offset 0).
252254
///
253255
/// On arithmetic overflow, returns `None`.
254-
pub fn extend(&self, next: Self) -> Option<(Self, usize)> {
256+
pub fn extend(&self, next: Self) -> Result<(Self, usize), LayoutErr> {
255257
let new_align = cmp::max(self.align, next.align);
256258
let realigned = Layout::from_size_align(self.size, new_align)?;
257259

258260
let pad = realigned.padding_needed_for(next.align);
259261

260-
let offset = self.size.checked_add(pad)?;
261-
let new_size = offset.checked_add(next.size)?;
262+
let offset = self.size.checked_add(pad)
263+
.ok_or(LayoutErr { private: () })?;
264+
let new_size = offset.checked_add(next.size)
265+
.ok_or(LayoutErr { private: () })?;
262266

263267
let layout = Layout::from_size_align(new_size, new_align)?;
264-
Some((layout, offset))
268+
Ok((layout, offset))
265269
}
266270

267271
/// Creates a layout describing the record for `n` instances of
@@ -276,8 +280,8 @@ impl Layout {
276280
/// aligned.
277281
///
278282
/// On arithmetic overflow, returns `None`.
279-
pub fn repeat_packed(&self, n: usize) -> Option<Self> {
280-
let size = self.size().checked_mul(n)?;
283+
pub fn repeat_packed(&self, n: usize) -> Result<Self, LayoutErr> {
284+
let size = self.size().checked_mul(n).ok_or(LayoutErr { private: () })?;
281285
Layout::from_size_align(size, self.align)
282286
}
283287

@@ -296,16 +300,17 @@ impl Layout {
296300
/// `extend`.)
297301
///
298302
/// On arithmetic overflow, returns `None`.
299-
pub fn extend_packed(&self, next: Self) -> Option<(Self, usize)> {
300-
let new_size = self.size().checked_add(next.size())?;
303+
pub fn extend_packed(&self, next: Self) -> Result<(Self, usize), LayoutErr> {
304+
let new_size = self.size().checked_add(next.size())
305+
.ok_or(LayoutErr { private: () })?;
301306
let layout = Layout::from_size_align(new_size, self.align)?;
302-
Some((layout, self.size()))
307+
Ok((layout, self.size()))
303308
}
304309

305310
/// Creates a layout describing the record for a `[T; n]`.
306311
///
307312
/// On arithmetic overflow, returns `None`.
308-
pub fn array<T>(n: usize) -> Option<Self> {
313+
pub fn array<T>(n: usize) -> Result<Self, LayoutErr> {
309314
Layout::new::<T>()
310315
.repeat(n)
311316
.map(|(k, offs)| {
@@ -315,6 +320,20 @@ impl Layout {
315320
}
316321
}
317322

323+
/// The parameters given to `Layout::from_size_align` do not satisfy
324+
/// its documented constraints.
325+
#[derive(Clone, PartialEq, Eq, Debug)]
326+
pub struct LayoutErr {
327+
private: ()
328+
}
329+
330+
// (we need this for downstream impl of trait Error)
331+
impl fmt::Display for LayoutErr {
332+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
333+
f.write_str("invalid parameters to Layout::from_size_align")
334+
}
335+
}
336+
318337
/// The `AllocErr` error specifies whether an allocation failure is
319338
/// specifically due to resource exhaustion or if it is due to
320339
/// something wrong when combining the given input arguments with this
@@ -990,7 +1009,7 @@ pub unsafe trait Alloc {
9901009
where Self: Sized
9911010
{
9921011
match Layout::array::<T>(n) {
993-
Some(ref layout) if layout.size() > 0 => {
1012+
Ok(ref layout) if layout.size() > 0 => {
9941013
unsafe {
9951014
self.alloc(layout.clone())
9961015
.map(|p| {
@@ -1041,7 +1060,7 @@ pub unsafe trait Alloc {
10411060
where Self: Sized
10421061
{
10431062
match (Layout::array::<T>(n_old), Layout::array::<T>(n_new), ptr.as_ptr()) {
1044-
(Some(ref k_old), Some(ref k_new), ptr) if k_old.size() > 0 && k_new.size() > 0 => {
1063+
(Ok(ref k_old), Ok(ref k_new), ptr) if k_old.size() > 0 && k_new.size() > 0 => {
10451064
self.realloc(ptr as *mut u8, k_old.clone(), k_new.clone())
10461065
.map(|p| NonNull::new_unchecked(p as *mut T))
10471066
}
@@ -1076,7 +1095,7 @@ pub unsafe trait Alloc {
10761095
{
10771096
let raw_ptr = ptr.as_ptr() as *mut u8;
10781097
match Layout::array::<T>(n) {
1079-
Some(ref k) if k.size() > 0 => {
1098+
Ok(ref k) if k.size() > 0 => {
10801099
Ok(self.dealloc(raw_ptr, k.clone()))
10811100
}
10821101
_ => {

src/libstd/collections/hash/table.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -755,7 +755,7 @@ impl<K, V> RawTable<K, V> {
755755
}
756756

757757
let buffer = Global.alloc(Layout::from_size_align(size, alignment)
758-
.ok_or(CollectionAllocErr::CapacityOverflow)?)?;
758+
.map_err(|_| CollectionAllocErr::CapacityOverflow)?)?;
759759

760760
let hashes = buffer as *mut HashUint;
761761

src/libstd/error.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ use cell;
5757
use char;
5858
use core::array;
5959
use fmt::{self, Debug, Display};
60-
use heap::{AllocErr, CannotReallocInPlace};
60+
use heap::{AllocErr, LayoutErr, CannotReallocInPlace};
6161
use mem::transmute;
6262
use num;
6363
use str;
@@ -247,6 +247,15 @@ impl Error for AllocErr {
247247
}
248248
}
249249

250+
#[unstable(feature = "allocator_api",
251+
reason = "the precise API and guarantees it provides may be tweaked.",
252+
issue = "32838")]
253+
impl Error for LayoutErr {
254+
fn description(&self) -> &str {
255+
"invalid parameters to Layout::from_size_align"
256+
}
257+
}
258+
250259
#[unstable(feature = "allocator_api",
251260
reason = "the precise API and guarantees it provides may be tweaked.",
252261
issue = "32838")]

0 commit comments

Comments
 (0)