Skip to content

Commit 110fdb6

Browse files
committed
Add PhantomData marker for dropck to BTreeMap
closes #99408
1 parent 8804161 commit 110fdb6

File tree

5 files changed

+76
-7
lines changed

5 files changed

+76
-7
lines changed

library/alloc/src/collections/btree/map.rs

+26-4
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,8 @@ pub struct BTreeMap<
178178
length: usize,
179179
/// `ManuallyDrop` to control drop order (needs to be dropped after all the nodes).
180180
pub(super) alloc: ManuallyDrop<A>,
181+
// For dropck; the `Box` avoids making the `Unpin` impl more strict than before
182+
_marker: PhantomData<crate::boxed::Box<(K, V)>>,
181183
}
182184

183185
#[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
187189
}
188190
}
189191

192+
// FIXME: This implementation is "wrong", but changing it would be a breaking change.
193+
// (The bounds of the automatic `UnwindSafe` implementation have been like this since Rust 1.50.)
194+
// Maybe we can fix it nonetheless with a crater run, or if the `UnwindSafe`
195+
// traits are deprecated, or disarmed (no longer causing hard errors) in the future.
196+
#[stable(feature = "btree_unwindsafe", since = "1.64.0")]
197+
impl<K, V, A: Allocator + Clone> core::panic::UnwindSafe for BTreeMap<K, V, A>
198+
where
199+
A: core::panic::UnwindSafe,
200+
K: core::panic::RefUnwindSafe,
201+
V: core::panic::RefUnwindSafe,
202+
{
203+
}
204+
190205
#[stable(feature = "rust1", since = "1.0.0")]
191206
impl<K: Clone, V: Clone, A: Allocator + Clone> Clone for BTreeMap<K, V, A> {
192207
fn clone(&self) -> BTreeMap<K, V, A> {
@@ -204,6 +219,7 @@ impl<K: Clone, V: Clone, A: Allocator + Clone> Clone for BTreeMap<K, V, A> {
204219
root: Some(Root::new(alloc.clone())),
205220
length: 0,
206221
alloc: ManuallyDrop::new(alloc),
222+
_marker: PhantomData,
207223
};
208224

209225
{
@@ -567,7 +583,7 @@ impl<K, V> BTreeMap<K, V> {
567583
#[rustc_const_unstable(feature = "const_btree_new", issue = "71835")]
568584
#[must_use]
569585
pub const fn new() -> BTreeMap<K, V> {
570-
BTreeMap { root: None, length: 0, alloc: ManuallyDrop::new(Global) }
586+
BTreeMap { root: None, length: 0, alloc: ManuallyDrop::new(Global), _marker: PhantomData }
571587
}
572588
}
573589

@@ -593,6 +609,7 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
593609
root: mem::replace(&mut self.root, None),
594610
length: mem::replace(&mut self.length, 0),
595611
alloc: self.alloc.clone(),
612+
_marker: PhantomData,
596613
});
597614
}
598615

@@ -615,7 +632,7 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
615632
/// ```
616633
#[unstable(feature = "btreemap_alloc", issue = "32838")]
617634
pub fn new_in(alloc: A) -> BTreeMap<K, V, A> {
618-
BTreeMap { root: None, length: 0, alloc: ManuallyDrop::new(alloc) }
635+
BTreeMap { root: None, length: 0, alloc: ManuallyDrop::new(alloc), _marker: PhantomData }
619636
}
620637
}
621638

@@ -1320,7 +1337,12 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
13201337
let (new_left_len, right_len) = Root::calc_split_length(total_num, &left_root, &right_root);
13211338
self.length = new_left_len;
13221339

1323-
BTreeMap { root: Some(right_root), length: right_len, alloc: self.alloc.clone() }
1340+
BTreeMap {
1341+
root: Some(right_root),
1342+
length: right_len,
1343+
alloc: self.alloc.clone(),
1344+
_marker: PhantomData,
1345+
}
13241346
}
13251347

13261348
/// Creates an iterator that visits all elements (key-value pairs) in
@@ -1445,7 +1467,7 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
14451467
let mut root = Root::new(alloc.clone());
14461468
let mut length = 0;
14471469
root.bulk_push(DedupSortedIter::new(iter.into_iter()), &mut length, alloc.clone());
1448-
BTreeMap { root: Some(root), length, alloc: ManuallyDrop::new(alloc) }
1470+
BTreeMap { root: Some(root), length, alloc: ManuallyDrop::new(alloc), _marker: PhantomData }
14491471
}
14501472
}
14511473

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
struct PrintOnDrop<'a>(&'a str);
2+
3+
impl Drop for PrintOnDrop<'_> {
4+
fn drop(&mut self) {
5+
println!("printint: {}", self.0);
6+
}
7+
}
8+
9+
use std::collections::BTreeMap;
10+
use std::iter::FromIterator;
11+
12+
fn main() {
13+
let s = String::from("Hello World!");
14+
let _map = BTreeMap::from_iter([((), PrintOnDrop(&s))]);
15+
drop(s); //~ ERROR cannot move out of `s` because it is borrowed
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error[E0505]: cannot move out of `s` because it is borrowed
2+
--> $DIR/btreemap_dropck.rs:15:10
3+
|
4+
LL | let _map = BTreeMap::from_iter([((), PrintOnDrop(&s))]);
5+
| -- borrow of `s` occurs here
6+
LL | drop(s);
7+
| ^ move out of `s` occurs here
8+
LL | }
9+
| - borrow might be used here, when `_map` is dropped and runs the `Drop` code for type `BTreeMap`
10+
11+
error: aborting due to previous error
12+
13+
For more information about this error, try `rustc --explain E0505`.

src/test/ui/issues/issue-72554.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
use std::collections::BTreeSet;
22

33
#[derive(Hash)]
4-
pub enum ElemDerived { //~ ERROR recursive type `ElemDerived` has infinite size
4+
pub enum ElemDerived {
5+
//~^ ERROR recursive type `ElemDerived` has infinite size
6+
//~| ERROR cycle detected when computing drop-check constraints for `ElemDerived`
57
A(ElemDerived)
68
}
79

10+
811
pub enum Elem {
912
Derived(ElemDerived)
1013
}

src/test/ui/issues/issue-72554.stderr

+17-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ error[E0072]: recursive type `ElemDerived` has infinite size
33
|
44
LL | pub enum ElemDerived {
55
| ^^^^^^^^^^^^^^^^^^^^ recursive type has infinite size
6+
...
67
LL | A(ElemDerived)
78
| ----------- recursive without indirection
89
|
@@ -11,6 +12,20 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `ElemDerived
1112
LL | A(Box<ElemDerived>)
1213
| ++++ +
1314

14-
error: aborting due to previous error
15+
error[E0391]: cycle detected when computing drop-check constraints for `ElemDerived`
16+
--> $DIR/issue-72554.rs:4:1
17+
|
18+
LL | pub enum ElemDerived {
19+
| ^^^^^^^^^^^^^^^^^^^^
20+
|
21+
= note: ...which immediately requires computing drop-check constraints for `ElemDerived` again
22+
note: cycle used when computing drop-check constraints for `Elem`
23+
--> $DIR/issue-72554.rs:11:1
24+
|
25+
LL | pub enum Elem {
26+
| ^^^^^^^^^^^^^
27+
28+
error: aborting due to 2 previous errors
1529

16-
For more information about this error, try `rustc --explain E0072`.
30+
Some errors have detailed explanations: E0072, E0391.
31+
For more information about an error, try `rustc --explain E0072`.

0 commit comments

Comments
 (0)