about summary refs log tree commit diff
path: root/library
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-02-26 12:40:05 +0000
committerbors <bors@rust-lang.org>2023-02-26 12:40:05 +0000
commitc4e0cd966062ca67daed20775f4e8a60c28e57df (patch)
treea76fa48fe30ba83326439fadaae6a62890573e4b /library
parent43ee4d15bf201f72c36abd7f02961df87dead441 (diff)
parent9c27fc7d34512a6b3d34247beab4a6ada2476c58 (diff)
downloadrust-c4e0cd966062ca67daed20775f4e8a60c28e57df.tar.gz
rust-c4e0cd966062ca67daed20775f4e8a60c28e57df.zip
Auto merge of #108488 - matthiaskrgr:rollup-i61epcw, r=matthiaskrgr
Rollup of 9 pull requests

Successful merges:

 - #107941 (Treat `str` as containing `[u8]` for auto trait purposes)
 - #108299 (Require `literal`s for some `(u)int_impl!` parameters)
 - #108337 (hir-analysis: make a helpful note)
 - #108379 (Add `ErrorGuaranteed` to `hir::{Expr,Ty}Kind::Err` variants)
 - #108418 (Replace parse_[sth]_expr with parse_expr_[sth] function names)
 - #108424 (rustc_infer: Consolidate obligation elaboration de-duplication)
 - #108475 (Fix `VecDeque::shrink_to` and add tests.)
 - #108482 (statically guarantee that current error codes are documented)
 - #108484 (Remove `from` lang item)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'library')
-rw-r--r--library/alloc/src/collections/vec_deque/mod.rs117
-rw-r--r--library/alloc/src/collections/vec_deque/tests.rs42
-rw-r--r--library/core/src/convert/mod.rs2
-rw-r--r--library/core/src/num/int_macros.rs45
-rw-r--r--library/core/src/num/uint_macros.rs37
5 files changed, 151 insertions, 92 deletions
diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs
index 1573b3d77dc..d4a12509b1c 100644
--- a/library/alloc/src/collections/vec_deque/mod.rs
+++ b/library/alloc/src/collections/vec_deque/mod.rs
@@ -944,65 +944,72 @@ impl<T, A: Allocator> VecDeque<T, A> {
             return;
         }
 
-        if target_cap < self.capacity() {
-            // There are three cases of interest:
-            //   All elements are out of desired bounds
-            //   Elements are contiguous, and head is out of desired bounds
-            //   Elements are discontiguous, and tail is out of desired bounds
+        // There are three cases of interest:
+        //   All elements are out of desired bounds
+        //   Elements are contiguous, and tail is out of desired bounds
+        //   Elements are discontiguous
+        //
+        // At all other times, element positions are unaffected.
+
+        // `head` and `len` are at most `isize::MAX` and `target_cap < self.capacity()`, so nothing can
+        // overflow.
+        let tail_outside = (target_cap + 1..=self.capacity()).contains(&(self.head + self.len));
+
+        if self.len == 0 {
+            self.head = 0;
+        } else if self.head >= target_cap && tail_outside {
+            // Head and tail are both out of bounds, so copy all of them to the front.
             //
-            // At all other times, element positions are unaffected.
+            //  H := head
+            //  L := last element
+            //                    H           L
+            //   [. . . . . . . . o o o o o o o . ]
+            //    H           L
+            //   [o o o o o o o . ]
+            unsafe {
+                // nonoverlapping because `self.head >= target_cap >= self.len`.
+                self.copy_nonoverlapping(self.head, 0, self.len);
+            }
+            self.head = 0;
+        } else if self.head < target_cap && tail_outside {
+            // Head is in bounds, tail is out of bounds.
+            // Copy the overflowing part to the beginning of the
+            // buffer. This won't overlap because `target_cap >= self.len`.
             //
-            // Indicates that elements at the head should be moved.
-
-            let tail_outside = (target_cap + 1..=self.capacity()).contains(&(self.head + self.len));
-            // Move elements from out of desired bounds (positions after target_cap)
-            if self.len == 0 {
-                self.head = 0;
-            } else if self.head >= target_cap && tail_outside {
-                //  H := head
-                //  L := last element
-                //                    H           L
-                //   [. . . . . . . . o o o o o o o . ]
-                //    H           L
-                //   [o o o o o o o . ]
-                unsafe {
-                    // nonoverlapping because self.head >= target_cap >= self.len
-                    self.copy_nonoverlapping(self.head, 0, self.len);
-                }
-                self.head = 0;
-            } else if self.head < target_cap && tail_outside {
-                //  H := head
-                //  L := last element
-                //          H           L
-                //   [. . . o o o o o o o . . . . . . ]
-                //      L   H
-                //   [o o . o o o o o ]
-                let len = self.head + self.len - target_cap;
-                unsafe {
-                    self.copy_nonoverlapping(target_cap, 0, len);
-                }
-            } else if self.head >= target_cap {
-                //  H := head
-                //  L := last element
-                //            L                   H
-                //   [o o o o o . . . . . . . . . o o ]
-                //            L   H
-                //   [o o o o o . o o ]
-                let len = self.capacity() - self.head;
-                let new_head = target_cap - len;
-                unsafe {
-                    // can't use copy_nonoverlapping here for the same reason
-                    // as in `handle_capacity_increase()`
-                    self.copy(self.head, new_head, len);
-                }
-                self.head = new_head;
+            //  H := head
+            //  L := last element
+            //          H           L
+            //   [. . . o o o o o o o . . . . . . ]
+            //      L   H
+            //   [o o . o o o o o ]
+            let len = self.head + self.len - target_cap;
+            unsafe {
+                self.copy_nonoverlapping(target_cap, 0, len);
             }
-
-            self.buf.shrink_to_fit(target_cap);
-
-            debug_assert!(self.head < self.capacity() || self.capacity() == 0);
-            debug_assert!(self.len <= self.capacity());
+        } else if !self.is_contiguous() {
+            // The head slice is at least partially out of bounds, tail is in bounds.
+            // Copy the head backwards so it lines up with the target capacity.
+            // This won't overlap because `target_cap >= self.len`.
+            //
+            //  H := head
+            //  L := last element
+            //            L                   H
+            //   [o o o o o . . . . . . . . . o o ]
+            //            L   H
+            //   [o o o o o . o o ]
+            let head_len = self.capacity() - self.head;
+            let new_head = target_cap - head_len;
+            unsafe {
+                // can't use `copy_nonoverlapping()` here because the new and old
+                // regions for the head might overlap.
+                self.copy(self.head, new_head, head_len);
+            }
+            self.head = new_head;
         }
+        self.buf.shrink_to_fit(target_cap);
+
+        debug_assert!(self.head < self.capacity() || self.capacity() == 0);
+        debug_assert!(self.len <= self.capacity());
     }
 
     /// Shortens the deque, keeping the first `len` elements and dropping
diff --git a/library/alloc/src/collections/vec_deque/tests.rs b/library/alloc/src/collections/vec_deque/tests.rs
index 220ad71beab..205a8ff3c19 100644
--- a/library/alloc/src/collections/vec_deque/tests.rs
+++ b/library/alloc/src/collections/vec_deque/tests.rs
@@ -749,6 +749,48 @@ fn test_drain() {
 }
 
 #[test]
+fn issue_108453() {
+    let mut deque = VecDeque::with_capacity(10);
+
+    deque.push_back(1u8);
+    deque.push_back(2);
+    deque.push_back(3);
+
+    deque.push_front(10);
+    deque.push_front(9);
+
+    deque.shrink_to(9);
+
+    assert_eq!(deque.into_iter().collect::<Vec<_>>(), vec![9, 10, 1, 2, 3]);
+}
+
+#[test]
+fn test_shrink_to() {
+    // test deques with capacity 16 with all possible head positions, lengths and target capacities.
+    let cap = 16;
+
+    for len in 0..cap {
+        for head in 0..cap {
+            let expected = (1..=len).collect::<VecDeque<_>>();
+
+            for target_cap in len..cap {
+                let mut deque = VecDeque::with_capacity(cap);
+                // currently, `with_capacity` always allocates the exact capacity if it's greater than 8.
+                assert_eq!(deque.capacity(), cap);
+
+                // we can let the head point anywhere in the buffer since the deque is empty.
+                deque.head = head;
+                deque.extend(1..=len);
+
+                deque.shrink_to(target_cap);
+
+                assert_eq!(deque, expected);
+            }
+        }
+    }
+}
+
+#[test]
 fn test_shrink_to_fit() {
     // This test checks that every single combination of head and tail position,
     // is tested. Capacity 15 should be large enough to cover every case.
diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs
index f95b880df34..805354be089 100644
--- a/library/core/src/convert/mod.rs
+++ b/library/core/src/convert/mod.rs
@@ -542,7 +542,7 @@ pub trait Into<T>: Sized {
 #[const_trait]
 pub trait From<T>: Sized {
     /// Converts to this type from the input type.
-    #[lang = "from"]
+    #[rustc_diagnostic_item = "from_fn"]
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn from(value: T) -> Self;
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index 572191d0f9b..aec15212d7f 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -3,21 +3,26 @@ macro_rules! int_impl {
         Self = $SelfT:ty,
         ActualT = $ActualT:ident,
         UnsignedT = $UnsignedT:ty,
-        BITS = $BITS:expr,
-        BITS_MINUS_ONE = $BITS_MINUS_ONE:expr,
-        Min = $Min:expr,
-        Max = $Max:expr,
-        rot = $rot:expr,
-        rot_op = $rot_op:expr,
-        rot_result = $rot_result:expr,
-        swap_op = $swap_op:expr,
-        swapped = $swapped:expr,
-        reversed = $reversed:expr,
-        le_bytes = $le_bytes:expr,
-        be_bytes = $be_bytes:expr,
+
+        // There are all for use *only* in doc comments.
+        // As such, they're all passed as literals -- passing them as a string
+        // literal is fine if they need to be multiple code tokens.
+        // In non-comments, use the associated constants rather than these.
+        BITS = $BITS:literal,
+        BITS_MINUS_ONE = $BITS_MINUS_ONE:literal,
+        Min = $Min:literal,
+        Max = $Max:literal,
+        rot = $rot:literal,
+        rot_op = $rot_op:literal,
+        rot_result = $rot_result:literal,
+        swap_op = $swap_op:literal,
+        swapped = $swapped:literal,
+        reversed = $reversed:literal,
+        le_bytes = $le_bytes:literal,
+        be_bytes = $be_bytes:literal,
         to_xe_bytes_doc = $to_xe_bytes_doc:expr,
         from_xe_bytes_doc = $from_xe_bytes_doc:expr,
-        bound_condition = $bound_condition:expr,
+        bound_condition = $bound_condition:literal,
     ) => {
         /// The smallest value that can be represented by this integer type
         #[doc = concat!("(&minus;2<sup>", $BITS_MINUS_ONE, "</sup>", $bound_condition, ").")]
@@ -30,7 +35,7 @@ macro_rules! int_impl {
         #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN, ", stringify!($Min), ");")]
         /// ```
         #[stable(feature = "assoc_int_consts", since = "1.43.0")]
-        pub const MIN: Self = !0 ^ ((!0 as $UnsignedT) >> 1) as Self;
+        pub const MIN: Self = !Self::MAX;
 
         /// The largest value that can be represented by this integer type
         #[doc = concat!("(2<sup>", $BITS_MINUS_ONE, "</sup> &minus; 1", $bound_condition, ").")]
@@ -43,7 +48,7 @@ macro_rules! int_impl {
         #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX, ", stringify!($Max), ");")]
         /// ```
         #[stable(feature = "assoc_int_consts", since = "1.43.0")]
-        pub const MAX: Self = !Self::MIN;
+        pub const MAX: Self = (<$UnsignedT>::MAX >> 1) as Self;
 
         /// The size of this integer type in bits.
         ///
@@ -53,7 +58,7 @@ macro_rules! int_impl {
         #[doc = concat!("assert_eq!(", stringify!($SelfT), "::BITS, ", stringify!($BITS), ");")]
         /// ```
         #[stable(feature = "int_bits_const", since = "1.53.0")]
-        pub const BITS: u32 = $BITS;
+        pub const BITS: u32 = <$UnsignedT>::BITS;
 
         /// Converts a string slice in a given base to an integer.
         ///
@@ -1380,7 +1385,7 @@ macro_rules! int_impl {
             // SAFETY: the masking by the bitsize of the type ensures that we do not shift
             // out of bounds
             unsafe {
-                self.unchecked_shl(rhs & ($BITS - 1))
+                self.unchecked_shl(rhs & (Self::BITS - 1))
             }
         }
 
@@ -1410,7 +1415,7 @@ macro_rules! int_impl {
             // SAFETY: the masking by the bitsize of the type ensures that we do not shift
             // out of bounds
             unsafe {
-                self.unchecked_shr(rhs & ($BITS - 1))
+                self.unchecked_shr(rhs & (Self::BITS - 1))
             }
         }
 
@@ -1916,7 +1921,7 @@ macro_rules! int_impl {
                       without modifying the original"]
         #[inline]
         pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
-            (self.wrapping_shl(rhs), (rhs > ($BITS - 1)))
+            (self.wrapping_shl(rhs), rhs >= Self::BITS)
         }
 
         /// Shifts self right by `rhs` bits.
@@ -1939,7 +1944,7 @@ macro_rules! int_impl {
                       without modifying the original"]
         #[inline]
         pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
-            (self.wrapping_shr(rhs), (rhs > ($BITS - 1)))
+            (self.wrapping_shr(rhs), rhs >= Self::BITS)
         }
 
         /// Computes the absolute value of `self`.
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index c4fe8e966fd..932038a0b01 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -4,19 +4,24 @@ macro_rules! uint_impl {
         ActualT = $ActualT:ident,
         SignedT = $SignedT:ident,
         NonZeroT = $NonZeroT:ident,
-        BITS = $BITS:expr,
-        MAX = $MaxV:expr,
-        rot = $rot:expr,
-        rot_op = $rot_op:expr,
-        rot_result = $rot_result:expr,
-        swap_op = $swap_op:expr,
-        swapped = $swapped:expr,
-        reversed = $reversed:expr,
-        le_bytes = $le_bytes:expr,
-        be_bytes = $be_bytes:expr,
+
+        // There are all for use *only* in doc comments.
+        // As such, they're all passed as literals -- passing them as a string
+        // literal is fine if they need to be multiple code tokens.
+        // In non-comments, use the associated constants rather than these.
+        BITS = $BITS:literal,
+        MAX = $MaxV:literal,
+        rot = $rot:literal,
+        rot_op = $rot_op:literal,
+        rot_result = $rot_result:literal,
+        swap_op = $swap_op:literal,
+        swapped = $swapped:literal,
+        reversed = $reversed:literal,
+        le_bytes = $le_bytes:literal,
+        be_bytes = $be_bytes:literal,
         to_xe_bytes_doc = $to_xe_bytes_doc:expr,
         from_xe_bytes_doc = $from_xe_bytes_doc:expr,
-        bound_condition = $bound_condition:expr,
+        bound_condition = $bound_condition:literal,
     ) => {
         /// The smallest value that can be represented by this integer type.
         ///
@@ -51,7 +56,7 @@ macro_rules! uint_impl {
         #[doc = concat!("assert_eq!(", stringify!($SelfT), "::BITS, ", stringify!($BITS), ");")]
         /// ```
         #[stable(feature = "int_bits_const", since = "1.53.0")]
-        pub const BITS: u32 = $BITS;
+        pub const BITS: u32 = Self::MAX.count_ones();
 
         /// Converts a string slice in a given base to an integer.
         ///
@@ -1403,7 +1408,7 @@ macro_rules! uint_impl {
             // SAFETY: the masking by the bitsize of the type ensures that we do not shift
             // out of bounds
             unsafe {
-                self.unchecked_shl(rhs & ($BITS - 1))
+                self.unchecked_shl(rhs & (Self::BITS - 1))
             }
         }
 
@@ -1436,7 +1441,7 @@ macro_rules! uint_impl {
             // SAFETY: the masking by the bitsize of the type ensures that we do not shift
             // out of bounds
             unsafe {
-                self.unchecked_shr(rhs & ($BITS - 1))
+                self.unchecked_shr(rhs & (Self::BITS - 1))
             }
         }
 
@@ -1860,7 +1865,7 @@ macro_rules! uint_impl {
                       without modifying the original"]
         #[inline(always)]
         pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
-            (self.wrapping_shl(rhs), (rhs > ($BITS - 1)))
+            (self.wrapping_shl(rhs), rhs >= Self::BITS)
         }
 
         /// Shifts self right by `rhs` bits.
@@ -1885,7 +1890,7 @@ macro_rules! uint_impl {
                       without modifying the original"]
         #[inline(always)]
         pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
-            (self.wrapping_shr(rhs), (rhs > ($BITS - 1)))
+            (self.wrapping_shr(rhs), rhs >= Self::BITS)
         }
 
         /// Raises self to the power of `exp`, using exponentiation by squaring.