From 7009e6d001ebc807eca04c5b9f07779db02eca99 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 14 Nov 2019 12:13:16 +0100 Subject: mem::forget docs: mention ManuallyDrop --- src/libcore/mem/mod.rs | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) (limited to 'src/libcore') diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs index dc7c36ff03c..5ba2a3aa599 100644 --- a/src/libcore/mem/mod.rs +++ b/src/libcore/mem/mod.rs @@ -45,8 +45,9 @@ pub use crate::intrinsics::transmute; /// `mem::forget` from safe code does not fundamentally change Rust's safety /// guarantees. /// -/// That said, leaking resources such as memory or I/O objects is usually undesirable, -/// so `forget` is only recommended for specialized use cases like those shown below. +/// That said, leaking resources such as memory or I/O objects is usually undesirable. +/// The need comes up in some specialized use cases for FFI or unsafe code, but even +/// then, [`ManuallyDrop`] is typically preferred. /// /// Because forgetting a value is allowed, any `unsafe` code you write must /// allow for this possibility. You cannot return a value and expect that the @@ -68,7 +69,35 @@ pub use crate::intrinsics::transmute; /// ``` /// /// The practical use cases for `forget` are rather specialized and mainly come -/// up in unsafe or FFI code. +/// up in unsafe or FFI code. However, [`ManuallyDrop`] is usually preferred +/// for such cases, e.g.: +/// +/// ``` +/// use std::mem::ManuallyDrop; +/// +/// let v = vec![65, 122]; +/// // Before we disassemble `v` into its raw parts, make sure it +/// // does not get dropped! +/// let mut v = ManuallyDrop::new(v); +/// // Now disassemble `v`. These operations cannot panic, so there cannot be a leak. +/// let ptr = v.as_mut_ptr(); +/// let cap = v.capacity(); +/// // Finally, build a `String`. +/// let s = unsafe { String::from_raw_parts(ptr, 2, cap) }; +/// assert_eq!(s, "Az"); +/// // `s` is implicitly dropped and its memory deallocated. +/// ``` +/// +/// Using `ManuallyDrop` here has two advantages: +/// +/// * We do not "touch" `v` after disassembling it. For some types, operations +/// such as passing ownership (to a funcion like `mem::forget`) requires them to actually +/// be fully owned right now; that is a promise we do not want to make here as we are +/// in the process of transferring ownership to the new `String` we are building. +/// * In case of an unexpected panic, `ManuallyDrop` is not dropped, but if the panic +/// occurs before `mem::forget` was called we might end up dropping invalid data, +/// or double-dropping. In other words, `ManuallyDrop` errs on the side of leaking +/// instead of erring on the side of dropping. /// /// [drop]: fn.drop.html /// [uninit]: fn.uninitialized.html @@ -78,6 +107,7 @@ pub use crate::intrinsics::transmute; /// [leak]: ../../std/boxed/struct.Box.html#method.leak /// [into_raw]: ../../std/boxed/struct.Box.html#method.into_raw /// [ub]: ../../reference/behavior-considered-undefined.html +/// [`ManuallyDrop`]: struct.ManuallyDrop.html #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn forget(t: T) { -- cgit 1.4.1-3-g733a5 From 59257e6e88cc09697642cce889445d0fd6572ec1 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 23 Nov 2019 07:06:27 +0100 Subject: make `./x.py bench` again --- src/libcore/benches/num/mod.rs | 4 +- src/librustc/benches/dispatch.rs | 34 ---------------- src/librustc/benches/lib.rs | 61 +++++++++++++++++++++++++++- src/librustc/benches/pattern.rs | 25 ------------ src/librustc_codegen_ssa/back/rpath/tests.rs | 4 +- 5 files changed, 63 insertions(+), 65 deletions(-) delete mode 100644 src/librustc/benches/dispatch.rs delete mode 100644 src/librustc/benches/pattern.rs (limited to 'src/libcore') diff --git a/src/libcore/benches/num/mod.rs b/src/libcore/benches/num/mod.rs index f5c49ea5bf0..2dcdf2b6fe9 100644 --- a/src/libcore/benches/num/mod.rs +++ b/src/libcore/benches/num/mod.rs @@ -35,7 +35,7 @@ macro_rules! from_str_bench { .iter() .cycle() .take(5_000) - .filter_map(|s| <($t)>::from_str(s).ok()) + .filter_map(|s| <$t>::from_str(s).ok()) .max() }) } @@ -51,7 +51,7 @@ macro_rules! from_str_radix_bench { .iter() .cycle() .take(5_000) - .filter_map(|s| <($t)>::from_str_radix(s, $radix).ok()) + .filter_map(|s| <$t>::from_str_radix(s, $radix).ok()) .max() }) } diff --git a/src/librustc/benches/dispatch.rs b/src/librustc/benches/dispatch.rs deleted file mode 100644 index e3b36be5696..00000000000 --- a/src/librustc/benches/dispatch.rs +++ /dev/null @@ -1,34 +0,0 @@ -use test::Bencher; - -// Static/dynamic method dispatch - -struct Struct { - field: isize -} - -trait Trait { - fn method(&self) -> isize; -} - -impl Trait for Struct { - fn method(&self) -> isize { - self.field - } -} - -#[bench] -fn trait_vtable_method_call(b: &mut Bencher) { - let s = Struct { field: 10 }; - let t = &s as &Trait; - b.iter(|| { - t.method() - }); -} - -#[bench] -fn trait_static_method_call(b: &mut Bencher) { - let s = Struct { field: 10 }; - b.iter(|| { - s.method() - }); -} diff --git a/src/librustc/benches/lib.rs b/src/librustc/benches/lib.rs index 0f81586d3bd..6b624028896 100644 --- a/src/librustc/benches/lib.rs +++ b/src/librustc/benches/lib.rs @@ -1,6 +1,63 @@ +#![feature(slice_patterns)] #![feature(test)] extern crate test; -mod dispatch; -mod pattern; +use test::Bencher; + +// Static/dynamic method dispatch + +struct Struct { + field: isize +} + +trait Trait { + fn method(&self) -> isize; +} + +impl Trait for Struct { + fn method(&self) -> isize { + self.field + } +} + +#[bench] +fn trait_vtable_method_call(b: &mut Bencher) { + let s = Struct { field: 10 }; + let t = &s as &dyn Trait; + b.iter(|| { + t.method() + }); +} + +#[bench] +fn trait_static_method_call(b: &mut Bencher) { + let s = Struct { field: 10 }; + b.iter(|| { + s.method() + }); +} + +// Overhead of various match forms + +#[bench] +fn option_some(b: &mut Bencher) { + let x = Some(10); + b.iter(|| { + match x { + Some(y) => y, + None => 11 + } + }); +} + +#[bench] +fn vec_pattern(b: &mut Bencher) { + let x = [1,2,3,4,5,6]; + b.iter(|| { + match x { + [1,2,3,..] => 10, + _ => 11, + } + }); +} diff --git a/src/librustc/benches/pattern.rs b/src/librustc/benches/pattern.rs deleted file mode 100644 index fd8cc5b83fd..00000000000 --- a/src/librustc/benches/pattern.rs +++ /dev/null @@ -1,25 +0,0 @@ -use test::Bencher; - -// Overhead of various match forms - -#[bench] -fn option_some(b: &mut Bencher) { - let x = Some(10); - b.iter(|| { - match x { - Some(y) => y, - None => 11 - } - }); -} - -#[bench] -fn vec_pattern(b: &mut Bencher) { - let x = [1,2,3,4,5,6]; - b.iter(|| { - match x { - [1,2,3,..] => 10, - _ => 11, - } - }); -} diff --git a/src/librustc_codegen_ssa/back/rpath/tests.rs b/src/librustc_codegen_ssa/back/rpath/tests.rs index e42a878d7e4..e8457fe0e19 100644 --- a/src/librustc_codegen_ssa/back/rpath/tests.rs +++ b/src/librustc_codegen_ssa/back/rpath/tests.rs @@ -52,7 +52,7 @@ fn test_minimize2() { fn test_rpath_relative() { if cfg!(target_os = "macos") { let config = &mut RPathConfig { - used_crates: Vec::new(), + used_crates: &[], has_rpath: true, is_like_osx: true, linker_is_gnu: false, @@ -64,7 +64,7 @@ fn test_rpath_relative() { assert_eq!(res, "@loader_path/../lib"); } else { let config = &mut RPathConfig { - used_crates: Vec::new(), + used_crates: &[], out_filename: PathBuf::from("bin/rustc"), get_install_prefix_lib_path: &mut || panic!(), has_rpath: true, -- cgit 1.4.1-3-g733a5