Skip to content

Commit

Permalink
Enable finalizer elision for more std lib collection types.
Browse files Browse the repository at this point in the history
This provides support for: BTree, BTreeSet, VecDeque, LinkedList, and
BinaryHeap.
  • Loading branch information
jacob-hughes committed Oct 31, 2024
1 parent e31aa9b commit 8103ac5
Show file tree
Hide file tree
Showing 8 changed files with 203 additions and 0 deletions.
4 changes: 4 additions & 0 deletions library/alloc/src/collections/btree/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use core::borrow::Borrow;
use core::cmp::Ordering;
use core::error::Error;
use core::fmt::{self, Debug};
use core::gc::DropMethodFinalizerElidable;
use core::hash::{Hash, Hasher};
use core::iter::FusedIterator;
use core::marker::PhantomData;
Expand Down Expand Up @@ -183,6 +184,9 @@ pub struct BTreeMap<
_marker: PhantomData<crate::boxed::Box<(K, V), A>>,
}

#[unstable(feature = "gc", issue = "none")]
unsafe impl<K, V, A: Allocator + Clone> DropMethodFinalizerElidable for BTreeMap<K, V, A> {}

#[stable(feature = "btree_drop", since = "1.7.0")]
unsafe impl<#[may_dangle] K, #[may_dangle] V, A: Allocator + Clone> Drop for BTreeMap<K, V, A> {
fn drop(&mut self) {
Expand Down
4 changes: 4 additions & 0 deletions library/alloc/src/collections/linked_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

use core::cmp::Ordering;
use core::fmt;
use core::gc::DropMethodFinalizerElidable;
use core::hash::{Hash, Hasher};
use core::iter::FusedIterator;
use core::marker::PhantomData;
Expand Down Expand Up @@ -1166,6 +1167,9 @@ impl<T, A: Allocator> LinkedList<T, A> {
}
}

#[unstable(feature = "gc", issue = "none")]
unsafe impl<T, A: Allocator> DropMethodFinalizerElidable for LinkedList<T, A> {}

#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl<#[may_dangle] T, A: Allocator> Drop for LinkedList<T, A> {
fn drop(&mut self) {
Expand Down
4 changes: 4 additions & 0 deletions library/alloc/src/collections/vec_deque/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

use core::cmp::{self, Ordering};
use core::fmt;
use core::gc::DropMethodFinalizerElidable;
use core::hash::{Hash, Hasher};
use core::iter::{repeat_n, repeat_with, ByRefSized};
use core::mem::{ManuallyDrop, SizedTypeProperties};
Expand Down Expand Up @@ -123,6 +124,9 @@ impl<T: Clone, A: Allocator + Clone> Clone for VecDeque<T, A> {
}
}

#[unstable(feature = "gc", issue = "none")]
unsafe impl<T, A: Allocator> DropMethodFinalizerElidable for VecDeque<T, A> {}

#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl<#[may_dangle] T, A: Allocator> Drop for VecDeque<T, A> {
fn drop(&mut self) {
Expand Down
41 changes: 41 additions & 0 deletions tests/ui/static/gc/elision/binary_heap.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//@ run-pass
// ignore-tidy-linelength
#![feature(gc)]
#![allow(dead_code)]
include!{"./auxiliary/types.rs"}

use std::mem::needs_finalizer;
use std::collections::BinaryHeap;
use std::gc::Gc;

static BH_TRIVIAL: bool = needs_finalizer::<BinaryHeap<usize>>();
static BH_FINALIZABLE: bool = needs_finalizer::<BinaryHeap<HasDrop>>();
static BH_UNFINALIZABLE: bool = needs_finalizer::<BinaryHeap<HasDropNoFinalize>>();
static BH_TUPLE_UNFINALIZABLE: bool = needs_finalizer::<BinaryHeap<(HasDropNoFinalize, usize)>>();
static BH_TUPLE_FINALIZABLE: bool = needs_finalizer::<BinaryHeap<(HasDrop, HasDrop)>>();
static BH_TUPLE_CONTAINS_FINALIZABLE: bool = needs_finalizer::<BinaryHeap<(HasDrop, usize)>>();
static BH_BH_FINALIZABLE: bool = needs_finalizer::<BinaryHeap<BinaryHeap<HasDrop>>>();
static BH_BH_UNFINALIZABLE: bool = needs_finalizer::<BinaryHeap<BinaryHeap<HasDropNoFinalize>>>();
static BH_STRING: bool = needs_finalizer::<BinaryHeap<String>>();
static BH_BOX_FINALIZABLE: bool = needs_finalizer::<BinaryHeap<Box<HasDrop>>>();
static BH_BOX_UNFINALIZABLE: bool = needs_finalizer::<BinaryHeap<Box<HasDropNoFinalize>>>();
static BH_TUPLE_GC_UNFINALIZABLE: bool = needs_finalizer::<BinaryHeap<(HasDropNoFinalize, Gc<HasDrop>)>>();
static BH_TUPLE_GC_FINALIZABLE: bool = needs_finalizer::<BinaryHeap<(HasDrop, Gc<HasDrop>)>>();
static BH_COLLECTABLE_NO_DROP_ELEMENT: bool = needs_finalizer::<BinaryHeap<NonAnnotated>>();

fn main() {
assert!(!BH_TRIVIAL);
assert!(BH_FINALIZABLE);
assert!(!BH_UNFINALIZABLE);
assert!(!BH_TUPLE_UNFINALIZABLE);
assert!(BH_TUPLE_FINALIZABLE);
assert!(BH_TUPLE_CONTAINS_FINALIZABLE);
assert!(BH_BH_FINALIZABLE);
assert!(!BH_BH_UNFINALIZABLE);
assert!(!BH_STRING);
assert!(BH_BOX_FINALIZABLE);
assert!(!BH_BOX_UNFINALIZABLE);
assert!(!BH_TUPLE_GC_UNFINALIZABLE);
assert!(BH_TUPLE_GC_FINALIZABLE);
assert!(!BH_COLLECTABLE_NO_DROP_ELEMENT);
}
27 changes: 27 additions & 0 deletions tests/ui/static/gc/elision/btreemap.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//@ run-pass
// ignore-tidy-linelength
#![feature(gc)]
#![allow(dead_code)]
include!{"./auxiliary/types.rs"}

use std::mem::needs_finalizer;
use std::collections::BTreeMap;
use std::gc::Gc;

static BTM_TRIVIAL: bool = needs_finalizer::<BTreeMap<usize, usize>>();
static BTM_FIN_KEY: bool = needs_finalizer::<BTreeMap<HasDrop, HasDropNoFinalize>>();
static BTM_FIN_VAL: bool = needs_finalizer::<BTreeMap<HasDropNoFinalize, HasDrop>>();
static BTM_FIN_BOTH: bool = needs_finalizer::<BTreeMap<HasDrop, HasDrop>>();
static BTM_FIN_GC_KEY: bool = needs_finalizer::<BTreeMap<Gc<HasDropNoFinalize>, Gc<HasDrop>>>();
static BTM_FIN_GC_VAL: bool = needs_finalizer::<BTreeMap<Gc<HasDropNoFinalize>, Gc<HasDrop>>>();
static BTM_FIN_GC_BOTH: bool = needs_finalizer::<BTreeMap<Gc<HasDrop>, Gc<HasDrop>>>();

fn main() {
assert!(!BTM_TRIVIAL);
assert!(BTM_FIN_KEY);
assert!(BTM_FIN_VAL);
assert!(BTM_FIN_BOTH);
assert!(!BTM_FIN_GC_KEY);
assert!(!BTM_FIN_GC_VAL);
assert!(!BTM_FIN_GC_BOTH);
}
41 changes: 41 additions & 0 deletions tests/ui/static/gc/elision/btreeset.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//@ run-pass
// ignore-tidy-linelength
#![feature(gc)]
#![allow(dead_code)]
include!{"./auxiliary/types.rs"}

use std::mem::needs_finalizer;
use std::collections::BTreeSet;
use std::gc::Gc;

static BT_TRIVIAL: bool = needs_finalizer::<BTreeSet<usize>>();
static BT_FINALIZABLE: bool = needs_finalizer::<BTreeSet<HasDrop>>();
static BT_UNFINALIZABLE: bool = needs_finalizer::<BTreeSet<HasDropNoFinalize>>();
static BT_TUPLE_UNFINALIZABLE: bool = needs_finalizer::<BTreeSet<(HasDropNoFinalize, usize)>>();
static BT_TUPLE_FINALIZABLE: bool = needs_finalizer::<BTreeSet<(HasDrop, HasDrop)>>();
static BT_TUPLE_CONTAINS_FINALIZABLE: bool = needs_finalizer::<BTreeSet<(HasDrop, usize)>>();
static BT_BT_FINALIZABLE: bool = needs_finalizer::<BTreeSet<BTreeSet<HasDrop>>>();
static BT_BT_UNFINALIZABLE: bool = needs_finalizer::<BTreeSet<BTreeSet<HasDropNoFinalize>>>();
static BT_STRING: bool = needs_finalizer::<BTreeSet<String>>();
static BT_BOX_FINALIZABLE: bool = needs_finalizer::<BTreeSet<Box<HasDrop>>>();
static BT_BOX_UNFINALIZABLE: bool = needs_finalizer::<BTreeSet<Box<HasDropNoFinalize>>>();
static BT_TUPLE_GC_UNFINALIZABLE: bool = needs_finalizer::<BTreeSet<(HasDropNoFinalize, Gc<HasDrop>)>>();
static BT_TUPLE_GC_FINALIZABLE: bool = needs_finalizer::<BTreeSet<(HasDrop, Gc<HasDrop>)>>();
static BT_COLLECTABLE_NO_DROP_ELEMENT: bool = needs_finalizer::<BTreeSet<NonAnnotated>>();

fn main() {
assert!(!BT_TRIVIAL);
assert!(BT_FINALIZABLE);
assert!(!BT_UNFINALIZABLE);
assert!(!BT_TUPLE_UNFINALIZABLE);
assert!(BT_TUPLE_FINALIZABLE);
assert!(BT_TUPLE_CONTAINS_FINALIZABLE);
assert!(BT_BT_FINALIZABLE);
assert!(!BT_BT_UNFINALIZABLE);
assert!(!BT_STRING);
assert!(BT_BOX_FINALIZABLE);
assert!(!BT_BOX_UNFINALIZABLE);
assert!(!BT_TUPLE_GC_UNFINALIZABLE);
assert!(BT_TUPLE_GC_FINALIZABLE);
assert!(!BT_COLLECTABLE_NO_DROP_ELEMENT);
}
41 changes: 41 additions & 0 deletions tests/ui/static/gc/elision/linked_list.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//@ run-pass
// ignore-tidy-linelength
#![feature(gc)]
#![allow(dead_code)]
include!{"./auxiliary/types.rs"}

use std::mem::needs_finalizer;
use std::collections::LinkedList;
use std::gc::Gc;

static LL_TRIVIAL: bool = needs_finalizer::<LinkedList<usize>>();
static LL_FINALIZABLE: bool = needs_finalizer::<LinkedList<HasDrop>>();
static LL_UNFINALIZABLE: bool = needs_finalizer::<LinkedList<HasDropNoFinalize>>();
static LL_TUPLE_UNFINALIZABLE: bool = needs_finalizer::<LinkedList<(HasDropNoFinalize, usize)>>();
static LL_TUPLE_FINALIZABLE: bool = needs_finalizer::<LinkedList<(HasDrop, HasDrop)>>();
static LL_TUPLE_CONTAINS_FINALIZABLE: bool = needs_finalizer::<LinkedList<(HasDrop, usize)>>();
static LL_LL_FINALIZABLE: bool = needs_finalizer::<LinkedList<LinkedList<HasDrop>>>();
static LL_LL_UNFINALIZABLE: bool = needs_finalizer::<LinkedList<LinkedList<HasDropNoFinalize>>>();
static LL_STRING: bool = needs_finalizer::<LinkedList<String>>();
static LL_BOX_FINALIZABLE: bool = needs_finalizer::<LinkedList<Box<HasDrop>>>();
static LL_BOX_UNFINALIZABLE: bool = needs_finalizer::<LinkedList<Box<HasDropNoFinalize>>>();
static LL_TUPLE_GC_UNFINALIZABLE: bool = needs_finalizer::<LinkedList<(HasDropNoFinalize, Gc<HasDrop>)>>();
static LL_TUPLE_GC_FINALIZABLE: bool = needs_finalizer::<LinkedList<(HasDrop, Gc<HasDrop>)>>();
static LL_COLLECTABLE_NO_DROP_ELEMENT: bool = needs_finalizer::<LinkedList<NonAnnotated>>();

fn main() {
assert!(!LL_TRIVIAL);
assert!(LL_FINALIZABLE);
assert!(!LL_UNFINALIZABLE);
assert!(!LL_TUPLE_UNFINALIZABLE);
assert!(LL_TUPLE_FINALIZABLE);
assert!(LL_TUPLE_CONTAINS_FINALIZABLE);
assert!(LL_LL_FINALIZABLE);
assert!(!LL_LL_UNFINALIZABLE);
assert!(!LL_STRING);
assert!(LL_BOX_FINALIZABLE);
assert!(!LL_BOX_UNFINALIZABLE);
assert!(!LL_TUPLE_GC_UNFINALIZABLE);
assert!(LL_TUPLE_GC_FINALIZABLE);
assert!(!LL_COLLECTABLE_NO_DROP_ELEMENT);
}
41 changes: 41 additions & 0 deletions tests/ui/static/gc/elision/vecdeque.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//@ run-pass
// ignore-tidy-linelength
#![feature(gc)]
#![allow(dead_code)]
include!{"./auxiliary/types.rs"}

use std::mem::needs_finalizer;
use std::collections::VecDeque;
use std::gc::Gc;

static VD_TRIVIAL: bool = needs_finalizer::<VecDeque<usize>>();
static VD_FINALIZABLE: bool = needs_finalizer::<VecDeque<HasDrop>>();
static VD_UNFINALIZABLE: bool = needs_finalizer::<VecDeque<HasDropNoFinalize>>();
static VD_TUPLE_UNFINALIZABLE: bool = needs_finalizer::<VecDeque<(HasDropNoFinalize, usize)>>();
static VD_TUPLE_FINALIZABLE: bool = needs_finalizer::<VecDeque<(HasDrop, HasDrop)>>();
static VD_TUPLE_CONTAINS_FINALIZABLE: bool = needs_finalizer::<VecDeque<(HasDrop, usize)>>();
static VD_VD_FINALIZABLE: bool = needs_finalizer::<VecDeque<VecDeque<HasDrop>>>();
static VD_VD_UNFINALIZABLE: bool = needs_finalizer::<VecDeque<VecDeque<HasDropNoFinalize>>>();
static VD_STRING: bool = needs_finalizer::<VecDeque<String>>();
static VD_BOX_FINALIZABLE: bool = needs_finalizer::<VecDeque<Box<HasDrop>>>();
static VD_BOX_UNFINALIZABLE: bool = needs_finalizer::<VecDeque<Box<HasDropNoFinalize>>>();
static VD_TUPLE_GC_UNFINALIZABLE: bool = needs_finalizer::<VecDeque<(HasDropNoFinalize, Gc<HasDrop>)>>();
static VD_TUPLE_GC_FINALIZABLE: bool = needs_finalizer::<VecDeque<(HasDrop, Gc<HasDrop>)>>();
static VD_COLLECTABLE_NO_DROP_ELEMENT: bool = needs_finalizer::<VecDeque<NonAnnotated>>();

fn main() {
assert!(!VD_TRIVIAL);
assert!(VD_FINALIZABLE);
assert!(!VD_UNFINALIZABLE);
assert!(!VD_TUPLE_UNFINALIZABLE);
assert!(VD_TUPLE_FINALIZABLE);
assert!(VD_TUPLE_CONTAINS_FINALIZABLE);
assert!(VD_VD_FINALIZABLE);
assert!(!VD_VD_UNFINALIZABLE);
assert!(!VD_STRING);
assert!(VD_BOX_FINALIZABLE);
assert!(!VD_BOX_UNFINALIZABLE);
assert!(!VD_TUPLE_GC_UNFINALIZABLE);
assert!(VD_TUPLE_GC_FINALIZABLE);
assert!(!VD_COLLECTABLE_NO_DROP_ELEMENT);
}

0 comments on commit 8103ac5

Please sign in to comment.