From 8103ac5a18c9b52a6e8a209dab2586ec8fc3be13 Mon Sep 17 00:00:00 2001 From: Jake Hughes Date: Thu, 31 Oct 2024 19:39:41 +0000 Subject: [PATCH] Enable finalizer elision for more std lib collection types. This provides support for: BTree, BTreeSet, VecDeque, LinkedList, and BinaryHeap. --- library/alloc/src/collections/btree/map.rs | 4 ++ library/alloc/src/collections/linked_list.rs | 4 ++ .../alloc/src/collections/vec_deque/mod.rs | 4 ++ tests/ui/static/gc/elision/binary_heap.rs | 41 +++++++++++++++++++ tests/ui/static/gc/elision/btreemap.rs | 27 ++++++++++++ tests/ui/static/gc/elision/btreeset.rs | 41 +++++++++++++++++++ tests/ui/static/gc/elision/linked_list.rs | 41 +++++++++++++++++++ tests/ui/static/gc/elision/vecdeque.rs | 41 +++++++++++++++++++ 8 files changed, 203 insertions(+) create mode 100644 tests/ui/static/gc/elision/binary_heap.rs create mode 100644 tests/ui/static/gc/elision/btreemap.rs create mode 100644 tests/ui/static/gc/elision/btreeset.rs create mode 100644 tests/ui/static/gc/elision/linked_list.rs create mode 100644 tests/ui/static/gc/elision/vecdeque.rs diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 3875f61efafdf..c9b625a62a79f 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -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; @@ -183,6 +184,9 @@ pub struct BTreeMap< _marker: PhantomData>, } +#[unstable(feature = "gc", issue = "none")] +unsafe impl DropMethodFinalizerElidable for BTreeMap {} + #[stable(feature = "btree_drop", since = "1.7.0")] unsafe impl<#[may_dangle] K, #[may_dangle] V, A: Allocator + Clone> Drop for BTreeMap { fn drop(&mut self) { diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index f2a01efef69b2..5d20cb073d89e 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -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; @@ -1166,6 +1167,9 @@ impl LinkedList { } } +#[unstable(feature = "gc", issue = "none")] +unsafe impl DropMethodFinalizerElidable for LinkedList {} + #[stable(feature = "rust1", since = "1.0.0")] unsafe impl<#[may_dangle] T, A: Allocator> Drop for LinkedList { fn drop(&mut self) { diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 4643a6bbe2ecd..ca5abb8e74518 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -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}; @@ -123,6 +124,9 @@ impl Clone for VecDeque { } } +#[unstable(feature = "gc", issue = "none")] +unsafe impl DropMethodFinalizerElidable for VecDeque {} + #[stable(feature = "rust1", since = "1.0.0")] unsafe impl<#[may_dangle] T, A: Allocator> Drop for VecDeque { fn drop(&mut self) { diff --git a/tests/ui/static/gc/elision/binary_heap.rs b/tests/ui/static/gc/elision/binary_heap.rs new file mode 100644 index 0000000000000..fec28a803fba1 --- /dev/null +++ b/tests/ui/static/gc/elision/binary_heap.rs @@ -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::>(); +static BH_FINALIZABLE: bool = needs_finalizer::>(); +static BH_UNFINALIZABLE: bool = needs_finalizer::>(); +static BH_TUPLE_UNFINALIZABLE: bool = needs_finalizer::>(); +static BH_TUPLE_FINALIZABLE: bool = needs_finalizer::>(); +static BH_TUPLE_CONTAINS_FINALIZABLE: bool = needs_finalizer::>(); +static BH_BH_FINALIZABLE: bool = needs_finalizer::>>(); +static BH_BH_UNFINALIZABLE: bool = needs_finalizer::>>(); +static BH_STRING: bool = needs_finalizer::>(); +static BH_BOX_FINALIZABLE: bool = needs_finalizer::>>(); +static BH_BOX_UNFINALIZABLE: bool = needs_finalizer::>>(); +static BH_TUPLE_GC_UNFINALIZABLE: bool = needs_finalizer::)>>(); +static BH_TUPLE_GC_FINALIZABLE: bool = needs_finalizer::)>>(); +static BH_COLLECTABLE_NO_DROP_ELEMENT: bool = needs_finalizer::>(); + +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); +} diff --git a/tests/ui/static/gc/elision/btreemap.rs b/tests/ui/static/gc/elision/btreemap.rs new file mode 100644 index 0000000000000..8d20ed23f11d0 --- /dev/null +++ b/tests/ui/static/gc/elision/btreemap.rs @@ -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::>(); +static BTM_FIN_KEY: bool = needs_finalizer::>(); +static BTM_FIN_VAL: bool = needs_finalizer::>(); +static BTM_FIN_BOTH: bool = needs_finalizer::>(); +static BTM_FIN_GC_KEY: bool = needs_finalizer::, Gc>>(); +static BTM_FIN_GC_VAL: bool = needs_finalizer::, Gc>>(); +static BTM_FIN_GC_BOTH: bool = needs_finalizer::, Gc>>(); + +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); +} diff --git a/tests/ui/static/gc/elision/btreeset.rs b/tests/ui/static/gc/elision/btreeset.rs new file mode 100644 index 0000000000000..d086caff0e335 --- /dev/null +++ b/tests/ui/static/gc/elision/btreeset.rs @@ -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::>(); +static BT_FINALIZABLE: bool = needs_finalizer::>(); +static BT_UNFINALIZABLE: bool = needs_finalizer::>(); +static BT_TUPLE_UNFINALIZABLE: bool = needs_finalizer::>(); +static BT_TUPLE_FINALIZABLE: bool = needs_finalizer::>(); +static BT_TUPLE_CONTAINS_FINALIZABLE: bool = needs_finalizer::>(); +static BT_BT_FINALIZABLE: bool = needs_finalizer::>>(); +static BT_BT_UNFINALIZABLE: bool = needs_finalizer::>>(); +static BT_STRING: bool = needs_finalizer::>(); +static BT_BOX_FINALIZABLE: bool = needs_finalizer::>>(); +static BT_BOX_UNFINALIZABLE: bool = needs_finalizer::>>(); +static BT_TUPLE_GC_UNFINALIZABLE: bool = needs_finalizer::)>>(); +static BT_TUPLE_GC_FINALIZABLE: bool = needs_finalizer::)>>(); +static BT_COLLECTABLE_NO_DROP_ELEMENT: bool = needs_finalizer::>(); + +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); +} diff --git a/tests/ui/static/gc/elision/linked_list.rs b/tests/ui/static/gc/elision/linked_list.rs new file mode 100644 index 0000000000000..08d7317ca1ab4 --- /dev/null +++ b/tests/ui/static/gc/elision/linked_list.rs @@ -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::>(); +static LL_FINALIZABLE: bool = needs_finalizer::>(); +static LL_UNFINALIZABLE: bool = needs_finalizer::>(); +static LL_TUPLE_UNFINALIZABLE: bool = needs_finalizer::>(); +static LL_TUPLE_FINALIZABLE: bool = needs_finalizer::>(); +static LL_TUPLE_CONTAINS_FINALIZABLE: bool = needs_finalizer::>(); +static LL_LL_FINALIZABLE: bool = needs_finalizer::>>(); +static LL_LL_UNFINALIZABLE: bool = needs_finalizer::>>(); +static LL_STRING: bool = needs_finalizer::>(); +static LL_BOX_FINALIZABLE: bool = needs_finalizer::>>(); +static LL_BOX_UNFINALIZABLE: bool = needs_finalizer::>>(); +static LL_TUPLE_GC_UNFINALIZABLE: bool = needs_finalizer::)>>(); +static LL_TUPLE_GC_FINALIZABLE: bool = needs_finalizer::)>>(); +static LL_COLLECTABLE_NO_DROP_ELEMENT: bool = needs_finalizer::>(); + +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); +} diff --git a/tests/ui/static/gc/elision/vecdeque.rs b/tests/ui/static/gc/elision/vecdeque.rs new file mode 100644 index 0000000000000..7004b8a70740f --- /dev/null +++ b/tests/ui/static/gc/elision/vecdeque.rs @@ -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::>(); +static VD_FINALIZABLE: bool = needs_finalizer::>(); +static VD_UNFINALIZABLE: bool = needs_finalizer::>(); +static VD_TUPLE_UNFINALIZABLE: bool = needs_finalizer::>(); +static VD_TUPLE_FINALIZABLE: bool = needs_finalizer::>(); +static VD_TUPLE_CONTAINS_FINALIZABLE: bool = needs_finalizer::>(); +static VD_VD_FINALIZABLE: bool = needs_finalizer::>>(); +static VD_VD_UNFINALIZABLE: bool = needs_finalizer::>>(); +static VD_STRING: bool = needs_finalizer::>(); +static VD_BOX_FINALIZABLE: bool = needs_finalizer::>>(); +static VD_BOX_UNFINALIZABLE: bool = needs_finalizer::>>(); +static VD_TUPLE_GC_UNFINALIZABLE: bool = needs_finalizer::)>>(); +static VD_TUPLE_GC_FINALIZABLE: bool = needs_finalizer::)>>(); +static VD_COLLECTABLE_NO_DROP_ELEMENT: bool = needs_finalizer::>(); + +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); +}