summaryrefslogtreecommitdiffstats
path: root/library/alloc/tests
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--library/alloc/tests/autotraits.rs293
-rw-r--r--library/alloc/tests/lib.rs7
-rw-r--r--library/alloc/tests/vec.rs65
3 files changed, 333 insertions, 32 deletions
diff --git a/library/alloc/tests/autotraits.rs b/library/alloc/tests/autotraits.rs
new file mode 100644
index 000000000..8ff5f0abe
--- /dev/null
+++ b/library/alloc/tests/autotraits.rs
@@ -0,0 +1,293 @@
+fn require_sync<T: Sync>(_: T) {}
+fn require_send_sync<T: Send + Sync>(_: T) {}
+
+struct NotSend(*const ());
+unsafe impl Sync for NotSend {}
+
+#[test]
+fn test_btree_map() {
+ // Tests of this form are prone to https://github.com/rust-lang/rust/issues/64552.
+ //
+ // In theory the async block's future would be Send if the value we hold
+ // across the await point is Send, and Sync if the value we hold across the
+ // await point is Sync.
+ //
+ // We test autotraits in this convoluted way, instead of a straightforward
+ // `require_send_sync::<TypeIWantToTest>()`, because the interaction with
+ // generators exposes some current limitations in rustc's ability to prove a
+ // lifetime bound on the erased generator witness types. See the above link.
+ //
+ // A typical way this would surface in real code is:
+ //
+ // fn spawn<T: Future + Send>(_: T) {}
+ //
+ // async fn f() {
+ // let map = BTreeMap::<u32, Box<dyn Send + Sync>>::new();
+ // for _ in &map {
+ // async {}.await;
+ // }
+ // }
+ //
+ // fn main() {
+ // spawn(f());
+ // }
+ //
+ // where with some unintentionally overconstrained Send impls in liballoc's
+ // internals, the future might incorrectly not be Send even though every
+ // single type involved in the program is Send and Sync.
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_map::Iter<'_, &u32, &u32>>;
+ async {}.await;
+ });
+
+ // Testing like this would not catch all issues that the above form catches.
+ require_send_sync(None::<alloc::collections::btree_map::Iter<'_, &u32, &u32>>);
+
+ require_sync(async {
+ let _v = None::<alloc::collections::btree_map::Iter<'_, u32, NotSend>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_map::BTreeMap<&u32, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<
+ alloc::collections::btree_map::DrainFilter<
+ '_,
+ &u32,
+ &u32,
+ fn(&&u32, &mut &u32) -> bool,
+ >,
+ >;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_map::Entry<'_, &u32, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_map::IntoIter<&u32, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_map::IntoKeys<&u32, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_map::IntoValues<&u32, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_map::Iter<'_, &u32, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_map::IterMut<'_, &u32, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_map::Keys<'_, &u32, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_map::OccupiedEntry<'_, &u32, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_map::OccupiedError<'_, &u32, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_map::Range<'_, &u32, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_map::RangeMut<'_, &u32, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_map::VacantEntry<'_, &u32, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_map::Values<'_, &u32, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_map::ValuesMut<'_, &u32, &u32>>;
+ async {}.await;
+ });
+}
+
+#[test]
+fn test_btree_set() {
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_set::BTreeSet<&u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_set::Difference<'_, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_set::DrainFilter<'_, &u32, fn(&&u32) -> bool>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_set::Intersection<'_, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_set::IntoIter<&u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_set::Iter<'_, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_set::Range<'_, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_set::SymmetricDifference<'_, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_set::Union<'_, &u32>>;
+ async {}.await;
+ });
+}
+
+#[test]
+fn test_binary_heap() {
+ require_send_sync(async {
+ let _v = None::<alloc::collections::binary_heap::BinaryHeap<&u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::binary_heap::Drain<'_, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::binary_heap::DrainSorted<'_, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::binary_heap::IntoIter<&u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::binary_heap::IntoIterSorted<&u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::binary_heap::Iter<'_, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::binary_heap::PeekMut<'_, &u32>>;
+ async {}.await;
+ });
+}
+
+#[test]
+fn test_linked_list() {
+ require_send_sync(async {
+ let _v = None::<alloc::collections::linked_list::Cursor<'_, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::linked_list::CursorMut<'_, &u32>>;
+ async {}.await;
+ });
+
+ // FIXME
+ /*
+ require_send_sync(async {
+ let _v =
+ None::<alloc::collections::linked_list::DrainFilter<'_, &u32, fn(&mut &u32) -> bool>>;
+ async {}.await;
+ });
+ */
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::linked_list::IntoIter<&u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::linked_list::Iter<'_, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::linked_list::IterMut<'_, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::linked_list::LinkedList<&u32>>;
+ async {}.await;
+ });
+}
+
+#[test]
+fn test_vec_deque() {
+ require_send_sync(async {
+ let _v = None::<alloc::collections::vec_deque::Drain<'_, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::vec_deque::IntoIter<&u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::vec_deque::Iter<'_, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::vec_deque::IterMut<'_, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::vec_deque::VecDeque<&u32>>;
+ async {}.await;
+ });
+}
diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs
index 490c0d8f7..ffc5ca7a5 100644
--- a/library/alloc/tests/lib.rs
+++ b/library/alloc/tests/lib.rs
@@ -2,6 +2,7 @@
#![feature(alloc_layout_extra)]
#![feature(assert_matches)]
#![feature(box_syntax)]
+#![feature(btree_drain_filter)]
#![feature(cow_is_borrowed)]
#![feature(const_box)]
#![feature(const_convert)]
@@ -14,6 +15,8 @@
#![feature(core_intrinsics)]
#![feature(drain_filter)]
#![feature(exact_size_is_empty)]
+#![feature(linked_list_cursors)]
+#![feature(map_try_insert)]
#![feature(new_uninit)]
#![feature(pattern)]
#![feature(trusted_len)]
@@ -32,7 +35,7 @@
#![feature(slice_group_by)]
#![feature(slice_partition_dedup)]
#![feature(string_remove_matches)]
-#![feature(const_btree_new)]
+#![feature(const_btree_len)]
#![feature(const_default_impls)]
#![feature(const_trait_impl)]
#![feature(const_str_from_utf8)]
@@ -41,7 +44,6 @@
#![feature(pointer_is_aligned)]
#![feature(slice_flatten)]
#![feature(thin_box)]
-#![feature(bench_black_box)]
#![feature(strict_provenance)]
#![feature(once_cell)]
#![feature(drain_keep_rest)]
@@ -50,6 +52,7 @@ use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
mod arc;
+mod autotraits;
mod borrow;
mod boxed;
mod btree_set_hash;
diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs
index f140fc414..e02711870 100644
--- a/library/alloc/tests/vec.rs
+++ b/library/alloc/tests/vec.rs
@@ -1191,48 +1191,53 @@ fn test_from_iter_specialization_panic_during_iteration_drops() {
}
#[test]
-fn test_from_iter_specialization_panic_during_drop_leaks() {
- static mut DROP_COUNTER: usize = 0;
+fn test_from_iter_specialization_panic_during_drop_doesnt_leak() {
+ static mut DROP_COUNTER_OLD: [usize; 5] = [0; 5];
+ static mut DROP_COUNTER_NEW: [usize; 2] = [0; 2];
#[derive(Debug)]
- enum Droppable {
- DroppedTwice(Box<i32>),
- PanicOnDrop,
- }
+ struct Old(usize);
- impl Drop for Droppable {
+ impl Drop for Old {
fn drop(&mut self) {
- match self {
- Droppable::DroppedTwice(_) => {
- unsafe {
- DROP_COUNTER += 1;
- }
- println!("Dropping!")
- }
- Droppable::PanicOnDrop => {
- if !std::thread::panicking() {
- panic!();
- }
- }
+ unsafe {
+ DROP_COUNTER_OLD[self.0] += 1;
+ }
+
+ if self.0 == 3 {
+ panic!();
}
+
+ println!("Dropped Old: {}", self.0);
}
}
- let mut to_free: *mut Droppable = core::ptr::null_mut();
- let mut cap = 0;
+ #[derive(Debug)]
+ struct New(usize);
+
+ impl Drop for New {
+ fn drop(&mut self) {
+ unsafe {
+ DROP_COUNTER_NEW[self.0] += 1;
+ }
+
+ println!("Dropped New: {}", self.0);
+ }
+ }
let _ = std::panic::catch_unwind(AssertUnwindSafe(|| {
- let mut v = vec![Droppable::DroppedTwice(Box::new(123)), Droppable::PanicOnDrop];
- to_free = v.as_mut_ptr();
- cap = v.capacity();
- let _ = v.into_iter().take(0).collect::<Vec<_>>();
+ let v = vec![Old(0), Old(1), Old(2), Old(3), Old(4)];
+ let _ = v.into_iter().map(|x| New(x.0)).take(2).collect::<Vec<_>>();
}));
- assert_eq!(unsafe { DROP_COUNTER }, 1);
- // clean up the leak to keep miri happy
- unsafe {
- drop(Vec::from_raw_parts(to_free, 0, cap));
- }
+ assert_eq!(unsafe { DROP_COUNTER_OLD[0] }, 1);
+ assert_eq!(unsafe { DROP_COUNTER_OLD[1] }, 1);
+ assert_eq!(unsafe { DROP_COUNTER_OLD[2] }, 1);
+ assert_eq!(unsafe { DROP_COUNTER_OLD[3] }, 1);
+ assert_eq!(unsafe { DROP_COUNTER_OLD[4] }, 1);
+
+ assert_eq!(unsafe { DROP_COUNTER_NEW[0] }, 1);
+ assert_eq!(unsafe { DROP_COUNTER_NEW[1] }, 1);
}
// regression test for issue #85322. Peekable previously implemented InPlaceIterable,