diff options
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/bitflags.rs | 37 | ||||
| -rw-r--r-- | src/libstd/io/buffered.rs | 21 | ||||
| -rw-r--r-- | src/libstd/io/flate.rs | 52 | ||||
| -rw-r--r-- | src/libstd/io/tempfile.rs | 36 | ||||
| -rw-r--r-- | src/libstd/lib.rs | 7 | ||||
| -rw-r--r-- | src/libstd/rt/local.rs | 22 | ||||
| -rw-r--r-- | src/libstd/rt/thread.rs | 10 | ||||
| -rw-r--r-- | src/libstd/str.rs | 5 | ||||
| -rw-r--r-- | src/libstd/unstable/mod.rs | 31 | ||||
| -rw-r--r-- | src/libstd/vec.rs | 45 |
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); + } } |
