Skip to content

Commit e008e4f

Browse files
committed
Auto merge of #59632 - Centril:rollup, r=Centril
Rollup of 8 pull requests Successful merges: - #59262 (Remove duplicated code from Iterator::{ne, lt, le, gt, ge}) - #59286 (Refactor async fn return type lowering) - #59444 (Implement useful steps_between for all integers) - #59452 (Speed up rustdoc run a bit) - #59533 (Support allocating iterators with arenas) - #59585 (Fixes for shallow borrows) - #59607 (Renames `EvalErrorKind` to `InterpError`) - #59613 (SGX target: convert a bunch of panics to aborts) Failed merges: - #59630 (Shrink `mir::Statement`.) r? @ghost
2 parents f694222 + d0d3466 commit e008e4f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+982
-673
lines changed

Cargo.lock

+4-3
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ name = "arena"
5454
version = "0.0.0"
5555
dependencies = [
5656
"rustc_data_structures 0.0.0",
57+
"smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
5758
]
5859

5960
[[package]]
@@ -1520,7 +1521,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
15201521

15211522
[[package]]
15221523
name = "minifier"
1523-
version = "0.0.28"
1524+
version = "0.0.29"
15241525
source = "registry+https://github.com/rust-lang/crates.io-index"
15251526
dependencies = [
15261527
"macro-utils 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3039,7 +3040,7 @@ dependencies = [
30393040
name = "rustdoc"
30403041
version = "0.0.0"
30413042
dependencies = [
3042-
"minifier 0.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
3043+
"minifier 0.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
30433044
"parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
30443045
"pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
30453046
"tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -4149,7 +4150,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
41494150
"checksum memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0a3eb002f0535929f1199681417029ebea04aadc0c7a4224b46be99c7f5d6a16"
41504151
"checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff"
41514152
"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
4152-
"checksum minifier 0.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "3a2898502751dcc9d66b6fff57f3cf63cc91605e83e1a33515396f5027f8e4ca"
4153+
"checksum minifier 0.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1f4950cb2617b1933e2da0446e864dfe0d6a22c22ff72297996c46e6a63b210b"
41534154
"checksum miniz-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0300eafb20369952951699b68243ab4334f4b10a88f411c221d444b36c40e649"
41544155
"checksum miniz_oxide 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ad30a47319c16cde58d0314f5d98202a80c9083b5f61178457403dfb14e509c"
41554156
"checksum miniz_oxide_c_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "28edaef377517fd9fe3e085c37d892ce7acd1fbeab9239c5a36eec352d8a8b7e"

src/libarena/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ crate-type = ["dylib"]
1111

1212
[dependencies]
1313
rustc_data_structures = { path = "../librustc_data_structures" }
14+
smallvec = { version = "0.6.7", features = ["union", "may_dangle"] }

src/libarena/lib.rs

+139-16
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@
2323

2424
extern crate alloc;
2525

26+
use rustc_data_structures::cold_path;
2627
use rustc_data_structures::sync::MTLock;
28+
use smallvec::SmallVec;
2729

2830
use std::cell::{Cell, RefCell};
2931
use std::cmp;
@@ -55,13 +57,16 @@ pub struct TypedArena<T> {
5557
struct TypedArenaChunk<T> {
5658
/// The raw storage for the arena chunk.
5759
storage: RawVec<T>,
60+
/// The number of valid entries in the chunk.
61+
entries: usize,
5862
}
5963

6064
impl<T> TypedArenaChunk<T> {
6165
#[inline]
6266
unsafe fn new(capacity: usize) -> TypedArenaChunk<T> {
6367
TypedArenaChunk {
6468
storage: RawVec::with_capacity(capacity),
69+
entries: 0,
6570
}
6671
}
6772

@@ -149,6 +154,34 @@ impl<T> TypedArena<T> {
149154
}
150155
}
151156

157+
#[inline]
158+
fn can_allocate(&self, len: usize) -> bool {
159+
let available_capacity_bytes = self.end.get() as usize - self.ptr.get() as usize;
160+
let at_least_bytes = len.checked_mul(mem::size_of::<T>()).unwrap();
161+
available_capacity_bytes >= at_least_bytes
162+
}
163+
164+
/// Ensures there's enough space in the current chunk to fit `len` objects.
165+
#[inline]
166+
fn ensure_capacity(&self, len: usize) {
167+
if !self.can_allocate(len) {
168+
self.grow(len);
169+
debug_assert!(self.can_allocate(len));
170+
}
171+
}
172+
173+
#[inline]
174+
unsafe fn alloc_raw_slice(&self, len: usize) -> *mut T {
175+
assert!(mem::size_of::<T>() != 0);
176+
assert!(len != 0);
177+
178+
self.ensure_capacity(len);
179+
180+
let start_ptr = self.ptr.get();
181+
self.ptr.set(start_ptr.add(len));
182+
start_ptr
183+
}
184+
152185
/// Allocates a slice of objects that are copied into the `TypedArena`, returning a mutable
153186
/// reference to it. Will panic if passed a zero-sized types.
154187
///
@@ -161,21 +194,64 @@ impl<T> TypedArena<T> {
161194
where
162195
T: Copy,
163196
{
197+
unsafe {
198+
let len = slice.len();
199+
let start_ptr = self.alloc_raw_slice(len);
200+
slice.as_ptr().copy_to_nonoverlapping(start_ptr, len);
201+
slice::from_raw_parts_mut(start_ptr, len)
202+
}
203+
}
204+
205+
#[inline]
206+
pub fn alloc_from_iter<I: IntoIterator<Item = T>>(&self, iter: I) -> &mut [T] {
164207
assert!(mem::size_of::<T>() != 0);
165-
assert!(slice.len() != 0);
208+
let mut iter = iter.into_iter();
209+
let size_hint = iter.size_hint();
166210

167-
let available_capacity_bytes = self.end.get() as usize - self.ptr.get() as usize;
168-
let at_least_bytes = slice.len() * mem::size_of::<T>();
169-
if available_capacity_bytes < at_least_bytes {
170-
self.grow(slice.len());
171-
}
211+
match size_hint {
212+
(min, Some(max)) if min == max => {
213+
// We know the exact number of elements the iterator will produce here
214+
let len = min;
172215

173-
unsafe {
174-
let start_ptr = self.ptr.get();
175-
let arena_slice = slice::from_raw_parts_mut(start_ptr, slice.len());
176-
self.ptr.set(start_ptr.add(arena_slice.len()));
177-
arena_slice.copy_from_slice(slice);
178-
arena_slice
216+
if len == 0 {
217+
return &mut [];
218+
}
219+
220+
self.ensure_capacity(len);
221+
222+
let slice = self.ptr.get();
223+
224+
unsafe {
225+
let mut ptr = self.ptr.get();
226+
for _ in 0..len {
227+
// Write into uninitialized memory.
228+
ptr::write(ptr, iter.next().unwrap());
229+
// Advance the pointer.
230+
ptr = ptr.offset(1);
231+
// Update the pointer per iteration so if `iter.next()` panics
232+
// we destroy the correct amount
233+
self.ptr.set(ptr);
234+
}
235+
slice::from_raw_parts_mut(slice, len)
236+
}
237+
}
238+
_ => {
239+
cold_path(move || -> &mut [T] {
240+
let mut vec: SmallVec<[_; 8]> = iter.collect();
241+
if vec.is_empty() {
242+
return &mut [];
243+
}
244+
// Move the content to the arena by copying it and then forgetting
245+
// the content of the SmallVec
246+
unsafe {
247+
let len = vec.len();
248+
let start_ptr = self.alloc_raw_slice(len);
249+
vec.as_ptr().copy_to_nonoverlapping(start_ptr, len);
250+
vec.set_len(0);
251+
slice::from_raw_parts_mut(start_ptr, len)
252+
}
253+
})
254+
}
179255
}
180256
}
181257

@@ -189,6 +265,7 @@ impl<T> TypedArena<T> {
189265
if let Some(last_chunk) = chunks.last_mut() {
190266
let used_bytes = self.ptr.get() as usize - last_chunk.start() as usize;
191267
let currently_used_cap = used_bytes / mem::size_of::<T>();
268+
last_chunk.entries = currently_used_cap;
192269
if last_chunk.storage.reserve_in_place(currently_used_cap, n) {
193270
self.end.set(last_chunk.end());
194271
return;
@@ -222,8 +299,7 @@ impl<T> TypedArena<T> {
222299
let len = chunks_borrow.len();
223300
// If `T` is ZST, code below has no effect.
224301
for mut chunk in chunks_borrow.drain(..len-1) {
225-
let cap = chunk.storage.cap();
226-
chunk.destroy(cap);
302+
chunk.destroy(chunk.entries);
227303
}
228304
}
229305
}
@@ -265,8 +341,7 @@ unsafe impl<#[may_dangle] T> Drop for TypedArena<T> {
265341
self.clear_last_chunk(&mut last_chunk);
266342
// The last chunk will be dropped. Destroy all other chunks.
267343
for chunk in chunks_borrow.iter_mut() {
268-
let cap = chunk.storage.cap();
269-
chunk.destroy(cap);
344+
chunk.destroy(chunk.entries);
270345
}
271346
}
272347
// RawVec handles deallocation of `last_chunk` and `self.chunks`.
@@ -410,6 +485,54 @@ impl DroplessArena {
410485
arena_slice
411486
}
412487
}
488+
489+
#[inline]
490+
pub fn alloc_from_iter<T, I: IntoIterator<Item = T>>(&self, iter: I) -> &mut [T] {
491+
let mut iter = iter.into_iter();
492+
assert!(mem::size_of::<T>() != 0);
493+
assert!(!mem::needs_drop::<T>());
494+
495+
let size_hint = iter.size_hint();
496+
497+
match size_hint {
498+
(min, Some(max)) if min == max => {
499+
// We know the exact number of elements the iterator will produce here
500+
let len = min;
501+
502+
if len == 0 {
503+
return &mut []
504+
}
505+
let size = len.checked_mul(mem::size_of::<T>()).unwrap();
506+
let mem = self.alloc_raw(size, mem::align_of::<T>()) as *mut _ as *mut T;
507+
unsafe {
508+
for i in 0..len {
509+
ptr::write(mem.offset(i as isize), iter.next().unwrap())
510+
}
511+
slice::from_raw_parts_mut(mem, len)
512+
}
513+
}
514+
(_, _) => {
515+
cold_path(move || -> &mut [T] {
516+
let mut vec: SmallVec<[_; 8]> = iter.collect();
517+
if vec.is_empty() {
518+
return &mut [];
519+
}
520+
// Move the content to the arena by copying it and then forgetting
521+
// the content of the SmallVec
522+
unsafe {
523+
let len = vec.len();
524+
let start_ptr = self.alloc_raw(
525+
len * mem::size_of::<T>(),
526+
mem::align_of::<T>()
527+
) as *mut _ as *mut T;
528+
vec.as_ptr().copy_to_nonoverlapping(start_ptr, len);
529+
vec.set_len(0);
530+
slice::from_raw_parts_mut(start_ptr, len)
531+
}
532+
})
533+
}
534+
}
535+
}
413536
}
414537

415538
#[derive(Default)]

src/libcore/benches/iter.rs

+10
Original file line numberDiff line numberDiff line change
@@ -334,3 +334,13 @@ fn bench_filter_chain_ref_count(b: &mut Bencher) {
334334
(0i64..1000000).chain(0..1000000).map(black_box).by_ref().filter(|x| x % 3 == 0).count()
335335
})
336336
}
337+
338+
#[bench]
339+
fn bench_partial_cmp(b: &mut Bencher) {
340+
b.iter(|| (0..100000).map(black_box).partial_cmp((0..100000).map(black_box)))
341+
}
342+
343+
#[bench]
344+
fn bench_lt(b: &mut Bencher) {
345+
b.iter(|| (0..100000).map(black_box).lt((0..100000).map(black_box)))
346+
}

src/libcore/iter/range.rs

+10-51
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,9 @@ macro_rules! step_impl_unsigned {
6868
issue = "42168")]
6969
impl Step for $t {
7070
#[inline]
71-
#[allow(trivial_numeric_casts)]
7271
fn steps_between(start: &$t, end: &$t) -> Option<usize> {
7372
if *start < *end {
74-
// Note: We assume $t <= usize here
75-
Some((*end - *start) as usize)
73+
usize::try_from(*end - *start).ok()
7674
} else {
7775
Some(0)
7876
}
@@ -98,13 +96,11 @@ macro_rules! step_impl_signed {
9896
issue = "42168")]
9997
impl Step for $t {
10098
#[inline]
101-
#[allow(trivial_numeric_casts)]
10299
fn steps_between(start: &$t, end: &$t) -> Option<usize> {
103100
if *start < *end {
104-
// Note: We assume $t <= isize here
105-
// Use .wrapping_sub and cast to usize to compute the
106-
// difference that may not fit inside the range of isize.
107-
Some((*end as isize).wrapping_sub(*start as isize) as usize)
101+
// Use .wrapping_sub and cast to unsigned to compute the
102+
// difference that may not fit inside the range of $t.
103+
usize::try_from(end.wrapping_sub(*start) as $unsigned).ok()
108104
} else {
109105
Some(0)
110106
}
@@ -134,46 +130,9 @@ macro_rules! step_impl_signed {
134130
)*)
135131
}
136132

137-
macro_rules! step_impl_no_between {
138-
($($t:ty)*) => ($(
139-
#[unstable(feature = "step_trait",
140-
reason = "likely to be replaced by finer-grained traits",
141-
issue = "42168")]
142-
impl Step for $t {
143-
#[inline]
144-
fn steps_between(_start: &Self, _end: &Self) -> Option<usize> {
145-
None
146-
}
147-
148-
#[inline]
149-
fn add_usize(&self, n: usize) -> Option<Self> {
150-
self.checked_add(n as $t)
151-
}
152-
153-
step_identical_methods!();
154-
}
155-
)*)
156-
}
157-
158-
step_impl_unsigned!(usize u8 u16);
159-
#[cfg(not(target_pointer_width = "16"))]
160-
step_impl_unsigned!(u32);
161-
#[cfg(target_pointer_width = "16")]
162-
step_impl_no_between!(u32);
133+
step_impl_unsigned!(usize u8 u16 u32 u64 u128);
163134
step_impl_signed!([isize: usize] [i8: u8] [i16: u16]);
164-
#[cfg(not(target_pointer_width = "16"))]
165-
step_impl_signed!([i32: u32]);
166-
#[cfg(target_pointer_width = "16")]
167-
step_impl_no_between!(i32);
168-
#[cfg(target_pointer_width = "64")]
169-
step_impl_unsigned!(u64);
170-
#[cfg(target_pointer_width = "64")]
171-
step_impl_signed!([i64: u64]);
172-
// If the target pointer width is not 64-bits, we
173-
// assume here that it is less than 64-bits.
174-
#[cfg(not(target_pointer_width = "64"))]
175-
step_impl_no_between!(u64 i64);
176-
step_impl_no_between!(u128 i128);
135+
step_impl_signed!([i32: u32] [i64: u64] [i128: u128]);
177136

178137
macro_rules! range_exact_iter_impl {
179138
($($t:ty)*) => ($(
@@ -229,7 +188,7 @@ impl<A: Step> Iterator for ops::Range<A> {
229188
fn size_hint(&self) -> (usize, Option<usize>) {
230189
match Step::steps_between(&self.start, &self.end) {
231190
Some(hint) => (hint, Some(hint)),
232-
None => (0, None)
191+
None => (usize::MAX, None)
233192
}
234193
}
235194

@@ -273,8 +232,8 @@ range_incl_exact_iter_impl!(u8 u16 i8 i16);
273232
//
274233
// They need to guarantee that .size_hint() is either exact, or that
275234
// the upper bound is None when it does not fit the type limits.
276-
range_trusted_len_impl!(usize isize u8 i8 u16 i16 u32 i32 i64 u64);
277-
range_incl_trusted_len_impl!(usize isize u8 i8 u16 i16 u32 i32 i64 u64);
235+
range_trusted_len_impl!(usize isize u8 i8 u16 i16 u32 i32 u64 i64 u128 i128);
236+
range_incl_trusted_len_impl!(usize isize u8 i8 u16 i16 u32 i32 u64 i64 u128 i128);
278237

279238
#[stable(feature = "rust1", since = "1.0.0")]
280239
impl<A: Step> DoubleEndedIterator for ops::Range<A> {
@@ -350,7 +309,7 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> {
350309

351310
match Step::steps_between(&self.start, &self.end) {
352311
Some(hint) => (hint.saturating_add(1), hint.checked_add(1)),
353-
None => (0, None),
312+
None => (usize::MAX, None),
354313
}
355314
}
356315

0 commit comments

Comments
 (0)