Skip to content

Commit 51ce234

Browse files
committed
Merge from rustc
2 parents 7c8d318 + e57be41 commit 51ce234

File tree

30 files changed

+313
-130
lines changed

30 files changed

+313
-130
lines changed

core/src/char/convert.rs

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,20 +87,54 @@ impl From<char> for u128 {
8787
}
8888
}
8989

90-
/// Map `char` with code point in U+0000..=U+00FF to byte in 0x00..=0xFF with same value, failing
91-
/// if the code point is greater than U+00FF.
90+
/// Maps a `char` with code point in U+0000..=U+00FF to a byte in 0x00..=0xFF with same value,
91+
/// failing if the code point is greater than U+00FF.
9292
///
9393
/// See [`impl From<u8> for char`](char#impl-From<u8>-for-char) for details on the encoding.
9494
#[stable(feature = "u8_from_char", since = "1.59.0")]
9595
impl TryFrom<char> for u8 {
9696
type Error = TryFromCharError;
9797

98+
/// Tries to convert a [`char`] into a [`u8`].
99+
///
100+
/// # Examples
101+
///
102+
/// ```
103+
/// let a = 'ÿ'; // U+00FF
104+
/// let b = 'Ā'; // U+0100
105+
/// assert_eq!(u8::try_from(a), Ok(0xFF_u8));
106+
/// assert!(u8::try_from(b).is_err());
107+
/// ```
98108
#[inline]
99109
fn try_from(c: char) -> Result<u8, Self::Error> {
100110
u8::try_from(u32::from(c)).map_err(|_| TryFromCharError(()))
101111
}
102112
}
103113

114+
/// Maps a `char` with code point in U+0000..=U+FFFF to a `u16` in 0x0000..=0xFFFF with same value,
115+
/// failing if the code point is greater than U+FFFF.
116+
///
117+
/// This corresponds to the UCS-2 encoding, as specified in ISO/IEC 10646:2003.
118+
#[stable(feature = "u16_from_char", since = "CURRENT_RUSTC_VERSION")]
119+
impl TryFrom<char> for u16 {
120+
type Error = TryFromCharError;
121+
122+
/// Tries to convert a [`char`] into a [`u16`].
123+
///
124+
/// # Examples
125+
///
126+
/// ```
127+
/// let trans_rights = '⚧'; // U+26A7
128+
/// let ninjas = '🥷'; // U+1F977
129+
/// assert_eq!(u16::try_from(trans_rights), Ok(0x26A7_u16));
130+
/// assert!(u16::try_from(ninjas).is_err());
131+
/// ```
132+
#[inline]
133+
fn try_from(c: char) -> Result<u16, Self::Error> {
134+
u16::try_from(u32::from(c)).map_err(|_| TryFromCharError(()))
135+
}
136+
}
137+
104138
/// Maps a byte in 0x00..=0xFF to a `char` whose code point has the same value, in U+0000..=U+00FF.
105139
///
106140
/// Unicode is designed such that this effectively decodes bytes

core/src/iter/adapters/take.rs

Lines changed: 82 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use crate::cmp;
2-
use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedLen};
2+
use crate::iter::{
3+
adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedLen, TrustedRandomAccess,
4+
};
35
use crate::num::NonZeroUsize;
46
use crate::ops::{ControlFlow, Try};
57

@@ -98,26 +100,18 @@ where
98100
}
99101
}
100102

101-
impl_fold_via_try_fold! { fold -> try_fold }
102-
103103
#[inline]
104-
fn for_each<F: FnMut(Self::Item)>(mut self, f: F) {
105-
// The default implementation would use a unit accumulator, so we can
106-
// avoid a stateful closure by folding over the remaining number
107-
// of items we wish to return instead.
108-
fn check<'a, Item>(
109-
mut action: impl FnMut(Item) + 'a,
110-
) -> impl FnMut(usize, Item) -> Option<usize> + 'a {
111-
move |more, x| {
112-
action(x);
113-
more.checked_sub(1)
114-
}
115-
}
104+
fn fold<B, F>(self, init: B, f: F) -> B
105+
where
106+
Self: Sized,
107+
F: FnMut(B, Self::Item) -> B,
108+
{
109+
Self::spec_fold(self, init, f)
110+
}
116111

117-
let remaining = self.n;
118-
if remaining > 0 {
119-
self.iter.try_fold(remaining - 1, check(f));
120-
}
112+
#[inline]
113+
fn for_each<F: FnMut(Self::Item)>(self, f: F) {
114+
Self::spec_for_each(self, f)
121115
}
122116

123117
#[inline]
@@ -249,3 +243,72 @@ impl<I> FusedIterator for Take<I> where I: FusedIterator {}
249243

250244
#[unstable(feature = "trusted_len", issue = "37572")]
251245
unsafe impl<I: TrustedLen> TrustedLen for Take<I> {}
246+
247+
trait SpecTake: Iterator {
248+
fn spec_fold<B, F>(self, init: B, f: F) -> B
249+
where
250+
Self: Sized,
251+
F: FnMut(B, Self::Item) -> B;
252+
253+
fn spec_for_each<F: FnMut(Self::Item)>(self, f: F);
254+
}
255+
256+
impl<I: Iterator> SpecTake for Take<I> {
257+
#[inline]
258+
default fn spec_fold<B, F>(mut self, init: B, f: F) -> B
259+
where
260+
Self: Sized,
261+
F: FnMut(B, Self::Item) -> B,
262+
{
263+
use crate::ops::NeverShortCircuit;
264+
self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).0
265+
}
266+
267+
#[inline]
268+
default fn spec_for_each<F: FnMut(Self::Item)>(mut self, f: F) {
269+
// The default implementation would use a unit accumulator, so we can
270+
// avoid a stateful closure by folding over the remaining number
271+
// of items we wish to return instead.
272+
fn check<'a, Item>(
273+
mut action: impl FnMut(Item) + 'a,
274+
) -> impl FnMut(usize, Item) -> Option<usize> + 'a {
275+
move |more, x| {
276+
action(x);
277+
more.checked_sub(1)
278+
}
279+
}
280+
281+
let remaining = self.n;
282+
if remaining > 0 {
283+
self.iter.try_fold(remaining - 1, check(f));
284+
}
285+
}
286+
}
287+
288+
impl<I: Iterator + TrustedRandomAccess> SpecTake for Take<I> {
289+
#[inline]
290+
fn spec_fold<B, F>(mut self, init: B, mut f: F) -> B
291+
where
292+
Self: Sized,
293+
F: FnMut(B, Self::Item) -> B,
294+
{
295+
let mut acc = init;
296+
let end = self.n.min(self.iter.size());
297+
for i in 0..end {
298+
// SAFETY: i < end <= self.iter.size() and we discard the iterator at the end
299+
let val = unsafe { self.iter.__iterator_get_unchecked(i) };
300+
acc = f(acc, val);
301+
}
302+
acc
303+
}
304+
305+
#[inline]
306+
fn spec_for_each<F: FnMut(Self::Item)>(mut self, mut f: F) {
307+
let end = self.n.min(self.iter.size());
308+
for i in 0..end {
309+
// SAFETY: i < end <= self.iter.size() and we discard the iterator at the end
310+
let val = unsafe { self.iter.__iterator_get_unchecked(i) };
311+
f(val);
312+
}
313+
}
314+
}

core/src/iter/range.rs

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::ascii::Char as AsciiChar;
12
use crate::convert::TryFrom;
23
use crate::mem;
34
use crate::num::NonZeroUsize;
@@ -14,7 +15,7 @@ macro_rules! unsafe_impl_trusted_step {
1415
unsafe impl TrustedStep for $type {}
1516
)*};
1617
}
17-
unsafe_impl_trusted_step![char i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize];
18+
unsafe_impl_trusted_step![AsciiChar char i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize];
1819

1920
/// Objects that have a notion of *successor* and *predecessor* operations.
2021
///
@@ -484,6 +485,48 @@ impl Step for char {
484485
}
485486
}
486487

488+
#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
489+
impl Step for AsciiChar {
490+
#[inline]
491+
fn steps_between(&start: &AsciiChar, &end: &AsciiChar) -> Option<usize> {
492+
Step::steps_between(&start.to_u8(), &end.to_u8())
493+
}
494+
495+
#[inline]
496+
fn forward_checked(start: AsciiChar, count: usize) -> Option<AsciiChar> {
497+
let end = Step::forward_checked(start.to_u8(), count)?;
498+
AsciiChar::from_u8(end)
499+
}
500+
501+
#[inline]
502+
fn backward_checked(start: AsciiChar, count: usize) -> Option<AsciiChar> {
503+
let end = Step::backward_checked(start.to_u8(), count)?;
504+
505+
// SAFETY: Values below that of a valid ASCII character are also valid ASCII
506+
Some(unsafe { AsciiChar::from_u8_unchecked(end) })
507+
}
508+
509+
#[inline]
510+
unsafe fn forward_unchecked(start: AsciiChar, count: usize) -> AsciiChar {
511+
// SAFETY: Caller asserts that result is a valid ASCII character,
512+
// and therefore it is a valid u8.
513+
let end = unsafe { Step::forward_unchecked(start.to_u8(), count) };
514+
515+
// SAFETY: Caller asserts that result is a valid ASCII character.
516+
unsafe { AsciiChar::from_u8_unchecked(end) }
517+
}
518+
519+
#[inline]
520+
unsafe fn backward_unchecked(start: AsciiChar, count: usize) -> AsciiChar {
521+
// SAFETY: Caller asserts that result is a valid ASCII character,
522+
// and therefore it is a valid u8.
523+
let end = unsafe { Step::backward_unchecked(start.to_u8(), count) };
524+
525+
// SAFETY: Caller asserts that result is a valid ASCII character.
526+
unsafe { AsciiChar::from_u8_unchecked(end) }
527+
}
528+
}
529+
487530
macro_rules! range_exact_iter_impl {
488531
($($t:ty)*) => ($(
489532
#[stable(feature = "rust1", since = "1.0.0")]

core/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,6 @@
152152
#![feature(const_slice_from_raw_parts_mut)]
153153
#![feature(const_slice_from_ref)]
154154
#![feature(const_slice_index)]
155-
#![feature(const_slice_is_ascii)]
156155
#![feature(const_slice_ptr_len)]
157156
#![feature(const_slice_split_at_mut)]
158157
#![feature(const_str_from_utf8_unchecked_mut)]

core/src/num/nonzero.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,20 @@ macro_rules! nonzero_integers {
4141
/// with the exception that `0` is not a valid instance.
4242
#[doc = concat!("`Option<", stringify!($Ty), ">` is guaranteed to be compatible with `", stringify!($Int), "`,")]
4343
/// including in FFI.
44+
///
45+
/// Thanks to the [null pointer optimization],
46+
#[doc = concat!("`", stringify!($Ty), "` and `Option<", stringify!($Ty), ">`")]
47+
/// are guaranteed to have the same size and alignment:
48+
///
49+
/// ```
50+
/// # use std::mem::{size_of, align_of};
51+
#[doc = concat!("use std::num::", stringify!($Ty), ";")]
52+
///
53+
#[doc = concat!("assert_eq!(size_of::<", stringify!($Ty), ">(), size_of::<Option<", stringify!($Ty), ">>());")]
54+
#[doc = concat!("assert_eq!(align_of::<", stringify!($Ty), ">(), align_of::<Option<", stringify!($Ty), ">>());")]
55+
/// ```
56+
///
57+
/// [null pointer optimization]: crate::option#representation
4458
#[$stability]
4559
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
4660
#[repr(transparent)]

core/src/num/saturating.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ use crate::ops::{Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign};
3535
#[unstable(feature = "saturating_int_impl", issue = "87920")]
3636
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default, Hash)]
3737
#[repr(transparent)]
38+
#[rustc_diagnostic_item = "Saturating"]
3839
pub struct Saturating<T>(#[unstable(feature = "saturating_int_impl", issue = "87920")] pub T);
3940

4041
#[unstable(feature = "saturating_int_impl", issue = "87920")]

core/src/num/wrapping.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ use crate::ops::{Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign};
3939
#[stable(feature = "rust1", since = "1.0.0")]
4040
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default, Hash)]
4141
#[repr(transparent)]
42+
#[rustc_diagnostic_item = "Wrapping"]
4243
pub struct Wrapping<T>(#[stable(feature = "rust1", since = "1.0.0")] pub T);
4344

4445
#[stable(feature = "rust1", since = "1.0.0")]

core/src/option.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@
119119
//! # Representation
120120
//!
121121
//! Rust guarantees to optimize the following types `T` such that
122-
//! [`Option<T>`] has the same size as `T`:
122+
//! [`Option<T>`] has the same size and alignment as `T`:
123123
//!
124124
//! * [`Box<U>`]
125125
//! * `&U`

core/src/ptr/non_null.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,27 @@ use crate::slice::{self, SliceIndex};
4343
/// it is your responsibility to ensure that `as_mut` is never called, and `as_ptr`
4444
/// is never used for mutation.
4545
///
46+
/// # Representation
47+
///
48+
/// Thanks to the [null pointer optimization],
49+
/// `NonNull<T>` and `Option<NonNull<T>>`
50+
/// are guaranteed to have the same size and alignment:
51+
///
52+
/// ```
53+
/// # use std::mem::{size_of, align_of};
54+
/// use std::ptr::NonNull;
55+
///
56+
/// assert_eq!(size_of::<NonNull<i16>>(), size_of::<Option<NonNull<i16>>>());
57+
/// assert_eq!(align_of::<NonNull<i16>>(), align_of::<Option<NonNull<i16>>>());
58+
///
59+
/// assert_eq!(size_of::<NonNull<str>>(), size_of::<Option<NonNull<str>>>());
60+
/// assert_eq!(align_of::<NonNull<str>>(), align_of::<Option<NonNull<str>>>());
61+
/// ```
62+
///
4663
/// [covariant]: https://doc.rust-lang.org/reference/subtyping.html
4764
/// [`PhantomData`]: crate::marker::PhantomData
4865
/// [`UnsafeCell<T>`]: crate::cell::UnsafeCell
66+
/// [null pointer optimization]: crate::option#representation
4967
#[stable(feature = "nonnull", since = "1.25.0")]
5068
#[repr(transparent)]
5169
#[rustc_layout_scalar_valid_range_start(1)]

core/src/slice/ascii.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::ops;
1010
impl [u8] {
1111
/// Checks if all bytes in this slice are within the ASCII range.
1212
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
13-
#[rustc_const_unstable(feature = "const_slice_is_ascii", issue = "111090")]
13+
#[rustc_const_stable(feature = "const_slice_is_ascii", since = "CURRENT_RUSTC_VERSION")]
1414
#[must_use]
1515
#[inline]
1616
pub const fn is_ascii(&self) -> bool {

0 commit comments

Comments
 (0)