diff --git a/Cargo.lock b/Cargo.lock index bcb369d155462..39ecc880097e3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2257,7 +2257,7 @@ dependencies = [ "rls-analysis 0.16.12 (registry+https://github.com/rust-lang/crates.io-index)", "rls-blacklist 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "rls-data 0.18.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-rustc 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-rustc 0.6.0", "rls-span 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "rls-vfs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2310,8 +2310,7 @@ dependencies = [ [[package]] name = "rls-rustc" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +version = "0.6.0" [[package]] name = "rls-span" @@ -2748,7 +2747,7 @@ version = "0.0.0" dependencies = [ "graphviz 0.0.0", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_data_structures 0.0.0", "rustc_fs_util 0.0.0", @@ -2779,7 +2778,7 @@ dependencies = [ "rustc_resolve 0.0.0", "rustc_traits 0.0.0", "rustc_typeck 0.0.0", - "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serialize 0.0.0", "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "syntax 0.0.0", @@ -4210,7 +4209,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rls-analysis 0.16.12 (registry+https://github.com/rust-lang/crates.io-index)" = "ae18d8ad01dec3b2014f4d7ae3c607d7adbcff79e5d3b48ea42ea71c10d43a71" "checksum rls-blacklist 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b8ce1fdac03e138c4617ff87b194e1ff57a39bb985a044ccbd8673d30701e411" "checksum rls-data 0.18.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5f80b84551b32e26affaf7f12374913b5061730c0dcd185d9e8fa5a15e36e65c" -"checksum rls-rustc 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9dba7390427aefa953608429701e3665192ca810ba8ae09301e001b7c7bed0" "checksum rls-span 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "33d66f1d6c6ccd5c98029f162544131698f6ebb61d8c697681cac409dcd08805" "checksum rls-vfs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "72d56425bd5aa86d9d4372b76f0381d3b4bda9c0220e71956c9fcc929f45c1f1" "checksum rustc-ap-arena 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8be999235b541fc8eb54901b66e899a06076709ac5f53d6b2c5c59d29ad54780" diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index eb1a2a59fa3c5..ffd23e72e80a6 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -405,7 +405,8 @@ impl<'a> Builder<'a> { test::Miri, test::Clippy, test::CompiletestTest, - test::RustdocJS, + test::RustdocJSStd, + test::RustdocJSNotStd, test::RustdocTheme, // Run bootstrap close to the end as it's unlikely to fail test::Bootstrap, diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 51412f79c3d0c..b7323b2eadc3d 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -574,22 +574,22 @@ impl Step for RustdocTheme { } #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct RustdocJS { +pub struct RustdocJSStd { pub host: Interned, pub target: Interned, } -impl Step for RustdocJS { +impl Step for RustdocJSStd { type Output = (); const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.path("src/test/rustdoc-js") + run.path("src/test/rustdoc-js-std") } fn make_run(run: RunConfig<'_>) { - run.builder.ensure(RustdocJS { + run.builder.ensure(RustdocJSStd { host: run.host, target: run.target, }); @@ -598,12 +598,55 @@ impl Step for RustdocJS { fn run(self, builder: &Builder<'_>) { if let Some(ref nodejs) = builder.config.nodejs { let mut command = Command::new(nodejs); - command.args(&["src/tools/rustdoc-js/tester.js", &*self.host]); + command.args(&["src/tools/rustdoc-js-std/tester.js", &*self.host]); builder.ensure(crate::doc::Std { target: self.target, stage: builder.top_stage, }); builder.run(&mut command); + } else { + builder.info( + "No nodejs found, skipping \"src/test/rustdoc-js-std\" tests" + ); + } + } +} + +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct RustdocJSNotStd { + pub host: Interned, + pub target: Interned, + pub compiler: Compiler, +} + +impl Step for RustdocJSNotStd { + type Output = (); + const DEFAULT: bool = true; + const ONLY_HOSTS: bool = true; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.path("src/test/rustdoc-js") + } + + fn make_run(run: RunConfig<'_>) { + let compiler = run.builder.compiler(run.builder.top_stage, run.host); + run.builder.ensure(RustdocJSNotStd { + host: run.host, + target: run.target, + compiler, + }); + } + + fn run(self, builder: &Builder<'_>) { + if builder.config.nodejs.is_some() { + builder.ensure(Compiletest { + compiler: self.compiler, + target: self.target, + mode: "js-doc-test", + suite: "rustdoc-js", + path: None, + compare_mode: None, + }); } else { builder.info( "No nodejs found, skipping \"src/test/rustdoc-js\" tests" @@ -990,12 +1033,13 @@ impl Step for Compiletest { .arg(builder.sysroot_libdir(compiler, target)); cmd.arg("--rustc-path").arg(builder.rustc(compiler)); - let is_rustdoc_ui = suite.ends_with("rustdoc-ui"); + let is_rustdoc = suite.ends_with("rustdoc-ui") || suite.ends_with("rustdoc-js"); // Avoid depending on rustdoc when we don't need it. if mode == "rustdoc" || (mode == "run-make" && suite.ends_with("fulldeps")) - || (mode == "ui" && is_rustdoc_ui) + || (mode == "ui" && is_rustdoc) + || mode == "js-doc-test" { cmd.arg("--rustdoc-path") .arg(builder.rustdoc(compiler.host)); @@ -1029,12 +1073,12 @@ impl Step for Compiletest { cmd.arg("--nodejs").arg(nodejs); } - let mut flags = if is_rustdoc_ui { + let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] }; - if !is_rustdoc_ui { + if !is_rustdoc { if builder.config.rust_optimize_tests { flags.push("-O".to_string()); } diff --git a/src/ci/docker/i686-gnu/Dockerfile b/src/ci/docker/i686-gnu/Dockerfile index daa24e0e8186d..17441ddb4546b 100644 --- a/src/ci/docker/i686-gnu/Dockerfile +++ b/src/ci/docker/i686-gnu/Dockerfile @@ -18,4 +18,10 @@ COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu -ENV SCRIPT python2.7 ../x.py test +# Exclude some tests that are unlikely to be platform specific, to speed up +# this slow job. +ENV SCRIPT python2.7 ../x.py test \ + --exclude src/bootstrap \ + --exclude src/test/rustdoc-js \ + --exclude src/tools/error_index_generator \ + --exclude src/tools/linkchecker diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 74325a69e15ef..9bce142b483f2 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -489,7 +489,7 @@ impl From> for Pin> { } #[stable(feature = "box_from_slice", since = "1.17.0")] -impl<'a, T: Copy> From<&'a [T]> for Box<[T]> { +impl From<&[T]> for Box<[T]> { /// Converts a `&[T]` into a `Box<[T]>` /// /// This conversion allocates on the heap @@ -503,7 +503,7 @@ impl<'a, T: Copy> From<&'a [T]> for Box<[T]> { /// /// println!("{:?}", boxed_slice); /// ``` - fn from(slice: &'a [T]) -> Box<[T]> { + fn from(slice: &[T]) -> Box<[T]> { let mut boxed = unsafe { RawVec::with_capacity(slice.len()).into_box() }; boxed.copy_from_slice(slice); boxed @@ -511,7 +511,7 @@ impl<'a, T: Copy> From<&'a [T]> for Box<[T]> { } #[stable(feature = "box_from_slice", since = "1.17.0")] -impl<'a> From<&'a str> for Box { +impl From<&str> for Box { /// Converts a `&str` into a `Box` /// /// This conversion allocates on the heap @@ -523,7 +523,7 @@ impl<'a> From<&'a str> for Box { /// println!("{}", boxed); /// ``` #[inline] - fn from(s: &'a str) -> Box { + fn from(s: &str) -> Box { unsafe { from_boxed_utf8_unchecked(Box::from(s.as_bytes())) } } } diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 12f75d84211e6..68eecd97ea11a 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -1145,7 +1145,7 @@ impl From for Rc { } #[stable(feature = "shared_from_slice", since = "1.21.0")] -impl<'a, T: Clone> From<&'a [T]> for Rc<[T]> { +impl From<&[T]> for Rc<[T]> { #[inline] fn from(v: &[T]) -> Rc<[T]> { >::from_slice(v) @@ -1153,7 +1153,7 @@ impl<'a, T: Clone> From<&'a [T]> for Rc<[T]> { } #[stable(feature = "shared_from_slice", since = "1.21.0")] -impl<'a> From<&'a str> for Rc { +impl From<&str> for Rc { #[inline] fn from(v: &str) -> Rc { let rc = Rc::<[u8]>::from(v.as_bytes()); diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index b714df5d36b6a..a3e2098695f70 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -2172,9 +2172,9 @@ impl AsRef<[u8]> for String { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a> From<&'a str> for String { +impl From<&str> for String { #[inline] - fn from(s: &'a str) -> String { + fn from(s: &str) -> String { s.to_owned() } } diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index adcd3d84f4832..cd62c3e05244c 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -2182,25 +2182,25 @@ impl AsMut<[T]> for Vec { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T: Clone> From<&'a [T]> for Vec { +impl From<&[T]> for Vec { #[cfg(not(test))] - fn from(s: &'a [T]) -> Vec { + fn from(s: &[T]) -> Vec { s.to_vec() } #[cfg(test)] - fn from(s: &'a [T]) -> Vec { + fn from(s: &[T]) -> Vec { crate::slice::to_vec(s) } } #[stable(feature = "vec_from_mut", since = "1.19.0")] -impl<'a, T: Clone> From<&'a mut [T]> for Vec { +impl From<&mut [T]> for Vec { #[cfg(not(test))] - fn from(s: &'a mut [T]) -> Vec { + fn from(s: &mut [T]) -> Vec { s.to_vec() } #[cfg(test)] - fn from(s: &'a mut [T]) -> Vec { + fn from(s: &mut [T]) -> Vec { crate::slice::to_vec(s) } } @@ -2231,8 +2231,8 @@ impl From> for Box<[T]> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a> From<&'a str> for Vec { - fn from(s: &'a str) -> Vec { +impl From<&str> for Vec { + fn from(s: &str) -> Vec { From::from(s.as_bytes()) } } diff --git a/src/libcore/array.rs b/src/libcore/array.rs index 9c6ecc4350246..dcd9ce6dad756 100644 --- a/src/libcore/array.rs +++ b/src/libcore/array.rs @@ -139,7 +139,7 @@ macro_rules! array_impls { } #[stable(feature = "try_from", since = "1.34.0")] - impl<'a, T> TryFrom<&'a [T]> for [T; $N] where T: Copy { + impl TryFrom<&[T]> for [T; $N] where T: Copy { type Error = TryFromSliceError; fn try_from(slice: &[T]) -> Result<[T; $N], TryFromSliceError> { diff --git a/src/libcore/benches/iter.rs b/src/libcore/benches/iter.rs index 1dd2bd3ee78aa..825bd368bdf1d 100644 --- a/src/libcore/benches/iter.rs +++ b/src/libcore/benches/iter.rs @@ -35,7 +35,7 @@ fn scatter(x: i32) -> i32 { (x * 31) % 127 } fn bench_max_by_key(b: &mut Bencher) { b.iter(|| { let it = 0..100; - it.max_by_key(|&x| scatter(x)) + it.map(black_box).max_by_key(|&x| scatter(x)) }) } @@ -56,7 +56,7 @@ fn bench_max_by_key2(b: &mut Bencher) { fn bench_max(b: &mut Bencher) { b.iter(|| { let it = 0..100; - it.map(scatter).max() + it.map(black_box).map(scatter).max() }) } diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 81fcdeee12d29..94bed3708369a 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -1004,26 +1004,26 @@ mod impls { // & pointers #[stable(feature = "rust1", since = "1.0.0")] - impl<'a, 'b, A: ?Sized, B: ?Sized> PartialEq<&'b B> for &'a A where A: PartialEq { + impl PartialEq<&B> for &A where A: PartialEq { #[inline] - fn eq(&self, other: & &'b B) -> bool { PartialEq::eq(*self, *other) } + fn eq(&self, other: & &B) -> bool { PartialEq::eq(*self, *other) } #[inline] - fn ne(&self, other: & &'b B) -> bool { PartialEq::ne(*self, *other) } + fn ne(&self, other: & &B) -> bool { PartialEq::ne(*self, *other) } } #[stable(feature = "rust1", since = "1.0.0")] - impl<'a, 'b, A: ?Sized, B: ?Sized> PartialOrd<&'b B> for &'a A where A: PartialOrd { + impl PartialOrd<&B> for &A where A: PartialOrd { #[inline] - fn partial_cmp(&self, other: &&'b B) -> Option { + fn partial_cmp(&self, other: &&B) -> Option { PartialOrd::partial_cmp(*self, *other) } #[inline] - fn lt(&self, other: & &'b B) -> bool { PartialOrd::lt(*self, *other) } + fn lt(&self, other: & &B) -> bool { PartialOrd::lt(*self, *other) } #[inline] - fn le(&self, other: & &'b B) -> bool { PartialOrd::le(*self, *other) } + fn le(&self, other: & &B) -> bool { PartialOrd::le(*self, *other) } #[inline] - fn ge(&self, other: & &'b B) -> bool { PartialOrd::ge(*self, *other) } + fn ge(&self, other: & &B) -> bool { PartialOrd::ge(*self, *other) } #[inline] - fn gt(&self, other: & &'b B) -> bool { PartialOrd::gt(*self, *other) } + fn gt(&self, other: & &B) -> bool { PartialOrd::gt(*self, *other) } } #[stable(feature = "rust1", since = "1.0.0")] impl Ord for &A where A: Ord { @@ -1036,26 +1036,26 @@ mod impls { // &mut pointers #[stable(feature = "rust1", since = "1.0.0")] - impl<'a, 'b, A: ?Sized, B: ?Sized> PartialEq<&'b mut B> for &'a mut A where A: PartialEq { + impl PartialEq<&mut B> for &mut A where A: PartialEq { #[inline] - fn eq(&self, other: &&'b mut B) -> bool { PartialEq::eq(*self, *other) } + fn eq(&self, other: &&mut B) -> bool { PartialEq::eq(*self, *other) } #[inline] - fn ne(&self, other: &&'b mut B) -> bool { PartialEq::ne(*self, *other) } + fn ne(&self, other: &&mut B) -> bool { PartialEq::ne(*self, *other) } } #[stable(feature = "rust1", since = "1.0.0")] - impl<'a, 'b, A: ?Sized, B: ?Sized> PartialOrd<&'b mut B> for &'a mut A where A: PartialOrd { + impl PartialOrd<&mut B> for &mut A where A: PartialOrd { #[inline] - fn partial_cmp(&self, other: &&'b mut B) -> Option { + fn partial_cmp(&self, other: &&mut B) -> Option { PartialOrd::partial_cmp(*self, *other) } #[inline] - fn lt(&self, other: &&'b mut B) -> bool { PartialOrd::lt(*self, *other) } + fn lt(&self, other: &&mut B) -> bool { PartialOrd::lt(*self, *other) } #[inline] - fn le(&self, other: &&'b mut B) -> bool { PartialOrd::le(*self, *other) } + fn le(&self, other: &&mut B) -> bool { PartialOrd::le(*self, *other) } #[inline] - fn ge(&self, other: &&'b mut B) -> bool { PartialOrd::ge(*self, *other) } + fn ge(&self, other: &&mut B) -> bool { PartialOrd::ge(*self, *other) } #[inline] - fn gt(&self, other: &&'b mut B) -> bool { PartialOrd::gt(*self, *other) } + fn gt(&self, other: &&mut B) -> bool { PartialOrd::gt(*self, *other) } } #[stable(feature = "rust1", since = "1.0.0")] impl Ord for &mut A where A: Ord { @@ -1066,18 +1066,18 @@ mod impls { impl Eq for &mut A where A: Eq {} #[stable(feature = "rust1", since = "1.0.0")] - impl<'a, 'b, A: ?Sized, B: ?Sized> PartialEq<&'b mut B> for &'a A where A: PartialEq { + impl PartialEq<&mut B> for &A where A: PartialEq { #[inline] - fn eq(&self, other: &&'b mut B) -> bool { PartialEq::eq(*self, *other) } + fn eq(&self, other: &&mut B) -> bool { PartialEq::eq(*self, *other) } #[inline] - fn ne(&self, other: &&'b mut B) -> bool { PartialEq::ne(*self, *other) } + fn ne(&self, other: &&mut B) -> bool { PartialEq::ne(*self, *other) } } #[stable(feature = "rust1", since = "1.0.0")] - impl<'a, 'b, A: ?Sized, B: ?Sized> PartialEq<&'b B> for &'a mut A where A: PartialEq { + impl PartialEq<&B> for &mut A where A: PartialEq { #[inline] - fn eq(&self, other: &&'b B) -> bool { PartialEq::eq(*self, *other) } + fn eq(&self, other: &&B) -> bool { PartialEq::eq(*self, *other) } #[inline] - fn ne(&self, other: &&'b B) -> bool { PartialEq::ne(*self, *other) } + fn ne(&self, other: &&B) -> bool { PartialEq::ne(*self, *other) } } } diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index 5ecfa9cde032e..774d648558b48 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -361,11 +361,17 @@ pub trait From: Sized { /// An attempted conversion that consumes `self`, which may or may not be /// expensive. /// -/// Library authors should not directly implement this trait, but should prefer -/// implementing the [`TryFrom`] trait, which offers greater flexibility and -/// provides an equivalent `TryInto` implementation for free, thanks to a -/// blanket implementation in the standard library. For more information on this, -/// see the documentation for [`Into`]. +/// Library authors should usually not directly implement this trait, +/// but should prefer implementing the [`TryFrom`] trait, which offers +/// greater flexibility and provides an equivalent `TryInto` +/// implementation for free, thanks to a blanket implementation in the +/// standard library. For more information on this, see the +/// documentation for [`Into`]. +/// +/// # Implementing `TryInto` +/// +/// This suffers the same restrictions and reasoning as implementing +/// [`Into`], see there for details. /// /// [`TryFrom`]: trait.TryFrom.html /// [`Into`]: trait.Into.html @@ -380,7 +386,55 @@ pub trait TryInto: Sized { fn try_into(self) -> Result; } -/// Attempt to construct `Self` via a conversion. +/// Simple and safe type conversions that may fail in a controlled +/// way under some circumstances. It is the reciprocal of [`TryInto`]. +/// +/// This is useful when you are doing a type conversion that may +/// trivially succeed but may also need special handling. +/// For example, there is no way to convert an `i64` into an `i32` +/// using the [`From`] trait, because an `i64` may contain a value +/// that an `i32` cannot represent and so the conversion would lose data. +/// This might be handled by truncating the `i64` to an `i32` (essentially +/// giving the `i64`'s value modulo `i32::MAX`) or by simply returning +/// `i32::MAX`, or by some other method. The `From` trait is intended +/// for perfect conversions, so the `TryFrom` trait informs the +/// programmer when a type conversion could go bad and lets them +/// decide how to handle it. +/// +/// # Generic Implementations +/// +/// - `TryFrom for U` implies [`TryInto`]` for T` +/// - [`try_from`] is reflexive, which means that `TryFrom for T` +/// is implemented and cannot fail -- the associated `Error` type for +/// calling `T::try_from()` on a value of type `T` is `Infallible`. +/// When the `!` type is stablized `Infallible` and `!` will be +/// equivalent. +/// +/// # Examples +/// +/// As described, [`i32`] implements `TryFrom`: +/// +/// ``` +/// use std::convert::TryFrom; +/// +/// let big_number = 1_000_000_000_000i64; +/// // Silently truncates `big_number`, requires detecting +/// // and handling the truncation after the fact. +/// let smaller_number = big_number as i32; +/// assert_eq!(smaller_number, -727379968); +/// +/// // Returns an error because `big_number` is too big to +/// // fit in an `i32`. +/// let try_smaller_number = i32::try_from(big_number); +/// assert!(try_smaller_number.is_err()); +/// +/// // Returns `Ok(3)`. +/// let try_successful_smaller_number = i32::try_from(3); +/// assert!(try_successful_smaller_number.is_ok()); +/// ``` +/// +/// [`try_from`]: trait.TryFrom.html#tymethod.try_from +/// [`TryInto`]: trait.TryInto.html #[stable(feature = "try_from", since = "1.34.0")] pub trait TryFrom: Sized { /// The type returned in the event of a conversion error. diff --git a/src/libcore/internal_macros.rs b/src/libcore/internal_macros.rs index faca785e488c3..b5c20582986b2 100644 --- a/src/libcore/internal_macros.rs +++ b/src/libcore/internal_macros.rs @@ -37,21 +37,21 @@ macro_rules! forward_ref_binop { } #[$attr] - impl<'a> $imp<&'a $u> for $t { + impl $imp<&$u> for $t { type Output = <$t as $imp<$u>>::Output; #[inline] - fn $method(self, other: &'a $u) -> <$t as $imp<$u>>::Output { + fn $method(self, other: &$u) -> <$t as $imp<$u>>::Output { $imp::$method(self, *other) } } #[$attr] - impl<'a, 'b> $imp<&'a $u> for &'b $t { + impl $imp<&$u> for &$t { type Output = <$t as $imp<$u>>::Output; #[inline] - fn $method(self, other: &'a $u) -> <$t as $imp<$u>>::Output { + fn $method(self, other: &$u) -> <$t as $imp<$u>>::Output { $imp::$method(*self, *other) } } @@ -67,9 +67,9 @@ macro_rules! forward_ref_op_assign { }; (impl $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => { #[$attr] - impl<'a> $imp<&'a $u> for $t { + impl $imp<&$u> for $t { #[inline] - fn $method(&mut self, other: &'a $u) { + fn $method(&mut self, other: &$u) { $imp::$method(self, *other); } } diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs index 861e9c3157a79..ca7feed0712d1 100644 --- a/src/libcore/iter/traits/iterator.rs +++ b/src/libcore/iter/traits/iterator.rs @@ -2008,12 +2008,7 @@ pub trait Iterator { #[stable(feature = "rust1", since = "1.0.0")] fn max(self) -> Option where Self: Sized, Self::Item: Ord { - select_fold1(self, - |_| (), - // switch to y even if it is only equal, to preserve - // stability. - |_, x, _, y| *x <= *y) - .map(|(_, x)| x) + self.max_by(Ord::cmp) } /// Returns the minimum element of an iterator. @@ -2038,12 +2033,7 @@ pub trait Iterator { #[stable(feature = "rust1", since = "1.0.0")] fn min(self) -> Option where Self: Sized, Self::Item: Ord { - select_fold1(self, - |_| (), - // only switch to y if it is strictly smaller, to - // preserve stability. - |_, x, _, y| *x > *y) - .map(|(_, x)| x) + self.min_by(Ord::cmp) } /// Returns the element that gives the maximum value from the @@ -2062,15 +2052,11 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iter_cmp_by_key", since = "1.6.0")] - fn max_by_key(self, f: F) -> Option + fn max_by_key(self, mut f: F) -> Option where Self: Sized, F: FnMut(&Self::Item) -> B, { - select_fold1(self, - f, - // switch to y even if it is only equal, to preserve - // stability. - |x_p, _, y_p, _| x_p <= y_p) - .map(|(_, x)| x) + // switch to y even if it is only equal, to preserve stability. + select_fold1(self.map(|x| (f(&x), x)), |(x_p, _), (y_p, _)| x_p <= y_p).map(|(_, x)| x) } /// Returns the element that gives the maximum value with respect to the @@ -2092,12 +2078,8 @@ pub trait Iterator { fn max_by(self, mut compare: F) -> Option where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering, { - select_fold1(self, - |_| (), - // switch to y even if it is only equal, to preserve - // stability. - |_, x, _, y| Ordering::Greater != compare(x, y)) - .map(|(_, x)| x) + // switch to y even if it is only equal, to preserve stability. + select_fold1(self, |x, y| compare(x, y) != Ordering::Greater) } /// Returns the element that gives the minimum value from the @@ -2115,15 +2097,11 @@ pub trait Iterator { /// assert_eq!(*a.iter().min_by_key(|x| x.abs()).unwrap(), 0); /// ``` #[stable(feature = "iter_cmp_by_key", since = "1.6.0")] - fn min_by_key(self, f: F) -> Option + fn min_by_key(self, mut f: F) -> Option where Self: Sized, F: FnMut(&Self::Item) -> B, { - select_fold1(self, - f, - // only switch to y if it is strictly smaller, to - // preserve stability. - |x_p, _, y_p, _| x_p > y_p) - .map(|(_, x)| x) + // only switch to y if it is strictly smaller, to preserve stability. + select_fold1(self.map(|x| (f(&x), x)), |(x_p, _), (y_p, _)| x_p > y_p).map(|(_, x)| x) } /// Returns the element that gives the minimum value with respect to the @@ -2145,12 +2123,8 @@ pub trait Iterator { fn min_by(self, mut compare: F) -> Option where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering, { - select_fold1(self, - |_| (), - // switch to y even if it is strictly smaller, to - // preserve stability. - |_, x, _, y| Ordering::Greater == compare(x, y)) - .map(|(_, x)| x) + // only switch to y if it is strictly smaller, to preserve stability. + select_fold1(self, |x, y| compare(x, y) == Ordering::Greater) } @@ -2693,34 +2667,23 @@ pub trait Iterator { } } -/// Select an element from an iterator based on the given "projection" -/// and "comparison" function. +/// Select an element from an iterator based on the given "comparison" +/// function. /// /// This is an idiosyncratic helper to try to factor out the /// commonalities of {max,min}{,_by}. In particular, this avoids /// having to implement optimizations several times. #[inline] -fn select_fold1(mut it: I, - mut f_proj: FProj, - mut f_cmp: FCmp) -> Option<(B, I::Item)> - where I: Iterator, - FProj: FnMut(&I::Item) -> B, - FCmp: FnMut(&B, &I::Item, &B, &I::Item) -> bool +fn select_fold1(mut it: I, mut f: F) -> Option + where + I: Iterator, + F: FnMut(&I::Item, &I::Item) -> bool, { // start with the first element as our selection. This avoids // having to use `Option`s inside the loop, translating to a // sizeable performance gain (6x in one case). it.next().map(|first| { - let first_p = f_proj(&first); - - it.fold((first_p, first), |(sel_p, sel), x| { - let x_p = f_proj(&x); - if f_cmp(&sel_p, &sel, &x_p, &x) { - (x_p, x) - } else { - (sel_p, sel) - } - }) + it.fold(first, |sel, x| if f(&sel, &x) { x } else { sel }) }) } diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 98b5fcd3ee4f0..d93cfbc2a28ac 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1979,10 +1979,10 @@ When starting from a slice rather than an array, fallible conversion APIs can be ``` use std::convert::TryInto; -fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " { +fn read_le_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " { let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">()); *input = rest; - ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap()) + ", stringify!($SelfT), "::from_le_bytes(int_bytes.try_into().unwrap()) } ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] @@ -2020,10 +2020,10 @@ When starting from a slice rather than an array, fallible conversion APIs can be ``` use std::convert::TryInto; -fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " { +fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " { let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">()); *input = rest; - ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap()) + ", stringify!($SelfT), "::from_ne_bytes(int_bytes.try_into().unwrap()) } ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] @@ -3695,10 +3695,10 @@ When starting from a slice rather than an array, fallible conversion APIs can be ``` use std::convert::TryInto; -fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " { +fn read_le_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " { let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">()); *input = rest; - ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap()) + ", stringify!($SelfT), "::from_le_bytes(int_bytes.try_into().unwrap()) } ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] @@ -3736,10 +3736,10 @@ When starting from a slice rather than an array, fallible conversion APIs can be ``` use std::convert::TryInto; -fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " { +fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " { let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">()); *input = rest; - ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap()) + ", stringify!($SelfT), "::from_ne_bytes(int_bytes.try_into().unwrap()) } ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] @@ -4442,6 +4442,9 @@ macro_rules! try_from_unbounded { impl TryFrom<$source> for $target { type Error = TryFromIntError; + /// Try to create the target number type from a source + /// number type. This returns an error if the source value + /// is outside of the range of the target type. #[inline] fn try_from(value: $source) -> Result { Ok(value as $target) @@ -4457,6 +4460,9 @@ macro_rules! try_from_lower_bounded { impl TryFrom<$source> for $target { type Error = TryFromIntError; + /// Try to create the target number type from a source + /// number type. This returns an error if the source value + /// is outside of the range of the target type. #[inline] fn try_from(u: $source) -> Result<$target, TryFromIntError> { if u >= 0 { @@ -4476,6 +4482,9 @@ macro_rules! try_from_upper_bounded { impl TryFrom<$source> for $target { type Error = TryFromIntError; + /// Try to create the target number type from a source + /// number type. This returns an error if the source value + /// is outside of the range of the target type. #[inline] fn try_from(u: $source) -> Result<$target, TryFromIntError> { if u > (<$target>::max_value() as $source) { @@ -4495,6 +4504,9 @@ macro_rules! try_from_both_bounded { impl TryFrom<$source> for $target { type Error = TryFromIntError; + /// Try to create the target number type from a source + /// number type. This returns an error if the source value + /// is outside of the range of the target type. #[inline] fn try_from(u: $source) -> Result<$target, TryFromIntError> { let min = <$target>::min_value() as $source; diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs index 998b597d5e113..81a8d001dd9cb 100644 --- a/src/libcore/ops/range.rs +++ b/src/libcore/ops/range.rs @@ -26,11 +26,13 @@ use hash::{Hash, Hasher}; /// Used as a [slicing index], `RangeFull` produces the full array as a slice. /// /// ``` -/// let arr = [0, 1, 2, 3]; -/// assert_eq!(arr[ .. ], [0,1,2,3]); // RangeFull -/// assert_eq!(arr[ ..3], [0,1,2 ]); -/// assert_eq!(arr[1.. ], [ 1,2,3]); -/// assert_eq!(arr[1..3], [ 1,2 ]); +/// let arr = [0, 1, 2, 3, 4]; +/// assert_eq!(arr[ .. ], [0,1,2,3,4]); // RangeFull +/// assert_eq!(arr[ .. 3], [0,1,2 ]); +/// assert_eq!(arr[ ..=3], [0,1,2,3 ]); +/// assert_eq!(arr[1.. ], [ 1,2,3,4]); +/// assert_eq!(arr[1.. 3], [ 1,2 ]); +/// assert_eq!(arr[1..=3], [ 1,2,3 ]); /// ``` /// /// [`IntoIterator`]: ../iter/trait.Iterator.html @@ -60,11 +62,13 @@ impl fmt::Debug for RangeFull { /// assert_eq!((3..5), std::ops::Range { start: 3, end: 5 }); /// assert_eq!(3 + 4 + 5, (3..6).sum()); /// -/// let arr = ['a', 'b', 'c', 'd']; -/// assert_eq!(arr[ .. ], ['a', 'b', 'c', 'd']); -/// assert_eq!(arr[ ..3], ['a', 'b', 'c', ]); -/// assert_eq!(arr[1.. ], [ 'b', 'c', 'd']); -/// assert_eq!(arr[1..3], [ 'b', 'c' ]); // Range +/// let arr = [0, 1, 2, 3, 4]; +/// assert_eq!(arr[ .. ], [0,1,2,3,4]); +/// assert_eq!(arr[ .. 3], [0,1,2 ]); +/// assert_eq!(arr[ ..=3], [0,1,2,3 ]); +/// assert_eq!(arr[1.. ], [ 1,2,3,4]); +/// assert_eq!(arr[1.. 3], [ 1,2 ]); // Range +/// assert_eq!(arr[1..=3], [ 1,2,3 ]); /// ``` #[doc(alias = "..")] #[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 @@ -160,11 +164,13 @@ impl> Range { /// assert_eq!((2..), std::ops::RangeFrom { start: 2 }); /// assert_eq!(2 + 3 + 4, (2..).take(3).sum()); /// -/// let arr = [0, 1, 2, 3]; -/// assert_eq!(arr[ .. ], [0,1,2,3]); -/// assert_eq!(arr[ ..3], [0,1,2 ]); -/// assert_eq!(arr[1.. ], [ 1,2,3]); // RangeFrom -/// assert_eq!(arr[1..3], [ 1,2 ]); +/// let arr = [0, 1, 2, 3, 4]; +/// assert_eq!(arr[ .. ], [0,1,2,3,4]); +/// assert_eq!(arr[ .. 3], [0,1,2 ]); +/// assert_eq!(arr[ ..=3], [0,1,2,3 ]); +/// assert_eq!(arr[1.. ], [ 1,2,3,4]); // RangeFrom +/// assert_eq!(arr[1.. 3], [ 1,2 ]); +/// assert_eq!(arr[1..=3], [ 1,2,3 ]); /// ``` /// /// [`Iterator`]: ../iter/trait.IntoIterator.html @@ -240,11 +246,13 @@ impl> RangeFrom { /// elements before the index indicated by `end`. /// /// ``` -/// let arr = [0, 1, 2, 3]; -/// assert_eq!(arr[ .. ], [0,1,2,3]); -/// assert_eq!(arr[ ..3], [0,1,2 ]); // RangeTo -/// assert_eq!(arr[1.. ], [ 1,2,3]); -/// assert_eq!(arr[1..3], [ 1,2 ]); +/// let arr = [0, 1, 2, 3, 4]; +/// assert_eq!(arr[ .. ], [0,1,2,3,4]); +/// assert_eq!(arr[ .. 3], [0,1,2 ]); // RangeTo +/// assert_eq!(arr[ ..=3], [0,1,2,3 ]); +/// assert_eq!(arr[1.. ], [ 1,2,3,4]); +/// assert_eq!(arr[1.. 3], [ 1,2 ]); +/// assert_eq!(arr[1..=3], [ 1,2,3 ]); /// ``` /// /// [`IntoIterator`]: ../iter/trait.Iterator.html @@ -312,9 +320,13 @@ impl> RangeTo { /// assert_eq!((3..=5), std::ops::RangeInclusive::new(3, 5)); /// assert_eq!(3 + 4 + 5, (3..=5).sum()); /// -/// let arr = [0, 1, 2, 3]; -/// assert_eq!(arr[ ..=2], [0,1,2 ]); -/// assert_eq!(arr[1..=2], [ 1,2 ]); // RangeInclusive +/// let arr = [0, 1, 2, 3, 4]; +/// assert_eq!(arr[ .. ], [0,1,2,3,4]); +/// assert_eq!(arr[ .. 3], [0,1,2 ]); +/// assert_eq!(arr[ ..=3], [0,1,2,3 ]); +/// assert_eq!(arr[1.. ], [ 1,2,3,4]); +/// assert_eq!(arr[1.. 3], [ 1,2 ]); +/// assert_eq!(arr[1..=3], [ 1,2,3 ]); // RangeInclusive /// ``` #[doc(alias = "..=")] #[derive(Clone)] // not Copy -- see #27186 @@ -569,9 +581,13 @@ impl> RangeInclusive { /// array elements up to and including the index indicated by `end`. /// /// ``` -/// let arr = [0, 1, 2, 3]; -/// assert_eq!(arr[ ..=2], [0,1,2 ]); // RangeToInclusive -/// assert_eq!(arr[1..=2], [ 1,2 ]); +/// let arr = [0, 1, 2, 3, 4]; +/// assert_eq!(arr[ .. ], [0,1,2,3,4]); +/// assert_eq!(arr[ .. 3], [0,1,2 ]); +/// assert_eq!(arr[ ..=3], [0,1,2,3 ]); // RangeToInclusive +/// assert_eq!(arr[1.. ], [ 1,2,3,4]); +/// assert_eq!(arr[1.. 3], [ 1,2 ]); +/// assert_eq!(arr[1..=3], [ 1,2,3 ]); /// ``` /// /// [`IntoIterator`]: ../iter/trait.Iterator.html @@ -676,7 +692,7 @@ pub enum Bound { #[stable(feature = "collections_range", since = "1.28.0")] /// `RangeBounds` is implemented by Rust's built-in range types, produced -/// by range syntax like `..`, `a..`, `..b` or `c..d`. +/// by range syntax like `..`, `a..`, `..b`, `..=c`, `d..e`, or `f..=g`. pub trait RangeBounds { /// Start index bound. /// diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 53d4197603068..a9a029d606d6f 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -2837,15 +2837,15 @@ impl fmt::Pointer for Unique { } #[unstable(feature = "ptr_internals", issue = "0")] -impl<'a, T: ?Sized> From<&'a mut T> for Unique { - fn from(reference: &'a mut T) -> Self { +impl From<&mut T> for Unique { + fn from(reference: &mut T) -> Self { unsafe { Unique { pointer: reference as *mut T, _marker: PhantomData } } } } #[unstable(feature = "ptr_internals", issue = "0")] -impl<'a, T: ?Sized> From<&'a T> for Unique { - fn from(reference: &'a T) -> Self { +impl From<&T> for Unique { + fn from(reference: &T) -> Self { unsafe { Unique { pointer: reference as *const T, _marker: PhantomData } } } } @@ -2874,6 +2874,16 @@ impl<'a, T: ?Sized> From> for Unique { /// Usually this won't be necessary; covariance is correct for most safe abstractions, /// such as Box, Rc, Arc, Vec, and LinkedList. This is the case because they /// provide a public API that follows the normal shared XOR mutable rules of Rust. +/// +/// Notice that `NonNull` has a `From` instance for `&T`. However, this does +/// not change the fact that mutating through a (pointer derived from a) shared +/// reference is undefined behavior unless the mutation happens inside an +/// [`UnsafeCell`]. The same goes for creating a mutable reference from a shared +/// reference. When using this `From` instance without an `UnsafeCell`, +/// it is your responsibility to ensure that `as_mut` is never called, and `as_ptr` +/// is never used for mutation. +/// +/// [`UnsafeCell`]: ../cell/struct.UnsafeCell.html #[stable(feature = "nonnull", since = "1.25.0")] #[repr(transparent)] #[rustc_layout_scalar_valid_range_start(1)] @@ -3049,17 +3059,17 @@ impl From> for NonNull { } #[stable(feature = "nonnull", since = "1.25.0")] -impl<'a, T: ?Sized> From<&'a mut T> for NonNull { +impl From<&mut T> for NonNull { #[inline] - fn from(reference: &'a mut T) -> Self { + fn from(reference: &mut T) -> Self { unsafe { NonNull { pointer: reference as *mut T } } } } #[stable(feature = "nonnull", since = "1.25.0")] -impl<'a, T: ?Sized> From<&'a T> for NonNull { +impl From<&T> for NonNull { #[inline] - fn from(reference: &'a T) -> Self { + fn from(reference: &T) -> Self { unsafe { NonNull { pointer: reference as *const T } } } } diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 92d29f6ee8a30..2bd6b536301e8 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -1200,7 +1200,7 @@ impl> FromIterator> for Result { /// let res: Result, &'static str> = v.iter().map(|x: &u32| /// x.checked_add(1).ok_or("Overflow!") /// ).collect(); - /// assert!(res == Ok(vec![2, 3])); + /// assert_eq!(res, Ok(vec![2, 3])); /// ``` #[inline] fn from_iter>>(iter: I) -> Result { diff --git a/src/libcore/tests/fmt/num.rs b/src/libcore/tests/fmt/num.rs index 6d9494ec289aa..10fcf8b76ccb4 100644 --- a/src/libcore/tests/fmt/num.rs +++ b/src/libcore/tests/fmt/num.rs @@ -3,146 +3,146 @@ fn test_format_int() { // Formatting integers should select the right implementation based off // the type of the argument. Also, hex/octal/binary should be defined // for integers, but they shouldn't emit the negative sign. - assert!(format!("{}", 1isize) == "1"); - assert!(format!("{}", 1i8) == "1"); - assert!(format!("{}", 1i16) == "1"); - assert!(format!("{}", 1i32) == "1"); - assert!(format!("{}", 1i64) == "1"); - assert!(format!("{}", -1isize) == "-1"); - assert!(format!("{}", -1i8) == "-1"); - assert!(format!("{}", -1i16) == "-1"); - assert!(format!("{}", -1i32) == "-1"); - assert!(format!("{}", -1i64) == "-1"); - assert!(format!("{:?}", 1isize) == "1"); - assert!(format!("{:?}", 1i8) == "1"); - assert!(format!("{:?}", 1i16) == "1"); - assert!(format!("{:?}", 1i32) == "1"); - assert!(format!("{:?}", 1i64) == "1"); - assert!(format!("{:b}", 1isize) == "1"); - assert!(format!("{:b}", 1i8) == "1"); - assert!(format!("{:b}", 1i16) == "1"); - assert!(format!("{:b}", 1i32) == "1"); - assert!(format!("{:b}", 1i64) == "1"); - assert!(format!("{:x}", 1isize) == "1"); - assert!(format!("{:x}", 1i8) == "1"); - assert!(format!("{:x}", 1i16) == "1"); - assert!(format!("{:x}", 1i32) == "1"); - assert!(format!("{:x}", 1i64) == "1"); - assert!(format!("{:X}", 1isize) == "1"); - assert!(format!("{:X}", 1i8) == "1"); - assert!(format!("{:X}", 1i16) == "1"); - assert!(format!("{:X}", 1i32) == "1"); - assert!(format!("{:X}", 1i64) == "1"); - assert!(format!("{:o}", 1isize) == "1"); - assert!(format!("{:o}", 1i8) == "1"); - assert!(format!("{:o}", 1i16) == "1"); - assert!(format!("{:o}", 1i32) == "1"); - assert!(format!("{:o}", 1i64) == "1"); + assert_eq!(format!("{}", 1isize), "1"); + assert_eq!(format!("{}", 1i8), "1"); + assert_eq!(format!("{}", 1i16), "1"); + assert_eq!(format!("{}", 1i32), "1"); + assert_eq!(format!("{}", 1i64), "1"); + assert_eq!(format!("{}", -1isize), "-1"); + assert_eq!(format!("{}", -1i8), "-1"); + assert_eq!(format!("{}", -1i16), "-1"); + assert_eq!(format!("{}", -1i32), "-1"); + assert_eq!(format!("{}", -1i64), "-1"); + assert_eq!(format!("{:?}", 1isize), "1"); + assert_eq!(format!("{:?}", 1i8), "1"); + assert_eq!(format!("{:?}", 1i16), "1"); + assert_eq!(format!("{:?}", 1i32), "1"); + assert_eq!(format!("{:?}", 1i64), "1"); + assert_eq!(format!("{:b}", 1isize), "1"); + assert_eq!(format!("{:b}", 1i8), "1"); + assert_eq!(format!("{:b}", 1i16), "1"); + assert_eq!(format!("{:b}", 1i32), "1"); + assert_eq!(format!("{:b}", 1i64), "1"); + assert_eq!(format!("{:x}", 1isize), "1"); + assert_eq!(format!("{:x}", 1i8), "1"); + assert_eq!(format!("{:x}", 1i16), "1"); + assert_eq!(format!("{:x}", 1i32), "1"); + assert_eq!(format!("{:x}", 1i64), "1"); + assert_eq!(format!("{:X}", 1isize), "1"); + assert_eq!(format!("{:X}", 1i8), "1"); + assert_eq!(format!("{:X}", 1i16), "1"); + assert_eq!(format!("{:X}", 1i32), "1"); + assert_eq!(format!("{:X}", 1i64), "1"); + assert_eq!(format!("{:o}", 1isize), "1"); + assert_eq!(format!("{:o}", 1i8), "1"); + assert_eq!(format!("{:o}", 1i16), "1"); + assert_eq!(format!("{:o}", 1i32), "1"); + assert_eq!(format!("{:o}", 1i64), "1"); - assert!(format!("{}", 1usize) == "1"); - assert!(format!("{}", 1u8) == "1"); - assert!(format!("{}", 1u16) == "1"); - assert!(format!("{}", 1u32) == "1"); - assert!(format!("{}", 1u64) == "1"); - assert!(format!("{:?}", 1usize) == "1"); - assert!(format!("{:?}", 1u8) == "1"); - assert!(format!("{:?}", 1u16) == "1"); - assert!(format!("{:?}", 1u32) == "1"); - assert!(format!("{:?}", 1u64) == "1"); - assert!(format!("{:b}", 1usize) == "1"); - assert!(format!("{:b}", 1u8) == "1"); - assert!(format!("{:b}", 1u16) == "1"); - assert!(format!("{:b}", 1u32) == "1"); - assert!(format!("{:b}", 1u64) == "1"); - assert!(format!("{:x}", 1usize) == "1"); - assert!(format!("{:x}", 1u8) == "1"); - assert!(format!("{:x}", 1u16) == "1"); - assert!(format!("{:x}", 1u32) == "1"); - assert!(format!("{:x}", 1u64) == "1"); - assert!(format!("{:X}", 1usize) == "1"); - assert!(format!("{:X}", 1u8) == "1"); - assert!(format!("{:X}", 1u16) == "1"); - assert!(format!("{:X}", 1u32) == "1"); - assert!(format!("{:X}", 1u64) == "1"); - assert!(format!("{:o}", 1usize) == "1"); - assert!(format!("{:o}", 1u8) == "1"); - assert!(format!("{:o}", 1u16) == "1"); - assert!(format!("{:o}", 1u32) == "1"); - assert!(format!("{:o}", 1u64) == "1"); + assert_eq!(format!("{}", 1usize), "1"); + assert_eq!(format!("{}", 1u8), "1"); + assert_eq!(format!("{}", 1u16), "1"); + assert_eq!(format!("{}", 1u32), "1"); + assert_eq!(format!("{}", 1u64), "1"); + assert_eq!(format!("{:?}", 1usize), "1"); + assert_eq!(format!("{:?}", 1u8), "1"); + assert_eq!(format!("{:?}", 1u16), "1"); + assert_eq!(format!("{:?}", 1u32), "1"); + assert_eq!(format!("{:?}", 1u64), "1"); + assert_eq!(format!("{:b}", 1usize), "1"); + assert_eq!(format!("{:b}", 1u8), "1"); + assert_eq!(format!("{:b}", 1u16), "1"); + assert_eq!(format!("{:b}", 1u32), "1"); + assert_eq!(format!("{:b}", 1u64), "1"); + assert_eq!(format!("{:x}", 1usize), "1"); + assert_eq!(format!("{:x}", 1u8), "1"); + assert_eq!(format!("{:x}", 1u16), "1"); + assert_eq!(format!("{:x}", 1u32), "1"); + assert_eq!(format!("{:x}", 1u64), "1"); + assert_eq!(format!("{:X}", 1usize), "1"); + assert_eq!(format!("{:X}", 1u8), "1"); + assert_eq!(format!("{:X}", 1u16), "1"); + assert_eq!(format!("{:X}", 1u32), "1"); + assert_eq!(format!("{:X}", 1u64), "1"); + assert_eq!(format!("{:o}", 1usize), "1"); + assert_eq!(format!("{:o}", 1u8), "1"); + assert_eq!(format!("{:o}", 1u16), "1"); + assert_eq!(format!("{:o}", 1u32), "1"); + assert_eq!(format!("{:o}", 1u64), "1"); // Test a larger number - assert!(format!("{:b}", 55) == "110111"); - assert!(format!("{:o}", 55) == "67"); - assert!(format!("{}", 55) == "55"); - assert!(format!("{:x}", 55) == "37"); - assert!(format!("{:X}", 55) == "37"); + assert_eq!(format!("{:b}", 55), "110111"); + assert_eq!(format!("{:o}", 55), "67"); + assert_eq!(format!("{}", 55), "55"); + assert_eq!(format!("{:x}", 55), "37"); + assert_eq!(format!("{:X}", 55), "37"); } #[test] fn test_format_int_zero() { - assert!(format!("{}", 0) == "0"); - assert!(format!("{:?}", 0) == "0"); - assert!(format!("{:b}", 0) == "0"); - assert!(format!("{:o}", 0) == "0"); - assert!(format!("{:x}", 0) == "0"); - assert!(format!("{:X}", 0) == "0"); + assert_eq!(format!("{}", 0), "0"); + assert_eq!(format!("{:?}", 0), "0"); + assert_eq!(format!("{:b}", 0), "0"); + assert_eq!(format!("{:o}", 0), "0"); + assert_eq!(format!("{:x}", 0), "0"); + assert_eq!(format!("{:X}", 0), "0"); - assert!(format!("{}", 0u32) == "0"); - assert!(format!("{:?}", 0u32) == "0"); - assert!(format!("{:b}", 0u32) == "0"); - assert!(format!("{:o}", 0u32) == "0"); - assert!(format!("{:x}", 0u32) == "0"); - assert!(format!("{:X}", 0u32) == "0"); + assert_eq!(format!("{}", 0u32), "0"); + assert_eq!(format!("{:?}", 0u32), "0"); + assert_eq!(format!("{:b}", 0u32), "0"); + assert_eq!(format!("{:o}", 0u32), "0"); + assert_eq!(format!("{:x}", 0u32), "0"); + assert_eq!(format!("{:X}", 0u32), "0"); } #[test] fn test_format_int_flags() { - assert!(format!("{:3}", 1) == " 1"); - assert!(format!("{:>3}", 1) == " 1"); - assert!(format!("{:>+3}", 1) == " +1"); - assert!(format!("{:<3}", 1) == "1 "); - assert!(format!("{:#}", 1) == "1"); - assert!(format!("{:#x}", 10) == "0xa"); - assert!(format!("{:#X}", 10) == "0xA"); - assert!(format!("{:#5x}", 10) == " 0xa"); - assert!(format!("{:#o}", 10) == "0o12"); - assert!(format!("{:08x}", 10) == "0000000a"); - assert!(format!("{:8x}", 10) == " a"); - assert!(format!("{:<8x}", 10) == "a "); - assert!(format!("{:>8x}", 10) == " a"); - assert!(format!("{:#08x}", 10) == "0x00000a"); - assert!(format!("{:08}", -10) == "-0000010"); - assert!(format!("{:x}", !0u8) == "ff"); - assert!(format!("{:X}", !0u8) == "FF"); - assert!(format!("{:b}", !0u8) == "11111111"); - assert!(format!("{:o}", !0u8) == "377"); - assert!(format!("{:#x}", !0u8) == "0xff"); - assert!(format!("{:#X}", !0u8) == "0xFF"); - assert!(format!("{:#b}", !0u8) == "0b11111111"); - assert!(format!("{:#o}", !0u8) == "0o377"); + assert_eq!(format!("{:3}", 1), " 1"); + assert_eq!(format!("{:>3}", 1), " 1"); + assert_eq!(format!("{:>+3}", 1), " +1"); + assert_eq!(format!("{:<3}", 1), "1 "); + assert_eq!(format!("{:#}", 1), "1"); + assert_eq!(format!("{:#x}", 10), "0xa"); + assert_eq!(format!("{:#X}", 10), "0xA"); + assert_eq!(format!("{:#5x}", 10), " 0xa"); + assert_eq!(format!("{:#o}", 10), "0o12"); + assert_eq!(format!("{:08x}", 10), "0000000a"); + assert_eq!(format!("{:8x}", 10), " a"); + assert_eq!(format!("{:<8x}", 10), "a "); + assert_eq!(format!("{:>8x}", 10), " a"); + assert_eq!(format!("{:#08x}", 10), "0x00000a"); + assert_eq!(format!("{:08}", -10), "-0000010"); + assert_eq!(format!("{:x}", !0u8), "ff"); + assert_eq!(format!("{:X}", !0u8), "FF"); + assert_eq!(format!("{:b}", !0u8), "11111111"); + assert_eq!(format!("{:o}", !0u8), "377"); + assert_eq!(format!("{:#x}", !0u8), "0xff"); + assert_eq!(format!("{:#X}", !0u8), "0xFF"); + assert_eq!(format!("{:#b}", !0u8), "0b11111111"); + assert_eq!(format!("{:#o}", !0u8), "0o377"); } #[test] fn test_format_int_sign_padding() { - assert!(format!("{:+5}", 1) == " +1"); - assert!(format!("{:+5}", -1) == " -1"); - assert!(format!("{:05}", 1) == "00001"); - assert!(format!("{:05}", -1) == "-0001"); - assert!(format!("{:+05}", 1) == "+0001"); - assert!(format!("{:+05}", -1) == "-0001"); + assert_eq!(format!("{:+5}", 1), " +1"); + assert_eq!(format!("{:+5}", -1), " -1"); + assert_eq!(format!("{:05}", 1), "00001"); + assert_eq!(format!("{:05}", -1), "-0001"); + assert_eq!(format!("{:+05}", 1), "+0001"); + assert_eq!(format!("{:+05}", -1), "-0001"); } #[test] fn test_format_int_twos_complement() { - use core::{i8, i16, i32, i64}; - assert!(format!("{}", i8::MIN) == "-128"); - assert!(format!("{}", i16::MIN) == "-32768"); - assert!(format!("{}", i32::MIN) == "-2147483648"); - assert!(format!("{}", i64::MIN) == "-9223372036854775808"); + use core::{i16, i32, i64, i8}; + assert_eq!(format!("{}", i8::MIN), "-128"); + assert_eq!(format!("{}", i16::MIN), "-32768"); + assert_eq!(format!("{}", i32::MIN), "-2147483648"); + assert_eq!(format!("{}", i64::MIN), "-9223372036854775808"); } #[test] fn test_format_debug_hex() { - assert!(format!("{:02x?}", b"Foo\0") == "[46, 6f, 6f, 00]"); - assert!(format!("{:02X?}", b"Foo\0") == "[46, 6F, 6F, 00]"); + assert_eq!(format!("{:02x?}", b"Foo\0"), "[46, 6f, 6f, 00]"); + assert_eq!(format!("{:02X?}", b"Foo\0"), "[46, 6F, 6F, 00]"); } diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index d880abb181c20..a9db9b35d8d80 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -1082,12 +1082,39 @@ fn test_iterator_product_result() { assert_eq!(v.iter().cloned().product::>(), Err(())); } +/// A wrapper struct that implements `Eq` and `Ord` based on the wrapped +/// integer modulo 3. Used to test that `Iterator::max` and `Iterator::min` +/// return the correct element if some of them are equal. +#[derive(Debug)] +struct Mod3(i32); + +impl PartialEq for Mod3 { + fn eq(&self, other: &Self) -> bool { + self.0 % 3 == other.0 % 3 + } +} + +impl Eq for Mod3 {} + +impl PartialOrd for Mod3 { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Mod3 { + fn cmp(&self, other: &Self) -> core::cmp::Ordering { + (self.0 % 3).cmp(&(other.0 % 3)) + } +} + #[test] fn test_iterator_max() { let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; assert_eq!(v[..4].iter().cloned().max(), Some(3)); assert_eq!(v.iter().cloned().max(), Some(10)); assert_eq!(v[..0].iter().cloned().max(), None); + assert_eq!(v.iter().cloned().map(Mod3).max().map(|x| x.0), Some(8)); } #[test] @@ -1096,6 +1123,7 @@ fn test_iterator_min() { assert_eq!(v[..4].iter().cloned().min(), Some(0)); assert_eq!(v.iter().cloned().min(), Some(0)); assert_eq!(v[..0].iter().cloned().min(), None); + assert_eq!(v.iter().cloned().map(Mod3).min().map(|x| x.0), Some(0)); } #[test] diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index f6d864f5b404d..b45fc3ffd82fe 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -3,12 +3,13 @@ use crate::util::nodemap::{NodeMap, DefIdMap}; use syntax::ast; use syntax::ext::base::MacroKind; use syntax_pos::Span; +use rustc_macros::HashStable; use crate::hir; use crate::ty; use self::Namespace::*; -#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)] pub enum CtorKind { /// Constructor function automatically created by a tuple struct/variant. Fn, @@ -18,7 +19,7 @@ pub enum CtorKind { Fictive, } -#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)] pub enum NonMacroAttrKind { /// Single-segment attribute defined by the language (`#[inline]`) Builtin, @@ -32,7 +33,7 @@ pub enum NonMacroAttrKind { Custom, } -#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)] pub enum Def { // Type namespace Mod(DefId), @@ -209,7 +210,7 @@ pub type ExportMap = DefIdMap>; /// namespace. pub type ImportMap = NodeMap>>; -#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)] +#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] pub struct Export { /// The name of the target. pub ident: ast::Ident, diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index e47bc3d1c2533..88ab58d10fc34 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -122,6 +122,7 @@ impl fmt::Display for HirId { // hack to ensure that we don't try to access the private parts of `ItemLocalId` in this module mod item_local_id_inner { use rustc_data_structures::indexed_vec::Idx; + use rustc_macros::HashStable; newtype_index! { /// An `ItemLocalId` uniquely identifies something within a given "item-like", /// that is within a hir::Item, hir::TraitItem, or hir::ImplItem. There is no @@ -131,7 +132,9 @@ mod item_local_id_inner { /// integers starting at zero, so a mapping that maps all or most nodes within /// an "item-like" to something else can be implement by a `Vec` instead of a /// tree or hash map. - pub struct ItemLocalId { .. } + pub struct ItemLocalId { + derive [HashStable] + } } } @@ -164,7 +167,7 @@ pub struct Lifetime { pub name: LifetimeName, } -#[derive(Debug, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)] +#[derive(Debug, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy, HashStable)] pub enum ParamName { /// Some user-given name like `T` or `'x`. Plain(Ident), @@ -207,7 +210,7 @@ impl ParamName { } } -#[derive(Debug, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)] +#[derive(Debug, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy, HashStable)] pub enum LifetimeName { /// User-given names or fresh (synthetic) names. Param(ParamName), @@ -290,7 +293,7 @@ impl Lifetime { /// A `Path` is essentially Rust's notion of a name; for instance, /// `std::cmp::PartialEq`. It's represented as a sequence of identifiers, /// along with a bunch of supporting information. -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)] pub struct Path { pub span: Span, /// The definition that the path resolved to. @@ -319,9 +322,10 @@ impl fmt::Display for Path { /// A segment of a path: an identifier, an optional lifetime, and a set of /// types. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct PathSegment { /// The identifier portion of this path segment. + #[stable_hasher(project(name))] pub ident: Ident, // `id` and `def` are optional. We currently only use these in save-analysis, // any path segments without these will not have save-analysis info and @@ -391,13 +395,13 @@ impl PathSegment { } } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct ConstArg { pub value: AnonConst, pub span: Span, } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum GenericArg { Lifetime(Lifetime), Type(Ty), @@ -422,7 +426,7 @@ impl GenericArg { } } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct GenericArgs { /// The generic arguments for this path segment. pub args: HirVec, @@ -486,7 +490,7 @@ impl GenericArgs { /// A modifier on a bound, currently this is only used for `?Sized`, where the /// modifier is `Maybe`. Negative bounds should also be handled here. -#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)] pub enum TraitBoundModifier { None, Maybe, @@ -496,7 +500,7 @@ pub enum TraitBoundModifier { /// `typeck::collect::compute_bounds` matches these against /// the "special" built-in traits (see `middle::lang_items`) and /// detects `Copy`, `Send` and `Sync`. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum GenericBound { Trait(PolyTraitRef, TraitBoundModifier), Outlives(Lifetime), @@ -513,7 +517,7 @@ impl GenericBound { pub type GenericBounds = HirVec; -#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum LifetimeParamKind { // Indicates that the lifetime definition was explicitly declared (e.g., in // `fn foo<'a>(x: &'a u8) -> &'a u8 { x }`). @@ -532,7 +536,7 @@ pub enum LifetimeParamKind { Error, } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum GenericParamKind { /// A lifetime definition (e.g., `'a: 'b + 'c + 'd`). Lifetime { @@ -547,7 +551,7 @@ pub enum GenericParamKind { } } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct GenericParam { pub hir_id: HirId, pub name: ParamName, @@ -568,7 +572,7 @@ pub struct GenericParamCount { /// Represents lifetimes and type parameters attached to a declaration /// of a function, enum, trait, etc. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct Generics { pub params: HirVec, pub where_clause: WhereClause, @@ -616,13 +620,13 @@ impl Generics { /// Synthetic type parameters are converted to another form during lowering; this allows /// us to track the original form they had, and is useful for error messages. -#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)] pub enum SyntheticTyParamKind { ImplTrait } /// A where-clause in a definition. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct WhereClause { pub hir_id: HirId, pub predicates: HirVec, @@ -641,7 +645,7 @@ impl WhereClause { } /// A single predicate in a where-clause. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum WherePredicate { /// A type binding (e.g., `for<'c> Foo: Send + Clone + 'c`). BoundPredicate(WhereBoundPredicate), @@ -662,7 +666,7 @@ impl WherePredicate { } /// A type bound (e.g., `for<'c> Foo: Send + Clone + 'c`). -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct WhereBoundPredicate { pub span: Span, /// Any generics from a `for` binding. @@ -674,7 +678,7 @@ pub struct WhereBoundPredicate { } /// A lifetime predicate (e.g., `'a: 'b + 'c`). -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct WhereRegionPredicate { pub span: Span, pub lifetime: Lifetime, @@ -682,7 +686,7 @@ pub struct WhereRegionPredicate { } /// An equality predicate (e.g., `T = int`); currently unsupported. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct WhereEqPredicate { pub hir_id: HirId, pub span: Span, @@ -801,7 +805,7 @@ impl Crate { /// A macro definition, in this crate or imported from another. /// /// Not parsed directly, but created on macro import or `macro_rules!` expansion. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct MacroDef { pub name: Name, pub vis: Visibility, @@ -812,13 +816,14 @@ pub struct MacroDef { pub legacy: bool, } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct Block { /// Statements in a block. pub stmts: HirVec, /// An expression at the end of the block /// without a semicolon, if any. pub expr: Option>, + #[stable_hasher(ignore)] pub hir_id: HirId, /// Distinguishes between `unsafe { ... }` and `{ ... }`. pub rules: BlockCheckMode, @@ -829,8 +834,9 @@ pub struct Block { pub targeted_by_break: bool, } -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)] pub struct Pat { + #[stable_hasher(ignore)] pub hir_id: HirId, pub node: PatKind, pub span: Span, @@ -891,10 +897,12 @@ impl Pat { /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` /// are treated the same as` x: x, y: ref y, z: ref mut z`, /// except `is_shorthand` is true. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct FieldPat { + #[stable_hasher(ignore)] pub hir_id: HirId, /// The identifier for the field. + #[stable_hasher(project(name))] pub ident: Ident, /// The pattern the field is destructured to. pub pat: P, @@ -904,7 +912,7 @@ pub struct FieldPat { /// Explicit binding annotations given in the HIR for a binding. Note /// that this is not the final binding *mode* that we infer after type /// inference. -#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)] +#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy, HashStable)] pub enum BindingAnnotation { /// No binding annotation given: this means that the final binding mode /// will depend on whether we have skipped through a `&` reference @@ -925,13 +933,13 @@ pub enum BindingAnnotation { RefMut, } -#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)] +#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum RangeEnd { Included, Excluded, } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum PatKind { /// Represents a wildcard pattern (i.e., `_`). Wild, @@ -976,7 +984,8 @@ pub enum PatKind { Slice(HirVec>, Option>, HirVec>), } -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, HashStable, + RustcEncodable, RustcDecodable, Hash, Debug, Copy)] pub enum Mutability { MutMutable, MutImmutable, @@ -992,7 +1001,7 @@ impl Mutability { } } -#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy, Hash)] +#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy, Hash, HashStable)] pub enum BinOpKind { /// The `+` operator (addition). Add, @@ -1126,7 +1135,7 @@ impl Into for BinOpKind { pub type BinOp = Spanned; -#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy, Hash)] +#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy, Hash, HashStable)] pub enum UnOp { /// The `*` operator (deferencing). UnDeref, @@ -1169,7 +1178,7 @@ impl fmt::Debug for Stmt { } } -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)] pub enum StmtKind { /// A local (`let`) binding. Local(P), @@ -1196,7 +1205,7 @@ impl StmtKind { } /// Represents a `let` statement (i.e., `let : = ;`). -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct Local { pub pat: P, pub ty: Option>, @@ -1209,7 +1218,7 @@ pub struct Local { } /// Represents a single arm of a `match` expression. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct Arm { pub attrs: HirVec, pub pats: HirVec>, @@ -1217,13 +1226,14 @@ pub struct Arm { pub body: P, } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum Guard { If(P), } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct Field { + #[stable_hasher(ignore)] pub hir_id: HirId, pub ident: Ident, pub expr: P, @@ -1231,7 +1241,7 @@ pub struct Field { pub is_shorthand: bool, } -#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)] +#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy, HashStable)] pub enum BlockCheckMode { DefaultBlock, UnsafeBlock(UnsafeSource), @@ -1239,7 +1249,7 @@ pub enum BlockCheckMode { PopUnsafeBlock(UnsafeSource), } -#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)] +#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy, HashStable)] pub enum UnsafeSource { CompilerGenerated, UserProvided, @@ -1315,7 +1325,7 @@ impl BodyOwnerKind { /// These are usually found nested inside types (e.g., array lengths) /// or expressions (e.g., repeat counts), and also used to define /// explicit discriminant values for enum variants. -#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct AnonConst { pub hir_id: HirId, pub body: BodyId, @@ -1431,7 +1441,7 @@ impl fmt::Debug for Expr { } } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum ExprKind { /// A `box x` expression. Box(P), @@ -1537,7 +1547,7 @@ pub enum ExprKind { } /// Optionally `Self`-qualified value/type path or associated extension. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum QPath { /// Path to a definition, optionally "fully-qualified" with a `Self` /// type, if the path points to an associated item in a trait. @@ -1557,7 +1567,7 @@ pub enum QPath { } /// Hints at the original code for a let statement. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, HashStable)] pub enum LocalSource { /// A `match _ { .. }`. Normal, @@ -1566,7 +1576,7 @@ pub enum LocalSource { } /// Hints at the original code for a `match _ { .. }`. -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy, HashStable)] pub enum MatchSource { /// A `match _ { .. }`. Normal, @@ -1584,7 +1594,7 @@ pub enum MatchSource { } /// The loop type that yielded an `ExprKind::Loop`. -#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)] +#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy, HashStable)] pub enum LoopSource { /// A `loop { .. }` loop. Loop, @@ -1594,7 +1604,7 @@ pub enum LoopSource { ForLoop, } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, HashStable)] pub enum LoopIdError { OutsideLoopScope, UnlabeledCfInWhileCondition, @@ -1612,7 +1622,7 @@ impl fmt::Display for LoopIdError { } } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, HashStable)] pub struct Destination { // This is `Some(_)` iff there is an explicit user-specified `label pub label: Option