Skip to content

Commit 15600fa

Browse files
committed
Merge from rustc
2 parents b58b950 + e8612fd commit 15600fa

File tree

37 files changed

+953
-602
lines changed

37 files changed

+953
-602
lines changed

alloc/src/collections/vec_deque/mod.rs

Lines changed: 62 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -944,65 +944,72 @@ impl<T, A: Allocator> VecDeque<T, A> {
944944
return;
945945
}
946946

947-
if target_cap < self.capacity() {
948-
// There are three cases of interest:
949-
// All elements are out of desired bounds
950-
// Elements are contiguous, and head is out of desired bounds
951-
// Elements are discontiguous, and tail is out of desired bounds
947+
// There are three cases of interest:
948+
// All elements are out of desired bounds
949+
// Elements are contiguous, and tail is out of desired bounds
950+
// Elements are discontiguous
951+
//
952+
// At all other times, element positions are unaffected.
953+
954+
// `head` and `len` are at most `isize::MAX` and `target_cap < self.capacity()`, so nothing can
955+
// overflow.
956+
let tail_outside = (target_cap + 1..=self.capacity()).contains(&(self.head + self.len));
957+
958+
if self.len == 0 {
959+
self.head = 0;
960+
} else if self.head >= target_cap && tail_outside {
961+
// Head and tail are both out of bounds, so copy all of them to the front.
952962
//
953-
// At all other times, element positions are unaffected.
963+
// H := head
964+
// L := last element
965+
// H L
966+
// [. . . . . . . . o o o o o o o . ]
967+
// H L
968+
// [o o o o o o o . ]
969+
unsafe {
970+
// nonoverlapping because `self.head >= target_cap >= self.len`.
971+
self.copy_nonoverlapping(self.head, 0, self.len);
972+
}
973+
self.head = 0;
974+
} else if self.head < target_cap && tail_outside {
975+
// Head is in bounds, tail is out of bounds.
976+
// Copy the overflowing part to the beginning of the
977+
// buffer. This won't overlap because `target_cap >= self.len`.
954978
//
955-
// Indicates that elements at the head should be moved.
956-
957-
let tail_outside = (target_cap + 1..=self.capacity()).contains(&(self.head + self.len));
958-
// Move elements from out of desired bounds (positions after target_cap)
959-
if self.len == 0 {
960-
self.head = 0;
961-
} else if self.head >= target_cap && tail_outside {
962-
// H := head
963-
// L := last element
964-
// H L
965-
// [. . . . . . . . o o o o o o o . ]
966-
// H L
967-
// [o o o o o o o . ]
968-
unsafe {
969-
// nonoverlapping because self.head >= target_cap >= self.len
970-
self.copy_nonoverlapping(self.head, 0, self.len);
971-
}
972-
self.head = 0;
973-
} else if self.head < target_cap && tail_outside {
974-
// H := head
975-
// L := last element
976-
// H L
977-
// [. . . o o o o o o o . . . . . . ]
978-
// L H
979-
// [o o . o o o o o ]
980-
let len = self.head + self.len - target_cap;
981-
unsafe {
982-
self.copy_nonoverlapping(target_cap, 0, len);
983-
}
984-
} else if self.head >= target_cap {
985-
// H := head
986-
// L := last element
987-
// L H
988-
// [o o o o o . . . . . . . . . o o ]
989-
// L H
990-
// [o o o o o . o o ]
991-
let len = self.capacity() - self.head;
992-
let new_head = target_cap - len;
993-
unsafe {
994-
// can't use copy_nonoverlapping here for the same reason
995-
// as in `handle_capacity_increase()`
996-
self.copy(self.head, new_head, len);
997-
}
998-
self.head = new_head;
979+
// H := head
980+
// L := last element
981+
// H L
982+
// [. . . o o o o o o o . . . . . . ]
983+
// L H
984+
// [o o . o o o o o ]
985+
let len = self.head + self.len - target_cap;
986+
unsafe {
987+
self.copy_nonoverlapping(target_cap, 0, len);
999988
}
1000-
1001-
self.buf.shrink_to_fit(target_cap);
1002-
1003-
debug_assert!(self.head < self.capacity() || self.capacity() == 0);
1004-
debug_assert!(self.len <= self.capacity());
989+
} else if !self.is_contiguous() {
990+
// The head slice is at least partially out of bounds, tail is in bounds.
991+
// Copy the head backwards so it lines up with the target capacity.
992+
// This won't overlap because `target_cap >= self.len`.
993+
//
994+
// H := head
995+
// L := last element
996+
// L H
997+
// [o o o o o . . . . . . . . . o o ]
998+
// L H
999+
// [o o o o o . o o ]
1000+
let head_len = self.capacity() - self.head;
1001+
let new_head = target_cap - head_len;
1002+
unsafe {
1003+
// can't use `copy_nonoverlapping()` here because the new and old
1004+
// regions for the head might overlap.
1005+
self.copy(self.head, new_head, head_len);
1006+
}
1007+
self.head = new_head;
10051008
}
1009+
self.buf.shrink_to_fit(target_cap);
1010+
1011+
debug_assert!(self.head < self.capacity() || self.capacity() == 0);
1012+
debug_assert!(self.len <= self.capacity());
10061013
}
10071014

10081015
/// Shortens the deque, keeping the first `len` elements and dropping

alloc/src/collections/vec_deque/tests.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,48 @@ fn test_drain() {
748748
}
749749
}
750750

751+
#[test]
752+
fn issue_108453() {
753+
let mut deque = VecDeque::with_capacity(10);
754+
755+
deque.push_back(1u8);
756+
deque.push_back(2);
757+
deque.push_back(3);
758+
759+
deque.push_front(10);
760+
deque.push_front(9);
761+
762+
deque.shrink_to(9);
763+
764+
assert_eq!(deque.into_iter().collect::<Vec<_>>(), vec![9, 10, 1, 2, 3]);
765+
}
766+
767+
#[test]
768+
fn test_shrink_to() {
769+
// test deques with capacity 16 with all possible head positions, lengths and target capacities.
770+
let cap = 16;
771+
772+
for len in 0..cap {
773+
for head in 0..cap {
774+
let expected = (1..=len).collect::<VecDeque<_>>();
775+
776+
for target_cap in len..cap {
777+
let mut deque = VecDeque::with_capacity(cap);
778+
// currently, `with_capacity` always allocates the exact capacity if it's greater than 8.
779+
assert_eq!(deque.capacity(), cap);
780+
781+
// we can let the head point anywhere in the buffer since the deque is empty.
782+
deque.head = head;
783+
deque.extend(1..=len);
784+
785+
deque.shrink_to(target_cap);
786+
787+
assert_eq!(deque, expected);
788+
}
789+
}
790+
}
791+
}
792+
751793
#[test]
752794
fn test_shrink_to_fit() {
753795
// This test checks that every single combination of head and tail position,

alloc/src/vec/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -378,8 +378,8 @@ mod spec_extend;
378378
/// Currently, `Vec` does not guarantee the order in which elements are dropped.
379379
/// The order has changed in the past and may change again.
380380
///
381-
/// [`get`]: ../../std/vec/struct.Vec.html#method.get
382-
/// [`get_mut`]: ../../std/vec/struct.Vec.html#method.get_mut
381+
/// [`get`]: slice::get
382+
/// [`get_mut`]: slice::get_mut
383383
/// [`String`]: crate::string::String
384384
/// [`&str`]: type@str
385385
/// [`shrink_to_fit`]: Vec::shrink_to_fit

core/src/convert/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,7 @@ pub trait Into<T>: Sized {
542542
#[const_trait]
543543
pub trait From<T>: Sized {
544544
/// Converts to this type from the input type.
545-
#[lang = "from"]
545+
#[rustc_diagnostic_item = "from_fn"]
546546
#[must_use]
547547
#[stable(feature = "rust1", since = "1.0.0")]
548548
fn from(value: T) -> Self;

core/src/iter/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@
278278
//!
279279
//! ```
280280
//! # #![allow(unused_must_use)]
281+
//! # #![cfg_attr(not(bootstrap), allow(map_unit_fn))]
281282
//! let v = vec![1, 2, 3, 4, 5];
282283
//! v.iter().map(|x| println!("{x}"));
283284
//! ```

0 commit comments

Comments
 (0)