From dcbf4ec2a1cfd9f521c96b9dab62a2d27ded1b24 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 17 Jun 2014 16:00:04 -0700 Subject: [PATCH] librustc: Put `#[unsafe_destructor]` behind a feature gate. Closes #8142. This is not the semantics we want long-term. You can continue to use `#[unsafe_destructor]`, but you'll need to add `#![feature(unsafe_destructor)]` to the crate attributes. [breaking-change] --- src/doc/guide-unsafe.md | 8 ++++++-- src/doc/rust.md | 5 +++-- src/liballoc/lib.rs | 3 ++- src/libarena/lib.rs | 3 +++ src/libcollections/lib.rs | 2 ++ src/libcore/lib.rs | 3 ++- src/libnative/lib.rs | 4 +++- src/librustc/front/feature_gate.rs | 12 ++++++++++++ src/librustc/lib.rs | 5 +++-- src/librustrt/lib.rs | 6 ++++-- src/librustuv/lib.rs | 2 +- src/libstd/lib.rs | 6 ++++-- src/libsync/lib.rs | 3 ++- src/libsyntax/lib.rs | 5 +++-- src/test/auxiliary/issue-2526.rs | 2 ++ src/test/bench/task-perf-alloc-unwind.rs | 2 +- .../compile-fail/borrowck-borrowed-uniq-rvalue-2.rs | 2 ++ src/test/compile-fail/no-send-res-ports.rs | 2 +- src/test/compile-fail/pinned-deep-copy.rs | 2 +- src/test/compile-fail/unique-vec-res.rs | 2 +- src/test/run-fail/unwind-resource-fail3.rs | 2 +- src/test/run-pass/attr-no-drop-flag-size.rs | 2 ++ src/test/run-pass/drop-trait-generic.rs | 2 ++ src/test/run-pass/init-res-into-things.rs | 2 +- src/test/run-pass/issue-2718.rs | 2 ++ src/test/run-pass/issue-2735-2.rs | 2 +- src/test/run-pass/issue-2735-3.rs | 2 +- src/test/run-pass/issue-4252.rs | 2 ++ src/test/run-pass/issue-979.rs | 2 +- src/test/run-pass/newtype-struct-drop-run.rs | 2 +- src/test/run-pass/option-unwrap.rs | 2 +- src/test/run-pass/resource-assign-is-not-copy.rs | 2 +- src/test/run-pass/resource-destruct.rs | 2 +- src/test/run-pass/resource-in-struct.rs | 2 +- src/test/run-pass/unwind-resource2.rs | 2 +- src/test/run-pass/vec-slice-drop.rs | 2 +- 36 files changed, 78 insertions(+), 33 deletions(-) diff --git a/src/doc/guide-unsafe.md b/src/doc/guide-unsafe.md index 1431c8a5c9ae4..def96c62deb00 100644 --- a/src/doc/guide-unsafe.md +++ b/src/doc/guide-unsafe.md @@ -192,6 +192,8 @@ As an example, we give a reimplementation of owned boxes by wrapping reimplementation is as safe as the `Box` type. ``` +#![feature(unsafe_destructor)] + extern crate libc; use libc::{c_void, size_t, malloc, free}; use std::mem; @@ -242,10 +244,12 @@ impl Unique { // A key ingredient for safety, we associate a destructor with // Unique, making the struct manage the raw pointer: when the // struct goes out of scope, it will automatically free the raw pointer. +// // NB: This is an unsafe destructor, because rustc will not normally -// allow destructors to be associated with parametrized types, due to +// allow destructors to be associated with parameterized types, due to // bad interaction with managed boxes. (With the Send restriction, -// we don't have this problem.) +// we don't have this problem.) Note that the `#[unsafe_destructor]` +// feature gate is required to use unsafe destructors. #[unsafe_destructor] impl Drop for Unique { fn drop(&mut self) { diff --git a/src/doc/rust.md b/src/doc/rust.md index 7e5e5b2e67a43..ca5ecc191cc9a 100644 --- a/src/doc/rust.md +++ b/src/doc/rust.md @@ -1940,12 +1940,13 @@ interpreted: enum representation in C is undefined, and this may be incorrect when the C code is compiled with certain flags. - `simd` - on certain tuple structs, derive the arithmetic operators, which - lower to the target's SIMD instructions, if any. + lower to the target's SIMD instructions, if any; the `simd` feature gate + is necessary to use this attribute. - `static_assert` - on statics whose type is `bool`, terminates compilation with an error if it is not initialized to `true`. - `unsafe_destructor` - allow implementations of the "drop" language item where the type it is implemented for does not implement the "send" language - item. + item; the `unsafe_destructor` feature gate is needed to use this attribute - `unsafe_no_drop_flag` - on structs, remove the flag that prevents destructors from being run twice. Destructors might be run multiple times on the same object with this attribute. diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index e578346861e24..53a79217241ba 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -69,7 +69,8 @@ html_root_url = "http://doc.rust-lang.org/")] #![no_std] -#![feature(phase)] +#![feature(phase, unsafe_destructor)] +#![allow(unknown_features)] // NOTE: remove after a stage0 snap #[phase(plugin, link)] extern crate core; diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index 86babb7a3d2e7..5ddb088c8c840 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -27,7 +27,10 @@ #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://doc.rust-lang.org/")] + +#![feature(unsafe_destructor)] #![allow(missing_doc)] +#![allow(unknown_features)] // NOTE: remove after a stage0 snap use std::cell::{Cell, RefCell}; use std::cmp; diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 3abecc3fc8622..ca7de131dc212 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -22,7 +22,9 @@ html_playground_url = "http://play.rust-lang.org/")] #![feature(macro_rules, managed_boxes, default_type_params, phase, globs)] +#![feature(unsafe_destructor)] #![no_std] +#![allow(unknown_features)] // NOTE: remove after a stage0 snap #[phase(plugin, link)] extern crate core; extern crate alloc; diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 62c34912f66ad..3d2382e6208b4 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -55,8 +55,9 @@ html_playground_url = "http://play.rust-lang.org/")] #![no_std] -#![feature(globs, macro_rules, managed_boxes, phase, simd)] +#![feature(globs, macro_rules, managed_boxes, phase, simd, unsafe_destructor)] #![deny(missing_doc)] +#![allow(unknown_features)] // NOTE: remove after a stage0 snap #[cfg(test)] extern crate realcore = "core"; #[cfg(test)] extern crate libc; diff --git a/src/libnative/lib.rs b/src/libnative/lib.rs index 24f1b9b9407db..b44673a24ef05 100644 --- a/src/libnative/lib.rs +++ b/src/libnative/lib.rs @@ -52,15 +52,17 @@ #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://doc.rust-lang.org/")] + #![deny(unused_result, unused_must_use)] #![allow(non_camel_case_types)] #![allow(deprecated)] +#![allow(unknown_features)] // NOTE: remove after a stage0 snap #![feature(default_type_params)] // NB this crate explicitly does *not* allow glob imports, please seriously // consider whether they're needed before adding that feature here (the // answer is that you don't need them) -#![feature(macro_rules)] +#![feature(macro_rules, unsafe_destructor)] extern crate alloc; extern crate libc; diff --git a/src/librustc/front/feature_gate.rs b/src/librustc/front/feature_gate.rs index 30d0c6d0564f2..07926ee112d5a 100644 --- a/src/librustc/front/feature_gate.rs +++ b/src/librustc/front/feature_gate.rs @@ -50,6 +50,7 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[ ("log_syntax", Active), ("trace_macros", Active), ("concat_idents", Active), + ("unsafe_destructor", Active), ("simd", Active), ("default_type_params", Active), @@ -220,6 +221,17 @@ impl<'a> Visitor<()> for Context<'a> { } } + ast::ItemImpl(..) => { + if attr::contains_name(i.attrs.as_slice(), + "unsafe_destructor") { + self.gate_feature("unsafe_destructor", + i.span, + "`#[unsafe_destructor]` allows too \ + many unsafe patterns and may be \ + removed in the future"); + } + } + _ => {} } diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 86529cf198797..fff0ae9e40c0d 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -29,8 +29,9 @@ This API is completely unstable and subject to change. html_root_url = "http://doc.rust-lang.org/")] #![allow(deprecated)] -#![feature(macro_rules, globs, struct_variant, managed_boxes, quote, - default_type_params, phase)] +#![allow(unknown_features)] // NOTE: remove after a stage0 snap +#![feature(macro_rules, globs, struct_variant, managed_boxes, quote)] +#![feature(default_type_params, phase, unsafe_destructor)] extern crate arena; extern crate debug; diff --git a/src/librustrt/lib.rs b/src/librustrt/lib.rs index c461dccceff02..f5521886f52df 100644 --- a/src/librustrt/lib.rs +++ b/src/librustrt/lib.rs @@ -15,10 +15,12 @@ #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://doc.rust-lang.org/")] -#![feature(macro_rules, phase, globs, thread_local, managed_boxes, asm, - linkage)] + +#![feature(macro_rules, phase, globs, thread_local, managed_boxes, asm)] +#![feature(linkage, unsafe_destructor)] #![no_std] #![experimental] +#![allow(unknown_features)] // NOTE: remove after a stage0 snap #[phase(plugin, link)] extern crate core; extern crate alloc; diff --git a/src/librustuv/lib.rs b/src/librustuv/lib.rs index dae94acb6f0af..74caf86a63102 100644 --- a/src/librustuv/lib.rs +++ b/src/librustuv/lib.rs @@ -40,7 +40,7 @@ via `close` and `delete` methods. #![crate_type = "rlib"] #![crate_type = "dylib"] -#![feature(macro_rules)] +#![feature(macro_rules, unsafe_destructor)] #![deny(unused_result, unused_must_use)] #![allow(visible_private_types)] diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 695c61efcf07a..a99fa016aef1d 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -103,14 +103,16 @@ html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://doc.rust-lang.org/", html_playground_url = "http://play.rust-lang.org/")] -#![feature(macro_rules, globs, managed_boxes, - linkage, default_type_params, phase)] + +#![feature(macro_rules, globs, managed_boxes)] +#![feature(linkage, default_type_params, phase, unsafe_destructor)] // Don't link to std. We are std. #![no_std] #![allow(deprecated)] #![deny(missing_doc)] +#![allow(unknown_features)] // NOTE: remove after a stage0 snap // When testing libstd, bring in libuv as the I/O backend so tests can print // things and all of the std::io tests have an I/O interface to run on top diff --git a/src/libsync/lib.rs b/src/libsync/lib.rs index 1336ea48d3150..a2f22bcaa6816 100644 --- a/src/libsync/lib.rs +++ b/src/libsync/lib.rs @@ -26,10 +26,11 @@ html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://doc.rust-lang.org/", html_playground_url = "http://play.rust-lang.org/")] -#![feature(phase, globs, macro_rules)] +#![feature(phase, globs, macro_rules, unsafe_destructor)] #![deny(missing_doc)] #![no_std] +#![allow(unknown_features)] // NOTE: remove after a stage0 snap #[phase(plugin, link)] extern crate core; extern crate alloc; diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index b18e3a221f9f3..1fbc6e41e55c9 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -27,9 +27,10 @@ This API is completely unstable and subject to change. html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://doc.rust-lang.org/")] -#![feature(macro_rules, globs, managed_boxes, default_type_params, phase, - quote)] +#![feature(macro_rules, globs, managed_boxes, default_type_params, phase)] +#![feature(quote, unsafe_destructor)] #![allow(deprecated)] +#![allow(unknown_features)] // NOTE: remove after a stage0 snap extern crate serialize; extern crate term; diff --git a/src/test/auxiliary/issue-2526.rs b/src/test/auxiliary/issue-2526.rs index 8d096a9b7e793..c6ca0f3ed7bdd 100644 --- a/src/test/auxiliary/issue-2526.rs +++ b/src/test/auxiliary/issue-2526.rs @@ -11,6 +11,8 @@ #![crate_id="issue_2526#0.2"] #![crate_type = "lib"] +#![feature(unsafe_destructor)] + struct arc_destruct { _data: int, } diff --git a/src/test/bench/task-perf-alloc-unwind.rs b/src/test/bench/task-perf-alloc-unwind.rs index 037a326880f00..a3d788238161d 100644 --- a/src/test/bench/task-perf-alloc-unwind.rs +++ b/src/test/bench/task-perf-alloc-unwind.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(managed_boxes)] +#![feature(managed_boxes, unsafe_destructor)] extern crate collections; extern crate time; diff --git a/src/test/compile-fail/borrowck-borrowed-uniq-rvalue-2.rs b/src/test/compile-fail/borrowck-borrowed-uniq-rvalue-2.rs index 6f385a8d1eb5e..081dc61d9fc97 100644 --- a/src/test/compile-fail/borrowck-borrowed-uniq-rvalue-2.rs +++ b/src/test/compile-fail/borrowck-borrowed-uniq-rvalue-2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(unsafe_destructor)] + extern crate debug; struct defer<'a> { diff --git a/src/test/compile-fail/no-send-res-ports.rs b/src/test/compile-fail/no-send-res-ports.rs index 20edd17556064..c086f44d08b90 100644 --- a/src/test/compile-fail/no-send-res-ports.rs +++ b/src/test/compile-fail/no-send-res-ports.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(managed_boxes)] +#![feature(managed_boxes, unsafe_destructor)] extern crate debug; diff --git a/src/test/compile-fail/pinned-deep-copy.rs b/src/test/compile-fail/pinned-deep-copy.rs index aaa09de826b2c..d6e8507d0200b 100644 --- a/src/test/compile-fail/pinned-deep-copy.rs +++ b/src/test/compile-fail/pinned-deep-copy.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(managed_boxes)] +#![feature(managed_boxes, unsafe_destructor)] extern crate debug; diff --git a/src/test/compile-fail/unique-vec-res.rs b/src/test/compile-fail/unique-vec-res.rs index 4d10537aa4d04..a2adb55a2dd09 100644 --- a/src/test/compile-fail/unique-vec-res.rs +++ b/src/test/compile-fail/unique-vec-res.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(managed_boxes)] +#![feature(managed_boxes, unsafe_destructor)] extern crate debug; use std::cell::Cell; diff --git a/src/test/run-fail/unwind-resource-fail3.rs b/src/test/run-fail/unwind-resource-fail3.rs index 6252944973d65..8186c6263ca74 100644 --- a/src/test/run-fail/unwind-resource-fail3.rs +++ b/src/test/run-fail/unwind-resource-fail3.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(managed_boxes)] +#![feature(managed_boxes, unsafe_destructor)] // error-pattern:quux diff --git a/src/test/run-pass/attr-no-drop-flag-size.rs b/src/test/run-pass/attr-no-drop-flag-size.rs index 48768a1c6fd27..b3fb162790072 100644 --- a/src/test/run-pass/attr-no-drop-flag-size.rs +++ b/src/test/run-pass/attr-no-drop-flag-size.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(unsafe_destructor)] + use std::mem::size_of; #[unsafe_no_drop_flag] diff --git a/src/test/run-pass/drop-trait-generic.rs b/src/test/run-pass/drop-trait-generic.rs index 977bd474d177d..4ba3aa70dfcdf 100644 --- a/src/test/run-pass/drop-trait-generic.rs +++ b/src/test/run-pass/drop-trait-generic.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(unsafe_destructor)] + struct S { x: T } diff --git a/src/test/run-pass/init-res-into-things.rs b/src/test/run-pass/init-res-into-things.rs index 4c05103973f49..5e0aeeb6bed76 100644 --- a/src/test/run-pass/init-res-into-things.rs +++ b/src/test/run-pass/init-res-into-things.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(managed_boxes)] +#![feature(managed_boxes, unsafe_destructor)] use std::cell::Cell; use std::gc::{Gc, GC}; diff --git a/src/test/run-pass/issue-2718.rs b/src/test/run-pass/issue-2718.rs index 5f180f13ffa2a..5eb9453134dea 100644 --- a/src/test/run-pass/issue-2718.rs +++ b/src/test/run-pass/issue-2718.rs @@ -9,6 +9,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(unsafe_destructor)] + pub type Task = int; // tjc: I don't know why diff --git a/src/test/run-pass/issue-2735-2.rs b/src/test/run-pass/issue-2735-2.rs index b62905634ad09..744ab45adc459 100644 --- a/src/test/run-pass/issue-2735-2.rs +++ b/src/test/run-pass/issue-2735-2.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(managed_boxes)] +#![feature(managed_boxes, unsafe_destructor)] use std::cell::Cell; use std::gc::{Gc, GC}; diff --git a/src/test/run-pass/issue-2735-3.rs b/src/test/run-pass/issue-2735-3.rs index f59c143c46fda..a69ec1dac7270 100644 --- a/src/test/run-pass/issue-2735-3.rs +++ b/src/test/run-pass/issue-2735-3.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(managed_boxes)] +#![feature(managed_boxes, unsafe_destructor)] use std::cell::Cell; use std::gc::{Gc, GC}; diff --git a/src/test/run-pass/issue-4252.rs b/src/test/run-pass/issue-4252.rs index 151d00eb2d02b..186dd0363eeb6 100644 --- a/src/test/run-pass/issue-4252.rs +++ b/src/test/run-pass/issue-4252.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(unsafe_destructor)] + extern crate debug; trait X { diff --git a/src/test/run-pass/issue-979.rs b/src/test/run-pass/issue-979.rs index 39b81d1651918..fc29299a4a97e 100644 --- a/src/test/run-pass/issue-979.rs +++ b/src/test/run-pass/issue-979.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(managed_boxes)] +#![feature(managed_boxes, unsafe_destructor)] use std::cell::Cell; use std::gc::{GC, Gc}; diff --git a/src/test/run-pass/newtype-struct-drop-run.rs b/src/test/run-pass/newtype-struct-drop-run.rs index 3821efcb1bcf7..efa151c6606c3 100644 --- a/src/test/run-pass/newtype-struct-drop-run.rs +++ b/src/test/run-pass/newtype-struct-drop-run.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(managed_boxes)] +#![feature(managed_boxes, unsafe_destructor)] // Make sure the destructor is run for newtype structs. diff --git a/src/test/run-pass/option-unwrap.rs b/src/test/run-pass/option-unwrap.rs index eea5296d7e487..e9df731fbbf3c 100644 --- a/src/test/run-pass/option-unwrap.rs +++ b/src/test/run-pass/option-unwrap.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(managed_boxes)] +#![feature(managed_boxes, unsafe_destructor)] use std::cell::Cell; use std::gc::{GC, Gc}; diff --git a/src/test/run-pass/resource-assign-is-not-copy.rs b/src/test/run-pass/resource-assign-is-not-copy.rs index 7f266ec912abb..dc6dac15bb2b1 100644 --- a/src/test/run-pass/resource-assign-is-not-copy.rs +++ b/src/test/run-pass/resource-assign-is-not-copy.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(managed_boxes)] +#![feature(managed_boxes, unsafe_destructor)] extern crate debug; diff --git a/src/test/run-pass/resource-destruct.rs b/src/test/run-pass/resource-destruct.rs index 85750899259c2..60526faef509b 100644 --- a/src/test/run-pass/resource-destruct.rs +++ b/src/test/run-pass/resource-destruct.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(managed_boxes)] +#![feature(managed_boxes, unsafe_destructor)] use std::cell::Cell; use std::gc::{GC, Gc}; diff --git a/src/test/run-pass/resource-in-struct.rs b/src/test/run-pass/resource-in-struct.rs index 88edefdfe29a0..253a2c0c7123e 100644 --- a/src/test/run-pass/resource-in-struct.rs +++ b/src/test/run-pass/resource-in-struct.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(managed_boxes)] +#![feature(managed_boxes, unsafe_destructor)] // Ensures that class dtors run if the object is inside an enum // variant diff --git a/src/test/run-pass/unwind-resource2.rs b/src/test/run-pass/unwind-resource2.rs index b1669dea7b216..2739b898f9f4f 100644 --- a/src/test/run-pass/unwind-resource2.rs +++ b/src/test/run-pass/unwind-resource2.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(managed_boxes)] +#![feature(managed_boxes, unsafe_destructor)] use std::task; use std::gc::{Gc, GC}; diff --git a/src/test/run-pass/vec-slice-drop.rs b/src/test/run-pass/vec-slice-drop.rs index 3c0a9abec144a..9e5fc6d0518d1 100644 --- a/src/test/run-pass/vec-slice-drop.rs +++ b/src/test/run-pass/vec-slice-drop.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(managed_boxes)] +#![feature(managed_boxes, unsafe_destructor)] use std::cell::Cell; use std::gc::{Gc, GC};