diff options
Diffstat (limited to 'src/libstd')
29 files changed, 474 insertions, 804 deletions
diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 2a2d41112ff..1459420cdc0 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -66,10 +66,80 @@ pub trait Error: Debug + Display + Reflect { /// The description should not contain newlines or sentence-ending /// punctuation, to facilitate embedding in larger user-facing /// strings. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// + /// match "xc".parse::<u32>() { + /// Err(e) => { + /// println!("Error: {}", e.description()); + /// } + /// _ => println!("No error"), + /// } + /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn description(&self) -> &str; /// The lower-level cause of this error, if any. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::fmt; + /// + /// #[derive(Debug)] + /// struct SuperError { + /// side: SuperErrorSideKick, + /// } + /// + /// impl fmt::Display for SuperError { + /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + /// write!(f, "SuperError is here!") + /// } + /// } + /// + /// impl Error for SuperError { + /// fn description(&self) -> &str { + /// "I'm the superhero of errors!" + /// } + /// + /// fn cause(&self) -> Option<&Error> { + /// Some(&self.side) + /// } + /// } + /// + /// #[derive(Debug)] + /// struct SuperErrorSideKick; + /// + /// impl fmt::Display for SuperErrorSideKick { + /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + /// write!(f, "SuperErrorSideKick is here!") + /// } + /// } + /// + /// impl Error for SuperErrorSideKick { + /// fn description(&self) -> &str { + /// "I'm SuperError side kick!" + /// } + /// } + /// + /// fn get_super_error() -> Result<(), SuperError> { + /// Err(SuperError { side: SuperErrorSideKick }) + /// } + /// + /// fn main() { + /// match get_super_error() { + /// Err(e) => { + /// println!("Error: {}", e.description()); + /// println!("Caused by: {}", e.cause().unwrap()); + /// } + /// _ => println!("No error"), + /// } + /// } + /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn cause(&self) -> Option<&Error> { None } diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 668fa1fb303..83439b3f132 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -141,7 +141,7 @@ pub struct Permissions(fs_imp::FilePermissions); /// An structure representing a type of file with accessors for each file type. #[stable(feature = "file_type", since = "1.1.0")] -#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub struct FileType(fs_imp::FileType); /// A builder used to create directories in various manners. diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs index 07f43f72ff5..c8b52fc0467 100644 --- a/src/libstd/io/util.rs +++ b/src/libstd/io/util.rs @@ -152,8 +152,8 @@ pub struct Sink { _priv: () } /// ```rust /// use std::io::{self, Write}; /// -/// let mut buffer = vec![1, 2, 3, 5, 8]; -/// let num_bytes = io::sink().write(&mut buffer).unwrap(); +/// let buffer = vec![1, 2, 3, 5, 8]; +/// let num_bytes = io::sink().write(&buffer).unwrap(); /// assert_eq!(num_bytes, 5); /// ``` #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index a396c7be09a..d05a5a09614 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -468,15 +468,3 @@ pub mod __rand { // the rustdoc documentation for primitive types. Using `include!` // because rustdoc only looks for these modules at the crate level. include!("primitive_docs.rs"); - -// FIXME(stage0): remove this after a snapshot -// HACK: this is needed because the interpretation of slice -// patterns changed between stage0 and now. -#[cfg(stage0)] -fn slice_pat<'a, 'b, T>(t: &'a &'b [T]) -> &'a &'b [T] { - t -} -#[cfg(not(stage0))] -fn slice_pat<'a, 'b, T>(t: &'a &'b [T]) -> &'b [T] { - *t -} diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 57d75441bff..67410e87a8b 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -83,6 +83,10 @@ impl Ipv4Addr { } /// Returns true for the special 'unspecified' address (0.0.0.0). + /// + /// This property is defined in _UNIX Network Programming, Second Edition_, + /// W. Richard Stevens, p. 891; see also [ip7] + /// [ip7][http://man7.org/linux/man-pages/man7/ip.7.html] pub fn is_unspecified(&self) -> bool { self.inner.s_addr == 0 } diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs index d8cadf09cb2..ba18d15f5c4 100644 --- a/src/libstd/panic.rs +++ b/src/libstd/panic.rs @@ -227,6 +227,11 @@ impl<T: ?Sized> !RefUnwindSafe for UnsafeCell<T> {} #[stable(feature = "catch_unwind", since = "1.9.0")] impl<T> RefUnwindSafe for AssertUnwindSafe<T> {} +#[stable(feature = "unwind_safe_lock_refs", since = "1.12.0")] +impl<T: ?Sized> RefUnwindSafe for Mutex<T> {} +#[stable(feature = "unwind_safe_lock_refs", since = "1.12.0")] +impl<T: ?Sized> RefUnwindSafe for RwLock<T> {} + #[stable(feature = "catch_unwind", since = "1.9.0")] impl<T> Deref for AssertUnwindSafe<T> { type Target = T; diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs index be9cd6a6888..de891ea8918 100644 --- a/src/libstd/primitive_docs.rs +++ b/src/libstd/primitive_docs.rs @@ -506,6 +506,9 @@ mod prim_f64 { } /// /// *[See also the `std::i8` module](i8/index.html).* /// +/// However, please note that examples are shared between primitive integer +/// types. So it's normal if you see usage of types like `i64` in there. +/// mod prim_i8 { } #[doc(primitive = "i16")] @@ -514,6 +517,9 @@ mod prim_i8 { } /// /// *[See also the `std::i16` module](i16/index.html).* /// +/// However, please note that examples are shared between primitive integer +/// types. So it's normal if you see usage of types like `i32` in there. +/// mod prim_i16 { } #[doc(primitive = "i32")] @@ -522,6 +528,9 @@ mod prim_i16 { } /// /// *[See also the `std::i32` module](i32/index.html).* /// +/// However, please note that examples are shared between primitive integer +/// types. So it's normal if you see usage of types like `i16` in there. +/// mod prim_i32 { } #[doc(primitive = "i64")] @@ -530,6 +539,9 @@ mod prim_i32 { } /// /// *[See also the `std::i64` module](i64/index.html).* /// +/// However, please note that examples are shared between primitive integer +/// types. So it's normal if you see usage of types like `i8` in there. +/// mod prim_i64 { } #[doc(primitive = "u8")] @@ -538,6 +550,9 @@ mod prim_i64 { } /// /// *[See also the `std::u8` module](u8/index.html).* /// +/// However, please note that examples are shared between primitive integer +/// types. So it's normal if you see usage of types like `u64` in there. +/// mod prim_u8 { } #[doc(primitive = "u16")] @@ -546,6 +561,9 @@ mod prim_u8 { } /// /// *[See also the `std::u16` module](u16/index.html).* /// +/// However, please note that examples are shared between primitive integer +/// types. So it's normal if you see usage of types like `u32` in there. +/// mod prim_u16 { } #[doc(primitive = "u32")] @@ -554,6 +572,9 @@ mod prim_u16 { } /// /// *[See also the `std::u32` module](u32/index.html).* /// +/// However, please note that examples are shared between primitive integer +/// types. So it's normal if you see usage of types like `u16` in there. +/// mod prim_u32 { } #[doc(primitive = "u64")] @@ -562,6 +583,9 @@ mod prim_u32 { } /// /// *[See also the `std::u64` module](u64/index.html).* /// +/// However, please note that examples are shared between primitive integer +/// types. So it's normal if you see usage of types like `u8` in there. +/// mod prim_u64 { } #[doc(primitive = "isize")] @@ -570,6 +594,9 @@ mod prim_u64 { } /// /// *[See also the `std::isize` module](isize/index.html).* /// +/// However, please note that examples are shared between primitive integer +/// types. So it's normal if you see usage of types like `usize` in there. +/// mod prim_isize { } #[doc(primitive = "usize")] @@ -578,4 +605,7 @@ mod prim_isize { } /// /// *[See also the `std::usize` module](usize/index.html).* /// +/// However, please note that examples are shared between primitive integer +/// types. So it's normal if you see usage of types like `isize` in there. +/// mod prim_usize { } diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 2edd1a30638..16bc81de78e 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -27,8 +27,9 @@ use sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; /// Representation of a running or exited child process. /// /// This structure is used to represent and manage child processes. A child -/// process is created via the `Command` struct, which configures the spawning -/// process and can itself be constructed using a builder-style interface. +/// process is created via the [`Command`] struct, which configures the +/// spawning process and can itself be constructed using a builder-style +/// interface. /// /// # Examples /// @@ -48,13 +49,18 @@ use sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; /// /// # Note /// -/// Take note that there is no implementation of -/// [`Drop`](../../core/ops/trait.Drop.html) for child processes, so if you -/// do not ensure the `Child` has exited then it will continue to run, even -/// after the `Child` handle to the child process has gone out of scope. +/// Take note that there is no implementation of [`Drop`] for child processes, +/// so if you do not ensure the `Child` has exited then it will continue to +/// run, even after the `Child` handle to the child process has gone out of +/// scope. /// -/// Calling `wait` (or other functions that wrap around it) will make the -/// parent process wait until the child has actually exited before continuing. +/// Calling [`wait`][`wait`] (or other functions that wrap around it) will make +/// the parent process wait until the child has actually exited before +/// continuing. +/// +/// [`Command`]: struct.Command.html +/// [`Drop`]: ../../core/ops/trait.Drop.html +/// [`wait`]: #method.wait #[stable(feature = "process", since = "1.0.0")] pub struct Child { handle: imp::Process, @@ -91,7 +97,11 @@ impl IntoInner<imp::Process> for Child { fn into_inner(self) -> imp::Process { self.handle } } -/// A handle to a child process's stdin +/// A handle to a child process's stdin. This struct is used in the [`stdin`] +/// field on [`Child`]. +/// +/// [`Child`]: struct.Child.html +/// [`stdin`]: struct.Child.html#structfield.stdin #[stable(feature = "process", since = "1.0.0")] pub struct ChildStdin { inner: AnonPipe @@ -122,7 +132,11 @@ impl FromInner<AnonPipe> for ChildStdin { } } -/// A handle to a child process's stdout +/// A handle to a child process's stdout. This struct is used in the [`stdout`] +/// field on [`Child`]. +/// +/// [`Child`]: struct.Child.html +/// [`stdout`]: struct.Child.html#structfield.stdout #[stable(feature = "process", since = "1.0.0")] pub struct ChildStdout { inner: AnonPipe @@ -152,7 +166,11 @@ impl FromInner<AnonPipe> for ChildStdout { } } -/// A handle to a child process's stderr +/// A handle to a child process's stderr. This struct is used in the [`stderr`] +/// field on [`Child`]. +/// +/// [`Child`]: struct.Child.html +/// [`stderr`]: struct.Child.html#structfield.stderr #[stable(feature = "process", since = "1.0.0")] pub struct ChildStderr { inner: AnonPipe diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs index bf4b119a0b6..3c52ebc72f2 100644 --- a/src/libstd/sync/condvar.rs +++ b/src/libstd/sync/condvar.rs @@ -15,7 +15,7 @@ use sync::{mutex, MutexGuard, PoisonError}; use sys_common::condvar as sys; use sys_common::mutex as sys_mutex; use sys_common::poison::{self, LockResult}; -use time::{Instant, Duration}; +use time::Duration; /// A type indicating whether a timed wait on a condition variable returned /// due to a time out or not. @@ -72,59 +72,19 @@ impl WaitTimeoutResult { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated)] -pub struct Condvar { inner: Box<StaticCondvar> } - -/// Statically allocated condition variables. -/// -/// This structure is identical to `Condvar` except that it is suitable for use -/// in static initializers for other structures. -/// -/// # Examples -/// -/// ``` -/// #![feature(static_condvar)] -/// -/// use std::sync::{StaticCondvar, CONDVAR_INIT}; -/// -/// static CVAR: StaticCondvar = CONDVAR_INIT; -/// ``` -#[unstable(feature = "static_condvar", - reason = "may be merged with Condvar in the future", - issue = "27717")] -#[rustc_deprecated(since = "1.10.0", - reason = "the lazy-static crate suffices for static sync \ - primitives and eventually this type shouldn't \ - be necessary as `Condvar::new` in a static should \ - suffice")] -pub struct StaticCondvar { - inner: sys::Condvar, +pub struct Condvar { + inner: Box<sys::Condvar>, mutex: AtomicUsize, } -/// Constant initializer for a statically allocated condition variable. -#[unstable(feature = "static_condvar", - reason = "may be merged with Condvar in the future", - issue = "27717")] -#[rustc_deprecated(since = "1.10.0", - reason = "the lazy-static crate suffices for static sync \ - primitives and eventually this type shouldn't \ - be necessary as `Condvar::new` in a static should \ - suffice")] -#[allow(deprecated)] -pub const CONDVAR_INIT: StaticCondvar = StaticCondvar::new(); - -#[allow(deprecated)] impl Condvar { /// Creates a new condition variable which is ready to be waited on and /// notified. #[stable(feature = "rust1", since = "1.0.0")] pub fn new() -> Condvar { Condvar { - inner: box StaticCondvar { - inner: sys::Condvar::new(), - mutex: AtomicUsize::new(0), - } + inner: box sys::Condvar::new(), + mutex: AtomicUsize::new(0), } } @@ -157,9 +117,16 @@ impl Condvar { #[stable(feature = "rust1", since = "1.0.0")] pub fn wait<'a, T>(&self, guard: MutexGuard<'a, T>) -> LockResult<MutexGuard<'a, T>> { - unsafe { - let me: &'static Condvar = &*(self as *const _); - me.inner.wait(guard) + let poisoned = unsafe { + let lock = mutex::guard_lock(&guard); + self.verify(lock); + self.inner.wait(lock); + mutex::guard_poison(&guard).get() + }; + if poisoned { + Err(PoisonError::new(guard)) + } else { + Ok(guard) } } @@ -206,9 +173,16 @@ impl Condvar { pub fn wait_timeout<'a, T>(&self, guard: MutexGuard<'a, T>, dur: Duration) -> LockResult<(MutexGuard<'a, T>, WaitTimeoutResult)> { - unsafe { - let me: &'static Condvar = &*(self as *const _); - me.inner.wait_timeout(guard, dur) + let (poisoned, result) = unsafe { + let lock = mutex::guard_lock(&guard); + self.verify(lock); + let success = self.inner.wait_timeout(lock, dur); + (mutex::guard_poison(&guard).get(), WaitTimeoutResult(!success)) + }; + if poisoned { + Err(PoisonError::new((guard, result))) + } else { + Ok((guard, result)) } } @@ -220,7 +194,9 @@ impl Condvar { /// /// To wake up all threads, see `notify_all()`. #[stable(feature = "rust1", since = "1.0.0")] - pub fn notify_one(&self) { unsafe { self.inner.inner.notify_one() } } + pub fn notify_one(&self) { + unsafe { self.inner.notify_one() } + } /// Wakes up all blocked threads on this condvar. /// @@ -230,169 +206,8 @@ impl Condvar { /// /// To wake up only one thread, see `notify_one()`. #[stable(feature = "rust1", since = "1.0.0")] - pub fn notify_all(&self) { unsafe { self.inner.inner.notify_all() } } -} - -#[stable(feature = "condvar_default", since = "1.9.0")] -impl Default for Condvar { - fn default() -> Condvar { - Condvar::new() - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated)] -impl Drop for Condvar { - fn drop(&mut self) { - unsafe { self.inner.inner.destroy() } - } -} - -#[rustc_deprecated(since = "1.10.0", - reason = "the lazy-static crate suffices for static sync \ - primitives and eventually this type shouldn't \ - be necessary as `Condvar::new` in a static should \ - suffice")] -#[unstable(feature = "static_condvar", - reason = "may be merged with Condvar in the future", - issue = "27717")] -#[allow(deprecated)] -impl StaticCondvar { - /// Creates a new condition variable - #[unstable(feature = "static_condvar", - reason = "may be merged with Condvar in the future", - issue = "27717")] - pub const fn new() -> StaticCondvar { - StaticCondvar { - inner: sys::Condvar::new(), - mutex: AtomicUsize::new(0), - } - } - - /// Blocks the current thread until this condition variable receives a - /// notification. - /// - /// See `Condvar::wait`. - #[unstable(feature = "static_condvar", - reason = "may be merged with Condvar in the future", - issue = "27717")] - pub fn wait<'a, T>(&'static self, guard: MutexGuard<'a, T>) - -> LockResult<MutexGuard<'a, T>> { - let poisoned = unsafe { - let lock = mutex::guard_lock(&guard); - self.verify(lock); - self.inner.wait(lock); - mutex::guard_poison(&guard).get() - }; - if poisoned { - Err(PoisonError::new(guard)) - } else { - Ok(guard) - } - } - - /// Waits on this condition variable for a notification, timing out after a - /// specified duration. - /// - /// See `Condvar::wait_timeout`. - #[unstable(feature = "static_condvar", - reason = "may be merged with Condvar in the future", - issue = "27717")] - pub fn wait_timeout<'a, T>(&'static self, - guard: MutexGuard<'a, T>, - timeout: Duration) - -> LockResult<(MutexGuard<'a, T>, WaitTimeoutResult)> { - let (poisoned, result) = unsafe { - let lock = mutex::guard_lock(&guard); - self.verify(lock); - let success = self.inner.wait_timeout(lock, timeout); - (mutex::guard_poison(&guard).get(), WaitTimeoutResult(!success)) - }; - if poisoned { - Err(PoisonError::new((guard, result))) - } else { - Ok((guard, result)) - } - } - - /// Waits on this condition variable for a notification, timing out after a - /// specified duration. - /// - /// The implementation will repeatedly wait while the duration has not - /// passed and the function returns `false`. - /// - /// See `Condvar::wait_timeout_with`. - #[unstable(feature = "static_condvar", - reason = "may be merged with Condvar in the future", - issue = "27717")] - pub fn wait_timeout_with<'a, T, F>(&'static self, - guard: MutexGuard<'a, T>, - dur: Duration, - mut f: F) - -> LockResult<(MutexGuard<'a, T>, WaitTimeoutResult)> - where F: FnMut(LockResult<&mut T>) -> bool { - // This could be made more efficient by pushing the implementation into - // sys::condvar - let start = Instant::now(); - let mut guard_result: LockResult<MutexGuard<'a, T>> = Ok(guard); - while !f(guard_result - .as_mut() - .map(|g| &mut **g) - .map_err(|e| PoisonError::new(&mut **e.get_mut()))) { - let consumed = start.elapsed(); - let guard = guard_result.unwrap_or_else(|e| e.into_inner()); - let (new_guard_result, timed_out) = if consumed > dur { - (Ok(guard), WaitTimeoutResult(true)) - } else { - match self.wait_timeout(guard, dur - consumed) { - Ok((new_guard, timed_out)) => (Ok(new_guard), timed_out), - Err(err) => { - let (new_guard, no_timeout) = err.into_inner(); - (Err(PoisonError::new(new_guard)), no_timeout) - } - } - }; - guard_result = new_guard_result; - if timed_out.timed_out() { - let result = f(guard_result - .as_mut() - .map(|g| &mut **g) - .map_err(|e| PoisonError::new(&mut **e.get_mut()))); - let result = WaitTimeoutResult(!result); - return poison::map_result(guard_result, |g| (g, result)); - } - } - - poison::map_result(guard_result, |g| (g, WaitTimeoutResult(false))) - } - - /// Wakes up one blocked thread on this condvar. - /// - /// See `Condvar::notify_one`. - #[unstable(feature = "static_condvar", - reason = "may be merged with Condvar in the future", - issue = "27717")] - pub fn notify_one(&'static self) { unsafe { self.inner.notify_one() } } - - /// Wakes up all blocked threads on this condvar. - /// - /// See `Condvar::notify_all`. - #[unstable(feature = "static_condvar", - reason = "may be merged with Condvar in the future", - issue = "27717")] - pub fn notify_all(&'static self) { unsafe { self.inner.notify_all() } } - - /// Deallocates all resources associated with this static condvar. - /// - /// This method is unsafe to call as there is no guarantee that there are no - /// active users of the condvar, and this also doesn't prevent any future - /// users of the condvar. This method is required to be called to not leak - /// memory on all platforms. - #[unstable(feature = "static_condvar", - reason = "may be merged with Condvar in the future", - issue = "27717")] - pub unsafe fn destroy(&'static self) { - self.inner.destroy() + pub fn notify_all(&self) { + unsafe { self.inner.notify_all() } } fn verify(&self, mutex: &sys_mutex::Mutex) { @@ -414,15 +229,26 @@ impl StaticCondvar { } } +#[stable(feature = "condvar_default", since = "1.9.0")] +impl Default for Condvar { + fn default() -> Condvar { + Condvar::new() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Drop for Condvar { + fn drop(&mut self) { + unsafe { self.inner.destroy() } + } +} + #[cfg(test)] -#[allow(deprecated)] mod tests { use prelude::v1::*; - use super::StaticCondvar; use sync::mpsc::channel; - use sync::{StaticMutex, Condvar, Mutex, Arc}; - use sync::atomic::{AtomicUsize, Ordering}; + use sync::{Condvar, Mutex, Arc}; use thread; use time::Duration; use u32; @@ -435,26 +261,19 @@ mod tests { } #[test] - fn static_smoke() { - static C: StaticCondvar = StaticCondvar::new(); - C.notify_one(); - C.notify_all(); - unsafe { C.destroy(); } - } - - #[test] fn notify_one() { - static C: StaticCondvar = StaticCondvar::new(); - static M: StaticMutex = StaticMutex::new(); + let m = Arc::new(Mutex::new(())); + let m2 = m.clone(); + let c = Arc::new(Condvar::new()); + let c2 = c.clone(); - let g = M.lock().unwrap(); + let g = m.lock().unwrap(); let _t = thread::spawn(move|| { - let _g = M.lock().unwrap(); - C.notify_one(); + let _g = m2.lock().unwrap(); + c2.notify_one(); }); - let g = C.wait(g).unwrap(); + let g = c.wait(g).unwrap(); drop(g); - unsafe { C.destroy(); M.destroy(); } } #[test] @@ -495,84 +314,41 @@ mod tests { #[test] fn wait_timeout_ms() { - static C: StaticCondvar = StaticCondvar::new(); - static M: StaticMutex = StaticMutex::new(); + let m = Arc::new(Mutex::new(())); + let m2 = m.clone(); + let c = Arc::new(Condvar::new()); + let c2 = c.clone(); - let g = M.lock().unwrap(); - let (g, _no_timeout) = C.wait_timeout(g, Duration::from_millis(1)).unwrap(); + let g = m.lock().unwrap(); + let (g, _no_timeout) = c.wait_timeout(g, Duration::from_millis(1)).unwrap(); // spurious wakeups mean this isn't necessarily true // assert!(!no_timeout); let _t = thread::spawn(move || { - let _g = M.lock().unwrap(); - C.notify_one(); + let _g = m2.lock().unwrap(); + c2.notify_one(); }); - let (g, timeout_res) = C.wait_timeout(g, Duration::from_millis(u32::MAX as u64)).unwrap(); + let (g, timeout_res) = c.wait_timeout(g, Duration::from_millis(u32::MAX as u64)).unwrap(); assert!(!timeout_res.timed_out()); drop(g); - unsafe { C.destroy(); M.destroy(); } - } - - #[test] - fn wait_timeout_with() { - static C: StaticCondvar = StaticCondvar::new(); - static M: StaticMutex = StaticMutex::new(); - static S: AtomicUsize = AtomicUsize::new(0); - - let g = M.lock().unwrap(); - let (g, timed_out) = C.wait_timeout_with(g, Duration::new(0, 1000), |_| { - false - }).unwrap(); - assert!(timed_out.timed_out()); - - let (tx, rx) = channel(); - let _t = thread::spawn(move || { - rx.recv().unwrap(); - let g = M.lock().unwrap(); - S.store(1, Ordering::SeqCst); - C.notify_one(); - drop(g); - - rx.recv().unwrap(); - let g = M.lock().unwrap(); - S.store(2, Ordering::SeqCst); - C.notify_one(); - drop(g); - - rx.recv().unwrap(); - let _g = M.lock().unwrap(); - S.store(3, Ordering::SeqCst); - C.notify_one(); - }); - - let mut state = 0; - let day = 24 * 60 * 60; - let (_g, timed_out) = C.wait_timeout_with(g, Duration::new(day, 0), |_| { - assert_eq!(state, S.load(Ordering::SeqCst)); - tx.send(()).unwrap(); - state += 1; - match state { - 1|2 => false, - _ => true, - } - }).unwrap(); - assert!(!timed_out.timed_out()); } #[test] #[should_panic] fn two_mutexes() { - static M1: StaticMutex = StaticMutex::new(); - static M2: StaticMutex = StaticMutex::new(); - static C: StaticCondvar = StaticCondvar::new(); + let m = Arc::new(Mutex::new(())); + let m2 = m.clone(); + let c = Arc::new(Condvar::new()); + let c2 = c.clone(); - let mut g = M1.lock().unwrap(); + let mut g = m.lock().unwrap(); let _t = thread::spawn(move|| { - let _g = M1.lock().unwrap(); - C.notify_one(); + let _g = m2.lock().unwrap(); + c2.notify_one(); }); - g = C.wait(g).unwrap(); + g = c.wait(g).unwrap(); drop(g); - let _ = C.wait(M2.lock().unwrap()).unwrap(); + let m = Mutex::new(()); + let _ = c.wait(m.lock().unwrap()).unwrap(); } } diff --git a/src/libstd/sync/mod.rs b/src/libstd/sync/mod.rs index 56eb7340c89..289b47b3484 100644 --- a/src/libstd/sync/mod.rs +++ b/src/libstd/sync/mod.rs @@ -25,23 +25,15 @@ pub use core::sync::atomic; #[stable(feature = "rust1", since = "1.0.0")] pub use self::barrier::{Barrier, BarrierWaitResult}; #[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated)] -pub use self::condvar::{Condvar, StaticCondvar, WaitTimeoutResult, CONDVAR_INIT}; +pub use self::condvar::{Condvar, WaitTimeoutResult}; #[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated)] -pub use self::mutex::MUTEX_INIT; -#[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated)] -pub use self::mutex::{Mutex, MutexGuard, StaticMutex}; +pub use self::mutex::{Mutex, MutexGuard}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::once::{Once, OnceState, ONCE_INIT}; #[stable(feature = "rust1", since = "1.0.0")] pub use sys_common::poison::{PoisonError, TryLockError, TryLockResult, LockResult}; #[stable(feature = "rust1", since = "1.0.0")] -pub use self::rwlock::{RwLockReadGuard, RwLockWriteGuard}; -#[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated)] -pub use self::rwlock::{RwLock, StaticRwLock, RW_LOCK_INIT}; +pub use self::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard}; pub mod mpsc; diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index 34bc210b3c8..d96fd6228e6 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -2181,6 +2181,15 @@ mod sync_tests { } #[test] + fn oneshot_single_thread_try_recv_closed_with_data() { + let (tx, rx) = sync_channel::<i32>(1); + tx.send(10).unwrap(); + drop(tx); + assert_eq!(rx.try_recv(), Ok(10)); + assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected)); + } + + #[test] fn oneshot_single_thread_peek_data() { let (tx, rx) = sync_channel::<i32>(1); assert_eq!(rx.try_recv(), Err(TryRecvError::Empty)); diff --git a/src/libstd/sync/mpsc/sync.rs b/src/libstd/sync/mpsc/sync.rs index f021689acad..9d13a71ff95 100644 --- a/src/libstd/sync/mpsc/sync.rs +++ b/src/libstd/sync/mpsc/sync.rs @@ -309,7 +309,7 @@ impl<T> Packet<T> { let mut guard = self.lock.lock().unwrap(); // Easy cases first - if guard.disconnected { return Err(Disconnected) } + if guard.disconnected && guard.buf.size() == 0 { return Err(Disconnected) } if guard.buf.size() == 0 { return Err(Empty) } // Be sure to wake up neighbors diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index c75a5c09146..6bc458397f1 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -113,14 +113,14 @@ use sys_common::poison::{self, TryLockError, TryLockResult, LockResult}; /// *guard += 1; /// ``` #[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated)] pub struct Mutex<T: ?Sized> { - // Note that this static mutex is in a *box*, not inlined into the struct - // itself. Once a native mutex has been used once, its address can never - // change (it can't be moved). This mutex type can be safely moved at any - // time, so to ensure that the native mutex is used correctly we box the - // inner lock to give it a constant address. - inner: Box<StaticMutex>, + // Note that this mutex is in a *box*, not inlined into the struct itself. + // Once a native mutex has been used once, its address can never change (it + // can't be moved). This mutex type can be safely moved at any time, so to + // ensure that the native mutex is used correctly we box the inner lock to + // give it a constant address. + inner: Box<sys::Mutex>, + poison: poison::Flag, data: UnsafeCell<T>, } @@ -131,42 +131,6 @@ unsafe impl<T: ?Sized + Send> Send for Mutex<T> { } #[stable(feature = "rust1", since = "1.0.0")] unsafe impl<T: ?Sized + Send> Sync for Mutex<T> { } -/// The static mutex type is provided to allow for static allocation of mutexes. -/// -/// Note that this is a separate type because using a Mutex correctly means that -/// it needs to have a destructor run. In Rust, statics are not allowed to have -/// destructors. As a result, a `StaticMutex` has one extra method when compared -/// to a `Mutex`, a `destroy` method. This method is unsafe to call, and -/// documentation can be found directly on the method. -/// -/// # Examples -/// -/// ``` -/// #![feature(static_mutex)] -/// -/// use std::sync::{StaticMutex, MUTEX_INIT}; -/// -/// static LOCK: StaticMutex = MUTEX_INIT; -/// -/// { -/// let _g = LOCK.lock().unwrap(); -/// // do some productive work -/// } -/// // lock is unlocked here. -/// ``` -#[unstable(feature = "static_mutex", - reason = "may be merged with Mutex in the future", - issue = "27717")] -#[rustc_deprecated(since = "1.10.0", - reason = "the lazy-static crate suffices for static sync \ - primitives and eventually this type shouldn't \ - be necessary as `Mutex::new` in a static should \ - suffice")] -pub struct StaticMutex { - lock: sys::Mutex, - poison: poison::Flag, -} - /// An RAII implementation of a "scoped lock" of a mutex. When this structure is /// dropped (falls out of scope), the lock will be unlocked. /// @@ -174,48 +138,32 @@ pub struct StaticMutex { /// `Deref` and `DerefMut` implementations #[must_use] #[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated)] pub struct MutexGuard<'a, T: ?Sized + 'a> { // funny underscores due to how Deref/DerefMut currently work (they // disregard field privacy). - __lock: &'a StaticMutex, - __data: &'a mut T, + __lock: &'a Mutex<T>, __poison: poison::Guard, } #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T: ?Sized> !marker::Send for MutexGuard<'a, T> {} -/// Static initialization of a mutex. This constant can be used to initialize -/// other mutex constants. -#[unstable(feature = "static_mutex", - reason = "may be merged with Mutex in the future", - issue = "27717")] -#[rustc_deprecated(since = "1.10.0", - reason = "the lazy-static crate suffices for static sync \ - primitives and eventually this type shouldn't \ - be necessary as `Mutex::new` in a static should \ - suffice")] -#[allow(deprecated)] -pub const MUTEX_INIT: StaticMutex = StaticMutex::new(); - -#[allow(deprecated)] impl<T> Mutex<T> { /// Creates a new mutex in an unlocked state ready for use. #[stable(feature = "rust1", since = "1.0.0")] pub fn new(t: T) -> Mutex<T> { let mut m = Mutex { - inner: box StaticMutex::new(), + inner: box sys::Mutex::new(), + poison: poison::Flag::new(), data: UnsafeCell::new(t), }; unsafe { - m.inner.lock.init(); + m.inner.init(); } m } } -#[allow(deprecated)] impl<T: ?Sized> Mutex<T> { /// Acquires a mutex, blocking the current thread until it is able to do so. /// @@ -240,8 +188,8 @@ impl<T: ?Sized> Mutex<T> { #[stable(feature = "rust1", since = "1.0.0")] pub fn lock(&self) -> LockResult<MutexGuard<T>> { unsafe { - self.inner.lock.lock(); - MutexGuard::new(&*self.inner, &self.data) + self.inner.lock(); + MutexGuard::new(self) } } @@ -261,8 +209,8 @@ impl<T: ?Sized> Mutex<T> { #[stable(feature = "rust1", since = "1.0.0")] pub fn try_lock(&self) -> TryLockResult<MutexGuard<T>> { unsafe { - if self.inner.lock.try_lock() { - Ok(MutexGuard::new(&*self.inner, &self.data)?) + if self.inner.try_lock() { + Ok(MutexGuard::new(self)?) } else { Err(TryLockError::WouldBlock) } @@ -277,7 +225,7 @@ impl<T: ?Sized> Mutex<T> { #[inline] #[stable(feature = "sync_poison", since = "1.2.0")] pub fn is_poisoned(&self) -> bool { - self.inner.poison.get() + self.poison.get() } /// Consumes this mutex, returning the underlying data. @@ -289,21 +237,22 @@ impl<T: ?Sized> Mutex<T> { #[stable(feature = "mutex_into_inner", since = "1.6.0")] pub fn into_inner(self) -> LockResult<T> where T: Sized { // We know statically that there are no outstanding references to - // `self` so there's no need to lock the inner StaticMutex. + // `self` so there's no need to lock the inner lock. // // To get the inner value, we'd like to call `data.into_inner()`, // but because `Mutex` impl-s `Drop`, we can't move out of it, so // we'll have to destructure it manually instead. unsafe { - // Like `let Mutex { inner, data } = self`. - let (inner, data) = { - let Mutex { ref inner, ref data } = self; - (ptr::read(inner), ptr::read(data)) + // Like `let Mutex { inner, poison, data } = self`. + let (inner, poison, data) = { + let Mutex { ref inner, ref poison, ref data } = self; + (ptr::read(inner), ptr::read(poison), ptr::read(data)) }; mem::forget(self); - inner.lock.destroy(); // Keep in sync with the `Drop` impl. + inner.destroy(); // Keep in sync with the `Drop` impl. + drop(inner); - poison::map_result(inner.poison.borrow(), |_| data.into_inner()) + poison::map_result(poison.borrow(), |_| data.into_inner()) } } @@ -319,14 +268,13 @@ impl<T: ?Sized> Mutex<T> { #[stable(feature = "mutex_get_mut", since = "1.6.0")] pub fn get_mut(&mut self) -> LockResult<&mut T> { // We know statically that there are no other references to `self`, so - // there's no need to lock the inner StaticMutex. + // there's no need to lock the inner lock. let data = unsafe { &mut *self.data.get() }; - poison::map_result(self.inner.poison.borrow(), |_| data ) + poison::map_result(self.poison.borrow(), |_| data ) } } #[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated)] impl<T: ?Sized> Drop for Mutex<T> { #[unsafe_destructor_blind_to_params] fn drop(&mut self) { @@ -335,7 +283,7 @@ impl<T: ?Sized> Drop for Mutex<T> { // dropped, that's not our job) // // IMPORTANT: This code must be kept in sync with `Mutex::into_inner`. - unsafe { self.inner.lock.destroy() } + unsafe { self.inner.destroy() } } } @@ -359,72 +307,11 @@ impl<T: ?Sized + fmt::Debug> fmt::Debug for Mutex<T> { } } -struct Dummy(UnsafeCell<()>); -unsafe impl Sync for Dummy {} -static DUMMY: Dummy = Dummy(UnsafeCell::new(())); - -#[unstable(feature = "static_mutex", - reason = "may be merged with Mutex in the future", - issue = "27717")] -#[rustc_deprecated(since = "1.10.0", - reason = "the lazy-static crate suffices for static sync \ - primitives and eventually this type shouldn't \ - be necessary as `Mutex::new` in a static should \ - suffice")] -#[allow(deprecated)] -impl StaticMutex { - /// Creates a new mutex in an unlocked state ready for use. - pub const fn new() -> StaticMutex { - StaticMutex { - lock: sys::Mutex::new(), - poison: poison::Flag::new(), - } - } - - /// Acquires this lock, see `Mutex::lock` - #[inline] - pub fn lock(&'static self) -> LockResult<MutexGuard<()>> { - unsafe { - self.lock.lock(); - MutexGuard::new(self, &DUMMY.0) - } - } - - /// Attempts to grab this lock, see `Mutex::try_lock` - #[inline] - pub fn try_lock(&'static self) -> TryLockResult<MutexGuard<()>> { - unsafe { - if self.lock.try_lock() { - Ok(MutexGuard::new(self, &DUMMY.0)?) - } else { - Err(TryLockError::WouldBlock) - } - } - } - - /// Deallocates resources associated with this static mutex. - /// - /// This method is unsafe because it provides no guarantees that there are - /// no active users of this mutex, and safety is not guaranteed if there are - /// active users of this mutex. - /// - /// This method is required to ensure that there are no memory leaks on - /// *all* platforms. It may be the case that some platforms do not leak - /// memory if this method is not called, but this is not guaranteed to be - /// true on all platforms. - pub unsafe fn destroy(&'static self) { - self.lock.destroy() - } -} - -#[allow(deprecated)] impl<'mutex, T: ?Sized> MutexGuard<'mutex, T> { - unsafe fn new(lock: &'mutex StaticMutex, data: &'mutex UnsafeCell<T>) - -> LockResult<MutexGuard<'mutex, T>> { + unsafe fn new(lock: &'mutex Mutex<T>) -> LockResult<MutexGuard<'mutex, T>> { poison::map_result(lock.poison.borrow(), |guard| { MutexGuard { __lock: lock, - __data: &mut *data.get(), __poison: guard, } }) @@ -435,43 +322,43 @@ impl<'mutex, T: ?Sized> MutexGuard<'mutex, T> { impl<'mutex, T: ?Sized> Deref for MutexGuard<'mutex, T> { type Target = T; - fn deref(&self) -> &T {self.__data } + fn deref(&self) -> &T { + unsafe { &*self.__lock.data.get() } + } } #[stable(feature = "rust1", since = "1.0.0")] impl<'mutex, T: ?Sized> DerefMut for MutexGuard<'mutex, T> { - fn deref_mut(&mut self) -> &mut T { self.__data } + fn deref_mut(&mut self) -> &mut T { + unsafe { &mut *self.__lock.data.get() } + } } #[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated)] impl<'a, T: ?Sized> Drop for MutexGuard<'a, T> { #[inline] fn drop(&mut self) { unsafe { self.__lock.poison.done(&self.__poison); - self.__lock.lock.unlock(); + self.__lock.inner.unlock(); } } } -#[allow(deprecated)] pub fn guard_lock<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a sys::Mutex { - &guard.__lock.lock + &guard.__lock.inner } -#[allow(deprecated)] pub fn guard_poison<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a poison::Flag { &guard.__lock.poison } #[cfg(test)] -#[allow(deprecated)] mod tests { use prelude::v1::*; use sync::mpsc::channel; - use sync::{Arc, Mutex, StaticMutex, Condvar}; + use sync::{Arc, Mutex, Condvar}; use sync::atomic::{AtomicUsize, Ordering}; use thread; @@ -491,47 +378,33 @@ mod tests { } #[test] - fn smoke_static() { - static M: StaticMutex = StaticMutex::new(); - unsafe { - drop(M.lock().unwrap()); - drop(M.lock().unwrap()); - M.destroy(); - } - } - - #[test] fn lots_and_lots() { - static M: StaticMutex = StaticMutex::new(); - static mut CNT: u32 = 0; const J: u32 = 1000; const K: u32 = 3; - fn inc() { + let m = Arc::new(Mutex::new(0)); + + fn inc(m: &Mutex<u32>) { for _ in 0..J { - unsafe { - let _g = M.lock().unwrap(); - CNT += 1; - } + *m.lock().unwrap() += 1; } } let (tx, rx) = channel(); for _ in 0..K { let tx2 = tx.clone(); - thread::spawn(move|| { inc(); tx2.send(()).unwrap(); }); + let m2 = m.clone(); + thread::spawn(move|| { inc(&m2); tx2.send(()).unwrap(); }); let tx2 = tx.clone(); - thread::spawn(move|| { inc(); tx2.send(()).unwrap(); }); + let m2 = m.clone(); + thread::spawn(move|| { inc(&m2); tx2.send(()).unwrap(); }); } drop(tx); for _ in 0..2 * K { rx.recv().unwrap(); } - assert_eq!(unsafe {CNT}, J * K * 2); - unsafe { - M.destroy(); - } + assert_eq!(*m.lock().unwrap(), J * K * 2); } #[test] diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index e9ea465cc99..54c1fe6c564 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -65,6 +65,7 @@ // it! use marker; +use ptr; use sync::atomic::{AtomicUsize, AtomicBool, Ordering}; use thread::{self, Thread}; @@ -297,7 +298,7 @@ impl Once { let mut node = Waiter { thread: Some(thread::current()), signaled: AtomicBool::new(false), - next: 0 as *mut Waiter, + next: ptr::null_mut(), }; let me = &mut node as *mut Waiter as usize; assert!(me & STATE_MASK == 0); diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index 03d3483902d..65b5686de86 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -66,9 +66,9 @@ use sys_common::rwlock as sys; /// } // write lock is dropped here /// ``` #[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated)] pub struct RwLock<T: ?Sized> { - inner: Box<StaticRwLock>, + inner: Box<sys::RWLock>, + poison: poison::Flag, data: UnsafeCell<T>, } @@ -77,64 +77,12 @@ unsafe impl<T: ?Sized + Send + Sync> Send for RwLock<T> {} #[stable(feature = "rust1", since = "1.0.0")] unsafe impl<T: ?Sized + Send + Sync> Sync for RwLock<T> {} -/// Structure representing a statically allocated RwLock. -/// -/// This structure is intended to be used inside of a `static` and will provide -/// automatic global access as well as lazy initialization. The internal -/// resources of this RwLock, however, must be manually deallocated. -/// -/// # Examples -/// -/// ``` -/// #![feature(static_rwlock)] -/// -/// use std::sync::{StaticRwLock, RW_LOCK_INIT}; -/// -/// static LOCK: StaticRwLock = RW_LOCK_INIT; -/// -/// { -/// let _g = LOCK.read().unwrap(); -/// // ... shared read access -/// } -/// { -/// let _g = LOCK.write().unwrap(); -/// // ... exclusive write access -/// } -/// unsafe { LOCK.destroy() } // free all resources -/// ``` -#[unstable(feature = "static_rwlock", - reason = "may be merged with RwLock in the future", - issue = "27717")] -#[rustc_deprecated(since = "1.10.0", - reason = "the lazy-static crate suffices for static sync \ - primitives and eventually this type shouldn't \ - be necessary as `RwLock::new` in a static should \ - suffice")] -pub struct StaticRwLock { - lock: sys::RWLock, - poison: poison::Flag, -} - -/// Constant initialization for a statically-initialized rwlock. -#[unstable(feature = "static_rwlock", - reason = "may be merged with RwLock in the future", - issue = "27717")] -#[rustc_deprecated(since = "1.10.0", - reason = "the lazy-static crate suffices for static sync \ - primitives and eventually this type shouldn't \ - be necessary as `RwLock::new` in a static should \ - suffice")] -#[allow(deprecated)] -pub const RW_LOCK_INIT: StaticRwLock = StaticRwLock::new(); - /// RAII structure used to release the shared read access of a lock when /// dropped. #[must_use] #[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated)] pub struct RwLockReadGuard<'a, T: ?Sized + 'a> { - __lock: &'a StaticRwLock, - __data: &'a T, + __lock: &'a RwLock<T>, } #[stable(feature = "rust1", since = "1.0.0")] @@ -144,17 +92,14 @@ impl<'a, T: ?Sized> !marker::Send for RwLockReadGuard<'a, T> {} /// dropped. #[must_use] #[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated)] pub struct RwLockWriteGuard<'a, T: ?Sized + 'a> { - __lock: &'a StaticRwLock, - __data: &'a mut T, + __lock: &'a RwLock<T>, __poison: poison::Guard, } #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T: ?Sized> !marker::Send for RwLockWriteGuard<'a, T> {} -#[allow(deprecated)] impl<T> RwLock<T> { /// Creates a new instance of an `RwLock<T>` which is unlocked. /// @@ -167,11 +112,14 @@ impl<T> RwLock<T> { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn new(t: T) -> RwLock<T> { - RwLock { inner: box StaticRwLock::new(), data: UnsafeCell::new(t) } + RwLock { + inner: box sys::RWLock::new(), + poison: poison::Flag::new(), + data: UnsafeCell::new(t), + } } } -#[allow(deprecated)] impl<T: ?Sized> RwLock<T> { /// Locks this rwlock with shared read access, blocking the current thread /// until it can be acquired. @@ -194,8 +142,8 @@ impl<T: ?Sized> RwLock<T> { #[stable(feature = "rust1", since = "1.0.0")] pub fn read(&self) -> LockResult<RwLockReadGuard<T>> { unsafe { - self.inner.lock.read(); - RwLockReadGuard::new(&*self.inner, &self.data) + self.inner.read(); + RwLockReadGuard::new(self) } } @@ -220,8 +168,8 @@ impl<T: ?Sized> RwLock<T> { #[stable(feature = "rust1", since = "1.0.0")] pub fn try_read(&self) -> TryLockResult<RwLockReadGuard<T>> { unsafe { - if self.inner.lock.try_read() { - Ok(RwLockReadGuard::new(&*self.inner, &self.data)?) + if self.inner.try_read() { + Ok(RwLockReadGuard::new(self)?) } else { Err(TryLockError::WouldBlock) } @@ -246,8 +194,8 @@ impl<T: ?Sized> RwLock<T> { #[stable(feature = "rust1", since = "1.0.0")] pub fn write(&self) -> LockResult<RwLockWriteGuard<T>> { unsafe { - self.inner.lock.write(); - RwLockWriteGuard::new(&*self.inner, &self.data) + self.inner.write(); + RwLockWriteGuard::new(self) } } @@ -272,8 +220,8 @@ impl<T: ?Sized> RwLock<T> { #[stable(feature = "rust1", since = "1.0.0")] pub fn try_write(&self) -> TryLockResult<RwLockWriteGuard<T>> { unsafe { - if self.inner.lock.try_write() { - Ok(RwLockWriteGuard::new(&*self.inner, &self.data)?) + if self.inner.try_write() { + Ok(RwLockWriteGuard::new(self)?) } else { Err(TryLockError::WouldBlock) } @@ -288,7 +236,7 @@ impl<T: ?Sized> RwLock<T> { #[inline] #[stable(feature = "sync_poison", since = "1.2.0")] pub fn is_poisoned(&self) -> bool { - self.inner.poison.get() + self.poison.get() } /// Consumes this `RwLock`, returning the underlying data. @@ -302,21 +250,22 @@ impl<T: ?Sized> RwLock<T> { #[stable(feature = "rwlock_into_inner", since = "1.6.0")] pub fn into_inner(self) -> LockResult<T> where T: Sized { // We know statically that there are no outstanding references to - // `self` so there's no need to lock the inner StaticRwLock. + // `self` so there's no need to lock the inner lock. // // To get the inner value, we'd like to call `data.into_inner()`, // but because `RwLock` impl-s `Drop`, we can't move out of it, so // we'll have to destructure it manually instead. unsafe { - // Like `let RwLock { inner, data } = self`. - let (inner, data) = { - let RwLock { ref inner, ref data } = self; - (ptr::read(inner), ptr::read(data)) + // Like `let RwLock { inner, poison, data } = self`. + let (inner, poison, data) = { + let RwLock { ref inner, ref poison, ref data } = self; + (ptr::read(inner), ptr::read(poison), ptr::read(data)) }; mem::forget(self); - inner.lock.destroy(); // Keep in sync with the `Drop` impl. + inner.destroy(); // Keep in sync with the `Drop` impl. + drop(inner); - poison::map_result(inner.poison.borrow(), |_| data.into_inner()) + poison::map_result(poison.borrow(), |_| data.into_inner()) } } @@ -334,19 +283,18 @@ impl<T: ?Sized> RwLock<T> { #[stable(feature = "rwlock_get_mut", since = "1.6.0")] pub fn get_mut(&mut self) -> LockResult<&mut T> { // We know statically that there are no other references to `self`, so - // there's no need to lock the inner StaticRwLock. + // there's no need to lock the inner lock. let data = unsafe { &mut *self.data.get() }; - poison::map_result(self.inner.poison.borrow(), |_| data ) + poison::map_result(self.poison.borrow(), |_| data) } } #[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated)] impl<T: ?Sized> Drop for RwLock<T> { #[unsafe_destructor_blind_to_params] fn drop(&mut self) { // IMPORTANT: This code needs to be kept in sync with `RwLock::into_inner`. - unsafe { self.inner.lock.destroy() } + unsafe { self.inner.destroy() } } } @@ -370,114 +318,23 @@ impl<T: Default> Default for RwLock<T> { } } -struct Dummy(UnsafeCell<()>); -unsafe impl Sync for Dummy {} -static DUMMY: Dummy = Dummy(UnsafeCell::new(())); - -#[unstable(feature = "static_rwlock", - reason = "may be merged with RwLock in the future", - issue = "27717")] -#[rustc_deprecated(since = "1.10.0", - reason = "the lazy-static crate suffices for static sync \ - primitives and eventually this type shouldn't \ - be necessary as `RwLock::new` in a static should \ - suffice")] -#[allow(deprecated)] -impl StaticRwLock { - /// Creates a new rwlock. - pub const fn new() -> StaticRwLock { - StaticRwLock { - lock: sys::RWLock::new(), - poison: poison::Flag::new(), - } - } - - /// Locks this rwlock with shared read access, blocking the current thread - /// until it can be acquired. - /// - /// See `RwLock::read`. - #[inline] - pub fn read(&'static self) -> LockResult<RwLockReadGuard<'static, ()>> { - unsafe { - self.lock.read(); - RwLockReadGuard::new(self, &DUMMY.0) - } - } - - /// Attempts to acquire this lock with shared read access. - /// - /// See `RwLock::try_read`. - #[inline] - pub fn try_read(&'static self) - -> TryLockResult<RwLockReadGuard<'static, ()>> { - unsafe { - if self.lock.try_read(){ - Ok(RwLockReadGuard::new(self, &DUMMY.0)?) - } else { - Err(TryLockError::WouldBlock) - } - } - } - - /// Locks this rwlock with exclusive write access, blocking the current - /// thread until it can be acquired. - /// - /// See `RwLock::write`. - #[inline] - pub fn write(&'static self) -> LockResult<RwLockWriteGuard<'static, ()>> { - unsafe { - self.lock.write(); - RwLockWriteGuard::new(self, &DUMMY.0) - } - } - - /// Attempts to lock this rwlock with exclusive write access. - /// - /// See `RwLock::try_write`. - #[inline] - pub fn try_write(&'static self) - -> TryLockResult<RwLockWriteGuard<'static, ()>> { - unsafe { - if self.lock.try_write() { - Ok(RwLockWriteGuard::new(self, &DUMMY.0)?) - } else { - Err(TryLockError::WouldBlock) - } - } - } - - /// Deallocates all resources associated with this static lock. - /// - /// This method is unsafe to call as there is no guarantee that there are no - /// active users of the lock, and this also doesn't prevent any future users - /// of this lock. This method is required to be called to not leak memory on - /// all platforms. - pub unsafe fn destroy(&'static self) { - self.lock.destroy() - } -} - -#[allow(deprecated)] impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> { - unsafe fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell<T>) - -> LockResult<RwLockReadGuard<'rwlock, T>> { + unsafe fn new(lock: &'rwlock RwLock<T>) + -> LockResult<RwLockReadGuard<'rwlock, T>> { poison::map_result(lock.poison.borrow(), |_| { RwLockReadGuard { __lock: lock, - __data: &*data.get(), } }) } } -#[allow(deprecated)] impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> { - unsafe fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell<T>) - -> LockResult<RwLockWriteGuard<'rwlock, T>> { + unsafe fn new(lock: &'rwlock RwLock<T>) + -> LockResult<RwLockWriteGuard<'rwlock, T>> { poison::map_result(lock.poison.borrow(), |guard| { RwLockWriteGuard { __lock: lock, - __data: &mut *data.get(), __poison: guard, } }) @@ -488,42 +345,43 @@ impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> { impl<'rwlock, T: ?Sized> Deref for RwLockReadGuard<'rwlock, T> { type Target = T; - fn deref(&self) -> &T { self.__data } + fn deref(&self) -> &T { + unsafe { &*self.__lock.data.get() } + } } #[stable(feature = "rust1", since = "1.0.0")] impl<'rwlock, T: ?Sized> Deref for RwLockWriteGuard<'rwlock, T> { type Target = T; - fn deref(&self) -> &T { self.__data } + fn deref(&self) -> &T { + unsafe { &*self.__lock.data.get() } + } } #[stable(feature = "rust1", since = "1.0.0")] impl<'rwlock, T: ?Sized> DerefMut for RwLockWriteGuard<'rwlock, T> { fn deref_mut(&mut self) -> &mut T { - self.__data + unsafe { &mut *self.__lock.data.get() } } } -#[allow(deprecated)] #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T: ?Sized> Drop for RwLockReadGuard<'a, T> { fn drop(&mut self) { - unsafe { self.__lock.lock.read_unlock(); } + unsafe { self.__lock.inner.read_unlock(); } } } -#[allow(deprecated)] #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T: ?Sized> Drop for RwLockWriteGuard<'a, T> { fn drop(&mut self) { self.__lock.poison.done(&self.__poison); - unsafe { self.__lock.lock.write_unlock(); } + unsafe { self.__lock.inner.write_unlock(); } } } #[cfg(test)] -#[allow(deprecated)] mod tests { #![allow(deprecated)] // rand @@ -532,7 +390,7 @@ mod tests { use rand::{self, Rng}; use sync::mpsc::channel; use thread; - use sync::{Arc, RwLock, StaticRwLock, TryLockError}; + use sync::{Arc, RwLock, TryLockError}; use sync::atomic::{AtomicUsize, Ordering}; #[derive(Eq, PartialEq, Debug)] @@ -548,31 +406,23 @@ mod tests { } #[test] - fn static_smoke() { - static R: StaticRwLock = StaticRwLock::new(); - drop(R.read().unwrap()); - drop(R.write().unwrap()); - drop((R.read().unwrap(), R.read().unwrap())); - drop(R.write().unwrap()); - unsafe { R.destroy(); } - } - - #[test] fn frob() { - static R: StaticRwLock = StaticRwLock::new(); const N: usize = 10; const M: usize = 1000; + let r = Arc::new(RwLock::new(())); + let (tx, rx) = channel::<()>(); for _ in 0..N { let tx = tx.clone(); - thread::spawn(move|| { + let r = r.clone(); + thread::spawn(move || { let mut rng = rand::thread_rng(); for _ in 0..M { if rng.gen_weighted_bool(N) { - drop(R.write().unwrap()); + drop(r.write().unwrap()); } else { - drop(R.read().unwrap()); + drop(r.read().unwrap()); } } drop(tx); @@ -580,7 +430,6 @@ mod tests { } drop(tx); let _ = rx.recv(); - unsafe { R.destroy(); } } #[test] diff --git a/src/libstd/sys/common/backtrace.rs b/src/libstd/sys/common/backtrace.rs index 6f185437e50..4c23ceb63f2 100644 --- a/src/libstd/sys/common/backtrace.rs +++ b/src/libstd/sys/common/backtrace.rs @@ -170,7 +170,9 @@ pub fn demangle(writer: &mut Write, s: &str) -> io::Result<()> { "$u20$", => b" ", "$u27$", => b"'", "$u5b$", => b"[", - "$u5d$", => b"]" + "$u5d$", => b"]", + "$u7b$", => b"{", + "$u7d$", => b"}" ) } else { let idx = match rest.find('$') { diff --git a/src/libstd/sys/common/net.rs b/src/libstd/sys/common/net.rs index 26925b12f93..442618c55b3 100644 --- a/src/libstd/sys/common/net.rs +++ b/src/libstd/sys/common/net.rs @@ -25,19 +25,23 @@ use time::Duration; #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "ios", target_os = "macos", - target_os = "openbsd", target_os = "netbsd"))] + target_os = "openbsd", target_os = "netbsd", + target_os = "solaris"))] use sys::net::netc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP; #[cfg(not(any(target_os = "dragonfly", target_os = "freebsd", target_os = "ios", target_os = "macos", - target_os = "openbsd", target_os = "netbsd")))] + target_os = "openbsd", target_os = "netbsd", + target_os = "solaris")))] use sys::net::netc::IPV6_ADD_MEMBERSHIP; #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "ios", target_os = "macos", - target_os = "openbsd", target_os = "netbsd"))] + target_os = "openbsd", target_os = "netbsd", + target_os = "solaris"))] use sys::net::netc::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP; #[cfg(not(any(target_os = "dragonfly", target_os = "freebsd", target_os = "ios", target_os = "macos", - target_os = "openbsd", target_os = "netbsd")))] + target_os = "openbsd", target_os = "netbsd", + target_os = "solaris")))] use sys::net::netc::IPV6_DROP_MEMBERSHIP; //////////////////////////////////////////////////////////////////////////////// @@ -601,3 +605,22 @@ impl fmt::Debug for UdpSocket { .finish() } } + +#[cfg(test)] +mod tests { + use prelude::v1::*; + + use super::*; + use collections::HashMap; + + #[test] + fn no_lookup_host_duplicates() { + let mut addrs = HashMap::new(); + let lh = match lookup_host("localhost") { + Ok(lh) => lh, + Err(e) => panic!("couldn't resolve `localhost': {}", e) + }; + let _na = lh.map(|sa| *addrs.entry(sa).or_insert(0) += 1).count(); + assert!(addrs.values().filter(|&&v| v > 1).count() == 0); + } +} diff --git a/src/libstd/sys/common/poison.rs b/src/libstd/sys/common/poison.rs index 83780a31cce..55212bf35d6 100644 --- a/src/libstd/sys/common/poison.rs +++ b/src/libstd/sys/common/poison.rs @@ -8,22 +8,28 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use cell::Cell; use error::{Error}; use fmt; use marker::Reflect; +use sync::atomic::{AtomicBool, Ordering}; use thread; -pub struct Flag { failed: Cell<bool> } +pub struct Flag { failed: AtomicBool } -// This flag is only ever accessed with a lock previously held. Note that this -// a totally private structure. -unsafe impl Send for Flag {} -unsafe impl Sync for Flag {} +// Note that the Ordering uses to access the `failed` field of `Flag` below is +// always `Relaxed`, and that's because this isn't actually protecting any data, +// it's just a flag whether we've panicked or not. +// +// The actual location that this matters is when a mutex is **locked** which is +// where we have external synchronization ensuring that we see memory +// reads/writes to this flag. +// +// As a result, if it matters, we should see the correct value for `failed` in +// all cases. impl Flag { pub const fn new() -> Flag { - Flag { failed: Cell::new(false) } + Flag { failed: AtomicBool::new(false) } } #[inline] @@ -39,13 +45,13 @@ impl Flag { #[inline] pub fn done(&self, guard: &Guard) { if !guard.panicking && thread::panicking() { - self.failed.set(true); + self.failed.store(true, Ordering::Relaxed); } } #[inline] pub fn get(&self) -> bool { - self.failed.get() + self.failed.load(Ordering::Relaxed) } } diff --git a/src/libstd/sys/common/wtf8.rs b/src/libstd/sys/common/wtf8.rs index b6be85a4dfa..2c1a656290f 100644 --- a/src/libstd/sys/common/wtf8.rs +++ b/src/libstd/sys/common/wtf8.rs @@ -566,7 +566,7 @@ impl Wtf8 { if len < 3 { return None } - match ::slice_pat(&&self.bytes[(len - 3)..]) { + match &self.bytes[(len - 3)..] { &[0xED, b2 @ 0xA0...0xAF, b3] => Some(decode_surrogate(b2, b3)), _ => None } @@ -578,7 +578,7 @@ impl Wtf8 { if len < 3 { return None } - match ::slice_pat(&&self.bytes[..3]) { + match &self.bytes[..3] { &[0xED, b2 @ 0xB0...0xBF, b3] => Some(decode_surrogate(b2, b3)), _ => None } diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 0524851df91..b315e676263 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -84,7 +84,7 @@ pub struct OpenOptions { #[derive(Clone, PartialEq, Eq, Debug)] pub struct FilePermissions { mode: mode_t } -#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub struct FileType { mode: mode_t } pub struct DirBuilder { mode: mode_t } @@ -205,9 +205,15 @@ impl Iterator for ReadDir { // of the thread safety, on Illumos the readdir(3C) function is safe to use // in threaded applications and it is generally preferred over the // readdir_r(3C) function. + super::os::set_errno(0); let entry_ptr = libc::readdir(self.dirp.0); if entry_ptr.is_null() { - return None + // NULL can mean either the end is reached or an error occurred. + // So we had to clear errno beforehand to check for an error now. + return match super::os::errno() { + 0 => None, + e => Some(Err(Error::from_raw_os_error(e))), + } } let name = (*entry_ptr).d_name.as_ptr(); diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index 21ce6b19ceb..63e13f0bb47 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -35,28 +35,37 @@ use vec; const TMPBUF_SZ: usize = 128; static ENV_LOCK: Mutex = Mutex::new(); + +extern { + #[cfg_attr(any(target_os = "linux", target_os = "emscripten"), + link_name = "__errno_location")] + #[cfg_attr(any(target_os = "bitrig", + target_os = "netbsd", + target_os = "openbsd", + target_os = "android", + target_env = "newlib"), + link_name = "__errno")] + #[cfg_attr(target_os = "solaris", link_name = "___errno")] + #[cfg_attr(any(target_os = "macos", + target_os = "ios", + target_os = "freebsd"), + link_name = "__error")] + fn errno_location() -> *mut c_int; +} + /// Returns the platform-specific value of errno #[cfg(not(target_os = "dragonfly"))] pub fn errno() -> i32 { - extern { - #[cfg_attr(any(target_os = "linux", target_os = "emscripten"), - link_name = "__errno_location")] - #[cfg_attr(any(target_os = "bitrig", - target_os = "netbsd", - target_os = "openbsd", - target_os = "android", - target_env = "newlib"), - link_name = "__errno")] - #[cfg_attr(target_os = "solaris", link_name = "___errno")] - #[cfg_attr(any(target_os = "macos", - target_os = "ios", - target_os = "freebsd"), - link_name = "__error")] - fn errno_location() -> *const c_int; + unsafe { + (*errno_location()) as i32 } +} +/// Sets the platform-specific value of errno +#[cfg(target_os = "solaris")] // only needed for readdir so far +pub fn set_errno(e: i32) { unsafe { - (*errno_location()) as i32 + *errno_location() = e as c_int } } @@ -227,11 +236,11 @@ pub fn current_exe() -> io::Result<PathBuf> { libc::KERN_PROC_ARGV]; let mib = mib.as_mut_ptr(); let mut argv_len = 0; - cvt(libc::sysctl(mib, 4, 0 as *mut _, &mut argv_len, - 0 as *mut _, 0))?; + cvt(libc::sysctl(mib, 4, ptr::null_mut(), &mut argv_len, + ptr::null_mut(), 0))?; let mut argv = Vec::<*const libc::c_char>::with_capacity(argv_len as usize); cvt(libc::sysctl(mib, 4, argv.as_mut_ptr() as *mut _, - &mut argv_len, 0 as *mut _, 0))?; + &mut argv_len, ptr::null_mut(), 0))?; argv.set_len(argv_len as usize); if argv[0].is_null() { return Err(io::Error::new(io::ErrorKind::Other, diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs index 2dde9c0e615..01059413338 100644 --- a/src/libstd/sys/unix/pipe.rs +++ b/src/libstd/sys/unix/pipe.rs @@ -14,6 +14,7 @@ use cmp; use io; use libc::{self, c_int}; use mem; +use ptr; use sys::cvt_r; use sys::fd::FileDesc; @@ -92,8 +93,8 @@ pub fn read2(p1: AnonPipe, let mut read: libc::fd_set = mem::zeroed(); libc::FD_SET(p1.raw(), &mut read); libc::FD_SET(p2.raw(), &mut read); - libc::select(max + 1, &mut read, 0 as *mut _, 0 as *mut _, - 0 as *mut _) + libc::select(max + 1, &mut read, ptr::null_mut(), ptr::null_mut(), + ptr::null_mut()) })?; // Read as much as we can from each pipe, ignoring EWOULDBLOCK or diff --git a/src/libstd/sys/unix/process.rs b/src/libstd/sys/unix/process.rs index 98cfdcdf110..d68867fb3d2 100644 --- a/src/libstd/sys/unix/process.rs +++ b/src/libstd/sys/unix/process.rs @@ -96,7 +96,7 @@ impl Command { let mut saw_nul = false; let program = os2c(program, &mut saw_nul); Command { - argv: vec![program.as_ptr(), 0 as *const _], + argv: vec![program.as_ptr(), ptr::null()], program: program, args: Vec::new(), env: None, @@ -117,7 +117,7 @@ impl Command { // pointer. let arg = os2c(arg, &mut self.saw_nul); self.argv[self.args.len() + 1] = arg.as_ptr(); - self.argv.push(0 as *const _); + self.argv.push(ptr::null()); // Also make sure we keep track of the owned value to schedule a // destructor for this memory. @@ -134,7 +134,7 @@ impl Command { envp.push(s.as_ptr()); map.insert(k, (envp.len() - 1, s)); } - envp.push(0 as *const _); + envp.push(ptr::null()); self.env = Some(map); self.envp = Some(envp); } @@ -158,7 +158,7 @@ impl Command { Entry::Vacant(e) => { let len = envp.len(); envp[len - 1] = new_key.as_ptr(); - envp.push(0 as *const _); + envp.push(ptr::null()); e.insert((len - 1, new_key)); } } @@ -183,7 +183,7 @@ impl Command { pub fn env_clear(&mut self) { self.env = Some(HashMap::new()); - self.envp = Some(vec![0 as *const _]); + self.envp = Some(vec![ptr::null()]); } pub fn cwd(&mut self, dir: &OsStr) { diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index 371319a93d2..1061ca87f64 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -12,7 +12,6 @@ use prelude::v1::*; use alloc::boxed::FnBox; use cmp; -#[cfg(not(any(target_env = "newlib", target_os = "solaris")))] use ffi::CStr; use io; use libc; diff --git a/src/libstd/sys/unix/time.rs b/src/libstd/sys/unix/time.rs index 68eebba9e7b..a08cec38f73 100644 --- a/src/libstd/sys/unix/time.rs +++ b/src/libstd/sys/unix/time.rs @@ -9,8 +9,8 @@ // except according to those terms. use cmp::Ordering; -use time::Duration; use libc; +use time::Duration; pub use self::inner::{Instant, SystemTime, UNIX_EPOCH}; @@ -164,12 +164,14 @@ mod inner { impl SystemTime { pub fn now() -> SystemTime { + use ptr; + let mut s = libc::timeval { tv_sec: 0, tv_usec: 0, }; cvt(unsafe { - libc::gettimeofday(&mut s, 0 as *mut _) + libc::gettimeofday(&mut s, ptr::null_mut()) }).unwrap(); return SystemTime::from(s) } diff --git a/src/libstd/sys/windows/backtrace.rs b/src/libstd/sys/windows/backtrace.rs index 0e10a8d8e8d..82a44c1c110 100644 --- a/src/libstd/sys/windows/backtrace.rs +++ b/src/libstd/sys/windows/backtrace.rs @@ -30,9 +30,9 @@ use io; use libc::c_void; use mem; use ptr; -use sync::StaticMutex; use sys::c; use sys::dynamic_lib::DynamicLibrary; +use sys::mutex::Mutex; macro_rules! sym { ($lib:expr, $e:expr, $t:ident) => ( @@ -101,53 +101,59 @@ impl Drop for Cleanup { pub fn write(w: &mut Write) -> io::Result<()> { // According to windows documentation, all dbghelp functions are // single-threaded. - static LOCK: StaticMutex = StaticMutex::new(); - let _g = LOCK.lock(); + static LOCK: Mutex = Mutex::new(); + unsafe { + LOCK.lock(); + let res = _write(w); + LOCK.unlock(); + return res + } +} +unsafe fn _write(w: &mut Write) -> io::Result<()> { let dbghelp = match DynamicLibrary::open("dbghelp.dll") { Ok(lib) => lib, Err(..) => return Ok(()), }; - unsafe { - // Fetch the symbols necessary from dbghelp.dll - let SymInitialize = sym!(dbghelp, "SymInitialize", SymInitializeFn); - let SymCleanup = sym!(dbghelp, "SymCleanup", SymCleanupFn); - let StackWalk64 = sym!(dbghelp, "StackWalk64", StackWalk64Fn); - - // Allocate necessary structures for doing the stack walk - let process = c::GetCurrentProcess(); - let thread = c::GetCurrentThread(); - let mut context: c::CONTEXT = mem::zeroed(); - c::RtlCaptureContext(&mut context); - let mut frame: c::STACKFRAME64 = mem::zeroed(); - let image = init_frame(&mut frame, &context); - - // Initialize this process's symbols - let ret = SymInitialize(process, ptr::null_mut(), c::TRUE); - if ret != c::TRUE { return Ok(()) } - let _c = Cleanup { handle: process, SymCleanup: SymCleanup }; - - // And now that we're done with all the setup, do the stack walking! - // Start from -1 to avoid printing this stack frame, which will - // always be exactly the same. - let mut i = -1; - write!(w, "stack backtrace:\n")?; - while StackWalk64(image, process, thread, &mut frame, &mut context, - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut()) == c::TRUE { - let addr = frame.AddrPC.Offset; - if addr == frame.AddrReturn.Offset || addr == 0 || - frame.AddrReturn.Offset == 0 { break } - - i += 1; - - if i >= 0 { - printing::print(w, i, addr - 1, process, &dbghelp)?; - } - } - Ok(()) + // Fetch the symbols necessary from dbghelp.dll + let SymInitialize = sym!(dbghelp, "SymInitialize", SymInitializeFn); + let SymCleanup = sym!(dbghelp, "SymCleanup", SymCleanupFn); + let StackWalk64 = sym!(dbghelp, "StackWalk64", StackWalk64Fn); + + // Allocate necessary structures for doing the stack walk + let process = c::GetCurrentProcess(); + let thread = c::GetCurrentThread(); + let mut context: c::CONTEXT = mem::zeroed(); + c::RtlCaptureContext(&mut context); + let mut frame: c::STACKFRAME64 = mem::zeroed(); + let image = init_frame(&mut frame, &context); + + // Initialize this process's symbols + let ret = SymInitialize(process, ptr::null_mut(), c::TRUE); + if ret != c::TRUE { return Ok(()) } + let _c = Cleanup { handle: process, SymCleanup: SymCleanup }; + + // And now that we're done with all the setup, do the stack walking! + // Start from -1 to avoid printing this stack frame, which will + // always be exactly the same. + let mut i = -1; + write!(w, "stack backtrace:\n")?; + while StackWalk64(image, process, thread, &mut frame, &mut context, + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut()) == c::TRUE { + let addr = frame.AddrPC.Offset; + if addr == frame.AddrReturn.Offset || addr == 0 || + frame.AddrReturn.Offset == 0 { break } + + i += 1; + + if i >= 0 { + printing::print(w, i, addr - 1, process, &dbghelp)?; + } } + + Ok(()) } diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index c243e890526..2683e57256d 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -38,7 +38,7 @@ pub struct FileAttr { reparse_tag: c::DWORD, } -#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub enum FileType { Dir, File, SymlinkFile, SymlinkDir, ReparsePoint, MountPoint, } @@ -117,7 +117,7 @@ impl Drop for FindNextFileHandle { impl DirEntry { fn new(root: &Arc<PathBuf>, wfd: &c::WIN32_FIND_DATAW) -> Option<DirEntry> { - match ::slice_pat(&&wfd.cFileName[0..3]) { + match &wfd.cFileName[0..3] { // check for '.' and '..' &[46, 0, ..] | &[46, 46, 0, ..] => return None, diff --git a/src/libstd/sys/windows/handle.rs b/src/libstd/sys/windows/handle.rs index 74546bb893b..d10abae2865 100644 --- a/src/libstd/sys/windows/handle.rs +++ b/src/libstd/sys/windows/handle.rs @@ -46,10 +46,10 @@ impl Handle { pub fn new_event(manual: bool, init: bool) -> io::Result<Handle> { unsafe { - let event = c::CreateEventW(0 as *mut _, + let event = c::CreateEventW(ptr::null_mut(), manual as c::BOOL, init as c::BOOL, - 0 as *const _); + ptr::null()); if event.is_null() { Err(io::Error::last_os_error()) } else { diff --git a/src/libstd/sys/windows/pipe.rs b/src/libstd/sys/windows/pipe.rs index 8631a63d653..6e9c67051a6 100644 --- a/src/libstd/sys/windows/pipe.rs +++ b/src/libstd/sys/windows/pipe.rs @@ -12,9 +12,10 @@ use prelude::v1::*; use os::windows::prelude::*; use ffi::OsStr; -use path::Path; use io; use mem; +use path::Path; +use ptr; use rand::{self, Rng}; use slice; use sys::c; @@ -66,7 +67,7 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> { 4096, 4096, 0, - 0 as *mut _); + ptr::null_mut()); // We pass the FILE_FLAG_FIRST_PIPE_INSTANCE flag above, and we're // also just doing a best effort at selecting a unique name. If |
