diff options
| author | bors <bors@rust-lang.org> | 2023-02-26 12:40:05 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-02-26 12:40:05 +0000 |
| commit | c4e0cd966062ca67daed20775f4e8a60c28e57df (patch) | |
| tree | a76fa48fe30ba83326439fadaae6a62890573e4b /library | |
| parent | 43ee4d15bf201f72c36abd7f02961df87dead441 (diff) | |
| parent | 9c27fc7d34512a6b3d34247beab4a6ada2476c58 (diff) | |
| download | rust-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.rs | 117 | ||||
| -rw-r--r-- | library/alloc/src/collections/vec_deque/tests.rs | 42 | ||||
| -rw-r--r-- | library/core/src/convert/mod.rs | 2 | ||||
| -rw-r--r-- | library/core/src/num/int_macros.rs | 45 | ||||
| -rw-r--r-- | library/core/src/num/uint_macros.rs | 37 |
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!("(−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> − 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. |
