diff --git a/Cargo.lock b/Cargo.lock index db2a5f9ec7c34..39ecc880097e3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2747,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", @@ -2778,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", 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/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 fb40bccee6abf..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")] 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/middle/dead.rs b/src/librustc/middle/dead.rs index 8ffd119f95c0b..94de999c25da8 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -3,7 +3,7 @@ // from live codes are live, and everything else is dead. use crate::hir::Node; -use crate::hir::{self, PatKind}; +use crate::hir::{self, PatKind, TyKind}; use crate::hir::intravisit::{self, Visitor, NestedVisitorMap}; use crate::hir::itemlikevisit::ItemLikeVisitor; @@ -282,6 +282,17 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { self.handle_definition(path.def); intravisit::walk_path(self, path); } + + fn visit_ty(&mut self, ty: &'tcx hir::Ty) { + match ty.node { + TyKind::Def(item_id, _) => { + let item = self.tcx.hir().expect_item(item_id.id); + intravisit::walk_item(self, item); + } + _ => () + } + intravisit::walk_ty(self, ty); + } } fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt<'_, '_, '_>, diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index 7648bde1d3c87..8c684c0775ee3 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -275,6 +275,8 @@ impl<'a, 'b, 'gcx, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'gcx, self.selcx.infcx().resolve_type_vars_if_possible(&obligation.predicate); } + debug!("process_obligation: obligation = {:?}", obligation); + match obligation.predicate { ty::Predicate::Trait(ref data) => { let trait_obligation = obligation.with(data.clone()); diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index b705968ce8aed..08b595c5eaa5a 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1443,16 +1443,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } - // This method exercises the `in_scope_traits_map` query for all possible - // values so that we have their fingerprints available in the DepGraph. - // This is only required as long as we still use the old dependency tracking - // which needs to have the fingerprints of all input nodes beforehand. - pub fn precompute_in_scope_traits_hashes(self) { - for &def_index in self.trait_map.keys() { - self.in_scope_traits_map(def_index); - } - } - pub fn serialize_query_result_cache(self, encoder: &mut E) -> Result<(), E::Error> diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index 599d38bc4ab6e..fa35416cdd498 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -482,8 +482,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { // // Note: in fact we only permit builtin traits, not `Bar<'d>`, I // am looking forward to the future here. - - if !data.has_escaping_bound_vars() { + if !data.has_escaping_bound_vars() && !region.has_escaping_bound_vars() { let implicit_bounds = object_region_bounds(self.infcx.tcx, data); diff --git a/src/librustc_codegen_llvm/debuginfo/doc.rs b/src/librustc_codegen_llvm/debuginfo/doc.rs index cf18b995b61da..daccfc9b242f9 100644 --- a/src/librustc_codegen_llvm/debuginfo/doc.rs +++ b/src/librustc_codegen_llvm/debuginfo/doc.rs @@ -1,13 +1,13 @@ //! # Debug Info Module //! //! This module serves the purpose of generating debug symbols. We use LLVM's -//! [source level debugging](http://!llvm.org/docs/SourceLevelDebugging.html) +//! [source level debugging](https://llvm.org/docs/SourceLevelDebugging.html) //! features for generating the debug information. The general principle is //! this: //! //! Given the right metadata in the LLVM IR, the LLVM code generator is able to //! create DWARF debug symbols for the given code. The -//! [metadata](http://!llvm.org/docs/LangRef.html#metadata-type) is structured +//! [metadata](https://llvm.org/docs/LangRef.html#metadata-type) is structured //! much like DWARF *debugging information entries* (DIE), representing type //! information such as datatype layout, function signatures, block layout, //! variable location and scope information, etc. It is the purpose of this @@ -15,7 +15,7 @@ //! //! As the exact format of metadata trees may change between different LLVM //! versions, we now use LLVM -//! [DIBuilder](http://!llvm.org/docs/doxygen/html/classllvm_1_1DIBuilder.html) +//! [DIBuilder](https://llvm.org/docs/doxygen/html/classllvm_1_1DIBuilder.html) //! to create metadata where possible. This will hopefully ease the adaption of //! this module to future LLVM versions. //! diff --git a/src/librustc_incremental/Cargo.toml b/src/librustc_incremental/Cargo.toml index 10b448b7fec3f..df971ec5bdb85 100644 --- a/src/librustc_incremental/Cargo.toml +++ b/src/librustc_incremental/Cargo.toml @@ -12,7 +12,7 @@ crate-type = ["dylib"] [dependencies] graphviz = { path = "../libgraphviz" } log = "0.4" -rand = "0.5" +rand = "0.6" rustc = { path = "../librustc" } rustc_data_structures = { path = "../librustc_data_structures" } serialize = { path = "../libserialize" } diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs index 4295034692958..255a3899d1183 100644 --- a/src/librustc_incremental/persist/load.rs +++ b/src/librustc_incremental/persist/load.rs @@ -21,7 +21,6 @@ pub fn dep_graph_tcx_init<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { } tcx.allocate_metadata_dep_nodes(); - tcx.precompute_in_scope_traits_hashes(); } type WorkProductMap = FxHashMap; diff --git a/src/librustc_interface/Cargo.toml b/src/librustc_interface/Cargo.toml index 1acd3dfc7656a..294e23dc6177c 100644 --- a/src/librustc_interface/Cargo.toml +++ b/src/librustc_interface/Cargo.toml @@ -12,7 +12,7 @@ crate-type = ["dylib"] log = "0.4" rustc-rayon = "0.1.1" smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } -scoped-tls = { version = "0.1.1", features = ["nightly"] } +scoped-tls = "1.0" syntax = { path = "../libsyntax" } syntax_ext = { path = "../libsyntax_ext" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs index 01f8cbfbe8e2b..d60a0941b5979 100644 --- a/src/librustc_mir/build/matches/simplify.rs +++ b/src/librustc_mir/build/matches/simplify.rs @@ -19,6 +19,7 @@ use rustc::ty; use rustc::ty::layout::{Integer, IntegerExt, Size}; use syntax::attr::{SignedInt, UnsignedInt}; use rustc::hir::RangeEnd; +use rustc::mir::interpret::truncate; use std::mem; @@ -115,14 +116,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ty::Int(ity) => { // FIXME(49937): refactor these bit manipulations into interpret. let size = Integer::from_attr(&tcx, SignedInt(ity)).size(); - let max = !0u128 >> (128 - size.bits()); + let max = truncate(u128::max_value(), size); let bias = 1u128 << (size.bits() - 1); (Some((0, max, size)), bias) } ty::Uint(uty) => { // FIXME(49937): refactor these bit manipulations into interpret. let size = Integer::from_attr(&tcx, UnsignedInt(uty)).size(); - let max = !0u128 >> (128 - size.bits()); + let max = truncate(u128::max_value(), size); (Some((0, max, size)), 0) } _ => (None, 0), diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 1e5f5d244e9c4..f79bf4e999d54 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -917,7 +917,7 @@ pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref); tcx.infer_ctxt().enter(|infcx| { - let param_env = ty::ParamEnv::empty(); + let param_env = tcx.param_env(impl_c.def_id); let inh = Inherited::new(infcx, impl_c.def_id); let infcx = &inh.infcx; diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 8a599c11b2095..f2111f2d9e028 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -850,7 +850,7 @@ impl Default for HashSet } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b, T, S> BitOr<&'b HashSet> for &'a HashSet +impl BitOr<&HashSet> for &HashSet where T: Eq + Hash + Clone, S: BuildHasher + Default { @@ -882,7 +882,7 @@ impl<'a, 'b, T, S> BitOr<&'b HashSet> for &'a HashSet } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b, T, S> BitAnd<&'b HashSet> for &'a HashSet +impl BitAnd<&HashSet> for &HashSet where T: Eq + Hash + Clone, S: BuildHasher + Default { @@ -914,7 +914,7 @@ impl<'a, 'b, T, S> BitAnd<&'b HashSet> for &'a HashSet } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b, T, S> BitXor<&'b HashSet> for &'a HashSet +impl BitXor<&HashSet> for &HashSet where T: Eq + Hash + Clone, S: BuildHasher + Default { @@ -946,7 +946,7 @@ impl<'a, 'b, T, S> BitXor<&'b HashSet> for &'a HashSet } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b, T, S> Sub<&'b HashSet> for &'a HashSet +impl Sub<&HashSet> for &HashSet where T: Eq + Hash + Clone, S: BuildHasher + Default { diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 2858308e8f8d5..3eb289501cb0f 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -337,7 +337,7 @@ impl From for Box { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b> From<&'b str> for Box { +impl<'a> From<&str> for Box { /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. /// /// # Examples @@ -351,13 +351,13 @@ impl<'a, 'b> From<&'b str> for Box { /// assert!( /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` - fn from(err: &'b str) -> Box { + fn from(err: &str) -> Box { From::from(String::from(err)) } } #[stable(feature = "string_box_error", since = "1.6.0")] -impl<'a> From<&'a str> for Box { +impl From<&str> for Box { /// Converts a [`str`] into a box of dyn [`Error`]. /// /// # Examples @@ -370,7 +370,7 @@ impl<'a> From<&'a str> for Box { /// let a_boxed_error = Box::::from(a_str_error); /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` - fn from(err: &'a str) -> Box { + fn from(err: &str) -> Box { From::from(String::from(err)) } } diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 139680e526fd6..ad3f45bfadaf4 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -690,8 +690,8 @@ impl<'a> From> for CString { } #[stable(feature = "box_from_c_str", since = "1.17.0")] -impl<'a> From<&'a CStr> for Box { - fn from(s: &'a CStr) -> Box { +impl From<&CStr> for Box { + fn from(s: &CStr) -> Box { let boxed: Box<[u8]> = Box::from(s.to_bytes_with_nul()); unsafe { Box::from_raw(Box::into_raw(boxed) as *mut CStr) } } @@ -767,7 +767,7 @@ impl From for Arc { } #[stable(feature = "shared_from_slice2", since = "1.24.0")] -impl<'a> From<&'a CStr> for Arc { +impl From<&CStr> for Arc { #[inline] fn from(s: &CStr) -> Arc { let arc: Arc<[u8]> = Arc::from(s.to_bytes_with_nul()); @@ -789,7 +789,7 @@ impl From for Rc { } #[stable(feature = "shared_from_slice2", since = "1.24.0")] -impl<'a> From<&'a CStr> for Rc { +impl From<&CStr> for Rc { #[inline] fn from(s: &CStr) -> Rc { let rc: Rc<[u8]> = Rc::from(s.to_bytes_with_nul()); @@ -1268,8 +1268,8 @@ impl ToOwned for CStr { } #[stable(feature = "cstring_asref", since = "1.7.0")] -impl<'a> From<&'a CStr> for CString { - fn from(s: &'a CStr) -> CString { +impl From<&CStr> for CString { + fn from(s: &CStr) -> CString { s.to_owned() } } diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index f68eaeb9c7e1f..3a0590021c917 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -357,8 +357,8 @@ impl From for OsString { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T: ?Sized + AsRef> From<&'a T> for OsString { - fn from(s: &'a T) -> OsString { +impl> From<&T> for OsString { + fn from(s: &T) -> OsString { s.as_ref().to_os_string() } } @@ -421,8 +421,8 @@ impl PartialEq for str { } #[stable(feature = "os_str_str_ref_eq", since = "1.29.0")] -impl<'a> PartialEq<&'a str> for OsString { - fn eq(&self, other: &&'a str) -> bool { +impl PartialEq<&str> for OsString { + fn eq(&self, other: &&str) -> bool { **self == **other } } @@ -656,8 +656,8 @@ impl OsStr { } #[stable(feature = "box_from_os_str", since = "1.17.0")] -impl<'a> From<&'a OsStr> for Box { - fn from(s: &'a OsStr) -> Box { +impl From<&OsStr> for Box { + fn from(s: &OsStr) -> Box { let rw = Box::into_raw(s.inner.into_box()) as *mut OsStr; unsafe { Box::from_raw(rw) } } @@ -707,7 +707,7 @@ impl From for Arc { } #[stable(feature = "shared_from_slice2", since = "1.24.0")] -impl<'a> From<&'a OsStr> for Arc { +impl From<&OsStr> for Arc { #[inline] fn from(s: &OsStr) -> Arc { let arc = s.inner.into_arc(); @@ -729,7 +729,7 @@ impl From for Rc { } #[stable(feature = "shared_from_slice2", since = "1.24.0")] -impl<'a> From<&'a OsStr> for Rc { +impl From<&OsStr> for Rc { #[inline] fn from(s: &OsStr) -> Rc { let rc = s.inner.into_rc(); diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 858a5778b8161..ea3fcd8ce2859 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -1456,8 +1456,8 @@ impl PathBuf { } #[stable(feature = "box_from_path", since = "1.17.0")] -impl<'a> From<&'a Path> for Box { - fn from(path: &'a Path) -> Box { +impl From<&Path> for Box { + fn from(path: &Path) -> Box { let boxed: Box = path.inner.into(); let rw = Box::into_raw(boxed) as *mut Path; unsafe { Box::from_raw(rw) } @@ -1494,8 +1494,8 @@ impl Clone for Box { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T: ?Sized + AsRef> From<&'a T> for PathBuf { - fn from(s: &'a T) -> PathBuf { +impl> From<&T> for PathBuf { + fn from(s: &T) -> PathBuf { PathBuf::from(s.as_ref().to_os_string()) } } @@ -1630,7 +1630,7 @@ impl From for Arc { } #[stable(feature = "shared_from_slice2", since = "1.24.0")] -impl<'a> From<&'a Path> for Arc { +impl From<&Path> for Arc { /// Converts a Path into a Rc by copying the Path data into a new Rc buffer. #[inline] fn from(s: &Path) -> Arc { @@ -1650,7 +1650,7 @@ impl From for Rc { } #[stable(feature = "shared_from_slice2", since = "1.24.0")] -impl<'a> From<&'a Path> for Rc { +impl From<&Path> for Rc { /// Converts a Path into a Rc by copying the Path data into a new Rc buffer. #[inline] fn from(s: &Path) -> Rc { diff --git a/src/libstd/sys/cloudabi/shims/net.rs b/src/libstd/sys/cloudabi/shims/net.rs index 50d72dc7b240b..6d2a4962ab444 100644 --- a/src/libstd/sys/cloudabi/shims/net.rs +++ b/src/libstd/sys/cloudabi/shims/net.rs @@ -297,10 +297,10 @@ impl Iterator for LookupHost { } } -impl<'a> TryFrom<&'a str> for LookupHost { +impl TryFrom<&str> for LookupHost { type Error = io::Error; - fn try_from(_v: &'a str) -> io::Result { + fn try_from(_v: &str) -> io::Result { unsupported() } } diff --git a/src/libstd/sys/redox/net/mod.rs b/src/libstd/sys/redox/net/mod.rs index a172763f61313..dbaa140ed8a0f 100644 --- a/src/libstd/sys/redox/net/mod.rs +++ b/src/libstd/sys/redox/net/mod.rs @@ -35,7 +35,7 @@ impl Iterator for LookupHost { } } -impl<'a> TryFrom<&'a str> for LookupHost { +impl TryFrom<&str> for LookupHost { type Error = io::Error; fn try_from(s: &str) -> io::Result { diff --git a/src/libstd/sys/sgx/net.rs b/src/libstd/sys/sgx/net.rs index ab8b2681393f8..e5e42e3d0b048 100644 --- a/src/libstd/sys/sgx/net.rs +++ b/src/libstd/sys/sgx/net.rs @@ -420,10 +420,10 @@ impl Iterator for LookupHost { } } -impl<'a> TryFrom<&'a str> for LookupHost { +impl TryFrom<&str> for LookupHost { type Error = io::Error; - fn try_from(v: &'a str) -> io::Result { + fn try_from(v: &str) -> io::Result { LookupHost::new(v.to_owned()) } } diff --git a/src/libstd/sys/unix/l4re.rs b/src/libstd/sys/unix/l4re.rs index b6e8cc738946b..b9e725371a36e 100644 --- a/src/libstd/sys/unix/l4re.rs +++ b/src/libstd/sys/unix/l4re.rs @@ -447,10 +447,10 @@ pub mod net { unsafe impl Send for LookupHost {} - impl<'a> TryFrom<&'a str> for LookupHost { + impl TryFrom<&str> for LookupHost { type Error = io::Error; - fn try_from(_v: &'a str) -> io::Result { + fn try_from(_v: &str) -> io::Result { unimpl!(); } } diff --git a/src/libstd/sys/wasm/net.rs b/src/libstd/sys/wasm/net.rs index 1249832fb09d2..a2ea2dfbbc032 100644 --- a/src/libstd/sys/wasm/net.rs +++ b/src/libstd/sys/wasm/net.rs @@ -298,10 +298,10 @@ impl Iterator for LookupHost { } } -impl<'a> TryFrom<&'a str> for LookupHost { +impl TryFrom<&str> for LookupHost { type Error = io::Error; - fn try_from(_v: &'a str) -> io::Result { + fn try_from(_v: &str) -> io::Result { unsupported() } } diff --git a/src/libstd/sys_common/net.rs b/src/libstd/sys_common/net.rs index 36721171b1733..b9505aaa69ba5 100644 --- a/src/libstd/sys_common/net.rs +++ b/src/libstd/sys_common/net.rs @@ -157,7 +157,7 @@ impl Drop for LookupHost { } } -impl<'a> TryFrom<&'a str> for LookupHost { +impl TryFrom<&str> for LookupHost { type Error = io::Error; fn try_from(s: &str) -> io::Result { diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index db5b8dcda4eab..01e3b29290318 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -1423,15 +1423,17 @@ impl<'a> StringReader<'a> { // If the character is an ident start not followed by another single // quote, then this is a lifetime name: - if ident_start(Some(c2)) && !self.ch_is('\'') { + if (ident_start(Some(c2)) || c2.is_numeric()) && !self.ch_is('\'') { while ident_continue(self.ch) { self.bump(); } // lifetimes shouldn't end with a single quote // if we find one, then this is an invalid character literal if self.ch_is('\'') { - self.err_span_(start_with_quote, self.next_pos, - "character literal may only contain one codepoint"); + self.err_span_( + start_with_quote, + self.next_pos, + "character literal may only contain one codepoint"); self.bump(); return Ok(token::Literal(token::Err(Symbol::intern("??")), None)) @@ -1444,6 +1446,15 @@ impl<'a> StringReader<'a> { self.mk_ident(&format!("'{}", lifetime_name)) }); + if c2.is_numeric() { + // this is a recovered lifetime written `'1`, error but accept it + self.err_span_( + start_with_quote, + self.pos, + "lifetimes cannot start with a number", + ); + } + return Ok(token::Lifetime(ident)); } @@ -1873,6 +1884,7 @@ fn is_block_doc_comment(s: &str) -> bool { res } +/// Determine whether `c` is a valid start for an ident. fn ident_start(c: Option) -> bool { let c = match c { Some(c) => c, diff --git a/src/test/ui/associated-const/associated-const-generic-obligations.rs b/src/test/ui/associated-const/associated-const-generic-obligations.rs index e0b502edaa15e..498e315b5c83c 100644 --- a/src/test/ui/associated-const/associated-const-generic-obligations.rs +++ b/src/test/ui/associated-const/associated-const-generic-obligations.rs @@ -12,7 +12,7 @@ trait Bar: Foo { impl Bar for T { const FROM: &'static str = "foo"; - //~^ ERROR the trait bound `T: Foo` is not satisfied [E0277] + //~^ ERROR implemented const `FROM` has an incompatible type for trait [E0326] } fn main() {} diff --git a/src/test/ui/associated-const/associated-const-generic-obligations.stderr b/src/test/ui/associated-const/associated-const-generic-obligations.stderr index e4b86d84cafc9..eeee26a75671f 100644 --- a/src/test/ui/associated-const/associated-const-generic-obligations.stderr +++ b/src/test/ui/associated-const/associated-const-generic-obligations.stderr @@ -1,11 +1,15 @@ -error[E0277]: the trait bound `T: Foo` is not satisfied - --> $DIR/associated-const-generic-obligations.rs:14:5 +error[E0326]: implemented const `FROM` has an incompatible type for trait + --> $DIR/associated-const-generic-obligations.rs:14:17 | +LL | const FROM: Self::Out; + | --------- type in trait +... LL | const FROM: &'static str = "foo"; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `T` + | ^^^^^^^^^^^^ expected associated type, found reference | - = help: consider adding a `where T: Foo` bound + = note: expected type `::Out` + found type `&'static str` error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0326`. diff --git a/src/test/ui/associated-const/associated-const-trait-bound.rs b/src/test/ui/associated-const/associated-const-trait-bound.rs new file mode 100644 index 0000000000000..0ce46d312afef --- /dev/null +++ b/src/test/ui/associated-const/associated-const-trait-bound.rs @@ -0,0 +1,21 @@ +// compile-pass + +trait ConstDefault { + const DEFAULT: Self; +} + +trait Foo: Sized {} + +trait FooExt: Foo { + type T: ConstDefault; +} + +trait Bar { + const T: F::T; +} + +impl Bar for () { + const T: F::T = ::DEFAULT; +} + +fn main() {} diff --git a/src/test/ui/generator/issue-53548-1.rs b/src/test/ui/generator/issue-53548-1.rs new file mode 100644 index 0000000000000..df11800731c72 --- /dev/null +++ b/src/test/ui/generator/issue-53548-1.rs @@ -0,0 +1,20 @@ +// A variant of #53548 that does not actually require generators, +// but which encountered the same ICE/error. See `issue-53548.rs` +// for details. +// +// compile-pass + +use std::cell::RefCell; +use std::rc::Rc; + +trait Trait: 'static {} + +struct Store { + inner: Rc>>, +} + +fn main() { + let store = Store:: fn(&(dyn Trait + 'a))>> { + inner: Default::default(), + }; +} diff --git a/src/test/ui/generator/issue-53548.rs b/src/test/ui/generator/issue-53548.rs new file mode 100644 index 0000000000000..00fdb91faab76 --- /dev/null +++ b/src/test/ui/generator/issue-53548.rs @@ -0,0 +1,39 @@ +// Regression test for #53548. The `Box` type below is +// expanded to `Box`, but the generator "witness" +// that results is `for<'r> { Box }`. The WF code was +// encountering an ICE (when debug-assertions were enabled) and an +// unexpected compilation error (without debug-asserions) when trying +// to process this `'r` region bound. In particular, to be WF, the +// region bound must meet the requirements of the trait, and hence we +// got `for<'r> { 'r: 'static }`. This would ICE because the `Binder` +// constructor we were using was assering that no higher-ranked +// regions were involved (because the WF code is supposed to skip +// those). The error (if debug-asserions were disabled) came because +// we obviously cannot prove that `'r: 'static` for any region `'r`. +// Pursuant with our "lazy WF" strategy for higher-ranked regions, the +// fix is not to require that `for<'r> { 'r: 'static }` holds (this is +// also analogous to what we would do for higher-ranked regions +// appearing within the trait in other positions). +// +// compile-pass + +#![feature(generators)] + +use std::cell::RefCell; +use std::rc::Rc; + +trait Trait: 'static {} + +struct Store { + inner: Rc>>, +} + +fn main() { + Box::new(static move || { + let store = Store::> { + inner: Default::default(), + }; + yield (); + }); +} + diff --git a/src/test/ui/lint/lint-dead-code-impl-trait.rs b/src/test/ui/lint/lint-dead-code-impl-trait.rs new file mode 100644 index 0000000000000..a2736d97308af --- /dev/null +++ b/src/test/ui/lint/lint-dead-code-impl-trait.rs @@ -0,0 +1,18 @@ +#![deny(dead_code)] + +trait Trait { + type Type; +} + +impl Trait for () { + type Type = (); +} + +type Used = (); +type Unused = (); //~ ERROR type alias is never used + +fn foo() -> impl Trait {} + +fn main() { + foo(); +} diff --git a/src/test/ui/lint/lint-dead-code-impl-trait.stderr b/src/test/ui/lint/lint-dead-code-impl-trait.stderr new file mode 100644 index 0000000000000..61d0954bf3146 --- /dev/null +++ b/src/test/ui/lint/lint-dead-code-impl-trait.stderr @@ -0,0 +1,14 @@ +error: type alias is never used: `Unused` + --> $DIR/lint-dead-code-impl-trait.rs:12:1 + | +LL | type Unused = (); + | ^^^^^^^^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/lint-dead-code-impl-trait.rs:1:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/nll/trait-associated-constant.rs b/src/test/ui/nll/trait-associated-constant.rs index 9d3e1a690f001..31dc58185e90a 100644 --- a/src/test/ui/nll/trait-associated-constant.rs +++ b/src/test/ui/nll/trait-associated-constant.rs @@ -9,24 +9,23 @@ trait Anything<'a: 'b, 'b> { const AC: Option<&'b str>; } -struct OKStruct { } +struct OKStruct1 { } -impl<'a: 'b, 'b> Anything<'a, 'b> for OKStruct { +impl<'a: 'b, 'b> Anything<'a, 'b> for OKStruct1 { const AC: Option<&'b str> = None; } -struct FailStruct1 { } +struct FailStruct { } -impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct1 { +impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct { const AC: Option<&'c str> = None; //~^ ERROR: mismatched types } -struct FailStruct2 { } +struct OKStruct2 { } -impl<'a: 'b, 'b> Anything<'a, 'b> for FailStruct2 { +impl<'a: 'b, 'b> Anything<'a, 'b> for OKStruct2 { const AC: Option<&'a str> = None; - //~^ ERROR: mismatched types } fn main() {} diff --git a/src/test/ui/nll/trait-associated-constant.stderr b/src/test/ui/nll/trait-associated-constant.stderr index 78ef513f3eecb..f39f668e2329a 100644 --- a/src/test/ui/nll/trait-associated-constant.stderr +++ b/src/test/ui/nll/trait-associated-constant.stderr @@ -9,33 +9,14 @@ LL | const AC: Option<&'c str> = None; note: the lifetime 'c as defined on the impl at 20:18... --> $DIR/trait-associated-constant.rs:20:18 | -LL | impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct1 { +LL | impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct { | ^^ note: ...does not necessarily outlive the lifetime 'b as defined on the impl at 20:14 --> $DIR/trait-associated-constant.rs:20:14 | -LL | impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct1 { +LL | impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct { | ^^ -error[E0308]: mismatched types - --> $DIR/trait-associated-constant.rs:28:5 - | -LL | const AC: Option<&'a str> = None; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch - | - = note: expected type `std::option::Option<&'b str>` - found type `std::option::Option<&'a str>` -note: the lifetime 'a as defined on the impl at 27:6... - --> $DIR/trait-associated-constant.rs:27:6 - | -LL | impl<'a: 'b, 'b> Anything<'a, 'b> for FailStruct2 { - | ^^ -note: ...does not necessarily outlive the lifetime 'b as defined on the impl at 27:14 - --> $DIR/trait-associated-constant.rs:27:14 - | -LL | impl<'a: 'b, 'b> Anything<'a, 'b> for FailStruct2 { - | ^^ - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/numeric-lifetime.rs b/src/test/ui/parser/numeric-lifetime.rs new file mode 100644 index 0000000000000..2d82354c62cca --- /dev/null +++ b/src/test/ui/parser/numeric-lifetime.rs @@ -0,0 +1,8 @@ +struct S<'1> { s: &'1 usize } +//~^ ERROR lifetimes cannot start with a number +//~| ERROR lifetimes cannot start with a number +fn main() { + // verify that the parse error doesn't stop type checking + let x: usize = ""; + //~^ ERROR mismatched types +} diff --git a/src/test/ui/parser/numeric-lifetime.stderr b/src/test/ui/parser/numeric-lifetime.stderr new file mode 100644 index 0000000000000..4018b24aac175 --- /dev/null +++ b/src/test/ui/parser/numeric-lifetime.stderr @@ -0,0 +1,24 @@ +error: lifetimes cannot start with a number + --> $DIR/numeric-lifetime.rs:1:10 + | +LL | struct S<'1> { s: &'1 usize } + | ^^ + +error: lifetimes cannot start with a number + --> $DIR/numeric-lifetime.rs:1:20 + | +LL | struct S<'1> { s: &'1 usize } + | ^^ + +error[E0308]: mismatched types + --> $DIR/numeric-lifetime.rs:6:20 + | +LL | let x: usize = ""; + | ^^ expected usize, found reference + | + = note: expected type `usize` + found type `&'static str` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`.