Skip to content

Commit

Permalink
Merge from rustc
Browse files Browse the repository at this point in the history
  • Loading branch information
RalfJung committed Jan 23, 2023
2 parents fbc18e4 + ffabd00 commit d6c2912
Show file tree
Hide file tree
Showing 30 changed files with 785 additions and 442 deletions.
1 change: 1 addition & 0 deletions alloc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
#![feature(const_size_of_val)]
#![feature(const_align_of_val)]
#![feature(const_ptr_read)]
#![feature(const_maybe_uninit_zeroed)]
#![feature(const_maybe_uninit_write)]
#![feature(const_maybe_uninit_as_mut_ptr)]
#![feature(const_refs_to_cell)]
Expand Down
348 changes: 39 additions & 309 deletions alloc/src/slice.rs

Large diffs are not rendered by default.

14 changes: 6 additions & 8 deletions alloc/src/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -559,10 +559,9 @@ impl str {
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
#[inline]
pub fn to_ascii_uppercase(&self) -> String {
let mut bytes = self.as_bytes().to_vec();
bytes.make_ascii_uppercase();
// make_ascii_uppercase() preserves the UTF-8 invariant.
unsafe { String::from_utf8_unchecked(bytes) }
let mut s = self.to_owned();
s.make_ascii_uppercase();
s
}

/// Returns a copy of this string where each character is mapped to its
Expand Down Expand Up @@ -592,10 +591,9 @@ impl str {
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
#[inline]
pub fn to_ascii_lowercase(&self) -> String {
let mut bytes = self.as_bytes().to_vec();
bytes.make_ascii_lowercase();
// make_ascii_lowercase() preserves the UTF-8 invariant.
unsafe { String::from_utf8_unchecked(bytes) }
let mut s = self.to_owned();
s.make_ascii_lowercase();
s
}
}

Expand Down
6 changes: 3 additions & 3 deletions alloc/src/vec/drain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,9 +223,9 @@ impl<T, A: Allocator> Drop for Drain<'_, T, A> {
}

// as_slice() must only be called when iter.len() is > 0 because
// vec::Splice modifies vec::Drain fields and may grow the vec which would invalidate
// the iterator's internal pointers. Creating a reference to deallocated memory
// is invalid even when it is zero-length
// it also gets touched by vec::Splice which may turn it into a dangling pointer
// which would make it and the vec pointer point to different allocations which would
// lead to invalid pointer arithmetic below.
let drop_ptr = iter.as_slice().as_ptr();

unsafe {
Expand Down
20 changes: 19 additions & 1 deletion alloc/src/vec/is_zero.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ use crate::boxed::Box;

#[rustc_specialization_trait]
pub(super) unsafe trait IsZero {
/// Whether this value's representation is all zeros
/// Whether this value's representation is all zeros,
/// or can be represented with all zeroes.
fn is_zero(&self) -> bool;
}

Expand Down Expand Up @@ -147,6 +148,23 @@ impl_is_zero_option_of_nonzero!(
NonZeroIsize,
);

macro_rules! impl_is_zero_option_of_num {
($($t:ty,)+) => {$(
unsafe impl IsZero for Option<$t> {
#[inline]
fn is_zero(&self) -> bool {
const {
let none: Self = unsafe { core::mem::MaybeUninit::zeroed().assume_init() };
assert!(none.is_none());
}
self.is_none()
}
}
)+};
}

impl_is_zero_option_of_num!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, usize, isize,);

unsafe impl<T: IsZero> IsZero for Wrapping<T> {
#[inline]
fn is_zero(&self) -> bool {
Expand Down
6 changes: 6 additions & 0 deletions alloc/src/vec/splice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ impl<I: Iterator, A: Allocator> ExactSizeIterator for Splice<'_, I, A> {}
impl<I: Iterator, A: Allocator> Drop for Splice<'_, I, A> {
fn drop(&mut self) {
self.drain.by_ref().for_each(drop);
// At this point draining is done and the only remaining tasks are splicing
// and moving things into the final place.
// Which means we can replace the slice::Iter with pointers that won't point to deallocated
// memory, so that Drain::drop is still allowed to call iter.len(), otherwise it would break
// the ptr.sub_ptr contract.
self.drain.iter = (&[]).iter();

unsafe {
if self.drain.tail_len == 0 {
Expand Down
1 change: 0 additions & 1 deletion alloc/tests/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#![feature(allocator_api)]
#![feature(alloc_layout_extra)]
#![feature(assert_matches)]
#![feature(box_syntax)]
#![feature(btree_drain_filter)]
#![feature(cow_is_borrowed)]
#![feature(const_box)]
Expand Down
3 changes: 2 additions & 1 deletion core/src/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -662,7 +662,8 @@ impl dyn Any + Send + Sync {
/// While `TypeId` implements `Hash`, `PartialOrd`, and `Ord`, it is worth
/// noting that the hashes and ordering will vary between Rust releases. Beware
/// of relying on them inside of your code!
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
#[derive(Clone, Copy, Debug, Hash, Eq)]
#[derive_const(PartialEq, PartialOrd, Ord)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct TypeId {
t: u64,
Expand Down
60 changes: 30 additions & 30 deletions core/src/fmt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1355,11 +1355,11 @@ impl<'a> Formatter<'a> {
/// }
/// }
///
/// assert_eq!(&format!("{}", Foo::new(2)), "2");
/// assert_eq!(&format!("{}", Foo::new(-1)), "-1");
/// assert_eq!(&format!("{}", Foo::new(0)), "0");
/// assert_eq!(&format!("{:#}", Foo::new(-1)), "-Foo 1");
/// assert_eq!(&format!("{:0>#8}", Foo::new(-1)), "00-Foo 1");
/// assert_eq!(format!("{}", Foo::new(2)), "2");
/// assert_eq!(format!("{}", Foo::new(-1)), "-1");
/// assert_eq!(format!("{}", Foo::new(0)), "0");
/// assert_eq!(format!("{:#}", Foo::new(-1)), "-Foo 1");
/// assert_eq!(format!("{:0>#8}", Foo::new(-1)), "00-Foo 1");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn pad_integral(&mut self, is_nonnegative: bool, prefix: &str, buf: &str) -> Result {
Expand Down Expand Up @@ -1452,8 +1452,8 @@ impl<'a> Formatter<'a> {
/// }
/// }
///
/// assert_eq!(&format!("{Foo:<4}"), "Foo ");
/// assert_eq!(&format!("{Foo:0>4}"), "0Foo");
/// assert_eq!(format!("{Foo:<4}"), "Foo ");
/// assert_eq!(format!("{Foo:0>4}"), "0Foo");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn pad(&mut self, s: &str) -> Result {
Expand Down Expand Up @@ -1636,8 +1636,8 @@ impl<'a> Formatter<'a> {
/// }
/// }
///
/// assert_eq!(&format!("{Foo}"), "Foo");
/// assert_eq!(&format!("{Foo:0>8}"), "Foo");
/// assert_eq!(format!("{Foo}"), "Foo");
/// assert_eq!(format!("{Foo:0>8}"), "Foo");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn write_str(&mut self, data: &str) -> Result {
Expand All @@ -1659,8 +1659,8 @@ impl<'a> Formatter<'a> {
/// }
/// }
///
/// assert_eq!(&format!("{}", Foo(-1)), "Foo -1");
/// assert_eq!(&format!("{:0>8}", Foo(2)), "Foo 2");
/// assert_eq!(format!("{}", Foo(-1)), "Foo -1");
/// assert_eq!(format!("{:0>8}", Foo(2)), "Foo 2");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn write_fmt(&mut self, fmt: Arguments<'_>) -> Result {
Expand Down Expand Up @@ -1703,8 +1703,8 @@ impl<'a> Formatter<'a> {
/// }
///
/// // We set alignment to the right with ">".
/// assert_eq!(&format!("{Foo:G>3}"), "GGG");
/// assert_eq!(&format!("{Foo:t>6}"), "tttttt");
/// assert_eq!(format!("{Foo:G>3}"), "GGG");
/// assert_eq!(format!("{Foo:t>6}"), "tttttt");
/// ```
#[must_use]
#[stable(feature = "fmt_flags", since = "1.5.0")]
Expand Down Expand Up @@ -1738,10 +1738,10 @@ impl<'a> Formatter<'a> {
/// }
/// }
///
/// assert_eq!(&format!("{Foo:<}"), "left");
/// assert_eq!(&format!("{Foo:>}"), "right");
/// assert_eq!(&format!("{Foo:^}"), "center");
/// assert_eq!(&format!("{Foo}"), "into the void");
/// assert_eq!(format!("{Foo:<}"), "left");
/// assert_eq!(format!("{Foo:>}"), "right");
/// assert_eq!(format!("{Foo:^}"), "center");
/// assert_eq!(format!("{Foo}"), "into the void");
/// ```
#[must_use]
#[stable(feature = "fmt_flags_align", since = "1.28.0")]
Expand All @@ -1767,16 +1767,16 @@ impl<'a> Formatter<'a> {
/// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
/// if let Some(width) = formatter.width() {
/// // If we received a width, we use it
/// write!(formatter, "{:width$}", &format!("Foo({})", self.0), width = width)
/// write!(formatter, "{:width$}", format!("Foo({})", self.0), width = width)
/// } else {
/// // Otherwise we do nothing special
/// write!(formatter, "Foo({})", self.0)
/// }
/// }
/// }
///
/// assert_eq!(&format!("{:10}", Foo(23)), "Foo(23) ");
/// assert_eq!(&format!("{}", Foo(23)), "Foo(23)");
/// assert_eq!(format!("{:10}", Foo(23)), "Foo(23) ");
/// assert_eq!(format!("{}", Foo(23)), "Foo(23)");
/// ```
#[must_use]
#[stable(feature = "fmt_flags", since = "1.5.0")]
Expand Down Expand Up @@ -1806,8 +1806,8 @@ impl<'a> Formatter<'a> {
/// }
/// }
///
/// assert_eq!(&format!("{:.4}", Foo(23.2)), "Foo(23.2000)");
/// assert_eq!(&format!("{}", Foo(23.2)), "Foo(23.20)");
/// assert_eq!(format!("{:.4}", Foo(23.2)), "Foo(23.2000)");
/// assert_eq!(format!("{}", Foo(23.2)), "Foo(23.20)");
/// ```
#[must_use]
#[stable(feature = "fmt_flags", since = "1.5.0")]
Expand Down Expand Up @@ -1837,9 +1837,9 @@ impl<'a> Formatter<'a> {
/// }
/// }
///
/// assert_eq!(&format!("{:+}", Foo(23)), "Foo(+23)");
/// assert_eq!(&format!("{:+}", Foo(-23)), "Foo(-23)");
/// assert_eq!(&format!("{}", Foo(23)), "Foo(23)");
/// assert_eq!(format!("{:+}", Foo(23)), "Foo(+23)");
/// assert_eq!(format!("{:+}", Foo(-23)), "Foo(-23)");
/// assert_eq!(format!("{}", Foo(23)), "Foo(23)");
/// ```
#[must_use]
#[stable(feature = "fmt_flags", since = "1.5.0")]
Expand Down Expand Up @@ -1867,8 +1867,8 @@ impl<'a> Formatter<'a> {
/// }
/// }
///
/// assert_eq!(&format!("{:-}", Foo(23)), "-Foo(23)");
/// assert_eq!(&format!("{}", Foo(23)), "Foo(23)");
/// assert_eq!(format!("{:-}", Foo(23)), "-Foo(23)");
/// assert_eq!(format!("{}", Foo(23)), "Foo(23)");
/// ```
#[must_use]
#[stable(feature = "fmt_flags", since = "1.5.0")]
Expand All @@ -1895,8 +1895,8 @@ impl<'a> Formatter<'a> {
/// }
/// }
///
/// assert_eq!(&format!("{:#}", Foo(23)), "Foo(23)");
/// assert_eq!(&format!("{}", Foo(23)), "23");
/// assert_eq!(format!("{:#}", Foo(23)), "Foo(23)");
/// assert_eq!(format!("{}", Foo(23)), "23");
/// ```
#[must_use]
#[stable(feature = "fmt_flags", since = "1.5.0")]
Expand All @@ -1922,7 +1922,7 @@ impl<'a> Formatter<'a> {
/// }
/// }
///
/// assert_eq!(&format!("{:04}", Foo(23)), "23");
/// assert_eq!(format!("{:04}", Foo(23)), "23");
/// ```
#[must_use]
#[stable(feature = "fmt_flags", since = "1.5.0")]
Expand Down
4 changes: 4 additions & 0 deletions core/src/future/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ pub unsafe fn get_context<'a, 'b>(cx: ResumeTy) -> &'a mut Context<'b> {
unsafe { &mut *cx.0.as_ptr().cast() }
}

// FIXME(swatinem): This fn is currently needed to work around shortcomings
// in type and lifetime inference.
// See the comment at the bottom of `LoweringContext::make_async_expr` and
// <https://github.com/rust-lang/rust/issues/104826>.
#[doc(hidden)]
#[unstable(feature = "gen_future", issue = "50547")]
#[inline]
Expand Down
69 changes: 69 additions & 0 deletions core/src/hint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,75 @@ pub fn spin_loop() {
/// backend used. Programs cannot rely on `black_box` for *correctness* in any way.
///
/// [`std::convert::identity`]: crate::convert::identity
///
/// # When is this useful?
///
/// First and foremost: `black_box` does _not_ guarantee any exact behavior and, in some cases, may
/// do nothing at all. As such, it **must not be relied upon to control critical program behavior.**
/// This _immediately_ precludes any direct use of this function for cryptographic or security
/// purposes.
///
/// While not suitable in those mission-critical cases, `back_box`'s functionality can generally be
/// relied upon for benchmarking, and should be used there. It will try to ensure that the
/// compiler doesn't optimize away part of the intended test code based on context. For
/// example:
///
/// ```
/// fn contains(haystack: &[&str], needle: &str) -> bool {
/// haystack.iter().any(|x| x == &needle)
/// }
///
/// pub fn benchmark() {
/// let haystack = vec!["abc", "def", "ghi", "jkl", "mno"];
/// let needle = "ghi";
/// for _ in 0..10 {
/// contains(&haystack, needle);
/// }
/// }
/// ```
///
/// The compiler could theoretically make optimizations like the following:
///
/// - `needle` and `haystack` are always the same, move the call to `contains` outside the loop and
/// delete the loop
/// - Inline `contains`
/// - `needle` and `haystack` have values known at compile time, `contains` is always true. Remove
/// the call and replace with `true`
/// - Nothing is done with the result of `contains`: delete this function call entirely
/// - `benchmark` now has no purpose: delete this function
///
/// It is not likely that all of the above happens, but the compiler is definitely able to make some
/// optimizations that could result in a very inaccurate benchmark. This is where `black_box` comes
/// in:
///
/// ```
/// use std::hint::black_box;
///
/// // Same `contains` function
/// fn contains(haystack: &[&str], needle: &str) -> bool {
/// haystack.iter().any(|x| x == &needle)
/// }
///
/// pub fn benchmark() {
/// let haystack = vec!["abc", "def", "ghi", "jkl", "mno"];
/// let needle = "ghi";
/// for _ in 0..10 {
/// // Adjust our benchmark loop contents
/// black_box(contains(black_box(&haystack), black_box(needle)));
/// }
/// }
/// ```
///
/// This essentially tells the compiler to block optimizations across any calls to `black_box`. So,
/// it now:
///
/// - Treats both arguments to `contains` as unpredictable: the body of `contains` can no longer be
/// optimized based on argument values
/// - Treats the call to `contains` and its result as volatile: the body of `benchmark` cannot
/// optimize this away
///
/// This makes our benchmark much more realistic to how the function would be used in situ, where
/// arguments are usually not known at compile time and the result is used in some way.
#[inline]
#[stable(feature = "bench_black_box", since = "1.66.0")]
#[rustc_const_unstable(feature = "const_black_box", issue = "none")]
Expand Down
2 changes: 2 additions & 0 deletions core/src/intrinsics/mir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,8 @@ define!("mir_unreachable", fn Unreachable() -> BasicBlock);
define!("mir_drop", fn Drop<T>(place: T, goto: BasicBlock));
define!("mir_drop_and_replace", fn DropAndReplace<T>(place: T, value: T, goto: BasicBlock));
define!("mir_call", fn Call<T>(place: T, goto: BasicBlock, call: T));
define!("mir_storage_live", fn StorageLive<T>(local: T));
define!("mir_storage_dead", fn StorageDead<T>(local: T));
define!("mir_retag", fn Retag<T>(place: T));
define!("mir_move", fn Move<T>(place: T) -> T);
define!("mir_static", fn Static<T>(s: T) -> &'static T);
Expand Down
Loading

0 comments on commit d6c2912

Please sign in to comment.