diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 0bddd7a990699..cacbd54b6c246 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -178,6 +178,8 @@ pub struct BTreeMap< length: usize, /// `ManuallyDrop` to control drop order (needs to be dropped after all the nodes). pub(super) alloc: ManuallyDrop, + // For dropck; the `Box` avoids making the `Unpin` impl more strict than before + _marker: PhantomData>, } #[stable(feature = "btree_drop", since = "1.7.0")] @@ -187,6 +189,19 @@ unsafe impl<#[may_dangle] K, #[may_dangle] V, A: Allocator + Clone> Drop for BTr } } +// FIXME: This implementation is "wrong", but changing it would be a breaking change. +// (The bounds of the automatic `UnwindSafe` implementation have been like this since Rust 1.50.) +// Maybe we can fix it nonetheless with a crater run, or if the `UnwindSafe` +// traits are deprecated, or disarmed (no longer causing hard errors) in the future. +#[stable(feature = "btree_unwindsafe", since = "1.64.0")] +impl core::panic::UnwindSafe for BTreeMap +where + A: core::panic::UnwindSafe, + K: core::panic::RefUnwindSafe, + V: core::panic::RefUnwindSafe, +{ +} + #[stable(feature = "rust1", since = "1.0.0")] impl Clone for BTreeMap { fn clone(&self) -> BTreeMap { @@ -204,6 +219,7 @@ impl Clone for BTreeMap { root: Some(Root::new(alloc.clone())), length: 0, alloc: ManuallyDrop::new(alloc), + _marker: PhantomData, }; { @@ -567,7 +583,7 @@ impl BTreeMap { #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")] #[must_use] pub const fn new() -> BTreeMap { - BTreeMap { root: None, length: 0, alloc: ManuallyDrop::new(Global) } + BTreeMap { root: None, length: 0, alloc: ManuallyDrop::new(Global), _marker: PhantomData } } } @@ -593,6 +609,7 @@ impl BTreeMap { root: mem::replace(&mut self.root, None), length: mem::replace(&mut self.length, 0), alloc: self.alloc.clone(), + _marker: PhantomData, }); } @@ -615,7 +632,7 @@ impl BTreeMap { /// ``` #[unstable(feature = "btreemap_alloc", issue = "32838")] pub fn new_in(alloc: A) -> BTreeMap { - BTreeMap { root: None, length: 0, alloc: ManuallyDrop::new(alloc) } + BTreeMap { root: None, length: 0, alloc: ManuallyDrop::new(alloc), _marker: PhantomData } } } @@ -1320,7 +1337,12 @@ impl BTreeMap { let (new_left_len, right_len) = Root::calc_split_length(total_num, &left_root, &right_root); self.length = new_left_len; - BTreeMap { root: Some(right_root), length: right_len, alloc: self.alloc.clone() } + BTreeMap { + root: Some(right_root), + length: right_len, + alloc: self.alloc.clone(), + _marker: PhantomData, + } } /// Creates an iterator that visits all elements (key-value pairs) in @@ -1445,7 +1467,7 @@ impl BTreeMap { let mut root = Root::new(alloc.clone()); let mut length = 0; root.bulk_push(DedupSortedIter::new(iter.into_iter()), &mut length, alloc.clone()); - BTreeMap { root: Some(root), length, alloc: ManuallyDrop::new(alloc) } + BTreeMap { root: Some(root), length, alloc: ManuallyDrop::new(alloc), _marker: PhantomData } } } diff --git a/src/test/ui/btreemap/btreemap_dropck.rs b/src/test/ui/btreemap/btreemap_dropck.rs new file mode 100644 index 0000000000000..c58727df30cae --- /dev/null +++ b/src/test/ui/btreemap/btreemap_dropck.rs @@ -0,0 +1,16 @@ +struct PrintOnDrop<'a>(&'a str); + +impl Drop for PrintOnDrop<'_> { + fn drop(&mut self) { + println!("printint: {}", self.0); + } +} + +use std::collections::BTreeMap; +use std::iter::FromIterator; + +fn main() { + let s = String::from("Hello World!"); + let _map = BTreeMap::from_iter([((), PrintOnDrop(&s))]); + drop(s); //~ ERROR cannot move out of `s` because it is borrowed +} diff --git a/src/test/ui/btreemap/btreemap_dropck.stderr b/src/test/ui/btreemap/btreemap_dropck.stderr new file mode 100644 index 0000000000000..e953e7ae82bb8 --- /dev/null +++ b/src/test/ui/btreemap/btreemap_dropck.stderr @@ -0,0 +1,13 @@ +error[E0505]: cannot move out of `s` because it is borrowed + --> $DIR/btreemap_dropck.rs:15:10 + | +LL | let _map = BTreeMap::from_iter([((), PrintOnDrop(&s))]); + | -- borrow of `s` occurs here +LL | drop(s); + | ^ move out of `s` occurs here +LL | } + | - borrow might be used here, when `_map` is dropped and runs the `Drop` code for type `BTreeMap` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0505`. diff --git a/src/test/ui/issues/issue-72554.rs b/src/test/ui/issues/issue-72554.rs index 47aca05d7786f..7287639c61dde 100644 --- a/src/test/ui/issues/issue-72554.rs +++ b/src/test/ui/issues/issue-72554.rs @@ -1,10 +1,13 @@ use std::collections::BTreeSet; #[derive(Hash)] -pub enum ElemDerived { //~ ERROR recursive type `ElemDerived` has infinite size +pub enum ElemDerived { + //~^ ERROR recursive type `ElemDerived` has infinite size + //~| ERROR cycle detected when computing drop-check constraints for `ElemDerived` A(ElemDerived) } + pub enum Elem { Derived(ElemDerived) } diff --git a/src/test/ui/issues/issue-72554.stderr b/src/test/ui/issues/issue-72554.stderr index a6e44be636a43..3e5adcae133ca 100644 --- a/src/test/ui/issues/issue-72554.stderr +++ b/src/test/ui/issues/issue-72554.stderr @@ -3,6 +3,7 @@ error[E0072]: recursive type `ElemDerived` has infinite size | LL | pub enum ElemDerived { | ^^^^^^^^^^^^^^^^^^^^ recursive type has infinite size +... LL | A(ElemDerived) | ----------- recursive without indirection | @@ -11,6 +12,20 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `ElemDerived LL | A(Box) | ++++ + -error: aborting due to previous error +error[E0391]: cycle detected when computing drop-check constraints for `ElemDerived` + --> $DIR/issue-72554.rs:4:1 + | +LL | pub enum ElemDerived { + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: ...which immediately requires computing drop-check constraints for `ElemDerived` again +note: cycle used when computing drop-check constraints for `Elem` + --> $DIR/issue-72554.rs:11:1 + | +LL | pub enum Elem { + | ^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0072`. +Some errors have detailed explanations: E0072, E0391. +For more information about an error, try `rustc --explain E0072`.