about summary refs log tree commit diff
path: root/library/core/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-07-25 22:57:23 +0000
committerbors <bors@rust-lang.org>2022-07-25 22:57:23 +0000
commita86705942c4cfaaee60f2e7308ca2bca703a710f (patch)
tree133bd48f82d214929324a7e2337871b505adb8e5 /library/core/src
parent6dbae3ad19309bb541d9e76638e6aa4b5449f29a (diff)
parente58bfacd90bea9fab8bdbd9cf6129290937fed63 (diff)
downloadrust-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.rs74
-rw-r--r--library/core/src/intrinsics.rs51
-rw-r--r--library/core/src/lib.rs1
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)]