diff options
| author | bors <bors@rust-lang.org> | 2022-07-25 22:57:23 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-07-25 22:57:23 +0000 |
| commit | a86705942c4cfaaee60f2e7308ca2bca703a710f (patch) | |
| tree | 133bd48f82d214929324a7e2337871b505adb8e5 /library/core/src | |
| parent | 6dbae3ad19309bb541d9e76638e6aa4b5449f29a (diff) | |
| parent | e58bfacd90bea9fab8bdbd9cf6129290937fed63 (diff) | |
| download | rust-a86705942c4cfaaee60f2e7308ca2bca703a710f.tar.gz rust-a86705942c4cfaaee60f2e7308ca2bca703a710f.zip | |
Auto merge of #99735 - JohnTitor:rollup-d93jyr2, r=JohnTitor
Rollup of 9 pull requests Successful merges: - #92390 (Constify a few `(Partial)Ord` impls) - #97077 (Simplify some code that depend on Deref) - #98710 (correct the output of a `capacity` method example) - #99084 (clarify how write_bytes can lead to UB due to invalid values) - #99178 (Lighten up const_prop_lint, reusing const_prop) - #99673 (don't ICE on invalid dyn calls) - #99703 (Expose size_hint() for TokenStream's iterator) - #99709 (`Inherited` always has `TypeckResults` available) - #99713 (Fix sidebar background) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'library/core/src')
| -rw-r--r-- | library/core/src/cmp.rs | 74 | ||||
| -rw-r--r-- | library/core/src/intrinsics.rs | 51 | ||||
| -rw-r--r-- | library/core/src/lib.rs | 1 |
3 files changed, 70 insertions, 56 deletions
diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index 1d3466696ed..ac286c171f0 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -22,6 +22,8 @@ #![stable(feature = "rust1", since = "1.0.0")] +use crate::marker::Destruct; + use self::Ordering::*; /// Trait for equality comparisons which are [partial equivalence @@ -603,7 +605,8 @@ impl Ordering { pub struct Reverse<T>(#[stable(feature = "reverse_cmp_key", since = "1.19.0")] pub T); #[stable(feature = "reverse_cmp_key", since = "1.19.0")] -impl<T: PartialOrd> PartialOrd for Reverse<T> { +#[rustc_const_unstable(feature = "const_cmp", issue = "92391")] +impl<T: ~const PartialOrd> const PartialOrd for Reverse<T> { #[inline] fn partial_cmp(&self, other: &Reverse<T>) -> Option<Ordering> { other.0.partial_cmp(&self.0) @@ -761,6 +764,7 @@ impl<T: Clone> Clone for Reverse<T> { #[doc(alias = ">=")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "Ord"] +#[const_trait] pub trait Ord: Eq + PartialOrd<Self> { /// This method returns an [`Ordering`] between `self` and `other`. /// @@ -796,8 +800,15 @@ pub trait Ord: Eq + PartialOrd<Self> { fn max(self, other: Self) -> Self where Self: Sized, + Self: ~const Destruct, { - max_by(self, other, Ord::cmp) + // HACK(fee1-dead): go back to using `self.max_by(other, Ord::cmp)` + // when trait methods are allowed to be used when a const closure is + // expected. + match self.cmp(&other) { + Ordering::Less | Ordering::Equal => other, + Ordering::Greater => self, + } } /// Compares and returns the minimum of two values. @@ -816,8 +827,15 @@ pub trait Ord: Eq + PartialOrd<Self> { fn min(self, other: Self) -> Self where Self: Sized, + Self: ~const Destruct, { - min_by(self, other, Ord::cmp) + // HACK(fee1-dead): go back to using `self.min_by(other, Ord::cmp)` + // when trait methods are allowed to be used when a const closure is + // expected. + match self.cmp(&other) { + Ordering::Less | Ordering::Equal => self, + Ordering::Greater => other, + } } /// Restrict a value to a certain interval. @@ -841,6 +859,8 @@ pub trait Ord: Eq + PartialOrd<Self> { fn clamp(self, min: Self, max: Self) -> Self where Self: Sized, + Self: ~const Destruct, + Self: ~const PartialOrd, { assert!(min <= max); if self < min { @@ -862,7 +882,8 @@ pub macro Ord($item:item) { } #[stable(feature = "rust1", since = "1.0.0")] -impl Ord for Ordering { +#[rustc_const_unstable(feature = "const_cmp", issue = "92391")] +impl const Ord for Ordering { #[inline] fn cmp(&self, other: &Ordering) -> Ordering { (*self as i32).cmp(&(*other as i32)) @@ -870,7 +891,8 @@ impl Ord for Ordering { } #[stable(feature = "rust1", since = "1.0.0")] -impl PartialOrd for Ordering { +#[rustc_const_unstable(feature = "const_cmp", issue = "92391")] +impl const PartialOrd for Ordering { #[inline] fn partial_cmp(&self, other: &Ordering) -> Option<Ordering> { (*self as i32).partial_cmp(&(*other as i32)) @@ -1187,8 +1209,9 @@ pub macro PartialOrd($item:item) { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature = "const_cmp", issue = "92391")] #[cfg_attr(not(test), rustc_diagnostic_item = "cmp_min")] -pub fn min<T: Ord>(v1: T, v2: T) -> T { +pub const fn min<T: ~const Ord + ~const Destruct>(v1: T, v2: T) -> T { v1.min(v2) } @@ -1250,8 +1273,9 @@ pub fn min_by_key<T, F: FnMut(&T) -> K, K: Ord>(v1: T, v2: T, mut f: F) -> T { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature = "const_cmp", issue = "92391")] #[cfg_attr(not(test), rustc_diagnostic_item = "cmp_max")] -pub fn max<T: Ord>(v1: T, v2: T) -> T { +pub const fn max<T: ~const Ord + ~const Destruct>(v1: T, v2: T) -> T { v1.max(v2) } @@ -1304,7 +1328,8 @@ mod impls { macro_rules! partial_eq_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - impl PartialEq for $t { + #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] + impl const PartialEq for $t { #[inline] fn eq(&self, other: &$t) -> bool { (*self) == (*other) } #[inline] @@ -1314,7 +1339,8 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl PartialEq for () { + #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] + impl const PartialEq for () { #[inline] fn eq(&self, _other: &()) -> bool { true @@ -1341,7 +1367,8 @@ mod impls { macro_rules! partial_ord_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - impl PartialOrd for $t { + #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] + impl const PartialOrd for $t { #[inline] fn partial_cmp(&self, other: &$t) -> Option<Ordering> { match (*self <= *other, *self >= *other) { @@ -1364,7 +1391,8 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl PartialOrd for () { + #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] + impl const PartialOrd for () { #[inline] fn partial_cmp(&self, _: &()) -> Option<Ordering> { Some(Equal) @@ -1372,7 +1400,8 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl PartialOrd for bool { + #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] + impl const PartialOrd for bool { #[inline] fn partial_cmp(&self, other: &bool) -> Option<Ordering> { Some(self.cmp(other)) @@ -1384,7 +1413,8 @@ mod impls { macro_rules! ord_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - impl PartialOrd for $t { + #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] + impl const PartialOrd for $t { #[inline] fn partial_cmp(&self, other: &$t) -> Option<Ordering> { Some(self.cmp(other)) @@ -1400,7 +1430,8 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl Ord for $t { + #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] + impl const Ord for $t { #[inline] fn cmp(&self, other: &$t) -> Ordering { // The order here is important to generate more optimal assembly. @@ -1414,7 +1445,8 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl Ord for () { + #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] + impl const Ord for () { #[inline] fn cmp(&self, _other: &()) -> Ordering { Equal @@ -1422,7 +1454,8 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl Ord for bool { + #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] + impl const Ord for bool { #[inline] fn cmp(&self, other: &bool) -> Ordering { // Casting to i8's and converting the difference to an Ordering generates @@ -1441,7 +1474,8 @@ mod impls { ord_impl! { char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } #[unstable(feature = "never_type", issue = "35121")] - impl PartialEq for ! { + #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] + impl const PartialEq for ! { fn eq(&self, _: &!) -> bool { *self } @@ -1451,14 +1485,16 @@ mod impls { impl Eq for ! {} #[unstable(feature = "never_type", issue = "35121")] - impl PartialOrd for ! { + #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] + impl const PartialOrd for ! { fn partial_cmp(&self, _: &!) -> Option<Ordering> { *self } } #[unstable(feature = "never_type", issue = "35121")] - impl Ord for ! { + #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] + impl const Ord for ! { fn cmp(&self, _: &!) -> Ordering { *self } diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 4a595902282..7e65f4ebdad 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2566,14 +2566,23 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) { /// /// * `dst` must be properly aligned. /// -/// Additionally, the caller must ensure that writing `count * -/// size_of::<T>()` bytes to the given region of memory results in a valid -/// value of `T`. Using a region of memory typed as a `T` that contains an -/// invalid value of `T` is undefined behavior. -/// /// Note that even if the effectively copied size (`count * size_of::<T>()`) is /// `0`, the pointer must be non-null and properly aligned. /// +/// Additionally, note that changing `*dst` in this way can easily lead to undefined behavior (UB) +/// later if the written bytes are not a valid representation of some `T`. For instance, the +/// following is an **incorrect** use of this function: +/// +/// ```rust,no_run +/// unsafe { +/// let mut value: u8 = 0; +/// let ptr: *mut bool = &mut value as *mut u8 as *mut bool; +/// let _bool = ptr.read(); // This is fine, `ptr` points to a valid `bool`. +/// ptr.write_bytes(42u8, 1); // This function itself does not cause UB... +/// let _bool = ptr.read(); // ...but it makes this operation UB! ⚠️ +/// } +/// ``` +/// /// [valid]: crate::ptr#safety /// /// # Examples @@ -2590,38 +2599,6 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) { /// } /// assert_eq!(vec, [0xfefefefe, 0xfefefefe, 0, 0]); /// ``` -/// -/// Creating an invalid value: -/// -/// ``` -/// use std::ptr; -/// -/// let mut v = Box::new(0i32); -/// -/// unsafe { -/// // Leaks the previously held value by overwriting the `Box<T>` with -/// // a null pointer. -/// ptr::write_bytes(&mut v as *mut Box<i32>, 0, 1); -/// } -/// -/// // At this point, using or dropping `v` results in undefined behavior. -/// // drop(v); // ERROR -/// -/// // Even leaking `v` "uses" it, and hence is undefined behavior. -/// // mem::forget(v); // ERROR -/// -/// // In fact, `v` is invalid according to basic type layout invariants, so *any* -/// // operation touching it is undefined behavior. -/// // let v2 = v; // ERROR -/// -/// unsafe { -/// // Let us instead put in a valid value -/// ptr::write(&mut v as *mut Box<i32>, Box::new(42i32)); -/// } -/// -/// // Now the box is fine -/// assert_eq!(*v, 42); -/// ``` #[doc(alias = "memset")] #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(bootstrap), rustc_allowed_through_unstable_modules)] diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index f24a7ab61ae..30f2f0ee05c 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -105,6 +105,7 @@ #![feature(const_cell_into_inner)] #![feature(const_char_convert)] #![feature(const_clone)] +#![feature(const_cmp)] #![feature(const_discriminant)] #![feature(const_eval_select)] #![feature(const_float_bits_conv)] |
