Skip to content

Commit 757a68c

Browse files
committed
Merge from rustc
2 parents a293a60 + 7b5d108 commit 757a68c

File tree

12 files changed

+94
-31
lines changed

12 files changed

+94
-31
lines changed

alloc/src/rc.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1738,11 +1738,11 @@ impl<T: ?Sized + PartialEq> PartialEq for Rc<T> {
17381738

17391739
/// Inequality for two `Rc`s.
17401740
///
1741-
/// Two `Rc`s are unequal if their inner values are unequal.
1741+
/// Two `Rc`s are not equal if their inner values are not equal.
17421742
///
17431743
/// If `T` also implements `Eq` (implying reflexivity of equality),
17441744
/// two `Rc`s that point to the same allocation are
1745-
/// never unequal.
1745+
/// always equal.
17461746
///
17471747
/// # Examples
17481748
///

alloc/src/sync.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2475,10 +2475,10 @@ impl<T: ?Sized + PartialEq> PartialEq for Arc<T> {
24752475

24762476
/// Inequality for two `Arc`s.
24772477
///
2478-
/// Two `Arc`s are unequal if their inner values are unequal.
2478+
/// Two `Arc`s are not equal if their inner values are not equal.
24792479
///
24802480
/// If `T` also implements `Eq` (implying reflexivity of equality),
2481-
/// two `Arc`s that point to the same value are never unequal.
2481+
/// two `Arc`s that point to the same value are always equal.
24822482
///
24832483
/// # Examples
24842484
///

core/src/fmt/mod.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -392,8 +392,31 @@ enum FlagV1 {
392392
}
393393

394394
impl<'a> Arguments<'a> {
395+
#[doc(hidden)]
396+
#[inline]
397+
#[unstable(feature = "fmt_internals", issue = "none")]
398+
#[rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none")]
399+
pub const fn new_const(pieces: &'a [&'static str]) -> Self {
400+
if pieces.len() > 1 {
401+
panic!("invalid args");
402+
}
403+
Arguments { pieces, fmt: None, args: &[] }
404+
}
405+
395406
/// When using the format_args!() macro, this function is used to generate the
396407
/// Arguments structure.
408+
#[cfg(not(bootstrap))]
409+
#[doc(hidden)]
410+
#[inline]
411+
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
412+
pub fn new_v1(pieces: &'a [&'static str], args: &'a [ArgumentV1<'a>]) -> Arguments<'a> {
413+
if pieces.len() < args.len() || pieces.len() > args.len() + 1 {
414+
panic!("invalid args");
415+
}
416+
Arguments { pieces, fmt: None, args }
417+
}
418+
419+
#[cfg(bootstrap)]
397420
#[doc(hidden)]
398421
#[inline]
399422
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
@@ -417,8 +440,7 @@ impl<'a> Arguments<'a> {
417440
#[doc(hidden)]
418441
#[inline]
419442
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
420-
#[rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none")]
421-
pub const fn new_v1_formatted(
443+
pub fn new_v1_formatted(
422444
pieces: &'a [&'static str],
423445
args: &'a [ArgumentV1<'a>],
424446
fmt: &'a [rt::v1::Argument],

core/src/hash/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ mod sip;
158158
///
159159
/// Implementations of `hash` should ensure that the data they
160160
/// pass to the `Hasher` are prefix-free. That is,
161-
/// unequal values should cause two different sequences of values to be written,
161+
/// values which are not equal should cause two different sequences of values to be written,
162162
/// and neither of the two sequences should be a prefix of the other.
163163
///
164164
/// For example, the standard implementation of [`Hash` for `&str`][impl] passes an extra

core/src/intrinsics.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2020,6 +2020,16 @@ extern "rust-intrinsic" {
20202020
#[rustc_safe_intrinsic]
20212021
pub fn saturating_sub<T: Copy>(a: T, b: T) -> T;
20222022

2023+
/// This is an implementation detail of [`crate::ptr::read`] and should
2024+
/// not be used anywhere else. See its comments for why this exists.
2025+
///
2026+
/// This intrinsic can *only* be called where the argument is a local without
2027+
/// projections (`read_via_copy(p)`, not `read_via_copy(*p)`) so that it
2028+
/// trivially obeys runtime-MIR rules about derefs in operands.
2029+
#[cfg(not(bootstrap))]
2030+
#[rustc_const_unstable(feature = "const_ptr_read", issue = "80377")]
2031+
pub fn read_via_copy<T>(p: *const T) -> T;
2032+
20232033
/// Returns the value of the discriminant for the variant in 'v';
20242034
/// if `T` has no discriminant, returns `0`.
20252035
///

core/src/iter/traits/iterator.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3721,7 +3721,7 @@ pub trait Iterator {
37213721
}
37223722
}
37233723

3724-
/// Determines if the elements of this [`Iterator`] are unequal to those of
3724+
/// Determines if the elements of this [`Iterator`] are not equal to those of
37253725
/// another.
37263726
///
37273727
/// # Examples

core/src/panicking.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ pub const fn panic(expr: &'static str) -> ! {
111111
// truncation and padding (even though none is used here). Using
112112
// Arguments::new_v1 may allow the compiler to omit Formatter::pad from the
113113
// output binary, saving up to a few kilobytes.
114-
panic_fmt(fmt::Arguments::new_v1(&[expr], &[]));
114+
panic_fmt(fmt::Arguments::new_const(&[expr]));
115115
}
116116

117117
/// Like `panic`, but without unwinding and track_caller to reduce the impact on codesize.
@@ -120,7 +120,7 @@ pub const fn panic(expr: &'static str) -> ! {
120120
#[lang = "panic_nounwind"] // needed by codegen for non-unwinding panics
121121
#[rustc_nounwind]
122122
pub fn panic_nounwind(expr: &'static str) -> ! {
123-
panic_nounwind_fmt(fmt::Arguments::new_v1(&[expr], &[]));
123+
panic_nounwind_fmt(fmt::Arguments::new_const(&[expr]));
124124
}
125125

126126
#[inline]

core/src/primitive_docs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1110,7 +1110,7 @@ impl<T: Copy> Copy for (T,) {
11101110
/// - [NaN (not a number)](#associatedconstant.NAN): this value results from
11111111
/// calculations like `(-1.0).sqrt()`. NaN has some potentially unexpected
11121112
/// behavior:
1113-
/// - It is unequal to any float, including itself! This is the reason `f32`
1113+
/// - It is not equal to any float, including itself! This is the reason `f32`
11141114
/// doesn't implement the `Eq` trait.
11151115
/// - It is also neither smaller nor greater than any float, making it
11161116
/// impossible to sort by the default comparison operation, which is the

core/src/ptr/mod.rs

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,27 +1135,58 @@ pub const unsafe fn replace<T>(dst: *mut T, mut src: T) -> T {
11351135
#[rustc_const_unstable(feature = "const_ptr_read", issue = "80377")]
11361136
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
11371137
pub const unsafe fn read<T>(src: *const T) -> T {
1138-
// We are calling the intrinsics directly to avoid function calls in the generated code
1139-
// as `intrinsics::copy_nonoverlapping` is a wrapper function.
1140-
extern "rust-intrinsic" {
1141-
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
1142-
fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
1143-
}
1138+
// It would be semantically correct to implement this via `copy_nonoverlapping`
1139+
// and `MaybeUninit`, as was done before PR #109035. Calling `assume_init`
1140+
// provides enough information to know that this is a typed operation.
11441141

1145-
let mut tmp = MaybeUninit::<T>::uninit();
1146-
// SAFETY: the caller must guarantee that `src` is valid for reads.
1147-
// `src` cannot overlap `tmp` because `tmp` was just allocated on
1148-
// the stack as a separate allocated object.
1142+
// However, as of March 2023 the compiler was not capable of taking advantage
1143+
// of that information. Thus the implementation here switched to an intrinsic,
1144+
// which lowers to `_0 = *src` in MIR, to address a few issues:
11491145
//
1150-
// Also, since we just wrote a valid value into `tmp`, it is guaranteed
1151-
// to be properly initialized.
1146+
// - Using `MaybeUninit::assume_init` after a `copy_nonoverlapping` was not
1147+
// turning the untyped copy into a typed load. As such, the generated
1148+
// `load` in LLVM didn't get various metadata, such as `!range` (#73258),
1149+
// `!nonnull`, and `!noundef`, resulting in poorer optimization.
1150+
// - Going through the extra local resulted in multiple extra copies, even
1151+
// in optimized MIR. (Ignoring StorageLive/Dead, the intrinsic is one
1152+
// MIR statement, while the previous implementation was eight.) LLVM
1153+
// could sometimes optimize them away, but because `read` is at the core
1154+
// of so many things, not having them in the first place improves what we
1155+
// hand off to the backend. For example, `mem::replace::<Big>` previously
1156+
// emitted 4 `alloca` and 6 `memcpy`s, but is now 1 `alloc` and 3 `memcpy`s.
1157+
// - In general, this approach keeps us from getting any more bugs (like
1158+
// #106369) that boil down to "`read(p)` is worse than `*p`", as this
1159+
// makes them look identical to the backend (or other MIR consumers).
1160+
//
1161+
// Future enhancements to MIR optimizations might well allow this to return
1162+
// to the previous implementation, rather than using an intrinsic.
1163+
1164+
// SAFETY: the caller must guarantee that `src` is valid for reads.
11521165
unsafe {
11531166
assert_unsafe_precondition!(
11541167
"ptr::read requires that the pointer argument is aligned and non-null",
11551168
[T](src: *const T) => is_aligned_and_not_null(src)
11561169
);
1157-
copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
1158-
tmp.assume_init()
1170+
1171+
#[cfg(bootstrap)]
1172+
{
1173+
// We are calling the intrinsics directly to avoid function calls in the
1174+
// generated code as `intrinsics::copy_nonoverlapping` is a wrapper function.
1175+
extern "rust-intrinsic" {
1176+
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
1177+
fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
1178+
}
1179+
1180+
// `src` cannot overlap `tmp` because `tmp` was just allocated on
1181+
// the stack as a separate allocated object.
1182+
let mut tmp = MaybeUninit::<T>::uninit();
1183+
copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
1184+
tmp.assume_init()
1185+
}
1186+
#[cfg(not(bootstrap))]
1187+
{
1188+
crate::intrinsics::read_via_copy(src)
1189+
}
11591190
}
11601191
}
11611192

core/tests/fmt/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ fn test_pointer_formats_data_pointer() {
2222
#[test]
2323
fn test_estimated_capacity() {
2424
assert_eq!(format_args!("").estimated_capacity(), 0);
25-
assert_eq!(format_args!("{}", "").estimated_capacity(), 0);
25+
assert_eq!(format_args!("{}", {""}).estimated_capacity(), 0);
2626
assert_eq!(format_args!("Hello").estimated_capacity(), 5);
27-
assert_eq!(format_args!("Hello, {}!", "").estimated_capacity(), 16);
28-
assert_eq!(format_args!("{}, hello!", "World").estimated_capacity(), 0);
29-
assert_eq!(format_args!("{}. 16-bytes piece", "World").estimated_capacity(), 32);
27+
assert_eq!(format_args!("Hello, {}!", {""}).estimated_capacity(), 16);
28+
assert_eq!(format_args!("{}, hello!", {"World"}).estimated_capacity(), 0);
29+
assert_eq!(format_args!("{}. 16-bytes piece", {"World"}).estimated_capacity(), 32);
3030
}
3131

3232
#[test]

0 commit comments

Comments
 (0)