Skip to content

Commit 04df1c0

Browse files
committed
Auto merge of rust-lang#81113 - m-ou-se:rollup-a1unz4x, r=m-ou-se
Rollup of 13 pull requests Successful merges: - rust-lang#79298 (correctly deal with late-bound lifetimes in anon consts) - rust-lang#80031 (resolve: Reject ambiguity built-in attr vs different built-in attr) - rust-lang#80201 (Add benchmark and fast path for BufReader::read_exact) - rust-lang#80635 (Improve diagnostics when closure doesn't meet trait bound) - rust-lang#80765 (resolve: Simplify collection of traits in scope) - rust-lang#80932 (Allow downloading LLVM on Windows and MacOS) - rust-lang#80983 (Remove is_dllimport_foreign_item definition from cg_ssa) - rust-lang#81064 (Support non-stage0 check) - rust-lang#81080 (Force vec![] to expression position only) - rust-lang#81082 (BTreeMap: clean up a few more comments) - rust-lang#81084 (Use Option::map instead of open-coding it) - rust-lang#81095 (Use Option::unwrap_or instead of open-coding it) - rust-lang#81107 (Add NonZeroUn::is_power_of_two) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 25479f9 + c066c77 commit 04df1c0

File tree

8 files changed

+107
-27
lines changed

8 files changed

+107
-27
lines changed

alloc/src/collections/btree/node.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ impl<K, V> NodeRef<marker::Owned, K, V, marker::LeafOrInternal> {
184184

185185
/// Removes the internal root node, using its first child as the new root node.
186186
/// As it is intended only to be called when the root node has only one child,
187-
/// no cleanup is done on any of the other children.
187+
/// no cleanup is done on any of the keys, values and other children.
188188
/// This decreases the height by 1 and is the opposite of `push_internal_level`.
189189
///
190190
/// Requires exclusive access to the `Root` object but not to the root node;
@@ -225,7 +225,7 @@ impl<K, V> NodeRef<marker::Owned, K, V, marker::LeafOrInternal> {
225225
/// - When this is `Owned`, the `NodeRef` acts roughly like `Box<Node>`,
226226
/// but does not have a destructor, and must be cleaned up manually.
227227
/// Since any `NodeRef` allows navigating through the tree, `BorrowType`
228-
/// effectively applies to the entire tree, not just the node itself.
228+
/// effectively applies to the entire tree, not just to the node itself.
229229
/// - `K` and `V`: These are the types of keys and values stored in the nodes.
230230
/// - `Type`: This can be `Leaf`, `Internal`, or `LeafOrInternal`. When this is
231231
/// `Leaf`, the `NodeRef` points to a leaf node, when this is `Internal` the
@@ -425,7 +425,7 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Immut<'a>, K, V, Type> {
425425

426426
impl<K, V> NodeRef<marker::Owned, K, V, marker::LeafOrInternal> {
427427
/// Similar to `ascend`, gets a reference to a node's parent node, but also
428-
/// deallocate the current node in the process. This is unsafe because the
428+
/// deallocates the current node in the process. This is unsafe because the
429429
/// current node will still be accessible despite being deallocated.
430430
pub unsafe fn deallocate_and_ascend(
431431
self,
@@ -661,7 +661,10 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal> {
661661
/// Removes a key-value pair from the end of the node and returns the pair.
662662
/// Also removes the edge that was to the right of that pair and, if the node
663663
/// is internal, returns the orphaned subtree that this edge owned.
664-
fn pop(&mut self) -> (K, V, Option<Root<K, V>>) {
664+
///
665+
/// # Safety
666+
/// The node must not be empty.
667+
unsafe fn pop(&mut self) -> (K, V, Option<Root<K, V>>) {
665668
debug_assert!(self.len() > 0);
666669

667670
let idx = self.len() - 1;

alloc/src/collections/btree/search.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@ pub enum SearchResult<BorrowType, K, V, FoundType, GoDownType> {
1212

1313
/// Looks up a given key in a (sub)tree headed by the given node, recursively.
1414
/// Returns a `Found` with the handle of the matching KV, if any. Otherwise,
15-
/// returns a `GoDown` with the handle of the possible leaf edge where the key
16-
/// belongs.
15+
/// returns a `GoDown` with the handle of the leaf edge where the key belongs.
1716
///
1817
/// The result is meaningful only if the tree is ordered by key, like the tree
1918
/// in a `BTreeMap` is.

alloc/src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@
140140
#![feature(type_alias_impl_trait)]
141141
#![feature(associated_type_bounds)]
142142
#![feature(slice_group_by)]
143+
#![feature(decl_macro)]
143144
// Allow testing this library
144145

145146
#[cfg(test)]
@@ -193,4 +194,11 @@ mod std {
193194
#[unstable(feature = "liballoc_internals", issue = "none", reason = "implementation detail")]
194195
pub mod __export {
195196
pub use core::format_args;
197+
198+
/// Force AST node to an expression to improve diagnostics in pattern position.
199+
#[rustc_macro_transparency = "semitransparent"]
200+
#[unstable(feature = "liballoc_internals", issue = "none", reason = "implementation detail")]
201+
pub macro force_expr($e:expr) {
202+
$e
203+
}
196204
}

alloc/src/macros.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,16 @@
3737
#[cfg(not(test))]
3838
#[macro_export]
3939
#[stable(feature = "rust1", since = "1.0.0")]
40-
#[allow_internal_unstable(box_syntax)]
40+
#[allow_internal_unstable(box_syntax, liballoc_internals)]
4141
macro_rules! vec {
4242
() => (
43-
$crate::vec::Vec::new()
43+
$crate::__export::force_expr!($crate::vec::Vec::new())
4444
);
4545
($elem:expr; $n:expr) => (
46-
$crate::vec::from_elem($elem, $n)
46+
$crate::__export::force_expr!($crate::vec::from_elem($elem, $n))
4747
);
4848
($($x:expr),+ $(,)?) => (
49-
<[_]>::into_vec(box [$($x),+])
49+
$crate::__export::force_expr!(<[_]>::into_vec(box [$($x),+]))
5050
);
5151
}
5252

core/src/num/nonzero.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,3 +286,43 @@ nonzero_integers_div! {
286286
NonZeroU128(u128);
287287
NonZeroUsize(usize);
288288
}
289+
290+
macro_rules! nonzero_unsigned_is_power_of_two {
291+
( $( $Ty: ident )+ ) => {
292+
$(
293+
impl $Ty {
294+
295+
/// Returns `true` if and only if `self == (1 << k)` for some `k`.
296+
///
297+
/// On many architectures, this function can perform better than `is_power_of_two()`
298+
/// on the underlying integer type, as special handling of zero can be avoided.
299+
///
300+
/// # Examples
301+
///
302+
/// Basic usage:
303+
///
304+
/// ```
305+
/// #![feature(nonzero_is_power_of_two)]
306+
///
307+
#[doc = concat!("let eight = std::num::", stringify!($Ty), "::new(8).unwrap();")]
308+
/// assert!(eight.is_power_of_two());
309+
#[doc = concat!("let ten = std::num::", stringify!($Ty), "::new(10).unwrap();")]
310+
/// assert!(!ten.is_power_of_two());
311+
/// ```
312+
#[unstable(feature = "nonzero_is_power_of_two", issue = "81106")]
313+
#[inline]
314+
pub const fn is_power_of_two(self) -> bool {
315+
// LLVM 11 normalizes `unchecked_sub(x, 1) & x == 0` to the implementation seen here.
316+
// On the basic x86-64 target, this saves 3 instructions for the zero check.
317+
// On x86_64 with BMI1, being nonzero lets it codegen to `BLSR`, which saves an instruction
318+
// compared to the `POPCNT` implementation on the underlying integer type.
319+
320+
intrinsics::ctpop(self.get()) < 2
321+
}
322+
323+
}
324+
)+
325+
}
326+
}
327+
328+
nonzero_unsigned_is_power_of_two! { NonZeroU8 NonZeroU16 NonZeroU32 NonZeroU64 NonZeroU128 NonZeroUsize }

std/src/io/buffered/bufreader.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,20 @@ impl<R: Read> Read for BufReader<R> {
271271
Ok(nread)
272272
}
273273

274+
// Small read_exacts from a BufReader are extremely common when used with a deserializer.
275+
// The default implementation calls read in a loop, which results in surprisingly poor code
276+
// generation for the common path where the buffer has enough bytes to fill the passed-in
277+
// buffer.
278+
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
279+
if self.buffer().len() >= buf.len() {
280+
buf.copy_from_slice(&self.buffer()[..buf.len()]);
281+
self.consume(buf.len());
282+
return Ok(());
283+
}
284+
285+
crate::io::default_read_exact(self, buf)
286+
}
287+
274288
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
275289
let total_len = bufs.iter().map(|b| b.len()).sum::<usize>();
276290
if self.pos == self.cap && total_len >= self.buf.len() {

std/src/io/buffered/tests.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,18 @@ fn bench_buffered_reader(b: &mut test::Bencher) {
443443
b.iter(|| BufReader::new(io::empty()));
444444
}
445445

446+
#[bench]
447+
fn bench_buffered_reader_small_reads(b: &mut test::Bencher) {
448+
let data = (0..u8::MAX).cycle().take(1024 * 4).collect::<Vec<_>>();
449+
b.iter(|| {
450+
let mut reader = BufReader::new(&data[..]);
451+
let mut buf = [0u8; 4];
452+
for _ in 0..1024 {
453+
reader.read_exact(&mut buf).unwrap();
454+
}
455+
});
456+
}
457+
446458
#[bench]
447459
fn bench_buffered_writer(b: &mut test::Bencher) {
448460
b.iter(|| BufWriter::new(io::sink()));

std/src/io/mod.rs

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,25 @@ where
416416
write(buf)
417417
}
418418

419+
pub(crate) fn default_read_exact<R: Read + ?Sized>(this: &mut R, mut buf: &mut [u8]) -> Result<()> {
420+
while !buf.is_empty() {
421+
match this.read(buf) {
422+
Ok(0) => break,
423+
Ok(n) => {
424+
let tmp = buf;
425+
buf = &mut tmp[n..];
426+
}
427+
Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
428+
Err(e) => return Err(e),
429+
}
430+
}
431+
if !buf.is_empty() {
432+
Err(Error::new(ErrorKind::UnexpectedEof, "failed to fill whole buffer"))
433+
} else {
434+
Ok(())
435+
}
436+
}
437+
419438
/// The `Read` trait allows for reading bytes from a source.
420439
///
421440
/// Implementors of the `Read` trait are called 'readers'.
@@ -766,23 +785,8 @@ pub trait Read {
766785
/// }
767786
/// ```
768787
#[stable(feature = "read_exact", since = "1.6.0")]
769-
fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<()> {
770-
while !buf.is_empty() {
771-
match self.read(buf) {
772-
Ok(0) => break,
773-
Ok(n) => {
774-
let tmp = buf;
775-
buf = &mut tmp[n..];
776-
}
777-
Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
778-
Err(e) => return Err(e),
779-
}
780-
}
781-
if !buf.is_empty() {
782-
Err(Error::new(ErrorKind::UnexpectedEof, "failed to fill whole buffer"))
783-
} else {
784-
Ok(())
785-
}
788+
fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
789+
default_read_exact(self, buf)
786790
}
787791

788792
/// Creates a "by reference" adaptor for this instance of `Read`.

0 commit comments

Comments
 (0)