When constructing a Rc<[T]> or Arc<[T]> with a capacity exceeding isize::MAX, taking into account the size used for their headers, they cause a panic by unwrapping a LayoutError. Instead, they should panic with a more helpful error like Vec<T> and Box<[T]> do. This seems to be a simple oversight.
For example:
const MAX: usize = isize::MAX as usize;
type Header = (usize, usize);
const S: usize = size_of::<Header>();
const A: usize = align_of::<Header>();
Rc::<[u8]>::new_uninit_slice((MAX / A * A) - S + 1); // layout error
Rc::<[u8]>::new_zeroed_slice((MAX / A * A) - S + 1); // layout error
Arc::<[u8]>::new_uninit_slice((MAX / A * A) - S + 1); // layout error
Arc::<[u8]>::new_zeroed_slice((MAX / A * A) - S + 1); // layout error
called `Result::unwrap()` on an `Err` value: LayoutError
See all LayoutError panic backtraces
thread 'main' panicked at library/alloc/src/rc.rs:298:49:
called `Result::unwrap()` on an `Err` value: LayoutError
stack backtrace:
3: core::result::Result<T,E>::unwrap
at /rustc/43ca9d18e333797f0aa3b525501a7cec8d61a96b/library/core/src/result.rs:1109:23
4: alloc::rc::rc_inner_layout_for_value_layout
at /rustc/43ca9d18e333797f0aa3b525501a7cec8d61a96b/library/alloc/src/rc.rs:298:5
5: alloc::rc::Rc<T>::allocate_for_layout
at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/rc.rs:2057:22
6: alloc::rc::Rc<[T]>::allocate_for_slice
at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/rc.rs:2136:13
7: alloc::rc::Rc<[T]>::new_uninit_slice
at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/rc.rs:1050:31
Rc::<[u8]>::new_zeroed_slice((MAX / A * A) - S + 1);
thread 'main' panicked at library/alloc/src/rc.rs:298:49:
called `Result::unwrap()` on an `Err` value: LayoutError
stack backtrace:
3: core::result::Result<T,E>::unwrap
at /rustc/43ca9d18e333797f0aa3b525501a7cec8d61a96b/library/core/src/result.rs:1109:23
4: alloc::rc::rc_inner_layout_for_value_layout
at /rustc/43ca9d18e333797f0aa3b525501a7cec8d61a96b/library/alloc/src/rc.rs:298:5
5: alloc::rc::Rc<T>::allocate_for_layout
at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/rc.rs:2057:22
6: alloc::rc::Rc<[T]>::new_zeroed_slice
at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/rc.rs:1078:26
Arc::<[u8]>::new_uninit_slice((MAX / A * A) - S + 1);
thread 'main' panicked at library/alloc/src/sync.rs:367:50:
called `Result::unwrap()` on an `Err` value: LayoutError
stack backtrace:
3: core::result::Result<T,E>::unwrap
at /rustc/43ca9d18e333797f0aa3b525501a7cec8d61a96b/library/core/src/result.rs:1109:23
4: alloc::sync::arcinner_layout_for_value_layout
at /rustc/43ca9d18e333797f0aa3b525501a7cec8d61a96b/library/alloc/src/sync.rs:367:5
5: alloc::sync::Arc<T>::allocate_for_layout
at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/sync.rs:1950:22
6: alloc::sync::Arc<[T]>::allocate_for_slice
at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/sync.rs:2037:13
7: alloc::sync::Arc<[T]>::new_uninit_slice
at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/sync.rs:1168:32
Arc::<[u8]>::new_zeroed_slice((MAX / A * A) - S + 1);
thread 'main' panicked at library/alloc/src/sync.rs:367:50:
called `Result::unwrap()` on an `Err` value: LayoutError
stack backtrace:
3: core::result::Result<T,E>::unwrap
at /rustc/43ca9d18e333797f0aa3b525501a7cec8d61a96b/library/core/src/result.rs:1109:23
4: alloc::sync::arcinner_layout_for_value_layout
at /rustc/43ca9d18e333797f0aa3b525501a7cec8d61a96b/library/alloc/src/sync.rs:367:5
5: alloc::sync::Arc<T>::allocate_for_layout
at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/sync.rs:1950:22
6: alloc::sync::Arc<[T]>::new_zeroed_slice
at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/sync.rs:1197:27
In contrast, in this same case, Vec<T> and Box<[T]> panic with a more useful capacity overflow:
Vec::<u8>::with_capacity(MAX + 1); // capacity overflow
vec![0u8; MAX + 1]; // capacity overflow
Box::<[u8]>::new_uninit_slice(MAX + 1); // capacity overflow
Box::<[u8]>::new_zeroed_slice(MAX + 1); // capacity overflow
See all capacity overflow backtraces
Vec::<u8>::with_capacity(MAX + 1);
thread 'main' panicked at src/main.rs:11:9:
capacity overflow
stack backtrace:
2: alloc::raw_vec::capacity_overflow
at /rustc/43ca9d18e333797f0aa3b525501a7cec8d61a96b/library/alloc/src/raw_vec.rs:25:5
3: alloc::raw_vec::handle_error
at /rustc/43ca9d18e333797f0aa3b525501a7cec8d61a96b/library/alloc/src/raw_vec.rs:793:29
4: alloc::raw_vec::RawVecInner<A>::with_capacity_in
at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/raw_vec.rs:426:25
5: alloc::raw_vec::RawVec<T,A>::with_capacity_in
at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/raw_vec.rs:186:20
6: alloc::vec::Vec<T,A>::with_capacity_in
at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/vec/mod.rs:803:20
7: alloc::vec::Vec<T>::with_capacity
at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/vec/mod.rs:483:9
thread 'main' panicked at src/main.rs:12:9:
capacity overflow
stack backtrace:
2: alloc::raw_vec::capacity_overflow
at /rustc/43ca9d18e333797f0aa3b525501a7cec8d61a96b/library/alloc/src/raw_vec.rs:25:5
3: alloc::raw_vec::handle_error
at /rustc/43ca9d18e333797f0aa3b525501a7cec8d61a96b/library/alloc/src/raw_vec.rs:793:29
4: alloc::raw_vec::RawVecInner<A>::with_capacity_zeroed_in
at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/raw_vec.rs:445:25
5: alloc::raw_vec::RawVec<T,A>::with_capacity_zeroed_in
at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/raw_vec.rs:208:20
6: <u8 as alloc::vec::spec_from_elem::SpecFromElem>::from_elem
at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/vec/spec_from_elem.rs:55:31
7: alloc::vec::from_elem
at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/vec/mod.rs:3189:5
Box::<[u8]>::new_uninit_slice(MAX + 1);
thread 'main' panicked at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/boxed.rs:688:18:
capacity overflow
stack backtrace:
2: alloc::raw_vec::capacity_overflow
at /rustc/43ca9d18e333797f0aa3b525501a7cec8d61a96b/library/alloc/src/raw_vec.rs:25:5
3: alloc::raw_vec::handle_error
at /rustc/43ca9d18e333797f0aa3b525501a7cec8d61a96b/library/alloc/src/raw_vec.rs:793:29
4: alloc::raw_vec::RawVecInner::with_capacity
at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/raw_vec.rs:148:25
5: alloc::raw_vec::RawVec<T>::with_capacity
at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/raw_vec.rs:124:23
6: alloc::boxed::Box<[T]>::new_uninit_slice
at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/boxed.rs:688:18
Box::<[u8]>::new_zeroed_slice(MAX + 1);
thread 'main' panicked at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/boxed.rs:713:18:
capacity overflow
stack backtrace:
2: alloc::raw_vec::capacity_overflow
at /rustc/43ca9d18e333797f0aa3b525501a7cec8d61a96b/library/alloc/src/raw_vec.rs:25:5
3: alloc::raw_vec::handle_error
at /rustc/43ca9d18e333797f0aa3b525501a7cec8d61a96b/library/alloc/src/raw_vec.rs:793:29
4: alloc::raw_vec::RawVecInner<A>::with_capacity_zeroed_in
at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/raw_vec.rs:445:25
5: alloc::raw_vec::RawVec<T>::with_capacity_zeroed
at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/raw_vec.rs:134:20
6: alloc::boxed::Box<[T]>::new_zeroed_slice
at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/boxed.rs:713:18
Rc::<[u8]>::new_uninit_slice((MAX / A * A) - S + 1);
For completeness, all of these constructors consistently handle failed allocations for valid capacities with alloc::handle_alloc_error:
Vec::<u8>::with_capacity(MAX);
// memory allocation of 9223372036854775807 bytes failed
Rc::<[u8]>::new_zeroed_slice((MAX / A * A) - S);
// memory allocation of 9223372036854775800 bytes failed
See all memory allocation failures
Vec::<u8>::with_capacity(MAX);
memory allocation of 9223372036854775807 bytes failed
memory allocation of 9223372036854775807 bytes failed
Box::<[u8]>::new_uninit_slice(MAX);
memory allocation of 9223372036854775807 bytes failed
Box::<[u8]>::new_zeroed_slice(MAX);
memory allocation of 9223372036854775807 bytes failed
Rc::<[u8]>::new_uninit_slice((MAX / A * A) - S);
memory allocation of 9223372036854775800 bytes failed
Rc::<[u8]>::new_zeroed_slice((MAX / A * A) - S);
memory allocation of 9223372036854775800 bytes failed
Arc::<[u8]>::new_uninit_slice((MAX / A * A) - S);
memory allocation of 9223372036854775800 bytes failed
Arc::<[u8]>::new_zeroed_slice((MAX / A * A) - S);
memory allocation of 9223372036854775800 bytes failed
$ rustc --version --verbose
rustc 1.86.0-nightly (43ca9d18e 2025-02-08)
binary: rustc
commit-hash: 43ca9d18e333797f0aa3b525501a7cec8d61a96b
commit-date: 2025-02-08
host: x86_64-apple-darwin
release: 1.86.0-nightly
LLVM version: 19.1.7
(Similarly on Rust 1.84.1)
When constructing a
Rc<[T]>orArc<[T]>with a capacity exceedingisize::MAX, taking into account the size used for their headers, they cause a panic by unwrapping aLayoutError. Instead, they should panic with a more helpful error likeVec<T>andBox<[T]>do. This seems to be a simple oversight.For example:
See all
LayoutErrorpanic backtracesIn contrast, in this same case,
Vec<T>andBox<[T]>panic with a more useful capacity overflow:See all capacity overflow backtraces
For completeness, all of these constructors consistently handle failed allocations for valid capacities with
alloc::handle_alloc_error:See all memory allocation failures
(Similarly on Rust 1.84.1)