Auto merge of #118405 - matthiaskrgr:rollup-3a2eevc, r=matthiaskrgr

Rollup of 7 pull requests

Successful merges:

 - #115331 (optimize str::iter::Chars::advance_by)
 - #118236 (Update mod comment)
 - #118299 (Update `OnceLock` documentation to give a concrete 'lazy static' example, and expand on the existing example.)
 - #118314 (Rename `{collections=>alloc}{tests,benches}`)
 - #118341 (Simplify indenting in THIR printing)
 - #118366 (Detect and reject malformed `repr(Rust)` hints)
 - #118397 (Fix comments for unsigned non-zero `checked_add`, `saturating_add`)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-11-28 10:21:41 +00:00
commit 46a24ed2f4
13 changed files with 174 additions and 29 deletions

View File

@ -985,7 +985,7 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
Ok(literal) => acc.push(ReprPacked(literal)),
Err(message) => literal_error = Some(message),
};
} else if matches!(name, sym::C | sym::simd | sym::transparent)
} else if matches!(name, sym::Rust | sym::C | sym::simd | sym::transparent)
|| int_type_of_word(name).is_some()
{
recognised = true;
@ -1018,7 +1018,7 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
});
} else if matches!(
meta_item.name_or_empty(),
sym::C | sym::simd | sym::transparent
sym::Rust | sym::C | sym::simd | sym::transparent
) || int_type_of_word(meta_item.name_or_empty()).is_some()
{
recognised = true;
@ -1043,7 +1043,7 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
);
} else if matches!(
meta_item.name_or_empty(),
sym::C | sym::simd | sym::transparent
sym::Rust | sym::C | sym::simd | sym::transparent
) || int_type_of_word(meta_item.name_or_empty()).is_some()
{
recognised = true;

View File

@ -31,8 +31,8 @@ const INDENT: &str = " ";
macro_rules! print_indented {
($writer:ident, $s:expr, $indent_lvl:expr) => {
let indent = (0..$indent_lvl).map(|_| INDENT).collect::<Vec<_>>().concat();
writeln!($writer, "{}{}", indent, $s).expect("unable to write to ThirPrinter");
$writer.indent($indent_lvl);
writeln!($writer, "{}", $s).expect("unable to write to ThirPrinter");
};
}
@ -48,6 +48,12 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
Self { thir, fmt: String::new() }
}
fn indent(&mut self, level: usize) {
for _ in 0..level {
self.fmt.push_str(INDENT);
}
}
fn print(&mut self) {
print_indented!(self, "params: [", 0);
for param in self.thir.params.iter() {

View File

@ -17,11 +17,11 @@ rand = { version = "0.8.5", default-features = false, features = ["alloc"] }
rand_xorshift = "0.3.0"
[[test]]
name = "collectionstests"
name = "alloctests"
path = "tests/lib.rs"
[[bench]]
name = "collectionsbenches"
name = "allocbenches"
path = "benches/lib.rs"
test = true

View File

@ -1170,6 +1170,17 @@ fn test_iterator() {
assert_eq!(s.chars().count(), v.len());
}
#[test]
fn test_iterator_advance() {
let s = "「赤錆」と呼ばれる鉄錆は、水の存在下での鉄の自然酸化によって生じる、オキシ水酸化鉄(III) 等の(含水)酸化物粒子の疎な凝集膜であるとみなせる。";
let chars: Vec<char> = s.chars().collect();
let mut it = s.chars();
it.advance_by(1).unwrap();
assert_eq!(it.next(), Some(chars[1]));
it.advance_by(33).unwrap();
assert_eq!(it.next(), Some(chars[35]));
}
#[test]
fn test_rev_iterator() {
let s = "ศไทย中华Việt Nam";

View File

@ -5,6 +5,7 @@
#![feature(trusted_random_access)]
#![feature(iter_array_chunks)]
#![feature(iter_next_chunk)]
#![feature(iter_advance_by)]
extern crate test;

View File

@ -3,6 +3,7 @@ use test::{black_box, Bencher};
mod char_count;
mod corpora;
mod iter;
#[bench]
fn str_validate_emoji(b: &mut Bencher) {

View File

@ -0,0 +1,17 @@
use super::corpora;
use test::{black_box, Bencher};
#[bench]
fn chars_advance_by_1000(b: &mut Bencher) {
b.iter(|| black_box(corpora::ru::LARGE).chars().advance_by(1000));
}
#[bench]
fn chars_advance_by_0010(b: &mut Bencher) {
b.iter(|| black_box(corpora::ru::LARGE).chars().advance_by(10));
}
#[bench]
fn chars_advance_by_0001(b: &mut Bencher) {
b.iter(|| black_box(corpora::ru::LARGE).chars().advance_by(1));
}

View File

@ -474,7 +474,7 @@ impl isize {
}
}
/// If 6th bit is set ascii is lower case.
/// If the 6th bit is set ascii is lower case.
const ASCII_CASE_MASK: u8 = 0b0010_0000;
impl u8 {
@ -549,7 +549,7 @@ impl u8 {
#[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")]
#[inline]
pub const fn to_ascii_uppercase(&self) -> u8 {
// Toggle the fifth bit if this is a lowercase letter
// Toggle the 6th bit if this is a lowercase letter
*self ^ ((self.is_ascii_lowercase() as u8) * ASCII_CASE_MASK)
}
@ -574,7 +574,7 @@ impl u8 {
#[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")]
#[inline]
pub const fn to_ascii_lowercase(&self) -> u8 {
// Set the fifth bit if this is an uppercase letter
// Set the 6th bit if this is an uppercase letter
*self | (self.is_ascii_uppercase() as u8 * ASCII_CASE_MASK)
}

View File

@ -355,7 +355,7 @@ macro_rules! nonzero_unsigned_operations {
if let Some(result) = self.get().checked_add(other) {
// SAFETY:
// - `checked_add` returns `None` on overflow
// - `self` and `other` are non-zero
// - `self` is non-zero
// - the only way to get zero from an addition without overflow is for both
// sides to be zero
//
@ -393,7 +393,7 @@ macro_rules! nonzero_unsigned_operations {
pub const fn saturating_add(self, other: $Int) -> $Ty {
// SAFETY:
// - `saturating_add` returns `u*::MAX` on overflow, which is non-zero
// - `self` and `other` are non-zero
// - `self` is non-zero
// - the only way to get zero from an addition without overflow is for both
// sides to be zero
//

View File

@ -8,6 +8,7 @@ use crate::iter::{TrustedRandomAccess, TrustedRandomAccessNoCoerce};
use crate::ops::Try;
use crate::option;
use crate::slice::{self, Split as SliceSplit};
use core::num::NonZeroUsize;
use super::from_utf8_unchecked;
use super::pattern::Pattern;
@ -49,6 +50,55 @@ impl<'a> Iterator for Chars<'a> {
super::count::count_chars(self.as_str())
}
#[inline]
fn advance_by(&mut self, mut remainder: usize) -> Result<(), NonZeroUsize> {
const CHUNK_SIZE: usize = 32;
if remainder >= CHUNK_SIZE {
let mut chunks = self.iter.as_slice().array_chunks::<CHUNK_SIZE>();
let mut bytes_skipped: usize = 0;
while remainder > CHUNK_SIZE
&& let Some(chunk) = chunks.next()
{
bytes_skipped += CHUNK_SIZE;
let mut start_bytes = [false; CHUNK_SIZE];
for i in 0..CHUNK_SIZE {
start_bytes[i] = !super::validations::utf8_is_cont_byte(chunk[i]);
}
remainder -= start_bytes.into_iter().map(|i| i as u8).sum::<u8>() as usize;
}
// SAFETY: The amount of bytes exists since we just iterated over them,
// so advance_by will succeed.
unsafe { self.iter.advance_by(bytes_skipped).unwrap_unchecked() };
// skip trailing continuation bytes
while self.iter.len() > 0 {
let b = self.iter.as_slice()[0];
if !super::validations::utf8_is_cont_byte(b) {
break;
}
// SAFETY: We just peeked at the byte, therefore it exists
unsafe { self.iter.advance_by(1).unwrap_unchecked() };
}
}
while (remainder > 0) && (self.iter.len() > 0) {
remainder -= 1;
let b = self.iter.as_slice()[0];
let slurp = super::validations::utf8_char_width(b);
// SAFETY: utf8 validity requires that the string must contain
// the continuation bytes (if any)
unsafe { self.iter.advance_by(slurp).unwrap_unchecked() };
}
NonZeroUsize::new(remainder).map_or(Ok(()), Err)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.iter.len();

View File

@ -13,22 +13,54 @@ use crate::sync::Once;
///
/// # Examples
///
/// Using `OnceCell` to store a functions previously computed value (a.k.a.
/// lazy static or memoizing):
///
/// ```
/// use std::collections::HashMap;
/// use std::sync::OnceLock;
///
/// fn hash_map() -> &'static HashMap<u32, char> {
/// static HASHMAP: OnceLock<HashMap<u32, char>> = OnceLock::new();
/// HASHMAP.get_or_init(|| {
/// let mut m = HashMap::new();
/// m.insert(0, 'a');
/// m.insert(1, 'b');
/// m.insert(2, 'c');
/// m
/// })
/// }
///
/// // The `HashMap` is built, stored in the `OnceLock`, and returned.
/// let _ = hash_map();
///
/// // The `HashMap` is retrieved from the `OnceLock` and returned.
/// let _ = hash_map();
/// ```
///
/// Writing to a `OnceLock` from a separate thread:
///
/// ```
/// use std::sync::OnceLock;
///
/// static CELL: OnceLock<String> = OnceLock::new();
/// static CELL: OnceLock<usize> = OnceLock::new();
///
/// // `OnceLock` has not been written to yet.
/// assert!(CELL.get().is_none());
///
/// // Spawn a thread and write to `OnceLock`.
/// std::thread::spawn(|| {
/// let value: &String = CELL.get_or_init(|| {
/// "Hello, World!".to_string()
/// });
/// assert_eq!(value, "Hello, World!");
/// }).join().unwrap();
/// let value = CELL.get_or_init(|| 12345);
/// assert_eq!(value, &12345);
/// })
/// .join()
/// .unwrap();
///
/// let value: Option<&String> = CELL.get();
/// assert!(value.is_some());
/// assert_eq!(value.unwrap().as_str(), "Hello, World!");
/// // `OnceLock` now contains the value.
/// assert_eq!(
/// CELL.get(),
/// Some(&12345),
/// );
/// ```
#[stable(feature = "once_cell", since = "1.70.0")]
pub struct OnceLock<T> {

View File

@ -19,6 +19,15 @@ struct S3;
//~^ ERROR: incorrect `repr(align)` attribute format
struct S4;
// Regression test for issue #118334:
#[repr(Rust(u8))]
//~^ ERROR: invalid representation hint
#[repr(Rust(0))]
//~^ ERROR: invalid representation hint
#[repr(Rust = 0)]
//~^ ERROR: invalid representation hint
struct S5;
#[repr(i8())]
//~^ ERROR: invalid representation hint
enum E1 { A, B }

View File

@ -1,46 +1,64 @@
error[E0552]: incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all
--> $DIR/issue-83921-ice.rs:6:8
--> $DIR/malformed-repr-hints.rs:6:8
|
LL | #[repr(packed())]
| ^^^^^^^^
error[E0589]: invalid `repr(align)` attribute: `align` needs an argument
--> $DIR/issue-83921-ice.rs:10:8
--> $DIR/malformed-repr-hints.rs:10:8
|
LL | #[repr(align)]
| ^^^^^ help: supply an argument here: `align(...)`
error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses
--> $DIR/issue-83921-ice.rs:14:8
--> $DIR/malformed-repr-hints.rs:14:8
|
LL | #[repr(align(2, 4))]
| ^^^^^^^^^^^
error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses
--> $DIR/issue-83921-ice.rs:18:8
--> $DIR/malformed-repr-hints.rs:18:8
|
LL | #[repr(align())]
| ^^^^^^^
error[E0552]: invalid representation hint: `Rust` does not take a parenthesized argument list
--> $DIR/malformed-repr-hints.rs:23:8
|
LL | #[repr(Rust(u8))]
| ^^^^^^^^
error[E0552]: invalid representation hint: `Rust` does not take a parenthesized argument list
--> $DIR/malformed-repr-hints.rs:25:8
|
LL | #[repr(Rust(0))]
| ^^^^^^^
error[E0552]: invalid representation hint: `Rust` does not take a value
--> $DIR/malformed-repr-hints.rs:27:8
|
LL | #[repr(Rust = 0)]
| ^^^^^^^^
error[E0552]: invalid representation hint: `i8` does not take a parenthesized argument list
--> $DIR/issue-83921-ice.rs:22:8
--> $DIR/malformed-repr-hints.rs:31:8
|
LL | #[repr(i8())]
| ^^^^
error[E0552]: invalid representation hint: `u32` does not take a parenthesized argument list
--> $DIR/issue-83921-ice.rs:26:8
--> $DIR/malformed-repr-hints.rs:35:8
|
LL | #[repr(u32(42))]
| ^^^^^^^
error[E0552]: invalid representation hint: `i64` does not take a value
--> $DIR/issue-83921-ice.rs:30:8
--> $DIR/malformed-repr-hints.rs:39:8
|
LL | #[repr(i64 = 2)]
| ^^^^^^^
error: aborting due to 7 previous errors
error: aborting due to 10 previous errors
Some errors have detailed explanations: E0552, E0589, E0693.
For more information about an error, try `rustc --explain E0552`.