about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-05-15 15:56:54 -0700
committerbors <bors@rust-lang.org>2014-05-15 15:56:54 -0700
commit0481d628b826104085c5df267cf6089a89fcd17b (patch)
tree5d488af95a17f26977bb0384d701bd560dbdcde8 /src/libstd
parent182c96c9212a2b7e830fe5f9a6662e72f73775ec (diff)
parent17df573a2e47d5815b5feb938626f9b6ec9ee4ee (diff)
downloadrust-0481d628b826104085c5df267cf6089a89fcd17b.tar.gz
rust-0481d628b826104085c5df267cf6089a89fcd17b.zip
auto merge of #14234 : alexcrichton/rust/rollup, r=alexcrichton
Let's try this again!
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/bitflags.rs37
-rw-r--r--src/libstd/io/buffered.rs21
-rw-r--r--src/libstd/io/flate.rs52
-rw-r--r--src/libstd/io/tempfile.rs36
-rw-r--r--src/libstd/lib.rs7
-rw-r--r--src/libstd/rt/local.rs22
-rw-r--r--src/libstd/rt/thread.rs10
-rw-r--r--src/libstd/str.rs5
-rw-r--r--src/libstd/unstable/mod.rs31
-rw-r--r--src/libstd/vec.rs45
10 files changed, 135 insertions, 131 deletions
diff --git a/src/libstd/bitflags.rs b/src/libstd/bitflags.rs
index 32f9bc1173b..163ccd22552 100644
--- a/src/libstd/bitflags.rs
+++ b/src/libstd/bitflags.rs
@@ -136,10 +136,20 @@ macro_rules! bitflags(
                 self.bits
             }
 
-            /// Convert from underlying bit representation. Unsafe because the
-            /// bits are not guaranteed to represent valid flags.
-            pub unsafe fn from_bits(bits: $T) -> $BitFlags {
-                $BitFlags { bits: bits }
+            /// Convert from underlying bit representation, unless that
+            /// representation contains bits that do not correspond to a flag.
+            pub fn from_bits(bits: $T) -> ::std::option::Option<$BitFlags> {
+                if (bits & !$BitFlags::all().bits()) != 0 {
+                    ::std::option::None
+                } else {
+                    ::std::option::Some($BitFlags { bits: bits })
+                }
+            }
+
+            /// Convert from underlying bit representation, dropping any bits
+            /// that do not correspond to flags.
+            pub fn from_bits_truncate(bits: $T) -> $BitFlags {
+                $BitFlags { bits: bits } & $BitFlags::all()
             }
 
             /// Returns `true` if no flags are currently stored.
@@ -209,6 +219,7 @@ macro_rules! bitflags(
 
 #[cfg(test)]
 mod tests {
+    use option::{Some, None};
     use ops::{BitOr, BitAnd, Sub, Not};
 
     bitflags!(
@@ -231,9 +242,21 @@ mod tests {
 
     #[test]
     fn test_from_bits() {
-        assert!(unsafe { Flags::from_bits(0x00000000) } == Flags::empty());
-        assert!(unsafe { Flags::from_bits(0x00000001) } == FlagA);
-        assert!(unsafe { Flags::from_bits(0x00000111) } == FlagABC);
+        assert!(Flags::from_bits(0) == Some(Flags::empty()));
+        assert!(Flags::from_bits(0x1) == Some(FlagA));
+        assert!(Flags::from_bits(0x10) == Some(FlagB));
+        assert!(Flags::from_bits(0x11) == Some(FlagA | FlagB));
+        assert!(Flags::from_bits(0x1000) == None);
+    }
+
+    #[test]
+    fn test_from_bits_truncate() {
+        assert!(Flags::from_bits_truncate(0) == Flags::empty());
+        assert!(Flags::from_bits_truncate(0x1) == FlagA);
+        assert!(Flags::from_bits_truncate(0x10) == FlagB);
+        assert!(Flags::from_bits_truncate(0x11) == (FlagA | FlagB));
+        assert!(Flags::from_bits_truncate(0x1000) == Flags::empty());
+        assert!(Flags::from_bits_truncate(0x1001) == FlagA);
     }
 
     #[test]
diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs
index a8e7b324bd7..68cbdd2e0aa 100644
--- a/src/libstd/io/buffered.rs
+++ b/src/libstd/io/buffered.rs
@@ -209,7 +209,7 @@ impl<W: Writer> Writer for BufferedWriter<W> {
 impl<W: Writer> Drop for BufferedWriter<W> {
     fn drop(&mut self) {
         if self.inner.is_some() {
-            // FIXME(#12628): should this error be ignored?
+            // dtors should not fail, so we ignore a failed flush
             let _ = self.flush_buf();
         }
     }
@@ -370,6 +370,7 @@ mod test {
     use io;
     use prelude::*;
     use super::*;
+    use super::super::{IoResult, EndOfFile};
     use super::super::mem::{MemReader, MemWriter, BufReader};
     use self::test::Bencher;
     use str::StrSlice;
@@ -584,6 +585,24 @@ mod test {
         assert_eq!(it.next(), None);
     }
 
+    #[test]
+    #[should_fail]
+    fn dont_fail_in_drop_on_failed_flush() {
+        struct FailFlushWriter;
+
+        impl Writer for FailFlushWriter {
+            fn write(&mut self, _buf: &[u8]) -> IoResult<()> { Ok(()) }
+            fn flush(&mut self) -> IoResult<()> { Err(io::standard_error(EndOfFile)) }
+        }
+
+        let writer = FailFlushWriter;
+        let _writer = BufferedWriter::new(writer);
+
+        // Trigger failure. If writer fails *again* due to the flush
+        // error then the process will abort.
+        fail!();
+    }
+
     #[bench]
     fn bench_buffered_reader(b: &mut Bencher) {
         b.iter(|| {
diff --git a/src/libstd/io/flate.rs b/src/libstd/io/flate.rs
deleted file mode 100644
index 0cf00b2c1a9..00000000000
--- a/src/libstd/io/flate.rs
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2013 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Some various other I/O types
-
-// FIXME(#3660): should move to libextra
-
-use prelude::*;
-use super::*;
-
-/// A Writer decorator that compresses using the 'deflate' scheme
-pub struct DeflateWriter<W> {
-    priv inner_writer: W
-}
-
-impl<W: Writer> DeflateWriter<W> {
-    pub fn new(inner_writer: W) -> DeflateWriter<W> {
-        DeflateWriter {
-            inner_writer: inner_writer
-        }
-    }
-}
-
-impl<W: Writer> Writer for DeflateWriter<W> {
-    fn write(&mut self, _buf: &[u8]) { fail!() }
-
-    fn flush(&mut self) { fail!() }
-}
-
-/// A Reader decorator that decompresses using the 'deflate' scheme
-pub struct InflateReader<R> {
-    priv inner_reader: R
-}
-
-impl<R: Reader> InflateReader<R> {
-    pub fn new(inner_reader: R) -> InflateReader<R> {
-        InflateReader {
-            inner_reader: inner_reader
-        }
-    }
-}
-
-impl<R: Reader> Reader for InflateReader<R> {
-    fn read(&mut self, _buf: &mut [u8]) -> Option<uint> { fail!() }
-}
diff --git a/src/libstd/io/tempfile.rs b/src/libstd/io/tempfile.rs
index 8c28caa988a..b4fb95c8af7 100644
--- a/src/libstd/io/tempfile.rs
+++ b/src/libstd/io/tempfile.rs
@@ -10,7 +10,7 @@
 
 //! Temporary files and directories
 
-use io::fs;
+use io::{fs, IoResult};
 use io;
 use iter::{Iterator, range};
 use libc;
@@ -18,13 +18,14 @@ use ops::Drop;
 use option::{Option, None, Some};
 use os;
 use path::{Path, GenericPath};
-use result::{Ok, Err, ResultUnwrap};
+use result::{Ok, Err};
 use sync::atomics;
 
 /// A wrapper for a path to temporary directory implementing automatic
 /// scope-based deletion.
 pub struct TempDir {
-    path: Option<Path>
+    path: Option<Path>,
+    disarmed: bool
 }
 
 impl TempDir {
@@ -48,7 +49,7 @@ impl TempDir {
             let p = tmpdir.join(filename);
             match fs::mkdir(&p, io::UserRWX) {
                 Err(..) => {}
-                Ok(()) => return Some(TempDir { path: Some(p) })
+                Ok(()) => return Some(TempDir { path: Some(p), disarmed: false })
             }
         }
         None
@@ -75,15 +76,32 @@ impl TempDir {
     pub fn path<'a>(&'a self) -> &'a Path {
         self.path.get_ref()
     }
+
+    /// Close and remove the temporary directory
+    ///
+    /// Although `TempDir` removes the directory on drop, in the destructor
+    /// any errors are ignored. To detect errors cleaning up the temporary
+    /// directory, call `close` instead.
+    pub fn close(mut self) -> IoResult<()> {
+        self.cleanup_dir()
+    }
+
+    fn cleanup_dir(&mut self) -> IoResult<()> {
+        assert!(!self.disarmed);
+        self.disarmed = true;
+        match self.path {
+            Some(ref p) => {
+                fs::rmdir_recursive(p)
+            }
+            None => Ok(())
+        }
+    }
 }
 
 impl Drop for TempDir {
     fn drop(&mut self) {
-        for path in self.path.iter() {
-            if path.exists() {
-                // FIXME: is failing the right thing to do?
-                fs::rmdir_recursive(path).unwrap();
-            }
+        if !self.disarmed {
+            let _ = self.cleanup_dir();
         }
     }
 }
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index a37f9a516fd..87c4ef1046f 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -133,16 +133,13 @@ extern crate core;
 #[cfg(test)] pub use ops = realstd::ops;
 #[cfg(test)] pub use cmp = realstd::cmp;
 #[cfg(test)] pub use ty = realstd::ty;
-#[cfg(not(stage0), test)] pub use owned = realstd::owned;
+#[cfg(test)] pub use owned = realstd::owned;
 
 #[cfg(not(test))] pub use cmp = core::cmp;
 #[cfg(not(test))] pub use kinds = core::kinds;
 #[cfg(not(test))] pub use ops = core::ops;
 #[cfg(not(test))] pub use ty = core::ty;
 
-#[cfg(stage0, test)] pub use owned = realstd::owned;
-#[cfg(stage0, not(test))] pub use owned = core::owned;
-
 pub use core::any;
 pub use core::bool;
 pub use core::cell;
@@ -209,7 +206,7 @@ pub mod ascii;
 
 pub mod rc;
 pub mod gc;
-#[cfg(not(stage0), not(test))]
+#[cfg(not(test))]
 pub mod owned;
 
 /* Common traits */
diff --git a/src/libstd/rt/local.rs b/src/libstd/rt/local.rs
index 05d1f1764b5..9f0ed804480 100644
--- a/src/libstd/rt/local.rs
+++ b/src/libstd/rt/local.rs
@@ -53,24 +53,24 @@ impl Local<local_ptr::Borrowed<Task>> for Task {
 #[cfg(test)]
 mod test {
     use option::{None, Option};
-    use unstable::run_in_bare_thread;
+    use rt::thread::Thread;
     use super::*;
     use owned::Box;
     use rt::task::Task;
 
     #[test]
     fn thread_local_task_smoke_test() {
-        run_in_bare_thread(proc() {
+        Thread::start(proc() {
             let task = box Task::new();
             Local::put(task);
             let task: Box<Task> = Local::take();
             cleanup_task(task);
-        });
+        }).join();
     }
 
     #[test]
     fn thread_local_task_two_instances() {
-        run_in_bare_thread(proc() {
+        Thread::start(proc() {
             let task = box Task::new();
             Local::put(task);
             let task: Box<Task> = Local::take();
@@ -79,12 +79,12 @@ mod test {
             Local::put(task);
             let task: Box<Task> = Local::take();
             cleanup_task(task);
-        });
+        }).join();
     }
 
     #[test]
     fn borrow_smoke_test() {
-        run_in_bare_thread(proc() {
+        Thread::start(proc() {
             let task = box Task::new();
             Local::put(task);
 
@@ -93,12 +93,12 @@ mod test {
             }
             let task: Box<Task> = Local::take();
             cleanup_task(task);
-        });
+        }).join();
     }
 
     #[test]
     fn borrow_with_return() {
-        run_in_bare_thread(proc() {
+        Thread::start(proc() {
             let task = box Task::new();
             Local::put(task);
 
@@ -108,12 +108,12 @@ mod test {
 
             let task: Box<Task> = Local::take();
             cleanup_task(task);
-        });
+        }).join();
     }
 
     #[test]
     fn try_take() {
-        run_in_bare_thread(proc() {
+        Thread::start(proc() {
             let task = box Task::new();
             Local::put(task);
 
@@ -122,7 +122,7 @@ mod test {
             assert!(u.is_none());
 
             cleanup_task(t);
-        });
+        }).join();
     }
 
     fn cleanup_task(mut t: Box<Task>) {
diff --git a/src/libstd/rt/thread.rs b/src/libstd/rt/thread.rs
index 4f0d7d35ce8..e25fa4734d5 100644
--- a/src/libstd/rt/thread.rs
+++ b/src/libstd/rt/thread.rs
@@ -273,13 +273,8 @@ mod imp {
         assert_eq!(pthread_detach(native), 0);
     }
 
-    #[cfg(target_os = "macos")]
-    #[cfg(target_os = "android")]
     pub unsafe fn yield_now() { assert_eq!(sched_yield(), 0); }
 
-    #[cfg(not(target_os = "macos"), not(target_os = "android"))]
-    pub unsafe fn yield_now() { assert_eq!(pthread_yield(), 0); }
-
     // glibc >= 2.15 has a __pthread_get_minstack() function that returns
     // PTHREAD_STACK_MIN plus however many bytes are needed for thread-local
     // storage.  We need that information to avoid blowing up when a small stack
@@ -326,12 +321,7 @@ mod imp {
         fn pthread_attr_setdetachstate(attr: *mut libc::pthread_attr_t,
                                        state: libc::c_int) -> libc::c_int;
         fn pthread_detach(thread: libc::pthread_t) -> libc::c_int;
-
-        #[cfg(target_os = "macos")]
-        #[cfg(target_os = "android")]
         fn sched_yield() -> libc::c_int;
-        #[cfg(not(target_os = "macos"), not(target_os = "android"))]
-        fn pthread_yield() -> libc::c_int;
     }
 }
 
diff --git a/src/libstd/str.rs b/src/libstd/str.rs
index fa4cf8e4427..aee5fe9ff96 100644
--- a/src/libstd/str.rs
+++ b/src/libstd/str.rs
@@ -564,6 +564,11 @@ impl<'a> IntoMaybeOwned<'a> for ~str {
     fn into_maybe_owned(self) -> MaybeOwned<'a> { Owned(self) }
 }
 
+impl<'a> IntoMaybeOwned<'a> for StrBuf {
+    #[inline]
+    fn into_maybe_owned(self) -> MaybeOwned<'a> { Owned(self.into_owned()) }
+}
+
 impl<'a> IntoMaybeOwned<'a> for &'a str {
     #[inline]
     fn into_maybe_owned(self) -> MaybeOwned<'a> { Slice(self) }
diff --git a/src/libstd/unstable/mod.rs b/src/libstd/unstable/mod.rs
index 8b07850263f..f464f70772d 100644
--- a/src/libstd/unstable/mod.rs
+++ b/src/libstd/unstable/mod.rs
@@ -11,7 +11,6 @@
 #![doc(hidden)]
 
 use libc::uintptr_t;
-use kinds::Send;
 
 pub use core::finally;
 
@@ -21,36 +20,6 @@ pub mod simd;
 pub mod sync;
 pub mod mutex;
 
-/**
-
-Start a new thread outside of the current runtime context and wait
-for it to terminate.
-
-The executing thread has no access to a task pointer and will be using
-a normal large stack.
-*/
-pub fn run_in_bare_thread(f: proc():Send) {
-    use rt::thread::Thread;
-    Thread::start(f).join()
-}
-
-#[test]
-fn test_run_in_bare_thread() {
-    let i = 100;
-    run_in_bare_thread(proc() {
-        assert_eq!(i, 100);
-    });
-}
-
-#[test]
-fn test_run_in_bare_thread_exchange() {
-    // Does the exchange heap work without the runtime?
-    let i = box 100;
-    run_in_bare_thread(proc() {
-        assert!(i == box 100);
-    });
-}
-
 /// Dynamically inquire about whether we're running under V.
 /// You should usually not use this unless your test definitely
 /// can't run correctly un-altered. Valgrind is there to help
diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs
index 528ab72762a..57f8d78948f 100644
--- a/src/libstd/vec.rs
+++ b/src/libstd/vec.rs
@@ -635,14 +635,14 @@ impl<T> Vec<T> {
     /// ```
     pub fn truncate(&mut self, len: uint) {
         unsafe {
-            let mut i = len;
             // drop any extra elements
-            while i < self.len {
-                ptr::read(self.as_slice().unsafe_ref(i));
-                i += 1;
+            while len < self.len {
+                // decrement len before the read(), so a failure on Drop doesn't
+                // re-drop the just-failed value.
+                self.len -= 1;
+                ptr::read(self.as_slice().unsafe_ref(self.len));
             }
         }
-        self.len = len;
     }
 
     /// Work with `self` as a mutable slice.
@@ -1862,4 +1862,39 @@ mod tests {
         assert_eq!(b[0].x, 42);
         assert_eq!(b[1].x, 84);
     }
+
+    #[test]
+    fn test_vec_truncate_drop() {
+        static mut drops: uint = 0;
+        struct Elem(int);
+        impl Drop for Elem {
+            fn drop(&mut self) {
+                unsafe { drops += 1; }
+            }
+        }
+
+        let mut v = vec![Elem(1), Elem(2), Elem(3), Elem(4), Elem(5)];
+        assert_eq!(unsafe { drops }, 0);
+        v.truncate(3);
+        assert_eq!(unsafe { drops }, 2);
+        v.truncate(0);
+        assert_eq!(unsafe { drops }, 5);
+    }
+
+    #[test]
+    #[should_fail]
+    fn test_vec_truncate_fail() {
+        struct BadElem(int);
+        impl Drop for BadElem {
+            fn drop(&mut self) {
+                let BadElem(ref mut x) = *self;
+                if *x == 0xbadbeef {
+                    fail!("BadElem failure: 0xbadbeef")
+                }
+            }
+        }
+
+        let mut v = vec![BadElem(1), BadElem(2), BadElem(0xbadbeef), BadElem(4)];
+        v.truncate(0);
+    }
 }