From 1d5c0ba75f5ca999396466b455dc07e45546e9a8 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 31 Aug 2017 12:21:11 +0300 Subject: [PATCH] Allow Drop types in const's too, with #![feature(drop_types_in_const)]. --- src/librustc_mir/transform/qualify_consts.rs | 12 +++++----- .../issue-17718-const-destructors.rs | 2 +- src/test/compile-fail/static-drop-scope.rs | 11 ++++++++-- src/test/run-pass/issue-34053.rs | 22 +++++++++++++++++-- src/test/ui/span/E0493.rs | 4 +++- src/test/ui/span/E0493.stderr | 8 +++---- 6 files changed, 44 insertions(+), 15 deletions(-) diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 2198b533ea07a..c2e2684fffc34 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -203,7 +203,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { /// Check for NEEDS_DROP (from an ADT or const fn call) and /// error, unless we're in a function, or the feature-gate - /// for globals with destructors is enabled. + /// for constant with destructors is enabled. fn deny_drop(&self) { self.deny_drop_with_feature_gate_override(true); } @@ -213,9 +213,9 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { return; } - // Static and const fn's allow destructors, but they're feature-gated. - let msg = if allow_gate && self.mode != Mode::Const { - // Feature-gate for globals with destructors is enabled. + // Constants allow destructors, but they're feature-gated. + let msg = if allow_gate { + // Feature-gate for constant with destructors is enabled. if self.tcx.sess.features.borrow().drop_types_in_const { return; } @@ -235,11 +235,13 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { let mut err = struct_span_err!(self.tcx.sess, self.span, E0493, "{}", msg); - if allow_gate && self.mode != Mode::Const { + if allow_gate { help!(&mut err, "in Nightly builds, add `#![feature(drop_types_in_const)]` \ to the crate attributes to enable"); } else { + // FIXME(eddyb) this looks up `self.mir.return_ty`. + // We probably want the actual return type here, if at all. self.find_drop_implementation_method_span() .map(|span| err.span_label(span, "destructor defined here")); diff --git a/src/test/compile-fail/issue-17718-const-destructors.rs b/src/test/compile-fail/issue-17718-const-destructors.rs index e888f917741ab..6c2eafe040a36 100644 --- a/src/test/compile-fail/issue-17718-const-destructors.rs +++ b/src/test/compile-fail/issue-17718-const-destructors.rs @@ -14,6 +14,6 @@ impl Drop for A { } const FOO: A = A; -//~^ ERROR: constants are not allowed to have destructors +//~^ ERROR: destructors in constants are an unstable feature fn main() {} diff --git a/src/test/compile-fail/static-drop-scope.rs b/src/test/compile-fail/static-drop-scope.rs index e5f10b65ceed7..f8fdf8c45cbdb 100644 --- a/src/test/compile-fail/static-drop-scope.rs +++ b/src/test/compile-fail/static-drop-scope.rs @@ -16,11 +16,18 @@ impl Drop for WithDtor { fn drop(&mut self) {} } -static FOO: Option<&'static WithDtor> = Some(&WithDtor); +static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor); //~^ ERROR statics are not allowed to have destructors //~| ERROR borrowed value does not live long enoug -static BAR: i32 = (WithDtor, 0).1; +const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor); +//~^ ERROR constants are not allowed to have destructors +//~| ERROR borrowed value does not live long enoug + +static EARLY_DROP_S: i32 = (WithDtor, 0).1; //~^ ERROR statics are not allowed to have destructors +const EARLY_DROP_C: i32 = (WithDtor, 0).1; +//~^ ERROR constants are not allowed to have destructors + fn main () {} diff --git a/src/test/run-pass/issue-34053.rs b/src/test/run-pass/issue-34053.rs index 7f8a4941494a9..c085ee7d46ac3 100644 --- a/src/test/run-pass/issue-34053.rs +++ b/src/test/run-pass/issue-34053.rs @@ -10,14 +10,32 @@ #![feature(drop_types_in_const)] +use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; + +static DROP_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT; + struct A(i32); impl Drop for A { - fn drop(&mut self) {} + fn drop(&mut self) { + // update global drop count + DROP_COUNTER.fetch_add(1, Ordering::SeqCst); + } } static FOO: A = A(123); +const BAR: A = A(456); + +impl A { + const BAZ: A = A(789); +} fn main() { - println!("{}", &FOO.0); + assert_eq!(DROP_COUNTER.load(Ordering::SeqCst), 0); + assert_eq!(&FOO.0, &123); + assert_eq!(DROP_COUNTER.load(Ordering::SeqCst), 0); + assert_eq!(BAR.0, 456); + assert_eq!(DROP_COUNTER.load(Ordering::SeqCst), 1); + assert_eq!(A::BAZ.0, 789); + assert_eq!(DROP_COUNTER.load(Ordering::SeqCst), 2); } diff --git a/src/test/ui/span/E0493.rs b/src/test/ui/span/E0493.rs index ea4526b70f6a8..eae871d2d4e46 100644 --- a/src/test/ui/span/E0493.rs +++ b/src/test/ui/span/E0493.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(drop_types_in_const)] + struct Foo { a: u32 } @@ -24,7 +26,7 @@ impl Drop for Bar { fn drop(&mut self) {} } -const F : Foo = Foo { a : 0 }; +const F : Foo = (Foo { a : 0 }, Foo { a : 1 }).1; fn main() { } diff --git a/src/test/ui/span/E0493.stderr b/src/test/ui/span/E0493.stderr index afcc9a240eb4e..8da11fefc177a 100644 --- a/src/test/ui/span/E0493.stderr +++ b/src/test/ui/span/E0493.stderr @@ -1,11 +1,11 @@ error[E0493]: constants are not allowed to have destructors - --> $DIR/E0493.rs:27:17 + --> $DIR/E0493.rs:29:17 | -16 | fn drop(&mut self) {} +18 | fn drop(&mut self) {} | --------------------- destructor defined here ... -27 | const F : Foo = Foo { a : 0 }; - | ^^^^^^^^^^^^^ constants cannot have destructors +29 | const F : Foo = (Foo { a : 0 }, Foo { a : 1 }).1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constants cannot have destructors error: aborting due to previous error