diff options
| author | Marcin Fatyga <marcinf@google.com> | 2016-11-01 15:26:22 +0100 |
|---|---|---|
| committer | Marcin Fatyga <marcinf@google.com> | 2016-11-01 15:26:22 +0100 |
| commit | 655effedf25e2039d283b839429bf2f42b7012a4 (patch) | |
| tree | 34fd087d891556c70a14b26a90d1bdccd0a7ccb2 /src/libcore | |
| parent | 4e2822c5c28bb342e5862ba7cc0b90b865c68be1 (diff) | |
| parent | ac968c466451cb9aafd9e8598ddb396ed0e6fe31 (diff) | |
Merge branch 'master' of https://github.com/rust-lang/rust
Conflicts: src/libcoretest/lib.rs
Diffstat (limited to 'src/libcore')
36 files changed, 1343 insertions, 699 deletions
diff --git a/src/libcore/any.rs b/src/libcore/any.rs index a3018a46eea..eb0636e8576 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -73,7 +73,6 @@ use fmt; use intrinsics; -use marker::Reflect; /////////////////////////////////////////////////////////////////////////////// // Any trait @@ -86,7 +85,7 @@ use marker::Reflect; /// /// [mod]: index.html #[stable(feature = "rust1", since = "1.0.0")] -pub trait Any: Reflect + 'static { +pub trait Any: 'static { /// Gets the `TypeId` of `self`. /// /// # Examples @@ -112,7 +111,7 @@ pub trait Any: Reflect + 'static { } #[stable(feature = "rust1", since = "1.0.0")] -impl<T: Reflect + 'static + ?Sized > Any for T { +impl<T: 'static + ?Sized > Any for T { fn get_type_id(&self) -> TypeId { TypeId::of::<T>() } } @@ -352,12 +351,10 @@ impl TypeId { /// # Examples /// /// ``` - /// #![feature(get_type_id)] - /// /// use std::any::{Any, TypeId}; /// - /// fn is_string(s: &Any) -> bool { - /// TypeId::of::<String>() == s.get_type_id() + /// fn is_string<T: ?Sized + Any>(_s: &T) -> bool { + /// TypeId::of::<String>() == TypeId::of::<T>() /// } /// /// fn main() { @@ -366,7 +363,7 @@ impl TypeId { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn of<T: ?Sized + Reflect + 'static>() -> TypeId { + pub fn of<T: ?Sized + 'static>() -> TypeId { TypeId { t: unsafe { intrinsics::type_id::<T>() }, } diff --git a/src/libcore/array.rs b/src/libcore/array.rs index 9866a39619a..37bd57034a7 100644 --- a/src/libcore/array.rs +++ b/src/libcore/array.rs @@ -93,6 +93,7 @@ macro_rules! __impl_slice_eq2 { macro_rules! array_impls { ($($N:expr)+) => { $( + #[stable(feature = "rust1", since = "1.0.0")] impl<T> AsRef<[T]> for [T; $N] { #[inline] fn as_ref(&self) -> &[T] { @@ -100,6 +101,7 @@ macro_rules! array_impls { } } + #[stable(feature = "rust1", since = "1.0.0")] impl<T> AsMut<[T]> for [T; $N] { #[inline] fn as_mut(&mut self) -> &mut [T] { diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 51221f1b9b9..64a7a8c5ef7 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -175,7 +175,7 @@ use cmp::Ordering; use fmt::{self, Debug, Display}; -use marker::{PhantomData, Unsize}; +use marker::Unsize; use ops::{Deref, DerefMut, CoerceUnsized}; /// A mutable memory location that admits only `Copy` data. @@ -403,40 +403,40 @@ pub enum BorrowState { } /// An error returned by [`RefCell::try_borrow`](struct.RefCell.html#method.try_borrow). -#[unstable(feature = "try_borrow", issue = "35070")] -pub struct BorrowError<'a, T: 'a + ?Sized> { - marker: PhantomData<&'a RefCell<T>>, +#[stable(feature = "try_borrow", since = "1.13.0")] +pub struct BorrowError { + _private: (), } -#[unstable(feature = "try_borrow", issue = "35070")] -impl<'a, T: ?Sized> Debug for BorrowError<'a, T> { +#[stable(feature = "try_borrow", since = "1.13.0")] +impl Debug for BorrowError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("BorrowError").finish() } } -#[unstable(feature = "try_borrow", issue = "35070")] -impl<'a, T: ?Sized> Display for BorrowError<'a, T> { +#[stable(feature = "try_borrow", since = "1.13.0")] +impl Display for BorrowError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Display::fmt("already mutably borrowed", f) } } /// An error returned by [`RefCell::try_borrow_mut`](struct.RefCell.html#method.try_borrow_mut). -#[unstable(feature = "try_borrow", issue = "35070")] -pub struct BorrowMutError<'a, T: 'a + ?Sized> { - marker: PhantomData<&'a RefCell<T>>, +#[stable(feature = "try_borrow", since = "1.13.0")] +pub struct BorrowMutError { + _private: (), } -#[unstable(feature = "try_borrow", issue = "35070")] -impl<'a, T: ?Sized> Debug for BorrowMutError<'a, T> { +#[stable(feature = "try_borrow", since = "1.13.0")] +impl Debug for BorrowMutError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("BorrowMutError").finish() } } -#[unstable(feature = "try_borrow", issue = "35070")] -impl<'a, T: ?Sized> Display for BorrowMutError<'a, T> { +#[stable(feature = "try_borrow", since = "1.13.0")] +impl Display for BorrowMutError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Display::fmt("already borrowed", f) } @@ -573,8 +573,6 @@ impl<T: ?Sized> RefCell<T> { /// # Examples /// /// ``` - /// #![feature(try_borrow)] - /// /// use std::cell::RefCell; /// /// let c = RefCell::new(5); @@ -589,15 +587,15 @@ impl<T: ?Sized> RefCell<T> { /// assert!(c.try_borrow().is_ok()); /// } /// ``` - #[unstable(feature = "try_borrow", issue = "35070")] + #[stable(feature = "try_borrow", since = "1.13.0")] #[inline] - pub fn try_borrow(&self) -> Result<Ref<T>, BorrowError<T>> { + pub fn try_borrow(&self) -> Result<Ref<T>, BorrowError> { match BorrowRef::new(&self.borrow) { Some(b) => Ok(Ref { value: unsafe { &*self.value.get() }, borrow: b, }), - None => Err(BorrowError { marker: PhantomData }), + None => Err(BorrowError { _private: () }), } } @@ -654,8 +652,6 @@ impl<T: ?Sized> RefCell<T> { /// # Examples /// /// ``` - /// #![feature(try_borrow)] - /// /// use std::cell::RefCell; /// /// let c = RefCell::new(5); @@ -667,15 +663,15 @@ impl<T: ?Sized> RefCell<T> { /// /// assert!(c.try_borrow_mut().is_ok()); /// ``` - #[unstable(feature = "try_borrow", issue = "35070")] + #[stable(feature = "try_borrow", since = "1.13.0")] #[inline] - pub fn try_borrow_mut(&self) -> Result<RefMut<T>, BorrowMutError<T>> { + pub fn try_borrow_mut(&self) -> Result<RefMut<T>, BorrowMutError> { match BorrowRefMut::new(&self.borrow) { Some(b) => Ok(RefMut { value: unsafe { &mut *self.value.get() }, borrow: b, }), - None => Err(BorrowMutError { marker: PhantomData }), + None => Err(BorrowMutError { _private: () }), } } diff --git a/src/libcore/char.rs b/src/libcore/char.rs index ad492c81bd3..26d28049a47 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -18,6 +18,7 @@ use char_private::is_printable; use convert::TryFrom; use fmt; +use slice; use iter::FusedIterator; use mem::transmute; @@ -327,9 +328,9 @@ pub trait CharExt { #[stable(feature = "core", since = "1.6.0")] fn len_utf16(self) -> usize; #[unstable(feature = "unicode", issue = "27784")] - fn encode_utf8(self) -> EncodeUtf8; + fn encode_utf8(self, dst: &mut [u8]) -> &mut str; #[unstable(feature = "unicode", issue = "27784")] - fn encode_utf16(self) -> EncodeUtf16; + fn encode_utf16(self, dst: &mut [u16]) -> &mut [u16]; } #[stable(feature = "core", since = "1.6.0")] @@ -419,47 +420,59 @@ impl CharExt for char { } #[inline] - fn encode_utf8(self) -> EncodeUtf8 { + fn encode_utf8(self, dst: &mut [u8]) -> &mut str { let code = self as u32; - let mut buf = [0; 4]; - let pos = if code < MAX_ONE_B { - buf[3] = code as u8; - 3 - } else if code < MAX_TWO_B { - buf[2] = (code >> 6 & 0x1F) as u8 | TAG_TWO_B; - buf[3] = (code & 0x3F) as u8 | TAG_CONT; - 2 - } else if code < MAX_THREE_B { - buf[1] = (code >> 12 & 0x0F) as u8 | TAG_THREE_B; - buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT; - buf[3] = (code & 0x3F) as u8 | TAG_CONT; - 1 - } else { - buf[0] = (code >> 18 & 0x07) as u8 | TAG_FOUR_B; - buf[1] = (code >> 12 & 0x3F) as u8 | TAG_CONT; - buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT; - buf[3] = (code & 0x3F) as u8 | TAG_CONT; - 0 - }; - EncodeUtf8 { buf: buf, pos: pos } + unsafe { + let len = + if code < MAX_ONE_B && !dst.is_empty() { + *dst.get_unchecked_mut(0) = code as u8; + 1 + } else if code < MAX_TWO_B && dst.len() >= 2 { + *dst.get_unchecked_mut(0) = (code >> 6 & 0x1F) as u8 | TAG_TWO_B; + *dst.get_unchecked_mut(1) = (code & 0x3F) as u8 | TAG_CONT; + 2 + } else if code < MAX_THREE_B && dst.len() >= 3 { + *dst.get_unchecked_mut(0) = (code >> 12 & 0x0F) as u8 | TAG_THREE_B; + *dst.get_unchecked_mut(1) = (code >> 6 & 0x3F) as u8 | TAG_CONT; + *dst.get_unchecked_mut(2) = (code & 0x3F) as u8 | TAG_CONT; + 3 + } else if dst.len() >= 4 { + *dst.get_unchecked_mut(0) = (code >> 18 & 0x07) as u8 | TAG_FOUR_B; + *dst.get_unchecked_mut(1) = (code >> 12 & 0x3F) as u8 | TAG_CONT; + *dst.get_unchecked_mut(2) = (code >> 6 & 0x3F) as u8 | TAG_CONT; + *dst.get_unchecked_mut(3) = (code & 0x3F) as u8 | TAG_CONT; + 4 + } else { + panic!("encode_utf8: need {} bytes to encode U+{:X}, but the buffer has {}", + from_u32_unchecked(code).len_utf8(), + code, + dst.len()) + }; + transmute(slice::from_raw_parts_mut(dst.as_mut_ptr(), len)) + } } #[inline] - fn encode_utf16(self) -> EncodeUtf16 { - let mut buf = [0; 2]; + fn encode_utf16(self, dst: &mut [u16]) -> &mut [u16] { let mut code = self as u32; - let pos = if (code & 0xFFFF) == code { - // The BMP falls through (assuming non-surrogate, as it should) - buf[1] = code as u16; - 1 - } else { - // Supplementary planes break into surrogates. - code -= 0x1_0000; - buf[0] = 0xD800 | ((code >> 10) as u16); - buf[1] = 0xDC00 | ((code as u16) & 0x3FF); - 0 - }; - EncodeUtf16 { buf: buf, pos: pos } + unsafe { + if (code & 0xFFFF) == code && !dst.is_empty() { + // The BMP falls through (assuming non-surrogate, as it should) + *dst.get_unchecked_mut(0) = code as u16; + slice::from_raw_parts_mut(dst.as_mut_ptr(), 1) + } else if dst.len() >= 2 { + // Supplementary planes break into surrogates. + code -= 0x1_0000; + *dst.get_unchecked_mut(0) = 0xD800 | ((code >> 10) as u16); + *dst.get_unchecked_mut(1) = 0xDC00 | ((code as u16) & 0x3FF); + slice::from_raw_parts_mut(dst.as_mut_ptr(), 2) + } else { + panic!("encode_utf16: need {} units to encode U+{:X}, but the buffer has {}", + from_u32_unchecked(code).len_utf16(), + code, + dst.len()) + } + } } } @@ -702,88 +715,7 @@ impl ExactSizeIterator for EscapeDebug { } #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for EscapeDebug {} -/// An iterator over `u8` entries represending the UTF-8 encoding of a `char` -/// value. -/// -/// Constructed via the `.encode_utf8()` method on `char`. -#[unstable(feature = "unicode", issue = "27784")] -#[derive(Debug)] -pub struct EncodeUtf8 { - buf: [u8; 4], - pos: usize, -} - -impl EncodeUtf8 { - /// Returns the remaining bytes of this iterator as a slice. - #[unstable(feature = "unicode", issue = "27784")] - pub fn as_slice(&self) -> &[u8] { - &self.buf[self.pos..] - } -} - -#[unstable(feature = "unicode", issue = "27784")] -impl Iterator for EncodeUtf8 { - type Item = u8; - - fn next(&mut self) -> Option<u8> { - if self.pos == self.buf.len() { - None - } else { - let ret = Some(self.buf[self.pos]); - self.pos += 1; - ret - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - self.as_slice().iter().size_hint() - } -} - -#[unstable(feature = "fused", issue = "35602")] -impl FusedIterator for EncodeUtf8 {} - -/// An iterator over `u16` entries represending the UTF-16 encoding of a `char` -/// value. -/// -/// Constructed via the `.encode_utf16()` method on `char`. -#[unstable(feature = "unicode", issue = "27784")] -#[derive(Debug)] -pub struct EncodeUtf16 { - buf: [u16; 2], - pos: usize, -} - -impl EncodeUtf16 { - /// Returns the remaining bytes of this iterator as a slice. - #[unstable(feature = "unicode", issue = "27784")] - pub fn as_slice(&self) -> &[u16] { - &self.buf[self.pos..] - } -} - - -#[unstable(feature = "unicode", issue = "27784")] -impl Iterator for EncodeUtf16 { - type Item = u16; - - fn next(&mut self) -> Option<u16> { - if self.pos == self.buf.len() { - None - } else { - let ret = Some(self.buf[self.pos]); - self.pos += 1; - ret - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - self.as_slice().iter().size_hint() - } -} -#[unstable(feature = "fused", issue = "35602")] -impl FusedIterator for EncodeUtf16 {} /// An iterator over an iterator of bytes of the characters the bytes represent /// as UTF-8 @@ -800,7 +732,7 @@ pub fn decode_utf8<I: IntoIterator<Item = u8>>(i: I) -> DecodeUtf8<I::IntoIter> /// `<DecodeUtf8 as Iterator>::next` returns this for an invalid input sequence. #[unstable(feature = "decode_utf8", issue = "33906")] -#[derive(PartialEq, Debug)] +#[derive(PartialEq, Eq, Debug)] pub struct InvalidSequence(()); #[unstable(feature = "decode_utf8", issue = "33906")] diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index 0b800cacfc1..d72b18ae345 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -129,13 +129,6 @@ pub struct AssertParamIsClone<T: Clone + ?Sized> { _field: ::marker::PhantomData reason = "deriving hack, should not be public", issue = "0")] pub struct AssertParamIsCopy<T: Copy + ?Sized> { _field: ::marker::PhantomData<T> } -#[cfg(stage0)] -#[doc(hidden)] -#[inline(always)] -#[unstable(feature = "derive_clone_copy", - reason = "deriving hack, should not be public", - issue = "0")] -pub fn assert_receiver_is_clone<T: Clone + ?Sized>(_: &T) {} #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T: ?Sized> Clone for &'a T { diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 31920fcb0f8..0daf658a0f4 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -10,10 +10,13 @@ //! Functionality for ordering and comparison. //! -//! This module defines both `PartialOrd` and `PartialEq` traits which are used +//! This module defines both [`PartialOrd`] and [`PartialEq`] traits which are used //! by the compiler to implement comparison operators. Rust programs may -//! implement `PartialOrd` to overload the `<`, `<=`, `>`, and `>=` operators, -//! and may implement `PartialEq` to overload the `==` and `!=` operators. +//! implement [`PartialOrd`] to overload the `<`, `<=`, `>`, and `>=` operators, +//! and may implement [`PartialEq`] to overload the `==` and `!=` operators. +//! +//! [`PartialOrd`]: trait.PartialOrd.html +//! [`PartialEq`]: trait.PartialEq.html //! //! # Examples //! @@ -777,24 +780,24 @@ mod impls { ord_impl! { char usize u8 u16 u32 u64 isize i8 i16 i32 i64 } - #[unstable(feature = "never_type", issue = "35121")] + #[unstable(feature = "never_type_impls", issue = "35121")] impl PartialEq for ! { fn eq(&self, _: &!) -> bool { *self } } - #[unstable(feature = "never_type", issue = "35121")] + #[unstable(feature = "never_type_impls", issue = "35121")] impl Eq for ! {} - #[unstable(feature = "never_type", issue = "35121")] + #[unstable(feature = "never_type_impls", issue = "35121")] impl PartialOrd for ! { fn partial_cmp(&self, _: &!) -> Option<Ordering> { *self } } - #[unstable(feature = "never_type", issue = "35121")] + #[unstable(feature = "never_type_impls", issue = "35121")] impl Ord for ! { fn cmp(&self, _: &!) -> Ordering { *self diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index 5191cd76010..5f16a4f2435 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -92,6 +92,22 @@ pub trait AsRef<T: ?Sized> { /// [`Option<T>`]: ../../std/option/enum.Option.html /// [`Result<T, E>`]: ../../std/result/enum.Result.html /// +/// # Examples +/// +/// [`Box<T>`] implements `AsMut<T>`: +/// +/// [`Box<T>`]: ../../std/boxed/struct.Box.html +/// +/// ``` +/// fn add_one<T: AsMut<u64>>(num: &mut T) { +/// *num.as_mut() += 1; +/// } +/// +/// let mut boxed_num = Box::new(0); +/// add_one(&mut boxed_num); +/// assert_eq!(*boxed_num, 1); +/// ``` +/// /// # Generic Impls /// /// - `AsMut` auto-dereferences if the inner type is a reference or a mutable diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 66ef92928eb..2d75a8ec420 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -97,9 +97,7 @@ pub trait Write { /// This function will return an instance of `Error` on error. #[stable(feature = "fmt_write_char", since = "1.1.0")] fn write_char(&mut self, c: char) -> Result { - self.write_str(unsafe { - str::from_utf8_unchecked(c.encode_utf8().as_slice()) - }) + self.write_str(c.encode_utf8(&mut [0; 4])) } /// Glue for usage of the `write!` macro with implementors of this trait. @@ -272,10 +270,14 @@ impl<'a> Arguments<'a> { /// safely be done so, so no constructors are given and the fields are private /// to prevent modification. /// -/// The `format_args!` macro will safely create an instance of this structure +/// The [`format_args!`] macro will safely create an instance of this structure /// and pass it to a function or closure, passed as the first argument. The -/// macro validates the format string at compile-time so usage of the `write` -/// and `format` functions can be safely performed. +/// macro validates the format string at compile-time so usage of the [`write`] +/// and [`format`] functions can be safely performed. +/// +/// [`format_args!`]: ../../std/macro.format_args.html +/// [`format`]: ../../std/fmt/fn.format.html +/// [`write`]: ../../std/fmt/fn.write.html #[stable(feature = "rust1", since = "1.0.0")] #[derive(Copy, Clone)] pub struct Arguments<'a> { @@ -792,7 +794,7 @@ pub trait UpperExp { /// assert_eq!(output, "Hello world!"); /// ``` /// -/// Please note that using [`write!`][write_macro] might be preferrable. Example: +/// Please note that using [`write!`] might be preferrable. Example: /// /// ``` /// use std::fmt::Write; @@ -803,7 +805,7 @@ pub trait UpperExp { /// assert_eq!(output, "Hello world!"); /// ``` /// -/// [write_macro]: ../../std/macro.write!.html +/// [`write!`]: ../../std/macro.write.html #[stable(feature = "rust1", since = "1.0.0")] pub fn write(output: &mut Write, args: Arguments) -> Result { let mut formatter = Formatter { @@ -920,9 +922,7 @@ impl<'a> Formatter<'a> { // Writes the sign if it exists, and then the prefix if it was requested let write_prefix = |f: &mut Formatter| { if let Some(c) = sign { - f.buf.write_str(unsafe { - str::from_utf8_unchecked(c.encode_utf8().as_slice()) - })?; + f.buf.write_str(c.encode_utf8(&mut [0; 4]))?; } if prefixed { f.buf.write_str(prefix) } else { Ok(()) } @@ -1028,10 +1028,8 @@ impl<'a> Formatter<'a> { rt::v1::Alignment::Center => (padding / 2, (padding + 1) / 2), }; - let fill = self.fill.encode_utf8(); - let fill = unsafe { - str::from_utf8_unchecked(fill.as_slice()) - }; + let mut fill = [0; 4]; + let fill = self.fill.encode_utf8(&mut fill); for _ in 0..pre_pad { self.buf.write_str(fill)?; @@ -1358,14 +1356,14 @@ macro_rules! fmt_refs { fmt_refs! { Debug, Display, Octal, Binary, LowerHex, UpperHex, LowerExp, UpperExp } -#[unstable(feature = "never_type", issue = "35121")] +#[unstable(feature = "never_type_impls", issue = "35121")] impl Debug for ! { fn fmt(&self, _: &mut Formatter) -> Result { *self } } -#[unstable(feature = "never_type", issue = "35121")] +#[unstable(feature = "never_type_impls", issue = "35121")] impl Display for ! { fn fmt(&self, _: &mut Formatter) -> Result { *self @@ -1431,9 +1429,7 @@ impl Display for char { if f.width.is_none() && f.precision.is_none() { f.write_char(*self) } else { - f.pad(unsafe { - str::from_utf8_unchecked(self.encode_utf8().as_slice()) - }) + f.pad(self.encode_utf8(&mut [0; 4])) } } } @@ -1570,11 +1566,11 @@ floating! { f64 } // Implementation of Display/Debug for various core types #[stable(feature = "rust1", since = "1.0.0")] -impl<T> Debug for *const T { +impl<T: ?Sized> Debug for *const T { fn fmt(&self, f: &mut Formatter) -> Result { Pointer::fmt(self, f) } } #[stable(feature = "rust1", since = "1.0.0")] -impl<T> Debug for *mut T { +impl<T: ?Sized> Debug for *mut T { fn fmt(&self, f: &mut Formatter) -> Result { Pointer::fmt(self, f) } } diff --git a/src/libcore/fmt/rt/v1.rs b/src/libcore/fmt/rt/v1.rs index 6b31e040622..ec7add9c375 100644 --- a/src/libcore/fmt/rt/v1.rs +++ b/src/libcore/fmt/rt/v1.rs @@ -31,7 +31,7 @@ pub struct FormatSpec { } /// Possible alignments that can be requested as part of a formatting directive. -#[derive(Copy, Clone, PartialEq)] +#[derive(Copy, Clone, PartialEq, Eq)] pub enum Alignment { /// Indication that contents should be left-aligned. Left, diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index 081f0c14ec3..ac36cbaace7 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -38,7 +38,9 @@ //! ``` //! //! If you need more control over how a value is hashed, you need to implement -//! the `Hash` trait: +//! the [`Hash`] trait: +//! +//! [`Hash`]: trait.Hash.html //! //! ```rust //! use std::hash::{Hash, Hasher, SipHasher}; @@ -76,9 +78,11 @@ use marker; use mem; #[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] pub use self::sip::SipHasher; #[unstable(feature = "sip_hash_13", issue = "29754")] +#[allow(deprecated)] pub use self::sip::{SipHasher13, SipHasher24}; mod sip; @@ -88,7 +92,7 @@ mod sip; /// The `H` type parameter is an abstract hash state that is used by the `Hash` /// to compute the hash. /// -/// If you are also implementing `Eq`, there is an additional property that +/// If you are also implementing [`Eq`], there is an additional property that /// is important: /// /// ```text @@ -96,13 +100,13 @@ mod sip; /// ``` /// /// In other words, if two keys are equal, their hashes should also be equal. -/// `HashMap` and `HashSet` both rely on this behavior. +/// [`HashMap`] and [`HashSet`] both rely on this behavior. /// /// ## Derivable /// /// This trait can be used with `#[derive]` if all fields implement `Hash`. /// When `derive`d, the resulting hash will be the combination of the values -/// from calling `.hash()` on each field. +/// from calling [`.hash()`] on each field. /// /// ## How can I implement `Hash`? /// @@ -125,6 +129,11 @@ mod sip; /// } /// } /// ``` +/// +/// [`Eq`]: ../../std/cmp/trait.Eq.html +/// [`HashMap`]: ../../std/collections/struct.HashMap.html +/// [`HashSet`]: ../../std/collections/struct.HashSet.html +/// [`.hash()`]: #tymethod.hash #[stable(feature = "rust1", since = "1.0.0")] pub trait Hash { /// Feeds this value into the state given, updating the hasher as necessary. @@ -149,35 +158,35 @@ pub trait Hasher { #[stable(feature = "rust1", since = "1.0.0")] fn finish(&self) -> u64; - /// Writes some data into this `Hasher` + /// Writes some data into this `Hasher`. #[stable(feature = "rust1", since = "1.0.0")] fn write(&mut self, bytes: &[u8]); - /// Write a single `u8` into this hasher + /// Write a single `u8` into this hasher. #[inline] #[stable(feature = "hasher_write", since = "1.3.0")] fn write_u8(&mut self, i: u8) { self.write(&[i]) } - /// Write a single `u16` into this hasher. + /// Writes a single `u16` into this hasher. #[inline] #[stable(feature = "hasher_write", since = "1.3.0")] fn write_u16(&mut self, i: u16) { self.write(&unsafe { mem::transmute::<_, [u8; 2]>(i) }) } - /// Write a single `u32` into this hasher. + /// Writes a single `u32` into this hasher. #[inline] #[stable(feature = "hasher_write", since = "1.3.0")] fn write_u32(&mut self, i: u32) { self.write(&unsafe { mem::transmute::<_, [u8; 4]>(i) }) } - /// Write a single `u64` into this hasher. + /// Writes a single `u64` into this hasher. #[inline] #[stable(feature = "hasher_write", since = "1.3.0")] fn write_u64(&mut self, i: u64) { self.write(&unsafe { mem::transmute::<_, [u8; 8]>(i) }) } - /// Write a single `usize` into this hasher. + /// Writes a single `usize` into this hasher. #[inline] #[stable(feature = "hasher_write", since = "1.3.0")] fn write_usize(&mut self, i: usize) { @@ -187,31 +196,31 @@ pub trait Hasher { self.write(bytes); } - /// Write a single `i8` into this hasher. + /// Writes a single `i8` into this hasher. #[inline] #[stable(feature = "hasher_write", since = "1.3.0")] fn write_i8(&mut self, i: i8) { self.write_u8(i as u8) } - /// Write a single `i16` into this hasher. + /// Writes a single `i16` into this hasher. #[inline] #[stable(feature = "hasher_write", since = "1.3.0")] fn write_i16(&mut self, i: i16) { self.write_u16(i as u16) } - /// Write a single `i32` into this hasher. + /// Writes a single `i32` into this hasher. #[inline] #[stable(feature = "hasher_write", since = "1.3.0")] fn write_i32(&mut self, i: i32) { self.write_u32(i as u32) } - /// Write a single `i64` into this hasher. + /// Writes a single `i64` into this hasher. #[inline] #[stable(feature = "hasher_write", since = "1.3.0")] fn write_i64(&mut self, i: i64) { self.write_u64(i as u64) } - /// Write a single `isize` into this hasher. + /// Writes a single `isize` into this hasher. #[inline] #[stable(feature = "hasher_write", since = "1.3.0")] fn write_isize(&mut self, i: isize) { diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs index dc53683d633..6b3ab64dfd8 100644 --- a/src/libcore/hash/sip.rs +++ b/src/libcore/hash/sip.rs @@ -10,13 +10,21 @@ //! An implementation of SipHash. +#![allow(deprecated)] + use marker::PhantomData; use ptr; +use cmp; +use mem; /// An implementation of SipHash 1-3. /// +/// This is currently the default hashing function used by standard library +/// (eg. `collections::HashMap` uses it by default). +/// /// See: https://131002.net/siphash/ #[unstable(feature = "sip_hash_13", issue = "34767")] +#[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")] #[derive(Debug, Clone, Default)] pub struct SipHasher13 { hasher: Hasher<Sip13Rounds>, @@ -26,6 +34,7 @@ pub struct SipHasher13 { /// /// See: https://131002.net/siphash/ #[unstable(feature = "sip_hash_13", issue = "34767")] +#[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")] #[derive(Debug, Clone, Default)] pub struct SipHasher24 { hasher: Hasher<Sip24Rounds>, @@ -35,9 +44,6 @@ pub struct SipHasher24 { /// /// See: https://131002.net/siphash/ /// -/// This is currently the default hashing function used by standard library -/// (eg. `collections::HashMap` uses it by default). -/// /// SipHash is a general-purpose hashing function: it runs at a good /// speed (competitive with Spooky and City) and permits strong _keyed_ /// hashing. This lets you key your hashtables from a strong RNG, such as @@ -47,6 +53,7 @@ pub struct SipHasher24 { /// it is not intended for cryptographic purposes. As such, all /// cryptographic uses of this implementation are _strongly discouraged_. #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")] #[derive(Debug, Clone, Default)] pub struct SipHasher(SipHasher24); @@ -73,69 +80,67 @@ struct State { v3: u64, } -// sadly, these macro definitions can't appear later, -// because they're needed in the following defs; -// this design could be improved. - -macro_rules! u8to64_le { - ($buf:expr, $i:expr) => - ($buf[0+$i] as u64 | - ($buf[1+$i] as u64) << 8 | - ($buf[2+$i] as u64) << 16 | - ($buf[3+$i] as u64) << 24 | - ($buf[4+$i] as u64) << 32 | - ($buf[5+$i] as u64) << 40 | - ($buf[6+$i] as u64) << 48 | - ($buf[7+$i] as u64) << 56); - ($buf:expr, $i:expr, $len:expr) => +macro_rules! compress { + ($state:expr) => ({ + compress!($state.v0, $state.v1, $state.v2, $state.v3) + }); + ($v0:expr, $v1:expr, $v2:expr, $v3:expr) => ({ - let mut t = 0; - let mut out = 0; - while t < $len { - out |= ($buf[t+$i] as u64) << t*8; - t += 1; - } - out + $v0 = $v0.wrapping_add($v1); $v1 = $v1.rotate_left(13); $v1 ^= $v0; + $v0 = $v0.rotate_left(32); + $v2 = $v2.wrapping_add($v3); $v3 = $v3.rotate_left(16); $v3 ^= $v2; + $v0 = $v0.wrapping_add($v3); $v3 = $v3.rotate_left(21); $v3 ^= $v0; + $v2 = $v2.wrapping_add($v1); $v1 = $v1.rotate_left(17); $v1 ^= $v2; + $v2 = $v2.rotate_left(32); }); } -/// Load a full u64 word from a byte stream, in LE order. Use +/// Load an integer of the desired type from a byte stream, in LE order. Uses /// `copy_nonoverlapping` to let the compiler generate the most efficient way -/// to load u64 from a possibly unaligned address. +/// to load it from a possibly unaligned address. /// -/// Unsafe because: unchecked indexing at i..i+8 -#[inline] -unsafe fn load_u64_le(buf: &[u8], i: usize) -> u64 { - debug_assert!(i + 8 <= buf.len()); - let mut data = 0u64; - ptr::copy_nonoverlapping(buf.get_unchecked(i), &mut data as *mut _ as *mut u8, 8); - data.to_le() -} - -macro_rules! rotl { - ($x:expr, $b:expr) => - (($x << $b) | ($x >> (64_i32.wrapping_sub($b)))) -} - -macro_rules! compress { - ($state:expr) => ({ - compress!($state.v0, $state.v1, $state.v2, $state.v3) - }); - ($v0:expr, $v1:expr, $v2:expr, $v3:expr) => +/// Unsafe because: unchecked indexing at i..i+size_of(int_ty) +macro_rules! load_int_le { + ($buf:expr, $i:expr, $int_ty:ident) => ({ - $v0 = $v0.wrapping_add($v1); $v1 = rotl!($v1, 13); $v1 ^= $v0; - $v0 = rotl!($v0, 32); - $v2 = $v2.wrapping_add($v3); $v3 = rotl!($v3, 16); $v3 ^= $v2; - $v0 = $v0.wrapping_add($v3); $v3 = rotl!($v3, 21); $v3 ^= $v0; - $v2 = $v2.wrapping_add($v1); $v1 = rotl!($v1, 17); $v1 ^= $v2; - $v2 = rotl!($v2, 32); + debug_assert!($i + mem::size_of::<$int_ty>() <= $buf.len()); + let mut data = 0 as $int_ty; + ptr::copy_nonoverlapping($buf.get_unchecked($i), + &mut data as *mut _ as *mut u8, + mem::size_of::<$int_ty>()); + data.to_le() }); } +/// Load an u64 using up to 7 bytes of a byte slice. +/// +/// Unsafe because: unchecked indexing at start..start+len +#[inline] +unsafe fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 { + debug_assert!(len < 8); + let mut i = 0; // current byte index (from LSB) in the output u64 + let mut out = 0; + if i + 3 < len { + out = load_int_le!(buf, start + i, u32) as u64; + i += 4; + } + if i + 1 < len { + out |= (load_int_le!(buf, start + i, u16) as u64) << (i * 8); + i += 2 + } + if i < len { + out |= (*buf.get_unchecked(start + i) as u64) << (i * 8); + i += 1; + } + debug_assert_eq!(i, len); + out +} + impl SipHasher { /// Creates a new `SipHasher` with the two initial keys set to 0. #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")] pub fn new() -> SipHasher { SipHasher::new_with_keys(0, 0) } @@ -143,16 +148,17 @@ impl SipHasher { /// Creates a `SipHasher` that is keyed off the provided keys. #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")] pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher { SipHasher(SipHasher24::new_with_keys(key0, key1)) } } - impl SipHasher13 { /// Creates a new `SipHasher13` with the two initial keys set to 0. #[inline] #[unstable(feature = "sip_hash_13", issue = "34767")] + #[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")] pub fn new() -> SipHasher13 { SipHasher13::new_with_keys(0, 0) } @@ -160,6 +166,7 @@ impl SipHasher13 { /// Creates a `SipHasher13` that is keyed off the provided keys. #[inline] #[unstable(feature = "sip_hash_13", issue = "34767")] + #[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")] pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher13 { SipHasher13 { hasher: Hasher::new_with_keys(key0, key1) @@ -171,6 +178,7 @@ impl SipHasher24 { /// Creates a new `SipHasher24` with the two initial keys set to 0. #[inline] #[unstable(feature = "sip_hash_13", issue = "34767")] + #[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")] pub fn new() -> SipHasher24 { SipHasher24::new_with_keys(0, 0) } @@ -178,6 +186,7 @@ impl SipHasher24 { /// Creates a `SipHasher24` that is keyed off the provided keys. #[inline] #[unstable(feature = "sip_hash_13", issue = "34767")] + #[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")] pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher24 { SipHasher24 { hasher: Hasher::new_with_keys(key0, key1) @@ -215,6 +224,37 @@ impl<S: Sip> Hasher<S> { self.state.v3 = self.k1 ^ 0x7465646279746573; self.ntail = 0; } + + // Specialized write function that is only valid for buffers with len <= 8. + // It's used to force inlining of write_u8 and write_usize, those would normally be inlined + // except for composite types (that includes slices and str hashing because of delimiter). + // Without this extra push the compiler is very reluctant to inline delimiter writes, + // degrading performance substantially for the most common use cases. + #[inline(always)] + fn short_write(&mut self, msg: &[u8]) { + debug_assert!(msg.len() <= 8); + let length = msg.len(); + self.length += length; + + let needed = 8 - self.ntail; + let fill = cmp::min(length, needed); + if fill == 8 { + self.tail = unsafe { load_int_le!(msg, 0, u64) }; + } else { + self.tail |= unsafe { u8to64_le(msg, 0, fill) } << (8 * self.ntail); + if length < needed { + self.ntail += length; + return; + } + } + self.state.v3 ^= self.tail; + S::c_rounds(&mut self.state); + self.state.v0 ^= self.tail; + + // Buffered tail is now flushed, process new input. + self.ntail = length - needed; + self.tail = unsafe { u8to64_le(msg, needed, self.ntail) }; + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -257,6 +297,21 @@ impl super::Hasher for SipHasher24 { } impl<S: Sip> super::Hasher for Hasher<S> { + // see short_write comment for explanation + #[inline] + fn write_usize(&mut self, i: usize) { + let bytes = unsafe { + ::slice::from_raw_parts(&i as *const usize as *const u8, mem::size_of::<usize>()) + }; + self.short_write(bytes); + } + + // see short_write comment for explanation + #[inline] + fn write_u8(&mut self, i: u8) { + self.short_write(&[i]); + } + #[inline] fn write(&mut self, msg: &[u8]) { let length = msg.len(); @@ -266,19 +321,16 @@ impl<S: Sip> super::Hasher for Hasher<S> { if self.ntail != 0 { needed = 8 - self.ntail; + self.tail |= unsafe { u8to64_le(msg, 0, cmp::min(length, needed)) } << 8 * self.ntail; if length < needed { - self.tail |= u8to64_le!(msg, 0, length) << 8 * self.ntail; self.ntail += length; return + } else { + self.state.v3 ^= self.tail; + S::c_rounds(&mut self.state); + self.state.v0 ^= self.tail; + self.ntail = 0; } - - let m = self.tail | u8to64_le!(msg, 0, needed) << 8 * self.ntail; - - self.state.v3 ^= m; - S::c_rounds(&mut self.state); - self.state.v0 ^= m; - - self.ntail = 0; } // Buffered tail is now flushed, process new input. @@ -287,7 +339,7 @@ impl<S: Sip> super::Hasher for Hasher<S> { let mut i = needed; while i < len - left { - let mi = unsafe { load_u64_le(msg, i) }; + let mi = unsafe { load_int_le!(msg, i, u64) }; self.state.v3 ^= mi; S::c_rounds(&mut self.state); @@ -296,7 +348,7 @@ impl<S: Sip> super::Hasher for Hasher<S> { i += 8; } - self.tail = u8to64_le!(msg, i, left); + self.tail = unsafe { u8to64_le(msg, i, left) }; self.ntail = left; } diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 22abe7a99b1..e844a158484 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -194,14 +194,12 @@ extern "rust-intrinsic" { /// own, or if it does not enable any significant optimizations. pub fn assume(b: bool); - #[cfg(not(stage0))] /// Hints to the compiler that branch condition is likely to be true. /// Returns the value passed to it. /// /// Any use other than with `if` statements will probably not have an effect. pub fn likely(b: bool) -> bool; - #[cfg(not(stage0))] /// Hints to the compiler that branch condition is likely to be false. /// Returns the value passed to it. /// @@ -596,6 +594,19 @@ extern "rust-intrinsic" { /// Invokes memset on the specified pointer, setting `count * size_of::<T>()` /// bytes of memory starting at `dst` to `val`. + /// + /// # Examples + /// + /// ``` + /// use std::ptr; + /// + /// let mut vec = vec![0; 4]; + /// unsafe { + /// let vec_ptr = vec.as_mut_ptr(); + /// ptr::write_bytes(vec_ptr, b'a', 2); + /// } + /// assert_eq!(vec, [b'a', b'a', 0, 0]); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn write_bytes<T>(dst: *mut T, val: u8, count: usize); diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 0e74bbe9c26..5a12f5db19d 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -195,13 +195,9 @@ pub trait Iterator { last } - /// Consumes the `n` first elements of the iterator, then returns the - /// `next()` one. + /// Returns the `n`th element of the iterator. /// - /// This method will evaluate the iterator `n` times, discarding those elements. - /// After it does so, it will call [`next()`] and return its value. - /// - /// [`next()`]: #tymethod.next + /// Note that all preceding elements will be consumed (i.e. discarded). /// /// Like most indexing operations, the count starts from zero, so `nth(0)` /// returns the first value, `nth(1)` the second, and so on. diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index b1d3ab1d1fe..df4f5e5c576 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -386,7 +386,7 @@ pub struct Cloned<I> { it: I, } -#[stable(feature = "rust1", since = "1.0.0")] +#[stable(feature = "iter_cloned", since = "1.1.0")] impl<'a, I, T: 'a> Iterator for Cloned<I> where I: Iterator<Item=&'a T>, T: Clone { @@ -399,9 +399,15 @@ impl<'a, I, T: 'a> Iterator for Cloned<I> fn size_hint(&self) -> (usize, Option<usize>) { self.it.size_hint() } + + fn fold<Acc, F>(self, init: Acc, mut f: F) -> Acc + where F: FnMut(Acc, Self::Item) -> Acc, + { + self.it.fold(init, move |acc, elt| f(acc, elt.clone())) + } } -#[stable(feature = "rust1", since = "1.0.0")] +#[stable(feature = "iter_cloned", since = "1.1.0")] impl<'a, I, T: 'a> DoubleEndedIterator for Cloned<I> where I: DoubleEndedIterator<Item=&'a T>, T: Clone { @@ -410,7 +416,7 @@ impl<'a, I, T: 'a> DoubleEndedIterator for Cloned<I> } } -#[stable(feature = "rust1", since = "1.0.0")] +#[stable(feature = "iter_cloned", since = "1.1.0")] impl<'a, I, T: 'a> ExactSizeIterator for Cloned<I> where I: ExactSizeIterator<Item=&'a T>, T: Clone {} @@ -420,6 +426,18 @@ impl<'a, I, T: 'a> FusedIterator for Cloned<I> where I: FusedIterator<Item=&'a T>, T: Clone {} +#[doc(hidden)] +unsafe impl<'a, I, T: 'a> TrustedRandomAccess for Cloned<I> + where I: TrustedRandomAccess<Item=&'a T>, T: Clone +{ + unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item { + self.it.get_unchecked(i).clone() + } + + #[inline] + fn may_have_side_effect() -> bool { true } +} + /// An iterator that repeats endlessly. /// /// This `struct` is created by the [`cycle()`] method on [`Iterator`]. See its @@ -532,6 +550,25 @@ impl<A, B> Iterator for Chain<A, B> where } } + fn fold<Acc, F>(self, init: Acc, mut f: F) -> Acc + where F: FnMut(Acc, Self::Item) -> Acc, + { + let mut accum = init; + match self.state { + ChainState::Both | ChainState::Front => { + accum = self.a.fold(accum, &mut f); + } + _ => { } + } + match self.state { + ChainState::Both | ChainState::Back => { + accum = self.b.fold(accum, &mut f); + } + _ => { } + } + accum + } + #[inline] fn nth(&mut self, mut n: usize) -> Option<A::Item> { match self.state { @@ -643,7 +680,9 @@ impl<A, B> FusedIterator for Chain<A, B> pub struct Zip<A, B> { a: A, b: B, - spec: <(A, B) as ZipImplData>::Data, + // index and len are only used by the specialized version of zip + index: usize, + len: usize, } #[stable(feature = "rust1", since = "1.0.0")] @@ -685,17 +724,6 @@ trait ZipImpl<A, B> { B: DoubleEndedIterator + ExactSizeIterator; } -// Zip specialization data members -#[doc(hidden)] -trait ZipImplData { - type Data: 'static + Clone + Default + fmt::Debug; -} - -#[doc(hidden)] -impl<T> ZipImplData for T { - default type Data = (); -} - // General Zip impl #[doc(hidden)] impl<A, B> ZipImpl<A, B> for Zip<A, B> @@ -706,7 +734,8 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B> Zip { a: a, b: b, - spec: Default::default(), // unused + index: 0, // unused + len: 0, // unused } } @@ -760,20 +789,6 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B> } #[doc(hidden)] -#[derive(Default, Debug, Clone)] -struct ZipImplFields { - index: usize, - len: usize, -} - -#[doc(hidden)] -impl<A, B> ZipImplData for (A, B) - where A: TrustedRandomAccess, B: TrustedRandomAccess -{ - type Data = ZipImplFields; -} - -#[doc(hidden)] impl<A, B> ZipImpl<A, B> for Zip<A, B> where A: TrustedRandomAccess, B: TrustedRandomAccess { @@ -782,21 +797,26 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B> Zip { a: a, b: b, - spec: ZipImplFields { - index: 0, - len: len, - } + index: 0, + len: len, } } #[inline] fn next(&mut self) -> Option<(A::Item, B::Item)> { - if self.spec.index < self.spec.len { - let i = self.spec.index; - self.spec.index += 1; + if self.index < self.len { + let i = self.index; + self.index += 1; unsafe { Some((self.a.get_unchecked(i), self.b.get_unchecked(i))) } + } else if A::may_have_side_effect() && self.index < self.a.len() { + // match the base implementation's potential side effects + unsafe { + self.a.get_unchecked(self.index); + } + self.index += 1; + None } else { None } @@ -804,7 +824,7 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B> #[inline] fn size_hint(&self) -> (usize, Option<usize>) { - let len = self.spec.len - self.spec.index; + let len = self.len - self.index; (len, Some(len)) } @@ -813,9 +833,26 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B> where A: DoubleEndedIterator + ExactSizeIterator, B: DoubleEndedIterator + ExactSizeIterator { - if self.spec.index < self.spec.len { - self.spec.len -= 1; - let i = self.spec.len; + // Adjust a, b to equal length + if A::may_have_side_effect() { + let sz = self.a.len(); + if sz > self.len { + for _ in 0..sz - cmp::max(self.len, self.index) { + self.a.next_back(); + } + } + } + if B::may_have_side_effect() { + let sz = self.b.len(); + if sz > self.len { + for _ in 0..sz - self.len { + self.b.next_back(); + } + } + } + if self.index < self.len { + self.len -= 1; + let i = self.len; unsafe { Some((self.a.get_unchecked(i), self.b.get_unchecked(i))) } @@ -838,6 +875,9 @@ unsafe impl<A, B> TrustedRandomAccess for Zip<A, B> (self.a.get_unchecked(i), self.b.get_unchecked(i)) } + fn may_have_side_effect() -> bool { + A::may_have_side_effect() || B::may_have_side_effect() + } } #[unstable(feature = "fused", issue = "35602")] @@ -924,6 +964,13 @@ impl<B, I: Iterator, F> Iterator for Map<I, F> where F: FnMut(I::Item) -> B { fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() } + + fn fold<Acc, G>(self, init: Acc, mut g: G) -> Acc + where G: FnMut(Acc, Self::Item) -> Acc, + { + let mut f = self.f; + self.iter.fold(init, move |acc, elt| g(acc, f(elt))) + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -944,6 +991,18 @@ impl<B, I: ExactSizeIterator, F> ExactSizeIterator for Map<I, F> impl<B, I: FusedIterator, F> FusedIterator for Map<I, F> where F: FnMut(I::Item) -> B {} +#[doc(hidden)] +unsafe impl<B, I, F> TrustedRandomAccess for Map<I, F> + where I: TrustedRandomAccess, + F: FnMut(I::Item) -> B, +{ + unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item { + (self.f)(self.iter.get_unchecked(i)) + } + #[inline] + fn may_have_side_effect() -> bool { true } +} + /// An iterator that filters the elements of `iter` with `predicate`. /// /// This `struct` is created by the [`filter()`] method on [`Iterator`]. See its @@ -1159,6 +1218,10 @@ unsafe impl<I> TrustedRandomAccess for Enumerate<I> unsafe fn get_unchecked(&mut self, i: usize) -> (usize, I::Item) { (self.count + i, self.iter.get_unchecked(i)) } + + fn may_have_side_effect() -> bool { + I::may_have_side_effect() + } } #[unstable(feature = "fused", issue = "35602")] @@ -1788,6 +1851,10 @@ unsafe impl<I> TrustedRandomAccess for Fuse<I> unsafe fn get_unchecked(&mut self, i: usize) -> I::Item { self.iter.get_unchecked(i) } + + fn may_have_side_effect() -> bool { + I::may_have_side_effect() + } } #[unstable(feature = "fused", issue = "35602")] diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 66d05d81d80..eaa3d50c88a 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -328,7 +328,8 @@ impl<A: Step> ops::RangeInclusive<A> { } } -#[stable(feature = "rust1", since = "1.0.0")] +#[unstable(feature = "step_by", reason = "recent addition", + issue = "27741")] impl<A> Iterator for StepBy<A, ops::RangeFrom<A>> where A: Clone, for<'a> &'a A: Add<&'a A, Output = A> @@ -352,7 +353,8 @@ impl<A> Iterator for StepBy<A, ops::RangeFrom<A>> where impl<A> FusedIterator for StepBy<A, ops::RangeFrom<A>> where A: Clone, for<'a> &'a A: Add<&'a A, Output = A> {} -#[stable(feature = "rust1", since = "1.0.0")] +#[unstable(feature = "step_by", reason = "recent addition", + issue = "27741")] impl<A: Step + Clone> Iterator for StepBy<A, ops::Range<A>> { type Item = A; @@ -466,7 +468,11 @@ macro_rules! range_exact_iter_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for ops::Range<$t> { } + )*) +} +macro_rules! range_incl_exact_iter_impl { + ($($t:ty)*) => ($( #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] @@ -500,9 +506,12 @@ impl<A: Step> Iterator for ops::Range<A> where } } -// Ranges of u64 and i64 are excluded because they cannot guarantee having -// a length <= usize::MAX, which is required by ExactSizeIterator. +// These macros generate `ExactSizeIterator` impls for various range types. +// Range<{u,i}64> and RangeInclusive<{u,i}{32,64,size}> are excluded +// because they cannot guarantee having a length <= usize::MAX, which is +// required by ExactSizeIterator. range_exact_iter_impl!(usize u8 u16 u32 isize i8 i16 i32); +range_incl_exact_iter_impl!(u8 u16 i8 i16); #[stable(feature = "rust1", since = "1.0.0")] impl<A: Step + Clone> DoubleEndedIterator for ops::Range<A> where diff --git a/src/libcore/iter_private.rs b/src/libcore/iter_private.rs index 83eeef31ab0..bc1aaa09f3d 100644 --- a/src/libcore/iter_private.rs +++ b/src/libcore/iter_private.rs @@ -14,6 +14,7 @@ /// # Safety /// /// The iterator's .len() and size_hint() must be exact. +/// `.len()` must be cheap to call. /// /// .get_unchecked() must return distinct mutable references for distinct /// indices (if applicable), and must return a valid reference if index is in @@ -21,5 +22,7 @@ #[doc(hidden)] pub unsafe trait TrustedRandomAccess : ExactSizeIterator { unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item; + /// Return `true` if getting an iterator element may have + /// side effects. Remember to take inner iterators into account. + fn may_have_side_effect() -> bool; } - diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 1ae4cf8e5ef..28101d21fc2 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -89,7 +89,7 @@ #![feature(specialization)] #![feature(staged_api)] #![feature(unboxed_closures)] -#![feature(question_mark)] +#![cfg_attr(stage0, feature(question_mark))] #![feature(never_type)] #![feature(prelude_import)] diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index f29a49dd5fe..e6c3f549ec8 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -119,6 +119,44 @@ macro_rules! assert_eq { }); } +/// Asserts that two expressions are not equal to each other. +/// +/// On panic, this macro will print the values of the expressions with their +/// debug representations. +/// +/// # Examples +/// +/// ``` +/// let a = 3; +/// let b = 2; +/// assert_ne!(a, b); +/// ``` +#[macro_export] +#[stable(feature = "assert_ne", since = "1.12.0")] +macro_rules! assert_ne { + ($left:expr , $right:expr) => ({ + match (&$left, &$right) { + (left_val, right_val) => { + if *left_val == *right_val { + panic!("assertion failed: `(left != right)` \ + (left: `{:?}`, right: `{:?}`)", left_val, right_val) + } + } + } + }); + ($left:expr , $right:expr, $($arg:tt)*) => ({ + match (&($left), &($right)) { + (left_val, right_val) => { + if *left_val == *right_val { + panic!("assertion failed: `(left != right)` \ + (left: `{:?}`, right: `{:?}`): {}", left_val, right_val, + format_args!($($arg)*)) + } + } + } + }); +} + /// Ensure that a boolean expression is `true` at runtime. /// /// This will invoke the `panic!` macro if the provided expression cannot be @@ -189,9 +227,37 @@ macro_rules! debug_assert_eq { ($($arg:tt)*) => (if cfg!(debug_assertions) { assert_eq!($($arg)*); }) } +/// Asserts that two expressions are not equal to each other. +/// +/// On panic, this macro will print the values of the expressions with their +/// debug representations. +/// +/// Unlike `assert_ne!`, `debug_assert_ne!` statements are only enabled in non +/// optimized builds by default. An optimized build will omit all +/// `debug_assert_ne!` statements unless `-C debug-assertions` is passed to the +/// compiler. This makes `debug_assert_ne!` useful for checks that are too +/// expensive to be present in a release build but may be helpful during +/// development. +/// +/// # Examples +/// +/// ``` +/// let a = 3; +/// let b = 2; +/// debug_assert_ne!(a, b); +/// ``` +#[macro_export] +#[stable(feature = "assert_ne", since = "1.12.0")] +macro_rules! debug_assert_ne { + ($($arg:tt)*) => (if cfg!(debug_assertions) { assert_ne!($($arg)*); }) +} + /// Helper macro for reducing boilerplate code for matching `Result` together /// with converting downstream errors. /// +/// Prefer using `?` syntax to `try!`. `?` is built in to the language and is +/// more succinct than `try!`. It is the standard method for error propagation. +/// /// `try!` matches the given `Result`. In case of the `Ok` variant, the /// expression has the value of the wrapped value. /// @@ -443,3 +509,143 @@ macro_rules! unreachable { macro_rules! unimplemented { () => (panic!("not yet implemented")) } + +/// Built-in macros to the compiler itself. +/// +/// These macros do not have any corresponding definition with a `macro_rules!` +/// macro, but are documented here. Their implementations can be found hardcoded +/// into libsyntax itself. +/// +/// For more information, see documentation for `std`'s macros. +#[cfg(dox)] +pub mod builtin { + /// The core macro for formatted string creation & output. + /// + /// For more information, see the documentation for [`std::format_args!`]. + /// + /// [`std::format_args!`]: ../std/macro.format_args.html + #[stable(feature = "rust1", since = "1.0.0")] + #[macro_export] + macro_rules! format_args { ($fmt:expr, $($args:tt)*) => ({ + /* compiler built-in */ + }) } + + /// Inspect an environment variable at compile time. + /// + /// For more information, see the documentation for [`std::env!`]. + /// + /// [`std::env!`]: ../std/macro.env.html + #[stable(feature = "rust1", since = "1.0.0")] + #[macro_export] + macro_rules! env { ($name:expr) => ({ /* compiler built-in */ }) } + + /// Optionally inspect an environment variable at compile time. + /// + /// For more information, see the documentation for [`std::option_env!`]. + /// + /// [`std::option_env!`]: ../std/macro.option_env.html + #[stable(feature = "rust1", since = "1.0.0")] + #[macro_export] + macro_rules! option_env { ($name:expr) => ({ /* compiler built-in */ }) } + + /// Concatenate identifiers into one identifier. + /// + /// For more information, see the documentation for [`std::concat_idents!`]. + /// + /// [`std::concat_idents!`]: ../std/macro.concat_idents.html + #[unstable(feature = "concat_idents_macro", issue = "29599")] + #[macro_export] + macro_rules! concat_idents { + ($($e:ident),*) => ({ /* compiler built-in */ }) + } + + /// Concatenates literals into a static string slice. + /// + /// For more information, see the documentation for [`std::concat!`]. + /// + /// [`std::concat!`]: ../std/macro.concat.html + #[stable(feature = "rust1", since = "1.0.0")] + #[macro_export] + macro_rules! concat { ($($e:expr),*) => ({ /* compiler built-in */ }) } + + /// A macro which expands to the line number on which it was invoked. + /// + /// For more information, see the documentation for [`std::line!`]. + /// + /// [`std::line!`]: ../std/macro.line.html + #[stable(feature = "rust1", since = "1.0.0")] + #[macro_export] + macro_rules! line { () => ({ /* compiler built-in */ }) } + + /// A macro which expands to the column number on which it was invoked. + /// + /// For more information, see the documentation for [`std::column!`]. + /// + /// [`std::column!`]: ../std/macro.column.html + #[stable(feature = "rust1", since = "1.0.0")] + #[macro_export] + macro_rules! column { () => ({ /* compiler built-in */ }) } + + /// A macro which expands to the file name from which it was invoked. + /// + /// For more information, see the documentation for [`std::file!`]. + /// + /// [`std::file!`]: ../std/macro.file.html + #[stable(feature = "rust1", since = "1.0.0")] + #[macro_export] + macro_rules! file { () => ({ /* compiler built-in */ }) } + + /// A macro which stringifies its argument. + /// + /// For more information, see the documentation for [`std::stringify!`]. + /// + /// [`std::stringify!`]: ../std/macro.stringify.html + #[stable(feature = "rust1", since = "1.0.0")] + #[macro_export] + macro_rules! stringify { ($t:tt) => ({ /* compiler built-in */ }) } + + /// Includes a utf8-encoded file as a string. + /// + /// For more information, see the documentation for [`std::include_str!`]. + /// + /// [`std::include_str!`]: ../std/macro.include_str.html + #[stable(feature = "rust1", since = "1.0.0")] + #[macro_export] + macro_rules! include_str { ($file:expr) => ({ /* compiler built-in */ }) } + + /// Includes a file as a reference to a byte array. + /// + /// For more information, see the documentation for [`std::include_bytes!`]. + /// + /// [`std::include_bytes!`]: ../std/macro.include_bytes.html + #[stable(feature = "rust1", since = "1.0.0")] + #[macro_export] + macro_rules! include_bytes { ($file:expr) => ({ /* compiler built-in */ }) } + + /// Expands to a string that represents the current module path. + /// + /// For more information, see the documentation for [`std::module_path!`]. + /// + /// [`std::module_path!`]: ../std/macro.module_path.html + #[stable(feature = "rust1", since = "1.0.0")] + #[macro_export] + macro_rules! module_path { () => ({ /* compiler built-in */ }) } + + /// Boolean evaluation of configuration flags. + /// + /// For more information, see the documentation for [`std::cfg!`]. + /// + /// [`std::cfg!`]: ../std/macro.cfg.html + #[stable(feature = "rust1", since = "1.0.0")] + #[macro_export] + macro_rules! cfg { ($($cfg:tt)*) => ({ /* compiler built-in */ }) } + + /// Parse a file as an expression or an item according to the context. + /// + /// For more information, see the documentation for [`std::include!`]. + /// + /// [`std::include!`]: ../std/macro.include.html + #[stable(feature = "rust1", since = "1.0.0")] + #[macro_export] + macro_rules! include { ($file:expr) => ({ /* compiler built-in */ }) } +} diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index c22c9f0d1c7..03d8af1563d 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -8,11 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Primitive traits and marker types representing basic 'kinds' of types. +//! Primitive traits and types representing basic properties of types. //! //! Rust types can be classified in various useful ways according to -//! intrinsic properties of the type. These classifications, often called -//! 'kinds', are represented as traits. +//! their intrinsic properties. These classifications are represented +//! as traits. #![stable(feature = "rust1", since = "1.0.0")] @@ -22,7 +22,21 @@ use hash::Hasher; /// Types that can be transferred across thread boundaries. /// -/// This trait is automatically derived when the compiler determines it's appropriate. +/// This trait is automatically implemented when the compiler determines it's +/// appropriate. +/// +/// An example of a non-`Send` type is the reference-counting pointer +/// [`rc::Rc`][rc]. If two threads attempt to clone `Rc`s that point to the same +/// reference-counted value, they might try to update the reference count at the +/// same time, which is [undefined behavior][ub] because `Rc` doesn't use atomic +/// operations. Its cousin [`sync::Arc`][arc] does use atomic operations (incurring +/// some overhead) and thus is `Send`. +/// +/// See [the Nomicon](../../nomicon/send-and-sync.html) for more details. +/// +/// [rc]: ../../std/rc/struct.Rc.html +/// [arc]: ../../std/sync/struct.Arc.html +/// [ub]: ../../reference.html#behavior-considered-undefined #[stable(feature = "rust1", since = "1.0.0")] #[lang = "send"] #[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"] @@ -38,10 +52,10 @@ impl<T: ?Sized> !Send for *const T { } #[stable(feature = "rust1", since = "1.0.0")] impl<T: ?Sized> !Send for *mut T { } -/// Types with a constant size known at compile-time. +/// Types with a constant size known at compile time. /// -/// All type parameters which can be bounded have an implicit bound of `Sized`. The special syntax -/// `?Sized` can be used to remove this bound if it is not appropriate. +/// All type parameters have an implicit bound of `Sized`. The special syntax +/// `?Sized` can be used to remove this bound if it's not appropriate. /// /// ``` /// # #![allow(dead_code)] @@ -51,6 +65,26 @@ impl<T: ?Sized> !Send for *mut T { } /// // struct FooUse(Foo<[i32]>); // error: Sized is not implemented for [i32] /// struct BarUse(Bar<[i32]>); // OK /// ``` +/// +/// The one exception is the implicit `Self` type of a trait, which does not +/// get an implicit `Sized` bound. This is because a `Sized` bound prevents +/// the trait from being used to form a [trait object]: +/// +/// ``` +/// # #![allow(unused_variables)] +/// trait Foo { } +/// trait Bar: Sized { } +/// +/// struct Impl; +/// impl Foo for Impl { } +/// impl Bar for Impl { } +/// +/// let x: &Foo = &Impl; // OK +/// // let y: &Bar = &Impl; // error: the trait `Bar` cannot +/// // be made into an object +/// ``` +/// +/// [trait object]: ../../book/trait-objects.html #[stable(feature = "rust1", since = "1.0.0")] #[lang = "sized"] #[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"] @@ -59,14 +93,27 @@ pub trait Sized { // Empty. } -/// Types that can be "unsized" to a dynamically sized type. +/// Types that can be "unsized" to a dynamically-sized type. +/// +/// For example, the sized array type `[i8; 2]` implements `Unsize<[i8]>` and +/// `Unsize<fmt::Debug>`. +/// +/// All implementations of `Unsize` are provided automatically by the compiler. +/// +/// `Unsize` is used along with [`ops::CoerceUnsized`][coerceunsized] to allow +/// "user-defined" containers such as [`rc::Rc`][rc] to contain dynamically-sized +/// types. See the [DST coercion RFC][RFC982] for more details. +/// +/// [coerceunsized]: ../ops/trait.CoerceUnsized.html +/// [rc]: ../../std/rc/struct.Rc.html +/// [RFC982]: https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md #[unstable(feature = "unsize", issue = "27732")] #[lang="unsize"] pub trait Unsize<T: ?Sized> { // Empty. } -/// Types that can be copied by simply copying bits (i.e. `memcpy`). +/// Types whose values can be duplicated simply by copying bits. /// /// By default, variable bindings have 'move semantics.' In other /// words: @@ -87,7 +134,8 @@ pub trait Unsize<T: ?Sized> { /// However, if a type implements `Copy`, it instead has 'copy semantics': /// /// ``` -/// // we can just derive a `Copy` implementation +/// // We can derive a `Copy` implementation. `Clone` is also required, as it's +/// // a supertrait of `Copy`. /// #[derive(Debug, Copy, Clone)] /// struct Foo; /// @@ -100,13 +148,59 @@ pub trait Unsize<T: ?Sized> { /// println!("{:?}", x); // A-OK! /// ``` /// -/// It's important to note that in these two examples, the only difference is if you are allowed to -/// access `x` after the assignment: a move is also a bitwise copy under the hood. +/// It's important to note that in these two examples, the only difference is whether you +/// are allowed to access `x` after the assignment. Under the hood, both a copy and a move +/// can result in bits being copied in memory, although this is sometimes optimized away. +/// +/// ## How can I implement `Copy`? +/// +/// There are two ways to implement `Copy` on your type. The simplest is to use `derive`: +/// +/// ``` +/// #[derive(Copy, Clone)] +/// struct MyStruct; +/// ``` +/// +/// You can also implement `Copy` and `Clone` manually: +/// +/// ``` +/// struct MyStruct; +/// +/// impl Copy for MyStruct { } +/// +/// impl Clone for MyStruct { +/// fn clone(&self) -> MyStruct { +/// *self +/// } +/// } +/// ``` +/// +/// There is a small difference between the two: the `derive` strategy will also place a `Copy` +/// bound on type parameters, which isn't always desired. +/// +/// ## What's the difference between `Copy` and `Clone`? +/// +/// Copies happen implicitly, for example as part of an assignment `y = x`. The behavior of +/// `Copy` is not overloadable; it is always a simple bit-wise copy. +/// +/// Cloning is an explicit action, `x.clone()`. The implementation of [`Clone`][clone] can +/// provide any type-specific behavior necessary to duplicate values safely. For example, +/// the implementation of `Clone` for [`String`][string] needs to copy the pointed-to string +/// buffer in the heap. A simple bitwise copy of `String` values would merely copy the +/// pointer, leading to a double free down the line. For this reason, `String` is `Clone` +/// but not `Copy`. +/// +/// `Clone` is a supertrait of `Copy`, so everything which is `Copy` must also implement +/// `Clone`. If a type is `Copy` then its `Clone` implementation need only return `*self` +/// (see the example above). +/// +/// [clone]: ../clone/trait.Clone.html +/// [string]: ../../std/string/struct.String.html /// /// ## When can my type be `Copy`? /// /// A type can implement `Copy` if all of its components implement `Copy`. For example, this -/// `struct` can be `Copy`: +/// struct can be `Copy`: /// /// ``` /// # #[allow(dead_code)] @@ -116,7 +210,8 @@ pub trait Unsize<T: ?Sized> { /// } /// ``` /// -/// A `struct` can be `Copy`, and `i32` is `Copy`, so therefore, `Point` is eligible to be `Copy`. +/// A struct can be `Copy`, and `i32` is `Copy`, therefore `Point` is eligible to be `Copy`. +/// By contrast, consider /// /// ``` /// # #![allow(dead_code)] @@ -126,57 +221,35 @@ pub trait Unsize<T: ?Sized> { /// } /// ``` /// -/// The `PointList` `struct` cannot implement `Copy`, because [`Vec<T>`] is not `Copy`. If we +/// The struct `PointList` cannot implement `Copy`, because [`Vec<T>`] is not `Copy`. If we /// attempt to derive a `Copy` implementation, we'll get an error: /// /// ```text /// the trait `Copy` may not be implemented for this type; field `points` does not implement `Copy` /// ``` /// -/// ## When can my type _not_ be `Copy`? +/// ## When *can't* my type be `Copy`? /// /// Some types can't be copied safely. For example, copying `&mut T` would create an aliased -/// mutable reference, and copying [`String`] would result in two attempts to free the same buffer. +/// mutable reference. Copying [`String`] would duplicate responsibility for managing the `String`'s +/// buffer, leading to a double free. /// /// Generalizing the latter case, any type implementing [`Drop`] can't be `Copy`, because it's /// managing some resource besides its own [`size_of::<T>()`] bytes. /// -/// ## What if I derive `Copy` on a type that can't? -/// -/// If you try to derive `Copy` on a struct or enum, you will get a compile-time error. -/// Specifically, with structs you'll get [E0204](https://doc.rust-lang.org/error-index.html#E0204) -/// and with enums you'll get [E0205](https://doc.rust-lang.org/error-index.html#E0205). -/// -/// ## When should my type be `Copy`? -/// -/// Generally speaking, if your type _can_ implement `Copy`, it should. There's one important thing -/// to consider though: if you think your type may _not_ be able to implement `Copy` in the future, -/// then it might be prudent to not implement `Copy`. This is because removing `Copy` is a breaking -/// change: that second example would fail to compile if we made `Foo` non-`Copy`. +/// If you try to implement `Copy` on a struct or enum containing non-`Copy` data, you will get a +/// compile-time error. Specifically, with structs you'll get [E0204] and with enums you'll get +/// [E0205]. /// -/// ## Derivable +/// [E0204]: https://doc.rust-lang.org/error-index.html#E0204 +/// [E0205]: https://doc.rust-lang.org/error-index.html#E0205 /// -/// This trait can be used with `#[derive]` if all of its components implement `Copy` and the type. +/// ## When *should* my type be `Copy`? /// -/// ## How can I implement `Copy`? -/// -/// There are two ways to implement `Copy` on your type: -/// -/// ``` -/// #[derive(Copy, Clone)] -/// struct MyStruct; -/// ``` -/// -/// and -/// -/// ``` -/// struct MyStruct; -/// impl Copy for MyStruct {} -/// impl Clone for MyStruct { fn clone(&self) -> MyStruct { *self } } -/// ``` -/// -/// There is a small difference between the two: the `derive` strategy will also place a `Copy` -/// bound on type parameters, which isn't always desired. +/// Generally speaking, if your type _can_ implement `Copy`, it should. Keep in mind, though, +/// that implementing `Copy` is part of the public API of your type. If the type might become +/// non-`Copy` in the future, it could be prudent to omit the `Copy` implementation now, to +/// avoid a breaking API change. /// /// [`Vec<T>`]: ../../std/vec/struct.Vec.html /// [`String`]: ../../std/string/struct.String.html @@ -188,64 +261,74 @@ pub trait Copy : Clone { // Empty. } -/// Types that can be safely shared between threads when aliased. +/// Types for which it is safe to share references between threads. +/// +/// This trait is automatically implemented when the compiler determines +/// it's appropriate. /// /// The precise definition is: a type `T` is `Sync` if `&T` is -/// thread-safe. In other words, there is no possibility of data races -/// when passing `&T` references between threads. -/// -/// As one would expect, primitive types like [`u8`] and [`f64`] are all -/// `Sync`, and so are simple aggregate types containing them (like -/// tuples, structs and enums). More instances of basic `Sync` types -/// include "immutable" types like `&T` and those with simple -/// inherited mutability, such as [`Box<T>`], [`Vec<T>`] and most other -/// collection types. (Generic parameters need to be `Sync` for their -/// container to be `Sync`.) -/// -/// A somewhat surprising consequence of the definition is `&mut T` is -/// `Sync` (if `T` is `Sync`) even though it seems that it might -/// provide unsynchronized mutation. The trick is a mutable reference -/// stored in an aliasable reference (that is, `& &mut T`) becomes -/// read-only, as if it were a `& &T`, hence there is no risk of a data -/// race. +/// [`Send`][send]. In other words, if there is no possibility of +/// [undefined behavior][ub] (including data races) when passing +/// `&T` references between threads. +/// +/// As one would expect, primitive types like [`u8`][u8] and [`f64`][f64] +/// are all `Sync`, and so are simple aggregate types containing them, +/// like tuples, structs and enums. More examples of basic `Sync` +/// types include "immutable" types like `&T`, and those with simple +/// inherited mutability, such as [`Box<T>`][box], [`Vec<T>`][vec] and +/// most other collection types. (Generic parameters need to be `Sync` +/// for their container to be `Sync`.) +/// +/// A somewhat surprising consequence of the definition is that `&mut T` +/// is `Sync` (if `T` is `Sync`) even though it seems like that might +/// provide unsynchronized mutation. The trick is that a mutable +/// reference behind a shared reference (that is, `& &mut T`) +/// becomes read-only, as if it were a `& &T`. Hence there is no risk +/// of a data race. /// /// Types that are not `Sync` are those that have "interior -/// mutability" in a non-thread-safe way, such as [`Cell`] and [`RefCell`] -/// in [`std::cell`]. These types allow for mutation of their contents -/// even when in an immutable, aliasable slot, e.g. the contents of -/// [`&Cell<T>`][`Cell`] can be [`.set`], and do not ensure data races are -/// impossible, hence they cannot be `Sync`. A higher level example -/// of a non-`Sync` type is the reference counted pointer -/// [`std::rc::Rc`][`Rc`], because any reference [`&Rc<T>`][`Rc`] can clone a new -/// reference, which modifies the reference counts in a non-atomic -/// way. -/// -/// For cases when one does need thread-safe interior mutability, -/// types like the atomics in [`std::sync`][`sync`] and [`Mutex`] / [`RwLock`] in -/// the [`sync`] crate do ensure that any mutation cannot cause data -/// races. Hence these types are `Sync`. -/// -/// Any types with interior mutability must also use the [`std::cell::UnsafeCell`] -/// wrapper around the value(s) which can be mutated when behind a `&` -/// reference; not doing this is undefined behavior (for example, -/// [`transmute`]-ing from `&T` to `&mut T` is invalid). +/// mutability" in a non-thread-safe form, such as [`cell::Cell`][cell] +/// and [`cell::RefCell`][refcell]. These types allow for mutation of +/// their contents even through an immutable, shared reference. For +/// example the `set` method on `Cell<T>` takes `&self`, so it requires +/// only a shared reference `&Cell<T>`. The method performs no +/// synchronization, thus `Cell` cannot be `Sync`. /// -/// This trait is automatically derived when the compiler determines it's appropriate. +/// Another example of a non-`Sync` type is the reference-counting +/// pointer [`rc::Rc`][rc]. Given any reference `&Rc<T>`, you can clone +/// a new `Rc<T>`, modifying the reference counts in a non-atomic way. /// -/// [`u8`]: ../../std/primitive.u8.html -/// [`f64`]: ../../std/primitive.f64.html -/// [`Vec<T>`]: ../../std/vec/struct.Vec.html -/// [`Box<T>`]: ../../std/boxed/struct.Box.html -/// [`Cell`]: ../../std/cell/struct.Cell.html -/// [`RefCell`]: ../../std/cell/struct.RefCell.html -/// [`std::cell`]: ../../std/cell/index.html -/// [`.set`]: ../../std/cell/struct.Cell.html#method.set -/// [`Rc`]: ../../std/rc/struct.Rc.html -/// [`sync`]: ../../std/sync/index.html -/// [`Mutex`]: ../../std/sync/struct.Mutex.html -/// [`RwLock`]: ../../std/sync/struct.RwLock.html -/// [`std::cell::UnsafeCell`]: ../../std/cell/struct.UnsafeCell.html -/// [`transmute`]: ../../std/mem/fn.transmute.html +/// For cases when one does need thread-safe interior mutability, +/// Rust provides [atomic data types], as well as explicit locking via +/// [`sync::Mutex`][mutex] and [`sync::RWLock`][rwlock]. These types +/// ensure that any mutation cannot cause data races, hence the types +/// are `Sync`. Likewise, [`sync::Arc`][arc] provides a thread-safe +/// analogue of `Rc`. +/// +/// Any types with interior mutability must also use the +/// [`cell::UnsafeCell`][unsafecell] wrapper around the value(s) which +/// can be mutated through a shared reference. Failing to doing this is +/// [undefined behavior][ub]. For example, [`transmute`][transmute]-ing +/// from `&T` to `&mut T` is invalid. +/// +/// See [the Nomicon](../../nomicon/send-and-sync.html) for more +/// details about `Sync`. +/// +/// [send]: trait.Send.html +/// [u8]: ../../std/primitive.u8.html +/// [f64]: ../../std/primitive.f64.html +/// [box]: ../../std/boxed/struct.Box.html +/// [vec]: ../../std/vec/struct.Vec.html +/// [cell]: ../cell/struct.Cell.html +/// [refcell]: ../cell/struct.RefCell.html +/// [rc]: ../../std/rc/struct.Rc.html +/// [arc]: ../../std/sync/struct.Arc.html +/// [atomic data types]: ../sync/atomic/index.html +/// [mutex]: ../../std/sync/struct.Mutex.html +/// [rwlock]: ../../std/sync/struct.RwLock.html +/// [unsafecell]: ../cell/struct.UnsafeCell.html +/// [ub]: ../../reference.html#behavior-considered-undefined +/// [transmute]: ../../std/mem/fn.transmute.html #[stable(feature = "rust1", since = "1.0.0")] #[lang = "sync"] #[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"] @@ -314,29 +397,30 @@ macro_rules! impls{ ) } -/// `PhantomData<T>` allows you to describe that a type acts as if it stores a value of type `T`, -/// even though it does not. This allows you to inform the compiler about certain safety properties -/// of your code. +/// Zero-sized type used to mark things that "act like" they own a `T`. /// -/// For a more in-depth explanation of how to use `PhantomData<T>`, please see [the Nomicon]. +/// Adding a `PhantomData<T>` field to your type tells the compiler that your +/// type acts as though it stores a value of type `T`, even though it doesn't +/// really. This information is used when computing certain safety properties. /// -/// [the Nomicon]: ../../nomicon/phantom-data.html +/// For a more in-depth explanation of how to use `PhantomData<T>`, please see +/// [the Nomicon](../../nomicon/phantom-data.html). /// /// # A ghastly note 👻👻👻 /// -/// Though they both have scary names, `PhantomData<T>` and 'phantom types' are related, but not -/// identical. Phantom types are a more general concept that don't require `PhantomData<T>` to -/// implement, but `PhantomData<T>` is the most common way to implement them in a correct manner. +/// Though they both have scary names, `PhantomData` and 'phantom types' are +/// related, but not identical. A phantom type parameter is simply a type +/// parameter which is never used. In Rust, this often causes the compiler to +/// complain, and the solution is to add a "dummy" use by way of `PhantomData`. /// /// # Examples /// -/// ## Unused lifetime parameter +/// ## Unused lifetime parameters /// -/// Perhaps the most common time that `PhantomData` is required is -/// with a struct that has an unused lifetime parameter, typically as -/// part of some unsafe code. For example, here is a struct `Slice` -/// that has two pointers of type `*const T`, presumably pointing into -/// an array somewhere: +/// Perhaps the most common use case for `PhantomData` is a struct that has an +/// unused lifetime parameter, typically as part of some unsafe code. For +/// example, here is a struct `Slice` that has two pointers of type `*const T`, +/// presumably pointing into an array somewhere: /// /// ```ignore /// struct Slice<'a, T> { @@ -350,7 +434,7 @@ macro_rules! impls{ /// intent is not expressed in the code, since there are no uses of /// the lifetime `'a` and hence it is not clear what data it applies /// to. We can correct this by telling the compiler to act *as if* the -/// `Slice` struct contained a borrowed reference `&'a T`: +/// `Slice` struct contained a reference `&'a T`: /// /// ``` /// use std::marker::PhantomData; @@ -359,29 +443,53 @@ macro_rules! impls{ /// struct Slice<'a, T: 'a> { /// start: *const T, /// end: *const T, -/// phantom: PhantomData<&'a T> +/// phantom: PhantomData<&'a T>, /// } /// ``` /// -/// This also in turn requires that we annotate `T:'a`, indicating -/// that `T` is a type that can be borrowed for the lifetime `'a`. +/// This also in turn requires the annotation `T: 'a`, indicating +/// that any references in `T` are valid over the lifetime `'a`. +/// +/// When initializing a `Slice` you simply provide the value +/// `PhantomData` for the field `phantom`: +/// +/// ``` +/// # #![allow(dead_code)] +/// # use std::marker::PhantomData; +/// # struct Slice<'a, T: 'a> { +/// # start: *const T, +/// # end: *const T, +/// # phantom: PhantomData<&'a T>, +/// # } +/// fn borrow_vec<'a, T>(vec: &'a Vec<T>) -> Slice<'a, T> { +/// let ptr = vec.as_ptr(); +/// Slice { +/// start: ptr, +/// end: unsafe { ptr.offset(vec.len() as isize) }, +/// phantom: PhantomData, +/// } +/// } +/// ``` /// /// ## Unused type parameters /// -/// It sometimes happens that there are unused type parameters that +/// It sometimes happens that you have unused type parameters which /// indicate what type of data a struct is "tied" to, even though that /// data is not actually found in the struct itself. Here is an -/// example where this arises when handling external resources over a -/// foreign function interface. `PhantomData<T>` can prevent -/// mismatches by enforcing types in the method implementations: +/// example where this arises with [FFI]. The foreign interface uses +/// handles of type `*mut ()` to refer to Rust values of different +/// types. We track the Rust type using a phantom type parameter on +/// the struct `ExternalResource` which wraps a handle. +/// +/// [FFI]: ../../book/ffi.html /// /// ``` /// # #![allow(dead_code)] -/// # trait ResType { fn foo(&self); } +/// # trait ResType { } /// # struct ParamType; /// # mod foreign_lib { -/// # pub fn new(_: usize) -> *mut () { 42 as *mut () } -/// # pub fn do_stuff(_: *mut (), _: usize) {} +/// # pub fn new(_: usize) -> *mut () { 42 as *mut () } +/// # pub fn do_stuff(_: *mut (), _: usize) {} /// # } /// # fn convert_params(_: ParamType) -> usize { 42 } /// use std::marker::PhantomData; @@ -408,21 +516,20 @@ macro_rules! impls{ /// } /// ``` /// -/// ## Indicating ownership +/// ## Ownership and the drop check /// -/// Adding a field of type `PhantomData<T>` also indicates that your -/// struct owns data of type `T`. This in turn implies that when your -/// struct is dropped, it may in turn drop one or more instances of -/// the type `T`, though that may not be apparent from the other -/// structure of the type itself. This is commonly necessary if the -/// structure is using a raw pointer like `*mut T` whose referent -/// may be dropped when the type is dropped, as a `*mut T` is -/// otherwise not treated as owned. +/// Adding a field of type `PhantomData<T>` indicates that your +/// type owns data of type `T`. This in turn implies that when your +/// type is dropped, it may drop one or more instances of the type +/// `T`. This has bearing on the Rust compiler's [drop check] +/// analysis. /// /// If your struct does not in fact *own* the data of type `T`, it is /// better to use a reference type, like `PhantomData<&'a T>` /// (ideally) or `PhantomData<*const T>` (if no lifetime applies), so /// as not to indicate ownership. +/// +/// [drop check]: ../../nomicon/dropck.html #[lang = "phantom_data"] #[stable(feature = "rust1", since = "1.0.0")] pub struct PhantomData<T:?Sized>; @@ -438,10 +545,13 @@ mod impls { /// Types that can be reflected over. /// -/// This trait is implemented for all types. Its purpose is to ensure -/// that when you write a generic function that will employ -/// reflection, that must be reflected (no pun intended) in the -/// generic bounds of that function. Here is an example: +/// By "reflection" we mean use of the [`Any`][any] trait, or related +/// machinery such as [`TypeId`][typeid]. +/// +/// `Reflect` is implemented for all types. Its purpose is to ensure +/// that when you write a generic function that will employ reflection, +/// that must be reflected (no pun intended) in the generic bounds of +/// that function. /// /// ``` /// #![feature(reflect_marker)] @@ -455,25 +565,29 @@ mod impls { /// } /// ``` /// -/// Without the declaration `T: Reflect`, `foo` would not type check -/// (note: as a matter of style, it would be preferable to write -/// `T: Any`, because `T: Any` implies `T: Reflect` and `T: 'static`, but -/// we use `Reflect` here to show how it works). The `Reflect` bound -/// thus serves to alert `foo`'s caller to the fact that `foo` may -/// behave differently depending on whether `T = u32` or not. In -/// particular, thanks to the `Reflect` bound, callers know that a -/// function declared like `fn bar<T>(...)` will always act in -/// precisely the same way no matter what type `T` is supplied, -/// because there are no bounds declared on `T`. (The ability for a -/// caller to reason about what a function may do based solely on what -/// generic bounds are declared is often called the ["parametricity -/// property"][1].) -/// -/// [1]: http://en.wikipedia.org/wiki/Parametricity +/// Without the bound `T: Reflect`, `foo` would not typecheck. (As +/// a matter of style, it would be preferable to write `T: Any`, +/// because `T: Any` implies `T: Reflect` and `T: 'static`, but we +/// use `Reflect` here for illustrative purposes.) +/// +/// The `Reflect` bound serves to alert `foo`'s caller to the +/// fact that `foo` may behave differently depending on whether +/// `T` is `u32` or not. The ability for a caller to reason about what +/// a function may do based solely on what generic bounds are declared +/// is often called the "[parametricity property][param]". Despite the +/// use of `Reflect`, Rust lacks true parametricity because a generic +/// function can, at the very least, call [`mem::size_of`][size_of] +/// without employing any trait bounds whatsoever. +/// +/// [any]: ../any/trait.Any.html +/// [typeid]: ../any/struct.TypeId.html +/// [param]: http://en.wikipedia.org/wiki/Parametricity +/// [size_of]: ../mem/fn.size_of.html #[rustc_reflect_like] #[unstable(feature = "reflect_marker", reason = "requires RFC and more experience", issue = "27749")] +#[rustc_deprecated(since = "1.14.0", reason = "Specialization makes parametricity impossible")] #[rustc_on_unimplemented = "`{Self}` does not implement `Any`; \ ensure all type parameters are bounded by `Any`"] pub trait Reflect {} @@ -481,4 +595,6 @@ pub trait Reflect {} #[unstable(feature = "reflect_marker", reason = "requires RFC and more experience", issue = "27749")] +#[rustc_deprecated(since = "1.14.0", reason = "Specialization makes parametricity impossible")] +#[allow(deprecated)] impl Reflect for .. { } diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index d3b8a60b797..e0aa25724c1 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -15,7 +15,12 @@ #![stable(feature = "rust1", since = "1.0.0")] +use clone; +use cmp; +use fmt; +use hash; use intrinsics; +use marker::{Copy, PhantomData, Sized}; use ptr; #[stable(feature = "rust1", since = "1.0.0")] @@ -647,3 +652,80 @@ pub fn drop<T>(_x: T) { } pub unsafe fn transmute_copy<T, U>(src: &T) -> U { ptr::read(src as *const T as *const U) } + +/// Opaque type representing the discriminant of an enum. +/// +/// See the `discriminant` function in this module for more information. +#[unstable(feature = "discriminant_value", reason = "recently added, follows RFC", issue = "24263")] +pub struct Discriminant<T>(u64, PhantomData<*const T>); + +// N.B. These trait implementations cannot be derived because we don't want any bounds on T. + +#[unstable(feature = "discriminant_value", reason = "recently added, follows RFC", issue = "24263")] +impl<T> Copy for Discriminant<T> {} + +#[unstable(feature = "discriminant_value", reason = "recently added, follows RFC", issue = "24263")] +impl<T> clone::Clone for Discriminant<T> { + fn clone(&self) -> Self { + *self + } +} + +#[unstable(feature = "discriminant_value", reason = "recently added, follows RFC", issue = "24263")] +impl<T> cmp::PartialEq for Discriminant<T> { + fn eq(&self, rhs: &Self) -> bool { + self.0 == rhs.0 + } +} + +#[unstable(feature = "discriminant_value", reason = "recently added, follows RFC", issue = "24263")] +impl<T> cmp::Eq for Discriminant<T> {} + +#[unstable(feature = "discriminant_value", reason = "recently added, follows RFC", issue = "24263")] +impl<T> hash::Hash for Discriminant<T> { + fn hash<H: hash::Hasher>(&self, state: &mut H) { + self.0.hash(state); + } +} + +#[unstable(feature = "discriminant_value", reason = "recently added, follows RFC", issue = "24263")] +impl<T> fmt::Debug for Discriminant<T> { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_tuple("Discriminant") + .field(&self.0) + .finish() + } +} + +/// Returns a value uniquely identifying the enum variant in `v`. +/// +/// If `T` is not an enum, calling this function will not result in undefined behavior, but the +/// return value is unspecified. +/// +/// # Stability +/// +/// The discriminant of an enum variant may change if the enum definition changes. A discriminant +/// of some variant will not change between compilations with the same compiler. +/// +/// # Examples +/// +/// This can be used to compare enums that carry data, while disregarding +/// the actual data: +/// +/// ``` +/// #![feature(discriminant_value)] +/// use std::mem; +/// +/// enum Foo { A(&'static str), B(i32), C(i32) } +/// +/// assert!(mem::discriminant(&Foo::A("bar")) == mem::discriminant(&Foo::A("baz"))); +/// assert!(mem::discriminant(&Foo::B(1)) == mem::discriminant(&Foo::B(2))); +/// assert!(mem::discriminant(&Foo::B(3)) != mem::discriminant(&Foo::C(3))); +/// ``` +#[unstable(feature = "discriminant_value", reason = "recently added, follows RFC", issue = "24263")] +pub fn discriminant<T>(v: &T) -> Discriminant<T> { + unsafe { + Discriminant(intrinsics::discriminant_value(v), PhantomData) + } +} + diff --git a/src/libcore/num/bignum.rs b/src/libcore/num/bignum.rs index 1ca550c6746..a1f4630c304 100644 --- a/src/libcore/num/bignum.rs +++ b/src/libcore/num/bignum.rs @@ -34,19 +34,22 @@ use intrinsics; pub trait FullOps: Sized { /// Returns `(carry', v')` such that `carry' * 2^W + v' = self + other + carry`, /// where `W` is the number of bits in `Self`. - fn full_add(self, other: Self, carry: bool) -> (bool /*carry*/, Self); + fn full_add(self, other: Self, carry: bool) -> (bool /* carry */, Self); /// Returns `(carry', v')` such that `carry' * 2^W + v' = self * other + carry`, /// where `W` is the number of bits in `Self`. - fn full_mul(self, other: Self, carry: Self) -> (Self /*carry*/, Self); + fn full_mul(self, other: Self, carry: Self) -> (Self /* carry */, Self); /// Returns `(carry', v')` such that `carry' * 2^W + v' = self * other + other2 + carry`, /// where `W` is the number of bits in `Self`. - fn full_mul_add(self, other: Self, other2: Self, carry: Self) -> (Self /*carry*/, Self); + fn full_mul_add(self, other: Self, other2: Self, carry: Self) -> (Self /* carry */, Self); /// Returns `(quo, rem)` such that `borrow * 2^W + self = quo * other + rem` /// and `0 <= rem < other`, where `W` is the number of bits in `Self`. - fn full_div_rem(self, other: Self, borrow: Self) -> (Self /*quotient*/, Self /*remainder*/); + fn full_div_rem(self, + other: Self, + borrow: Self) + -> (Self /* quotient */, Self /* remainder */); } macro_rules! impl_full_ops { @@ -100,11 +103,7 @@ impl_full_ops! { /// Table of powers of 5 representable in digits. Specifically, the largest {u8, u16, u32} value /// that's a power of five, plus the corresponding exponent. Used in `mul_pow5`. -const SMALL_POW5: [(u64, usize); 3] = [ - (125, 3), - (15625, 6), - (1_220_703_125, 13), -]; +const SMALL_POW5: [(u64, usize); 3] = [(125, 3), (15625, 6), (1_220_703_125, 13)]; macro_rules! define_bignum { ($name:ident: type=$ty:ty, n=$n:expr) => ( diff --git a/src/libcore/num/dec2flt/mod.rs b/src/libcore/num/dec2flt/mod.rs index cd40e399ab9..eee3e9250fe 100644 --- a/src/libcore/num/dec2flt/mod.rs +++ b/src/libcore/num/dec2flt/mod.rs @@ -155,13 +155,13 @@ from_str_float_impl!(f64); /// [`FromStr`]: ../str/trait.FromStr.html /// [`f32`]: ../../std/primitive.f32.html /// [`f64`]: ../../std/primitive.f64.html -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Eq)] #[stable(feature = "rust1", since = "1.0.0")] pub struct ParseFloatError { kind: FloatErrorKind } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Eq)] enum FloatErrorKind { Empty, Invalid, diff --git a/src/libcore/num/diy_float.rs b/src/libcore/num/diy_float.rs index 7c369ee3b3b..11eea753f93 100644 --- a/src/libcore/num/diy_float.rs +++ b/src/libcore/num/diy_float.rs @@ -49,12 +49,30 @@ impl Fp { pub fn normalize(&self) -> Fp { let mut f = self.f; let mut e = self.e; - if f >> (64 - 32) == 0 { f <<= 32; e -= 32; } - if f >> (64 - 16) == 0 { f <<= 16; e -= 16; } - if f >> (64 - 8) == 0 { f <<= 8; e -= 8; } - if f >> (64 - 4) == 0 { f <<= 4; e -= 4; } - if f >> (64 - 2) == 0 { f <<= 2; e -= 2; } - if f >> (64 - 1) == 0 { f <<= 1; e -= 1; } + if f >> (64 - 32) == 0 { + f <<= 32; + e -= 32; + } + if f >> (64 - 16) == 0 { + f <<= 16; + e -= 16; + } + if f >> (64 - 8) == 0 { + f <<= 8; + e -= 8; + } + if f >> (64 - 4) == 0 { + f <<= 4; + e -= 4; + } + if f >> (64 - 2) == 0 { + f <<= 2; + e -= 2; + } + if f >> (64 - 1) == 0 { + f <<= 1; + e -= 1; + } debug_assert!(f >= (1 >> 63)); Fp { f: f, e: e } } @@ -66,6 +84,9 @@ impl Fp { assert!(edelta >= 0); let edelta = edelta as usize; assert_eq!(self.f << edelta >> edelta, self.f); - Fp { f: self.f << edelta, e: e } + Fp { + f: self.f << edelta, + e: e, + } } } diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 07b05f91f48..4527d46a27d 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -61,13 +61,13 @@ pub const MAX_10_EXP: i32 = 38; /// Not a Number (NaN). #[stable(feature = "rust1", since = "1.0.0")] -pub const NAN: f32 = 0.0_f32/0.0_f32; +pub const NAN: f32 = 0.0_f32 / 0.0_f32; /// Infinity (∞). #[stable(feature = "rust1", since = "1.0.0")] -pub const INFINITY: f32 = 1.0_f32/0.0_f32; +pub const INFINITY: f32 = 1.0_f32 / 0.0_f32; /// Negative infinity (-∞). #[stable(feature = "rust1", since = "1.0.0")] -pub const NEG_INFINITY: f32 = -1.0_f32/0.0_f32; +pub const NEG_INFINITY: f32 = -1.0_f32 / 0.0_f32; /// Basic mathematical constants. #[stable(feature = "rust1", since = "1.0.0")] @@ -144,26 +144,40 @@ pub mod consts { issue = "32110")] impl Float for f32 { #[inline] - fn nan() -> f32 { NAN } + fn nan() -> f32 { + NAN + } #[inline] - fn infinity() -> f32 { INFINITY } + fn infinity() -> f32 { + INFINITY + } #[inline] - fn neg_infinity() -> f32 { NEG_INFINITY } + fn neg_infinity() -> f32 { + NEG_INFINITY + } #[inline] - fn zero() -> f32 { 0.0 } + fn zero() -> f32 { + 0.0 + } #[inline] - fn neg_zero() -> f32 { -0.0 } + fn neg_zero() -> f32 { + -0.0 + } #[inline] - fn one() -> f32 { 1.0 } + fn one() -> f32 { + 1.0 + } /// Returns `true` if the number is NaN. #[inline] - fn is_nan(self) -> bool { self != self } + fn is_nan(self) -> bool { + self != self + } /// Returns `true` if the number is infinite. #[inline] @@ -192,11 +206,11 @@ impl Float for f32 { let bits: u32 = unsafe { mem::transmute(self) }; match (bits & MAN_MASK, bits & EXP_MASK) { - (0, 0) => Fp::Zero, - (_, 0) => Fp::Subnormal, + (0, 0) => Fp::Zero, + (_, 0) => Fp::Subnormal, (0, EXP_MASK) => Fp::Infinite, (_, EXP_MASK) => Fp::Nan, - _ => Fp::Normal, + _ => Fp::Normal, } } @@ -252,7 +266,9 @@ impl Float for f32 { /// Returns the reciprocal (multiplicative inverse) of the number. #[inline] - fn recip(self) -> f32 { 1.0 / self } + fn recip(self) -> f32 { + 1.0 / self + } #[inline] fn powi(self, n: i32) -> f32 { @@ -261,7 +277,9 @@ impl Float for f32 { /// Converts to degrees, assuming the number is in radians. #[inline] - fn to_degrees(self) -> f32 { self * (180.0f32 / consts::PI) } + fn to_degrees(self) -> f32 { + self * (180.0f32 / consts::PI) + } /// Converts to radians, assuming the number is in degrees. #[inline] diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 82a09e599e0..991a8568349 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -61,13 +61,13 @@ pub const MAX_10_EXP: i32 = 308; /// Not a Number (NaN). #[stable(feature = "rust1", since = "1.0.0")] -pub const NAN: f64 = 0.0_f64/0.0_f64; +pub const NAN: f64 = 0.0_f64 / 0.0_f64; /// Infinity (∞). #[stable(feature = "rust1", since = "1.0.0")] -pub const INFINITY: f64 = 1.0_f64/0.0_f64; +pub const INFINITY: f64 = 1.0_f64 / 0.0_f64; /// Negative infinity (-∞). #[stable(feature = "rust1", since = "1.0.0")] -pub const NEG_INFINITY: f64 = -1.0_f64/0.0_f64; +pub const NEG_INFINITY: f64 = -1.0_f64 / 0.0_f64; /// Basic mathematical constants. #[stable(feature = "rust1", since = "1.0.0")] @@ -144,26 +144,40 @@ pub mod consts { issue = "32110")] impl Float for f64 { #[inline] - fn nan() -> f64 { NAN } + fn nan() -> f64 { + NAN + } #[inline] - fn infinity() -> f64 { INFINITY } + fn infinity() -> f64 { + INFINITY + } #[inline] - fn neg_infinity() -> f64 { NEG_INFINITY } + fn neg_infinity() -> f64 { + NEG_INFINITY + } #[inline] - fn zero() -> f64 { 0.0 } + fn zero() -> f64 { + 0.0 + } #[inline] - fn neg_zero() -> f64 { -0.0 } + fn neg_zero() -> f64 { + -0.0 + } #[inline] - fn one() -> f64 { 1.0 } + fn one() -> f64 { + 1.0 + } /// Returns `true` if the number is NaN. #[inline] - fn is_nan(self) -> bool { self != self } + fn is_nan(self) -> bool { + self != self + } /// Returns `true` if the number is infinite. #[inline] @@ -192,11 +206,11 @@ impl Float for f64 { let bits: u64 = unsafe { mem::transmute(self) }; match (bits & MAN_MASK, bits & EXP_MASK) { - (0, 0) => Fp::Zero, - (_, 0) => Fp::Subnormal, + (0, 0) => Fp::Zero, + (_, 0) => Fp::Subnormal, (0, EXP_MASK) => Fp::Infinite, (_, EXP_MASK) => Fp::Nan, - _ => Fp::Normal, + _ => Fp::Normal, } } @@ -252,7 +266,9 @@ impl Float for f64 { /// Returns the reciprocal (multiplicative inverse) of the number. #[inline] - fn recip(self) -> f64 { 1.0 / self } + fn recip(self) -> f64 { + 1.0 / self + } #[inline] fn powi(self, n: i32) -> f64 { @@ -261,7 +277,9 @@ impl Float for f64 { /// Converts to degrees, assuming the number is in radians. #[inline] - fn to_degrees(self) -> f64 { self * (180.0f64 / consts::PI) } + fn to_degrees(self) -> f64 { + self * (180.0f64 / consts::PI) + } /// Converts to radians, assuming the number is in degrees. #[inline] diff --git a/src/libcore/num/flt2dec/decoder.rs b/src/libcore/num/flt2dec/decoder.rs index 276667e44aa..72529d3da01 100644 --- a/src/libcore/num/flt2dec/decoder.rs +++ b/src/libcore/num/flt2dec/decoder.rs @@ -21,7 +21,7 @@ use num::dec2flt::rawfp::RawFloat; /// - Any number from `(mant - minus) * 2^exp` to `(mant + plus) * 2^exp` will /// round to the original value. The range is inclusive only when /// `inclusive` is true. -#[derive(Copy, Clone, Debug, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct Decoded { /// The scaled mantissa. pub mant: u64, @@ -38,7 +38,7 @@ pub struct Decoded { } /// Decoded unsigned value. -#[derive(Copy, Clone, Debug, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum FullDecoded { /// Not-a-number. Nan, diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 29ee29eb3eb..a4529909e83 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -43,7 +43,8 @@ use str::FromStr; /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default, Hash)] -pub struct Wrapping<T>(#[stable(feature = "rust1", since = "1.0.0")] pub T); +pub struct Wrapping<T>(#[stable(feature = "rust1", since = "1.0.0")] + pub T); #[stable(feature = "rust1", since = "1.0.0")] impl<T: fmt::Debug> fmt::Debug for Wrapping<T> { @@ -516,11 +517,10 @@ macro_rules! int_impl { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn checked_div(self, other: Self) -> Option<Self> { - if other == 0 { + if other == 0 || (self == Self::min_value() && other == -1) { None } else { - let (a, b) = self.overflowing_div(other); - if b {None} else {Some(a)} + Some(unsafe { intrinsics::unchecked_div(self, other) }) } } @@ -541,11 +541,10 @@ macro_rules! int_impl { #[stable(feature = "wrapping", since = "1.7.0")] #[inline] pub fn checked_rem(self, other: Self) -> Option<Self> { - if other == 0 { + if other == 0 || (self == Self::min_value() && other == -1) { None } else { - let (a, b) = self.overflowing_rem(other); - if b {None} else {Some(a)} + Some(unsafe { intrinsics::unchecked_rem(self, other) }) } } @@ -613,14 +612,12 @@ macro_rules! int_impl { /// Basic usage: /// /// ``` - /// # #![feature(no_panic_abs)] - /// /// use std::i32; /// /// assert_eq!((-5i32).checked_abs(), Some(5)); /// assert_eq!(i32::MIN.checked_abs(), None); /// ``` - #[unstable(feature = "no_panic_abs", issue = "35057")] + #[stable(feature = "no_panic_abs", since = "1.13.0")] #[inline] pub fn checked_abs(self) -> Option<Self> { if self.is_negative() { @@ -895,14 +892,12 @@ macro_rules! int_impl { /// Basic usage: /// /// ``` - /// # #![feature(no_panic_abs)] - /// /// assert_eq!(100i8.wrapping_abs(), 100); /// assert_eq!((-100i8).wrapping_abs(), 100); /// assert_eq!((-128i8).wrapping_abs(), -128); /// assert_eq!((-128i8).wrapping_abs() as u8, 128); /// ``` - #[unstable(feature = "no_panic_abs", issue = "35057")] + #[stable(feature = "no_panic_abs", since = "1.13.0")] #[inline(always)] pub fn wrapping_abs(self) -> Self { if self.is_negative() { @@ -1133,13 +1128,11 @@ macro_rules! int_impl { /// Basic usage: /// /// ``` - /// # #![feature(no_panic_abs)] - /// /// assert_eq!(10i8.overflowing_abs(), (10,false)); /// assert_eq!((-10i8).overflowing_abs(), (10,false)); /// assert_eq!((-128i8).overflowing_abs(), (-128,true)); /// ``` - #[unstable(feature = "no_panic_abs", issue = "35057")] + #[stable(feature = "no_panic_abs", since = "1.13.0")] #[inline] pub fn overflowing_abs(self) -> (Self, bool) { if self.is_negative() { @@ -1694,7 +1687,7 @@ macro_rules! uint_impl { pub fn checked_div(self, other: Self) -> Option<Self> { match other { 0 => None, - other => Some(self / other), + other => Some(unsafe { intrinsics::unchecked_div(self, other) }), } } @@ -1715,7 +1708,7 @@ macro_rules! uint_impl { if other == 0 { None } else { - Some(self % other) + Some(unsafe { intrinsics::unchecked_rem(self, other) }) } } @@ -2211,25 +2204,21 @@ macro_rules! uint_impl { let mut base = self; let mut acc = 1; - let mut prev_base = self; - let mut base_oflo = false; - while exp > 0 { + while exp > 1 { if (exp & 1) == 1 { - if base_oflo { - // ensure overflow occurs in the same manner it - // would have otherwise (i.e. signal any exception - // it would have otherwise). - acc = acc * (prev_base * prev_base); - } else { - acc = acc * base; - } + acc = acc * base; } - prev_base = base; - let (new_base, new_base_oflo) = base.overflowing_mul(base); - base = new_base; - base_oflo = new_base_oflo; exp /= 2; + base = base * base; + } + + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. + if exp == 1 { + acc = acc * base; } + acc } @@ -2405,7 +2394,7 @@ impl usize { /// assert_eq!(nan.classify(), FpCategory::Nan); /// assert_eq!(sub.classify(), FpCategory::Subnormal); /// ``` -#[derive(Copy, Clone, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Debug)] #[stable(feature = "rust1", since = "1.0.0")] pub enum FpCategory { /// "Not a Number", often obtained by dividing by zero. @@ -2414,7 +2403,7 @@ pub enum FpCategory { /// Positive or negative infinity. #[stable(feature = "rust1", since = "1.0.0")] - Infinite , + Infinite, /// Positive or negative zero. #[stable(feature = "rust1", since = "1.0.0")] @@ -2580,7 +2569,7 @@ impl fmt::Display for TryFromIntError { macro_rules! same_sign_from_int_impl { ($storage:ty, $target:ty, $($source:ty),*) => {$( - #[stable(feature = "rust1", since = "1.0.0")] + #[unstable(feature = "try_from", issue = "33417")] impl TryFrom<$source> for $target { type Err = TryFromIntError; @@ -2610,7 +2599,7 @@ same_sign_from_int_impl!(i64, isize, i8, i16, i32, i64, isize); macro_rules! cross_sign_from_int_impl { ($unsigned:ty, $($signed:ty),*) => {$( - #[stable(feature = "rust1", since = "1.0.0")] + #[unstable(feature = "try_from", issue = "33417")] impl TryFrom<$unsigned> for $signed { type Err = TryFromIntError; @@ -2624,7 +2613,7 @@ macro_rules! cross_sign_from_int_impl { } } - #[stable(feature = "rust1", since = "1.0.0")] + #[unstable(feature = "try_from", issue = "33417")] impl TryFrom<$signed> for $unsigned { type Err = TryFromIntError; @@ -2674,8 +2663,7 @@ macro_rules! doit { } doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize } -fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) - -> Result<T, ParseIntError> { +fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, ParseIntError> { use self::IntErrorKind::*; use self::ParseIntError as PIE; @@ -2698,7 +2686,7 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) let (is_positive, digits) = match src[0] { b'+' => (true, &src[1..]), b'-' if is_signed_ty => (false, &src[1..]), - _ => (true, src) + _ => (true, src), }; if digits.is_empty() { @@ -2748,11 +2736,13 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) /// on the primitive integer types, such as [`i8::from_str_radix()`]. /// /// [`i8::from_str_radix()`]: ../../std/primitive.i8.html#method.from_str_radix -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Eq)] #[stable(feature = "rust1", since = "1.0.0")] -pub struct ParseIntError { kind: IntErrorKind } +pub struct ParseIntError { + kind: IntErrorKind, +} -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Eq)] enum IntErrorKind { Empty, InvalidDigit, diff --git a/src/libcore/num/wrapping.rs b/src/libcore/num/wrapping.rs index 4857817e84e..d35c451ac26 100644 --- a/src/libcore/num/wrapping.rs +++ b/src/libcore/num/wrapping.rs @@ -28,7 +28,7 @@ macro_rules! sh_impl_signed { } } - #[stable(feature = "wrapping_impls", since = "1.7.0")] + #[stable(feature = "op_assign_traits", since = "1.8.0")] impl ShlAssign<$f> for Wrapping<$t> { #[inline(always)] fn shl_assign(&mut self, other: $f) { @@ -50,7 +50,7 @@ macro_rules! sh_impl_signed { } } - #[stable(feature = "wrapping_impls", since = "1.7.0")] + #[stable(feature = "op_assign_traits", since = "1.8.0")] impl ShrAssign<$f> for Wrapping<$t> { #[inline(always)] fn shr_assign(&mut self, other: $f) { @@ -72,7 +72,7 @@ macro_rules! sh_impl_unsigned { } } - #[stable(feature = "wrapping_impls", since = "1.7.0")] + #[stable(feature = "op_assign_traits", since = "1.8.0")] impl ShlAssign<$f> for Wrapping<$t> { #[inline(always)] fn shl_assign(&mut self, other: $f) { @@ -90,7 +90,7 @@ macro_rules! sh_impl_unsigned { } } - #[stable(feature = "wrapping_impls", since = "1.7.0")] + #[stable(feature = "op_assign_traits", since = "1.8.0")] impl ShrAssign<$f> for Wrapping<$t> { #[inline(always)] fn shr_assign(&mut self, other: $f) { @@ -310,13 +310,13 @@ mod shift_max { pub const isize: u32 = super::i64; } - pub const i8: u32 = (1 << 3) - 1; + pub const i8: u32 = (1 << 3) - 1; pub const i16: u32 = (1 << 4) - 1; pub const i32: u32 = (1 << 5) - 1; pub const i64: u32 = (1 << 6) - 1; pub use self::platform::isize; - pub const u8: u32 = i8; + pub const u8: u32 = i8; pub const u16: u32 = i16; pub const u32: u32 = i32; pub const u64: u32 = i64; diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index 85a52da332d..62aa57bbbbf 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -14,7 +14,7 @@ //! //! Some of these traits are imported by the prelude, so they are available in //! every Rust program. Only operators backed by traits can be overloaded. For -//! example, the addition operator (`+`) can be overloaded through the `Add` +//! example, the addition operator (`+`) can be overloaded through the [`Add`] //! trait, but since the assignment operator (`=`) has no backing trait, there //! is no way of overloading its semantics. Additionally, this module does not //! provide any mechanism to create new operators. If traitless overloading or @@ -30,17 +30,18 @@ //! contexts involving built-in types, this is usually not a problem. //! However, using these operators in generic code, requires some //! attention if values have to be reused as opposed to letting the operators -//! consume them. One option is to occasionally use `clone()`. +//! consume them. One option is to occasionally use [`clone()`]. //! Another option is to rely on the types involved providing additional //! operator implementations for references. For example, for a user-defined //! type `T` which is supposed to support addition, it is probably a good -//! idea to have both `T` and `&T` implement the traits `Add<T>` and `Add<&T>` -//! so that generic code can be written without unnecessary cloning. +//! idea to have both `T` and `&T` implement the traits [`Add<T>`][`Add`] and +//! [`Add<&T>`][`Add`] so that generic code can be written without unnecessary +//! cloning. //! //! # Examples //! -//! This example creates a `Point` struct that implements `Add` and `Sub`, and -//! then demonstrates adding and subtracting two `Point`s. +//! This example creates a `Point` struct that implements [`Add`] and [`Sub`], +//! and then demonstrates adding and subtracting two `Point`s. //! //! ```rust //! use std::ops::{Add, Sub}; @@ -75,18 +76,14 @@ //! See the documentation for each trait for an example implementation. //! //! The [`Fn`], [`FnMut`], and [`FnOnce`] traits are implemented by types that can be -//! invoked like functions. Note that `Fn` takes `&self`, `FnMut` takes `&mut -//! self` and `FnOnce` takes `self`. These correspond to the three kinds of +//! invoked like functions. Note that [`Fn`] takes `&self`, [`FnMut`] takes `&mut +//! self` and [`FnOnce`] takes `self`. These correspond to the three kinds of //! methods that can be invoked on an instance: call-by-reference, //! call-by-mutable-reference, and call-by-value. The most common use of these //! traits is to act as bounds to higher-level functions that take functions or //! closures as arguments. //! -//! [`Fn`]: trait.Fn.html -//! [`FnMut`]: trait.FnMut.html -//! [`FnOnce`]: trait.FnOnce.html -//! -//! Taking a `Fn` as a parameter: +//! Taking a [`Fn`] as a parameter: //! //! ```rust //! fn call_with_one<F>(func: F) -> usize @@ -99,7 +96,7 @@ //! assert_eq!(call_with_one(double), 2); //! ``` //! -//! Taking a `FnMut` as a parameter: +//! Taking a [`FnMut`] as a parameter: //! //! ```rust //! fn do_twice<F>(mut func: F) @@ -118,7 +115,7 @@ //! assert_eq!(x, 5); //! ``` //! -//! Taking a `FnOnce` as a parameter: +//! Taking a [`FnOnce`] as a parameter: //! //! ```rust //! fn consume_with_relish<F>(func: F) @@ -140,6 +137,13 @@ //! //! // `consume_and_return_x` can no longer be invoked at this point //! ``` +//! +//! [`Fn`]: trait.Fn.html +//! [`FnMut`]: trait.FnMut.html +//! [`FnOnce`]: trait.FnOnce.html +//! [`Add`]: trait.Add.html +//! [`Sub`]: trait.Sub.html +//! [`clone()`]: ../clone/trait.Clone.html#tymethod.clone #![stable(feature = "rust1", since = "1.0.0")] @@ -1641,7 +1645,7 @@ rem_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } #[lang = "bitand_assign"] #[stable(feature = "op_assign_traits", since = "1.8.0")] pub trait BitAndAssign<Rhs=Self> { - /// The method for the `&` operator + /// The method for the `&=` operator #[stable(feature = "op_assign_traits", since = "1.8.0")] fn bitand_assign(&mut self, Rhs); } @@ -1873,12 +1877,20 @@ macro_rules! shr_assign_impl_all { shr_assign_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize } /// The `Index` trait is used to specify the functionality of indexing operations -/// like `arr[idx]` when used in an immutable context. +/// like `container[index]` when used in an immutable context. +/// +/// `container[index]` is actually syntactic sugar for `*container.index(index)`, +/// but only when used as an immutable value. If a mutable value is requested, +/// [`IndexMut`] is used instead. This allows nice things such as +/// `let value = v[index]` if `value` implements [`Copy`]. +/// +/// [`IndexMut`]: ../../std/ops/trait.IndexMut.html +/// [`Copy`]: ../../std/marker/trait.Copy.html /// /// # Examples /// -/// This example implements `Index` on a read-only `NucleotideCount` container, -/// enabling individual counts to be retrieved with index syntax. +/// The following example implements `Index` on a read-only `NucleotideCount` +/// container, enabling individual counts to be retrieved with index syntax. /// /// ``` /// use std::ops::Index; @@ -1924,50 +1936,91 @@ pub trait Index<Idx: ?Sized> { #[stable(feature = "rust1", since = "1.0.0")] type Output: ?Sized; - /// The method for the indexing (`Foo[Bar]`) operation + /// The method for the indexing (`container[index]`) operation #[stable(feature = "rust1", since = "1.0.0")] fn index(&self, index: Idx) -> &Self::Output; } /// The `IndexMut` trait is used to specify the functionality of indexing -/// operations like `arr[idx]`, when used in a mutable context. +/// operations like `container[index]` when used in a mutable context. +/// +/// `container[index]` is actually syntactic sugar for +/// `*container.index_mut(index)`, but only when used as a mutable value. If +/// an immutable value is requested, the [`Index`] trait is used instead. This +/// allows nice things such as `v[index] = value` if `value` implements [`Copy`]. +/// +/// [`Index`]: ../../std/ops/trait.Index.html +/// [`Copy`]: ../../std/marker/trait.Copy.html /// /// # Examples /// -/// A trivial implementation of `IndexMut`. When `Foo[Bar]` happens, it ends up -/// calling `index_mut`, and therefore, `main` prints `Indexing!`. +/// A very simple implementation of a `Balance` struct that has two sides, where +/// each can be indexed mutably and immutably. /// /// ``` -/// use std::ops::{Index, IndexMut}; +/// use std::ops::{Index,IndexMut}; /// -/// #[derive(Copy, Clone)] -/// struct Foo; -/// struct Bar; +/// #[derive(Debug)] +/// enum Side { +/// Left, +/// Right, +/// } +/// +/// #[derive(Debug, PartialEq)] +/// enum Weight { +/// Kilogram(f32), +/// Pound(f32), +/// } /// -/// impl Index<Bar> for Foo { -/// type Output = Foo; +/// struct Balance { +/// pub left: Weight, +/// pub right:Weight, +/// } +/// +/// impl Index<Side> for Balance { +/// type Output = Weight; /// -/// fn index<'a>(&'a self, _index: Bar) -> &'a Foo { -/// self +/// fn index<'a>(&'a self, index: Side) -> &'a Weight { +/// println!("Accessing {:?}-side of balance immutably", index); +/// match index { +/// Side::Left => &self.left, +/// Side::Right => &self.right, +/// } /// } /// } /// -/// impl IndexMut<Bar> for Foo { -/// fn index_mut<'a>(&'a mut self, _index: Bar) -> &'a mut Foo { -/// println!("Indexing!"); -/// self +/// impl IndexMut<Side> for Balance { +/// fn index_mut<'a>(&'a mut self, index: Side) -> &'a mut Weight { +/// println!("Accessing {:?}-side of balance mutably", index); +/// match index { +/// Side::Left => &mut self.left, +/// Side::Right => &mut self.right, +/// } /// } /// } /// /// fn main() { -/// &mut Foo[Bar]; +/// let mut balance = Balance { +/// right: Weight::Kilogram(2.5), +/// left: Weight::Pound(1.5), +/// }; +/// +/// // In this case balance[Side::Right] is sugar for +/// // *balance.index(Side::Right), since we are only reading +/// // balance[Side::Right], not writing it. +/// assert_eq!(balance[Side::Right],Weight::Kilogram(2.5)); +/// +/// // However in this case balance[Side::Left] is sugar for +/// // *balance.index_mut(Side::Left), since we are writing +/// // balance[Side::Left]. +/// balance[Side::Left] = Weight::Kilogram(3.0); /// } /// ``` #[lang = "index_mut"] #[rustc_on_unimplemented = "the type `{Self}` cannot be mutably indexed by `{Idx}`"] #[stable(feature = "rust1", since = "1.0.0")] pub trait IndexMut<Idx: ?Sized>: Index<Idx> { - /// The method for the indexing (`Foo[Bar]`) operation + /// The method for the mutable indexing (`container[index]`) operation #[stable(feature = "rust1", since = "1.0.0")] fn index_mut(&mut self, index: Idx) -> &mut Self::Output; } diff --git a/src/libcore/option.rs b/src/libcore/option.rs index b9fb2dc90c7..a74979911d3 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -296,16 +296,14 @@ impl<T> Option<T> { /// Moves the value `v` out of the `Option<T>` if it is `Some(v)`. /// - /// # Panics - /// - /// Panics if the self value equals `None`. - /// - /// # Safety note - /// /// In general, because this function may panic, its use is discouraged. /// Instead, prefer to use pattern matching and handle the `None` /// case explicitly. /// + /// # Panics + /// + /// Panics if the self value equals `None`. + /// /// # Examples /// /// ``` @@ -916,12 +914,12 @@ impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> { /// ``` /// use std::u16; /// - /// let v = vec!(1, 2); + /// let v = vec![1, 2]; /// let res: Option<Vec<u16>> = v.iter().map(|&x: &u16| /// if x == u16::MAX { None } /// else { Some(x + 1) } /// ).collect(); - /// assert!(res == Some(vec!(2, 3))); + /// assert!(res == Some(vec![2, 3])); /// ``` #[inline] fn from_iter<I: IntoIterator<Item=Option<A>>>(iter: I) -> Option<V> { diff --git a/src/libcore/prelude/v1.rs b/src/libcore/prelude/v1.rs index 75db6fceab9..3fa6a97d4cd 100644 --- a/src/libcore/prelude/v1.rs +++ b/src/libcore/prelude/v1.rs @@ -18,36 +18,50 @@ // Reexported core operators #[stable(feature = "core_prelude", since = "1.4.0")] -#[doc(no_inline)] pub use marker::{Copy, Send, Sized, Sync}; +#[doc(no_inline)] +pub use marker::{Copy, Send, Sized, Sync}; #[stable(feature = "core_prelude", since = "1.4.0")] -#[doc(no_inline)] pub use ops::{Drop, Fn, FnMut, FnOnce}; +#[doc(no_inline)] +pub use ops::{Drop, Fn, FnMut, FnOnce}; // Reexported functions #[stable(feature = "core_prelude", since = "1.4.0")] -#[doc(no_inline)] pub use mem::drop; +#[doc(no_inline)] +pub use mem::drop; // Reexported types and traits #[stable(feature = "core_prelude", since = "1.4.0")] -#[doc(no_inline)] pub use clone::Clone; +#[doc(no_inline)] +pub use clone::Clone; #[stable(feature = "core_prelude", since = "1.4.0")] -#[doc(no_inline)] pub use cmp::{PartialEq, PartialOrd, Eq, Ord}; +#[doc(no_inline)] +pub use cmp::{PartialEq, PartialOrd, Eq, Ord}; #[stable(feature = "core_prelude", since = "1.4.0")] -#[doc(no_inline)] pub use convert::{AsRef, AsMut, Into, From}; +#[doc(no_inline)] +pub use convert::{AsRef, AsMut, Into, From}; #[stable(feature = "core_prelude", since = "1.4.0")] -#[doc(no_inline)] pub use default::Default; +#[doc(no_inline)] +pub use default::Default; #[stable(feature = "core_prelude", since = "1.4.0")] -#[doc(no_inline)] pub use iter::{Iterator, Extend, IntoIterator}; +#[doc(no_inline)] +pub use iter::{Iterator, Extend, IntoIterator}; #[stable(feature = "core_prelude", since = "1.4.0")] -#[doc(no_inline)] pub use iter::{DoubleEndedIterator, ExactSizeIterator}; +#[doc(no_inline)] +pub use iter::{DoubleEndedIterator, ExactSizeIterator}; #[stable(feature = "core_prelude", since = "1.4.0")] -#[doc(no_inline)] pub use option::Option::{self, Some, None}; +#[doc(no_inline)] +pub use option::Option::{self, Some, None}; #[stable(feature = "core_prelude", since = "1.4.0")] -#[doc(no_inline)] pub use result::Result::{self, Ok, Err}; +#[doc(no_inline)] +pub use result::Result::{self, Ok, Err}; // Reexported extension traits for primitive types #[stable(feature = "core_prelude", since = "1.4.0")] -#[doc(no_inline)] pub use slice::SliceExt; +#[doc(no_inline)] +pub use slice::SliceExt; #[stable(feature = "core_prelude", since = "1.4.0")] -#[doc(no_inline)] pub use str::StrExt; +#[doc(no_inline)] +pub use str::StrExt; #[stable(feature = "core_prelude", since = "1.4.0")] -#[doc(no_inline)] pub use char::CharExt; +#[doc(no_inline)] +pub use char::CharExt; diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 69682652a6a..f0510422a07 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -761,7 +761,7 @@ impl<T:?Sized> Deref for Unique<T> { } } -#[stable(feature = "rust1", since = "1.0.0")] +#[unstable(feature = "unique", issue = "27730")] impl<T> fmt::Pointer for Unique<T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Pointer::fmt(&*self.pointer, f) diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 96845259299..3d34f620067 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -792,6 +792,44 @@ impl<T: fmt::Debug, E> Result<T, E> { } } +impl<T: Default, E> Result<T, E> { + /// Returns the contained value or a default + /// + /// Consumes the `self` argument then, if `Ok`, returns the contained + /// value, otherwise if `Err`, returns the default value for that + /// type. + /// + /// # Examples + /// + /// Convert a string to an integer, turning poorly-formed strings + /// into 0 (the default value for integers). [`parse`] converts + /// a string to any other type that implements [`FromStr`], returning an + /// `Err` on error. + /// + /// ``` + /// #![feature(result_unwrap_or_default)] + /// + /// let good_year_from_input = "1909"; + /// let bad_year_from_input = "190blarg"; + /// let good_year = good_year_from_input.parse().unwrap_or_default(); + /// let bad_year = bad_year_from_input.parse().unwrap_or_default(); + /// + /// assert_eq!(1909, good_year); + /// assert_eq!(0, bad_year); + /// + /// [`parse`]: ../../std/primitive.str.html#method.parse + /// [`FromStr`]: ../../std/str/trait.FromStr.html + /// ``` + #[inline] + #[unstable(feature = "result_unwrap_or_default", issue = "0")] + pub fn unwrap_or_default(self) -> T { + match self { + Ok(x) => x, + Err(_) => Default::default(), + } + } +} + // This is a separate function to reduce the code size of the methods #[inline(never)] #[cold] @@ -977,12 +1015,12 @@ impl<A, E, V: FromIterator<A>> FromIterator<Result<A, E>> for Result<V, E> { /// ``` /// use std::u32; /// - /// let v = vec!(1, 2); + /// let v = vec![1, 2]; /// let res: Result<Vec<u32>, &'static str> = v.iter().map(|&x: &u32| /// if x == u32::MAX { Err("Overflow!") } /// else { Ok(x + 1) } /// ).collect(); - /// assert!(res == Ok(vec!(2, 3))); + /// assert!(res == Ok(vec![2, 3])); /// ``` #[inline] fn from_iter<I: IntoIterator<Item=Result<A, E>>>(iter: I) -> Result<V, E> { @@ -1008,6 +1046,11 @@ impl<A, E, V: FromIterator<A>> FromIterator<Result<A, E>> for Result<V, E> { None => None, } } + + fn size_hint(&self) -> (usize, Option<usize>) { + let (_min, max) = self.iter.size_hint(); + (0, max) + } } let mut adapter = Adapter { iter: iter.into_iter(), err: None }; diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index d1df56905df..31be404ba90 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -1968,6 +1968,7 @@ unsafe impl<'a, T> TrustedRandomAccess for Iter<'a, T> { unsafe fn get_unchecked(&mut self, i: usize) -> &'a T { &*self.ptr.offset(i as isize) } + fn may_have_side_effect() -> bool { false } } #[doc(hidden)] @@ -1975,4 +1976,5 @@ unsafe impl<'a, T> TrustedRandomAccess for IterMut<'a, T> { unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut T { &mut *self.ptr.offset(i as isize) } + fn may_have_side_effect() -> bool { false } } diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 1f1ae6f12ab..d63d2d64fe1 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -101,7 +101,7 @@ impl FromStr for bool { } /// An error returned when parsing a `bool` from a string fails. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Eq)] #[stable(feature = "rust1", since = "1.0.0")] pub struct ParseBoolError { _priv: () } diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index f5f37be52de..657f7e7992f 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -95,7 +95,7 @@ pub struct AtomicBool { #[cfg(target_has_atomic = "8")] #[stable(feature = "rust1", since = "1.0.0")] impl Default for AtomicBool { - /// Creates an `AtomicBool` initialised as false. + /// Creates an `AtomicBool` initialized to `false`. fn default() -> Self { Self::new(false) } @@ -277,7 +277,9 @@ impl AtomicBool { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn store(&self, val: bool, order: Ordering) { - unsafe { atomic_store(self.v.get(), val as u8, order); } + unsafe { + atomic_store(self.v.get(), val as u8, order); + } } /// Stores a value into the bool, returning the old value. @@ -366,9 +368,11 @@ impl AtomicBool { current: bool, new: bool, success: Ordering, - failure: Ordering) -> Result<bool, bool> { - match unsafe { atomic_compare_exchange(self.v.get(), current as u8, new as u8, - success, failure) } { + failure: Ordering) + -> Result<bool, bool> { + match unsafe { + atomic_compare_exchange(self.v.get(), current as u8, new as u8, success, failure) + } { Ok(x) => Ok(x != 0), Err(x) => Err(x != 0), } @@ -409,9 +413,11 @@ impl AtomicBool { current: bool, new: bool, success: Ordering, - failure: Ordering) -> Result<bool, bool> { - match unsafe { atomic_compare_exchange_weak(self.v.get(), current as u8, new as u8, - success, failure) } { + failure: Ordering) + -> Result<bool, bool> { + match unsafe { + atomic_compare_exchange_weak(self.v.get(), current as u8, new as u8, success, failure) + } { Ok(x) => Ok(x != 0), Err(x) => Err(x != 0), } @@ -632,9 +638,7 @@ impl<T> AtomicPtr<T> { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn load(&self, order: Ordering) -> *mut T { - unsafe { - atomic_load(self.p.get() as *mut usize, order) as *mut T - } + unsafe { atomic_load(self.p.get() as *mut usize, order) as *mut T } } /// Stores a value into the pointer. @@ -660,7 +664,9 @@ impl<T> AtomicPtr<T> { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn store(&self, ptr: *mut T, order: Ordering) { - unsafe { atomic_store(self.p.get() as *mut usize, ptr as usize, order); } + unsafe { + atomic_store(self.p.get() as *mut usize, ptr as usize, order); + } } /// Stores a value into the pointer, returning the old value. @@ -745,7 +751,8 @@ impl<T> AtomicPtr<T> { current: *mut T, new: *mut T, success: Ordering, - failure: Ordering) -> Result<*mut T, *mut T> { + failure: Ordering) + -> Result<*mut T, *mut T> { unsafe { let res = atomic_compare_exchange(self.p.get() as *mut usize, current as usize, @@ -794,7 +801,8 @@ impl<T> AtomicPtr<T> { current: *mut T, new: *mut T, success: Ordering, - failure: Ordering) -> Result<*mut T, *mut T> { + failure: Ordering) + -> Result<*mut T, *mut T> { unsafe { let res = atomic_compare_exchange_weak(self.p.get() as *mut usize, current as usize, @@ -1266,9 +1274,9 @@ fn strongest_failure_ordering(order: Ordering) -> Ordering { match order { Release => Relaxed, Relaxed => Relaxed, - SeqCst => SeqCst, + SeqCst => SeqCst, Acquire => Acquire, - AcqRel => Acquire, + AcqRel => Acquire, } } @@ -1277,9 +1285,9 @@ unsafe fn atomic_store<T>(dst: *mut T, val: T, order: Ordering) { match order { Release => intrinsics::atomic_store_rel(dst, val), Relaxed => intrinsics::atomic_store_relaxed(dst, val), - SeqCst => intrinsics::atomic_store(dst, val), + SeqCst => intrinsics::atomic_store(dst, val), Acquire => panic!("there is no such thing as an acquire store"), - AcqRel => panic!("there is no such thing as an acquire/release store"), + AcqRel => panic!("there is no such thing as an acquire/release store"), } } @@ -1288,9 +1296,9 @@ unsafe fn atomic_load<T>(dst: *const T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_load_acq(dst), Relaxed => intrinsics::atomic_load_relaxed(dst), - SeqCst => intrinsics::atomic_load(dst), + SeqCst => intrinsics::atomic_load(dst), Release => panic!("there is no such thing as a release load"), - AcqRel => panic!("there is no such thing as an acquire/release load"), + AcqRel => panic!("there is no such thing as an acquire/release load"), } } @@ -1299,9 +1307,9 @@ unsafe fn atomic_swap<T>(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_xchg_acq(dst, val), Release => intrinsics::atomic_xchg_rel(dst, val), - AcqRel => intrinsics::atomic_xchg_acqrel(dst, val), + AcqRel => intrinsics::atomic_xchg_acqrel(dst, val), Relaxed => intrinsics::atomic_xchg_relaxed(dst, val), - SeqCst => intrinsics::atomic_xchg(dst, val) + SeqCst => intrinsics::atomic_xchg(dst, val), } } @@ -1311,9 +1319,9 @@ unsafe fn atomic_add<T>(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_xadd_acq(dst, val), Release => intrinsics::atomic_xadd_rel(dst, val), - AcqRel => intrinsics::atomic_xadd_acqrel(dst, val), + AcqRel => intrinsics::atomic_xadd_acqrel(dst, val), Relaxed => intrinsics::atomic_xadd_relaxed(dst, val), - SeqCst => intrinsics::atomic_xadd(dst, val) + SeqCst => intrinsics::atomic_xadd(dst, val), } } @@ -1323,9 +1331,9 @@ unsafe fn atomic_sub<T>(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_xsub_acq(dst, val), Release => intrinsics::atomic_xsub_rel(dst, val), - AcqRel => intrinsics::atomic_xsub_acqrel(dst, val), + AcqRel => intrinsics::atomic_xsub_acqrel(dst, val), Relaxed => intrinsics::atomic_xsub_relaxed(dst, val), - SeqCst => intrinsics::atomic_xsub(dst, val) + SeqCst => intrinsics::atomic_xsub(dst, val), } } @@ -1334,26 +1342,23 @@ unsafe fn atomic_compare_exchange<T>(dst: *mut T, old: T, new: T, success: Ordering, - failure: Ordering) -> Result<T, T> { + failure: Ordering) + -> Result<T, T> { let (val, ok) = match (success, failure) { (Acquire, Acquire) => intrinsics::atomic_cxchg_acq(dst, old, new), (Release, Relaxed) => intrinsics::atomic_cxchg_rel(dst, old, new), - (AcqRel, Acquire) => intrinsics::atomic_cxchg_acqrel(dst, old, new), + (AcqRel, Acquire) => intrinsics::atomic_cxchg_acqrel(dst, old, new), (Relaxed, Relaxed) => intrinsics::atomic_cxchg_relaxed(dst, old, new), - (SeqCst, SeqCst) => intrinsics::atomic_cxchg(dst, old, new), + (SeqCst, SeqCst) => intrinsics::atomic_cxchg(dst, old, new), (Acquire, Relaxed) => intrinsics::atomic_cxchg_acq_failrelaxed(dst, old, new), - (AcqRel, Relaxed) => intrinsics::atomic_cxchg_acqrel_failrelaxed(dst, old, new), - (SeqCst, Relaxed) => intrinsics::atomic_cxchg_failrelaxed(dst, old, new), - (SeqCst, Acquire) => intrinsics::atomic_cxchg_failacq(dst, old, new), + (AcqRel, Relaxed) => intrinsics::atomic_cxchg_acqrel_failrelaxed(dst, old, new), + (SeqCst, Relaxed) => intrinsics::atomic_cxchg_failrelaxed(dst, old, new), + (SeqCst, Acquire) => intrinsics::atomic_cxchg_failacq(dst, old, new), (_, AcqRel) => panic!("there is no such thing as an acquire/release failure ordering"), (_, Release) => panic!("there is no such thing as a release failure ordering"), _ => panic!("a failure ordering can't be stronger than a success ordering"), }; - if ok { - Ok(val) - } else { - Err(val) - } + if ok { Ok(val) } else { Err(val) } } #[inline] @@ -1361,26 +1366,23 @@ unsafe fn atomic_compare_exchange_weak<T>(dst: *mut T, old: T, new: T, success: Ordering, - failure: Ordering) -> Result<T, T> { + failure: Ordering) + -> Result<T, T> { let (val, ok) = match (success, failure) { (Acquire, Acquire) => intrinsics::atomic_cxchgweak_acq(dst, old, new), (Release, Relaxed) => intrinsics::atomic_cxchgweak_rel(dst, old, new), - (AcqRel, Acquire) => intrinsics::atomic_cxchgweak_acqrel(dst, old, new), + (AcqRel, Acquire) => intrinsics::atomic_cxchgweak_acqrel(dst, old, new), (Relaxed, Relaxed) => intrinsics::atomic_cxchgweak_relaxed(dst, old, new), - (SeqCst, SeqCst) => intrinsics::atomic_cxchgweak(dst, old, new), + (SeqCst, SeqCst) => intrinsics::atomic_cxchgweak(dst, old, new), (Acquire, Relaxed) => intrinsics::atomic_cxchgweak_acq_failrelaxed(dst, old, new), - (AcqRel, Relaxed) => intrinsics::atomic_cxchgweak_acqrel_failrelaxed(dst, old, new), - (SeqCst, Relaxed) => intrinsics::atomic_cxchgweak_failrelaxed(dst, old, new), - (SeqCst, Acquire) => intrinsics::atomic_cxchgweak_failacq(dst, old, new), + (AcqRel, Relaxed) => intrinsics::atomic_cxchgweak_acqrel_failrelaxed(dst, old, new), + (SeqCst, Relaxed) => intrinsics::atomic_cxchgweak_failrelaxed(dst, old, new), + (SeqCst, Acquire) => intrinsics::atomic_cxchgweak_failacq(dst, old, new), (_, AcqRel) => panic!("there is no such thing as an acquire/release failure ordering"), (_, Release) => panic!("there is no such thing as a release failure ordering"), _ => panic!("a failure ordering can't be stronger than a success ordering"), }; - if ok { - Ok(val) - } else { - Err(val) - } + if ok { Ok(val) } else { Err(val) } } #[inline] @@ -1388,9 +1390,9 @@ unsafe fn atomic_and<T>(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_and_acq(dst, val), Release => intrinsics::atomic_and_rel(dst, val), - AcqRel => intrinsics::atomic_and_acqrel(dst, val), + AcqRel => intrinsics::atomic_and_acqrel(dst, val), Relaxed => intrinsics::atomic_and_relaxed(dst, val), - SeqCst => intrinsics::atomic_and(dst, val) + SeqCst => intrinsics::atomic_and(dst, val), } } @@ -1399,9 +1401,9 @@ unsafe fn atomic_or<T>(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_or_acq(dst, val), Release => intrinsics::atomic_or_rel(dst, val), - AcqRel => intrinsics::atomic_or_acqrel(dst, val), + AcqRel => intrinsics::atomic_or_acqrel(dst, val), Relaxed => intrinsics::atomic_or_relaxed(dst, val), - SeqCst => intrinsics::atomic_or(dst, val) + SeqCst => intrinsics::atomic_or(dst, val), } } @@ -1410,9 +1412,9 @@ unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_xor_acq(dst, val), Release => intrinsics::atomic_xor_rel(dst, val), - AcqRel => intrinsics::atomic_xor_acqrel(dst, val), + AcqRel => intrinsics::atomic_xor_acqrel(dst, val), Relaxed => intrinsics::atomic_xor_relaxed(dst, val), - SeqCst => intrinsics::atomic_xor(dst, val) + SeqCst => intrinsics::atomic_xor(dst, val), } } @@ -1443,9 +1445,9 @@ pub fn fence(order: Ordering) { match order { Acquire => intrinsics::atomic_fence_acq(), Release => intrinsics::atomic_fence_rel(), - AcqRel => intrinsics::atomic_fence_acqrel(), - SeqCst => intrinsics::atomic_fence(), - Relaxed => panic!("there is no such thing as a relaxed fence") + AcqRel => intrinsics::atomic_fence_acqrel(), + SeqCst => intrinsics::atomic_fence(), + Relaxed => panic!("there is no such thing as a relaxed fence"), } } } |
