!target.contains("emscripten") &&
!target.contains("wasm32") &&
!target.contains("nvptx") &&
+ !target.contains("fortanix") &&
!target.contains("fuchsia") {
Some(self.cc(target))
} else {
impl Layout {
/// Constructs a `Layout` from a given `size` and `align`,
- /// or returns `LayoutErr` if either of the following conditions
+ /// or returns `LayoutErr` if any of the following conditions
/// are not met:
///
/// * `align` must not be zero,
#[inline]
pub fn for_value<T: ?Sized>(t: &T) -> Self {
let (size, align) = (mem::size_of_val(t), mem::align_of_val(t));
- // See rationale in `new` for why this us using an unsafe variant below
+ // See rationale in `new` for why this is using an unsafe variant below
debug_assert!(Layout::from_size_align(size, align).is_ok());
unsafe {
Layout::from_size_align_unchecked(size, align)
// valid.
//
// 2. `len + align - 1` can overflow by at most `align - 1`,
- // so the &-mask wth `!(align - 1)` will ensure that in the
+ // so the &-mask with `!(align - 1)` will ensure that in the
// case of overflow, `len_rounded_up` will itself be 0.
// Thus the returned padding, when added to `len`, yields 0,
// which trivially satisfies the alignment `align`.
/// ```
/// #![feature(bool_to_option)]
///
- /// assert_eq!(false.then(0), None);
- /// assert_eq!(true.then(0), Some(0));
+ /// assert_eq!(false.then_some(0), None);
+ /// assert_eq!(true.then_some(0), Some(0));
/// ```
#[unstable(feature = "bool_to_option", issue = "64260")]
#[inline]
- pub fn then<T>(self, t: T) -> Option<T> {
+ pub fn then_some<T>(self, t: T) -> Option<T> {
if self {
Some(t)
} else {
/// ```
/// #![feature(bool_to_option)]
///
- /// assert_eq!(false.then_with(|| 0), None);
- /// assert_eq!(true.then_with(|| 0), Some(0));
+ /// assert_eq!(false.then(|| 0), None);
+ /// assert_eq!(true.then(|| 0), Some(0));
/// ```
#[unstable(feature = "bool_to_option", issue = "64260")]
#[inline]
- pub fn then_with<T, F: FnOnce() -> T>(self, f: F) -> Option<T> {
+ pub fn then<T, F: FnOnce() -> T>(self, f: F) -> Option<T> {
if self {
Some(f())
} else {
+++ /dev/null
-//! Traits for conversions between types.
-//!
-//! The traits in this module provide a way to convert from one type to another type.
-//! Each trait serves a different purpose:
-//!
-//! - Implement the [`AsRef`] trait for cheap reference-to-reference conversions
-//! - Implement the [`AsMut`] trait for cheap mutable-to-mutable conversions
-//! - Implement the [`From`] trait for consuming value-to-value conversions
-//! - Implement the [`Into`] trait for consuming value-to-value conversions to types
-//! outside the current crate
-//! - The [`TryFrom`] and [`TryInto`] traits behave like [`From`] and [`Into`],
-//! but should be implemented when the conversion can fail.
-//!
-//! The traits in this module are often used as trait bounds for generic functions such that to
-//! arguments of multiple types are supported. See the documentation of each trait for examples.
-//!
-//! As a library author, you should always prefer implementing [`From<T>`][`From`] or
-//! [`TryFrom<T>`][`TryFrom`] rather than [`Into<U>`][`Into`] or [`TryInto<U>`][`TryInto`],
-//! as [`From`] and [`TryFrom`] provide greater flexibility and offer
-//! equivalent [`Into`] or [`TryInto`] implementations for free, thanks to a
-//! blanket implementation in the standard library. Only implement [`Into`] or [`TryInto`]
-//! when a conversion to a type outside the current crate is required.
-//!
-//! # Generic Implementations
-//!
-//! - [`AsRef`] and [`AsMut`] auto-dereference if the inner type is a reference
-//! - [`From`]`<U> for T` implies [`Into`]`<T> for U`
-//! - [`TryFrom`]`<U> for T` implies [`TryInto`]`<T> for U`
-//! - [`From`] and [`Into`] are reflexive, which means that all types can
-//! `into` themselves and `from` themselves
-//!
-//! See each trait for usage examples.
-//!
-//! [`Into`]: trait.Into.html
-//! [`From`]: trait.From.html
-//! [`TryFrom`]: trait.TryFrom.html
-//! [`TryInto`]: trait.TryInto.html
-//! [`AsRef`]: trait.AsRef.html
-//! [`AsMut`]: trait.AsMut.html
-
-#![stable(feature = "rust1", since = "1.0.0")]
-
-/// The identity function.
-///
-/// Two things are important to note about this function:
-///
-/// - It is not always equivalent to a closure like `|x| x`, since the
-/// closure may coerce `x` into a different type.
-///
-/// - It moves the input `x` passed to the function.
-///
-/// While it might seem strange to have a function that just returns back the
-/// input, there are some interesting uses.
-///
-/// # Examples
-///
-/// Using `identity` to do nothing in a sequence of other, interesting,
-/// functions:
-///
-/// ```rust
-/// use std::convert::identity;
-///
-/// fn manipulation(x: u32) -> u32 {
-/// // Let's pretend that adding one is an interesting function.
-/// x + 1
-/// }
-///
-/// let _arr = &[identity, manipulation];
-/// ```
-///
-/// Using `identity` as a "do nothing" base case in a conditional:
-///
-/// ```rust
-/// use std::convert::identity;
-///
-/// # let condition = true;
-/// #
-/// # fn manipulation(x: u32) -> u32 { x + 1 }
-/// #
-/// let do_stuff = if condition { manipulation } else { identity };
-///
-/// // Do more interesting stuff...
-///
-/// let _results = do_stuff(42);
-/// ```
-///
-/// Using `identity` to keep the `Some` variants of an iterator of `Option<T>`:
-///
-/// ```rust
-/// use std::convert::identity;
-///
-/// let iter = vec![Some(1), None, Some(3)].into_iter();
-/// let filtered = iter.filter_map(identity).collect::<Vec<_>>();
-/// assert_eq!(vec![1, 3], filtered);
-/// ```
-#[stable(feature = "convert_id", since = "1.33.0")]
-#[inline]
-pub const fn identity<T>(x: T) -> T {
- x
-}
-
-/// Used to do a cheap reference-to-reference conversion.
-///
-/// This trait is similar to [`AsMut`] which is used for converting between mutable references.
-/// If you need to do a costly conversion it is better to implement [`From`] with type
-/// `&T` or write a custom function.
-///
-/// `AsRef` has the same signature as [`Borrow`], but [`Borrow`] is different in few aspects:
-///
-/// - Unlike `AsRef`, [`Borrow`] has a blanket impl for any `T`, and can be used to accept either
-/// a reference or a value.
-/// - [`Borrow`] also requires that [`Hash`], [`Eq`] and [`Ord`] for borrowed value are
-/// equivalent to those of the owned value. For this reason, if you want to
-/// borrow only a single field of a struct you can implement `AsRef`, but not [`Borrow`].
-///
-/// **Note: This trait must not fail**. If the conversion can fail, use a
-/// dedicated method which returns an [`Option<T>`] or a [`Result<T, E>`].
-///
-/// # Generic Implementations
-///
-/// - `AsRef` auto-dereferences if the inner type is a reference or a mutable
-/// reference (e.g.: `foo.as_ref()` will work the same if `foo` has type
-/// `&mut Foo` or `&&mut Foo`)
-///
-/// # Examples
-///
-/// By using trait bounds we can accept arguments of different types as long as they can be
-/// converted to the specified type `T`.
-///
-/// For example: By creating a generic function that takes an `AsRef<str>` we express that we
-/// want to accept all references that can be converted to [`&str`] as an argument.
-/// Since both [`String`] and [`&str`] implement `AsRef<str>` we can accept both as input argument.
-///
-/// [`Option<T>`]: ../../std/option/enum.Option.html
-/// [`Result<T, E>`]: ../../std/result/enum.Result.html
-/// [`Borrow`]: ../../std/borrow/trait.Borrow.html
-/// [`Hash`]: ../../std/hash/trait.Hash.html
-/// [`Eq`]: ../../std/cmp/trait.Eq.html
-/// [`Ord`]: ../../std/cmp/trait.Ord.html
-/// [`&str`]: ../../std/primitive.str.html
-/// [`String`]: ../../std/string/struct.String.html
-///
-/// ```
-/// fn is_hello<T: AsRef<str>>(s: T) {
-/// assert_eq!("hello", s.as_ref());
-/// }
-///
-/// let s = "hello";
-/// is_hello(s);
-///
-/// let s = "hello".to_string();
-/// is_hello(s);
-/// ```
-#[stable(feature = "rust1", since = "1.0.0")]
-pub trait AsRef<T: ?Sized> {
- /// Performs the conversion.
- #[stable(feature = "rust1", since = "1.0.0")]
- fn as_ref(&self) -> &T;
-}
-
-/// Used to do a cheap mutable-to-mutable reference conversion.
-///
-/// This trait is similar to [`AsRef`] but used for converting between mutable
-/// references. If you need to do a costly conversion it is better to
-/// implement [`From`] with type `&mut T` or write a custom function.
-///
-/// **Note: This trait must not fail**. If the conversion can fail, use a
-/// dedicated method which returns an [`Option<T>`] or a [`Result<T, E>`].
-///
-/// [`Option<T>`]: ../../std/option/enum.Option.html
-/// [`Result<T, E>`]: ../../std/result/enum.Result.html
-///
-/// # Generic Implementations
-///
-/// - `AsMut` auto-dereferences if the inner type is a mutable reference
-/// (e.g.: `foo.as_mut()` will work the same if `foo` has type `&mut Foo`
-/// or `&mut &mut Foo`)
-///
-/// # Examples
-///
-/// Using `AsMut` as trait bound for a generic function we can accept all mutable references
-/// that can be converted to type `&mut T`. Because [`Box<T>`] implements `AsMut<T>` we can
-/// write a function `add_one` that takes all arguments that can be converted to `&mut u64`.
-/// Because [`Box<T>`] implements `AsMut<T>`, `add_one` accepts arguments of type
-/// `&mut Box<u64>` as well:
-///
-/// ```
-/// fn add_one<T: AsMut<u64>>(num: &mut T) {
-/// *num.as_mut() += 1;
-/// }
-///
-/// let mut boxed_num = Box::new(0);
-/// add_one(&mut boxed_num);
-/// assert_eq!(*boxed_num, 1);
-/// ```
-///
-/// [`Box<T>`]: ../../std/boxed/struct.Box.html
-#[stable(feature = "rust1", since = "1.0.0")]
-pub trait AsMut<T: ?Sized> {
- /// Performs the conversion.
- #[stable(feature = "rust1", since = "1.0.0")]
- fn as_mut(&mut self) -> &mut T;
-}
-
-/// A value-to-value conversion that consumes the input value. The
-/// opposite of [`From`].
-///
-/// One should avoid implementing [`Into`] and implement [`From`] instead.
-/// Implementing [`From`] automatically provides one with an implementation of [`Into`]
-/// thanks to the blanket implementation in the standard library.
-///
-/// Prefer using [`Into`] over [`From`] when specifying trait bounds on a generic function
-/// to ensure that types that only implement [`Into`] can be used as well.
-///
-/// **Note: This trait must not fail**. If the conversion can fail, use [`TryInto`].
-///
-/// # Generic Implementations
-///
-/// - [`From`]`<T> for U` implies `Into<U> for T`
-/// - [`Into`] is reflexive, which means that `Into<T> for T` is implemented
-///
-/// # Implementing [`Into`] for conversions to external types in old versions of Rust
-///
-/// Prior to Rust 1.40, if the destination type was not part of the current crate
-/// then you couldn't implement [`From`] directly.
-/// For example, take this code:
-///
-/// ```
-/// struct Wrapper<T>(Vec<T>);
-/// impl<T> From<Wrapper<T>> for Vec<T> {
-/// fn from(w: Wrapper<T>) -> Vec<T> {
-/// w.0
-/// }
-/// }
-/// ```
-/// This will fail to compile in older versions of the language because Rust's orphaning rules
-/// used to be a little bit more strict. To bypass this, you could implement [`Into`] directly:
-///
-/// ```
-/// struct Wrapper<T>(Vec<T>);
-/// impl<T> Into<Vec<T>> for Wrapper<T> {
-/// fn into(self) -> Vec<T> {
-/// self.0
-/// }
-/// }
-/// ```
-///
-/// It is important to understand that [`Into`] does not provide a [`From`] implementation
-/// (as [`From`] does with [`Into`]). Therefore, you should always try to implement [`From`]
-/// and then fall back to [`Into`] if [`From`] can't be implemented.
-///
-/// # Examples
-///
-/// [`String`] implements [`Into`]`<`[`Vec`]`<`[`u8`]`>>`:
-///
-/// In order to express that we want a generic function to take all arguments that can be
-/// converted to a specified type `T`, we can use a trait bound of [`Into`]`<T>`.
-/// For example: The function `is_hello` takes all arguments that can be converted into a
-/// [`Vec`]`<`[`u8`]`>`.
-///
-/// ```
-/// fn is_hello<T: Into<Vec<u8>>>(s: T) {
-/// let bytes = b"hello".to_vec();
-/// assert_eq!(bytes, s.into());
-/// }
-///
-/// let s = "hello".to_string();
-/// is_hello(s);
-/// ```
-///
-/// [`TryInto`]: trait.TryInto.html
-/// [`Option<T>`]: ../../std/option/enum.Option.html
-/// [`Result<T, E>`]: ../../std/result/enum.Result.html
-/// [`String`]: ../../std/string/struct.String.html
-/// [`From`]: trait.From.html
-/// [`Into`]: trait.Into.html
-/// [`Vec`]: ../../std/vec/struct.Vec.html
-#[stable(feature = "rust1", since = "1.0.0")]
-pub trait Into<T>: Sized {
- /// Performs the conversion.
- #[stable(feature = "rust1", since = "1.0.0")]
- fn into(self) -> T;
-}
-
-/// Used to do value-to-value conversions while consuming the input value. It is the reciprocal of
-/// [`Into`].
-///
-/// One should always prefer implementing `From` over [`Into`]
-/// because implementing `From` automatically provides one with a implementation of [`Into`]
-/// thanks to the blanket implementation in the standard library.
-///
-/// Only implement [`Into`] if a conversion to a type outside the current crate is required.
-/// `From` cannot do these type of conversions because of Rust's orphaning rules.
-/// See [`Into`] for more details.
-///
-/// Prefer using [`Into`] over using `From` when specifying trait bounds on a generic function.
-/// This way, types that directly implement [`Into`] can be used as arguments as well.
-///
-/// The `From` is also very useful when performing error handling. When constructing a function
-/// that is capable of failing, the return type will generally be of the form `Result<T, E>`.
-/// The `From` trait simplifies error handling by allowing a function to return a single error type
-/// that encapsulate multiple error types. See the "Examples" section and [the book][book] for more
-/// details.
-///
-/// **Note: This trait must not fail**. If the conversion can fail, use [`TryFrom`].
-///
-/// # Generic Implementations
-///
-/// - `From<T> for U` implies [`Into`]`<U> for T`
-/// - `From` is reflexive, which means that `From<T> for T` is implemented
-///
-/// # Examples
-///
-/// [`String`] implements `From<&str>`:
-///
-/// An explicit conversion from a `&str` to a String is done as follows:
-///
-/// ```
-/// let string = "hello".to_string();
-/// let other_string = String::from("hello");
-///
-/// assert_eq!(string, other_string);
-/// ```
-///
-/// While performing error handling it is often useful to implement `From` for your own error type.
-/// By converting underlying error types to our own custom error type that encapsulates the
-/// underlying error type, we can return a single error type without losing information on the
-/// underlying cause. The '?' operator automatically converts the underlying error type to our
-/// custom error type by calling `Into<CliError>::into` which is automatically provided when
-/// implementing `From`. The compiler then infers which implementation of `Into` should be used.
-///
-/// ```
-/// use std::fs;
-/// use std::io;
-/// use std::num;
-///
-/// enum CliError {
-/// IoError(io::Error),
-/// ParseError(num::ParseIntError),
-/// }
-///
-/// impl From<io::Error> for CliError {
-/// fn from(error: io::Error) -> Self {
-/// CliError::IoError(error)
-/// }
-/// }
-///
-/// impl From<num::ParseIntError> for CliError {
-/// fn from(error: num::ParseIntError) -> Self {
-/// CliError::ParseError(error)
-/// }
-/// }
-///
-/// fn open_and_parse_file(file_name: &str) -> Result<i32, CliError> {
-/// let mut contents = fs::read_to_string(&file_name)?;
-/// let num: i32 = contents.trim().parse()?;
-/// Ok(num)
-/// }
-/// ```
-///
-/// [`TryFrom`]: trait.TryFrom.html
-/// [`Option<T>`]: ../../std/option/enum.Option.html
-/// [`Result<T, E>`]: ../../std/result/enum.Result.html
-/// [`String`]: ../../std/string/struct.String.html
-/// [`Into`]: trait.Into.html
-/// [`from`]: trait.From.html#tymethod.from
-/// [book]: ../../book/ch09-00-error-handling.html
-#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented(on(
- all(_Self = "&str", T = "std::string::String"),
- note = "to coerce a `{T}` into a `{Self}`, use `&*` as a prefix",
-))]
-pub trait From<T>: Sized {
- /// Performs the conversion.
- #[stable(feature = "rust1", since = "1.0.0")]
- fn from(_: T) -> Self;
-}
-
-/// An attempted conversion that consumes `self`, which may or may not be
-/// expensive.
-///
-/// Library authors should usually not directly implement this trait,
-/// but should prefer implementing the [`TryFrom`] trait, which offers
-/// greater flexibility and provides an equivalent `TryInto`
-/// implementation for free, thanks to a blanket implementation in the
-/// standard library. For more information on this, see the
-/// documentation for [`Into`].
-///
-/// # Implementing `TryInto`
-///
-/// This suffers the same restrictions and reasoning as implementing
-/// [`Into`], see there for details.
-///
-/// [`TryFrom`]: trait.TryFrom.html
-/// [`Into`]: trait.Into.html
-#[stable(feature = "try_from", since = "1.34.0")]
-pub trait TryInto<T>: Sized {
- /// The type returned in the event of a conversion error.
- #[stable(feature = "try_from", since = "1.34.0")]
- type Error;
-
- /// Performs the conversion.
- #[stable(feature = "try_from", since = "1.34.0")]
- fn try_into(self) -> Result<T, Self::Error>;
-}
-
-/// Simple and safe type conversions that may fail in a controlled
-/// way under some circumstances. It is the reciprocal of [`TryInto`].
-///
-/// This is useful when you are doing a type conversion that may
-/// trivially succeed but may also need special handling.
-/// For example, there is no way to convert an [`i64`] into an [`i32`]
-/// using the [`From`] trait, because an [`i64`] may contain a value
-/// that an [`i32`] cannot represent and so the conversion would lose data.
-/// This might be handled by truncating the [`i64`] to an [`i32`] (essentially
-/// giving the [`i64`]'s value modulo [`i32::MAX`]) or by simply returning
-/// [`i32::MAX`], or by some other method. The [`From`] trait is intended
-/// for perfect conversions, so the `TryFrom` trait informs the
-/// programmer when a type conversion could go bad and lets them
-/// decide how to handle it.
-///
-/// # Generic Implementations
-///
-/// - `TryFrom<T> for U` implies [`TryInto`]`<U> for T`
-/// - [`try_from`] is reflexive, which means that `TryFrom<T> for T`
-/// is implemented and cannot fail -- the associated `Error` type for
-/// calling `T::try_from()` on a value of type `T` is [`!`].
-///
-/// `TryFrom<T>` can be implemented as follows:
-///
-/// ```
-/// use std::convert::TryFrom;
-///
-/// struct GreaterThanZero(i32);
-///
-/// impl TryFrom<i32> for GreaterThanZero {
-/// type Error = &'static str;
-///
-/// fn try_from(value: i32) -> Result<Self, Self::Error> {
-/// if value <= 0 {
-/// Err("GreaterThanZero only accepts value superior than zero!")
-/// } else {
-/// Ok(GreaterThanZero(value))
-/// }
-/// }
-/// }
-/// ```
-///
-/// # Examples
-///
-/// As described, [`i32`] implements `TryFrom<`[`i64`]`>`:
-///
-/// ```
-/// use std::convert::TryFrom;
-///
-/// let big_number = 1_000_000_000_000i64;
-/// // Silently truncates `big_number`, requires detecting
-/// // and handling the truncation after the fact.
-/// let smaller_number = big_number as i32;
-/// assert_eq!(smaller_number, -727379968);
-///
-/// // Returns an error because `big_number` is too big to
-/// // fit in an `i32`.
-/// let try_smaller_number = i32::try_from(big_number);
-/// assert!(try_smaller_number.is_err());
-///
-/// // Returns `Ok(3)`.
-/// let try_successful_smaller_number = i32::try_from(3);
-/// assert!(try_successful_smaller_number.is_ok());
-/// ```
-///
-/// [`try_from`]: trait.TryFrom.html#tymethod.try_from
-/// [`TryInto`]: trait.TryInto.html
-/// [`i32::MAX`]: ../../std/i32/constant.MAX.html
-/// [`!`]: ../../std/primitive.never.html
-#[stable(feature = "try_from", since = "1.34.0")]
-pub trait TryFrom<T>: Sized {
- /// The type returned in the event of a conversion error.
- #[stable(feature = "try_from", since = "1.34.0")]
- type Error;
-
- /// Performs the conversion.
- #[stable(feature = "try_from", since = "1.34.0")]
- fn try_from(value: T) -> Result<Self, Self::Error>;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// GENERIC IMPLS
-////////////////////////////////////////////////////////////////////////////////
-
-// As lifts over &
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized, U: ?Sized> AsRef<U> for &T
-where
- T: AsRef<U>,
-{
- fn as_ref(&self) -> &U {
- <T as AsRef<U>>::as_ref(*self)
- }
-}
-
-// As lifts over &mut
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized, U: ?Sized> AsRef<U> for &mut T
-where
- T: AsRef<U>,
-{
- fn as_ref(&self) -> &U {
- <T as AsRef<U>>::as_ref(*self)
- }
-}
-
-// FIXME (#45742): replace the above impls for &/&mut with the following more general one:
-// // As lifts over Deref
-// impl<D: ?Sized + Deref<Target: AsRef<U>>, U: ?Sized> AsRef<U> for D {
-// fn as_ref(&self) -> &U {
-// self.deref().as_ref()
-// }
-// }
-
-// AsMut lifts over &mut
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized, U: ?Sized> AsMut<U> for &mut T
-where
- T: AsMut<U>,
-{
- fn as_mut(&mut self) -> &mut U {
- (*self).as_mut()
- }
-}
-
-// FIXME (#45742): replace the above impl for &mut with the following more general one:
-// // AsMut lifts over DerefMut
-// impl<D: ?Sized + Deref<Target: AsMut<U>>, U: ?Sized> AsMut<U> for D {
-// fn as_mut(&mut self) -> &mut U {
-// self.deref_mut().as_mut()
-// }
-// }
-
-// From implies Into
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T, U> Into<U> for T
-where
- U: From<T>,
-{
- fn into(self) -> U {
- U::from(self)
- }
-}
-
-// From (and thus Into) is reflexive
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T> From<T> for T {
- fn from(t: T) -> T {
- t
- }
-}
-
-/// **Stability note:** This impl does not yet exist, but we are
-/// "reserving space" to add it in the future. See
-/// [rust-lang/rust#64715][#64715] for details.
-///
-/// [#64715]: https://github.com/rust-lang/rust/issues/64715
-#[stable(feature = "convert_infallible", since = "1.34.0")]
-#[rustc_reservation_impl = "permitting this impl would forbid us from adding \
- `impl<T> From<!> for T` later; see rust-lang/rust#64715 for details"]
-impl<T> From<!> for T {
- fn from(t: !) -> T {
- t
- }
-}
-
-// TryFrom implies TryInto
-#[stable(feature = "try_from", since = "1.34.0")]
-impl<T, U> TryInto<U> for T
-where
- U: TryFrom<T>,
-{
- type Error = U::Error;
-
- fn try_into(self) -> Result<U, U::Error> {
- U::try_from(self)
- }
-}
-
-// Infallible conversions are semantically equivalent to fallible conversions
-// with an uninhabited error type.
-#[stable(feature = "try_from", since = "1.34.0")]
-impl<T, U> TryFrom<U> for T
-where
- U: Into<T>,
-{
- type Error = Infallible;
-
- fn try_from(value: U) -> Result<Self, Self::Error> {
- Ok(U::into(value))
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// CONCRETE IMPLS
-////////////////////////////////////////////////////////////////////////////////
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T> AsRef<[T]> for [T] {
- fn as_ref(&self) -> &[T] {
- self
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T> AsMut<[T]> for [T] {
- fn as_mut(&mut self) -> &mut [T] {
- self
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl AsRef<str> for str {
- #[inline]
- fn as_ref(&self) -> &str {
- self
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// THE NO-ERROR ERROR TYPE
-////////////////////////////////////////////////////////////////////////////////
-
-/// A type alias for [the `!` “never” type][never].
-///
-/// `Infallible` represents types of errors that can never happen since `!` has no valid values.
-/// This can be useful for generic APIs that use [`Result`] and parameterize the error type,
-/// to indicate that the result is always [`Ok`].
-///
-/// For example, the [`TryFrom`] trait (conversion that returns a [`Result`])
-/// has a blanket implementation for all types where a reverse [`Into`] implementation exists.
-///
-/// ```ignore (illustrates std code, duplicating the impl in a doctest would be an error)
-/// impl<T, U> TryFrom<U> for T where U: Into<T> {
-/// type Error = Infallible;
-///
-/// fn try_from(value: U) -> Result<Self, Infallible> {
-/// Ok(U::into(value)) // Never returns `Err`
-/// }
-/// }
-/// ```
-///
-/// # Eventual deprecation
-///
-/// Previously, `Infallible` was defined as `enum Infallible {}`.
-/// Now that it is merely a type alias to `!`, we will eventually deprecate `Infallible`.
-///
-/// [`Ok`]: ../result/enum.Result.html#variant.Ok
-/// [`Result`]: ../result/enum.Result.html
-/// [`TryFrom`]: trait.TryFrom.html
-/// [`Into`]: trait.Into.html
-/// [never]: ../../std/primitive.never.html
-#[stable(feature = "convert_infallible", since = "1.34.0")]
-pub type Infallible = !;
--- /dev/null
+//! Traits for conversions between types.
+//!
+//! The traits in this module provide a way to convert from one type to another type.
+//! Each trait serves a different purpose:
+//!
+//! - Implement the [`AsRef`] trait for cheap reference-to-reference conversions
+//! - Implement the [`AsMut`] trait for cheap mutable-to-mutable conversions
+//! - Implement the [`From`] trait for consuming value-to-value conversions
+//! - Implement the [`Into`] trait for consuming value-to-value conversions to types
+//! outside the current crate
+//! - The [`TryFrom`] and [`TryInto`] traits behave like [`From`] and [`Into`],
+//! but should be implemented when the conversion can fail.
+//!
+//! The traits in this module are often used as trait bounds for generic functions such that to
+//! arguments of multiple types are supported. See the documentation of each trait for examples.
+//!
+//! As a library author, you should always prefer implementing [`From<T>`][`From`] or
+//! [`TryFrom<T>`][`TryFrom`] rather than [`Into<U>`][`Into`] or [`TryInto<U>`][`TryInto`],
+//! as [`From`] and [`TryFrom`] provide greater flexibility and offer
+//! equivalent [`Into`] or [`TryInto`] implementations for free, thanks to a
+//! blanket implementation in the standard library. Only implement [`Into`] or [`TryInto`]
+//! when a conversion to a type outside the current crate is required.
+//!
+//! # Generic Implementations
+//!
+//! - [`AsRef`] and [`AsMut`] auto-dereference if the inner type is a reference
+//! - [`From`]`<U> for T` implies [`Into`]`<T> for U`
+//! - [`TryFrom`]`<U> for T` implies [`TryInto`]`<T> for U`
+//! - [`From`] and [`Into`] are reflexive, which means that all types can
+//! `into` themselves and `from` themselves
+//!
+//! See each trait for usage examples.
+//!
+//! [`Into`]: trait.Into.html
+//! [`From`]: trait.From.html
+//! [`TryFrom`]: trait.TryFrom.html
+//! [`TryInto`]: trait.TryInto.html
+//! [`AsRef`]: trait.AsRef.html
+//! [`AsMut`]: trait.AsMut.html
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+mod num;
+
+#[unstable(feature = "convert_float_to_int", issue = "67057")]
+pub use num::FloatToInt;
+
+/// The identity function.
+///
+/// Two things are important to note about this function:
+///
+/// - It is not always equivalent to a closure like `|x| x`, since the
+/// closure may coerce `x` into a different type.
+///
+/// - It moves the input `x` passed to the function.
+///
+/// While it might seem strange to have a function that just returns back the
+/// input, there are some interesting uses.
+///
+/// # Examples
+///
+/// Using `identity` to do nothing in a sequence of other, interesting,
+/// functions:
+///
+/// ```rust
+/// use std::convert::identity;
+///
+/// fn manipulation(x: u32) -> u32 {
+/// // Let's pretend that adding one is an interesting function.
+/// x + 1
+/// }
+///
+/// let _arr = &[identity, manipulation];
+/// ```
+///
+/// Using `identity` as a "do nothing" base case in a conditional:
+///
+/// ```rust
+/// use std::convert::identity;
+///
+/// # let condition = true;
+/// #
+/// # fn manipulation(x: u32) -> u32 { x + 1 }
+/// #
+/// let do_stuff = if condition { manipulation } else { identity };
+///
+/// // Do more interesting stuff...
+///
+/// let _results = do_stuff(42);
+/// ```
+///
+/// Using `identity` to keep the `Some` variants of an iterator of `Option<T>`:
+///
+/// ```rust
+/// use std::convert::identity;
+///
+/// let iter = vec![Some(1), None, Some(3)].into_iter();
+/// let filtered = iter.filter_map(identity).collect::<Vec<_>>();
+/// assert_eq!(vec![1, 3], filtered);
+/// ```
+#[stable(feature = "convert_id", since = "1.33.0")]
+#[inline]
+pub const fn identity<T>(x: T) -> T {
+ x
+}
+
+/// Used to do a cheap reference-to-reference conversion.
+///
+/// This trait is similar to [`AsMut`] which is used for converting between mutable references.
+/// If you need to do a costly conversion it is better to implement [`From`] with type
+/// `&T` or write a custom function.
+///
+/// `AsRef` has the same signature as [`Borrow`], but [`Borrow`] is different in few aspects:
+///
+/// - Unlike `AsRef`, [`Borrow`] has a blanket impl for any `T`, and can be used to accept either
+/// a reference or a value.
+/// - [`Borrow`] also requires that [`Hash`], [`Eq`] and [`Ord`] for borrowed value are
+/// equivalent to those of the owned value. For this reason, if you want to
+/// borrow only a single field of a struct you can implement `AsRef`, but not [`Borrow`].
+///
+/// **Note: This trait must not fail**. If the conversion can fail, use a
+/// dedicated method which returns an [`Option<T>`] or a [`Result<T, E>`].
+///
+/// # Generic Implementations
+///
+/// - `AsRef` auto-dereferences if the inner type is a reference or a mutable
+/// reference (e.g.: `foo.as_ref()` will work the same if `foo` has type
+/// `&mut Foo` or `&&mut Foo`)
+///
+/// # Examples
+///
+/// By using trait bounds we can accept arguments of different types as long as they can be
+/// converted to the specified type `T`.
+///
+/// For example: By creating a generic function that takes an `AsRef<str>` we express that we
+/// want to accept all references that can be converted to [`&str`] as an argument.
+/// Since both [`String`] and [`&str`] implement `AsRef<str>` we can accept both as input argument.
+///
+/// [`Option<T>`]: ../../std/option/enum.Option.html
+/// [`Result<T, E>`]: ../../std/result/enum.Result.html
+/// [`Borrow`]: ../../std/borrow/trait.Borrow.html
+/// [`Hash`]: ../../std/hash/trait.Hash.html
+/// [`Eq`]: ../../std/cmp/trait.Eq.html
+/// [`Ord`]: ../../std/cmp/trait.Ord.html
+/// [`&str`]: ../../std/primitive.str.html
+/// [`String`]: ../../std/string/struct.String.html
+///
+/// ```
+/// fn is_hello<T: AsRef<str>>(s: T) {
+/// assert_eq!("hello", s.as_ref());
+/// }
+///
+/// let s = "hello";
+/// is_hello(s);
+///
+/// let s = "hello".to_string();
+/// is_hello(s);
+/// ```
+#[stable(feature = "rust1", since = "1.0.0")]
+pub trait AsRef<T: ?Sized> {
+ /// Performs the conversion.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn as_ref(&self) -> &T;
+}
+
+/// Used to do a cheap mutable-to-mutable reference conversion.
+///
+/// This trait is similar to [`AsRef`] but used for converting between mutable
+/// references. If you need to do a costly conversion it is better to
+/// implement [`From`] with type `&mut T` or write a custom function.
+///
+/// **Note: This trait must not fail**. If the conversion can fail, use a
+/// dedicated method which returns an [`Option<T>`] or a [`Result<T, E>`].
+///
+/// [`Option<T>`]: ../../std/option/enum.Option.html
+/// [`Result<T, E>`]: ../../std/result/enum.Result.html
+///
+/// # Generic Implementations
+///
+/// - `AsMut` auto-dereferences if the inner type is a mutable reference
+/// (e.g.: `foo.as_mut()` will work the same if `foo` has type `&mut Foo`
+/// or `&mut &mut Foo`)
+///
+/// # Examples
+///
+/// Using `AsMut` as trait bound for a generic function we can accept all mutable references
+/// that can be converted to type `&mut T`. Because [`Box<T>`] implements `AsMut<T>` we can
+/// write a function `add_one` that takes all arguments that can be converted to `&mut u64`.
+/// Because [`Box<T>`] implements `AsMut<T>`, `add_one` accepts arguments of type
+/// `&mut Box<u64>` as well:
+///
+/// ```
+/// fn add_one<T: AsMut<u64>>(num: &mut T) {
+/// *num.as_mut() += 1;
+/// }
+///
+/// let mut boxed_num = Box::new(0);
+/// add_one(&mut boxed_num);
+/// assert_eq!(*boxed_num, 1);
+/// ```
+///
+/// [`Box<T>`]: ../../std/boxed/struct.Box.html
+#[stable(feature = "rust1", since = "1.0.0")]
+pub trait AsMut<T: ?Sized> {
+ /// Performs the conversion.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn as_mut(&mut self) -> &mut T;
+}
+
+/// A value-to-value conversion that consumes the input value. The
+/// opposite of [`From`].
+///
+/// One should avoid implementing [`Into`] and implement [`From`] instead.
+/// Implementing [`From`] automatically provides one with an implementation of [`Into`]
+/// thanks to the blanket implementation in the standard library.
+///
+/// Prefer using [`Into`] over [`From`] when specifying trait bounds on a generic function
+/// to ensure that types that only implement [`Into`] can be used as well.
+///
+/// **Note: This trait must not fail**. If the conversion can fail, use [`TryInto`].
+///
+/// # Generic Implementations
+///
+/// - [`From`]`<T> for U` implies `Into<U> for T`
+/// - [`Into`] is reflexive, which means that `Into<T> for T` is implemented
+///
+/// # Implementing [`Into`] for conversions to external types in old versions of Rust
+///
+/// Prior to Rust 1.40, if the destination type was not part of the current crate
+/// then you couldn't implement [`From`] directly.
+/// For example, take this code:
+///
+/// ```
+/// struct Wrapper<T>(Vec<T>);
+/// impl<T> From<Wrapper<T>> for Vec<T> {
+/// fn from(w: Wrapper<T>) -> Vec<T> {
+/// w.0
+/// }
+/// }
+/// ```
+/// This will fail to compile in older versions of the language because Rust's orphaning rules
+/// used to be a little bit more strict. To bypass this, you could implement [`Into`] directly:
+///
+/// ```
+/// struct Wrapper<T>(Vec<T>);
+/// impl<T> Into<Vec<T>> for Wrapper<T> {
+/// fn into(self) -> Vec<T> {
+/// self.0
+/// }
+/// }
+/// ```
+///
+/// It is important to understand that [`Into`] does not provide a [`From`] implementation
+/// (as [`From`] does with [`Into`]). Therefore, you should always try to implement [`From`]
+/// and then fall back to [`Into`] if [`From`] can't be implemented.
+///
+/// # Examples
+///
+/// [`String`] implements [`Into`]`<`[`Vec`]`<`[`u8`]`>>`:
+///
+/// In order to express that we want a generic function to take all arguments that can be
+/// converted to a specified type `T`, we can use a trait bound of [`Into`]`<T>`.
+/// For example: The function `is_hello` takes all arguments that can be converted into a
+/// [`Vec`]`<`[`u8`]`>`.
+///
+/// ```
+/// fn is_hello<T: Into<Vec<u8>>>(s: T) {
+/// let bytes = b"hello".to_vec();
+/// assert_eq!(bytes, s.into());
+/// }
+///
+/// let s = "hello".to_string();
+/// is_hello(s);
+/// ```
+///
+/// [`TryInto`]: trait.TryInto.html
+/// [`Option<T>`]: ../../std/option/enum.Option.html
+/// [`Result<T, E>`]: ../../std/result/enum.Result.html
+/// [`String`]: ../../std/string/struct.String.html
+/// [`From`]: trait.From.html
+/// [`Into`]: trait.Into.html
+/// [`Vec`]: ../../std/vec/struct.Vec.html
+#[stable(feature = "rust1", since = "1.0.0")]
+pub trait Into<T>: Sized {
+ /// Performs the conversion.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn into(self) -> T;
+}
+
+/// Used to do value-to-value conversions while consuming the input value. It is the reciprocal of
+/// [`Into`].
+///
+/// One should always prefer implementing `From` over [`Into`]
+/// because implementing `From` automatically provides one with a implementation of [`Into`]
+/// thanks to the blanket implementation in the standard library.
+///
+/// Only implement [`Into`] if a conversion to a type outside the current crate is required.
+/// `From` cannot do these type of conversions because of Rust's orphaning rules.
+/// See [`Into`] for more details.
+///
+/// Prefer using [`Into`] over using `From` when specifying trait bounds on a generic function.
+/// This way, types that directly implement [`Into`] can be used as arguments as well.
+///
+/// The `From` is also very useful when performing error handling. When constructing a function
+/// that is capable of failing, the return type will generally be of the form `Result<T, E>`.
+/// The `From` trait simplifies error handling by allowing a function to return a single error type
+/// that encapsulate multiple error types. See the "Examples" section and [the book][book] for more
+/// details.
+///
+/// **Note: This trait must not fail**. If the conversion can fail, use [`TryFrom`].
+///
+/// # Generic Implementations
+///
+/// - `From<T> for U` implies [`Into`]`<U> for T`
+/// - `From` is reflexive, which means that `From<T> for T` is implemented
+///
+/// # Examples
+///
+/// [`String`] implements `From<&str>`:
+///
+/// An explicit conversion from a `&str` to a String is done as follows:
+///
+/// ```
+/// let string = "hello".to_string();
+/// let other_string = String::from("hello");
+///
+/// assert_eq!(string, other_string);
+/// ```
+///
+/// While performing error handling it is often useful to implement `From` for your own error type.
+/// By converting underlying error types to our own custom error type that encapsulates the
+/// underlying error type, we can return a single error type without losing information on the
+/// underlying cause. The '?' operator automatically converts the underlying error type to our
+/// custom error type by calling `Into<CliError>::into` which is automatically provided when
+/// implementing `From`. The compiler then infers which implementation of `Into` should be used.
+///
+/// ```
+/// use std::fs;
+/// use std::io;
+/// use std::num;
+///
+/// enum CliError {
+/// IoError(io::Error),
+/// ParseError(num::ParseIntError),
+/// }
+///
+/// impl From<io::Error> for CliError {
+/// fn from(error: io::Error) -> Self {
+/// CliError::IoError(error)
+/// }
+/// }
+///
+/// impl From<num::ParseIntError> for CliError {
+/// fn from(error: num::ParseIntError) -> Self {
+/// CliError::ParseError(error)
+/// }
+/// }
+///
+/// fn open_and_parse_file(file_name: &str) -> Result<i32, CliError> {
+/// let mut contents = fs::read_to_string(&file_name)?;
+/// let num: i32 = contents.trim().parse()?;
+/// Ok(num)
+/// }
+/// ```
+///
+/// [`TryFrom`]: trait.TryFrom.html
+/// [`Option<T>`]: ../../std/option/enum.Option.html
+/// [`Result<T, E>`]: ../../std/result/enum.Result.html
+/// [`String`]: ../../std/string/struct.String.html
+/// [`Into`]: trait.Into.html
+/// [`from`]: trait.From.html#tymethod.from
+/// [book]: ../../book/ch09-00-error-handling.html
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_on_unimplemented(on(
+ all(_Self = "&str", T = "std::string::String"),
+ note = "to coerce a `{T}` into a `{Self}`, use `&*` as a prefix",
+))]
+pub trait From<T>: Sized {
+ /// Performs the conversion.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn from(_: T) -> Self;
+}
+
+/// An attempted conversion that consumes `self`, which may or may not be
+/// expensive.
+///
+/// Library authors should usually not directly implement this trait,
+/// but should prefer implementing the [`TryFrom`] trait, which offers
+/// greater flexibility and provides an equivalent `TryInto`
+/// implementation for free, thanks to a blanket implementation in the
+/// standard library. For more information on this, see the
+/// documentation for [`Into`].
+///
+/// # Implementing `TryInto`
+///
+/// This suffers the same restrictions and reasoning as implementing
+/// [`Into`], see there for details.
+///
+/// [`TryFrom`]: trait.TryFrom.html
+/// [`Into`]: trait.Into.html
+#[stable(feature = "try_from", since = "1.34.0")]
+pub trait TryInto<T>: Sized {
+ /// The type returned in the event of a conversion error.
+ #[stable(feature = "try_from", since = "1.34.0")]
+ type Error;
+
+ /// Performs the conversion.
+ #[stable(feature = "try_from", since = "1.34.0")]
+ fn try_into(self) -> Result<T, Self::Error>;
+}
+
+/// Simple and safe type conversions that may fail in a controlled
+/// way under some circumstances. It is the reciprocal of [`TryInto`].
+///
+/// This is useful when you are doing a type conversion that may
+/// trivially succeed but may also need special handling.
+/// For example, there is no way to convert an [`i64`] into an [`i32`]
+/// using the [`From`] trait, because an [`i64`] may contain a value
+/// that an [`i32`] cannot represent and so the conversion would lose data.
+/// This might be handled by truncating the [`i64`] to an [`i32`] (essentially
+/// giving the [`i64`]'s value modulo [`i32::MAX`]) or by simply returning
+/// [`i32::MAX`], or by some other method. The [`From`] trait is intended
+/// for perfect conversions, so the `TryFrom` trait informs the
+/// programmer when a type conversion could go bad and lets them
+/// decide how to handle it.
+///
+/// # Generic Implementations
+///
+/// - `TryFrom<T> for U` implies [`TryInto`]`<U> for T`
+/// - [`try_from`] is reflexive, which means that `TryFrom<T> for T`
+/// is implemented and cannot fail -- the associated `Error` type for
+/// calling `T::try_from()` on a value of type `T` is [`!`].
+///
+/// `TryFrom<T>` can be implemented as follows:
+///
+/// ```
+/// use std::convert::TryFrom;
+///
+/// struct GreaterThanZero(i32);
+///
+/// impl TryFrom<i32> for GreaterThanZero {
+/// type Error = &'static str;
+///
+/// fn try_from(value: i32) -> Result<Self, Self::Error> {
+/// if value <= 0 {
+/// Err("GreaterThanZero only accepts value superior than zero!")
+/// } else {
+/// Ok(GreaterThanZero(value))
+/// }
+/// }
+/// }
+/// ```
+///
+/// # Examples
+///
+/// As described, [`i32`] implements `TryFrom<`[`i64`]`>`:
+///
+/// ```
+/// use std::convert::TryFrom;
+///
+/// let big_number = 1_000_000_000_000i64;
+/// // Silently truncates `big_number`, requires detecting
+/// // and handling the truncation after the fact.
+/// let smaller_number = big_number as i32;
+/// assert_eq!(smaller_number, -727379968);
+///
+/// // Returns an error because `big_number` is too big to
+/// // fit in an `i32`.
+/// let try_smaller_number = i32::try_from(big_number);
+/// assert!(try_smaller_number.is_err());
+///
+/// // Returns `Ok(3)`.
+/// let try_successful_smaller_number = i32::try_from(3);
+/// assert!(try_successful_smaller_number.is_ok());
+/// ```
+///
+/// [`try_from`]: trait.TryFrom.html#tymethod.try_from
+/// [`TryInto`]: trait.TryInto.html
+/// [`i32::MAX`]: ../../std/i32/constant.MAX.html
+/// [`!`]: ../../std/primitive.never.html
+#[stable(feature = "try_from", since = "1.34.0")]
+pub trait TryFrom<T>: Sized {
+ /// The type returned in the event of a conversion error.
+ #[stable(feature = "try_from", since = "1.34.0")]
+ type Error;
+
+ /// Performs the conversion.
+ #[stable(feature = "try_from", since = "1.34.0")]
+ fn try_from(value: T) -> Result<Self, Self::Error>;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// GENERIC IMPLS
+////////////////////////////////////////////////////////////////////////////////
+
+// As lifts over &
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: ?Sized, U: ?Sized> AsRef<U> for &T
+where
+ T: AsRef<U>,
+{
+ fn as_ref(&self) -> &U {
+ <T as AsRef<U>>::as_ref(*self)
+ }
+}
+
+// As lifts over &mut
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: ?Sized, U: ?Sized> AsRef<U> for &mut T
+where
+ T: AsRef<U>,
+{
+ fn as_ref(&self) -> &U {
+ <T as AsRef<U>>::as_ref(*self)
+ }
+}
+
+// FIXME (#45742): replace the above impls for &/&mut with the following more general one:
+// // As lifts over Deref
+// impl<D: ?Sized + Deref<Target: AsRef<U>>, U: ?Sized> AsRef<U> for D {
+// fn as_ref(&self) -> &U {
+// self.deref().as_ref()
+// }
+// }
+
+// AsMut lifts over &mut
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: ?Sized, U: ?Sized> AsMut<U> for &mut T
+where
+ T: AsMut<U>,
+{
+ fn as_mut(&mut self) -> &mut U {
+ (*self).as_mut()
+ }
+}
+
+// FIXME (#45742): replace the above impl for &mut with the following more general one:
+// // AsMut lifts over DerefMut
+// impl<D: ?Sized + Deref<Target: AsMut<U>>, U: ?Sized> AsMut<U> for D {
+// fn as_mut(&mut self) -> &mut U {
+// self.deref_mut().as_mut()
+// }
+// }
+
+// From implies Into
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T, U> Into<U> for T
+where
+ U: From<T>,
+{
+ fn into(self) -> U {
+ U::from(self)
+ }
+}
+
+// From (and thus Into) is reflexive
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T> From<T> for T {
+ fn from(t: T) -> T {
+ t
+ }
+}
+
+/// **Stability note:** This impl does not yet exist, but we are
+/// "reserving space" to add it in the future. See
+/// [rust-lang/rust#64715][#64715] for details.
+///
+/// [#64715]: https://github.com/rust-lang/rust/issues/64715
+#[stable(feature = "convert_infallible", since = "1.34.0")]
+#[rustc_reservation_impl = "permitting this impl would forbid us from adding \
+ `impl<T> From<!> for T` later; see rust-lang/rust#64715 for details"]
+impl<T> From<!> for T {
+ fn from(t: !) -> T {
+ t
+ }
+}
+
+// TryFrom implies TryInto
+#[stable(feature = "try_from", since = "1.34.0")]
+impl<T, U> TryInto<U> for T
+where
+ U: TryFrom<T>,
+{
+ type Error = U::Error;
+
+ fn try_into(self) -> Result<U, U::Error> {
+ U::try_from(self)
+ }
+}
+
+// Infallible conversions are semantically equivalent to fallible conversions
+// with an uninhabited error type.
+#[stable(feature = "try_from", since = "1.34.0")]
+impl<T, U> TryFrom<U> for T
+where
+ U: Into<T>,
+{
+ type Error = Infallible;
+
+ fn try_from(value: U) -> Result<Self, Self::Error> {
+ Ok(U::into(value))
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// CONCRETE IMPLS
+////////////////////////////////////////////////////////////////////////////////
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T> AsRef<[T]> for [T] {
+ fn as_ref(&self) -> &[T] {
+ self
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T> AsMut<[T]> for [T] {
+ fn as_mut(&mut self) -> &mut [T] {
+ self
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRef<str> for str {
+ #[inline]
+ fn as_ref(&self) -> &str {
+ self
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// THE NO-ERROR ERROR TYPE
+////////////////////////////////////////////////////////////////////////////////
+
+/// A type alias for [the `!` “never” type][never].
+///
+/// `Infallible` represents types of errors that can never happen since `!` has no valid values.
+/// This can be useful for generic APIs that use [`Result`] and parameterize the error type,
+/// to indicate that the result is always [`Ok`].
+///
+/// For example, the [`TryFrom`] trait (conversion that returns a [`Result`])
+/// has a blanket implementation for all types where a reverse [`Into`] implementation exists.
+///
+/// ```ignore (illustrates std code, duplicating the impl in a doctest would be an error)
+/// impl<T, U> TryFrom<U> for T where U: Into<T> {
+/// type Error = Infallible;
+///
+/// fn try_from(value: U) -> Result<Self, Infallible> {
+/// Ok(U::into(value)) // Never returns `Err`
+/// }
+/// }
+/// ```
+///
+/// # Eventual deprecation
+///
+/// Previously, `Infallible` was defined as `enum Infallible {}`.
+/// Now that it is merely a type alias to `!`, we will eventually deprecate `Infallible`.
+///
+/// [`Ok`]: ../result/enum.Result.html#variant.Ok
+/// [`Result`]: ../result/enum.Result.html
+/// [`TryFrom`]: trait.TryFrom.html
+/// [`Into`]: trait.Into.html
+/// [never]: ../../std/primitive.never.html
+#[stable(feature = "convert_infallible", since = "1.34.0")]
+pub type Infallible = !;
--- /dev/null
+use super::{From, TryFrom};
+use crate::num::TryFromIntError;
+
+mod private {
+ /// This trait being unreachable from outside the crate
+ /// prevents other implementations of the `FloatToInt` trait,
+ /// which allows potentially adding more trait methods after the trait is `#[stable]`.
+ #[unstable(feature = "convert_float_to_int", issue = "67057")]
+ pub trait Sealed {}
+}
+
+/// Supporting trait for inherent methods of `f32` and `f64` such as `round_unchecked_to`.
+/// Typically doesn’t need to be used directly.
+#[unstable(feature = "convert_float_to_int", issue = "67057")]
+pub trait FloatToInt<Int>: private::Sealed + Sized {
+ #[cfg(not(bootstrap))]
+ #[unstable(feature = "float_approx_unchecked_to", issue = "67058")]
+ #[doc(hidden)]
+ unsafe fn approx_unchecked(self) -> Int;
+}
+
+macro_rules! impl_float_to_int {
+ ( $Float: ident => $( $Int: ident )+ ) => {
+ #[unstable(feature = "convert_float_to_int", issue = "67057")]
+ impl private::Sealed for $Float {}
+ $(
+ #[unstable(feature = "convert_float_to_int", issue = "67057")]
+ impl FloatToInt<$Int> for $Float {
+ #[cfg(not(bootstrap))]
+ #[doc(hidden)]
+ #[inline]
+ unsafe fn approx_unchecked(self) -> $Int {
+ crate::intrinsics::float_to_int_approx_unchecked(self)
+ }
+ }
+ )+
+ }
+}
+
+impl_float_to_int!(f32 => u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize);
+impl_float_to_int!(f64 => u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize);
+
+// Conversion traits for primitive integer and float types
+// Conversions T -> T are covered by a blanket impl and therefore excluded
+// Some conversions from and to usize/isize are not implemented due to portability concerns
+macro_rules! impl_from {
+ ($Small: ty, $Large: ty, #[$attr:meta], $doc: expr) => {
+ #[$attr]
+ #[doc = $doc]
+ impl From<$Small> for $Large {
+ #[inline]
+ fn from(small: $Small) -> $Large {
+ small as $Large
+ }
+ }
+ };
+ ($Small: ty, $Large: ty, #[$attr:meta]) => {
+ impl_from!($Small,
+ $Large,
+ #[$attr],
+ concat!("Converts `",
+ stringify!($Small),
+ "` to `",
+ stringify!($Large),
+ "` losslessly."));
+ }
+}
+
+macro_rules! impl_from_bool {
+ ($target: ty, #[$attr:meta]) => {
+ impl_from!(bool, $target, #[$attr], concat!("Converts a `bool` to a `",
+ stringify!($target), "`. The resulting value is `0` for `false` and `1` for `true`
+values.
+
+# Examples
+
+```
+assert_eq!(", stringify!($target), "::from(true), 1);
+assert_eq!(", stringify!($target), "::from(false), 0);
+```"));
+ };
+}
+
+// Bool -> Any
+impl_from_bool! { u8, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { u16, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { u32, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { u64, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { u128, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { usize, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { i8, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { i16, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { i32, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { i64, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { i128, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { isize, #[stable(feature = "from_bool", since = "1.28.0")] }
+
+// Unsigned -> Unsigned
+impl_from! { u8, u16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u8, u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u8, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u8, u128, #[stable(feature = "i128", since = "1.26.0")] }
+impl_from! { u8, usize, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u16, u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u16, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u16, u128, #[stable(feature = "i128", since = "1.26.0")] }
+impl_from! { u32, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u32, u128, #[stable(feature = "i128", since = "1.26.0")] }
+impl_from! { u64, u128, #[stable(feature = "i128", since = "1.26.0")] }
+
+// Signed -> Signed
+impl_from! { i8, i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i8, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i8, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i8, i128, #[stable(feature = "i128", since = "1.26.0")] }
+impl_from! { i8, isize, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i16, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i16, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i16, i128, #[stable(feature = "i128", since = "1.26.0")] }
+impl_from! { i32, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i32, i128, #[stable(feature = "i128", since = "1.26.0")] }
+impl_from! { i64, i128, #[stable(feature = "i128", since = "1.26.0")] }
+
+// Unsigned -> Signed
+impl_from! { u8, i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u8, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u8, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u8, i128, #[stable(feature = "i128", since = "1.26.0")] }
+impl_from! { u16, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u16, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u16, i128, #[stable(feature = "i128", since = "1.26.0")] }
+impl_from! { u32, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u32, i128, #[stable(feature = "i128", since = "1.26.0")] }
+impl_from! { u64, i128, #[stable(feature = "i128", since = "1.26.0")] }
+
+// The C99 standard defines bounds on INTPTR_MIN, INTPTR_MAX, and UINTPTR_MAX
+// which imply that pointer-sized integers must be at least 16 bits:
+// https://port70.net/~nsz/c/c99/n1256.html#7.18.2.4
+impl_from! { u16, usize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] }
+impl_from! { u8, isize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] }
+impl_from! { i16, isize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] }
+
+// RISC-V defines the possibility of a 128-bit address space (RV128).
+
+// CHERI proposes 256-bit “capabilities”. Unclear if this would be relevant to usize/isize.
+// https://www.cl.cam.ac.uk/research/security/ctsrd/pdfs/20171017a-cheri-poster.pdf
+// http://www.csl.sri.com/users/neumann/2012resolve-cheri.pdf
+
+
+// Note: integers can only be represented with full precision in a float if
+// they fit in the significand, which is 24 bits in f32 and 53 bits in f64.
+// Lossy float conversions are not implemented at this time.
+
+// Signed -> Float
+impl_from! { i8, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { i8, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { i16, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { i16, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { i32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+
+// Unsigned -> Float
+impl_from! { u8, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { u8, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { u16, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { u16, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { u32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+
+// Float -> Float
+impl_from! { f32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+
+// no possible bounds violation
+macro_rules! try_from_unbounded {
+ ($source:ty, $($target:ty),*) => {$(
+ #[stable(feature = "try_from", since = "1.34.0")]
+ impl TryFrom<$source> for $target {
+ type Error = TryFromIntError;
+
+ /// Try to create the target number type from a source
+ /// number type. This returns an error if the source value
+ /// is outside of the range of the target type.
+ #[inline]
+ fn try_from(value: $source) -> Result<Self, Self::Error> {
+ Ok(value as $target)
+ }
+ }
+ )*}
+}
+
+// only negative bounds
+macro_rules! try_from_lower_bounded {
+ ($source:ty, $($target:ty),*) => {$(
+ #[stable(feature = "try_from", since = "1.34.0")]
+ impl TryFrom<$source> for $target {
+ type Error = TryFromIntError;
+
+ /// Try to create the target number type from a source
+ /// number type. This returns an error if the source value
+ /// is outside of the range of the target type.
+ #[inline]
+ fn try_from(u: $source) -> Result<$target, TryFromIntError> {
+ if u >= 0 {
+ Ok(u as $target)
+ } else {
+ Err(TryFromIntError(()))
+ }
+ }
+ }
+ )*}
+}
+
+// unsigned to signed (only positive bound)
+macro_rules! try_from_upper_bounded {
+ ($source:ty, $($target:ty),*) => {$(
+ #[stable(feature = "try_from", since = "1.34.0")]
+ impl TryFrom<$source> for $target {
+ type Error = TryFromIntError;
+
+ /// Try to create the target number type from a source
+ /// number type. This returns an error if the source value
+ /// is outside of the range of the target type.
+ #[inline]
+ fn try_from(u: $source) -> Result<$target, TryFromIntError> {
+ if u > (<$target>::max_value() as $source) {
+ Err(TryFromIntError(()))
+ } else {
+ Ok(u as $target)
+ }
+ }
+ }
+ )*}
+}
+
+// all other cases
+macro_rules! try_from_both_bounded {
+ ($source:ty, $($target:ty),*) => {$(
+ #[stable(feature = "try_from", since = "1.34.0")]
+ impl TryFrom<$source> for $target {
+ type Error = TryFromIntError;
+
+ /// Try to create the target number type from a source
+ /// number type. This returns an error if the source value
+ /// is outside of the range of the target type.
+ #[inline]
+ fn try_from(u: $source) -> Result<$target, TryFromIntError> {
+ let min = <$target>::min_value() as $source;
+ let max = <$target>::max_value() as $source;
+ if u < min || u > max {
+ Err(TryFromIntError(()))
+ } else {
+ Ok(u as $target)
+ }
+ }
+ }
+ )*}
+}
+
+macro_rules! rev {
+ ($mac:ident, $source:ty, $($target:ty),*) => {$(
+ $mac!($target, $source);
+ )*}
+}
+
+// intra-sign conversions
+try_from_upper_bounded!(u16, u8);
+try_from_upper_bounded!(u32, u16, u8);
+try_from_upper_bounded!(u64, u32, u16, u8);
+try_from_upper_bounded!(u128, u64, u32, u16, u8);
+
+try_from_both_bounded!(i16, i8);
+try_from_both_bounded!(i32, i16, i8);
+try_from_both_bounded!(i64, i32, i16, i8);
+try_from_both_bounded!(i128, i64, i32, i16, i8);
+
+// unsigned-to-signed
+try_from_upper_bounded!(u8, i8);
+try_from_upper_bounded!(u16, i8, i16);
+try_from_upper_bounded!(u32, i8, i16, i32);
+try_from_upper_bounded!(u64, i8, i16, i32, i64);
+try_from_upper_bounded!(u128, i8, i16, i32, i64, i128);
+
+// signed-to-unsigned
+try_from_lower_bounded!(i8, u8, u16, u32, u64, u128);
+try_from_lower_bounded!(i16, u16, u32, u64, u128);
+try_from_lower_bounded!(i32, u32, u64, u128);
+try_from_lower_bounded!(i64, u64, u128);
+try_from_lower_bounded!(i128, u128);
+try_from_both_bounded!(i16, u8);
+try_from_both_bounded!(i32, u16, u8);
+try_from_both_bounded!(i64, u32, u16, u8);
+try_from_both_bounded!(i128, u64, u32, u16, u8);
+
+// usize/isize
+try_from_upper_bounded!(usize, isize);
+try_from_lower_bounded!(isize, usize);
+
+#[cfg(target_pointer_width = "16")]
+mod ptr_try_from_impls {
+ use super::TryFromIntError;
+ use crate::convert::TryFrom;
+
+ try_from_upper_bounded!(usize, u8);
+ try_from_unbounded!(usize, u16, u32, u64, u128);
+ try_from_upper_bounded!(usize, i8, i16);
+ try_from_unbounded!(usize, i32, i64, i128);
+
+ try_from_both_bounded!(isize, u8);
+ try_from_lower_bounded!(isize, u16, u32, u64, u128);
+ try_from_both_bounded!(isize, i8);
+ try_from_unbounded!(isize, i16, i32, i64, i128);
+
+ rev!(try_from_upper_bounded, usize, u32, u64, u128);
+ rev!(try_from_lower_bounded, usize, i8, i16);
+ rev!(try_from_both_bounded, usize, i32, i64, i128);
+
+ rev!(try_from_upper_bounded, isize, u16, u32, u64, u128);
+ rev!(try_from_both_bounded, isize, i32, i64, i128);
+}
+
+#[cfg(target_pointer_width = "32")]
+mod ptr_try_from_impls {
+ use super::TryFromIntError;
+ use crate::convert::TryFrom;
+
+ try_from_upper_bounded!(usize, u8, u16);
+ try_from_unbounded!(usize, u32, u64, u128);
+ try_from_upper_bounded!(usize, i8, i16, i32);
+ try_from_unbounded!(usize, i64, i128);
+
+ try_from_both_bounded!(isize, u8, u16);
+ try_from_lower_bounded!(isize, u32, u64, u128);
+ try_from_both_bounded!(isize, i8, i16);
+ try_from_unbounded!(isize, i32, i64, i128);
+
+ rev!(try_from_unbounded, usize, u32);
+ rev!(try_from_upper_bounded, usize, u64, u128);
+ rev!(try_from_lower_bounded, usize, i8, i16, i32);
+ rev!(try_from_both_bounded, usize, i64, i128);
+
+ rev!(try_from_unbounded, isize, u16);
+ rev!(try_from_upper_bounded, isize, u32, u64, u128);
+ rev!(try_from_unbounded, isize, i32);
+ rev!(try_from_both_bounded, isize, i64, i128);
+}
+
+#[cfg(target_pointer_width = "64")]
+mod ptr_try_from_impls {
+ use super::TryFromIntError;
+ use crate::convert::TryFrom;
+
+ try_from_upper_bounded!(usize, u8, u16, u32);
+ try_from_unbounded!(usize, u64, u128);
+ try_from_upper_bounded!(usize, i8, i16, i32, i64);
+ try_from_unbounded!(usize, i128);
+
+ try_from_both_bounded!(isize, u8, u16, u32);
+ try_from_lower_bounded!(isize, u64, u128);
+ try_from_both_bounded!(isize, i8, i16, i32);
+ try_from_unbounded!(isize, i64, i128);
+
+ rev!(try_from_unbounded, usize, u32, u64);
+ rev!(try_from_upper_bounded, usize, u128);
+ rev!(try_from_lower_bounded, usize, i8, i16, i32, i64);
+ rev!(try_from_both_bounded, usize, i128);
+
+ rev!(try_from_unbounded, isize, u16, u32);
+ rev!(try_from_upper_bounded, isize, u64, u128);
+ rev!(try_from_unbounded, isize, i32, i64);
+ rev!(try_from_both_bounded, isize, i128);
+}
/// May assume inputs are finite.
pub fn frem_fast<T>(a: T, b: T) -> T;
+ /// Convert with LLVM’s fptoui/fptosi, which may return undef for values out of range
+ /// https://github.com/rust-lang/rust/issues/10184
+ #[cfg(not(bootstrap))]
+ pub fn float_to_int_approx_unchecked<Float, Int>(value: Float) -> Int;
+
/// Returns the number of bits set in an integer type `T`
pub fn ctpop<T>(x: T) -> T;
#![stable(feature = "rust1", since = "1.0.0")]
+#[cfg(not(bootstrap))]
+use crate::convert::FloatToInt;
#[cfg(not(test))]
use crate::intrinsics;
-
use crate::mem;
use crate::num::FpCategory;
intrinsics::minnumf32(self, other)
}
+ /// Rounds toward zero and converts to any primitive integer type,
+ /// assuming that the value is finite and fits in that type.
+ ///
+ /// ```
+ /// #![feature(float_approx_unchecked_to)]
+ ///
+ /// let value = 4.6_f32;
+ /// let rounded = unsafe { value.approx_unchecked_to::<u16>() };
+ /// assert_eq!(rounded, 4);
+ ///
+ /// let value = -128.9_f32;
+ /// let rounded = unsafe { value.approx_unchecked_to::<i8>() };
+ /// assert_eq!(rounded, std::i8::MIN);
+ /// ```
+ ///
+ /// # Safety
+ ///
+ /// The value must:
+ ///
+ /// * Not be `NaN`
+ /// * Not be infinite
+ /// * Be representable in the return type `Int`, after truncating off its fractional part
+ #[cfg(not(bootstrap))]
+ #[unstable(feature = "float_approx_unchecked_to", issue = "67058")]
+ #[inline]
+ pub unsafe fn approx_unchecked_to<Int>(self) -> Int where Self: FloatToInt<Int> {
+ FloatToInt::<Int>::approx_unchecked(self)
+ }
+
/// Raw transmutation to `u32`.
///
/// This is currently identical to `transmute::<f32, u32>(self)` on all platforms.
#![stable(feature = "rust1", since = "1.0.0")]
+#[cfg(not(bootstrap))]
+use crate::convert::FloatToInt;
#[cfg(not(test))]
use crate::intrinsics;
-
use crate::mem;
use crate::num::FpCategory;
intrinsics::minnumf64(self, other)
}
+ /// Rounds toward zero and converts to any primitive integer type,
+ /// assuming that the value is finite and fits in that type.
+ ///
+ /// ```
+ /// #![feature(float_approx_unchecked_to)]
+ ///
+ /// let value = 4.6_f32;
+ /// let rounded = unsafe { value.approx_unchecked_to::<u16>() };
+ /// assert_eq!(rounded, 4);
+ ///
+ /// let value = -128.9_f32;
+ /// let rounded = unsafe { value.approx_unchecked_to::<i8>() };
+ /// assert_eq!(rounded, std::i8::MIN);
+ /// ```
+ ///
+ /// # Safety
+ ///
+ /// The value must:
+ ///
+ /// * Not be `NaN`
+ /// * Not be infinite
+ /// * Be representable in the return type `Int`, after truncating off its fractional part
+ #[cfg(not(bootstrap))]
+ #[unstable(feature = "float_approx_unchecked_to", issue = "67058")]
+ #[inline]
+ pub unsafe fn approx_unchecked_to<Int>(self) -> Int where Self: FloatToInt<Int> {
+ FloatToInt::<Int>::approx_unchecked(self)
+ }
+
/// Raw transmutation to `u64`.
///
/// This is currently identical to `transmute::<f64, u64>(self)` on all platforms.
#![stable(feature = "rust1", since = "1.0.0")]
-use crate::convert::TryFrom;
use crate::fmt;
use crate::intrinsics;
use crate::mem;
/// The error type returned when a checked integral type conversion fails.
#[stable(feature = "try_from", since = "1.34.0")]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
-pub struct TryFromIntError(());
+pub struct TryFromIntError(pub(crate) ());
impl TryFromIntError {
#[unstable(feature = "int_error_internals",
}
}
-// no possible bounds violation
-macro_rules! try_from_unbounded {
- ($source:ty, $($target:ty),*) => {$(
- #[stable(feature = "try_from", since = "1.34.0")]
- impl TryFrom<$source> for $target {
- type Error = TryFromIntError;
-
- /// Try to create the target number type from a source
- /// number type. This returns an error if the source value
- /// is outside of the range of the target type.
- #[inline]
- fn try_from(value: $source) -> Result<Self, Self::Error> {
- Ok(value as $target)
- }
- }
- )*}
-}
-
-// only negative bounds
-macro_rules! try_from_lower_bounded {
- ($source:ty, $($target:ty),*) => {$(
- #[stable(feature = "try_from", since = "1.34.0")]
- impl TryFrom<$source> for $target {
- type Error = TryFromIntError;
-
- /// Try to create the target number type from a source
- /// number type. This returns an error if the source value
- /// is outside of the range of the target type.
- #[inline]
- fn try_from(u: $source) -> Result<$target, TryFromIntError> {
- if u >= 0 {
- Ok(u as $target)
- } else {
- Err(TryFromIntError(()))
- }
- }
- }
- )*}
-}
-
-// unsigned to signed (only positive bound)
-macro_rules! try_from_upper_bounded {
- ($source:ty, $($target:ty),*) => {$(
- #[stable(feature = "try_from", since = "1.34.0")]
- impl TryFrom<$source> for $target {
- type Error = TryFromIntError;
-
- /// Try to create the target number type from a source
- /// number type. This returns an error if the source value
- /// is outside of the range of the target type.
- #[inline]
- fn try_from(u: $source) -> Result<$target, TryFromIntError> {
- if u > (<$target>::max_value() as $source) {
- Err(TryFromIntError(()))
- } else {
- Ok(u as $target)
- }
- }
- }
- )*}
-}
-
-// all other cases
-macro_rules! try_from_both_bounded {
- ($source:ty, $($target:ty),*) => {$(
- #[stable(feature = "try_from", since = "1.34.0")]
- impl TryFrom<$source> for $target {
- type Error = TryFromIntError;
-
- /// Try to create the target number type from a source
- /// number type. This returns an error if the source value
- /// is outside of the range of the target type.
- #[inline]
- fn try_from(u: $source) -> Result<$target, TryFromIntError> {
- let min = <$target>::min_value() as $source;
- let max = <$target>::max_value() as $source;
- if u < min || u > max {
- Err(TryFromIntError(()))
- } else {
- Ok(u as $target)
- }
- }
- }
- )*}
-}
-
-macro_rules! rev {
- ($mac:ident, $source:ty, $($target:ty),*) => {$(
- $mac!($target, $source);
- )*}
-}
-
-// intra-sign conversions
-try_from_upper_bounded!(u16, u8);
-try_from_upper_bounded!(u32, u16, u8);
-try_from_upper_bounded!(u64, u32, u16, u8);
-try_from_upper_bounded!(u128, u64, u32, u16, u8);
-
-try_from_both_bounded!(i16, i8);
-try_from_both_bounded!(i32, i16, i8);
-try_from_both_bounded!(i64, i32, i16, i8);
-try_from_both_bounded!(i128, i64, i32, i16, i8);
-
-// unsigned-to-signed
-try_from_upper_bounded!(u8, i8);
-try_from_upper_bounded!(u16, i8, i16);
-try_from_upper_bounded!(u32, i8, i16, i32);
-try_from_upper_bounded!(u64, i8, i16, i32, i64);
-try_from_upper_bounded!(u128, i8, i16, i32, i64, i128);
-
-// signed-to-unsigned
-try_from_lower_bounded!(i8, u8, u16, u32, u64, u128);
-try_from_lower_bounded!(i16, u16, u32, u64, u128);
-try_from_lower_bounded!(i32, u32, u64, u128);
-try_from_lower_bounded!(i64, u64, u128);
-try_from_lower_bounded!(i128, u128);
-try_from_both_bounded!(i16, u8);
-try_from_both_bounded!(i32, u16, u8);
-try_from_both_bounded!(i64, u32, u16, u8);
-try_from_both_bounded!(i128, u64, u32, u16, u8);
-
-// usize/isize
-try_from_upper_bounded!(usize, isize);
-try_from_lower_bounded!(isize, usize);
-
-#[cfg(target_pointer_width = "16")]
-mod ptr_try_from_impls {
- use super::TryFromIntError;
- use crate::convert::TryFrom;
-
- try_from_upper_bounded!(usize, u8);
- try_from_unbounded!(usize, u16, u32, u64, u128);
- try_from_upper_bounded!(usize, i8, i16);
- try_from_unbounded!(usize, i32, i64, i128);
-
- try_from_both_bounded!(isize, u8);
- try_from_lower_bounded!(isize, u16, u32, u64, u128);
- try_from_both_bounded!(isize, i8);
- try_from_unbounded!(isize, i16, i32, i64, i128);
-
- rev!(try_from_upper_bounded, usize, u32, u64, u128);
- rev!(try_from_lower_bounded, usize, i8, i16);
- rev!(try_from_both_bounded, usize, i32, i64, i128);
-
- rev!(try_from_upper_bounded, isize, u16, u32, u64, u128);
- rev!(try_from_both_bounded, isize, i32, i64, i128);
-}
-
-#[cfg(target_pointer_width = "32")]
-mod ptr_try_from_impls {
- use super::TryFromIntError;
- use crate::convert::TryFrom;
-
- try_from_upper_bounded!(usize, u8, u16);
- try_from_unbounded!(usize, u32, u64, u128);
- try_from_upper_bounded!(usize, i8, i16, i32);
- try_from_unbounded!(usize, i64, i128);
-
- try_from_both_bounded!(isize, u8, u16);
- try_from_lower_bounded!(isize, u32, u64, u128);
- try_from_both_bounded!(isize, i8, i16);
- try_from_unbounded!(isize, i32, i64, i128);
-
- rev!(try_from_unbounded, usize, u32);
- rev!(try_from_upper_bounded, usize, u64, u128);
- rev!(try_from_lower_bounded, usize, i8, i16, i32);
- rev!(try_from_both_bounded, usize, i64, i128);
-
- rev!(try_from_unbounded, isize, u16);
- rev!(try_from_upper_bounded, isize, u32, u64, u128);
- rev!(try_from_unbounded, isize, i32);
- rev!(try_from_both_bounded, isize, i64, i128);
-}
-
-#[cfg(target_pointer_width = "64")]
-mod ptr_try_from_impls {
- use super::TryFromIntError;
- use crate::convert::TryFrom;
-
- try_from_upper_bounded!(usize, u8, u16, u32);
- try_from_unbounded!(usize, u64, u128);
- try_from_upper_bounded!(usize, i8, i16, i32, i64);
- try_from_unbounded!(usize, i128);
-
- try_from_both_bounded!(isize, u8, u16, u32);
- try_from_lower_bounded!(isize, u64, u128);
- try_from_both_bounded!(isize, i8, i16, i32);
- try_from_unbounded!(isize, i64, i128);
-
- rev!(try_from_unbounded, usize, u32, u64);
- rev!(try_from_upper_bounded, usize, u128);
- rev!(try_from_lower_bounded, usize, i8, i16, i32, i64);
- rev!(try_from_both_bounded, usize, i128);
-
- rev!(try_from_unbounded, isize, u16, u32);
- rev!(try_from_upper_bounded, isize, u64, u128);
- rev!(try_from_unbounded, isize, i32, i64);
- rev!(try_from_both_bounded, isize, i128);
-}
-
#[doc(hidden)]
trait FromStrRadixHelper: PartialOrd + Copy {
fn min_value() -> Self;
#[stable(feature = "rust1", since = "1.0.0")]
pub use crate::num::dec2flt::ParseFloatError;
-
-// Conversion traits for primitive integer and float types
-// Conversions T -> T are covered by a blanket impl and therefore excluded
-// Some conversions from and to usize/isize are not implemented due to portability concerns
-macro_rules! impl_from {
- ($Small: ty, $Large: ty, #[$attr:meta], $doc: expr) => {
- #[$attr]
- #[doc = $doc]
- impl From<$Small> for $Large {
- #[inline]
- fn from(small: $Small) -> $Large {
- small as $Large
- }
- }
- };
- ($Small: ty, $Large: ty, #[$attr:meta]) => {
- impl_from!($Small,
- $Large,
- #[$attr],
- concat!("Converts `",
- stringify!($Small),
- "` to `",
- stringify!($Large),
- "` losslessly."));
- }
-}
-
-macro_rules! impl_from_bool {
- ($target: ty, #[$attr:meta]) => {
- impl_from!(bool, $target, #[$attr], concat!("Converts a `bool` to a `",
- stringify!($target), "`. The resulting value is `0` for `false` and `1` for `true`
-values.
-
-# Examples
-
-```
-assert_eq!(", stringify!($target), "::from(true), 1);
-assert_eq!(", stringify!($target), "::from(false), 0);
-```"));
- };
-}
-
-// Bool -> Any
-impl_from_bool! { u8, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { u16, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { u32, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { u64, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { u128, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { usize, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { i8, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { i16, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { i32, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { i64, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { i128, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { isize, #[stable(feature = "from_bool", since = "1.28.0")] }
-
-// Unsigned -> Unsigned
-impl_from! { u8, u16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u8, u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u8, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u8, u128, #[stable(feature = "i128", since = "1.26.0")] }
-impl_from! { u8, usize, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u16, u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u16, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u16, u128, #[stable(feature = "i128", since = "1.26.0")] }
-impl_from! { u32, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u32, u128, #[stable(feature = "i128", since = "1.26.0")] }
-impl_from! { u64, u128, #[stable(feature = "i128", since = "1.26.0")] }
-
-// Signed -> Signed
-impl_from! { i8, i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { i8, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { i8, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { i8, i128, #[stable(feature = "i128", since = "1.26.0")] }
-impl_from! { i8, isize, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { i16, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { i16, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { i16, i128, #[stable(feature = "i128", since = "1.26.0")] }
-impl_from! { i32, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { i32, i128, #[stable(feature = "i128", since = "1.26.0")] }
-impl_from! { i64, i128, #[stable(feature = "i128", since = "1.26.0")] }
-
-// Unsigned -> Signed
-impl_from! { u8, i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u8, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u8, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u8, i128, #[stable(feature = "i128", since = "1.26.0")] }
-impl_from! { u16, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u16, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u16, i128, #[stable(feature = "i128", since = "1.26.0")] }
-impl_from! { u32, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u32, i128, #[stable(feature = "i128", since = "1.26.0")] }
-impl_from! { u64, i128, #[stable(feature = "i128", since = "1.26.0")] }
-
-// The C99 standard defines bounds on INTPTR_MIN, INTPTR_MAX, and UINTPTR_MAX
-// which imply that pointer-sized integers must be at least 16 bits:
-// https://port70.net/~nsz/c/c99/n1256.html#7.18.2.4
-impl_from! { u16, usize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] }
-impl_from! { u8, isize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] }
-impl_from! { i16, isize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] }
-
-// RISC-V defines the possibility of a 128-bit address space (RV128).
-
-// CHERI proposes 256-bit “capabilities”. Unclear if this would be relevant to usize/isize.
-// https://www.cl.cam.ac.uk/research/security/ctsrd/pdfs/20171017a-cheri-poster.pdf
-// http://www.csl.sri.com/users/neumann/2012resolve-cheri.pdf
-
-
-// Note: integers can only be represented with full precision in a float if
-// they fit in the significand, which is 24 bits in f32 and 53 bits in f64.
-// Lossy float conversions are not implemented at this time.
-
-// Signed -> Float
-impl_from! { i8, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-impl_from! { i8, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-impl_from! { i16, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-impl_from! { i16, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-impl_from! { i32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-
-// Unsigned -> Float
-impl_from! { u8, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-impl_from! { u8, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-impl_from! { u16, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-impl_from! { u16, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-impl_from! { u32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-
-// Float -> Float
-impl_from! { f32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
#[test]
fn test_bool_to_option() {
- assert_eq!(false.then(0), None);
- assert_eq!(true.then(0), Some(0));
- assert_eq!(false.then_with(|| 0), None);
- assert_eq!(true.then_with(|| 0), Some(0));
+ assert_eq!(false.then_some(0), None);
+ assert_eq!(true.then_some(0), Some(0));
+ assert_eq!(false.then(|| 0), None);
+ assert_eq!(true.then(|| 0), Some(0));
}
#![feature(nll)]
#![feature(rustc_private)]
#![feature(unicode_internals)]
+#![feature(bool_to_option)]
pub use Piece::*;
pub use Position::*;
break;
}
}
- if found {
- Some(cur)
- } else {
- None
- }
+ found.then_some(cur)
}
}
return None
}
None => {
- if !tcx.sess.has_errors() {
+ if !tcx.sess.has_errors_or_delayed_span_bugs() {
bug!("try_mark_previous_green() - Forcing the DepNode \
should have set its color")
} else {
- // If the query we just forced has resulted
- // in some kind of compilation error, we
- // don't expect that the corresponding
- // dep-node color has been updated.
+ // If the query we just forced has resulted in
+ // some kind of compilation error, we cannot rely on
+ // the dep-node color having been properly updated.
+ // This means that the query system has reached an
+ // invalid state. We let the compiler continue (by
+ // returning `None`) so it can emit error messages
+ // and wind down, but rely on the fact that this
+ // invalid state will not be persisted to the
+ // incremental compilation cache because of
+ // compilation errors being present.
+ debug!("try_mark_previous_green({:?}) - END - \
+ dependency {:?} resulted in compilation error",
+ dep_node,
+ dep_dep_node);
+ return None
}
}
}
map::Node::Expr(e) => e.is_fn_like(),
_ => false
};
- if fn_like {
- Some(FnLikeNode {
- node,
- })
- } else {
- None
- }
+ fn_like.then_some(FnLikeNode { node })
}
pub fn body(self) -> ast::BodyId {
(r, p)
);
let p_ty = p.to_ty(tcx);
- if compare_ty(p_ty) {
- Some(ty::OutlivesPredicate(p_ty, r))
- } else {
- None
- }
+ compare_ty(p_ty).then_some(ty::OutlivesPredicate(p_ty, r))
});
param_bounds
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
#![feature(arbitrary_self_types)]
+#![feature(bool_to_option)]
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(const_fn)]
pub fn vars_iter<'a>(&'a self) -> impl Iterator<Item = Local> + 'a {
(self.arg_count + 1..self.local_decls.len()).filter_map(move |index| {
let local = Local::new(index);
- if self.local_decls[local].is_user_variable() {
- Some(local)
- } else {
- None
- }
+ self.local_decls[local].is_user_variable().then_some(local)
})
}
return None
};
- if tcx.has_attr(impl_def_id, sym::rustc_on_unimplemented) {
- Some(impl_def_id)
- } else {
- None
- }
+ tcx.has_attr(impl_def_id, sym::rustc_on_unimplemented).then_some(impl_def_id)
}
fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str> {
}
let span = self.tcx.def_span(generator_did);
+ // Do not ICE on closure typeck (#66868).
+ if let None = self.tcx.hir().as_local_hir_id(generator_did) {
+ return false;
+ }
let tables = self.tcx.typeck_tables_of(generator_did);
debug!("note_obligation_cause_for_async_await: generator_did={:?} span={:?} ",
generator_did, span);
}
};
- if is_associated_item {
- Some(self.associated_item(def_id))
- } else {
- None
- }
+ is_associated_item.then(|| self.associated_item(def_id))
}
fn associated_item_from_trait_item_ref(self,
let unnormalized_env = ty::ParamEnv::new(
tcx.intern_predicates(&predicates),
traits::Reveal::UserFacing,
- if tcx.sess.opts.debugging_opts.chalk { Some(def_id) } else { None }
+ tcx.sess.opts.debugging_opts.chalk.then_some(def_id),
);
let body_id = tcx.hir().as_local_hir_id(def_id).map_or(hir::DUMMY_HIR_ID, |id| {
return true;
}
- visit_waiters(query, |_, successor| {
- if connected_to_root(successor, visited) {
- Some(None)
- } else {
- None
- }
- }).is_some()
+ visit_waiters(query, |_, successor| connected_to_root(successor, visited).then_some(None))
+ .is_some()
}
// Deterministically pick an query from a list
let native_libs = tcx.native_libraries(cnum);
let def_id_to_native_lib = native_libs.iter().filter_map(|lib|
- if let Some(id) = lib.foreign_module {
- Some((id, lib))
- } else {
- None
- }
+ lib.foreign_module.map(|id| (id, lib))
).collect::<FxHashMap<_, _>>();
let mut ret = FxHashMap::default();
use rustc_data_structures::small_c_str::SmallCStr;
use errors::{Handler, FatalError};
-use std::ffi::{CString, CStr};
+use std::ffi::CString;
use std::fs;
use std::io::{self, Write};
use std::path::{Path, PathBuf};
})
.filter_map(|val| {
// Exclude some symbols that we know are not Rust symbols.
- let name = CStr::from_ptr(llvm::LLVMGetValueName(val));
- if ignored(name.to_bytes()) {
+ let name = llvm::get_value_name(val);
+ if ignored(name) {
None
} else {
Some((val, name))
})
.map(move |(val, name)| {
let mut imp_name = prefix.as_bytes().to_vec();
- imp_name.extend(name.to_bytes());
+ imp_name.extend(name);
let imp_name = CString::new(imp_name).unwrap();
(imp_name, val)
})
let (mut lo, mut hi) = (0u64, 0u64);
let success = llvm::LLVMRustConstInt128Get(v, sign_ext,
&mut hi, &mut lo);
- if success {
- Some(hi_lo_to_u128(lo, hi))
- } else {
- None
- }
+ success.then_some(hi_lo_to_u128(lo, hi))
})
}
use rustc::hir::{self, CodegenFnAttrs, CodegenFnAttrFlags};
-use std::ffi::{CStr, CString};
+use std::ffi::CStr;
pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll Value {
let mut llvals = Vec::with_capacity(alloc.relocations().len() + 1);
} else {
// If we created the global with the wrong type,
// correct the type.
- let empty_string = const_cstr!("");
- let name_str_ref = CStr::from_ptr(llvm::LLVMGetValueName(g));
- let name_string = CString::new(name_str_ref.to_bytes()).unwrap();
- llvm::LLVMSetValueName(g, empty_string.as_ptr());
+ let name = llvm::get_value_name(g).to_vec();
+ llvm::set_value_name(g, b"");
let linkage = llvm::LLVMRustGetLinkage(g);
let visibility = llvm::LLVMRustGetVisibility(g);
let new_g = llvm::LLVMRustGetOrInsertGlobal(
- self.llmod, name_string.as_ptr(), val_llty);
+ self.llmod, name.as_ptr().cast(), name.len(), val_llty);
llvm::LLVMRustSetLinkage(new_g, linkage);
llvm::LLVMRustSetVisibility(new_g, visibility);
use libc::c_uint;
use std::cell::RefCell;
-use std::ffi::{CStr, CString};
+use std::ffi::CString;
use smallvec::SmallVec;
use syntax_pos::{self, BytePos, Span, Pos};
return;
}
- let old_name = unsafe {
- CStr::from_ptr(llvm::LLVMGetValueName(value))
- };
- match old_name.to_str() {
- Ok("") => {}
- Ok(_) => {
- // Avoid replacing the name if it already exists.
- // While we could combine the names somehow, it'd
- // get noisy quick, and the usefulness is dubious.
- return;
- }
- Err(_) => return,
- }
-
- let cname = SmallCStr::new(name);
- unsafe {
- llvm::LLVMSetValueName(value, cname.as_ptr());
+ // Avoid replacing the name if it already exists.
+ // While we could combine the names somehow, it'd
+ // get noisy quick, and the usefulness is dubious.
+ if llvm::get_value_name(value).is_empty() {
+ llvm::set_value_name(value, name.as_bytes());
}
}
}
name: &str, ty: &'ll Type
) -> &'ll Value {
debug!("declare_global(name={:?})", name);
- let namebuf = SmallCStr::new(name);
unsafe {
- llvm::LLVMRustGetOrInsertGlobal(self.llmod, namebuf.as_ptr(), ty)
+ llvm::LLVMRustGetOrInsertGlobal(self.llmod, name.as_ptr().cast(), name.len(), ty)
}
}
return;
}
}
-
},
+ "float_to_int_approx_unchecked" => {
+ if float_type_width(arg_tys[0]).is_none() {
+ span_invalid_monomorphization_error(
+ tcx.sess, span,
+ &format!("invalid monomorphization of `float_to_int_approx_unchecked` \
+ intrinsic: expected basic float type, \
+ found `{}`", arg_tys[0]));
+ return;
+ }
+ match int_type_width_signed(ret_ty, self.cx) {
+ Some((width, signed)) => {
+ if signed {
+ self.fptosi(args[0].immediate(), self.cx.type_ix(width))
+ } else {
+ self.fptoui(args[0].immediate(), self.cx.type_ix(width))
+ }
+ }
+ None => {
+ span_invalid_monomorphization_error(
+ tcx.sess, span,
+ &format!("invalid monomorphization of `float_to_int_approx_unchecked` \
+ intrinsic: expected basic integer type, \
+ found `{}`", ret_ty));
+ return;
+ }
+ }
+ }
+
"discriminant_value" => {
args[0].deref(self.cx()).codegen_get_discr(self, ret_ty)
}
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
+#![feature(bool_to_option)]
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(const_cstr_unchecked)]
// Operations on all values
pub fn LLVMTypeOf(Val: &Value) -> &Type;
- pub fn LLVMGetValueName(Val: &Value) -> *const c_char;
- pub fn LLVMSetValueName(Val: &Value, Name: *const c_char);
+ pub fn LLVMGetValueName2(Val: &Value, Length: *mut size_t) -> *const c_char;
+ pub fn LLVMSetValueName2(Val: &Value, Name: *const c_char, NameLen: size_t);
pub fn LLVMReplaceAllUsesWith(OldVal: &'a Value, NewVal: &'a Value);
pub fn LLVMSetMetadata(Val: &'a Value, KindID: c_uint, Node: &'a Value);
pub fn LLVMIsAGlobalVariable(GlobalVar: &Value) -> Option<&Value>;
pub fn LLVMAddGlobal(M: &'a Module, Ty: &'a Type, Name: *const c_char) -> &'a Value;
pub fn LLVMGetNamedGlobal(M: &Module, Name: *const c_char) -> Option<&Value>;
- pub fn LLVMRustGetOrInsertGlobal(M: &'a Module, Name: *const c_char, T: &'a Type) -> &'a Value;
+ pub fn LLVMRustGetOrInsertGlobal(M: &'a Module, Name: *const c_char, NameLen: size_t,
+ T: &'a Type) -> &'a Value;
pub fn LLVMRustInsertPrivateGlobal(M: &'a Module, T: &'a Type) -> &'a Value;
pub fn LLVMGetFirstGlobal(M: &Module) -> Option<&Value>;
pub fn LLVMGetNextGlobal(GlobalVar: &Value) -> Option<&Value>;
pub fn LLVMRustPositionBuilderAtStart(B: &Builder<'a>, BB: &'a BasicBlock);
- pub fn LLVMRustSetComdat(M: &'a Module, V: &'a Value, Name: *const c_char);
+ pub fn LLVMRustSetComdat(M: &'a Module, V: &'a Value, Name: *const c_char, NameLen: size_t);
pub fn LLVMRustUnsetComdat(V: &Value);
pub fn LLVMRustSetModulePICLevel(M: &Module);
pub fn LLVMRustSetModulePIELevel(M: &Module);
// For more details on COMDAT sections see e.g., http://www.airs.com/blog/archives/52
pub fn SetUniqueComdat(llmod: &Module, val: &'a Value) {
unsafe {
- LLVMRustSetComdat(llmod, val, LLVMGetValueName(val));
+ let name = get_value_name(val);
+ LLVMRustSetComdat(llmod, val, name.as_ptr().cast(), name.len());
}
}
}
}
+/// Safe wrapper for `LLVMGetValueName2` into a byte slice
+pub fn get_value_name(value: &'a Value) -> &'a [u8] {
+ unsafe {
+ let mut len = 0;
+ let data = LLVMGetValueName2(value, &mut len);
+ std::slice::from_raw_parts(data.cast(), len)
+ }
+}
+
+/// Safe wrapper for `LLVMSetValueName2` from a byte slice
+pub fn set_value_name(value: &Value, name: &[u8]) {
+ unsafe {
+ let data = name.as_ptr().cast();
+ LLVMSetValueName2(value, data, name.len());
+ }
+}
+
pub fn build_string(f: impl FnOnce(&RustString)) -> Result<String, FromUtf8Error> {
let sr = RustString {
bytes: RefCell::new(Vec::new()),
use std::path::Component;
if path.is_absolute() != base.is_absolute() {
- if path.is_absolute() {
- Some(PathBuf::from(path))
- } else {
- None
- }
+ path.is_absolute().then(|| PathBuf::from(path))
} else {
let mut ita = path.components();
let mut itb = base.components();
match tcx.hir().get(hir_id) {
Node::ForeignItem(..) => {
let def_id = tcx.hir().local_def_id(hir_id);
- if tcx.is_statically_included_foreign_item(def_id) {
- Some(def_id)
- } else {
- None
- }
+ tcx.is_statically_included_foreign_item(def_id).then_some(def_id)
}
// Only consider nodes that actually have exported symbols.
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
+#![feature(bool_to_option)]
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(core_intrinsics)]
emit_bc: bool,
emit_bc_compressed: bool,
outputs: &OutputFilenames) -> CompiledModule {
- let object = if emit_obj {
- Some(outputs.temp_path(OutputType::Object, Some(&self.name)))
- } else {
- None
- };
- let bytecode = if emit_bc {
- Some(outputs.temp_path(OutputType::Bitcode, Some(&self.name)))
- } else {
- None
- };
- let bytecode_compressed = if emit_bc_compressed {
- Some(outputs.temp_path(OutputType::Bitcode, Some(&self.name))
- .with_extension(RLIB_BYTECODE_EXTENSION))
- } else {
- None
- };
+ let object = emit_obj
+ .then(|| outputs.temp_path(OutputType::Object, Some(&self.name)));
+ let bytecode = emit_bc
+ .then(|| outputs.temp_path(OutputType::Bitcode, Some(&self.name)));
+ let bytecode_compressed = emit_bc_compressed.then(|| {
+ outputs.temp_path(OutputType::Bitcode, Some(&self.name))
+ .with_extension(RLIB_BYTECODE_EXTENSION)
+ });
CompiledModule {
name: self.name.clone(),
if self.fn_abi.ret.layout.abi.is_uninhabited() {
// Functions with uninhabited return values are marked `noreturn`,
// so we should make sure that we never actually do.
+ // We play it safe by using a well-defined `abort`, but we could go for immediate UB
+ // if that turns out to be helpful.
bx.abort();
+ // `abort` does not terminate the block, so we still need to generate
+ // an `unreachable` terminator after it.
bx.unreachable();
return;
}
mir::TerminatorKind::Abort => {
bx.abort();
+ // `abort` does not terminate the block, so we still need to generate
+ // an `unreachable` terminator after it.
bx.unreachable();
}
},
}
// Allow RalfJ to sleep soundly knowing that even refactorings that remove
- // the above error (or silence it under some conditions) will not cause UB
+ // the above error (or silence it under some conditions) will not cause UB.
bx.abort();
- // We've errored, so we don't have to produce working code.
+ // We still have to return an operand but it doesn't matter,
+ // this code is unreachable.
let ty = self.monomorphize(&constant.literal.ty);
let layout = bx.cx().layout_of(ty);
bx.load_operand(PlaceRef::new_sized(
variant_index: VariantIdx
) {
if self.layout.for_variant(bx.cx(), variant_index).abi.is_uninhabited() {
+ // We play it safe by using a well-defined `abort`, but we could go for immediate UB
+ // if that turns out to be helpful.
+ bx.abort();
return;
}
match self.layout.variants {
},
Err(_) => {
// This is unreachable as long as runtime
- // and compile-time agree on values
+ // and compile-time agree perfectly.
// With floats that won't always be true,
- // so we generate an abort.
+ // so we generate a (safe) abort.
bx.abort();
+ // We still have to return a place but it doesn't matter,
+ // this code is unreachable.
let llval = bx.cx().const_undef(
bx.cx().type_ptr_to(bx.cx().backend_type(layout))
);
E0013: include_str!("./error_codes/E0013.md"),
E0014: include_str!("./error_codes/E0014.md"),
E0015: include_str!("./error_codes/E0015.md"),
-E0017: include_str!("./error_codes/E0017.md"),
E0019: include_str!("./error_codes/E0019.md"),
E0023: include_str!("./error_codes/E0023.md"),
E0025: include_str!("./error_codes/E0025.md"),
+++ /dev/null
-References in statics and constants may only refer to immutable values.
-
-Erroneous code example:
-
-```compile_fail,E0017
-static X: i32 = 1;
-const C: i32 = 2;
-
-// these three are not allowed:
-const CR: &mut i32 = &mut C;
-static STATIC_REF: &'static mut i32 = &mut X;
-static CONST_REF: &'static mut i32 = &mut C;
-```
-
-Statics are shared everywhere, and if they refer to mutable data one might
-violate memory safety since holding multiple mutable references to shared data
-is not allowed.
-
-If you really want global mutable state, try using `static mut` or a global
-`UnsafeCell`.
/// Allows the use of `#[cfg(sanitize = "option")]`; set when -Zsanitizer is used.
(active, cfg_sanitize, "1.41.0", Some(39699), None),
+ /// Allows using `&mut` in constant functions.
+ (active, const_mut_refs, "1.41.0", Some(57349), None),
+
// -------------------------------------------------------------------------
// feature-group-end: actual feature gates
// -------------------------------------------------------------------------
+#![feature(bool_to_option)]
#![feature(box_syntax)]
#![feature(set_stdio)]
#![feature(nll)]
}
fn output_conflicts_with_dir(output_paths: &[PathBuf]) -> Option<PathBuf> {
- let check = |output_path: &PathBuf| {
- if output_path.is_dir() {
- Some(output_path.clone())
- } else {
- None
- }
- };
+ let check = |output_path: &PathBuf| output_path.is_dir().then(|| output_path.clone());
check_output(output_paths, check)
}
use syntax::{self, ast};
/// Represent the result of a query.
-/// This result can be stolen with the `take` method and returned with the `give` method.
+/// This result can be stolen with the `take` method and generated with the `compute` method.
pub struct Query<T> {
result: RefCell<Option<Result<T>>>,
}
}
/// Takes ownership of the query result. Further attempts to take or peek the query
- /// result will panic unless it is returned by calling the `give` method.
+ /// result will panic unless it is generated by calling the `compute` method.
pub fn take(&self) -> T {
self.result
.borrow_mut()
pub fn dep_graph_future(&self) -> Result<&Query<Option<DepGraphFuture>>> {
self.dep_graph_future.compute(|| {
- Ok(if self.session().opts.build_dep_graph() {
- Some(rustc_incremental::load_dep_graph(self.session()))
- } else {
- None
- })
+ Ok(self.session().opts.build_dep_graph().then(|| {
+ rustc_incremental::load_dep_graph(self.session())
+ }))
})
}
fn get_stack_size() -> Option<usize> {
// FIXME: Hacks on hacks. If the env is trying to override the stack size
// then *don't* set it explicitly.
- if env::var_os("RUST_MIN_STACK").is_none() {
- Some(STACK_SIZE)
- } else {
- None
- }
+ env::var_os("RUST_MIN_STACK").is_none().then_some(STACK_SIZE)
}
struct Sink(Arc<Mutex<Vec<u8>>>);
} else {
"rustc"
});
- if candidate.exists() {
- Some(candidate)
- } else {
- None
- }
+ candidate.exists().then_some(candidate)
})
.next()
}
match pred {
ty::Predicate::TypeOutlives(outlives) => {
let outlives = outlives.skip_binder();
- if outlives.0.is_param(index) {
- Some(outlives.1)
- } else {
- None
- }
+ outlives.0.is_param(index).then_some(outlives.1)
}
_ => None
}
}),
_ => false,
};
- if is_inferred {
- Some((i, bound.span()))
- } else {
- None
- }
+ is_inferred.then_some((i, bound.span()))
} else {
None
}
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
#![cfg_attr(test, feature(test))]
+#![feature(bool_to_option)]
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(nll)]
// First up we check for global allocators. Look at the crate graph here
// and see what's a global allocator, including if we ourselves are a
// global allocator.
- let mut global_allocator = if self.cstore.has_global_allocator {
- Some(Symbol::intern("this crate"))
- } else {
- None
- };
+ let mut global_allocator = self.cstore.has_global_allocator
+ .then(|| Symbol::intern("this crate"));
self.cstore.iter_crate_data(|_, data| {
if !data.has_global_allocator() {
return
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
+#![feature(bool_to_option)]
#![feature(box_patterns)]
#![feature(core_intrinsics)]
#![feature(crate_visibility_modifier)]
Option<Rc<Output<RegionVid, BorrowIndex, LocationIndex, Local, MovePathIndex>>>,
Option<ClosureRegionRequirements<'tcx>>,
) {
- let mut all_facts = if AllFacts::enabled(infcx.tcx) {
- Some(AllFacts::default())
- } else {
- None
- };
+ let mut all_facts = AllFacts::enabled(infcx.tcx).then_some(AllFacts::default());
let universal_regions = Rc::new(universal_regions);
// functions below, which will trigger them to report errors
// eagerly.
let mut outlives_requirements =
- if infcx.tcx.is_closure(mir_def_id) { Some(vec![]) } else { None };
+ infcx.tcx.is_closure(mir_def_id).then(|| vec![]);
self.check_type_tests(
infcx,
let min = |r1: ty::RegionVid, r2: ty::RegionVid| -> Option<ty::RegionVid> {
let r1_outlives_r2 = self.universal_region_relations.outlives(r1, r2);
let r2_outlives_r1 = self.universal_region_relations.outlives(r2, r1);
- if r1_outlives_r2 && r2_outlives_r1 {
- Some(r1.min(r2))
- } else if r1_outlives_r2 {
- Some(r2)
- } else if r2_outlives_r1 {
- Some(r1)
- } else {
- None
+ match (r1_outlives_r2, r2_outlives_r1) {
+ (true, true) => Some(r1.min(r2)),
+ (true, false) => Some(r2),
+ (false, true) => Some(r1),
+ (false, false) => None,
}
};
let mut min_choice = choice_regions[0];
}
})();
- if no_overlap == Some(true) {
+ if let Some(true) = no_overlap {
// Testing range does not overlap with pattern range,
// so the pattern can be matched only if this test fails.
Some(1)
}
(&TestKind::Range(range), &PatKind::Constant { value }) => {
- if self.const_range_contains(range, value) == Some(false) {
+ if let Some(false) = self.const_range_contains(range, value) {
// `value` is not contained in the testing range,
// so `value` can be matched only if this test fails.
Some(1)
) -> Option<Ordering> {
trace!("compare_const_vals: {:?}, {:?}", a, b);
- let from_bool = |v: bool| {
- if v {
- Some(Ordering::Equal)
- } else {
- None
- }
- };
+ let from_bool = |v: bool| v.then_some(Ordering::Equal);
let fallback = || from_bool(a == b);
size: Size,
align: Align,
) -> InterpResult<'tcx, Option<Pointer<M::PointerTag>>> {
- let align = if M::CHECK_ALIGN { Some(align) } else { None };
+ let align = M::CHECK_ALIGN.then_some(align);
self.check_ptr_access_align(sptr, size, align, CheckInAllocMsg::MemoryAccessTest)
}
}
BinaryOp(bin_op, ref left, ref right) => {
- let layout = if binop_left_homogeneous(bin_op) { Some(dest.layout) } else { None };
+ let layout = binop_left_homogeneous(bin_op).then_some(dest.layout);
let left = self.read_immediate(self.eval_operand(left, layout)?)?;
- let layout = if binop_right_homogeneous(bin_op) { Some(left.layout) } else { None };
+ let layout = binop_right_homogeneous(bin_op).then_some(left.layout);
let right = self.read_immediate(self.eval_operand(right, layout)?)?;
self.binop_ignore_overflow(
bin_op,
CheckedBinaryOp(bin_op, ref left, ref right) => {
// Due to the extra boolean in the result, we can never reuse the `dest.layout`.
let left = self.read_immediate(self.eval_operand(left, None)?)?;
- let layout = if binop_right_homogeneous(bin_op) { Some(left.layout) } else { None };
+ let layout = binop_right_homogeneous(bin_op).then_some(left.layout);
let right = self.read_immediate(self.eval_operand(right, layout)?)?;
self.binop_with_overflow(
bin_op,
#![feature(in_band_lifetimes)]
#![feature(inner_deref)]
#![feature(slice_patterns)]
+#![feature(bool_to_option)]
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(crate_visibility_modifier)]
#![feature(associated_type_bounds)]
#![feature(range_is_empty)]
#![feature(stmt_expr_attributes)]
-#![feature(bool_to_option)]
#![feature(trait_alias)]
#![feature(matches_macro)]
.iter()
.map(|part| part.data.as_symbol());
- let volatile_suffix = if volatile {
- Some("volatile")
- } else {
- None
- };
+ let volatile_suffix = volatile.then_some("volatile");
name_builder.build_cgu_name(def_path.krate, components, volatile_suffix)
}).clone()
//! Concrete error types for all operations which may be invalid in a certain const context.
use rustc::hir::def_id::DefId;
-use rustc::mir::BorrowKind;
use rustc::session::config::nightly_options;
use rustc::ty::TyCtxt;
use syntax::feature_gate::feature_err;
}
#[derive(Debug)]
-pub struct MutBorrow(pub BorrowKind);
+pub struct CellBorrow;
+impl NonConstOp for CellBorrow {
+ fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
+ span_err!(item.tcx.sess, span, E0492,
+ "cannot borrow a constant which may contain \
+ interior mutability, create a static instead");
+ }
+}
+
+#[derive(Debug)]
+pub struct MutBorrow;
impl NonConstOp for MutBorrow {
+ fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
+ Some(tcx.features().const_mut_refs)
+ }
+
fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
- let kind = self.0;
- if let BorrowKind::Mut { .. } = kind {
- let mut err = struct_span_err!(item.tcx.sess, span, E0017,
- "references in {}s may only refer \
- to immutable values", item.const_kind());
- err.span_label(span, format!("{}s require immutable values",
- item.const_kind()));
- if item.tcx.sess.teach(&err.get_code().unwrap()) {
- err.note("References in statics and constants may only refer \
- to immutable values.\n\n\
- Statics are shared everywhere, and if they refer to \
- mutable data one might violate memory safety since \
- holding multiple mutable references to shared data \
- is not allowed.\n\n\
- If you really want global mutable state, try using \
- static mut or a global UnsafeCell.");
- }
- err.emit();
- } else {
- span_err!(item.tcx.sess, span, E0492,
- "cannot borrow a constant which may contain \
- interior mutability, create a static instead");
+ let mut err = feature_err(
+ &item.tcx.sess.parse_sess,
+ sym::const_mut_refs,
+ span,
+ &format!("references in {}s may only refer \
+ to immutable values", item.const_kind())
+ );
+ err.span_label(span, format!("{}s require immutable values",
+ item.const_kind()));
+ if item.tcx.sess.teach(&err.get_code().unwrap()) {
+ err.note("References in statics and constants may only refer \
+ to immutable values.\n\n\
+ Statics are shared everywhere, and if they refer to \
+ mutable data one might violate memory safety since \
+ holding multiple mutable references to shared data \
+ is not allowed.\n\n\
+ If you really want global mutable state, try using \
+ static mut or a global UnsafeCell.");
}
+ err.emit();
}
}
#[derive(Debug)]
pub struct MutDeref;
-impl NonConstOp for MutDeref {}
+impl NonConstOp for MutDeref {
+ fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
+ Some(tcx.features().const_mut_refs)
+ }
+}
#[derive(Debug)]
pub struct Panic;
};
if !is_allowed {
- self.check_op(ops::MutBorrow(kind));
+ if let BorrowKind::Mut{ .. } = kind {
+ self.check_op(ops::MutBorrow);
+ } else {
+ self.check_op(ops::CellBorrow);
+ }
}
}
);
if borrowed_place_has_mut_interior {
- self.check_op(ops::MutBorrow(kind));
+ if let BorrowKind::Mut{ .. } = kind {
+ self.check_op(ops::MutBorrow);
+ } else {
+ self.check_op(ops::CellBorrow);
+ }
}
}
}
}
}
-
fn visit_projection_elem(
&mut self,
place_base: &PlaceBase<'tcx>,
let mut unsafe_blocks: Vec<_> = unsafe_blocks.into_iter().collect();
unsafe_blocks.sort_by_cached_key(|(hir_id, _)| tcx.hir().hir_to_node_id(*hir_id));
let used_unsafe: FxHashSet<_> = unsafe_blocks.iter()
- .flat_map(|&&(id, used)| if used { Some(id) } else { None })
+ .flat_map(|&&(id, used)| used.then_some(id))
.collect();
for &(block_id, is_used) in unsafe_blocks {
if !is_used {
fn check_ty(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span, fn_def_id: DefId) -> McfResult {
for ty in ty.walk() {
match ty.kind {
- ty::Ref(_, _, hir::Mutability::Mutable) => return Err((
- span,
- "mutable references in const fn are unstable".into(),
- )),
+ ty::Ref(_, _, hir::Mutability::Mutable) => {
+ if !tcx.features().const_mut_refs {
+ return Err((
+ span,
+ "mutable references in const fn are unstable".into(),
+ ))
+ }
+ }
ty::Opaque(..) => return Err((span, "`impl Trait` in const fn is unstable".into())),
ty::FnPtr(..) => {
if !tcx.const_fn_is_allowed_fn_ptr(fn_def_id) {
// Only bother checking blocks which terminate by switching on a local.
if let Some(local) = get_discriminant_local(&terminator.kind) {
let stmt_before_term = (block_data.statements.len() > 0)
- .then_with(|| &block_data.statements[block_data.statements.len() - 1].kind);
+ .then(|| &block_data.statements[block_data.statements.len() - 1].kind);
if let Some(StatementKind::Assign(box (l, Rvalue::Discriminant(place)))) = stmt_before_term
{
.iter_enumerated()
.filter_map(|(idx, layout)| {
(layout.abi != Abi::Uninhabited)
- .then_with(|| ty.discriminant_for_variant(tcx, idx).unwrap().val)
+ .then(|| ty.discriminant_for_variant(tcx, idx).unwrap().val)
})
.collect(),
}
}
for var_debug_info in &body.var_debug_info {
- write!(w, r#"debug {} => {};<br align="left"/>"#,
+ write!(w, r#"debug {} => {};<br align="left"/>"#,
var_debug_info.name, escape(&var_debug_info.place))?;
}
//!
//! [#64197]: https://github.com/rust-lang/rust/issues/64197
-use crate::validate_attr;
+use crate::{parse_in, validate_attr};
use rustc_feature::Features;
use rustc_errors::Applicability;
use syntax::attr::HasAttrs;
use syntax::feature_gate::{feature_err, get_features};
use syntax::attr;
-use syntax::ast;
+use syntax::ast::{self, Attribute, AttrItem, MetaItem};
use syntax::edition::Edition;
use syntax::mut_visit::*;
use syntax::ptr::P;
use syntax::sess::ParseSess;
use syntax::util::map_in_place::MapInPlace;
+use syntax_pos::Span;
use syntax_pos::symbol::sym;
use smallvec::SmallVec;
}
}
+const CFG_ATTR_GRAMMAR_HELP: &str = "#[cfg_attr(condition, attribute, other_attribute, ...)]";
+const CFG_ATTR_NOTE_REF: &str = "for more information, visit \
+ <https://doc.rust-lang.org/reference/conditional-compilation.html\
+ #the-cfg_attr-attribute>";
+
impl<'a> StripUnconfigured<'a> {
pub fn configure<T: HasAttrs>(&mut self, mut node: T) -> Option<T> {
self.process_cfg_attrs(&mut node);
- if self.in_cfg(node.attrs()) { Some(node) } else { None }
+ self.in_cfg(node.attrs()).then_some(node)
}
/// Parse and expand all `cfg_attr` attributes into a list of attributes
/// Gives a compiler warning when the `cfg_attr` contains no attributes and
/// is in the original source file. Gives a compiler error if the syntax of
/// the attribute is incorrect.
- fn process_cfg_attr(&mut self, attr: ast::Attribute) -> Vec<ast::Attribute> {
+ fn process_cfg_attr(&mut self, attr: Attribute) -> Vec<Attribute> {
if !attr.has_name(sym::cfg_attr) {
return vec![attr];
}
- if let ast::MacArgs::Empty = attr.get_normal_item().args {
- self.sess.span_diagnostic
- .struct_span_err(
- attr.span,
- "malformed `cfg_attr` attribute input",
- ).span_suggestion(
- attr.span,
- "missing condition and attribute",
- "#[cfg_attr(condition, attribute, other_attribute, ...)]".to_owned(),
- Applicability::HasPlaceholders,
- ).note("for more information, visit \
- <https://doc.rust-lang.org/reference/conditional-compilation.html\
- #the-cfg_attr-attribute>")
- .emit();
- return vec![];
- }
- let res = crate::parse_in_attr(self.sess, &attr, |p| p.parse_cfg_attr());
- let (cfg_predicate, expanded_attrs) = match res {
- Ok(result) => result,
- Err(mut e) => {
- e.emit();
- return vec![];
- }
+ let (cfg_predicate, expanded_attrs) = match self.parse_cfg_attr(&attr) {
+ None => return vec![],
+ Some(r) => r,
};
// Lint on zero attributes in source.
// At this point we know the attribute is considered used.
attr::mark_used(&attr);
- if attr::cfg_matches(&cfg_predicate, self.sess, self.features) {
- // We call `process_cfg_attr` recursively in case there's a
- // `cfg_attr` inside of another `cfg_attr`. E.g.
- // `#[cfg_attr(false, cfg_attr(true, some_attr))]`.
- expanded_attrs.into_iter()
- .flat_map(|(item, span)| self.process_cfg_attr(attr::mk_attr_from_item(
- attr.style,
- item,
- span,
- )))
+ if !attr::cfg_matches(&cfg_predicate, self.sess, self.features) {
+ return vec![];
+ }
+
+ // We call `process_cfg_attr` recursively in case there's a
+ // `cfg_attr` inside of another `cfg_attr`. E.g.
+ // `#[cfg_attr(false, cfg_attr(true, some_attr))]`.
+ expanded_attrs
+ .into_iter()
+ .flat_map(|(item, span)| {
+ let attr = attr::mk_attr_from_item(attr.style, item, span);
+ self.process_cfg_attr(attr)
+ })
.collect()
- } else {
- vec![]
+ }
+
+ fn parse_cfg_attr(&self, attr: &Attribute) -> Option<(MetaItem, Vec<(AttrItem, Span)>)> {
+ match attr.get_normal_item().args {
+ ast::MacArgs::Delimited(dspan, delim, ref tts) if !tts.is_empty() => {
+ let msg = "wrong `cfg_attr` delimiters";
+ validate_attr::check_meta_bad_delim(self.sess, dspan, delim, msg);
+ match parse_in(self.sess, tts.clone(), "`cfg_attr` input", |p| p.parse_cfg_attr()) {
+ Ok(r) => return Some(r),
+ Err(mut e) => e
+ .help(&format!("the valid syntax is `{}`", CFG_ATTR_GRAMMAR_HELP))
+ .note(CFG_ATTR_NOTE_REF)
+ .emit(),
+ }
+ }
+ _ => self.error_malformed_cfg_attr_missing(attr.span),
}
+ None
+ }
+
+ fn error_malformed_cfg_attr_missing(&self, span: Span) {
+ self.sess
+ .span_diagnostic
+ .struct_span_err(span, "malformed `cfg_attr` attribute input")
+ .span_suggestion(
+ span,
+ "missing condition and attribute",
+ CFG_ATTR_GRAMMAR_HELP.to_string(),
+ Applicability::HasPlaceholders,
+ )
+ .note(CFG_ATTR_NOTE_REF)
+ .emit();
}
/// Determines if a node with the given attributes should be included in this configuration.
- pub fn in_cfg(&self, attrs: &[ast::Attribute]) -> bool {
+ pub fn in_cfg(&self, attrs: &[Attribute]) -> bool {
attrs.iter().all(|attr| {
if !is_cfg(attr) {
return true;
}
/// Visit attributes on expression and statements (but not attributes on items in blocks).
- fn visit_expr_attrs(&mut self, attrs: &[ast::Attribute]) {
+ fn visit_expr_attrs(&mut self, attrs: &[Attribute]) {
// flag the offending attributes
for attr in attrs.iter() {
self.maybe_emit_expr_attr_err(attr);
}
/// If attributes are not allowed on expressions, emit an error for `attr`
- pub fn maybe_emit_expr_attr_err(&self, attr: &ast::Attribute) {
+ pub fn maybe_emit_expr_attr_err(&self, attr: &Attribute) {
if !self.features.map(|features| features.stmt_expr_attributes).unwrap_or(true) {
let mut err = feature_err(self.sess,
sym::stmt_expr_attributes,
}
}
-fn is_cfg(attr: &ast::Attribute) -> bool {
+fn is_cfg(attr: &Attribute) -> bool {
attr.check_name(sym::cfg)
}
pub fn process_configure_mod(
sess: &ParseSess,
cfg_mods: bool,
- attrs: &[ast::Attribute],
-) -> (bool, Vec<ast::Attribute>) {
+ attrs: &[Attribute],
+) -> (bool, Vec<Attribute>) {
// Don't perform gated feature checking.
let mut strip_unconfigured = StripUnconfigured { sess, features: None };
let mut attrs = attrs.to_owned();
//! The main parser interface.
+#![feature(bool_to_option)]
#![feature(crate_visibility_modifier)]
use syntax::ast;
}
/// Runs the given subparser `f` on the tokens of the given `attr`'s item.
-pub fn parse_in_attr<'a, T>(
+pub fn parse_in<'a, T>(
sess: &'a ParseSess,
- attr: &ast::Attribute,
+ tts: TokenStream,
+ name: &'static str,
mut f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
) -> PResult<'a, T> {
- let mut parser = Parser::new(
- sess,
- // FIXME(#66940, Centril | petrochenkov): refactor this function so it doesn't
- // require reconstructing and immediately re-parsing delimiters.
- attr.get_normal_item().args.outer_tokens(),
- None,
- false,
- false,
- Some("attribute"),
- );
+ let mut parser = Parser::new(sess, tts, None, false, false, Some(name));
let result = f(&mut parser)?;
if parser.token != token::Eof {
parser.unexpected()?;
Ok(attrs)
}
- pub(super) fn parse_unsuffixed_lit(&mut self) -> PResult<'a, ast::Lit> {
+ crate fn parse_unsuffixed_lit(&mut self) -> PResult<'a, ast::Lit> {
let lit = self.parse_lit()?;
debug!("checking if {:?} is unusuffixed", lit);
/// Parses `cfg_attr(pred, attr_item_list)` where `attr_item_list` is comma-delimited.
pub fn parse_cfg_attr(&mut self) -> PResult<'a, (ast::MetaItem, Vec<(ast::AttrItem, Span)>)> {
- self.expect(&token::OpenDelim(token::Paren))?;
-
let cfg_predicate = self.parse_meta_item()?;
self.expect(&token::Comma)?;
// Presumably, the majority of the time there will only be one attr.
let mut expanded_attrs = Vec::with_capacity(1);
-
- while !self.check(&token::CloseDelim(token::Paren)) {
- let lo = self.token.span.lo();
+ while self.token.kind != token::Eof {
+ let lo = self.token.span;
let item = self.parse_attr_item()?;
- expanded_attrs.push((item, self.prev_span.with_lo(lo)));
- self.expect_one_of(&[token::Comma], &[token::CloseDelim(token::Paren)])?;
+ expanded_attrs.push((item, lo.to(self.prev_span)));
+ if !self.eat(&token::Comma) {
+ break;
+ }
}
- self.expect(&token::CloseDelim(token::Paren))?;
Ok((cfg_predicate, expanded_attrs))
}
+ /// Matches `COMMASEP(meta_item_inner)`.
+ crate fn parse_meta_seq_top(&mut self) -> PResult<'a, Vec<ast::NestedMetaItem>> {
+ // Presumably, the majority of the time there will only be one attr.
+ let mut nmis = Vec::with_capacity(1);
+ while self.token.kind != token::Eof {
+ nmis.push(self.parse_meta_item_inner()?);
+ if !self.eat(&token::Comma) {
+ break;
+ }
+ }
+ Ok(nmis)
+ }
+
/// Matches the following grammar (per RFC 1559).
///
/// meta_item : PATH ( '=' UNSUFFIXED_LIT | '(' meta_item_inner? ')' )? ;
/// Checks if current token is one of tokens which cannot be nested like `kw::Enum`. In case
/// it is, we try to parse the item and report error about nested types.
fn recover_nested_adt_item(&mut self, keyword: Symbol) -> PResult<'a, bool> {
- if self.token.is_keyword(kw::Enum) ||
+ if (self.token.is_keyword(kw::Enum) ||
self.token.is_keyword(kw::Struct) ||
- self.token.is_keyword(kw::Union)
+ self.token.is_keyword(kw::Union))
+ && self.look_ahead(1, |t| t.is_ident())
{
let kw_token = self.token.clone();
let kw_str = pprust::token_to_string(&kw_token);
use rustc_errors::{PResult, Applicability, pluralize};
use syntax::ast::{self, QSelf, Path, PathSegment, Ident, ParenthesizedArgs, AngleBracketedArgs};
use syntax::ast::{AnonConst, GenericArg, AssocTyConstraint, AssocTyConstraintKind, BlockCheckMode};
-use syntax::ast::MacArgs;
use syntax::ThinVec;
use syntax::token::{self, Token};
use syntax_pos::source_map::{Span, BytePos};
Ok(Path { segments, span: lo.to(self.prev_span) })
}
- /// Like `parse_path`, but also supports parsing `Word` meta items into paths for
- /// backwards-compatibility. This is used when parsing derive macro paths in `#[derive]`
- /// attributes.
- fn parse_path_allowing_meta(&mut self, style: PathStyle) -> PResult<'a, Path> {
- let meta_ident = match self.token.kind {
- token::Interpolated(ref nt) => match **nt {
- token::NtMeta(ref item) => match item.args {
- MacArgs::Empty => Some(item.path.clone()),
- _ => None,
- },
- _ => None,
- },
- _ => None,
- };
- if let Some(path) = meta_ident {
- self.bump();
- return Ok(path);
- }
- self.parse_path(style)
- }
-
- /// Parse a list of paths inside `#[derive(path_0, ..., path_n)]`.
- pub fn parse_derive_paths(&mut self) -> PResult<'a, Vec<Path>> {
- self.expect(&token::OpenDelim(token::Paren))?;
- let mut list = Vec::new();
- while !self.eat(&token::CloseDelim(token::Paren)) {
- let path = self.parse_path_allowing_meta(PathStyle::Mod)?;
- list.push(path);
- if !self.eat(&token::Comma) {
- self.expect(&token::CloseDelim(token::Paren))?;
- break
- }
- }
- Ok(list)
- }
-
pub(super) fn parse_path_segments(
&mut self,
segments: &mut Vec<PathSegment>,
//! Meta-syntax validation logic of attributes for post-expansion.
+use crate::parse_in;
+
use rustc_errors::{PResult, Applicability};
use rustc_feature::{AttributeTemplate, BUILTIN_ATTRIBUTE_MAP};
-use syntax::ast::{self, Attribute, AttrKind, Ident, MacArgs, MetaItem, MetaItemKind};
+use syntax::ast::{self, Attribute, AttrKind, Ident, MacArgs, MacDelimiter, MetaItem, MetaItemKind};
use syntax::attr::mk_name_value_item_str;
use syntax::early_buffered_lints::ILL_FORMED_ATTRIBUTE_INPUT;
+use syntax::tokenstream::DelimSpan;
use syntax::sess::ParseSess;
use syntax_pos::{Symbol, sym};
pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, MetaItem> {
Ok(match attr.kind {
AttrKind::Normal(ref item) => MetaItem {
- path: item.path.clone(),
- kind: super::parse_in_attr(sess, attr, |p| p.parse_meta_item_kind())?,
span: attr.span,
+ path: item.path.clone(),
+ kind: match &attr.get_normal_item().args {
+ MacArgs::Empty => MetaItemKind::Word,
+ MacArgs::Eq(_, t) => {
+ let v = parse_in(sess, t.clone(), "name value", |p| p.parse_unsuffixed_lit())?;
+ MetaItemKind::NameValue(v)
+ }
+ MacArgs::Delimited(dspan, delim, t) => {
+ check_meta_bad_delim(sess, *dspan, *delim, "wrong meta list delimiters");
+ let nmis = parse_in(sess, t.clone(), "meta list", |p| p.parse_meta_seq_top())?;
+ MetaItemKind::List(nmis)
+ }
+ }
},
AttrKind::DocComment(comment) => {
mk_name_value_item_str(Ident::new(sym::doc, attr.span), comment, attr.span)
})
}
+crate fn check_meta_bad_delim(sess: &ParseSess, span: DelimSpan, delim: MacDelimiter, msg: &str) {
+ if let ast::MacDelimiter::Parenthesis = delim {
+ return;
+ }
+
+ sess.span_diagnostic
+ .struct_span_err(span.entire(), msg)
+ .multipart_suggestion(
+ "the delimiters should be `(` and `)`",
+ vec![
+ (span.open, "(".to_string()),
+ (span.close, ")".to_string()),
+ ],
+ Applicability::MachineApplicable,
+ )
+ .emit();
+}
+
/// Checks that the given meta-item is compatible with this `AttributeTemplate`.
fn is_attr_template_compatible(template: &AttributeTemplate, meta: &ast::MetaItemKind) -> bool {
match meta {
Scope::MacroUsePrelude => {
suggestions.extend(this.macro_use_prelude.iter().filter_map(|(name, binding)| {
let res = binding.res();
- if filter_fn(res) {
- Some(TypoSuggestion::from_res(*name, res))
- } else {
- None
- }
+ filter_fn(res).then_some(TypoSuggestion::from_res(*name, res))
}));
}
Scope::BuiltinAttrs => {
Scope::ExternPrelude => {
suggestions.extend(this.extern_prelude.iter().filter_map(|(ident, _)| {
let res = Res::Def(DefKind::Mod, DefId::local(CRATE_DEF_INDEX));
- if filter_fn(res) {
- Some(TypoSuggestion::from_res(ident.name, res))
- } else {
- None
- }
+ filter_fn(res).then_some(TypoSuggestion::from_res(ident.name, res))
}));
}
Scope::ToolPrelude => {
suggestions.extend(
primitive_types.iter().flat_map(|(name, prim_ty)| {
let res = Res::PrimTy(*prim_ty);
- if filter_fn(res) {
- Some(TypoSuggestion::from_res(*name, res))
- } else {
- None
- }
+ filter_fn(res).then_some(TypoSuggestion::from_res(*name, res))
})
)
}
GenericParamKind::Lifetime { .. } => None,
GenericParamKind::Type { ref default, .. } => {
found_default |= default.is_some();
- if found_default {
- Some((Ident::with_dummy_span(param.ident.name), Res::Err))
- } else {
- None
- }
+ found_default.then_some((Ident::with_dummy_span(param.ident.name), Res::Err))
}
}));
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
+#![feature(bool_to_option)]
#![feature(crate_visibility_modifier)]
#![feature(label_break_value)]
#![feature(nll)]
}
pub fn incr_comp_session_dir_opt(&self) -> Option<cell::Ref<'_, PathBuf>> {
- if self.opts.incremental.is_some() {
- Some(self.incr_comp_session_dir())
- } else {
- None
- }
+ self.opts.incremental.as_ref().map(|_| self.incr_comp_session_dir())
}
pub fn print_perf_stats(&self) {
None
}
}
- }
- else { None };
+ } else {
+ None
+ };
let host_triple = TargetTriple::from_triple(config::host_triple());
let host = Target::search(&host_triple).unwrap_or_else(|e|
RegKind::Vector => size.bits() == 64 || size.bits() == 128
};
- if valid_unit {
- Some(Uniform {
- unit,
- total: size
- })
- } else {
- None
- }
+ valid_unit.then_some(Uniform { unit, total: size })
})
}
RegKind::Vector => size.bits() == 64 || size.bits() == 128
};
- if valid_unit {
- Some(Uniform {
- unit,
- total: size
- })
- } else {
- None
- }
+ valid_unit.then_some(Uniform { unit, total: size })
})
}
// i686-pc-windows-msvc, it results in wrong stack offsets.
// attrs.pointee_align = Some(self.layout.align.abi);
- let extra_attrs = if self.layout.is_unsized() {
- Some(ArgAttributes::new())
- } else {
- None
- };
+ let extra_attrs = self.layout.is_unsized().then_some(ArgAttributes::new());
self.mode = PassMode::Indirect(attrs, extra_attrs);
}
RegKind::Vector => arg.layout.size.bits() == 128
};
- if valid_unit {
- Some(Uniform {
- unit,
- total: arg.layout.size
- })
- } else {
- None
- }
+ valid_unit.then_some(Uniform { unit, total: arg.layout.size })
})
}
RegKind::Vector => arg.layout.size.bits() == 128
};
- if valid_unit {
- Some(Uniform {
- unit,
- total: arg.layout.size
- })
- } else {
- None
- }
+ valid_unit.then_some(Uniform { unit, total: arg.layout.size })
})
}
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
#![feature(box_syntax)]
+#![feature(bool_to_option)]
#![feature(nll)]
#![feature(slice_patterns)]
augment_error(&mut err);
}
+ if let Some(expr) = expression {
+ fcx.emit_coerce_suggestions(&mut err, expr, found, expected);
+ }
+
// Error possibly reported in `check_assign` so avoid emitting error again.
err.emit_unless(expression.filter(|e| fcx.is_assign_to_bool(e, expected))
.is_some());
use super::method::probe;
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
+
+ pub fn emit_coerce_suggestions(
+ &self,
+ err: &mut DiagnosticBuilder<'_>,
+ expr: &hir::Expr,
+ expr_ty: Ty<'tcx>,
+ expected: Ty<'tcx>
+ ) {
+ self.annotate_expected_due_to_let_ty(err, expr);
+ self.suggest_compatible_variants(err, expr, expected, expr_ty);
+ self.suggest_ref_or_into(err, expr, expected, expr_ty);
+ self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty);
+ self.suggest_missing_await(err, expr, expected, expr_ty);
+ }
+
+
// Requires that the two types unify, and prints an error message if
// they don't.
pub fn demand_suptype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
return (expected, None)
}
- self.annotate_expected_due_to_let_ty(&mut err, expr);
- self.suggest_compatible_variants(&mut err, expr, expected, expr_ty);
- self.suggest_ref_or_into(&mut err, expr, expected, expr_ty);
- self.suggest_boxing_when_appropriate(&mut err, expr, expected, expr_ty);
- self.suggest_missing_await(&mut err, expr, expected, expr_ty);
+ self.emit_coerce_suggestions(&mut err, expr, expr_ty, expected);
(expected, Some(err))
}
(1, vec![param(0), param(0)], param(0)),
"fadd_fast" | "fsub_fast" | "fmul_fast" | "fdiv_fast" | "frem_fast" =>
(1, vec![param(0), param(0)], param(0)),
+ "float_to_int_approx_unchecked" => (2, vec![ param(0) ], param(1)),
"assume" => (0, vec![tcx.types.bool], tcx.mk_unit()),
"likely" => (0, vec![tcx.types.bool], tcx.types.bool),
r.map(|mut pick| {
pick.autoderefs = step.autoderefs;
pick.autoref = Some(mutbl);
- pick.unsize = if step.unsize {
- Some(self_ty)
- } else {
- None
- };
+ pick.unsize = step.unsize.then_some(self_ty);
pick
})
})
pointing_at_return_type = self.suggest_missing_return_type(
err, &fn_decl, expected, found, can_suggest);
}
- self.suggest_ref_or_into(err, expr, expected, found);
- self.suggest_boxing_when_appropriate(err, expr, expected, found);
pointing_at_return_type
}
ty: expected,
}));
let obligation = traits::Obligation::new(self.misc(sp), self.param_env, predicate);
+ debug!("suggest_missing_await: trying obligation {:?}", obligation);
if self.infcx.predicate_may_hold(&obligation) {
+ debug!("suggest_missing_await: obligation held: {:?}", obligation);
if let Ok(code) = self.sess().source_map().span_to_snippet(sp) {
err.span_suggestion(
sp,
format!("{}.await", code),
Applicability::MaybeIncorrect,
);
+ } else {
+ debug!("suggest_missing_await: no snippet for {:?}", sp);
}
+ } else {
+ debug!("suggest_missing_await: obligation did not hold: {:?}", obligation)
}
}
}
};
let infer_kind = if let UpvarSubsts::Closure(closure_substs) = substs {
- if self.closure_kind(closure_def_id, closure_substs).is_none() {
- Some(closure_substs)
- } else {
- None
- }
+ self.closure_kind(closure_def_id, closure_substs).is_none().then_some(closure_substs)
} else {
None
};
#![allow(non_camel_case_types)]
+#![feature(bool_to_option)]
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(crate_visibility_modifier)]
impl ops::BitAndAssign for Cfg {
fn bitand_assign(&mut self, other: Cfg) {
+ if *self == other {
+ return;
+ }
match (self, other) {
(&mut Cfg::False, _) | (_, Cfg::True) => {},
(s, Cfg::False) => *s = Cfg::False,
impl ops::BitOrAssign for Cfg {
fn bitor_assign(&mut self, other: Cfg) {
+ if *self == other {
+ return;
+ }
match (self, other) {
(&mut Cfg::True, _) | (_, Cfg::False) => {},
(s, Cfg::True) => *s = Cfg::True,
let filename = &tmpdir.join("file_that_does_not_exist.txt");
let result = File::open(filename);
- #[cfg(unix)]
+ #[cfg(all(unix, not(target_os = "vxworks")))]
error!(result, "No such file or directory");
+ #[cfg(target_os = "vxworks")]
+ error!(result, "no such file or directory");
#[cfg(windows)]
error!(result, 2); // ERROR_FILE_NOT_FOUND
}
let result = fs::remove_file(filename);
- #[cfg(unix)]
+ #[cfg(all(unix, not(target_os = "vxworks")))]
error!(result, "No such file or directory");
+ #[cfg(target_os = "vxworks")]
+ error!(result, "no such file or directory");
#[cfg(windows)]
error!(result, 2); // ERROR_FILE_NOT_FOUND
}
check!(fs::set_permissions(filename, fs::Permissions::from_mode(0o1777)));
let metadata1 = check!(fs::metadata(filename));
+ #[cfg(all(unix, not(target_os = "vxworks")))]
assert_eq!(mask & metadata1.permissions().mode(), 0o1777);
+ #[cfg(target_os = "vxworks")]
+ assert_eq!(mask & metadata1.permissions().mode(), 0o0777);
}
#[test]
/// #![feature(io_slice_advance)]
///
/// use std::io::IoSliceMut;
- /// use std::mem;
/// use std::ops::Deref;
///
/// let mut buf1 = [1; 8];
/// ][..];
///
/// // Mark 10 bytes as read.
- /// bufs = IoSliceMut::advance(mem::replace(&mut bufs, &mut []), 10);
+ /// bufs = IoSliceMut::advance(bufs, 10);
/// assert_eq!(bufs[0].deref(), [2; 14].as_ref());
/// assert_eq!(bufs[1].deref(), [3; 8].as_ref());
/// ```
/// #![feature(io_slice_advance)]
///
/// use std::io::IoSlice;
- /// use std::mem;
/// use std::ops::Deref;
///
- /// let mut buf1 = [1; 8];
- /// let mut buf2 = [2; 16];
- /// let mut buf3 = [3; 8];
+ /// let buf1 = [1; 8];
+ /// let buf2 = [2; 16];
+ /// let buf3 = [3; 8];
/// let mut bufs = &mut [
- /// IoSlice::new(&mut buf1),
- /// IoSlice::new(&mut buf2),
- /// IoSlice::new(&mut buf3),
+ /// IoSlice::new(&buf1),
+ /// IoSlice::new(&buf2),
+ /// IoSlice::new(&buf3),
/// ][..];
///
/// // Mark 10 bytes as written.
- /// bufs = IoSlice::advance(mem::replace(&mut bufs, &mut []), 10);
+ /// bufs = IoSlice::advance(bufs, 10);
/// assert_eq!(bufs[0].deref(), [2; 14].as_ref());
/// assert_eq!(bufs[1].deref(), [3; 8].as_ref());
#[unstable(feature = "io_slice_advance", issue = "62726")]
use crate::cmp;
use crate::io::prelude::*;
use crate::io::{self, IoSlice, IoSliceMut};
- use crate::mem;
use crate::ops::Deref;
#[test]
][..];
// Only in a single buffer..
- bufs = IoSliceMut::advance(mem::replace(&mut bufs, &mut []), 1);
+ bufs = IoSliceMut::advance(bufs, 1);
assert_eq!(bufs[0].deref(), [1; 7].as_ref());
assert_eq!(bufs[1].deref(), [2; 16].as_ref());
assert_eq!(bufs[2].deref(), [3; 8].as_ref());
// Removing a buffer, leaving others as is.
- bufs = IoSliceMut::advance(mem::replace(&mut bufs, &mut []), 7);
+ bufs = IoSliceMut::advance(bufs, 7);
assert_eq!(bufs[0].deref(), [2; 16].as_ref());
assert_eq!(bufs[1].deref(), [3; 8].as_ref());
// Removing a buffer and removing from the next buffer.
- bufs = IoSliceMut::advance(mem::replace(&mut bufs, &mut []), 18);
+ bufs = IoSliceMut::advance(bufs, 18);
assert_eq!(bufs[0].deref(), [3; 6].as_ref());
}
#[test]
fn io_slice_mut_advance_empty_slice() {
- let mut empty_bufs = &mut [][..];
+ let empty_bufs = &mut [][..];
// Shouldn't panic.
- IoSliceMut::advance(&mut empty_bufs, 1);
+ IoSliceMut::advance(empty_bufs, 1);
}
#[test]
let mut bufs = &mut [IoSliceMut::new(&mut buf1)][..];
// Going beyond the total length should be ok.
- bufs = IoSliceMut::advance(mem::replace(&mut bufs, &mut []), 9);
+ bufs = IoSliceMut::advance(bufs, 9);
assert!(bufs.is_empty());
}
#[test]
fn io_slice_advance() {
- let mut buf1 = [1; 8];
- let mut buf2 = [2; 16];
- let mut buf3 = [3; 8];
+ let buf1 = [1; 8];
+ let buf2 = [2; 16];
+ let buf3 = [3; 8];
let mut bufs =
- &mut [IoSlice::new(&mut buf1), IoSlice::new(&mut buf2), IoSlice::new(&mut buf3)][..];
+ &mut [IoSlice::new(&buf1), IoSlice::new(&buf2), IoSlice::new(&buf3)][..];
// Only in a single buffer..
- bufs = IoSlice::advance(mem::replace(&mut bufs, &mut []), 1);
+ bufs = IoSlice::advance(bufs, 1);
assert_eq!(bufs[0].deref(), [1; 7].as_ref());
assert_eq!(bufs[1].deref(), [2; 16].as_ref());
assert_eq!(bufs[2].deref(), [3; 8].as_ref());
// Removing a buffer, leaving others as is.
- bufs = IoSlice::advance(mem::replace(&mut bufs, &mut []), 7);
+ bufs = IoSlice::advance(bufs, 7);
assert_eq!(bufs[0].deref(), [2; 16].as_ref());
assert_eq!(bufs[1].deref(), [3; 8].as_ref());
// Removing a buffer and removing from the next buffer.
- bufs = IoSlice::advance(mem::replace(&mut bufs, &mut []), 18);
+ bufs = IoSlice::advance(bufs, 18);
assert_eq!(bufs[0].deref(), [3; 6].as_ref());
}
#[test]
fn io_slice_advance_empty_slice() {
- let mut empty_bufs = &mut [][..];
+ let empty_bufs = &mut [][..];
// Shouldn't panic.
- IoSlice::advance(&mut empty_bufs, 1);
+ IoSlice::advance(empty_bufs, 1);
}
#[test]
fn io_slice_advance_beyond_total_length() {
- let mut buf1 = [1; 8];
- let mut bufs = &mut [IoSlice::new(&mut buf1)][..];
+ let buf1 = [1; 8];
+ let mut bufs = &mut [IoSlice::new(&buf1)][..];
// Going beyond the total length should be ok.
- bufs = IoSlice::advance(mem::replace(&mut bufs, &mut []), 9);
+ bufs = IoSlice::advance(bufs, 9);
assert!(bufs.is_empty());
}
}
self.read_atomically(move |p| cb(p).filter(|_| p.is_eof()))
}
- // Return result of first successful parser
- fn read_or<T>(
- &mut self,
- parsers: &mut [Box<dyn FnMut(&mut Parser<'_>) -> Option<T> + 'static>],
- ) -> Option<T> {
- for pf in parsers {
- if let Some(r) = self.read_atomically(|p: &mut Parser<'_>| pf(p)) {
- return Some(r);
- }
- }
- None
- }
-
// Apply 3 parsers sequentially
fn read_seq_3<A, B, C, PA, PB, PC>(&mut self, pa: PA, pb: PB, pc: PC) -> Option<(A, B, C)>
where
}
fn read_ip_addr(&mut self) -> Option<IpAddr> {
- let ipv4_addr = |p: &mut Parser<'_>| p.read_ipv4_addr().map(IpAddr::V4);
- let ipv6_addr = |p: &mut Parser<'_>| p.read_ipv6_addr().map(IpAddr::V6);
- self.read_or(&mut [Box::new(ipv4_addr), Box::new(ipv6_addr)])
+ self.read_ipv4_addr().map(IpAddr::V4)
+ .or_else(|| self.read_ipv6_addr().map(IpAddr::V6))
}
fn read_socket_addr_v4(&mut self) -> Option<SocketAddrV4> {
}
fn read_socket_addr(&mut self) -> Option<SocketAddr> {
- let v4 = |p: &mut Parser<'_>| p.read_socket_addr_v4().map(SocketAddr::V4);
- let v6 = |p: &mut Parser<'_>| p.read_socket_addr_v6().map(SocketAddr::V6);
- self.read_or(&mut [Box::new(v4), Box::new(v6)])
+ self.read_socket_addr_v4().map(SocketAddr::V4)
+ .or_else(|| self.read_socket_addr_v6().map(SocketAddr::V6))
}
}
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/",
test(attr(deny(warnings))))]
+#![feature(bool_to_option)]
#![feature(box_syntax)]
#![feature(const_fn)]
#![feature(const_transmute)]
}
fn token_to_string_ext(token: &Token, convert_dollar_crate: bool) -> String {
- let convert_dollar_crate = if convert_dollar_crate { Some(token.span) } else { None };
+ let convert_dollar_crate = convert_dollar_crate.then_some(token.span);
token_kind_to_string_ext(&token.kind, convert_dollar_crate)
}
if let Some(candidate) = case_insensitive_match {
Some(candidate) // exact case insensitive match has a higher priority
} else {
- if let Some((candidate, _)) = levenstein_match { Some(candidate) } else { None }
+ levenstein_match.map(|(candidate, _)| candidate)
}
}
use crate::base::{self, *};
use crate::proc_macro_server;
-use syntax::ast::{self, ItemKind, MacArgs};
+use syntax::ast::{self, ItemKind, MetaItemKind, NestedMetaItem};
use syntax::errors::{Applicability, FatalError};
use syntax::symbol::sym;
use syntax::token;
if !attr.has_name(sym::derive) {
return true;
}
- if !attr.is_meta_item_list() {
- cx.struct_span_err(attr.span, "malformed `derive` attribute input")
- .span_suggestion(
- attr.span,
- "missing traits to be derived",
- "#[derive(Trait1, Trait2, ...)]".to_owned(),
- Applicability::HasPlaceholders,
- ).emit();
- return false;
- }
- let parse_derive_paths = |attr: &ast::Attribute| {
- if let MacArgs::Empty = attr.get_normal_item().args {
- return Ok(Vec::new());
+ // 1) First let's ensure that it's a meta item.
+ let nmis = match attr.meta_item_list() {
+ None => {
+ cx.struct_span_err(attr.span, "malformed `derive` attribute input")
+ .span_suggestion(
+ attr.span,
+ "missing traits to be derived",
+ "#[derive(Trait1, Trait2, ...)]".to_owned(),
+ Applicability::HasPlaceholders,
+ )
+ .emit();
+ return false;
}
- rustc_parse::parse_in_attr(cx.parse_sess, attr, |p| p.parse_derive_paths())
+ Some(x) => x,
};
- match parse_derive_paths(attr) {
- Ok(traits) => {
- result.extend(traits);
- true
- }
- Err(mut e) => {
- e.emit();
- false
- }
- }
+ let mut error_reported_filter_map = false;
+ let mut error_reported_map = false;
+ let traits = nmis
+ .into_iter()
+ // 2) Moreover, let's ensure we have a path and not `#[derive("foo")]`.
+ .filter_map(|nmi| match nmi {
+ NestedMetaItem::Literal(lit) => {
+ error_reported_filter_map = true;
+ cx.struct_span_err(lit.span, "expected path to a trait, found literal")
+ .help("for example, write `#[derive(Debug)]` for `Debug`")
+ .emit();
+ None
+ }
+ NestedMetaItem::MetaItem(mi) => Some(mi),
+ })
+ // 3) Finally, we only accept `#[derive($path_0, $path_1, ..)]`
+ // but not e.g. `#[derive($path_0 = "value", $path_1(abc))]`.
+ // In this case we can still at least determine that the user
+ // wanted this trait to be derived, so let's keep it.
+ .map(|mi| {
+ let mut traits_dont_accept = |title, action| {
+ error_reported_map = true;
+ let sp = mi.span.with_lo(mi.path.span.hi());
+ cx.struct_span_err(sp, title)
+ .span_suggestion(
+ sp,
+ action,
+ String::new(),
+ Applicability::MachineApplicable,
+ )
+ .emit();
+ };
+ match &mi.kind {
+ MetaItemKind::List(..) => traits_dont_accept(
+ "traits in `#[derive(...)]` don't accept arguments",
+ "remove the arguments",
+ ),
+ MetaItemKind::NameValue(..) => traits_dont_accept(
+ "traits in `#[derive(...)]` don't accept values",
+ "remove the value",
+ ),
+ MetaItemKind::Word => {}
+ }
+ mi.path
+ });
+
+ result.extend(traits);
+ !error_reported_filter_map && !error_reported_map
});
result
}
};
// Has a special form in Rust for numbers.
- let fill = if c_zero { Some("0") } else { None };
+ let fill = c_zero.then_some("0");
- let align = if c_left { Some("<") } else { None };
+ let align = c_left.then_some("<");
// Rust doesn't have an equivalent to the `' '` flag.
- let sign = if c_plus { Some("+") } else { None };
+ let sign = c_plus.then_some("+");
// Not *quite* the same, depending on the type...
let alt = c_alt;
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
+#![feature(bool_to_option)]
#![feature(crate_visibility_modifier)]
#![feature(decl_macro)]
#![feature(nll)]
const_indexing,
const_in_array_repeat_expressions,
const_let,
+ const_mut_refs,
const_panic,
const_raw_ptr_deref,
const_raw_ptr_to_usize_cast,
#![cfg_attr(any(unix, target_os = "cloudabi"), feature(libc))]
#![feature(rustc_private)]
#![feature(nll)]
+#![feature(bool_to_option)]
#![feature(set_stdio)]
#![feature(panic_unwind)]
#![feature(staged_api)]
None
};
- let start = if report_time {
- Some(Instant::now())
- } else {
- None
- };
+ let start = report_time.then(Instant::now);
let result = catch_unwind(AssertUnwindSafe(testfn));
let exec_time = start.map(|start| {
let duration = start.elapsed();
let args = env::args().collect::<Vec<_>>();
let current_exe = &args[0];
- let start = if report_time {
- Some(Instant::now())
- } else {
- None
- };
+ let start = report_time.then(Instant::now);
let output = match Command::new(current_exe)
.env(SECONDARY_TEST_INVOKER_VAR, desc.name.as_slice())
.output() {
}
extern "C" LLVMValueRef
-LLVMRustGetOrInsertGlobal(LLVMModuleRef M, const char *Name, LLVMTypeRef Ty) {
- return wrap(unwrap(M)->getOrInsertGlobal(Name, unwrap(Ty)));
+LLVMRustGetOrInsertGlobal(LLVMModuleRef M, const char *Name, size_t NameLen, LLVMTypeRef Ty) {
+ StringRef NameRef(Name, NameLen);
+ return wrap(unwrap(M)->getOrInsertGlobal(NameRef, unwrap(Ty)));
}
extern "C" LLVMValueRef
}
extern "C" void LLVMRustSetComdat(LLVMModuleRef M, LLVMValueRef V,
- const char *Name) {
+ const char *Name, size_t NameLen) {
Triple TargetTriple(unwrap(M)->getTargetTriple());
GlobalObject *GV = unwrap<GlobalObject>(V);
if (!TargetTriple.isOSBinFormatMachO()) {
- GV->setComdat(unwrap(M)->getOrInsertComdat(Name));
+ StringRef NameRef(Name, NameLen);
+ GV->setComdat(unwrap(M)->getOrInsertComdat(NameRef));
}
}
--- /dev/null
+// compile-flags: -C opt-level=0
+#![crate_type = "lib"]
+
+pub enum ApiError {}
+#[allow(dead_code)]
+pub struct TokioError {
+ b: bool,
+}
+pub enum Error {
+ Api {
+ source: ApiError,
+ },
+ Ethereum,
+ Tokio {
+ source: TokioError,
+ },
+}
+struct Api;
+impl IntoError<Error> for Api
+{
+ type Source = ApiError;
+ // CHECK-LABEL: @into_error
+ // CHECK: llvm.trap()
+ // Also check the next two instructions to make sure we do not match against `trap`
+ // elsewhere in the code.
+ // CHECK-NEXT: load
+ // CHECK-NEXT: ret
+ #[no_mangle]
+ fn into_error(self, error: Self::Source) -> Error {
+ Error::Api {
+ source: (|v| v)(error),
+ }
+ }
+}
+
+pub trait IntoError<E>
+{
+ /// The underlying error
+ type Source;
+
+ /// Combine the information to produce the error
+ fn into_error(self, source: Self::Source) -> E;
+}
let mut sum = 0;
for i in 0..x {
//~^ ERROR E0015
- //~| ERROR E0017
+ //~| ERROR E0658
//~| ERROR E0080
//~| ERROR E0744
//~| ERROR E0019
--- /dev/null
+// revisions: rpass cfail
+
+enum A {
+ //[cfail]~^ ERROR 3:1: 3:7: recursive type `A` has infinite size [E0072]
+ B(C),
+}
+
+#[cfg(rpass)]
+struct C(Box<A>);
+
+#[cfg(cfail)]
+struct C(A);
+//[cfail]~^ ERROR 12:1: 12:13: recursive type `C` has infinite size [E0072]
+
+fn main() {}
--- /dev/null
+// This previously triggered an ICE.
+
+pub(in crate::r#mod) fn main() {}
+//~^ ERROR expected module, found unresolved item
--- /dev/null
+error[E0577]: expected module, found unresolved item `crate::r#mod`
+ --> $DIR/issue-61732.rs:3:8
+ |
+LL | pub(in crate::r#mod) fn main() {}
+ | ^^^^^^^^^^^^ not a module
+
+error: Compilation failed, aborting rustdoc
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0577`.
--- /dev/null
+#![crate_name = "foo"]
+#![feature(doc_cfg)]
+
+// @has 'foo/index.html'
+// @!has '-' '//*[@class="stab portability"]' 'feature="sync" and'
+// @has '-' '//*[@class="stab portability"]' 'feature="sync"'
+#[doc(cfg(feature = "sync"))]
+#[doc(cfg(feature = "sync"))]
+pub struct Foo;
+
+#[doc(cfg(feature = "sync"))]
+pub mod bar {
+ #[doc(cfg(feature = "sync"))]
+ pub struct Bar;
+}
//~| SUGGESTION x.await
}
+async fn dummy() {}
+
+#[allow(unused)]
+async fn suggest_await_in_async_fn_return() {
+ dummy().await;
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP try adding a semicolon
+ //~| HELP consider using `.await` here
+ //~| SUGGESTION dummy().await
+}
+
fn main() {}
//~| SUGGESTION x.await
}
+async fn dummy() {}
+
+#[allow(unused)]
+async fn suggest_await_in_async_fn_return() {
+ dummy()
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP try adding a semicolon
+ //~| HELP consider using `.await` here
+ //~| SUGGESTION dummy().await
+}
+
fn main() {}
= note: expected type `u32`
found opaque type `impl std::future::Future`
-error: aborting due to previous error
+error[E0308]: mismatched types
+ --> $DIR/suggest-missing-await.rs:23:5
+ |
+LL | dummy()
+ | ^^^^^^^ expected `()`, found opaque type
+ |
+ = note: expected unit type `()`
+ found opaque type `impl std::future::Future`
+help: try adding a semicolon
+ |
+LL | dummy();
+ | ^
+help: consider using `.await` here
+ |
+LL | dummy().await
+ |
+
+error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0308`.
-error[E0017]: references in statics may only refer to immutable values
+error[E0658]: references in statics may only refer to immutable values
--> $DIR/check-static-immutable-mut-slices.rs:3:37
|
LL | static TEST: &'static mut [isize] = &mut [];
| ^^^^^^^ statics require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
error: aborting due to previous error
-For more information about this error, try `rustc --explain E0017`.
+For more information about this error, try `rustc --explain E0658`.
// Parse `cfg_attr` with varying numbers of attributes and trailing commas
// Completely empty `cfg_attr` input
-#[cfg_attr()] //~ error: expected identifier, found `)`
+#[cfg_attr()] //~ error: malformed `cfg_attr` attribute input
struct NoConfigurationPredicate;
// Zero attributes, zero trailing comma (comma manatory here)
-#[cfg_attr(all())] //~ error: expected `,`, found `)`
+#[cfg_attr(all())] //~ error: expected `,`, found end of `cfg_attr`
struct A0C0;
// Zero attributes, one trailing comma
#[cfg_attr(all(), must_use, deprecated,,)] //~ ERROR expected identifier
struct A2C2;
+// Wrong delimiter `[`
+#[cfg_attr[all(),,]]
+//~^ ERROR wrong `cfg_attr` delimiters
+//~| ERROR expected identifier, found `,`
+struct BracketZero;
+
+// Wrong delimiter `{`
+#[cfg_attr{all(),,}]
+//~^ ERROR wrong `cfg_attr` delimiters
+//~| ERROR expected identifier, found `,`
+struct BraceZero;
+
fn main() {}
-error: expected identifier, found `)`
- --> $DIR/cfg-attr-parse.rs:4:12
+error: malformed `cfg_attr` attribute input
+ --> $DIR/cfg-attr-parse.rs:4:1
|
LL | #[cfg_attr()]
- | ^ expected identifier
+ | ^^^^^^^^^^^^^ help: missing condition and attribute: `#[cfg_attr(condition, attribute, other_attribute, ...)]`
+ |
+ = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
-error: expected `,`, found `)`
+error: expected `,`, found end of `cfg_attr` input
--> $DIR/cfg-attr-parse.rs:8:17
|
LL | #[cfg_attr(all())]
| ^ expected `,`
+ |
+ = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]`
+ = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
error: expected identifier, found `,`
--> $DIR/cfg-attr-parse.rs:16:18
|
LL | #[cfg_attr(all(),,)]
| ^ expected identifier
+ |
+ = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]`
+ = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
error: expected identifier, found `,`
--> $DIR/cfg-attr-parse.rs:28:28
|
LL | #[cfg_attr(all(), must_use,,)]
| ^ expected identifier
+ |
+ = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]`
+ = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
error: expected identifier, found `,`
--> $DIR/cfg-attr-parse.rs:40:40
|
LL | #[cfg_attr(all(), must_use, deprecated,,)]
| ^ expected identifier
+ |
+ = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]`
+ = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
+
+error: wrong `cfg_attr` delimiters
+ --> $DIR/cfg-attr-parse.rs:44:11
+ |
+LL | #[cfg_attr[all(),,]]
+ | ^^^^^^^^^
+ |
+help: the delimiters should be `(` and `)`
+ |
+LL | #[cfg_attr(all(),,)]
+ | ^ ^
+
+error: expected identifier, found `,`
+ --> $DIR/cfg-attr-parse.rs:44:18
+ |
+LL | #[cfg_attr[all(),,]]
+ | ^ expected identifier
+ |
+ = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]`
+ = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
+
+error: wrong `cfg_attr` delimiters
+ --> $DIR/cfg-attr-parse.rs:50:11
+ |
+LL | #[cfg_attr{all(),,}]
+ | ^^^^^^^^^
+ |
+help: the delimiters should be `(` and `)`
+ |
+LL | #[cfg_attr(all(),,)]
+ | ^ ^
+
+error: expected identifier, found `,`
+ --> $DIR/cfg-attr-parse.rs:50:18
+ |
+LL | #[cfg_attr{all(),,}]
+ | ^ expected identifier
+ |
+ = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]`
+ = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
-error: aborting due to 5 previous errors
+error: aborting due to 9 previous errors
-error[E0017]: references in constants may only refer to immutable values
+error[E0658]: references in constants may only refer to immutable values
--> $DIR/issue-65394.rs:8:13
|
LL | let r = &mut x;
| ^^^^^^ constants require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
error[E0493]: destructors cannot be evaluated at compile-time
--> $DIR/issue-65394.rs:7:9
error: aborting due to 2 previous errors
-Some errors have detailed explanations: E0017, E0493.
-For more information about an error, try `rustc --explain E0017`.
+Some errors have detailed explanations: E0493, E0658.
+For more information about an error, try `rustc --explain E0493`.
-error[E0017]: references in constants may only refer to immutable values
+error[E0658]: references in constants may only refer to immutable values
--> $DIR/const-multi-ref.rs:6:13
|
LL | let p = &mut a;
| ^^^^^^ constants require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
--> $DIR/const-multi-ref.rs:16:13
error: aborting due to 2 previous errors
-Some errors have detailed explanations: E0017, E0492.
-For more information about an error, try `rustc --explain E0017`.
+Some errors have detailed explanations: E0492, E0658.
+For more information about an error, try `rustc --explain E0492`.
--- /dev/null
+// run-pass
+
+#![feature(const_mut_refs)]
+
+struct Foo {
+ x: usize
+}
+
+const fn foo() -> Foo {
+ Foo { x: 0 }
+}
+
+impl Foo {
+ const fn bar(&mut self) -> usize {
+ self.x = 1;
+ self.x
+ }
+
+}
+
+const fn baz(foo: &mut Foo) -> usize {
+ let x = &mut foo.x;
+ *x = 2;
+ *x
+}
+
+const fn bazz(foo: &mut Foo) -> usize {
+ foo.x = 3;
+ foo.x
+}
+
+fn main() {
+ let _: [(); foo().bar()] = [(); 1];
+ let _: [(); baz(&mut foo())] = [(); 2];
+ let _: [(); bazz(&mut foo())] = [(); 3];
+}
--- /dev/null
+fn main() {
+ foo(&mut 5);
+}
+
+const fn foo(x: &mut i32) -> i32 { //~ ERROR mutable references in const fn are unstable
+ *x + 1
+}
--- /dev/null
+error[E0723]: mutable references in const fn are unstable
+ --> $DIR/feature-gate-const_mut_refs.rs:5:14
+ |
+LL | const fn foo(x: &mut i32) -> i32 {
+ | ^
+ |
+ = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
+ = help: add `#![feature(const_fn)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0723`.
LL | self.state = x;
| ^^^^^^^^^^^^^^
-error[E0017]: references in constants may only refer to immutable values
+error[E0658]: references in constants may only refer to immutable values
--> $DIR/const_let_assign3.rs:16:5
|
LL | s.foo(3);
| ^ constants require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
-error[E0017]: references in constants may only refer to immutable values
+error[E0658]: references in constants may only refer to immutable values
--> $DIR/const_let_assign3.rs:22:13
|
LL | let y = &mut x;
| ^^^^^^ constants require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
error[E0019]: constant contains unimplemented expression type
--> $DIR/const_let_assign3.rs:24:5
error: aborting due to 4 previous errors
-Some errors have detailed explanations: E0017, E0019.
-For more information about an error, try `rustc --explain E0017`.
+Some errors have detailed explanations: E0019, E0658.
+For more information about an error, try `rustc --explain E0019`.
// compile-flags: -Zunleash-the-miri-inside-of-you
#![feature(const_raw_ptr_deref)]
+#![feature(const_mut_refs)]
#![deny(const_err)]
use std::cell::UnsafeCell;
const MUTATING_BEHIND_RAW: () = {
// Test that `MUTABLE_BEHIND_RAW` is actually immutable, by doing this at const time.
unsafe {
- *MUTABLE_BEHIND_RAW = 99 //~ WARN skipping const checks
- //~^ ERROR any use of this value will cause an error
- //~^^ tried to modify constant memory
+ *MUTABLE_BEHIND_RAW = 99 //~ ERROR any use of this value will cause an error
}
};
warning: skipping const checks
- --> $DIR/mutable_const.rs:9:38
+ --> $DIR/mutable_const.rs:10:38
|
LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
| ^^^^^^^^^^^^^^^^^^^^
-warning: skipping const checks
- --> $DIR/mutable_const.rs:15:9
- |
-LL | *MUTABLE_BEHIND_RAW = 99
- | ^^^^^^^^^^^^^^^^^^^^^^^^
-
error: any use of this value will cause an error
- --> $DIR/mutable_const.rs:15:9
+ --> $DIR/mutable_const.rs:16:9
|
LL | / const MUTATING_BEHIND_RAW: () = {
LL | | // Test that `MUTABLE_BEHIND_RAW` is actually immutable, by doing this at const time.
LL | | unsafe {
LL | | *MUTABLE_BEHIND_RAW = 99
| | ^^^^^^^^^^^^^^^^^^^^^^^^ tried to modify constant memory
-... |
LL | | }
LL | | };
| |__-
|
note: lint level defined here
- --> $DIR/mutable_const.rs:4:9
+ --> $DIR/mutable_const.rs:5:9
|
LL | #![deny(const_err)]
| ^^^^^^^^^
// compile-flags: -Zunleash-the-miri-inside-of-you
+#![feature(const_mut_refs)]
#![allow(const_err)]
use std::cell::UnsafeCell;
// a test demonstrating what things we could allow with a smarter const qualification
+// this is fine because is not possible to mutate through an immutable reference.
static FOO: &&mut u32 = &&mut 42;
-//~^ WARN: skipping const checks
+// this is fine because accessing an immutable static `BAR` is equivalent to accessing `*&BAR`
+// which puts the mutable reference behind an immutable one.
static BAR: &mut () = &mut ();
-//~^ WARN: skipping const checks
struct Foo<T>(T);
+// this is fine for the same reason as `BAR`.
static BOO: &mut Foo<()> = &mut Foo(());
-//~^ WARN: skipping const checks
struct Meh {
x: &'static UnsafeCell<i32>,
//~^ WARN: skipping const checks
};
+// this is fine for the same reason as `BAR`.
static OH_YES: &mut i32 = &mut 42;
-//~^ WARN: skipping const checks
fn main() {
unsafe {
warning: skipping const checks
- --> $DIR/mutable_references.rs:8:26
- |
-LL | static FOO: &&mut u32 = &&mut 42;
- | ^^^^^^^
-
-warning: skipping const checks
- --> $DIR/mutable_references.rs:11:23
- |
-LL | static BAR: &mut () = &mut ();
- | ^^^^^^^
-
-warning: skipping const checks
- --> $DIR/mutable_references.rs:16:28
- |
-LL | static BOO: &mut Foo<()> = &mut Foo(());
- | ^^^^^^^^^^^^
-
-warning: skipping const checks
- --> $DIR/mutable_references.rs:26:8
+ --> $DIR/mutable_references.rs:28:8
|
LL | x: &UnsafeCell::new(42),
| ^^^^^^^^^^^^^^^^^^^^
-warning: skipping const checks
- --> $DIR/mutable_references.rs:30:27
- |
-LL | static OH_YES: &mut i32 = &mut 42;
- | ^^^^^^^
-
error[E0594]: cannot assign to `*OH_YES`, as `OH_YES` is an immutable static item
- --> $DIR/mutable_references.rs:37:5
+ --> $DIR/mutable_references.rs:39:5
|
LL | *OH_YES = 99;
| ^^^^^^^^^^^^ cannot assign
--- /dev/null
+// run-pass
+// compile-flags: -Zunleash-the-miri-inside-of-you
+#![feature(const_mut_refs)]
+#![allow(const_err)]
+
+static OH_YES: &mut i32 = &mut 42;
+
+fn main() {
+ // Make sure `OH_YES` can be read.
+ assert_eq!(*OH_YES, 42);
+}
--- /dev/null
+error[E0658]: dereferencing raw pointers in constants is unstable
+ --> $DIR/projection_qualif.rs:11:18
+ |
+LL | unsafe { *b = 5; }
+ | ^^^^^^
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/51911
+ = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
+// revisions: stock mut_refs
+
+#![cfg_attr(mut_refs, feature(const_mut_refs))]
+
use std::cell::Cell;
const FOO: &u32 = {
let mut a = 42;
{
- let b: *mut u32 = &mut a; //~ ERROR may only refer to immutable values
+ let b: *mut u32 = &mut a; //[stock]~ ERROR may only refer to immutable values
unsafe { *b = 5; } //~ ERROR dereferencing raw pointers in constants
- //~^ contains unimplemented expression
+ //[stock]~^ contains unimplemented expression
}
&{a}
};
+++ /dev/null
-error[E0017]: references in constants may only refer to immutable values
- --> $DIR/projection_qualif.rs:6:27
- |
-LL | let b: *mut u32 = &mut a;
- | ^^^^^^ constants require immutable values
-
-error[E0658]: dereferencing raw pointers in constants is unstable
- --> $DIR/projection_qualif.rs:7:18
- |
-LL | unsafe { *b = 5; }
- | ^^^^^^
- |
- = note: for more information, see https://github.com/rust-lang/rust/issues/51911
- = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable
-
-error[E0019]: constant contains unimplemented expression type
- --> $DIR/projection_qualif.rs:7:18
- |
-LL | unsafe { *b = 5; }
- | ^^^^^^
-
-error: aborting due to 3 previous errors
-
-Some errors have detailed explanations: E0017, E0019, E0658.
-For more information about an error, try `rustc --explain E0017`.
--- /dev/null
+error[E0658]: references in constants may only refer to immutable values
+ --> $DIR/projection_qualif.rs:10:27
+ |
+LL | let b: *mut u32 = &mut a;
+ | ^^^^^^ constants require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0658]: dereferencing raw pointers in constants is unstable
+ --> $DIR/projection_qualif.rs:11:18
+ |
+LL | unsafe { *b = 5; }
+ | ^^^^^^
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/51911
+ = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable
+
+error[E0019]: constant contains unimplemented expression type
+ --> $DIR/projection_qualif.rs:11:18
+ |
+LL | unsafe { *b = 5; }
+ | ^^^^^^
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0019, E0658.
+For more information about an error, try `rustc --explain E0019`.
--- /dev/null
+error[E0080]: could not evaluate static initializer
+ --> $DIR/static_mut_containing_mut_ref2.rs:7:45
+ |
+LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tried to modify a static's initial value from another static's initializer
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
+// revisions: stock mut_refs
+
+#![cfg_attr(mut_refs, feature(const_mut_refs))]
+
static mut STDERR_BUFFER_SPACE: u8 = 0;
pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
-//~^ ERROR references in statics may only refer to immutable values
-//~| ERROR static contains unimplemented expression type
+//[mut_refs]~^ ERROR could not evaluate static initializer
+//[stock]~^^ ERROR references in statics may only refer to immutable values
+//[stock]~| ERROR static contains unimplemented expression type
fn main() {}
+++ /dev/null
-error[E0017]: references in statics may only refer to immutable values
- --> $DIR/static_mut_containing_mut_ref2.rs:3:46
- |
-LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^ statics require immutable values
-
-error[E0019]: static contains unimplemented expression type
- --> $DIR/static_mut_containing_mut_ref2.rs:3:45
- |
-LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0017, E0019.
-For more information about an error, try `rustc --explain E0017`.
--- /dev/null
+error[E0658]: references in statics may only refer to immutable values
+ --> $DIR/static_mut_containing_mut_ref2.rs:7:46
+ |
+LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ statics require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0019]: static contains unimplemented expression type
+ --> $DIR/static_mut_containing_mut_ref2.rs:7:45
+ |
+LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0019, E0658.
+For more information about an error, try `rustc --explain E0019`.
--- /dev/null
+// This test checks that the union keyword
+// is accepted as the name of an enum variant
+// when not followed by an identifier
+// This special case exists because `union` is a contextual keyword.
+
+#![allow(warnings)]
+
+// check-pass
+
+enum A { union }
+enum B { union {} }
+enum C { union() }
+fn main(){}
const C: i32 = 2;
static mut M: i32 = 3;
-const CR: &'static mut i32 = &mut C; //~ ERROR E0017
-static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017
+const CR: &'static mut i32 = &mut C; //~ ERROR E0658
+static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0658
//~| ERROR E0019
//~| ERROR cannot borrow
-static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0017
-static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M }; //~ ERROR E0017
+static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0658
+static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M }; //~ ERROR E0658
fn main() {}
-error[E0017]: references in constants may only refer to immutable values
+error[E0658]: references in constants may only refer to immutable values
--> $DIR/E0017.rs:5:30
|
LL | const CR: &'static mut i32 = &mut C;
| ^^^^^^ constants require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
error[E0019]: static contains unimplemented expression type
--> $DIR/E0017.rs:6:39
LL | static STATIC_REF: &'static mut i32 = &mut X;
| ^^^^^^
-error[E0017]: references in statics may only refer to immutable values
+error[E0658]: references in statics may only refer to immutable values
--> $DIR/E0017.rs:6:39
|
LL | static STATIC_REF: &'static mut i32 = &mut X;
| ^^^^^^ statics require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
error[E0596]: cannot borrow immutable static item `X` as mutable
--> $DIR/E0017.rs:6:39
LL | static STATIC_REF: &'static mut i32 = &mut X;
| ^^^^^^ cannot borrow as mutable
-error[E0017]: references in statics may only refer to immutable values
+error[E0658]: references in statics may only refer to immutable values
--> $DIR/E0017.rs:9:38
|
LL | static CONST_REF: &'static mut i32 = &mut C;
| ^^^^^^ statics require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
-error[E0017]: references in statics may only refer to immutable values
+error[E0658]: references in statics may only refer to immutable values
--> $DIR/E0017.rs:10:52
|
LL | static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M };
| ^^^^^^ statics require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
error: aborting due to 6 previous errors
-Some errors have detailed explanations: E0017, E0019, E0596.
-For more information about an error, try `rustc --explain E0017`.
+Some errors have detailed explanations: E0019, E0596, E0658.
+For more information about an error, try `rustc --explain E0019`.
--- /dev/null
+static X: i32 = 1;
+const C: i32 = 2;
+
+const CR: &'static mut i32 = &mut C; //~ ERROR E0658
+static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0658
+ //~| ERROR cannot borrow
+ //~| ERROR E0019
+static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0658
+
+fn main() {}
--- /dev/null
+error[E0658]: references in constants may only refer to immutable values
+ --> $DIR/E0388.rs:4:30
+ |
+LL | const CR: &'static mut i32 = &mut C;
+ | ^^^^^^ constants require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0019]: static contains unimplemented expression type
+ --> $DIR/E0388.rs:5:39
+ |
+LL | static STATIC_REF: &'static mut i32 = &mut X;
+ | ^^^^^^
+
+error[E0658]: references in statics may only refer to immutable values
+ --> $DIR/E0388.rs:5:39
+ |
+LL | static STATIC_REF: &'static mut i32 = &mut X;
+ | ^^^^^^ statics require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0596]: cannot borrow immutable static item `X` as mutable
+ --> $DIR/E0388.rs:5:39
+ |
+LL | static STATIC_REF: &'static mut i32 = &mut X;
+ | ^^^^^^ cannot borrow as mutable
+
+error[E0658]: references in statics may only refer to immutable values
+ --> $DIR/E0388.rs:8:38
+ |
+LL | static CONST_REF: &'static mut i32 = &mut C;
+ | ^^^^^^ statics require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0019, E0596, E0658.
+For more information about an error, try `rustc --explain E0019`.
LL | fn bar(x: usize) -> Option<usize> {
| ------------- expected `std::option::Option<usize>` because of return type
LL | return x;
- | ^ expected enum `std::option::Option`, found `usize`
+ | ^
+ | |
+ | expected enum `std::option::Option`, found `usize`
+ | help: try using a variant of the expected enum: `Some(x)`
|
= note: expected enum `std::option::Option<usize>`
found type `usize`
-error[E0017]: references in constants may only refer to immutable values
+error[E0658]: references in constants may only refer to immutable values
--> $DIR/issue-17718-const-bad-values.rs:1:34
|
LL | const C1: &'static mut [usize] = &mut [];
| ^^^^^^^ constants require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
error[E0013]: constants cannot refer to statics, use a constant instead
--> $DIR/issue-17718-const-bad-values.rs:5:46
LL | const C2: &'static mut usize = unsafe { &mut S };
| ^
-error[E0017]: references in constants may only refer to immutable values
+error[E0658]: references in constants may only refer to immutable values
--> $DIR/issue-17718-const-bad-values.rs:5:41
|
LL | const C2: &'static mut usize = unsafe { &mut S };
| ^^^^^^ constants require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
error: aborting due to 3 previous errors
-Some errors have detailed explanations: E0013, E0017.
+Some errors have detailed explanations: E0013, E0658.
For more information about an error, try `rustc --explain E0013`.
-static buf: &mut [u8] = &mut [1u8,2,3,4,5,7]; //~ ERROR E0017
+static buf: &mut [u8] = &mut [1u8,2,3,4,5,7]; //~ ERROR E0658
fn write<T: AsRef<[u8]>>(buffer: T) { }
fn main() {
-error[E0017]: references in statics may only refer to immutable values
+error[E0658]: references in statics may only refer to immutable values
--> $DIR/issue-46604.rs:1:25
|
LL | static buf: &mut [u8] = &mut [1u8,2,3,4,5,7];
| ^^^^^^^^^^^^^^^^^^^^ statics require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
error[E0594]: cannot assign to `buf[_]`, as `buf` is an immutable static item
--> $DIR/issue-46604.rs:6:5
error: aborting due to 2 previous errors
-Some errors have detailed explanations: E0017, E0594.
-For more information about an error, try `rustc --explain E0017`.
+Some errors have detailed explanations: E0594, E0658.
+For more information about an error, try `rustc --explain E0594`.
--> $DIR/issue-51632-try-desugar-incompatible-types.rs:8:5
|
LL | missing_discourses()?
- | ^^^^^^^^^^^^^^^^^^^^-
- | | |
- | | help: try removing this `?`
- | expected enum `std::result::Result`, found `isize`
+ | ^^^^^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found `isize`
|
= note: expected enum `std::result::Result<isize, ()>`
found type `isize`
+help: try removing this `?`
+ |
+LL | missing_discourses()
+ | --
+help: try using a variant of the expected enum
+ |
+LL | Ok(missing_discourses()?)
+ |
error: aborting due to previous error
// run-rustfix
+// ignore-test
+//
+// FIXME: Re-enable this test once we support choosing
+// between multiple mutually exclusive suggestions for the same span
#![allow(warnings)]
--> $DIR/issue-59756.rs:13:5
|
LL | foo()?
- | ^^^^^-
- | | |
- | | help: try removing this `?`
- | expected enum `std::result::Result`, found struct `A`
+ | ^^^^^^ expected enum `std::result::Result`, found struct `A`
|
= note: expected enum `std::result::Result<A, B>`
found struct `A`
+help: try removing this `?`
+ |
+LL | foo()
+ | --
+help: try using a variant of the expected enum
+ |
+LL | Ok(foo()?)
+ |
error: aborting due to previous error
-#[derive(Copy(Bad))] //~ ERROR expected one of `)`, `,`, or `::`, found `(`
+#[derive(Copy(Bad))]
+//~^ ERROR traits in `#[derive(...)]` don't accept arguments
+//~| ERROR the trait bound
struct Test1;
-#[derive(Copy="bad")] //~ ERROR expected one of `)`, `,`, or `::`, found `=`
+#[derive(Copy="bad")]
+//~^ ERROR traits in `#[derive(...)]` don't accept values
+//~| ERROR the trait bound
struct Test2;
#[derive] //~ ERROR malformed `derive` attribute input
-error: expected one of `)`, `,`, or `::`, found `(`
+error: traits in `#[derive(...)]` don't accept arguments
--> $DIR/malformed-derive-entry.rs:1:14
|
LL | #[derive(Copy(Bad))]
- | ^ expected one of `)`, `,`, or `::`
+ | ^^^^^ help: remove the arguments
-error: expected one of `)`, `,`, or `::`, found `=`
- --> $DIR/malformed-derive-entry.rs:4:14
+error: traits in `#[derive(...)]` don't accept values
+ --> $DIR/malformed-derive-entry.rs:6:14
|
LL | #[derive(Copy="bad")]
- | ^ expected one of `)`, `,`, or `::`
+ | ^^^^^^ help: remove the value
error: malformed `derive` attribute input
- --> $DIR/malformed-derive-entry.rs:7:1
+ --> $DIR/malformed-derive-entry.rs:11:1
|
LL | #[derive]
| ^^^^^^^^^ help: missing traits to be derived: `#[derive(Trait1, Trait2, ...)]`
-error: aborting due to 3 previous errors
+error[E0277]: the trait bound `Test1: std::clone::Clone` is not satisfied
+ --> $DIR/malformed-derive-entry.rs:1:10
+ |
+LL | #[derive(Copy(Bad))]
+ | ^^^^ the trait `std::clone::Clone` is not implemented for `Test1`
+
+error[E0277]: the trait bound `Test2: std::clone::Clone` is not satisfied
+ --> $DIR/malformed-derive-entry.rs:6:10
+ |
+LL | #[derive(Copy="bad")]
+ | ^^^^ the trait `std::clone::Clone` is not implemented for `Test2`
+
+error: aborting due to 5 previous errors
+For more information about this error, try `rustc --explain E0277`.
--- /dev/null
+fn main() {}
+
+#[allow { foo_lint } ]
+//~^ ERROR wrong meta list delimiters
+//~| HELP the delimiters should be `(` and `)`
+fn delim_brace() {}
+
+#[allow [ foo_lint ] ]
+//~^ ERROR wrong meta list delimiters
+//~| HELP the delimiters should be `(` and `)`
+fn delim_bracket() {}
--- /dev/null
+error: wrong meta list delimiters
+ --> $DIR/malformed-meta-delim.rs:3:9
+ |
+LL | #[allow { foo_lint } ]
+ | ^^^^^^^^^^^^
+ |
+help: the delimiters should be `(` and `)`
+ |
+LL | #[allow ( foo_lint ) ]
+ | ^ ^
+
+error: wrong meta list delimiters
+ --> $DIR/malformed-meta-delim.rs:8:9
+ |
+LL | #[allow [ foo_lint ] ]
+ | ^^^^^^^^^^^^
+ |
+help: the delimiters should be `(` and `)`
+ |
+LL | #[allow ( foo_lint ) ]
+ | ^ ^
+
+error: aborting due to 2 previous errors
+
#[cfg_attr] //~ ERROR malformed `cfg_attr` attribute
struct S1;
-#[cfg_attr = ""] //~ ERROR expected `(`, found `=`
+#[cfg_attr = ""] //~ ERROR malformed `cfg_attr` attribute
struct S2;
#[derive] //~ ERROR malformed `derive` attribute
|
= note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
-error: expected `(`, found `=`
- --> $DIR/malformed-special-attrs.rs:4:12
+error: malformed `cfg_attr` attribute input
+ --> $DIR/malformed-special-attrs.rs:4:1
|
LL | #[cfg_attr = ""]
- | ^ expected `(`
+ | ^^^^^^^^^^^^^^^^ help: missing condition and attribute: `#[cfg_attr(condition, attribute, other_attribute, ...)]`
+ |
+ = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
error: malformed `derive` attribute input
--> $DIR/malformed-special-attrs.rs:7:1
LL | fn b() -> Option<Foo> {
| ----------- expected `std::option::Option<Foo>` because of return type
LL | Foo { bar: 1 }
- | ^^^^^^^^^^^^^^ expected enum `std::option::Option`, found struct `Foo`
+ | ^^^^^^^^^^^^^^
+ | |
+ | expected enum `std::option::Option`, found struct `Foo`
+ | help: try using a variant of the expected enum: `Some(Foo { bar: 1 })`
|
= note: expected enum `std::option::Option<Foo>`
found struct `Foo`
LL | fn c() -> Result<Foo, Bar> {
| ---------------- expected `std::result::Result<Foo, Bar>` because of return type
LL | Foo { bar: 1 }
- | ^^^^^^^^^^^^^^ expected enum `std::result::Result`, found struct `Foo`
+ | ^^^^^^^^^^^^^^
+ | |
+ | expected enum `std::result::Result`, found struct `Foo`
+ | help: try using a variant of the expected enum: `Ok(Foo { bar: 1 })`
|
= note: expected enum `std::result::Result<Foo, Bar>`
found struct `Foo`
#[rustc_on_unimplemented(
message="the message"
- label="the label" //~ ERROR expected one of `)` or `,`, found `label`
+ label="the label" //~ ERROR expected `,`, found `label`
)]
trait T {}
-error: expected one of `)` or `,`, found `label`
+error: expected `,`, found `label`
--> $DIR/expected-comma-found-token.rs:9:5
|
LL | message="the message"
- | -
- | |
- | expected one of `)` or `,`
- | help: missing `,`
+ | - expected `,`
LL | label="the label"
| ^^^^^ unexpected token
LL | match x {
LL | Some(x) => { return x },
| ^ expected `usize`, found `isize`
+ |
+help: you can convert an `isize` to `usize` and panic if the converted value wouldn't fit
+ |
+LL | Some(x) => { return x.try_into().unwrap() },
+ | ^^^^^^^^^^^^^^^^^^^^^
error[E0308]: mismatched types
--> $DIR/span-preservation.rs:33:22
foo::<T>!(); //~ ERROR generic arguments in macro path
foo::<>!(); //~ ERROR generic arguments in macro path
m!(Default<>); //~ ERROR generic arguments in macro path
- //~^ ERROR unexpected generic arguments in path
}
LL | foo::<>!();
| ^^
-error: unexpected generic arguments in path
- --> $DIR/macro-ty-params.rs:12:8
- |
-LL | m!(Default<>);
- | ^^^^^^^^^
-
error: generic arguments in macro path
--> $DIR/macro-ty-params.rs:12:15
|
LL | m!(Default<>);
| ^^
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
| ----- ^^^ expected `isize`, found `usize`
| |
| expected `isize` because of return type
+ |
+help: you can convert an `usize` to `isize` and panic if the converted value wouldn't fit
+ |
+LL | fn f() -> isize { return g().try_into().unwrap(); }
+ | ^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
| ----- ^ expected `usize`, found `isize`
| |
| expected `usize` because of return type
+ |
+help: you can convert an `isize` to `usize` and panic if the converted value wouldn't fit
+ |
+LL | fn mk_int() -> usize { let i: isize = 3; return i.try_into().unwrap(); }
+ | ^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error