Auto merge of #59151 - Centril:rollup, r=Centril

Rollup of 16 pull requests

Successful merges:

 - #58829 (librustc_interface: Update scoped-tls to 1.0)
 - #58876 (Parse lifetimes that start with a number and give specific error)
 - #58908 (Update rand version)
 - #58998 (Fix documentation of from_ne_bytes and from_le_bytes)
 - #59056 (Use lifetime contravariance to elide more lifetimes in core+alloc+std)
 - #59057 (Standardize `Range*` documentation)
 - #59080 (Fix incorrect links in librustc_codegen_llvm documentation)
 - #59083 (Fix #54822 and associated faulty tests)
 - #59093 (Remove precompute_in_scope_traits_hashes)
 - #59101 (Reduces Code Repetitions like `!n >> amt`)
 - #59121 (impl FromIterator for Result: Use assert_eq! instead of assert!)
 - #59124 (Replace assert with assert_eq)
 - #59129 (Visit impl Trait for dead_code lint)
 - #59130 (Note that NonNull does not launder shared references for mutation)
 - #59132 (ignore higher-ranked object bound conditions created by WF)
 - #59138 (Simplify Iterator::{min, max})

Failed merges:

r? @ghost
This commit is contained in:
bors 2019-03-13 03:30:20 +00:00
commit aa97448caf
49 changed files with 526 additions and 367 deletions

View File

@ -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",

View File

@ -489,7 +489,7 @@ impl<T: ?Sized> From<Box<T>> for Pin<Box<T>> {
}
#[stable(feature = "box_from_slice", since = "1.17.0")]
impl<'a, T: Copy> From<&'a [T]> for Box<[T]> {
impl<T: Copy> 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<str> {
impl From<&str> for Box<str> {
/// Converts a `&str` into a `Box<str>`
///
/// This conversion allocates on the heap
@ -523,7 +523,7 @@ impl<'a> From<&'a str> for Box<str> {
/// println!("{}", boxed);
/// ```
#[inline]
fn from(s: &'a str) -> Box<str> {
fn from(s: &str) -> Box<str> {
unsafe { from_boxed_utf8_unchecked(Box::from(s.as_bytes())) }
}
}

View File

@ -1145,7 +1145,7 @@ impl<T> From<T> for Rc<T> {
}
#[stable(feature = "shared_from_slice", since = "1.21.0")]
impl<'a, T: Clone> From<&'a [T]> for Rc<[T]> {
impl<T: Clone> From<&[T]> for Rc<[T]> {
#[inline]
fn from(v: &[T]) -> Rc<[T]> {
<Self as RcFromSlice<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<str> {
impl From<&str> for Rc<str> {
#[inline]
fn from(v: &str) -> Rc<str> {
let rc = Rc::<[u8]>::from(v.as_bytes());

View File

@ -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()
}
}

View File

@ -2182,25 +2182,25 @@ impl<T> AsMut<[T]> for Vec<T> {
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: Clone> From<&'a [T]> for Vec<T> {
impl<T: Clone> From<&[T]> for Vec<T> {
#[cfg(not(test))]
fn from(s: &'a [T]) -> Vec<T> {
fn from(s: &[T]) -> Vec<T> {
s.to_vec()
}
#[cfg(test)]
fn from(s: &'a [T]) -> Vec<T> {
fn from(s: &[T]) -> Vec<T> {
crate::slice::to_vec(s)
}
}
#[stable(feature = "vec_from_mut", since = "1.19.0")]
impl<'a, T: Clone> From<&'a mut [T]> for Vec<T> {
impl<T: Clone> From<&mut [T]> for Vec<T> {
#[cfg(not(test))]
fn from(s: &'a mut [T]) -> Vec<T> {
fn from(s: &mut [T]) -> Vec<T> {
s.to_vec()
}
#[cfg(test)]
fn from(s: &'a mut [T]) -> Vec<T> {
fn from(s: &mut [T]) -> Vec<T> {
crate::slice::to_vec(s)
}
}
@ -2231,8 +2231,8 @@ impl<T> From<Vec<T>> for Box<[T]> {
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> From<&'a str> for Vec<u8> {
fn from(s: &'a str) -> Vec<u8> {
impl From<&str> for Vec<u8> {
fn from(s: &str) -> Vec<u8> {
From::from(s.as_bytes())
}
}

View File

@ -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<T> TryFrom<&[T]> for [T; $N] where T: Copy {
type Error = TryFromSliceError;
fn try_from(slice: &[T]) -> Result<[T; $N], TryFromSliceError> {

View File

@ -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()
})
}

View File

@ -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<B> {
impl<A: ?Sized, B: ?Sized> PartialEq<&B> for &A where A: PartialEq<B> {
#[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<B> {
impl<A: ?Sized, B: ?Sized> PartialOrd<&B> for &A where A: PartialOrd<B> {
#[inline]
fn partial_cmp(&self, other: &&'b B) -> Option<Ordering> {
fn partial_cmp(&self, other: &&B) -> Option<Ordering> {
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<A: ?Sized> 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<B> {
impl<A: ?Sized, B: ?Sized> PartialEq<&mut B> for &mut A where A: PartialEq<B> {
#[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<B> {
impl<A: ?Sized, B: ?Sized> PartialOrd<&mut B> for &mut A where A: PartialOrd<B> {
#[inline]
fn partial_cmp(&self, other: &&'b mut B) -> Option<Ordering> {
fn partial_cmp(&self, other: &&mut B) -> Option<Ordering> {
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<A: ?Sized> Ord for &mut A where A: Ord {
@ -1066,18 +1066,18 @@ mod impls {
impl<A: ?Sized> 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<B> {
impl<A: ?Sized, B: ?Sized> PartialEq<&mut B> for &A where A: PartialEq<B> {
#[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<B> {
impl<A: ?Sized, B: ?Sized> PartialEq<&B> for &mut A where A: PartialEq<B> {
#[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) }
}
}

View File

@ -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);
}
}

View File

@ -2008,12 +2008,7 @@ pub trait Iterator {
#[stable(feature = "rust1", since = "1.0.0")]
fn max(self) -> Option<Self::Item> 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<Self::Item> 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<B: Ord, F>(self, f: F) -> Option<Self::Item>
fn max_by_key<B: Ord, F>(self, mut f: F) -> Option<Self::Item>
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<F>(self, mut compare: F) -> Option<Self::Item>
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<B: Ord, F>(self, f: F) -> Option<Self::Item>
fn min_by_key<B: Ord, F>(self, mut f: F) -> Option<Self::Item>
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<F>(self, mut compare: F) -> Option<Self::Item>
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<I, B, FProj, FCmp>(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<I, F>(mut it: I, mut f: F) -> Option<I::Item>
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 })
})
}

View File

@ -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")]

View File

@ -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<Idx: PartialOrd<Idx>> Range<Idx> {
/// 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<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
/// 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<Idx: PartialOrd<Idx>> RangeTo<Idx> {
/// 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<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
/// 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<T> {
#[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<T: ?Sized> {
/// Start index bound.
///

View File

@ -2837,15 +2837,15 @@ impl<T: ?Sized> fmt::Pointer for Unique<T> {
}
#[unstable(feature = "ptr_internals", issue = "0")]
impl<'a, T: ?Sized> From<&'a mut T> for Unique<T> {
fn from(reference: &'a mut T) -> Self {
impl<T: ?Sized> From<&mut T> for Unique<T> {
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<T> {
fn from(reference: &'a T) -> Self {
impl<T: ?Sized> From<&T> for Unique<T> {
fn from(reference: &T) -> Self {
unsafe { Unique { pointer: reference as *const T, _marker: PhantomData } }
}
}
@ -2874,6 +2874,16 @@ impl<'a, T: ?Sized> From<NonNull<T>> for Unique<T> {
/// 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<T>` 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<T>`]. The same goes for creating a mutable reference from a shared
/// reference. When using this `From` instance without an `UnsafeCell<T>`,
/// it is your responsibility to ensure that `as_mut` is never called, and `as_ptr`
/// is never used for mutation.
///
/// [`UnsafeCell<T>`]: ../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<T: ?Sized> From<Unique<T>> for NonNull<T> {
}
#[stable(feature = "nonnull", since = "1.25.0")]
impl<'a, T: ?Sized> From<&'a mut T> for NonNull<T> {
impl<T: ?Sized> From<&mut T> for NonNull<T> {
#[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<T> {
impl<T: ?Sized> From<&T> for NonNull<T> {
#[inline]
fn from(reference: &'a T) -> Self {
fn from(reference: &T) -> Self {
unsafe { NonNull { pointer: reference as *const T } }
}
}

View File

@ -1200,7 +1200,7 @@ impl<A, E, V: FromIterator<A>> FromIterator<Result<A, E>> for Result<V, E> {
/// let res: Result<Vec<u32>, &'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<I: IntoIterator<Item=Result<A, E>>>(iter: I) -> Result<V, E> {

View File

@ -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]");
}

View File

@ -1082,12 +1082,39 @@ fn test_iterator_product_result() {
assert_eq!(v.iter().cloned().product::<Result<i32, _>>(), 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<core::cmp::Ordering> {
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]

View File

@ -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<'_, '_, '_>,

View File

@ -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());

View File

@ -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<E>(self,
encoder: &mut E)
-> Result<(), E::Error>

View File

@ -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);

View File

@ -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.
//!

View File

@ -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" }

View File

@ -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<WorkProductId, WorkProduct>;

View File

@ -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" }

View File

@ -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),

View File

@ -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;

View File

@ -850,7 +850,7 @@ impl<T, S> Default for HashSet<T, S>
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, 'b, T, S> BitOr<&'b HashSet<T, S>> for &'a HashSet<T, S>
impl<T, S> BitOr<&HashSet<T, S>> for &HashSet<T, S>
where T: Eq + Hash + Clone,
S: BuildHasher + Default
{
@ -882,7 +882,7 @@ impl<'a, 'b, T, S> BitOr<&'b HashSet<T, S>> for &'a HashSet<T, S>
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, 'b, T, S> BitAnd<&'b HashSet<T, S>> for &'a HashSet<T, S>
impl<T, S> BitAnd<&HashSet<T, S>> for &HashSet<T, S>
where T: Eq + Hash + Clone,
S: BuildHasher + Default
{
@ -914,7 +914,7 @@ impl<'a, 'b, T, S> BitAnd<&'b HashSet<T, S>> for &'a HashSet<T, S>
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, 'b, T, S> BitXor<&'b HashSet<T, S>> for &'a HashSet<T, S>
impl<T, S> BitXor<&HashSet<T, S>> for &HashSet<T, S>
where T: Eq + Hash + Clone,
S: BuildHasher + Default
{
@ -946,7 +946,7 @@ impl<'a, 'b, T, S> BitXor<&'b HashSet<T, S>> for &'a HashSet<T, S>
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, 'b, T, S> Sub<&'b HashSet<T, S>> for &'a HashSet<T, S>
impl<T, S> Sub<&HashSet<T, S>> for &HashSet<T, S>
where T: Eq + Hash + Clone,
S: BuildHasher + Default
{

View File

@ -337,7 +337,7 @@ impl From<String> for Box<dyn Error> {
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, 'b> From<&'b str> for Box<dyn Error + Send + Sync + 'a> {
impl<'a> From<&str> for Box<dyn Error + Send + Sync + 'a> {
/// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
///
/// # Examples
@ -351,13 +351,13 @@ impl<'a, 'b> From<&'b str> for Box<dyn Error + Send + Sync + 'a> {
/// assert!(
/// mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
/// ```
fn from(err: &'b str) -> Box<dyn Error + Send + Sync + 'a> {
fn from(err: &str) -> Box<dyn Error + Send + Sync + 'a> {
From::from(String::from(err))
}
}
#[stable(feature = "string_box_error", since = "1.6.0")]
impl<'a> From<&'a str> for Box<dyn Error> {
impl From<&str> for Box<dyn Error> {
/// Converts a [`str`] into a box of dyn [`Error`].
///
/// # Examples
@ -370,7 +370,7 @@ impl<'a> From<&'a str> for Box<dyn Error> {
/// let a_boxed_error = Box::<Error>::from(a_str_error);
/// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
/// ```
fn from(err: &'a str) -> Box<dyn Error> {
fn from(err: &str) -> Box<dyn Error> {
From::from(String::from(err))
}
}

View File

@ -690,8 +690,8 @@ impl<'a> From<Cow<'a, CStr>> for CString {
}
#[stable(feature = "box_from_c_str", since = "1.17.0")]
impl<'a> From<&'a CStr> for Box<CStr> {
fn from(s: &'a CStr) -> Box<CStr> {
impl From<&CStr> for Box<CStr> {
fn from(s: &CStr) -> Box<CStr> {
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<CString> for Arc<CStr> {
}
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl<'a> From<&'a CStr> for Arc<CStr> {
impl From<&CStr> for Arc<CStr> {
#[inline]
fn from(s: &CStr) -> Arc<CStr> {
let arc: Arc<[u8]> = Arc::from(s.to_bytes_with_nul());
@ -789,7 +789,7 @@ impl From<CString> for Rc<CStr> {
}
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl<'a> From<&'a CStr> for Rc<CStr> {
impl From<&CStr> for Rc<CStr> {
#[inline]
fn from(s: &CStr) -> Rc<CStr> {
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()
}
}

View File

@ -357,8 +357,8 @@ impl From<String> for OsString {
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized + AsRef<OsStr>> From<&'a T> for OsString {
fn from(s: &'a T) -> OsString {
impl<T: ?Sized + AsRef<OsStr>> From<&T> for OsString {
fn from(s: &T) -> OsString {
s.as_ref().to_os_string()
}
}
@ -421,8 +421,8 @@ impl PartialEq<OsString> 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<OsStr> {
fn from(s: &'a OsStr) -> Box<OsStr> {
impl From<&OsStr> for Box<OsStr> {
fn from(s: &OsStr) -> Box<OsStr> {
let rw = Box::into_raw(s.inner.into_box()) as *mut OsStr;
unsafe { Box::from_raw(rw) }
}
@ -707,7 +707,7 @@ impl From<OsString> for Arc<OsStr> {
}
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl<'a> From<&'a OsStr> for Arc<OsStr> {
impl From<&OsStr> for Arc<OsStr> {
#[inline]
fn from(s: &OsStr) -> Arc<OsStr> {
let arc = s.inner.into_arc();
@ -729,7 +729,7 @@ impl From<OsString> for Rc<OsStr> {
}
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl<'a> From<&'a OsStr> for Rc<OsStr> {
impl From<&OsStr> for Rc<OsStr> {
#[inline]
fn from(s: &OsStr) -> Rc<OsStr> {
let rc = s.inner.into_rc();

View File

@ -1456,8 +1456,8 @@ impl PathBuf {
}
#[stable(feature = "box_from_path", since = "1.17.0")]
impl<'a> From<&'a Path> for Box<Path> {
fn from(path: &'a Path) -> Box<Path> {
impl From<&Path> for Box<Path> {
fn from(path: &Path) -> Box<Path> {
let boxed: Box<OsStr> = 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<Path> {
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized + AsRef<OsStr>> From<&'a T> for PathBuf {
fn from(s: &'a T) -> PathBuf {
impl<T: ?Sized + AsRef<OsStr>> From<&T> for PathBuf {
fn from(s: &T) -> PathBuf {
PathBuf::from(s.as_ref().to_os_string())
}
}
@ -1630,7 +1630,7 @@ impl From<PathBuf> for Arc<Path> {
}
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl<'a> From<&'a Path> for Arc<Path> {
impl From<&Path> for Arc<Path> {
/// Converts a Path into a Rc by copying the Path data into a new Rc buffer.
#[inline]
fn from(s: &Path) -> Arc<Path> {
@ -1650,7 +1650,7 @@ impl From<PathBuf> for Rc<Path> {
}
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl<'a> From<&'a Path> for Rc<Path> {
impl From<&Path> for Rc<Path> {
/// Converts a Path into a Rc by copying the Path data into a new Rc buffer.
#[inline]
fn from(s: &Path) -> Rc<Path> {

View File

@ -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<LookupHost> {
fn try_from(_v: &str) -> io::Result<LookupHost> {
unsupported()
}
}

View File

@ -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<LookupHost> {

View File

@ -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<LookupHost> {
fn try_from(v: &str) -> io::Result<LookupHost> {
LookupHost::new(v.to_owned())
}
}

View File

@ -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<LookupHost> {
fn try_from(_v: &str) -> io::Result<LookupHost> {
unimpl!();
}
}

View File

@ -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<LookupHost> {
fn try_from(_v: &str) -> io::Result<LookupHost> {
unsupported()
}
}

View File

@ -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<LookupHost> {

View File

@ -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<char>) -> bool {
let c = match c {
Some(c) => c,

View File

@ -12,7 +12,7 @@ trait Bar: Foo {
impl<T: Foo> 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() {}

View File

@ -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 `<T as Foo>::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`.

View File

@ -0,0 +1,21 @@
// compile-pass
trait ConstDefault {
const DEFAULT: Self;
}
trait Foo: Sized {}
trait FooExt: Foo {
type T: ConstDefault;
}
trait Bar<F: FooExt> {
const T: F::T;
}
impl<F: FooExt> Bar<F> for () {
const T: F::T = <F::T as ConstDefault>::DEFAULT;
}
fn main() {}

View File

@ -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<C> {
inner: Rc<RefCell<Option<C>>>,
}
fn main() {
let store = Store::<Box<for<'a> fn(&(dyn Trait + 'a))>> {
inner: Default::default(),
};
}

View File

@ -0,0 +1,39 @@
// Regression test for #53548. The `Box<dyn Trait>` type below is
// expanded to `Box<dyn Trait + 'static>`, but the generator "witness"
// that results is `for<'r> { Box<dyn Trait + 'r> }`. 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<C> {
inner: Rc<RefCell<Option<C>>>,
}
fn main() {
Box::new(static move || {
let store = Store::<Box<dyn Trait>> {
inner: Default::default(),
};
yield ();
});
}

View File

@ -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<Type = Used> {}
fn main() {
foo();
}

View File

@ -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

View File

@ -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() {}

View File

@ -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`.

View File

@ -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
}

View File

@ -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`.