Skip to content

Commit 7705433

Browse files
committed
Asserts the maximum value that can be returned from Vec::len
1 parent 9c7013c commit 7705433

File tree

3 files changed

+25
-9
lines changed

3 files changed

+25
-9
lines changed

Diff for: library/alloc/src/vec/mod.rs

+8
Original file line numberDiff line numberDiff line change
@@ -2630,6 +2630,14 @@ impl<T, A: Allocator> Vec<T, A> {
26302630
#[stable(feature = "rust1", since = "1.0.0")]
26312631
#[rustc_confusables("length", "size")]
26322632
pub fn len(&self) -> usize {
2633+
if !T::IS_ZST {
2634+
// SAFETY: The maximum capacity of `Vec<T>` is `isize::MAX` bytes, so if `T` non-ZST,
2635+
// `Vec<T>` can have at most `isize::MAX as usize / mem::size_of::<T>()` elements.
2636+
unsafe {
2637+
core::hint::assert_unchecked(self.len <= isize::MAX as usize / mem::size_of::<T>());
2638+
}
2639+
}
2640+
26332641
self.len
26342642
}
26352643

Diff for: tests/codegen/vec-in-place.rs

+17-8
Original file line numberDiff line numberDiff line change
@@ -37,39 +37,51 @@ pub struct Baz {
3737
#[no_mangle]
3838
pub fn vec_iterator_cast_primitive(vec: Vec<i8>) -> Vec<u8> {
3939
// CHECK-NOT: loop
40-
// CHECK-NOT: call
4140
vec.into_iter().map(|e| e as u8).collect()
4241
}
4342

4443
// CHECK-LABEL: @vec_iterator_cast_wrapper
4544
#[no_mangle]
4645
pub fn vec_iterator_cast_wrapper(vec: Vec<u8>) -> Vec<Wrapper<u8>> {
4746
// CHECK-NOT: loop
48-
// CHECK-NOT: call
4947
vec.into_iter().map(|e| Wrapper(e)).collect()
5048
}
5149

50+
// CHECK-LABEL: @vec_iterator_cast_signed
51+
#[no_mangle]
52+
pub fn vec_iterator_cast_signed(vec: Vec<i32>) -> Vec<u32> {
53+
// CHECK-NOT: and i{{[0-9]+}} %{{.*}}, {{[0-9]+}}
54+
vec.into_iter().map(|e| u32::from_ne_bytes(e.to_ne_bytes())).collect()
55+
}
56+
57+
// CHECK-LABEL: @vec_iterator_cast_signed_nested
58+
#[no_mangle]
59+
pub fn vec_iterator_cast_signed_nested(vec: Vec<Vec<i32>>) -> Vec<Vec<u32>> {
60+
// CHECK-NOT: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
61+
// CHECK-NOT: %{{.*}} = udiv
62+
vec.into_iter()
63+
.map(|e| e.into_iter().map(|e| u32::from_ne_bytes(e.to_ne_bytes())).collect())
64+
.collect()
65+
}
66+
5267
// CHECK-LABEL: @vec_iterator_cast_unwrap
5368
#[no_mangle]
5469
pub fn vec_iterator_cast_unwrap(vec: Vec<Wrapper<u8>>) -> Vec<u8> {
5570
// CHECK-NOT: loop
56-
// CHECK-NOT: call
5771
vec.into_iter().map(|e| e.0).collect()
5872
}
5973

6074
// CHECK-LABEL: @vec_iterator_cast_aggregate
6175
#[no_mangle]
6276
pub fn vec_iterator_cast_aggregate(vec: Vec<[u64; 4]>) -> Vec<Foo> {
6377
// CHECK-NOT: loop
64-
// CHECK-NOT: call
6578
vec.into_iter().map(|e| unsafe { std::mem::transmute(e) }).collect()
6679
}
6780

6881
// CHECK-LABEL: @vec_iterator_cast_deaggregate_tra
6982
#[no_mangle]
7083
pub fn vec_iterator_cast_deaggregate_tra(vec: Vec<Bar>) -> Vec<[u64; 4]> {
7184
// CHECK-NOT: loop
72-
// CHECK-NOT: call
7385

7486
// Safety: For the purpose of this test we assume that Bar layout matches [u64; 4].
7587
// This currently is not guaranteed for repr(Rust) types, but it happens to work here and
@@ -82,7 +94,6 @@ pub fn vec_iterator_cast_deaggregate_tra(vec: Vec<Bar>) -> Vec<[u64; 4]> {
8294
#[no_mangle]
8395
pub fn vec_iterator_cast_deaggregate_fold(vec: Vec<Baz>) -> Vec<[u64; 4]> {
8496
// CHECK-NOT: loop
85-
// CHECK-NOT: call
8697

8798
// Safety: For the purpose of this test we assume that Bar layout matches [u64; 4].
8899
// This currently is not guaranteed for repr(Rust) types, but it happens to work here and
@@ -95,7 +106,6 @@ pub fn vec_iterator_cast_deaggregate_fold(vec: Vec<Baz>) -> Vec<[u64; 4]> {
95106
#[no_mangle]
96107
pub fn vec_iterator_cast_unwrap_drop(vec: Vec<Wrapper<String>>) -> Vec<String> {
97108
// CHECK-NOT: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
98-
// CHECK-NOT: call
99109
// CHECK-NOT: %{{.*}} = mul
100110
// CHECK-NOT: %{{.*}} = udiv
101111

@@ -106,7 +116,6 @@ pub fn vec_iterator_cast_unwrap_drop(vec: Vec<Wrapper<String>>) -> Vec<String> {
106116
#[no_mangle]
107117
pub fn vec_iterator_cast_wrap_drop(vec: Vec<String>) -> Vec<Wrapper<String>> {
108118
// CHECK-NOT: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
109-
// CHECK-NOT: call
110119
// CHECK-NOT: %{{.*}} = mul
111120
// CHECK-NOT: %{{.*}} = udiv
112121

Diff for: tests/codegen/vec_pop_push_noop.rs

-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ pub fn noop(v: &mut Vec<u8>) {
99
// CHECK-NOT: call
1010
// CHECK: tail call void @llvm.assume
1111
// CHECK-NOT: grow_one
12-
// CHECK-NOT: call
1312
// CHECK: ret
1413
if let Some(x) = v.pop() {
1514
v.push(x)

0 commit comments

Comments
 (0)