diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 84d84cbd5e190..8468783b75e1c 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -92,6 +92,7 @@ pub mod prelude; /* Core modules for ownership management */ pub mod intrinsics; +pub mod manually_drop; pub mod mem; pub mod ptr; diff --git a/src/libcore/manually_drop.rs b/src/libcore/manually_drop.rs new file mode 100644 index 0000000000000..444ba62a04eeb --- /dev/null +++ b/src/libcore/manually_drop.rs @@ -0,0 +1,57 @@ +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Exposes the `ManuallyDrop` lang item for controlling the exactly what gets dropped within a +//! structure. + +/// A wrapper type that stores data inline without running its destructor when dropped. +#[lang="manually_drop"] +#[experimental] +pub struct ManuallyDrop { + /// Wrapped value + /// + /// This field should not be accessed directly, it is made public for static + /// initializers. + #[unstable] + pub value: T, +} + +impl ManuallyDrop { + /// Construct a new instance of `ManuallyDrop` which will wrap the specified + /// value. + /// + /// All access to the inner value through methods is `unsafe`, and it is + /// highly discouraged to access the fields directly. + /// + /// This function is unsafe for the same reason as `forget`, namely that it + /// prevents the value's destructors from running. + #[experimental] + pub unsafe fn new(value: T) -> ManuallyDrop { + ManuallyDrop { value: value } + } + + /// Gets a mutable pointer to the wrapped value. + /// + /// This function is unsafe as the pointer returned is an unsafe pointer and + /// no guarantees are made about the aliasing of the pointers being handed + /// out in this or other tasks. + #[experimental] + pub unsafe fn get(&self) -> *const T { + &self.value as *const T + } + + /// Unwraps the value + /// + /// This function is unsafe because there is no guarantee that this or other + /// tasks are currently inspecting the inner value. Additionally, the destructor + /// for the inner value is suddenly rescheduled to run. + #[experimental] + pub unsafe fn into_inner(self) -> T { self.value } +} diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 4a20c92d8e21e..8bc4ddedb31c6 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -256,6 +256,8 @@ lets_do_this! { UnsafeTypeLangItem, "unsafe", unsafe_type; + ManuallyDropLangItem, "manually_drop", manually_drop; + DerefTraitLangItem, "deref", deref_trait; DerefMutTraitLangItem, "deref_mut", deref_mut_trait; diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index ddbf69685cd91..144dab78e344c 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -3106,6 +3106,8 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents { tc | TC::Managed } else if Some(did) == cx.lang_items.unsafe_type() { tc | TC::InteriorUnsafe + } else if Some(did) == cx.lang_items.manually_drop() { + tc - TC::OwnsDtor } else { tc } diff --git a/src/test/run-pass/manually_drop.rs b/src/test/run-pass/manually_drop.rs new file mode 100644 index 0000000000000..c842111940765 --- /dev/null +++ b/src/test/run-pass/manually_drop.rs @@ -0,0 +1,37 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +extern crate core; + +static mut value: uint = 0; + +struct Canary; + +impl Drop for Canary { + fn drop(&mut self) { + unsafe { + value += 1; + } + } +} + +fn main() { + unsafe { + assert_eq!(value, 0); + + { Canary; } + assert_eq!(value, 1); + + { core::manually_drop::ManuallyDrop::new(Canary); } + assert_eq!(value, 1); + + { core::manually_drop::ManuallyDrop::new(Canary).into_inner(); } + assert_eq!(value, 2); + } +}