Merge from rustc
This commit is contained in:
commit
d1a2425333
124 changed files with 2460 additions and 805 deletions
|
|
@ -1,4 +1,8 @@
|
|||
use std::collections::VecDeque;
|
||||
use core::iter::Iterator;
|
||||
use std::{
|
||||
collections::{vec_deque, VecDeque},
|
||||
mem,
|
||||
};
|
||||
use test::{black_box, Bencher};
|
||||
|
||||
#[bench]
|
||||
|
|
@ -53,6 +57,146 @@ fn bench_try_fold(b: &mut Bencher) {
|
|||
b.iter(|| black_box(ring.iter().try_fold(0, |a, b| Some(a + b))))
|
||||
}
|
||||
|
||||
/// does the memory bookkeeping to reuse the buffer of the Vec between iterations.
|
||||
/// `setup` must not modify its argument's length or capacity. `g` must not move out of its argument.
|
||||
fn into_iter_helper<
|
||||
T: Copy,
|
||||
F: FnOnce(&mut VecDeque<T>),
|
||||
G: FnOnce(&mut vec_deque::IntoIter<T>),
|
||||
>(
|
||||
v: &mut Vec<T>,
|
||||
setup: F,
|
||||
g: G,
|
||||
) {
|
||||
let ptr = v.as_mut_ptr();
|
||||
let len = v.len();
|
||||
// ensure that the vec is full, to make sure that any wrapping from the deque doesn't
|
||||
// access uninitialized memory.
|
||||
assert_eq!(v.len(), v.capacity());
|
||||
|
||||
let mut deque = VecDeque::from(mem::take(v));
|
||||
setup(&mut deque);
|
||||
|
||||
let mut it = deque.into_iter();
|
||||
g(&mut it);
|
||||
|
||||
mem::forget(it);
|
||||
|
||||
// SAFETY: the provided functions are not allowed to modify the allocation, so the buffer is still alive.
|
||||
// len and capacity are accurate due to the above assertion.
|
||||
// All the elements in the buffer are still valid, because of `T: Copy` which implies `T: !Drop`.
|
||||
mem::forget(mem::replace(v, unsafe { Vec::from_raw_parts(ptr, len, len) }));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_into_iter(b: &mut Bencher) {
|
||||
let len = 1024;
|
||||
// we reuse this allocation for every run
|
||||
let mut vec: Vec<usize> = (0..len).collect();
|
||||
vec.shrink_to_fit();
|
||||
|
||||
b.iter(|| {
|
||||
let mut sum = 0;
|
||||
into_iter_helper(
|
||||
&mut vec,
|
||||
|_| {},
|
||||
|it| {
|
||||
for i in it {
|
||||
sum += i;
|
||||
}
|
||||
},
|
||||
);
|
||||
black_box(sum);
|
||||
|
||||
let mut sum = 0;
|
||||
// rotating a full deque doesn't move any memory.
|
||||
into_iter_helper(
|
||||
&mut vec,
|
||||
|d| d.rotate_left(len / 2),
|
||||
|it| {
|
||||
for i in it {
|
||||
sum += i;
|
||||
}
|
||||
},
|
||||
);
|
||||
black_box(sum);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_into_iter_fold(b: &mut Bencher) {
|
||||
let len = 1024;
|
||||
|
||||
// because `fold` takes ownership of the iterator,
|
||||
// we can't prevent it from dropping the memory,
|
||||
// so we have to bite the bullet and reallocate
|
||||
// for every iteration.
|
||||
b.iter(|| {
|
||||
let deque: VecDeque<usize> = (0..len).collect();
|
||||
assert_eq!(deque.len(), deque.capacity());
|
||||
let sum = deque.into_iter().fold(0, |a, b| a + b);
|
||||
black_box(sum);
|
||||
|
||||
// rotating a full deque doesn't move any memory.
|
||||
let mut deque: VecDeque<usize> = (0..len).collect();
|
||||
assert_eq!(deque.len(), deque.capacity());
|
||||
deque.rotate_left(len / 2);
|
||||
let sum = deque.into_iter().fold(0, |a, b| a + b);
|
||||
black_box(sum);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_into_iter_try_fold(b: &mut Bencher) {
|
||||
let len = 1024;
|
||||
// we reuse this allocation for every run
|
||||
let mut vec: Vec<usize> = (0..len).collect();
|
||||
vec.shrink_to_fit();
|
||||
|
||||
// Iterator::any uses Iterator::try_fold under the hood
|
||||
b.iter(|| {
|
||||
let mut b = false;
|
||||
into_iter_helper(&mut vec, |_| {}, |it| b = it.any(|i| i == len - 1));
|
||||
black_box(b);
|
||||
|
||||
into_iter_helper(&mut vec, |d| d.rotate_left(len / 2), |it| b = it.any(|i| i == len - 1));
|
||||
black_box(b);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_into_iter_next_chunk(b: &mut Bencher) {
|
||||
let len = 1024;
|
||||
// we reuse this allocation for every run
|
||||
let mut vec: Vec<usize> = (0..len).collect();
|
||||
vec.shrink_to_fit();
|
||||
|
||||
b.iter(|| {
|
||||
let mut buf = [0; 64];
|
||||
into_iter_helper(
|
||||
&mut vec,
|
||||
|_| {},
|
||||
|it| {
|
||||
while let Ok(a) = it.next_chunk() {
|
||||
buf = a;
|
||||
}
|
||||
},
|
||||
);
|
||||
black_box(buf);
|
||||
|
||||
into_iter_helper(
|
||||
&mut vec,
|
||||
|d| d.rotate_left(len / 2),
|
||||
|it| {
|
||||
while let Ok(a) = it.next_chunk() {
|
||||
buf = a;
|
||||
}
|
||||
},
|
||||
);
|
||||
black_box(buf);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_from_array_1000(b: &mut Bencher) {
|
||||
const N: usize = 1000;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use core::fmt;
|
||||
use core::iter::{FusedIterator, TrustedLen};
|
||||
use core::{array, fmt, mem::MaybeUninit, ops::Try, ptr};
|
||||
|
||||
use crate::alloc::{Allocator, Global};
|
||||
|
||||
|
|
@ -52,6 +52,126 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
|
|||
let len = self.inner.len();
|
||||
(len, Some(len))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
if self.inner.len < n {
|
||||
let len = self.inner.len;
|
||||
self.inner.clear();
|
||||
Err(len)
|
||||
} else {
|
||||
self.inner.drain(..n);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn count(self) -> usize {
|
||||
self.inner.len
|
||||
}
|
||||
|
||||
fn try_fold<B, F, R>(&mut self, mut init: B, mut f: F) -> R
|
||||
where
|
||||
F: FnMut(B, Self::Item) -> R,
|
||||
R: Try<Output = B>,
|
||||
{
|
||||
struct Guard<'a, T, A: Allocator> {
|
||||
deque: &'a mut VecDeque<T, A>,
|
||||
// `consumed <= deque.len` always holds.
|
||||
consumed: usize,
|
||||
}
|
||||
|
||||
impl<'a, T, A: Allocator> Drop for Guard<'a, T, A> {
|
||||
fn drop(&mut self) {
|
||||
self.deque.len -= self.consumed;
|
||||
self.deque.head = self.deque.to_physical_idx(self.consumed);
|
||||
}
|
||||
}
|
||||
|
||||
let mut guard = Guard { deque: &mut self.inner, consumed: 0 };
|
||||
|
||||
let (head, tail) = guard.deque.as_slices();
|
||||
|
||||
init = head
|
||||
.iter()
|
||||
.map(|elem| {
|
||||
guard.consumed += 1;
|
||||
// SAFETY: Because we incremented `guard.consumed`, the
|
||||
// deque effectively forgot the element, so we can take
|
||||
// ownership
|
||||
unsafe { ptr::read(elem) }
|
||||
})
|
||||
.try_fold(init, &mut f)?;
|
||||
|
||||
tail.iter()
|
||||
.map(|elem| {
|
||||
guard.consumed += 1;
|
||||
// SAFETY: Same as above.
|
||||
unsafe { ptr::read(elem) }
|
||||
})
|
||||
.try_fold(init, &mut f)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn fold<B, F>(mut self, init: B, mut f: F) -> B
|
||||
where
|
||||
F: FnMut(B, Self::Item) -> B,
|
||||
{
|
||||
match self.try_fold(init, |b, item| Ok::<B, !>(f(b, item))) {
|
||||
Ok(b) => b,
|
||||
Err(e) => match e {},
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn last(mut self) -> Option<Self::Item> {
|
||||
self.inner.pop_back()
|
||||
}
|
||||
|
||||
fn next_chunk<const N: usize>(
|
||||
&mut self,
|
||||
) -> Result<[Self::Item; N], array::IntoIter<Self::Item, N>> {
|
||||
let mut raw_arr = MaybeUninit::uninit_array();
|
||||
let raw_arr_ptr = raw_arr.as_mut_ptr().cast();
|
||||
let (head, tail) = self.inner.as_slices();
|
||||
|
||||
if head.len() >= N {
|
||||
// SAFETY: By manually adjusting the head and length of the deque, we effectively
|
||||
// make it forget the first `N` elements, so taking ownership of them is safe.
|
||||
unsafe { ptr::copy_nonoverlapping(head.as_ptr(), raw_arr_ptr, N) };
|
||||
self.inner.head = self.inner.to_physical_idx(N);
|
||||
self.inner.len -= N;
|
||||
// SAFETY: We initialized the entire array with items from `head`
|
||||
return Ok(unsafe { raw_arr.transpose().assume_init() });
|
||||
}
|
||||
|
||||
// SAFETY: Same argument as above.
|
||||
unsafe { ptr::copy_nonoverlapping(head.as_ptr(), raw_arr_ptr, head.len()) };
|
||||
let remaining = N - head.len();
|
||||
|
||||
if tail.len() >= remaining {
|
||||
// SAFETY: Same argument as above.
|
||||
unsafe {
|
||||
ptr::copy_nonoverlapping(tail.as_ptr(), raw_arr_ptr.add(head.len()), remaining)
|
||||
};
|
||||
self.inner.head = self.inner.to_physical_idx(N);
|
||||
self.inner.len -= N;
|
||||
// SAFETY: We initialized the entire array with items from `head` and `tail`
|
||||
Ok(unsafe { raw_arr.transpose().assume_init() })
|
||||
} else {
|
||||
// SAFETY: Same argument as above.
|
||||
unsafe {
|
||||
ptr::copy_nonoverlapping(tail.as_ptr(), raw_arr_ptr.add(head.len()), tail.len())
|
||||
};
|
||||
let init = head.len() + tail.len();
|
||||
// We completely drained all the deques elements.
|
||||
self.inner.head = 0;
|
||||
self.inner.len = 0;
|
||||
// SAFETY: We copied all elements from both slices to the beginning of the array, so
|
||||
// the given range is initialized.
|
||||
Err(unsafe { array::IntoIter::new_unchecked(raw_arr, 0..init) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
|
@ -60,10 +180,73 @@ impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> {
|
|||
fn next_back(&mut self) -> Option<T> {
|
||||
self.inner.pop_back()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
let len = self.inner.len;
|
||||
if len >= n {
|
||||
self.inner.truncate(len - n);
|
||||
Ok(())
|
||||
} else {
|
||||
self.inner.clear();
|
||||
Err(len)
|
||||
}
|
||||
}
|
||||
|
||||
fn try_rfold<B, F, R>(&mut self, mut init: B, mut f: F) -> R
|
||||
where
|
||||
F: FnMut(B, Self::Item) -> R,
|
||||
R: Try<Output = B>,
|
||||
{
|
||||
struct Guard<'a, T, A: Allocator> {
|
||||
deque: &'a mut VecDeque<T, A>,
|
||||
// `consumed <= deque.len` always holds.
|
||||
consumed: usize,
|
||||
}
|
||||
|
||||
impl<'a, T, A: Allocator> Drop for Guard<'a, T, A> {
|
||||
fn drop(&mut self) {
|
||||
self.deque.len -= self.consumed;
|
||||
}
|
||||
}
|
||||
|
||||
let mut guard = Guard { deque: &mut self.inner, consumed: 0 };
|
||||
|
||||
let (head, tail) = guard.deque.as_slices();
|
||||
|
||||
init = tail
|
||||
.iter()
|
||||
.map(|elem| {
|
||||
guard.consumed += 1;
|
||||
// SAFETY: See `try_fold`'s safety comment.
|
||||
unsafe { ptr::read(elem) }
|
||||
})
|
||||
.try_rfold(init, &mut f)?;
|
||||
|
||||
head.iter()
|
||||
.map(|elem| {
|
||||
guard.consumed += 1;
|
||||
// SAFETY: Same as above.
|
||||
unsafe { ptr::read(elem) }
|
||||
})
|
||||
.try_rfold(init, &mut f)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rfold<B, F>(mut self, init: B, mut f: F) -> B
|
||||
where
|
||||
F: FnMut(B, Self::Item) -> B,
|
||||
{
|
||||
match self.try_rfold(init, |b, item| Ok::<B, !>(f(b, item))) {
|
||||
Ok(b) => b,
|
||||
Err(e) => match e {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T, A: Allocator> ExactSizeIterator for IntoIter<T, A> {
|
||||
#[inline]
|
||||
fn is_empty(&self) -> bool {
|
||||
self.inner.is_empty()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -525,8 +525,6 @@ impl<T, E> Result<T, E> {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// let x: Result<i32, &str> = Ok(-3);
|
||||
/// assert_eq!(x.is_ok(), true);
|
||||
|
|
@ -572,8 +570,6 @@ impl<T, E> Result<T, E> {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// let x: Result<i32, &str> = Ok(-3);
|
||||
/// assert_eq!(x.is_err(), false);
|
||||
|
|
@ -627,8 +623,6 @@ impl<T, E> Result<T, E> {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// let x: Result<u32, &str> = Ok(2);
|
||||
/// assert_eq!(x.ok(), Some(2));
|
||||
|
|
@ -658,8 +652,6 @@ impl<T, E> Result<T, E> {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// let x: Result<u32, &str> = Ok(2);
|
||||
/// assert_eq!(x.err(), None);
|
||||
|
|
@ -693,8 +685,6 @@ impl<T, E> Result<T, E> {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// let x: Result<u32, &str> = Ok(2);
|
||||
/// assert_eq!(x.as_ref(), Ok(&2));
|
||||
|
|
@ -716,8 +706,6 @@ impl<T, E> Result<T, E> {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// fn mutate(r: &mut Result<i32, i32>) {
|
||||
/// match r.as_mut() {
|
||||
|
|
@ -812,8 +800,6 @@ impl<T, E> Result<T, E> {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// let k = 21;
|
||||
///
|
||||
|
|
@ -841,8 +827,6 @@ impl<T, E> Result<T, E> {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// fn stringify(x: u32) -> String { format!("error code: {x}") }
|
||||
///
|
||||
|
|
@ -968,8 +952,6 @@ impl<T, E> Result<T, E> {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// let x: Result<u32, &str> = Ok(7);
|
||||
/// assert_eq!(x.iter().next(), Some(&7));
|
||||
|
|
@ -989,8 +971,6 @@ impl<T, E> Result<T, E> {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// let mut x: Result<u32, &str> = Ok(7);
|
||||
/// match x.iter_mut().next() {
|
||||
|
|
@ -1031,8 +1011,6 @@ impl<T, E> Result<T, E> {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// let x: Result<u32, &str> = Err("emergency failure");
|
||||
/// x.expect("Testing expect"); // panics with `Testing expect: emergency failure`
|
||||
|
|
@ -1160,8 +1138,6 @@ impl<T, E> Result<T, E> {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// let x: Result<u32, &str> = Ok(10);
|
||||
/// x.expect_err("Testing expect_err"); // panics with `Testing expect_err: 10`
|
||||
|
|
@ -1222,8 +1198,6 @@ impl<T, E> Result<T, E> {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(never_type)]
|
||||
/// # #![feature(unwrap_infallible)]
|
||||
|
|
@ -1259,8 +1233,6 @@ impl<T, E> Result<T, E> {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(never_type)]
|
||||
/// # #![feature(unwrap_infallible)]
|
||||
|
|
@ -1298,8 +1270,6 @@ impl<T, E> Result<T, E> {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// let x: Result<u32, &str> = Ok(2);
|
||||
/// let y: Result<&str, &str> = Err("late error");
|
||||
|
|
@ -1383,8 +1353,6 @@ impl<T, E> Result<T, E> {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// let x: Result<u32, &str> = Ok(2);
|
||||
/// let y: Result<u32, &str> = Err("late error");
|
||||
|
|
@ -1426,8 +1394,6 @@ impl<T, E> Result<T, E> {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// fn sq(x: u32) -> Result<u32, u32> { Ok(x * x) }
|
||||
/// fn err(x: u32) -> Result<u32, u32> { Err(x) }
|
||||
|
|
@ -1456,8 +1422,6 @@ impl<T, E> Result<T, E> {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// let default = 2;
|
||||
/// let x: Result<u32, &str> = Ok(9);
|
||||
|
|
@ -1487,8 +1451,6 @@ impl<T, E> Result<T, E> {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// fn count(x: &str) -> usize { x.len() }
|
||||
///
|
||||
|
|
@ -1752,8 +1714,6 @@ impl<T, E> Result<Result<T, E>, E> {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(result_flattening)]
|
||||
/// let x: Result<Result<&'static str, u32>, u32> = Ok(Ok("hello"));
|
||||
|
|
@ -1842,8 +1802,6 @@ impl<T, E> IntoIterator for Result<T, E> {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// let x: Result<u32, &str> = Ok(5);
|
||||
/// let v: Vec<u32> = x.into_iter().collect();
|
||||
|
|
|
|||
|
|
@ -2730,8 +2730,10 @@ impl<T> [T] {
|
|||
/// This reordering has the additional property that any value at position `i < index` will be
|
||||
/// less than or equal to any value at a position `j > index`. Additionally, this reordering is
|
||||
/// unstable (i.e. any number of equal elements may end up at position `index`), in-place
|
||||
/// (i.e. does not allocate), and *O*(*n*) worst-case. This function is also/ known as "kth
|
||||
/// element" in other libraries. It returns a triplet of the following from the reordered slice:
|
||||
/// (i.e. does not allocate), and *O*(*n*) on average. The worst-case performance is *O*(*n* log *n*).
|
||||
/// This function is also known as "kth element" in other libraries.
|
||||
///
|
||||
/// It returns a triplet of the following from the reordered slice:
|
||||
/// the subslice prior to `index`, the element at `index`, and the subslice after `index`;
|
||||
/// accordingly, the values in those two subslices will respectively all be less-than-or-equal-to
|
||||
/// and greater-than-or-equal-to the value of the element at `index`.
|
||||
|
|
@ -2777,8 +2779,11 @@ impl<T> [T] {
|
|||
/// This reordering has the additional property that any value at position `i < index` will be
|
||||
/// less than or equal to any value at a position `j > index` using the comparator function.
|
||||
/// Additionally, this reordering is unstable (i.e. any number of equal elements may end up at
|
||||
/// position `index`), in-place (i.e. does not allocate), and *O*(*n*) worst-case. This function
|
||||
/// is also known as "kth element" in other libraries. It returns a triplet of the following from
|
||||
/// position `index`), in-place (i.e. does not allocate), and *O*(*n*) on average.
|
||||
/// The worst-case performance is *O*(*n* log *n*). This function is also known as
|
||||
/// "kth element" in other libraries.
|
||||
///
|
||||
/// It returns a triplet of the following from
|
||||
/// the slice reordered according to the provided comparator function: the subslice prior to
|
||||
/// `index`, the element at `index`, and the subslice after `index`; accordingly, the values in
|
||||
/// those two subslices will respectively all be less-than-or-equal-to and greater-than-or-equal-to
|
||||
|
|
@ -2829,8 +2834,11 @@ impl<T> [T] {
|
|||
/// This reordering has the additional property that any value at position `i < index` will be
|
||||
/// less than or equal to any value at a position `j > index` using the key extraction function.
|
||||
/// Additionally, this reordering is unstable (i.e. any number of equal elements may end up at
|
||||
/// position `index`), in-place (i.e. does not allocate), and *O*(*n*) worst-case. This function
|
||||
/// is also known as "kth element" in other libraries. It returns a triplet of the following from
|
||||
/// position `index`), in-place (i.e. does not allocate), and *O*(*n*) on average.
|
||||
/// The worst-case performance is *O*(*n* log *n*).
|
||||
/// This function is also known as "kth element" in other libraries.
|
||||
///
|
||||
/// It returns a triplet of the following from
|
||||
/// the slice reordered according to the provided key extraction function: the subslice prior to
|
||||
/// `index`, the element at `index`, and the subslice after `index`; accordingly, the values in
|
||||
/// those two subslices will respectively all be less-than-or-equal-to and greater-than-or-equal-to
|
||||
|
|
|
|||
|
|
@ -284,6 +284,10 @@ impl<'a> Read for &'a FileDesc {
|
|||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
(**self).read(buf)
|
||||
}
|
||||
|
||||
fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
|
||||
(**self).read_buf(cursor)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsInner<OwnedFd> for FileDesc {
|
||||
|
|
|
|||
|
|
@ -124,8 +124,10 @@
|
|||
//!
|
||||
//! ## Stack size
|
||||
//!
|
||||
//! The default stack size is platform-dependent and subject to change. Currently it is 2MB on all
|
||||
//! Tier-1 platforms. There are two ways to manually specify the stack size for spawned threads:
|
||||
//! The default stack size is platform-dependent and subject to change.
|
||||
//! Currently, it is 2 MiB on all Tier-1 platforms.
|
||||
//!
|
||||
//! There are two ways to manually specify the stack size for spawned threads:
|
||||
//!
|
||||
//! * Build the thread with [`Builder`] and pass the desired stack size to [`Builder::stack_size`].
|
||||
//! * Set the `RUST_MIN_STACK` environment variable to an integer representing the desired stack
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue