Auto merge of #48053 - Manishearth:rollup, r=Manishearth
Rollup of 10 pull requests - Successful merges: #47613, #47631, #47810, #47883, #47922, #47944, #48014, #48018, #48020, #48028 - Failed merges:
This commit is contained in:
commit
29c8276cee
56 changed files with 983 additions and 181 deletions
|
@ -530,9 +530,12 @@ impl<'a> Display for Arguments<'a> {
|
|||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_on_unimplemented = "`{Self}` cannot be formatted using `:?`; if it is \
|
||||
defined in your crate, add `#[derive(Debug)]` or \
|
||||
manually implement it"]
|
||||
#[rustc_on_unimplemented(
|
||||
on(crate_local, label="`{Self}` cannot be formatted using `:?`; \
|
||||
add `#[derive(Debug)]` or manually implement `{Debug}`"),
|
||||
message="`{Self}` doesn't implement `{Debug}`",
|
||||
label="`{Self}` cannot be formatted using `:?` because it doesn't implement `{Debug}`",
|
||||
)]
|
||||
#[lang = "debug_trait"]
|
||||
pub trait Debug {
|
||||
/// Formats the value using the given formatter.
|
||||
|
@ -593,9 +596,11 @@ pub trait Debug {
|
|||
///
|
||||
/// println!("The origin is: {}", origin);
|
||||
/// ```
|
||||
#[rustc_on_unimplemented = "`{Self}` cannot be formatted with the default \
|
||||
formatter; try using `:?` instead if you are using \
|
||||
a format string"]
|
||||
#[rustc_on_unimplemented(
|
||||
message="`{Self}` doesn't implement `{Display}`",
|
||||
label="`{Self}` cannot be formatted with the default formatter; \
|
||||
try using `:?` instead if you are using a format string",
|
||||
)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait Display {
|
||||
/// Formats the value using the given formatter.
|
||||
|
|
|
@ -28,8 +28,13 @@ fn _assert_is_object_safe(_: &Iterator<Item=()>) {}
|
|||
/// [module-level documentation]: index.html
|
||||
/// [impl]: index.html#implementing-iterator
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_on_unimplemented = "`{Self}` is not an iterator; maybe try calling \
|
||||
`.iter()` or a similar method"]
|
||||
#[rustc_on_unimplemented(
|
||||
on(
|
||||
_Self="&str",
|
||||
label="`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`"
|
||||
),
|
||||
label="`{Self}` is not an iterator; maybe try calling `.iter()` or a similar method"
|
||||
)]
|
||||
#[doc(spotlight)]
|
||||
pub trait Iterator {
|
||||
/// The type of the elements being iterated over.
|
||||
|
|
|
@ -2322,6 +2322,9 @@ impl<I> ExactSizeIterator for Take<I> where I: ExactSizeIterator {}
|
|||
#[unstable(feature = "fused", issue = "35602")]
|
||||
impl<I> FusedIterator for Take<I> where I: FusedIterator {}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<I: TrustedLen> TrustedLen for Take<I> {}
|
||||
|
||||
/// An iterator to maintain state while iterating another iterator.
|
||||
///
|
||||
/// This `struct` is created by the [`scan`] method on [`Iterator`]. See its
|
||||
|
|
|
@ -325,6 +325,9 @@ impl<A: Step> Iterator for ops::RangeFrom<A> {
|
|||
#[unstable(feature = "fused", issue = "35602")]
|
||||
impl<A: Step> FusedIterator for ops::RangeFrom<A> {}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<A: Step> TrustedLen for ops::RangeFrom<A> {}
|
||||
|
||||
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
|
||||
impl<A: Step> Iterator for ops::RangeInclusive<A> {
|
||||
type Item = A;
|
||||
|
|
|
@ -44,6 +44,9 @@ impl<A: Clone> DoubleEndedIterator for Repeat<A> {
|
|||
#[unstable(feature = "fused", issue = "35602")]
|
||||
impl<A: Clone> FusedIterator for Repeat<A> {}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<A: Clone> TrustedLen for Repeat<A> {}
|
||||
|
||||
/// Creates a new iterator that endlessly repeats a single element.
|
||||
///
|
||||
/// The `repeat()` function repeats a single value over and over and over and
|
||||
|
|
|
@ -970,9 +970,11 @@ impl<'a, I: FusedIterator + ?Sized> FusedIterator for &'a mut I {}
|
|||
/// The iterator reports a size hint where it is either exact
|
||||
/// (lower bound is equal to upper bound), or the upper bound is [`None`].
|
||||
/// The upper bound must only be [`None`] if the actual iterator length is
|
||||
/// larger than [`usize::MAX`].
|
||||
/// larger than [`usize::MAX`]. In that case, the lower bound must be
|
||||
/// [`usize::MAX`], resulting in a [`.size_hint`] of `(usize::MAX, None)`.
|
||||
///
|
||||
/// The iterator must produce exactly the number of elements it reported.
|
||||
/// The iterator must produce exactly the number of elements it reported
|
||||
/// or diverge before reaching the end.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
|
|
|
@ -75,7 +75,18 @@
|
|||
/// ```
|
||||
#[lang = "add"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_on_unimplemented = "no implementation for `{Self} + {RHS}`"]
|
||||
#[rustc_on_unimplemented(
|
||||
on(
|
||||
all(_Self="{integer}", RHS="{float}"),
|
||||
message="cannot add a float to an integer",
|
||||
),
|
||||
on(
|
||||
all(_Self="{float}", RHS="{integer}"),
|
||||
message="cannot add an integer to a float",
|
||||
),
|
||||
message="cannot add `{RHS}` to `{Self}`",
|
||||
label="no implementation for `{Self} + {RHS}`",
|
||||
)]
|
||||
pub trait Add<RHS=Self> {
|
||||
/// The resulting type after applying the `+` operator.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -170,7 +181,8 @@ add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
|
|||
/// ```
|
||||
#[lang = "sub"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_on_unimplemented = "no implementation for `{Self} - {RHS}`"]
|
||||
#[rustc_on_unimplemented(message="cannot substract `{RHS}` from `{Self}`",
|
||||
label="no implementation for `{Self} - {RHS}`")]
|
||||
pub trait Sub<RHS=Self> {
|
||||
/// The resulting type after applying the `-` operator.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -287,7 +299,8 @@ sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
|
|||
/// ```
|
||||
#[lang = "mul"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_on_unimplemented = "no implementation for `{Self} * {RHS}`"]
|
||||
#[rustc_on_unimplemented(message="cannot multiply `{RHS}` to `{Self}`",
|
||||
label="no implementation for `{Self} * {RHS}`")]
|
||||
pub trait Mul<RHS=Self> {
|
||||
/// The resulting type after applying the `*` operator.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -408,7 +421,8 @@ mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
|
|||
/// ```
|
||||
#[lang = "div"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_on_unimplemented = "no implementation for `{Self} / {RHS}`"]
|
||||
#[rustc_on_unimplemented(message="cannot divide `{Self}` by `{RHS}`",
|
||||
label="no implementation for `{Self} / {RHS}`")]
|
||||
pub trait Div<RHS=Self> {
|
||||
/// The resulting type after applying the `/` operator.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -490,7 +504,8 @@ div_impl_float! { f32 f64 }
|
|||
/// ```
|
||||
#[lang = "rem"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_on_unimplemented = "no implementation for `{Self} % {RHS}`"]
|
||||
#[rustc_on_unimplemented(message="cannot mod `{Self}` by `{RHS}`",
|
||||
label="no implementation for `{Self} % {RHS}`")]
|
||||
pub trait Rem<RHS=Self> {
|
||||
/// The resulting type after applying the `%` operator.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -647,7 +662,8 @@ neg_impl_numeric! { isize i8 i16 i32 i64 i128 f32 f64 }
|
|||
/// ```
|
||||
#[lang = "add_assign"]
|
||||
#[stable(feature = "op_assign_traits", since = "1.8.0")]
|
||||
#[rustc_on_unimplemented = "no implementation for `{Self} += {Rhs}`"]
|
||||
#[rustc_on_unimplemented(message="cannot add-assign `{Rhs}` to `{Self}`",
|
||||
label="no implementation for `{Self} += {Rhs}`")]
|
||||
pub trait AddAssign<Rhs=Self> {
|
||||
/// Performs the `+=` operation.
|
||||
#[stable(feature = "op_assign_traits", since = "1.8.0")]
|
||||
|
@ -700,7 +716,8 @@ add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
|
|||
/// ```
|
||||
#[lang = "sub_assign"]
|
||||
#[stable(feature = "op_assign_traits", since = "1.8.0")]
|
||||
#[rustc_on_unimplemented = "no implementation for `{Self} -= {Rhs}`"]
|
||||
#[rustc_on_unimplemented(message="cannot substract-assign `{Rhs}` from `{Self}`",
|
||||
label="no implementation for `{Self} -= {Rhs}`")]
|
||||
pub trait SubAssign<Rhs=Self> {
|
||||
/// Performs the `-=` operation.
|
||||
#[stable(feature = "op_assign_traits", since = "1.8.0")]
|
||||
|
@ -744,7 +761,8 @@ sub_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
|
|||
/// ```
|
||||
#[lang = "mul_assign"]
|
||||
#[stable(feature = "op_assign_traits", since = "1.8.0")]
|
||||
#[rustc_on_unimplemented = "no implementation for `{Self} *= {Rhs}`"]
|
||||
#[rustc_on_unimplemented(message="cannot multiply-assign `{Rhs}` to `{Self}`",
|
||||
label="no implementation for `{Self} *= {Rhs}`")]
|
||||
pub trait MulAssign<Rhs=Self> {
|
||||
/// Performs the `*=` operation.
|
||||
#[stable(feature = "op_assign_traits", since = "1.8.0")]
|
||||
|
@ -788,7 +806,8 @@ mul_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
|
|||
/// ```
|
||||
#[lang = "div_assign"]
|
||||
#[stable(feature = "op_assign_traits", since = "1.8.0")]
|
||||
#[rustc_on_unimplemented = "no implementation for `{Self} /= {Rhs}`"]
|
||||
#[rustc_on_unimplemented(message="cannot divide-assign `{Self}` by `{Rhs}`",
|
||||
label="no implementation for `{Self} /= {Rhs}`")]
|
||||
pub trait DivAssign<Rhs=Self> {
|
||||
/// Performs the `/=` operation.
|
||||
#[stable(feature = "op_assign_traits", since = "1.8.0")]
|
||||
|
@ -835,7 +854,8 @@ div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
|
|||
/// ```
|
||||
#[lang = "rem_assign"]
|
||||
#[stable(feature = "op_assign_traits", since = "1.8.0")]
|
||||
#[rustc_on_unimplemented = "no implementation for `{Self} %= {Rhs}`"]
|
||||
#[rustc_on_unimplemented(message="cannot mod-assign `{Self}` by `{Rhs}``",
|
||||
label="no implementation for `{Self} %= {Rhs}`")]
|
||||
pub trait RemAssign<Rhs=Self> {
|
||||
/// Performs the `%=` operation.
|
||||
#[stable(feature = "op_assign_traits", since = "1.8.0")]
|
||||
|
|
|
@ -120,7 +120,8 @@ not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
|
|||
/// ```
|
||||
#[lang = "bitand"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_on_unimplemented = "no implementation for `{Self} & {RHS}`"]
|
||||
#[rustc_on_unimplemented(message="no implementation for `{Self} & {RHS}`",
|
||||
label="no implementation for `{Self} & {RHS}`")]
|
||||
pub trait BitAnd<RHS=Self> {
|
||||
/// The resulting type after applying the `&` operator.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -201,7 +202,8 @@ bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
|
|||
/// ```
|
||||
#[lang = "bitor"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_on_unimplemented = "no implementation for `{Self} | {RHS}`"]
|
||||
#[rustc_on_unimplemented(message="no implementation for `{Self} | {RHS}`",
|
||||
label="no implementation for `{Self} | {RHS}`")]
|
||||
pub trait BitOr<RHS=Self> {
|
||||
/// The resulting type after applying the `|` operator.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -285,7 +287,8 @@ bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
|
|||
/// ```
|
||||
#[lang = "bitxor"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_on_unimplemented = "no implementation for `{Self} ^ {RHS}`"]
|
||||
#[rustc_on_unimplemented(message="no implementation for `{Self} ^ {RHS}`",
|
||||
label="no implementation for `{Self} ^ {RHS}`")]
|
||||
pub trait BitXor<RHS=Self> {
|
||||
/// The resulting type after applying the `^` operator.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -365,7 +368,8 @@ bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
|
|||
/// ```
|
||||
#[lang = "shl"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_on_unimplemented = "no implementation for `{Self} << {RHS}`"]
|
||||
#[rustc_on_unimplemented(message="no implementation for `{Self} << {RHS}`",
|
||||
label="no implementation for `{Self} << {RHS}`")]
|
||||
pub trait Shl<RHS> {
|
||||
/// The resulting type after applying the `<<` operator.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -466,7 +470,8 @@ shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 isize i128 }
|
|||
/// ```
|
||||
#[lang = "shr"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_on_unimplemented = "no implementation for `{Self} >> {RHS}`"]
|
||||
#[rustc_on_unimplemented(message="no implementation for `{Self} >> {RHS}`",
|
||||
label="no implementation for `{Self} >> {RHS}`")]
|
||||
pub trait Shr<RHS> {
|
||||
/// The resulting type after applying the `>>` operator.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -579,7 +584,8 @@ shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
|
|||
/// ```
|
||||
#[lang = "bitand_assign"]
|
||||
#[stable(feature = "op_assign_traits", since = "1.8.0")]
|
||||
#[rustc_on_unimplemented = "no implementation for `{Self} &= {Rhs}`"]
|
||||
#[rustc_on_unimplemented(message="no implementation for `{Self} &= {Rhs}`",
|
||||
label="no implementation for `{Self} &= {Rhs}`")]
|
||||
pub trait BitAndAssign<Rhs=Self> {
|
||||
/// Performs the `&=` operation.
|
||||
#[stable(feature = "op_assign_traits", since = "1.8.0")]
|
||||
|
@ -626,7 +632,8 @@ bitand_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
|
|||
/// ```
|
||||
#[lang = "bitor_assign"]
|
||||
#[stable(feature = "op_assign_traits", since = "1.8.0")]
|
||||
#[rustc_on_unimplemented = "no implementation for `{Self} |= {Rhs}`"]
|
||||
#[rustc_on_unimplemented(message="no implementation for `{Self} |= {Rhs}`",
|
||||
label="no implementation for `{Self} |= {Rhs}`")]
|
||||
pub trait BitOrAssign<Rhs=Self> {
|
||||
/// Performs the `|=` operation.
|
||||
#[stable(feature = "op_assign_traits", since = "1.8.0")]
|
||||
|
@ -673,7 +680,8 @@ bitor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
|
|||
/// ```
|
||||
#[lang = "bitxor_assign"]
|
||||
#[stable(feature = "op_assign_traits", since = "1.8.0")]
|
||||
#[rustc_on_unimplemented = "no implementation for `{Self} ^= {Rhs}`"]
|
||||
#[rustc_on_unimplemented(message="no implementation for `{Self} ^= {Rhs}`",
|
||||
label="no implementation for `{Self} ^= {Rhs}`")]
|
||||
pub trait BitXorAssign<Rhs=Self> {
|
||||
/// Performs the `^=` operation.
|
||||
#[stable(feature = "op_assign_traits", since = "1.8.0")]
|
||||
|
@ -718,7 +726,8 @@ bitxor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
|
|||
/// ```
|
||||
#[lang = "shl_assign"]
|
||||
#[stable(feature = "op_assign_traits", since = "1.8.0")]
|
||||
#[rustc_on_unimplemented = "no implementation for `{Self} <<= {Rhs}`"]
|
||||
#[rustc_on_unimplemented(message="no implementation for `{Self} <<= {Rhs}`",
|
||||
label="no implementation for `{Self} <<= {Rhs}`")]
|
||||
pub trait ShlAssign<Rhs> {
|
||||
/// Performs the `<<=` operation.
|
||||
#[stable(feature = "op_assign_traits", since = "1.8.0")]
|
||||
|
@ -784,7 +793,8 @@ shl_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
|
|||
/// ```
|
||||
#[lang = "shr_assign"]
|
||||
#[stable(feature = "op_assign_traits", since = "1.8.0")]
|
||||
#[rustc_on_unimplemented = "no implementation for `{Self} >>= {Rhs}`"]
|
||||
#[rustc_on_unimplemented(message="no implementation for `{Self} >>= {Rhs}`",
|
||||
label="no implementation for `{Self} >>= {Rhs}`")]
|
||||
pub trait ShrAssign<Rhs=Self> {
|
||||
/// Performs the `>>=` operation.
|
||||
#[stable(feature = "op_assign_traits", since = "1.8.0")]
|
||||
|
|
|
@ -2461,7 +2461,7 @@ impl<'a, T: ?Sized> From<NonNull<T>> for Unique<T> {
|
|||
}
|
||||
|
||||
/// Previous name of `NonNull`.
|
||||
#[rustc_deprecated(since = "1.24", reason = "renamed to `NonNull`")]
|
||||
#[rustc_deprecated(since = "1.25.0", reason = "renamed to `NonNull`")]
|
||||
#[unstable(feature = "shared", issue = "27730")]
|
||||
pub type Shared<T> = NonNull<T>;
|
||||
|
||||
|
@ -2482,26 +2482,19 @@ pub type Shared<T> = NonNull<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.
|
||||
#[stable(feature = "nonnull", since = "1.24.0")]
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
pub struct NonNull<T: ?Sized> {
|
||||
pointer: NonZero<*const T>,
|
||||
}
|
||||
|
||||
#[stable(feature = "nonnull", since = "1.24.0")]
|
||||
impl<T: ?Sized> fmt::Debug for NonNull<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Pointer::fmt(&self.as_ptr(), f)
|
||||
}
|
||||
}
|
||||
|
||||
/// `NonNull` pointers are not `Send` because the data they reference may be aliased.
|
||||
// NB: This impl is unnecessary, but should provide better error messages.
|
||||
#[stable(feature = "nonnull", since = "1.24.0")]
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
impl<T: ?Sized> !Send for NonNull<T> { }
|
||||
|
||||
/// `NonNull` pointers are not `Sync` because the data they reference may be aliased.
|
||||
// NB: This impl is unnecessary, but should provide better error messages.
|
||||
#[stable(feature = "nonnull", since = "1.24.0")]
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
impl<T: ?Sized> !Sync for NonNull<T> { }
|
||||
|
||||
impl<T: Sized> NonNull<T> {
|
||||
|
@ -2509,7 +2502,7 @@ impl<T: Sized> NonNull<T> {
|
|||
///
|
||||
/// This is useful for initializing types which lazily allocate, like
|
||||
/// `Vec::new` does.
|
||||
#[stable(feature = "nonnull", since = "1.24.0")]
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
pub fn dangling() -> Self {
|
||||
unsafe {
|
||||
let ptr = mem::align_of::<T>() as *mut T;
|
||||
|
@ -2524,19 +2517,19 @@ impl<T: ?Sized> NonNull<T> {
|
|||
/// # Safety
|
||||
///
|
||||
/// `ptr` must be non-null.
|
||||
#[stable(feature = "nonnull", since = "1.24.0")]
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
|
||||
NonNull { pointer: NonZero::new_unchecked(ptr) }
|
||||
}
|
||||
|
||||
/// Creates a new `NonNull` if `ptr` is non-null.
|
||||
#[stable(feature = "nonnull", since = "1.24.0")]
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
pub fn new(ptr: *mut T) -> Option<Self> {
|
||||
NonZero::new(ptr as *const T).map(|nz| NonNull { pointer: nz })
|
||||
}
|
||||
|
||||
/// Acquires the underlying `*mut` pointer.
|
||||
#[stable(feature = "nonnull", since = "1.24.0")]
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
pub fn as_ptr(self) -> *mut T {
|
||||
self.pointer.get() as *mut T
|
||||
}
|
||||
|
@ -2546,7 +2539,7 @@ impl<T: ?Sized> NonNull<T> {
|
|||
/// The resulting lifetime is bound to self so this behaves "as if"
|
||||
/// it were actually an instance of T that is getting borrowed. If a longer
|
||||
/// (unbound) lifetime is needed, use `&*my_ptr.as_ptr()`.
|
||||
#[stable(feature = "nonnull", since = "1.24.0")]
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
pub unsafe fn as_ref(&self) -> &T {
|
||||
&*self.as_ptr()
|
||||
}
|
||||
|
@ -2556,47 +2549,93 @@ impl<T: ?Sized> NonNull<T> {
|
|||
/// The resulting lifetime is bound to self so this behaves "as if"
|
||||
/// it were actually an instance of T that is getting borrowed. If a longer
|
||||
/// (unbound) lifetime is needed, use `&mut *my_ptr.as_ptr()`.
|
||||
#[stable(feature = "nonnull", since = "1.24.0")]
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
pub unsafe fn as_mut(&mut self) -> &mut T {
|
||||
&mut *self.as_ptr()
|
||||
}
|
||||
|
||||
/// Cast to a pointer of another type
|
||||
#[unstable(feature = "nonnull_cast", issue = "47653")]
|
||||
pub fn cast<U>(self) -> NonNull<U> {
|
||||
unsafe {
|
||||
NonNull::new_unchecked(self.as_ptr() as *mut U)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "nonnull", since = "1.24.0")]
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
impl<T: ?Sized> Clone for NonNull<T> {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "nonnull", since = "1.24.0")]
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
impl<T: ?Sized> Copy for NonNull<T> { }
|
||||
|
||||
#[stable(feature = "nonnull", since = "1.24.0")]
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
impl<T: ?Sized, U: ?Sized> CoerceUnsized<NonNull<U>> for NonNull<T> where T: Unsize<U> { }
|
||||
|
||||
#[stable(feature = "nonnull", since = "1.24.0")]
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
impl<T: ?Sized> fmt::Debug for NonNull<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Pointer::fmt(&self.as_ptr(), f)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
impl<T: ?Sized> fmt::Pointer for NonNull<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Pointer::fmt(&self.as_ptr(), f)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "nonnull", since = "1.24.0")]
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
impl<T: ?Sized> Eq for NonNull<T> {}
|
||||
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
impl<T: ?Sized> PartialEq for NonNull<T> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.as_ptr() == other.as_ptr()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
impl<T: ?Sized> Ord for NonNull<T> {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.as_ptr().cmp(&other.as_ptr())
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
impl<T: ?Sized> PartialOrd for NonNull<T> {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
self.as_ptr().partial_cmp(&other.as_ptr())
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
impl<T: ?Sized> hash::Hash for NonNull<T> {
|
||||
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
||||
self.as_ptr().hash(state)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
impl<T: ?Sized> From<Unique<T>> for NonNull<T> {
|
||||
fn from(unique: Unique<T>) -> Self {
|
||||
NonNull { pointer: unique.pointer }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "nonnull", since = "1.24.0")]
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
impl<'a, T: ?Sized> From<&'a mut T> for NonNull<T> {
|
||||
fn from(reference: &'a mut T) -> Self {
|
||||
NonNull { pointer: NonZero::from(reference) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "nonnull", since = "1.24.0")]
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
impl<'a, T: ?Sized> From<&'a T> for NonNull<T> {
|
||||
fn from(reference: &'a T) -> Self {
|
||||
NonNull { pointer: NonZero::from(reference) }
|
||||
|
|
|
@ -1371,6 +1371,29 @@ fn test_range_from_nth() {
|
|||
assert_eq!(r, 16..);
|
||||
assert_eq!(r.nth(10), Some(26));
|
||||
assert_eq!(r, 27..);
|
||||
|
||||
assert_eq!((0..).size_hint(), (usize::MAX, None));
|
||||
}
|
||||
|
||||
fn is_trusted_len<I: TrustedLen>(_: I) {}
|
||||
|
||||
#[test]
|
||||
fn test_range_from_take() {
|
||||
let mut it = (0..).take(3);
|
||||
assert_eq!(it.next(), Some(0));
|
||||
assert_eq!(it.next(), Some(1));
|
||||
assert_eq!(it.next(), Some(2));
|
||||
assert_eq!(it.next(), None);
|
||||
is_trusted_len((0..).take(3));
|
||||
assert_eq!((0..).take(3).size_hint(), (3, Some(3)));
|
||||
assert_eq!((0..).take(0).size_hint(), (0, Some(0)));
|
||||
assert_eq!((0..).take(usize::MAX).size_hint(), (usize::MAX, Some(usize::MAX)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_range_from_take_collect() {
|
||||
let v: Vec<_> = (0..).take(3).collect();
|
||||
assert_eq!(v, vec![0, 1, 2]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1485,6 +1508,26 @@ fn test_repeat() {
|
|||
assert_eq!(it.next(), Some(42));
|
||||
assert_eq!(it.next(), Some(42));
|
||||
assert_eq!(it.next(), Some(42));
|
||||
assert_eq!(repeat(42).size_hint(), (usize::MAX, None));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_repeat_take() {
|
||||
let mut it = repeat(42).take(3);
|
||||
assert_eq!(it.next(), Some(42));
|
||||
assert_eq!(it.next(), Some(42));
|
||||
assert_eq!(it.next(), Some(42));
|
||||
assert_eq!(it.next(), None);
|
||||
is_trusted_len(repeat(42).take(3));
|
||||
assert_eq!(repeat(42).take(3).size_hint(), (3, Some(3)));
|
||||
assert_eq!(repeat(42).take(0).size_hint(), (0, Some(0)));
|
||||
assert_eq!(repeat(42).take(usize::MAX).size_hint(), (usize::MAX, Some(usize::MAX)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_repeat_take_collect() {
|
||||
let v: Vec<_> = repeat(42).take(3).collect();
|
||||
assert_eq!(v, vec![42, 42, 42]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
#![feature(macro_vis_matcher)]
|
||||
#![feature(match_default_bindings)]
|
||||
#![feature(never_type)]
|
||||
#![feature(non_exhaustive)]
|
||||
#![feature(nonzero)]
|
||||
#![feature(quote)]
|
||||
#![feature(refcell_replace_swap)]
|
||||
|
|
|
@ -109,7 +109,7 @@ use self::VarKind::*;
|
|||
use hir::def::*;
|
||||
use ty::{self, TyCtxt};
|
||||
use lint;
|
||||
use util::nodemap::NodeMap;
|
||||
use util::nodemap::{NodeMap, NodeSet};
|
||||
|
||||
use std::{fmt, usize};
|
||||
use std::io::prelude::*;
|
||||
|
@ -244,7 +244,8 @@ struct CaptureInfo {
|
|||
#[derive(Copy, Clone, Debug)]
|
||||
struct LocalInfo {
|
||||
id: NodeId,
|
||||
name: ast::Name
|
||||
name: ast::Name,
|
||||
is_shorthand: bool,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
@ -333,6 +334,13 @@ impl<'a, 'tcx> IrMaps<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn variable_is_shorthand(&self, var: Variable) -> bool {
|
||||
match self.var_kinds[var.get()] {
|
||||
Local(LocalInfo { is_shorthand, .. }) => is_shorthand,
|
||||
Arg(..) | CleanExit => false
|
||||
}
|
||||
}
|
||||
|
||||
fn set_captures(&mut self, node_id: NodeId, cs: Vec<CaptureInfo>) {
|
||||
self.capture_info_map.insert(node_id, Rc::new(cs));
|
||||
}
|
||||
|
@ -384,8 +392,9 @@ fn visit_local<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, local: &'tcx hir::Local) {
|
|||
let name = path1.node;
|
||||
ir.add_live_node_for_node(p_id, VarDefNode(sp));
|
||||
ir.add_variable(Local(LocalInfo {
|
||||
id: p_id,
|
||||
name,
|
||||
id: p_id,
|
||||
name,
|
||||
is_shorthand: false,
|
||||
}));
|
||||
});
|
||||
intravisit::walk_local(ir, local);
|
||||
|
@ -393,6 +402,22 @@ fn visit_local<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, local: &'tcx hir::Local) {
|
|||
|
||||
fn visit_arm<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, arm: &'tcx hir::Arm) {
|
||||
for pat in &arm.pats {
|
||||
// for struct patterns, take note of which fields used shorthand (`x`
|
||||
// rather than `x: x`)
|
||||
//
|
||||
// FIXME: according to the rust-lang-nursery/rustc-guide book and
|
||||
// librustc/README.md, `NodeId`s are to be phased out in favor of
|
||||
// `HirId`s; however, we need to match the signature of `each_binding`,
|
||||
// which uses `NodeIds`.
|
||||
let mut shorthand_field_ids = NodeSet();
|
||||
if let hir::PatKind::Struct(_, ref fields, _) = pat.node {
|
||||
for field in fields {
|
||||
if field.node.is_shorthand {
|
||||
shorthand_field_ids.insert(field.node.pat.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pat.each_binding(|bm, p_id, sp, path1| {
|
||||
debug!("adding local variable {} from match with bm {:?}",
|
||||
p_id, bm);
|
||||
|
@ -400,7 +425,8 @@ fn visit_arm<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, arm: &'tcx hir::Arm) {
|
|||
ir.add_live_node_for_node(p_id, VarDefNode(sp));
|
||||
ir.add_variable(Local(LocalInfo {
|
||||
id: p_id,
|
||||
name,
|
||||
name: name,
|
||||
is_shorthand: shorthand_field_ids.contains(&p_id)
|
||||
}));
|
||||
})
|
||||
}
|
||||
|
@ -1483,17 +1509,26 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
|||
self.assigned_on_exit(ln, var).is_some()
|
||||
};
|
||||
|
||||
let suggest_underscore_msg = format!("consider using `_{}` instead",
|
||||
name);
|
||||
if is_assigned {
|
||||
self.ir.tcx.lint_node_note(lint::builtin::UNUSED_VARIABLES, id, sp,
|
||||
&format!("variable `{}` is assigned to, but never used",
|
||||
name),
|
||||
&format!("to avoid this warning, consider using `_{}` instead",
|
||||
name));
|
||||
self.ir.tcx
|
||||
.lint_node_note(lint::builtin::UNUSED_VARIABLES, id, sp,
|
||||
&format!("variable `{}` is assigned to, but never used",
|
||||
name),
|
||||
&suggest_underscore_msg);
|
||||
} else if name != "self" {
|
||||
self.ir.tcx.lint_node_note(lint::builtin::UNUSED_VARIABLES, id, sp,
|
||||
&format!("unused variable: `{}`", name),
|
||||
&format!("to avoid this warning, consider using `_{}` instead",
|
||||
name));
|
||||
let msg = format!("unused variable: `{}`", name);
|
||||
let mut err = self.ir.tcx
|
||||
.struct_span_lint_node(lint::builtin::UNUSED_VARIABLES, id, sp, &msg);
|
||||
if self.ir.variable_is_shorthand(var) {
|
||||
err.span_suggestion(sp, "try ignoring the field",
|
||||
format!("{}: _", name));
|
||||
} else {
|
||||
err.span_suggestion_short(sp, &suggest_underscore_msg,
|
||||
format!("_{}", name));
|
||||
}
|
||||
err.emit()
|
||||
}
|
||||
}
|
||||
true
|
||||
|
|
|
@ -112,6 +112,31 @@ pub enum OutputType {
|
|||
DepInfo,
|
||||
}
|
||||
|
||||
/// The epoch of the compiler (RFC 2052)
|
||||
#[derive(Clone, Copy, Hash, PartialOrd, Ord, Eq, PartialEq)]
|
||||
#[non_exhaustive]
|
||||
pub enum Epoch {
|
||||
// epochs must be kept in order, newest to oldest
|
||||
|
||||
/// The 2015 epoch
|
||||
Epoch2015,
|
||||
/// The 2018 epoch
|
||||
Epoch2018,
|
||||
|
||||
// when adding new epochs, be sure to update:
|
||||
//
|
||||
// - the list in the `parse_epoch` static
|
||||
// - the match in the `parse_epoch` function
|
||||
// - add a `rust_####()` function to the session
|
||||
// - update the enum in Cargo's sources as well
|
||||
//
|
||||
// When -Zepoch becomes --epoch, there will
|
||||
// also be a check for the epoch being nightly-only
|
||||
// somewhere. That will need to be updated
|
||||
// whenever we're stabilizing/introducing a new epoch
|
||||
// as well as changing the default Cargo template.
|
||||
}
|
||||
|
||||
impl_stable_hash_for!(enum self::OutputType {
|
||||
Bitcode,
|
||||
Assembly,
|
||||
|
@ -783,11 +808,13 @@ macro_rules! options {
|
|||
Some("`string` or `string=string`");
|
||||
pub const parse_lto: Option<&'static str> =
|
||||
Some("one of `thin`, `fat`, or omitted");
|
||||
pub const parse_epoch: Option<&'static str> =
|
||||
Some("one of: `2015`, `2018`");
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
mod $mod_set {
|
||||
use super::{$struct_name, Passes, SomePasses, AllPasses, Sanitizer, Lto};
|
||||
use super::{$struct_name, Passes, SomePasses, AllPasses, Sanitizer, Lto, Epoch};
|
||||
use rustc_back::{LinkerFlavor, PanicStrategy, RelroLevel};
|
||||
use std::path::PathBuf;
|
||||
|
||||
|
@ -991,6 +1018,15 @@ macro_rules! options {
|
|||
};
|
||||
true
|
||||
}
|
||||
|
||||
fn parse_epoch(slot: &mut Epoch, v: Option<&str>) -> bool {
|
||||
match v {
|
||||
Some("2015") => *slot = Epoch::Epoch2015,
|
||||
Some("2018") => *slot = Epoch::Epoch2018,
|
||||
_ => return false,
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
) }
|
||||
|
||||
|
@ -1278,6 +1314,10 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
|||
`everybody_loops` (all function bodies replaced with `loop {}`),
|
||||
`hir` (the HIR), `hir,identified`, or
|
||||
`hir,typed` (HIR with types for each node)."),
|
||||
epoch: Epoch = (Epoch::Epoch2015, parse_epoch, [TRACKED],
|
||||
"The epoch to build Rust with. Newer epochs may include features
|
||||
that require breaking changes. The default epoch is 2015 (the first
|
||||
epoch). Crates compiled with different epochs can be linked together."),
|
||||
}
|
||||
|
||||
pub fn default_lib_output() -> CrateType {
|
||||
|
@ -2069,7 +2109,7 @@ mod dep_tracking {
|
|||
use std::path::PathBuf;
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use super::{Passes, CrateType, OptLevel, DebugInfoLevel, Lto,
|
||||
OutputTypes, Externs, ErrorOutputType, Sanitizer};
|
||||
OutputTypes, Externs, ErrorOutputType, Sanitizer, Epoch};
|
||||
use syntax::feature_gate::UnstableFeatures;
|
||||
use rustc_back::{PanicStrategy, RelroLevel};
|
||||
|
||||
|
@ -2131,6 +2171,7 @@ mod dep_tracking {
|
|||
impl_dep_tracking_hash_via_hash!(cstore::NativeLibraryKind);
|
||||
impl_dep_tracking_hash_via_hash!(Sanitizer);
|
||||
impl_dep_tracking_hash_via_hash!(Option<Sanitizer>);
|
||||
impl_dep_tracking_hash_via_hash!(Epoch);
|
||||
|
||||
impl_dep_tracking_hash_for_sortable_vec_of!(String);
|
||||
impl_dep_tracking_hash_for_sortable_vec_of!(PathBuf);
|
||||
|
|
|
@ -19,7 +19,7 @@ use lint;
|
|||
use middle::allocator::AllocatorKind;
|
||||
use middle::dependency_format;
|
||||
use session::search_paths::PathKind;
|
||||
use session::config::{BorrowckMode, DebugInfoLevel, OutputType};
|
||||
use session::config::{BorrowckMode, DebugInfoLevel, OutputType, Epoch};
|
||||
use ty::tls;
|
||||
use util::nodemap::{FxHashMap, FxHashSet};
|
||||
use util::common::{duration_to_secs_str, ErrorReported};
|
||||
|
@ -864,6 +864,11 @@ impl Session {
|
|||
pub fn teach(&self, code: &DiagnosticId) -> bool {
|
||||
self.opts.debugging_opts.teach && !self.parse_sess.span_diagnostic.code_emitted(code)
|
||||
}
|
||||
|
||||
/// Are we allowed to use features from the Rust 2018 epoch?
|
||||
pub fn rust_2018(&self) -> bool {
|
||||
self.opts.debugging_opts.epoch >= Epoch::Epoch2018
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_session(sopts: config::Options,
|
||||
|
|
|
@ -348,7 +348,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
if direct {
|
||||
// this is a "direct", user-specified, rather than derived,
|
||||
// obligation.
|
||||
flags.push(("direct", None));
|
||||
flags.push(("direct".to_string(), None));
|
||||
}
|
||||
|
||||
if let ObligationCauseCode::ItemObligation(item) = obligation.cause.code {
|
||||
|
@ -359,21 +359,37 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
// Currently I'm leaving it for what I need for `try`.
|
||||
if self.tcx.trait_of_item(item) == Some(trait_ref.def_id) {
|
||||
method = self.tcx.item_name(item);
|
||||
flags.push(("from_method", None));
|
||||
flags.push(("from_method", Some(&*method)));
|
||||
flags.push(("from_method".to_string(), None));
|
||||
flags.push(("from_method".to_string(), Some(method.to_string())));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(k) = obligation.cause.span.compiler_desugaring_kind() {
|
||||
desugaring = k.as_symbol().as_str();
|
||||
flags.push(("from_desugaring", None));
|
||||
flags.push(("from_desugaring", Some(&*desugaring)));
|
||||
flags.push(("from_desugaring".to_string(), None));
|
||||
flags.push(("from_desugaring".to_string(), Some(desugaring.to_string())));
|
||||
}
|
||||
let generics = self.tcx.generics_of(def_id);
|
||||
let self_ty = trait_ref.self_ty();
|
||||
let self_ty_str = self_ty.to_string();
|
||||
flags.push(("_Self".to_string(), Some(self_ty_str.clone())));
|
||||
|
||||
for param in generics.types.iter() {
|
||||
let name = param.name.as_str().to_string();
|
||||
let ty = trait_ref.substs.type_for_def(param);
|
||||
let ty_str = ty.to_string();
|
||||
flags.push((name.clone(),
|
||||
Some(ty_str.clone())));
|
||||
}
|
||||
|
||||
if let Some(true) = self_ty.ty_to_def_id().map(|def_id| def_id.is_local()) {
|
||||
flags.push(("crate_local".to_string(), None));
|
||||
}
|
||||
|
||||
if let Ok(Some(command)) = OnUnimplementedDirective::of_item(
|
||||
self.tcx, trait_ref.def_id, def_id
|
||||
) {
|
||||
command.evaluate(self.tcx, trait_ref, &flags)
|
||||
command.evaluate(self.tcx, trait_ref, &flags[..])
|
||||
} else {
|
||||
OnUnimplementedNote::empty()
|
||||
}
|
||||
|
@ -549,7 +565,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
.map(|t| (format!(" in `{}`", t), format!("within `{}`, ", t)))
|
||||
.unwrap_or((String::new(), String::new()));
|
||||
|
||||
let OnUnimplementedNote { message, label }
|
||||
let OnUnimplementedNote { message, label, note }
|
||||
= self.on_unimplemented_note(trait_ref, obligation);
|
||||
let have_alt_message = message.is_some() || label.is_some();
|
||||
|
||||
|
@ -578,6 +594,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
trait_ref,
|
||||
trait_ref.self_ty()));
|
||||
}
|
||||
if let Some(ref s) = note {
|
||||
// If it has a custom "#[rustc_on_unimplemented]" note, let's display it
|
||||
err.note(s.as_str());
|
||||
}
|
||||
|
||||
self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err);
|
||||
|
||||
|
|
|
@ -29,16 +29,18 @@ pub struct OnUnimplementedDirective {
|
|||
pub subcommands: Vec<OnUnimplementedDirective>,
|
||||
pub message: Option<OnUnimplementedFormatString>,
|
||||
pub label: Option<OnUnimplementedFormatString>,
|
||||
pub note: Option<OnUnimplementedFormatString>,
|
||||
}
|
||||
|
||||
pub struct OnUnimplementedNote {
|
||||
pub message: Option<String>,
|
||||
pub label: Option<String>,
|
||||
pub note: Option<String>,
|
||||
}
|
||||
|
||||
impl OnUnimplementedNote {
|
||||
pub fn empty() -> Self {
|
||||
OnUnimplementedNote { message: None, label: None }
|
||||
OnUnimplementedNote { message: None, label: None, note: None }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,6 +91,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective {
|
|||
|
||||
let mut message = None;
|
||||
let mut label = None;
|
||||
let mut note = None;
|
||||
let mut subcommands = vec![];
|
||||
for item in item_iter {
|
||||
if item.check_name("message") && message.is_none() {
|
||||
|
@ -103,8 +106,14 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective {
|
|||
tcx, trait_def_id, label_.as_str(), span)?);
|
||||
continue;
|
||||
}
|
||||
} else if item.check_name("note") && note.is_none() {
|
||||
if let Some(note_) = item.value_str() {
|
||||
note = Some(OnUnimplementedFormatString::try_parse(
|
||||
tcx, trait_def_id, note_.as_str(), span)?);
|
||||
continue;
|
||||
}
|
||||
} else if item.check_name("on") && is_root &&
|
||||
message.is_none() && label.is_none()
|
||||
message.is_none() && label.is_none() && note.is_none()
|
||||
{
|
||||
if let Some(items) = item.meta_item_list() {
|
||||
if let Ok(subcommand) =
|
||||
|
@ -128,7 +137,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective {
|
|||
if errored {
|
||||
Err(ErrorReported)
|
||||
} else {
|
||||
Ok(OnUnimplementedDirective { condition, message, label, subcommands })
|
||||
Ok(OnUnimplementedDirective { condition, message, label, subcommands, note })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -154,7 +163,8 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective {
|
|||
message: None,
|
||||
subcommands: vec![],
|
||||
label: Some(OnUnimplementedFormatString::try_parse(
|
||||
tcx, trait_def_id, value.as_str(), attr.span)?)
|
||||
tcx, trait_def_id, value.as_str(), attr.span)?),
|
||||
note: None,
|
||||
}))
|
||||
} else {
|
||||
return Err(parse_error(tcx, attr.span,
|
||||
|
@ -169,20 +179,20 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective {
|
|||
pub fn evaluate(&self,
|
||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
trait_ref: ty::TraitRef<'tcx>,
|
||||
options: &[(&str, Option<&str>)])
|
||||
options: &[(String, Option<String>)])
|
||||
-> OnUnimplementedNote
|
||||
{
|
||||
let mut message = None;
|
||||
let mut label = None;
|
||||
info!("evaluate({:?}, trait_ref={:?}, options={:?})",
|
||||
self, trait_ref, options);
|
||||
let mut note = None;
|
||||
info!("evaluate({:?}, trait_ref={:?}, options={:?})", self, trait_ref, options);
|
||||
|
||||
for command in self.subcommands.iter().chain(Some(self)).rev() {
|
||||
if let Some(ref condition) = command.condition {
|
||||
if !attr::eval_condition(condition, &tcx.sess.parse_sess, &mut |c| {
|
||||
options.contains(&(&c.name().as_str(),
|
||||
match c.value_str().map(|s| s.as_str()) {
|
||||
Some(ref s) => Some(s),
|
||||
options.contains(&(c.name().as_str().to_string(),
|
||||
match c.value_str().map(|s| s.as_str().to_string()) {
|
||||
Some(s) => Some(s),
|
||||
None => None
|
||||
}))
|
||||
}) {
|
||||
|
@ -198,11 +208,16 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective {
|
|||
if let Some(ref label_) = command.label {
|
||||
label = Some(label_.clone());
|
||||
}
|
||||
|
||||
if let Some(ref note_) = command.note {
|
||||
note = Some(note_.clone());
|
||||
}
|
||||
}
|
||||
|
||||
OnUnimplementedNote {
|
||||
label: label.map(|l| l.format(tcx, trait_ref)),
|
||||
message: message.map(|m| m.format(tcx, trait_ref))
|
||||
message: message.map(|m| m.format(tcx, trait_ref)),
|
||||
note: note.map(|n| n.format(tcx, trait_ref)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
#![allow(non_snake_case)]
|
||||
|
||||
use hir::def_id::DefId;
|
||||
use hir::ItemLocalId;
|
||||
use hir::{HirId, ItemLocalId};
|
||||
use syntax::ast;
|
||||
|
||||
pub use rustc_data_structures::fx::FxHashMap;
|
||||
|
@ -21,10 +21,12 @@ pub use rustc_data_structures::fx::FxHashSet;
|
|||
|
||||
pub type NodeMap<T> = FxHashMap<ast::NodeId, T>;
|
||||
pub type DefIdMap<T> = FxHashMap<DefId, T>;
|
||||
pub type HirIdMap<T> = FxHashMap<HirId, T>;
|
||||
pub type ItemLocalMap<T> = FxHashMap<ItemLocalId, T>;
|
||||
|
||||
pub type NodeSet = FxHashSet<ast::NodeId>;
|
||||
pub type DefIdSet = FxHashSet<DefId>;
|
||||
pub type HirIdSet = FxHashSet<HirId>;
|
||||
pub type ItemLocalSet = FxHashSet<ItemLocalId>;
|
||||
|
||||
pub fn NodeMap<T>() -> NodeMap<T> { FxHashMap() }
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "s2wasm.h"
|
||||
|
@ -24,6 +25,7 @@ using namespace wasm;
|
|||
|
||||
struct BinaryenRustModule {
|
||||
BufferWithRandomAccess buffer;
|
||||
std::string sourceMapJSON;
|
||||
};
|
||||
|
||||
struct BinaryenRustModuleOptions {
|
||||
|
@ -36,6 +38,7 @@ struct BinaryenRustModuleOptions {
|
|||
bool ignoreUnknownSymbols;
|
||||
bool debugInfo;
|
||||
std::string startFunction;
|
||||
std::string sourceMapUrl;
|
||||
|
||||
BinaryenRustModuleOptions() :
|
||||
globalBase(0),
|
||||
|
@ -46,7 +49,8 @@ struct BinaryenRustModuleOptions {
|
|||
importMemory(false),
|
||||
ignoreUnknownSymbols(false),
|
||||
debugInfo(false),
|
||||
startFunction("")
|
||||
startFunction(""),
|
||||
sourceMapUrl("")
|
||||
{}
|
||||
|
||||
};
|
||||
|
@ -73,6 +77,12 @@ BinaryenRustModuleOptionsSetStart(BinaryenRustModuleOptions *options,
|
|||
options->startFunction = start;
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
BinaryenRustModuleOptionsSetSourceMapUrl(BinaryenRustModuleOptions *options,
|
||||
char *sourceMapUrl) {
|
||||
options->sourceMapUrl = sourceMapUrl;
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
BinaryenRustModuleOptionsSetStackAllocation(BinaryenRustModuleOptions *options,
|
||||
uint64_t stack) {
|
||||
|
@ -106,12 +116,20 @@ BinaryenRustModuleCreate(const BinaryenRustModuleOptions *options,
|
|||
{
|
||||
WasmBinaryWriter writer(&linker.getOutput().wasm, ret->buffer, options->debug);
|
||||
writer.setNamesSection(options->debugInfo);
|
||||
// FIXME: support source maps?
|
||||
// writer.setSourceMap(sourceMapStream.get(), sourceMapUrl);
|
||||
|
||||
std::unique_ptr<std::ostringstream> sourceMapStream = nullptr;
|
||||
{
|
||||
sourceMapStream = make_unique<std::ostringstream>();
|
||||
writer.setSourceMap(sourceMapStream.get(), options->sourceMapUrl);
|
||||
}
|
||||
|
||||
// FIXME: support symbol maps?
|
||||
// writer.setSymbolMap(symbolMap);
|
||||
writer.write();
|
||||
|
||||
if (sourceMapStream) {
|
||||
ret->sourceMapJSON = sourceMapStream->str();
|
||||
}
|
||||
}
|
||||
return ret.release();
|
||||
}
|
||||
|
@ -126,6 +144,16 @@ BinaryenRustModuleLen(const BinaryenRustModule *M) {
|
|||
return M->buffer.size();
|
||||
}
|
||||
|
||||
extern "C" const char*
|
||||
BinaryenRustModuleSourceMapPtr(const BinaryenRustModule *M) {
|
||||
return M->sourceMapJSON.data();
|
||||
}
|
||||
|
||||
extern "C" size_t
|
||||
BinaryenRustModuleSourceMapLen(const BinaryenRustModule *M) {
|
||||
return M->sourceMapJSON.length();
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
BinaryenRustModuleFree(BinaryenRustModule *M) {
|
||||
delete M;
|
||||
|
|
|
@ -51,6 +51,15 @@ impl Module {
|
|||
slice::from_raw_parts(ptr, len)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the data of the source map JSON.
|
||||
pub fn source_map(&self) -> &[u8] {
|
||||
unsafe {
|
||||
let ptr = BinaryenRustModuleSourceMapPtr(self.ptr);
|
||||
let len = BinaryenRustModuleSourceMapLen(self.ptr);
|
||||
slice::from_raw_parts(ptr, len)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Module {
|
||||
|
@ -94,6 +103,15 @@ impl ModuleOptions {
|
|||
self
|
||||
}
|
||||
|
||||
/// Configures a `sourceMappingURL` custom section value for the module.
|
||||
pub fn source_map_url(&mut self, url: &str) -> &mut Self {
|
||||
let url = CString::new(url).unwrap();
|
||||
unsafe {
|
||||
BinaryenRustModuleOptionsSetSourceMapUrl(self.ptr, url.as_ptr());
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures how much stack is initially allocated for the module. 1MB is
|
||||
/// probably good enough for now.
|
||||
pub fn stack(&mut self, amt: u64) -> &mut Self {
|
||||
|
@ -130,6 +148,8 @@ extern {
|
|||
-> *mut BinaryenRustModule;
|
||||
fn BinaryenRustModulePtr(module: *const BinaryenRustModule) -> *const u8;
|
||||
fn BinaryenRustModuleLen(module: *const BinaryenRustModule) -> usize;
|
||||
fn BinaryenRustModuleSourceMapPtr(module: *const BinaryenRustModule) -> *const u8;
|
||||
fn BinaryenRustModuleSourceMapLen(module: *const BinaryenRustModule) -> usize;
|
||||
fn BinaryenRustModuleFree(module: *mut BinaryenRustModule);
|
||||
|
||||
fn BinaryenRustModuleOptionsCreate()
|
||||
|
@ -138,6 +158,8 @@ extern {
|
|||
debuginfo: bool);
|
||||
fn BinaryenRustModuleOptionsSetStart(module: *mut BinaryenRustModuleOptions,
|
||||
start: *const libc::c_char);
|
||||
fn BinaryenRustModuleOptionsSetSourceMapUrl(module: *mut BinaryenRustModuleOptions,
|
||||
sourceMapUrl: *const libc::c_char);
|
||||
fn BinaryenRustModuleOptionsSetStackAllocation(
|
||||
module: *mut BinaryenRustModuleOptions,
|
||||
stack: u64,
|
||||
|
|
|
@ -71,9 +71,12 @@ pub enum Candidate {
|
|||
/// Borrow of a constant temporary.
|
||||
Ref(Location),
|
||||
|
||||
/// Array of indices found in the third argument of
|
||||
/// a call to one of the simd_shuffleN intrinsics.
|
||||
ShuffleIndices(BasicBlock)
|
||||
/// Currently applied to function calls where the callee has the unstable
|
||||
/// `#[rustc_args_required_const]` attribute as well as the SIMD shuffle
|
||||
/// intrinsic. The intrinsic requires the arguments are indeed constant and
|
||||
/// the attribute currently provides the semantic requirement that arguments
|
||||
/// must be constant.
|
||||
Argument { bb: BasicBlock, index: usize },
|
||||
}
|
||||
|
||||
struct TempCollector<'tcx> {
|
||||
|
@ -303,10 +306,10 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
|||
_ => bug!()
|
||||
}
|
||||
}
|
||||
Candidate::ShuffleIndices(bb) => {
|
||||
Candidate::Argument { bb, index } => {
|
||||
match self.source[bb].terminator_mut().kind {
|
||||
TerminatorKind::Call { ref mut args, .. } => {
|
||||
Rvalue::Use(mem::replace(&mut args[2], new_operand))
|
||||
Rvalue::Use(mem::replace(&mut args[index], new_operand))
|
||||
}
|
||||
_ => bug!()
|
||||
}
|
||||
|
@ -359,15 +362,15 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
|
|||
}
|
||||
(statement.source_info.span, dest.ty(mir, tcx).to_ty(tcx))
|
||||
}
|
||||
Candidate::ShuffleIndices(bb) => {
|
||||
Candidate::Argument { bb, index } => {
|
||||
let terminator = mir[bb].terminator();
|
||||
let ty = match terminator.kind {
|
||||
TerminatorKind::Call { ref args, .. } => {
|
||||
args[2].ty(mir, tcx)
|
||||
args[index].ty(mir, tcx)
|
||||
}
|
||||
_ => {
|
||||
span_bug!(terminator.source_info.span,
|
||||
"expected simd_shuffleN call to promote");
|
||||
"expected call argument to promote");
|
||||
}
|
||||
};
|
||||
(terminator.source_info.span, ty)
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
use rustc_data_structures::bitvec::BitVector;
|
||||
use rustc_data_structures::indexed_set::IdxSetBuf;
|
||||
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc::hir;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::middle::const_val::ConstVal;
|
||||
|
@ -30,6 +31,7 @@ use rustc::mir::visit::{PlaceContext, Visitor};
|
|||
use rustc::middle::lang_items;
|
||||
use syntax::abi::Abi;
|
||||
use syntax::attr;
|
||||
use syntax::ast::LitKind;
|
||||
use syntax::feature_gate::UnstableFeatures;
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
|
||||
|
@ -407,7 +409,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
|
|||
_ => {}
|
||||
}
|
||||
}
|
||||
Candidate::ShuffleIndices(_) => {}
|
||||
Candidate::Argument { .. } => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -730,8 +732,10 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
|
|||
self.visit_operand(func, location);
|
||||
|
||||
let fn_ty = func.ty(self.mir, self.tcx);
|
||||
let mut callee_def_id = None;
|
||||
let (mut is_shuffle, mut is_const_fn) = (false, None);
|
||||
if let ty::TyFnDef(def_id, _) = fn_ty.sty {
|
||||
callee_def_id = Some(def_id);
|
||||
match self.tcx.fn_sig(def_id).abi() {
|
||||
Abi::RustIntrinsic |
|
||||
Abi::PlatformIntrinsic => {
|
||||
|
@ -754,17 +758,39 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
let constant_arguments = callee_def_id.and_then(|id| {
|
||||
args_required_const(self.tcx, id)
|
||||
});
|
||||
for (i, arg) in args.iter().enumerate() {
|
||||
self.nest(|this| {
|
||||
this.visit_operand(arg, location);
|
||||
if is_shuffle && i == 2 && this.mode == Mode::Fn {
|
||||
let candidate = Candidate::ShuffleIndices(bb);
|
||||
if this.mode != Mode::Fn {
|
||||
return
|
||||
}
|
||||
let candidate = Candidate::Argument { bb, index: i };
|
||||
if is_shuffle && i == 2 {
|
||||
if this.can_promote() {
|
||||
this.promotion_candidates.push(candidate);
|
||||
} else {
|
||||
span_err!(this.tcx.sess, this.span, E0526,
|
||||
"shuffle indices are not constant");
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
let constant_arguments = match constant_arguments.as_ref() {
|
||||
Some(s) => s,
|
||||
None => return,
|
||||
};
|
||||
if !constant_arguments.contains(&i) {
|
||||
return
|
||||
}
|
||||
if this.can_promote() {
|
||||
this.promotion_candidates.push(candidate);
|
||||
} else {
|
||||
this.tcx.sess.span_err(this.span,
|
||||
&format!("argument {} is required to be a constant",
|
||||
i + 1));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1085,3 +1111,16 @@ impl MirPass for QualifyAndPromoteConstants {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn args_required_const(tcx: TyCtxt, def_id: DefId) -> Option<FxHashSet<usize>> {
|
||||
let attrs = tcx.get_attrs(def_id);
|
||||
let attr = attrs.iter().find(|a| a.check_name("rustc_args_required_const"))?;
|
||||
let mut ret = FxHashSet();
|
||||
for meta in attr.meta_item_list()? {
|
||||
match meta.literal()?.node {
|
||||
LitKind::Int(a, _) => { ret.insert(a as usize); }
|
||||
_ => return None,
|
||||
}
|
||||
}
|
||||
Some(ret)
|
||||
}
|
||||
|
|
|
@ -759,7 +759,10 @@ unsafe fn codegen(cgcx: &CodegenContext,
|
|||
|
||||
if asm2wasm && config.emit_obj {
|
||||
let assembly = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
|
||||
binaryen_assemble(cgcx, diag_handler, &assembly, &obj_out);
|
||||
let suffix = ".wasm.map"; // FIXME use target suffix
|
||||
let map = cgcx.output_filenames.path(OutputType::Exe)
|
||||
.with_extension(&suffix[1..]);
|
||||
binaryen_assemble(cgcx, diag_handler, &assembly, &obj_out, &map);
|
||||
timeline.record("binaryen");
|
||||
|
||||
if !config.emit_asm {
|
||||
|
@ -814,7 +817,8 @@ unsafe fn codegen(cgcx: &CodegenContext,
|
|||
fn binaryen_assemble(cgcx: &CodegenContext,
|
||||
handler: &Handler,
|
||||
assembly: &Path,
|
||||
object: &Path) {
|
||||
object: &Path,
|
||||
map: &Path) {
|
||||
use rustc_binaryen::{Module, ModuleOptions};
|
||||
|
||||
let input = fs::read(&assembly).and_then(|contents| {
|
||||
|
@ -823,6 +827,8 @@ fn binaryen_assemble(cgcx: &CodegenContext,
|
|||
let mut options = ModuleOptions::new();
|
||||
if cgcx.debuginfo != config::NoDebugInfo {
|
||||
options.debuginfo(true);
|
||||
let map_file_name = map.file_name().unwrap();
|
||||
options.source_map_url(map_file_name.to_str().unwrap());
|
||||
}
|
||||
|
||||
options.stack(1024 * 1024);
|
||||
|
@ -832,7 +838,13 @@ fn binaryen_assemble(cgcx: &CodegenContext,
|
|||
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))
|
||||
});
|
||||
let err = assembled.and_then(|binary| {
|
||||
fs::write(&object, binary.data())
|
||||
fs::write(&object, binary.data()).and_then(|()| {
|
||||
if cgcx.debuginfo != config::NoDebugInfo {
|
||||
fs::write(map, binary.source_map())
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
})
|
||||
});
|
||||
if let Err(e) = err {
|
||||
handler.err(&format!("failed to run binaryen assembler: {}", e));
|
||||
|
|
|
@ -326,13 +326,19 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
if reached_raw_pointer
|
||||
&& !self.tcx.sess.features.borrow().arbitrary_self_types {
|
||||
// this case used to be allowed by the compiler,
|
||||
// so we do a future-compat lint here
|
||||
// so we do a future-compat lint here for the 2015 epoch
|
||||
// (see https://github.com/rust-lang/rust/issues/46906)
|
||||
self.tcx.lint_node(
|
||||
lint::builtin::TYVAR_BEHIND_RAW_POINTER,
|
||||
scope_expr_id,
|
||||
span,
|
||||
&format!("the type of this value must be known in this context"));
|
||||
if self.tcx.sess.rust_2018() {
|
||||
span_err!(self.tcx.sess, span, E0908,
|
||||
"the type of this value must be known \
|
||||
to call a method on a raw pointer on it");
|
||||
} else {
|
||||
self.tcx.lint_node(
|
||||
lint::builtin::TYVAR_BEHIND_RAW_POINTER,
|
||||
scope_expr_id,
|
||||
span,
|
||||
&format!("the type of this value must be known in this context"));
|
||||
}
|
||||
} else {
|
||||
let t = self.structurally_resolved_type(span, final_ty);
|
||||
assert_eq!(t, self.tcx.types.err);
|
||||
|
|
|
@ -2925,7 +2925,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
let rcvr = &args[0];
|
||||
let rcvr_t = self.check_expr_with_needs(&rcvr, needs);
|
||||
// no need to check for bot/err -- callee does that
|
||||
let rcvr_t = self.structurally_resolved_type(expr.span, rcvr_t);
|
||||
let rcvr_t = self.structurally_resolved_type(args[0].span, rcvr_t);
|
||||
|
||||
let method = match self.lookup_method(rcvr_t,
|
||||
segment,
|
||||
|
|
|
@ -355,41 +355,35 @@ fn is_param<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
}
|
||||
}
|
||||
|
||||
fn ensure_no_ty_param_bounds(tcx: TyCtxt,
|
||||
span: Span,
|
||||
generics: &hir::Generics,
|
||||
thing: &'static str) {
|
||||
fn ensure_no_param_bounds(tcx: TyCtxt,
|
||||
span: Span,
|
||||
generics: &hir::Generics,
|
||||
thing: &'static str) {
|
||||
let mut warn = false;
|
||||
|
||||
for ty_param in generics.ty_params() {
|
||||
for bound in ty_param.bounds.iter() {
|
||||
match *bound {
|
||||
hir::TraitTyParamBound(..) => {
|
||||
warn = true;
|
||||
}
|
||||
hir::RegionTyParamBound(..) => { }
|
||||
}
|
||||
if !ty_param.bounds.is_empty() {
|
||||
warn = true;
|
||||
}
|
||||
}
|
||||
|
||||
for predicate in generics.where_clause.predicates.iter() {
|
||||
match *predicate {
|
||||
hir::WherePredicate::BoundPredicate(..) => {
|
||||
warn = true;
|
||||
}
|
||||
hir::WherePredicate::RegionPredicate(..) => { }
|
||||
hir::WherePredicate::EqPredicate(..) => { }
|
||||
for lft_param in generics.lifetimes() {
|
||||
if !lft_param.bounds.is_empty() {
|
||||
warn = true;
|
||||
}
|
||||
}
|
||||
|
||||
if !generics.where_clause.predicates.is_empty() {
|
||||
warn = true;
|
||||
}
|
||||
|
||||
if warn {
|
||||
// According to accepted RFC #XXX, we should
|
||||
// eventually accept these, but it will not be
|
||||
// part of this PR. Still, convert to warning to
|
||||
// make bootstrapping easier.
|
||||
span_warn!(tcx.sess, span, E0122,
|
||||
"trait bounds are not (yet) enforced \
|
||||
in {} definitions",
|
||||
"generic bounds are ignored in {}",
|
||||
thing);
|
||||
}
|
||||
}
|
||||
|
@ -455,7 +449,7 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) {
|
|||
}
|
||||
},
|
||||
hir::ItemTy(_, ref generics) => {
|
||||
ensure_no_ty_param_bounds(tcx, it.span, generics, "type");
|
||||
ensure_no_param_bounds(tcx, it.span, generics, "type aliases");
|
||||
tcx.generics_of(def_id);
|
||||
tcx.type_of(def_id);
|
||||
tcx.predicates_of(def_id);
|
||||
|
|
|
@ -4698,6 +4698,55 @@ element type `T`. Also note that the error is conservatively reported even when
|
|||
the alignment of the zero-sized type is less than or equal to the data field's
|
||||
alignment.
|
||||
"##,
|
||||
|
||||
|
||||
E0908: r##"
|
||||
A method was called on a raw pointer whose inner type wasn't completely known.
|
||||
|
||||
For example, you may have done something like:
|
||||
|
||||
```compile_fail
|
||||
# #![deny(warnings)]
|
||||
let foo = &1;
|
||||
let bar = foo as *const _;
|
||||
if bar.is_null() {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
Here, the type of `bar` isn't known; it could be a pointer to anything. Instead,
|
||||
specify a type for the pointer (preferably something that makes sense for the
|
||||
thing you're pointing to):
|
||||
|
||||
```
|
||||
let foo = &1;
|
||||
let bar = foo as *const i32;
|
||||
if bar.is_null() {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
Even though `is_null()` exists as a method on any raw pointer, Rust shows this
|
||||
error because Rust allows for `self` to have arbitrary types (behind the
|
||||
arbitrary_self_types feature flag).
|
||||
|
||||
This means that someone can specify such a function:
|
||||
|
||||
```ignore (cannot-doctest-feature-doesnt-exist-yet)
|
||||
impl Foo {
|
||||
fn is_null(self: *const Self) -> bool {
|
||||
// do something else
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
and now when you call `.is_null()` on a raw pointer to `Foo`, there's ambiguity.
|
||||
|
||||
Given that we don't know what type the pointer is, and there's potential
|
||||
ambiguity for some types, we disallow calling methods on raw pointers when
|
||||
the type is unknown.
|
||||
"##,
|
||||
|
||||
}
|
||||
|
||||
register_diagnostics! {
|
||||
|
|
|
@ -47,6 +47,8 @@
|
|||
// 2 for "In Return Types"
|
||||
var currentTab = 0;
|
||||
|
||||
var themesWidth = null;
|
||||
|
||||
function hasClass(elem, className) {
|
||||
if (elem && className && elem.className) {
|
||||
var elemClass = elem.className;
|
||||
|
@ -121,10 +123,25 @@
|
|||
sidebar.appendChild(div);
|
||||
}
|
||||
}
|
||||
var themeChoices = document.getElementById("theme-choices");
|
||||
if (themeChoices) {
|
||||
if (!themesWidth) {
|
||||
var savedState = themeChoices.style.display;
|
||||
themeChoices.style.display = 'block';
|
||||
themesWidth = themeChoices.offsetWidth + 'px';
|
||||
themeChoices.style.display = savedState;
|
||||
}
|
||||
themeChoices.style.position = "fixed";
|
||||
themeChoices.style.width = themesWidth;
|
||||
themeChoices.style.top = '78px';
|
||||
themeChoices.style.left = '250px';
|
||||
}
|
||||
document.getElementsByTagName("body")[0].style.marginTop = '45px';
|
||||
var themePicker = document.getElementById("theme-picker");
|
||||
if (themePicker) {
|
||||
themePicker.style.position = "fixed";
|
||||
themePicker.style.top = "50px";
|
||||
themePicker.style.left = "250px";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -143,6 +160,15 @@
|
|||
var themePicker = document.getElementById("theme-picker");
|
||||
if (themePicker) {
|
||||
themePicker.style.position = "absolute";
|
||||
themePicker.style.top = null;
|
||||
themePicker.style.left = null;
|
||||
}
|
||||
var themeChoices = document.getElementById("theme-choices");
|
||||
if (themeChoices) {
|
||||
themeChoices.style.position = 'absolute';
|
||||
themeChoices.style.width = null;
|
||||
themeChoices.style.top = null;
|
||||
themeChoices.style.left = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -870,6 +870,7 @@ span.since {
|
|||
display: block;
|
||||
border-bottom: 1px solid;
|
||||
border-right: 1px solid;
|
||||
height: 45px;
|
||||
}
|
||||
|
||||
.sidebar-elems {
|
||||
|
@ -889,13 +890,19 @@ span.since {
|
|||
}
|
||||
|
||||
nav.sub {
|
||||
margin: 0 auto;
|
||||
width: calc(100% - 32px);
|
||||
float: right;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
#main {
|
||||
margin-top: 50px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.content .in-band {
|
||||
width: 100%;
|
||||
}
|
||||
|
@ -1042,6 +1049,24 @@ h4 > .important-traits {
|
|||
|
||||
.show-it {
|
||||
display: block;
|
||||
width: 246px;
|
||||
}
|
||||
|
||||
.show-it > .block.items {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.show-it > .block.items > ul {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.show-it > .block.items > ul > li {
|
||||
text-align: center;
|
||||
margin: 2px 0;
|
||||
}
|
||||
|
||||
.show-it > .block.items > ul > li > a {
|
||||
font-size: 21px;
|
||||
}
|
||||
|
||||
/* Because of ios, we need to actually have a full height sidebar title so the
|
||||
|
@ -1198,8 +1223,8 @@ kbd {
|
|||
|
||||
@media (max-width: 700px) {
|
||||
.theme-picker {
|
||||
left: 109px;
|
||||
top: 7px;
|
||||
left: 10px;
|
||||
top: 54px;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -383,6 +383,6 @@ kbd {
|
|||
|
||||
@media (max-width: 700px) {
|
||||
#theme-picker {
|
||||
background: #353535;
|
||||
background: #f0f0f0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -198,7 +198,7 @@ impl<T: RefUnwindSafe + ?Sized> UnwindSafe for *const T {}
|
|||
impl<T: RefUnwindSafe + ?Sized> UnwindSafe for *mut T {}
|
||||
#[unstable(feature = "ptr_internals", issue = "0")]
|
||||
impl<T: UnwindSafe + ?Sized> UnwindSafe for Unique<T> {}
|
||||
#[stable(feature = "nonnull", since = "1.24.0")]
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
impl<T: RefUnwindSafe + ?Sized> UnwindSafe for NonNull<T> {}
|
||||
#[stable(feature = "catch_unwind", since = "1.9.0")]
|
||||
impl<T: ?Sized> UnwindSafe for Mutex<T> {}
|
||||
|
|
|
@ -761,6 +761,18 @@ impl<'a> Parser<'a> {
|
|||
})
|
||||
}
|
||||
|
||||
fn expected_ident_found(&self) -> DiagnosticBuilder<'a> {
|
||||
let mut err = self.struct_span_err(self.span,
|
||||
&format!("expected identifier, found {}",
|
||||
self.this_token_descr()));
|
||||
if let Some(token_descr) = self.token_descr() {
|
||||
err.span_label(self.span, format!("expected identifier, found {}", token_descr));
|
||||
} else {
|
||||
err.span_label(self.span, "expected identifier");
|
||||
}
|
||||
err
|
||||
}
|
||||
|
||||
pub fn parse_ident(&mut self) -> PResult<'a, ast::Ident> {
|
||||
self.parse_ident_common(true)
|
||||
}
|
||||
|
@ -769,15 +781,7 @@ impl<'a> Parser<'a> {
|
|||
match self.token {
|
||||
token::Ident(i) => {
|
||||
if self.token.is_reserved_ident() {
|
||||
let mut err = self.struct_span_err(self.span,
|
||||
&format!("expected identifier, found {}",
|
||||
self.this_token_descr()));
|
||||
if let Some(token_descr) = self.token_descr() {
|
||||
err.span_label(self.span, format!("expected identifier, found {}",
|
||||
token_descr));
|
||||
} else {
|
||||
err.span_label(self.span, "expected identifier");
|
||||
}
|
||||
let mut err = self.expected_ident_found();
|
||||
if recover {
|
||||
err.emit();
|
||||
} else {
|
||||
|
@ -791,14 +795,7 @@ impl<'a> Parser<'a> {
|
|||
Err(if self.prev_token_kind == PrevTokenKind::DocComment {
|
||||
self.span_fatal_err(self.prev_span, Error::UselessDocComment)
|
||||
} else {
|
||||
let mut err = self.fatal(&format!("expected identifier, found `{}`",
|
||||
self.this_token_to_string()));
|
||||
if let Some(token_descr) = self.token_descr() {
|
||||
err.span_label(self.span, format!("expected identifier, found {}",
|
||||
token_descr));
|
||||
} else {
|
||||
err.span_label(self.span, "expected identifier");
|
||||
}
|
||||
let mut err = self.expected_ident_found();
|
||||
if self.token == token::Underscore {
|
||||
err.note("`_` is a wildcard pattern, not an identifier");
|
||||
}
|
||||
|
|
23
src/test/codegen/repeat-trusted-len.rs
Normal file
23
src/test/codegen/repeat-trusted-len.rs
Normal file
|
@ -0,0 +1,23 @@
|
|||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -O
|
||||
// ignore-tidy-linelength
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
use std::iter;
|
||||
|
||||
// CHECK-LABEL: @repeat_take_collect
|
||||
#[no_mangle]
|
||||
pub fn repeat_take_collect() -> Vec<u8> {
|
||||
// CHECK: call void @llvm.memset.p0i8
|
||||
iter::repeat(42).take(100000).collect()
|
||||
}
|
|
@ -22,7 +22,7 @@ const A_I8_T
|
|||
: [u32; (i8::MAX as i8 + 1u8) as usize]
|
||||
//~^ ERROR mismatched types
|
||||
//~| expected i8, found u8
|
||||
//~| ERROR the trait bound `i8: std::ops::Add<u8>` is not satisfied
|
||||
//~| ERROR cannot add `u8` to `i8`
|
||||
= [0; (i8::MAX as usize) + 1];
|
||||
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
#![feature(unsized_tuple_coercion)]
|
||||
|
||||
type Fat<T: ?Sized> = (isize, &'static str, T);
|
||||
//~^ WARNING trait bounds are not (yet) enforced
|
||||
//~^ WARNING bounds are ignored
|
||||
|
||||
#[derive(PartialEq,Eq)]
|
||||
struct Bar;
|
||||
|
|
23
src/test/compile-fail/epoch-raw-pointer-method-2015.rs
Normal file
23
src/test/compile-fail/epoch-raw-pointer-method-2015.rs
Normal file
|
@ -0,0 +1,23 @@
|
|||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// ignore-tidy-linelength
|
||||
// compile-flags: -Zepoch=2015 -Zunstable-options
|
||||
|
||||
// tests that epochs work with the tyvar warning-turned-error
|
||||
|
||||
#[deny(warnings)]
|
||||
fn main() {
|
||||
let x = 0;
|
||||
let y = &x as *const _;
|
||||
let _ = y.is_null();
|
||||
//~^ error: the type of this value must be known in this context [tyvar_behind_raw_pointer]
|
||||
//~^^ warning: this was previously accepted
|
||||
}
|
22
src/test/compile-fail/epoch-raw-pointer-method-2018.rs
Normal file
22
src/test/compile-fail/epoch-raw-pointer-method-2018.rs
Normal file
|
@ -0,0 +1,22 @@
|
|||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// ignore-tidy-linelength
|
||||
// compile-flags: -Zepoch=2018 -Zunstable-options
|
||||
|
||||
// tests that epochs work with the tyvar warning-turned-error
|
||||
|
||||
#[deny(warnings)]
|
||||
fn main() {
|
||||
let x = 0;
|
||||
let y = &x as *const _;
|
||||
let _ = y.is_null();
|
||||
//~^ error: the type of this value must be known to call a method on a raw pointer on it [E0908]
|
||||
}
|
|
@ -58,7 +58,7 @@ mod traits {
|
|||
pub trait PubTr {}
|
||||
|
||||
pub type Alias<T: PrivTr> = T; //~ ERROR private trait `traits::PrivTr` in public interface
|
||||
//~^ WARN trait bounds are not (yet) enforced in type definitions
|
||||
//~^ WARN bounds are ignored in type aliases
|
||||
//~| WARNING hard error
|
||||
pub trait Tr1: PrivTr {} //~ ERROR private trait `traits::PrivTr` in public interface
|
||||
//~^ WARNING hard error
|
||||
|
|
36
src/test/compile-fail/rustc-args-required-const.rs
Normal file
36
src/test/compile-fail/rustc-args-required-const.rs
Normal file
|
@ -0,0 +1,36 @@
|
|||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(attr_literals, rustc_attrs, const_fn)]
|
||||
|
||||
#[rustc_args_required_const(0)]
|
||||
fn foo(_a: i32) {
|
||||
}
|
||||
|
||||
#[rustc_args_required_const(1)]
|
||||
fn bar(_a: i32, _b: i32) {
|
||||
}
|
||||
|
||||
const A: i32 = 3;
|
||||
|
||||
const fn baz() -> i32 {
|
||||
3
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foo(2);
|
||||
foo(2 + 3);
|
||||
foo(baz());
|
||||
let a = 4;
|
||||
foo(A);
|
||||
foo(a); //~ ERROR: argument 1 is required to be a constant
|
||||
bar(a, 3);
|
||||
bar(a, a); //~ ERROR: argument 2 is required to be a constant
|
||||
}
|
|
@ -12,7 +12,7 @@ use std::ops::Add;
|
|||
|
||||
fn main() {
|
||||
<i32 as Add<u32>>::add(1, 2);
|
||||
//~^ ERROR `i32: std::ops::Add<u32>` is not satisfied
|
||||
//~^ ERROR cannot add `u32` to `i32`
|
||||
<i32 as Add<i32>>::add(1u32, 2);
|
||||
//~^ ERROR mismatched types
|
||||
<i32 as Add<i32>>::add(1, 2u32);
|
||||
|
|
|
@ -32,7 +32,7 @@ fn sum_to(n: u32) -> impl Foo {
|
|||
0
|
||||
} else {
|
||||
n + sum_to(n - 1)
|
||||
//~^ ERROR the trait bound `u32: std::ops::Add<impl Foo>` is not satisfied
|
||||
//~^ ERROR cannot add `impl Foo` to `u32`
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ error[E0308]: mismatched types
|
|||
= note: expected type `i32`
|
||||
found type `u32`
|
||||
|
||||
error[E0277]: the trait bound `u32: std::ops::Add<impl Foo>` is not satisfied
|
||||
error[E0277]: cannot add `impl Foo` to `u32`
|
||||
--> $DIR/equality.rs:34:11
|
||||
|
|
||||
34 | n + sum_to(n - 1)
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// must-compile-successfully
|
||||
|
||||
#![warn(unused)] // UI tests pass `-A unused` (#43896)
|
||||
|
||||
struct SoulHistory {
|
||||
corridors_of_light: usize,
|
||||
hours_are_suns: bool,
|
||||
endless_and_singing: bool
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let i_think_continually = 2;
|
||||
let who_from_the_womb_remembered = SoulHistory {
|
||||
corridors_of_light: 5,
|
||||
hours_are_suns: true,
|
||||
endless_and_singing: true
|
||||
};
|
||||
|
||||
if let SoulHistory { corridors_of_light,
|
||||
mut hours_are_suns,
|
||||
endless_and_singing: true } = who_from_the_womb_remembered {
|
||||
hours_are_suns = false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
warning: unused variable: `i_think_continually`
|
||||
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:22:9
|
||||
|
|
||||
22 | let i_think_continually = 2;
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: consider using `_i_think_continually` instead
|
||||
|
|
||||
note: lint level defined here
|
||||
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:13:9
|
||||
|
|
||||
13 | #![warn(unused)] // UI tests pass `-A unused` (#43896)
|
||||
| ^^^^^^
|
||||
= note: #[warn(unused_variables)] implied by #[warn(unused)]
|
||||
|
||||
warning: unused variable: `corridors_of_light`
|
||||
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:29:26
|
||||
|
|
||||
29 | if let SoulHistory { corridors_of_light,
|
||||
| ^^^^^^^^^^^^^^^^^^ help: try ignoring the field: `corridors_of_light: _`
|
||||
|
||||
warning: variable `hours_are_suns` is assigned to, but never used
|
||||
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:30:26
|
||||
|
|
||||
30 | mut hours_are_suns,
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: consider using `_hours_are_suns` instead
|
||||
|
||||
warning: value assigned to `hours_are_suns` is never read
|
||||
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:32:9
|
||||
|
|
||||
32 | hours_are_suns = false;
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
note: lint level defined here
|
||||
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:13:9
|
||||
|
|
||||
13 | #![warn(unused)] // UI tests pass `-A unused` (#43896)
|
||||
| ^^^^^^
|
||||
= note: #[warn(unused_assignments)] implied by #[warn(unused)]
|
||||
|
|
@ -9,10 +9,10 @@
|
|||
// except according to those terms.
|
||||
|
||||
fn main() {
|
||||
1 + Some(1); //~ ERROR is not satisfied
|
||||
2 as usize - Some(1); //~ ERROR is not satisfied
|
||||
3 * (); //~ ERROR is not satisfied
|
||||
4 / ""; //~ ERROR is not satisfied
|
||||
1 + Some(1); //~ ERROR cannot add `std::option::Option<{integer}>` to `{integer}`
|
||||
2 as usize - Some(1); //~ ERROR cannot substract `std::option::Option<{integer}>` from `usize`
|
||||
3 * (); //~ ERROR cannot multiply `()` to `{integer}`
|
||||
4 / ""; //~ ERROR cannot divide `{integer}` by `&str`
|
||||
5 < String::new(); //~ ERROR is not satisfied
|
||||
6 == Ok(1); //~ ERROR is not satisfied
|
||||
}
|
||||
|
|
|
@ -1,31 +1,31 @@
|
|||
error[E0277]: the trait bound `{integer}: std::ops::Add<std::option::Option<{integer}>>` is not satisfied
|
||||
error[E0277]: cannot add `std::option::Option<{integer}>` to `{integer}`
|
||||
--> $DIR/binops.rs:12:7
|
||||
|
|
||||
12 | 1 + Some(1); //~ ERROR is not satisfied
|
||||
12 | 1 + Some(1); //~ ERROR cannot add `std::option::Option<{integer}>` to `{integer}`
|
||||
| ^ no implementation for `{integer} + std::option::Option<{integer}>`
|
||||
|
|
||||
= help: the trait `std::ops::Add<std::option::Option<{integer}>>` is not implemented for `{integer}`
|
||||
|
||||
error[E0277]: the trait bound `usize: std::ops::Sub<std::option::Option<{integer}>>` is not satisfied
|
||||
error[E0277]: cannot substract `std::option::Option<{integer}>` from `usize`
|
||||
--> $DIR/binops.rs:13:16
|
||||
|
|
||||
13 | 2 as usize - Some(1); //~ ERROR is not satisfied
|
||||
13 | 2 as usize - Some(1); //~ ERROR cannot substract `std::option::Option<{integer}>` from `usize`
|
||||
| ^ no implementation for `usize - std::option::Option<{integer}>`
|
||||
|
|
||||
= help: the trait `std::ops::Sub<std::option::Option<{integer}>>` is not implemented for `usize`
|
||||
|
||||
error[E0277]: the trait bound `{integer}: std::ops::Mul<()>` is not satisfied
|
||||
error[E0277]: cannot multiply `()` to `{integer}`
|
||||
--> $DIR/binops.rs:14:7
|
||||
|
|
||||
14 | 3 * (); //~ ERROR is not satisfied
|
||||
14 | 3 * (); //~ ERROR cannot multiply `()` to `{integer}`
|
||||
| ^ no implementation for `{integer} * ()`
|
||||
|
|
||||
= help: the trait `std::ops::Mul<()>` is not implemented for `{integer}`
|
||||
|
||||
error[E0277]: the trait bound `{integer}: std::ops::Div<&str>` is not satisfied
|
||||
error[E0277]: cannot divide `{integer}` by `&str`
|
||||
--> $DIR/binops.rs:15:7
|
||||
|
|
||||
15 | 4 / ""; //~ ERROR is not satisfied
|
||||
15 | 4 / ""; //~ ERROR cannot divide `{integer}` by `&str`
|
||||
| ^ no implementation for `{integer} / &str`
|
||||
|
|
||||
= help: the trait `std::ops::Div<&str>` is not implemented for `{integer}`
|
||||
|
|
14
src/test/ui/on-unimplemented/auxiliary/no_debug.rs
Normal file
14
src/test/ui/on-unimplemented/auxiliary/no_debug.rs
Normal file
|
@ -0,0 +1,14 @@
|
|||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
// ignore-tidy-linelength
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
pub struct Bar;
|
27
src/test/ui/on-unimplemented/no-debug.rs
Normal file
27
src/test/ui/on-unimplemented/no-debug.rs
Normal file
|
@ -0,0 +1,27 @@
|
|||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// aux-build:no_debug.rs
|
||||
|
||||
extern crate no_debug;
|
||||
|
||||
use no_debug::Bar;
|
||||
|
||||
struct Foo;
|
||||
|
||||
fn main() {
|
||||
println!("{:?} {:?}", Foo, Bar);
|
||||
println!("{} {}", Foo, Bar);
|
||||
}
|
||||
//~^^^ ERROR `Foo` doesn't implement `std::fmt::Debug`
|
||||
//~| ERROR `no_debug::Bar` doesn't implement `std::fmt::Debug`
|
||||
//~^^^^ ERROR `Foo` doesn't implement `std::fmt::Display`
|
||||
//~| ERROR `no_debug::Bar` doesn't implement `std::fmt::Display`
|
||||
|
38
src/test/ui/on-unimplemented/no-debug.stderr
Normal file
38
src/test/ui/on-unimplemented/no-debug.stderr
Normal file
|
@ -0,0 +1,38 @@
|
|||
error[E0277]: `Foo` doesn't implement `std::fmt::Debug`
|
||||
--> $DIR/no-debug.rs:20:27
|
||||
|
|
||||
20 | println!("{:?} {:?}", Foo, Bar);
|
||||
| ^^^ `Foo` cannot be formatted using `:?`; add `#[derive(Debug)]` or manually implement `std::fmt::Debug`
|
||||
|
|
||||
= help: the trait `std::fmt::Debug` is not implemented for `Foo`
|
||||
= note: required by `std::fmt::Debug::fmt`
|
||||
|
||||
error[E0277]: `no_debug::Bar` doesn't implement `std::fmt::Debug`
|
||||
--> $DIR/no-debug.rs:20:32
|
||||
|
|
||||
20 | println!("{:?} {:?}", Foo, Bar);
|
||||
| ^^^ `no_debug::Bar` cannot be formatted using `:?` because it doesn't implement `std::fmt::Debug`
|
||||
|
|
||||
= help: the trait `std::fmt::Debug` is not implemented for `no_debug::Bar`
|
||||
= note: required by `std::fmt::Debug::fmt`
|
||||
|
||||
error[E0277]: `Foo` doesn't implement `std::fmt::Display`
|
||||
--> $DIR/no-debug.rs:21:23
|
||||
|
|
||||
21 | println!("{} {}", Foo, Bar);
|
||||
| ^^^ `Foo` cannot be formatted with the default formatter; try using `:?` instead if you are using a format string
|
||||
|
|
||||
= help: the trait `std::fmt::Display` is not implemented for `Foo`
|
||||
= note: required by `std::fmt::Display::fmt`
|
||||
|
||||
error[E0277]: `no_debug::Bar` doesn't implement `std::fmt::Display`
|
||||
--> $DIR/no-debug.rs:21:28
|
||||
|
|
||||
21 | println!("{} {}", Foo, Bar);
|
||||
| ^^^ `no_debug::Bar` cannot be formatted with the default formatter; try using `:?` instead if you are using a format string
|
||||
|
|
||||
= help: the trait `std::fmt::Display` is not implemented for `no_debug::Bar`
|
||||
= note: required by `std::fmt::Display::fmt`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
33
src/test/ui/param-bounds-ignored.rs
Normal file
33
src/test/ui/param-bounds-ignored.rs
Normal file
|
@ -0,0 +1,33 @@
|
|||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// must-compile-successfully
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
type SVec<T: Send> = Vec<T>;
|
||||
type VVec<'b, 'a: 'b> = Vec<&'a i32>;
|
||||
type WVec<'b, T: 'b> = Vec<T>;
|
||||
|
||||
fn foo<'a>(y: &'a i32) {
|
||||
// If the bounds above would matter, the code below would be rejected.
|
||||
let mut x : SVec<_> = Vec::new();
|
||||
x.push(Rc::new(42));
|
||||
|
||||
let mut x : VVec<'static, 'a> = Vec::new();
|
||||
x.push(y);
|
||||
|
||||
let mut x : WVec<'static, & 'a i32> = Vec::new();
|
||||
x.push(y);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foo(&42);
|
||||
}
|
18
src/test/ui/param-bounds-ignored.stderr
Normal file
18
src/test/ui/param-bounds-ignored.stderr
Normal file
|
@ -0,0 +1,18 @@
|
|||
warning[E0122]: generic bounds are ignored in type aliases
|
||||
--> $DIR/param-bounds-ignored.rs:15:1
|
||||
|
|
||||
15 | type SVec<T: Send> = Vec<T>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning[E0122]: generic bounds are ignored in type aliases
|
||||
--> $DIR/param-bounds-ignored.rs:16:1
|
||||
|
|
||||
16 | type VVec<'b, 'a: 'b> = Vec<&'a i32>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning[E0122]: generic bounds are ignored in type aliases
|
||||
--> $DIR/param-bounds-ignored.rs:17:1
|
||||
|
|
||||
17 | type WVec<'b, T: 'b> = Vec<T>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -2,7 +2,7 @@ warning: unused variable: `theOtherTwo`
|
|||
--> $DIR/issue-24690.rs:23:9
|
||||
|
|
||||
23 | let theOtherTwo = 2; //~ WARN should have a snake case name
|
||||
| ^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^ help: consider using `_theOtherTwo` instead
|
||||
|
|
||||
note: lint level defined here
|
||||
--> $DIR/issue-24690.rs:18:9
|
||||
|
@ -10,7 +10,6 @@ note: lint level defined here
|
|||
18 | #![warn(unused)]
|
||||
| ^^^^^^
|
||||
= note: #[warn(unused_variables)] implied by #[warn(unused)]
|
||||
= note: to avoid this warning, consider using `_theOtherTwo` instead
|
||||
|
||||
warning: variable `theTwo` should have a snake case name such as `the_two`
|
||||
--> $DIR/issue-24690.rs:22:9
|
||||
|
|
27
src/test/ui/span/issue-42234-unknown-receiver-type.rs
Normal file
27
src/test/ui/span/issue-42234-unknown-receiver-type.rs
Normal file
|
@ -0,0 +1,27 @@
|
|||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// When the type of a method call's receiver is unknown, the span should point
|
||||
// to the receiver (and not the entire call, as was previously the case before
|
||||
// the fix of which this tests).
|
||||
|
||||
fn shines_a_beacon_through_the_darkness() {
|
||||
let x: Option<_> = None;
|
||||
x.unwrap().method_that_could_exist_on_some_type();
|
||||
//~^ ERROR 17:5: 17:15: the type of this value must be known in this context
|
||||
}
|
||||
|
||||
fn courier_to_des_moines_and_points_west(data: &[u32]) -> String {
|
||||
data.iter() //~ ERROR 22:5: 23:20: the type of this value must be known in this context
|
||||
.sum::<_>()
|
||||
.to_string()
|
||||
}
|
||||
|
||||
fn main() {}
|
15
src/test/ui/span/issue-42234-unknown-receiver-type.stderr
Normal file
15
src/test/ui/span/issue-42234-unknown-receiver-type.stderr
Normal file
|
@ -0,0 +1,15 @@
|
|||
error[E0619]: the type of this value must be known in this context
|
||||
--> $DIR/issue-42234-unknown-receiver-type.rs:17:5
|
||||
|
|
||||
17 | x.unwrap().method_that_could_exist_on_some_type();
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0619]: the type of this value must be known in this context
|
||||
--> $DIR/issue-42234-unknown-receiver-type.rs:22:5
|
||||
|
|
||||
22 | / data.iter() //~ ERROR 22:5: 23:20: the type of this value must be known in this context
|
||||
23 | | .sum::<_>()
|
||||
| |___________________^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
|
@ -20,7 +20,7 @@ fn main() {
|
|||
let x = 1;
|
||||
let y = 2;
|
||||
let z = 3;
|
||||
foo(1 as u32 + //~ ERROR not satisfied
|
||||
foo(1 as u32 + //~ ERROR cannot add `()` to `u32`
|
||||
|
||||
bar(x,
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
error[E0277]: the trait bound `u32: std::ops::Add<()>` is not satisfied
|
||||
error[E0277]: cannot add `()` to `u32`
|
||||
--> $DIR/multiline-span-simple.rs:23:18
|
||||
|
|
||||
23 | foo(1 as u32 + //~ ERROR not satisfied
|
||||
23 | foo(1 as u32 + //~ ERROR cannot add `()` to `u32`
|
||||
| ^ no implementation for `u32 + ()`
|
||||
|
|
||||
= help: the trait `std::ops::Add<()>` is not implemented for `u32`
|
||||
|
|
|
@ -2,7 +2,7 @@ error[E0277]: the trait bound `&str: std::iter::Iterator` is not satisfied
|
|||
--> $DIR/for-c-in-str.rs:14:14
|
||||
|
|
||||
14 | for c in "asdf" {
|
||||
| ^^^^^^ `&str` is not an iterator; maybe try calling `.iter()` or a similar method
|
||||
| ^^^^^^ `&str` is not an iterator; try calling `.chars()` or `.bytes()`
|
||||
|
|
||||
= help: the trait `std::iter::Iterator` is not implemented for `&str`
|
||||
= note: required by `std::iter::IntoIterator::into_iter`
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue