summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorBrian Anderson <andersrb@gmail.com>2015-05-11 11:22:01 -0700
committerBrian Anderson <andersrb@gmail.com>2015-05-11 11:22:01 -0700
commitfd815b7a57b0214362d53b5e4e0dc282c5c26dfd (patch)
treed3710cc7dcdb877fcc9c6622cab032c0c0920d8b /src
parent781c2aa6200f45fe2ce6c4cb74779792c17add63 (diff)
parentf245929834543ca9a00278827a82d29ae3b2770f (diff)
downloadrust-fd815b7a57b0214362d53b5e4e0dc282c5c26dfd.tar.gz
rust-fd815b7a57b0214362d53b5e4e0dc282c5c26dfd.zip
Merge pull request #25299 from alexcrichton/beta-backport
Backport mem::forget to beta
Diffstat (limited to 'src')
-rw-r--r--src/libcollections/slice.rs11
-rw-r--r--src/libcollections/str.rs11
-rw-r--r--src/libcollections/string.rs8
-rw-r--r--src/libcollections/vec.rs4
-rw-r--r--src/libcore/intrinsics.rs4
-rw-r--r--src/libcore/mem.rs51
-rw-r--r--src/libcore/str/mod.rs9
-rw-r--r--src/libstd/sys/unix/fd.rs2
-rw-r--r--src/libstd/sys/windows/handle.rs2
9 files changed, 76 insertions, 26 deletions
diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs
index 6622d8a9c40..8a566445e38 100644
--- a/src/libcollections/slice.rs
+++ b/src/libcollections/slice.rs
@@ -80,7 +80,6 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use alloc::boxed::Box;
-use core::convert::AsRef;
 use core::clone::Clone;
 use core::cmp::Ordering::{self, Greater, Less};
 use core::cmp::{self, Ord, PartialEq};
@@ -1028,23 +1027,23 @@ pub trait SliceConcatExt<T: ?Sized, U> {
     fn connect(&self, sep: &T) -> U;
 }
 
-impl<T: Clone, V: AsRef<[T]>> SliceConcatExt<T, Vec<T>> for [V] {
+impl<T: Clone, V: Borrow<[T]>> SliceConcatExt<T, Vec<T>> for [V] {
     fn concat(&self) -> Vec<T> {
-        let size = self.iter().fold(0, |acc, v| acc + v.as_ref().len());
+        let size = self.iter().fold(0, |acc, v| acc + v.borrow().len());
         let mut result = Vec::with_capacity(size);
         for v in self {
-            result.push_all(v.as_ref())
+            result.push_all(v.borrow())
         }
         result
     }
 
     fn connect(&self, sep: &T) -> Vec<T> {
-        let size = self.iter().fold(0, |acc, v| acc + v.as_ref().len());
+        let size = self.iter().fold(0, |acc, v| acc + v.borrow().len());
         let mut result = Vec::with_capacity(size + self.len());
         let mut first = true;
         for v in self {
             if first { first = false } else { result.push(sep.clone()) }
-            result.push_all(v.as_ref())
+            result.push_all(v.borrow())
         }
         result
     }
diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs
index 7a28b56b7c1..6edc62785e8 100644
--- a/src/libcollections/str.rs
+++ b/src/libcollections/str.rs
@@ -61,7 +61,6 @@ use core::str::pattern::Pattern;
 use core::str::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher};
 use unicode::str::{UnicodeStr, Utf16Encoder};
 
-use core::convert::AsRef;
 use vec_deque::VecDeque;
 use borrow::{Borrow, ToOwned};
 use string::String;
@@ -85,18 +84,18 @@ pub use core::str::pattern;
 Section: Creating a string
 */
 
-impl<S: AsRef<str>> SliceConcatExt<str, String> for [S] {
+impl<S: Borrow<str>> SliceConcatExt<str, String> for [S] {
     fn concat(&self) -> String {
         if self.is_empty() {
             return String::new();
         }
 
         // `len` calculation may overflow but push_str will check boundaries
-        let len = self.iter().map(|s| s.as_ref().len()).sum();
+        let len = self.iter().map(|s| s.borrow().len()).sum();
         let mut result = String::with_capacity(len);
 
         for s in self {
-            result.push_str(s.as_ref())
+            result.push_str(s.borrow())
         }
 
         result
@@ -115,7 +114,7 @@ impl<S: AsRef<str>> SliceConcatExt<str, String> for [S] {
         // this is wrong without the guarantee that `self` is non-empty
         // `len` calculation may overflow but push_str but will check boundaries
         let len = sep.len() * (self.len() - 1)
-            + self.iter().map(|s| s.as_ref().len()).sum::<usize>();
+            + self.iter().map(|s| s.borrow().len()).sum::<usize>();
         let mut result = String::with_capacity(len);
         let mut first = true;
 
@@ -125,7 +124,7 @@ impl<S: AsRef<str>> SliceConcatExt<str, String> for [S] {
             } else {
                 result.push_str(sep);
             }
-            result.push_str(s.as_ref());
+            result.push_str(s.borrow());
         }
         result
     }
diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs
index 41ad7c2d783..66fa4573bd7 100644
--- a/src/libcollections/string.rs
+++ b/src/libcollections/string.rs
@@ -1006,6 +1006,14 @@ impl AsRef<str> for String {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
+impl AsRef<[u8]> for String {
+    #[inline]
+    fn as_ref(&self) -> &[u8] {
+        self.as_bytes()
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> From<&'a str> for String {
     #[inline]
     fn from(s: &'a str) -> String {
diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs
index 6195056579d..d5112c9fdff 100644
--- a/src/libcollections/vec.rs
+++ b/src/libcollections/vec.rs
@@ -637,7 +637,7 @@ impl<T> Vec<T> {
             // zero-size types consume no memory, so we can't rely on the
             // address space running out
             self.len = self.len.checked_add(1).expect("length overflow");
-            unsafe { mem::forget(value); }
+            mem::forget(value);
             return
         }
 
@@ -959,7 +959,7 @@ impl<T> Vec<T> {
                 num_u: 0,
                 marker: PhantomData,
             };
-            unsafe { mem::forget(vec); }
+            mem::forget(vec);
 
             while pv.num_t != 0 {
                 unsafe {
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index 8ed89adec5b..077d6367ff3 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -217,10 +217,6 @@ extern "rust-intrinsic" {
     pub fn uninit<T>() -> T;
 
     /// Moves a value out of scope without running drop glue.
-    ///
-    /// `forget` is unsafe because the caller is responsible for
-    /// ensuring the argument is deallocated already.
-    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn forget<T>(_: T) -> ();
 
     /// Unsafely transforms a value of one type into a value of another type.
diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs
index c4128e79765..a149af3a440 100644
--- a/src/libcore/mem.rs
+++ b/src/libcore/mem.rs
@@ -22,15 +22,54 @@ use ptr;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use intrinsics::transmute;
 
-/// Moves a thing into the void.
+/// Leaks a value into the void, consuming ownership and never running its
+/// destructor.
 ///
-/// The forget function will take ownership of the provided value but neglect
-/// to run any required cleanup or memory management operations on it.
+/// This function will take ownership of its argument, but is distinct from the
+/// `mem::drop` function in that it **does not run the destructor**, leaking the
+/// value and any resources that it owns.
 ///
-/// This function is the unsafe version of the `drop` function because it does
-/// not run any destructors.
+/// # Safety
+///
+/// This function is not marked as `unsafe` as Rust does not guarantee that the
+/// `Drop` implementation for a value will always run. Note, however, that
+/// leaking resources such as memory or I/O objects is likely not desired, so
+/// this function is only recommended for specialized use cases.
+///
+/// The safety of this function implies that when writing `unsafe` code
+/// yourself care must be taken when leveraging a destructor that is required to
+/// run to preserve memory safety. There are known situations where the
+/// destructor may not run (such as if ownership of the object with the
+/// destructor is returned) which must be taken into account.
+///
+/// # Other forms of Leakage
+///
+/// It's important to point out that this function is not the only method by
+/// which a value can be leaked in safe Rust code. Other known sources of
+/// leakage are:
+///
+/// * `Rc` and `Arc` cycles
+/// * `mpsc::{Sender, Receiver}` cycles (they use `Arc` internally)
+/// * Panicking destructors are likely to leak local resources
+///
+/// # Example
+///
+/// ```rust,no_run
+/// use std::mem;
+/// use std::fs::File;
+///
+/// // Leak some heap memory by never deallocating it
+/// let heap_memory = Box::new(3);
+/// mem::forget(heap_memory);
+///
+/// // Leak an I/O object, never closing the file
+/// let file = File::open("foo.txt").unwrap();
+/// mem::forget(file);
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use intrinsics::forget;
+pub fn forget<T>(t: T) {
+    unsafe { intrinsics::forget(t) }
+}
 
 /// Returns the size of a type in bytes.
 ///
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index 31431f44962..bdd9f5a7ba7 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -23,6 +23,7 @@ use self::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher};
 use char::CharExt;
 use clone::Clone;
 use cmp::{self, Eq};
+use convert::AsRef;
 use default::Default;
 use fmt;
 use iter::ExactSizeIterator;
@@ -1843,6 +1844,14 @@ impl StrExt for str {
     fn parse<T: FromStr>(&self) -> Result<T, T::Err> { FromStr::from_str(self) }
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRef<[u8]> for str {
+    #[inline]
+    fn as_ref(&self) -> &[u8] {
+        self.as_bytes()
+    }
+}
+
 /// Pluck a code point out of a UTF-8-like byte slice and return the
 /// index of the next code point.
 #[inline]
diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs
index e5bdb554359..026380027d2 100644
--- a/src/libstd/sys/unix/fd.rs
+++ b/src/libstd/sys/unix/fd.rs
@@ -31,7 +31,7 @@ impl FileDesc {
     /// Extracts the actual filedescriptor without closing it.
     pub fn into_raw(self) -> c_int {
         let fd = self.fd;
-        unsafe { mem::forget(self) };
+        mem::forget(self);
         fd
     }
 
diff --git a/src/libstd/sys/windows/handle.rs b/src/libstd/sys/windows/handle.rs
index 9481e180ce5..c835d503388 100644
--- a/src/libstd/sys/windows/handle.rs
+++ b/src/libstd/sys/windows/handle.rs
@@ -32,7 +32,7 @@ impl Handle {
 
     pub fn into_raw(self) -> HANDLE {
         let ret = self.0;
-        unsafe { mem::forget(self) }
+        mem::forget(self);
         return ret;
     }