mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-03 05:27:36 +00:00
Auto merge of #67560 - Centril:rollup-fzdpu9c, r=Centril
Rollup of 8 pull requests Successful merges: - #67233 (Add PartialEq and Eq to Cursor) - #67466 (Require const stability attributes on intrinsics to be able to use them in constant contexts) - #67507 (Remove mem::uninitalized from tests) - #67527 (Results show too much) - #67536 (Move `{hir::lowering -> hir}::is_range_literal`) - #67538 (Improve diagnostics for invalid assignment) - #67546 (Fix ICE in mir interpretation) - #67559 (Document that calling Drop, even after it panics, is UB) Failed merges: r? @ghost
This commit is contained in:
commit
9ae6cedb8d
@ -1,6 +1,22 @@
|
|||||||
//! Compiler intrinsics.
|
//! Compiler intrinsics.
|
||||||
//!
|
//!
|
||||||
//! The corresponding definitions are in `librustc_codegen_llvm/intrinsic.rs`.
|
//! The corresponding definitions are in `librustc_codegen_llvm/intrinsic.rs`.
|
||||||
|
//! The corresponding const implementations are in `librustc_mir/interpret/intrinsics.rs`
|
||||||
|
//!
|
||||||
|
//! # Const intrinsics
|
||||||
|
//!
|
||||||
|
//! Note: any changes to the constness of intrinsics should be discussed with the language team.
|
||||||
|
//! This includes changes in the stability of the constness.
|
||||||
|
//!
|
||||||
|
//! In order to make an intrinsic usable at compile-time, one needs to copy the implementation
|
||||||
|
//! from https://github.com/rust-lang/miri/blob/master/src/shims/intrinsics.rs to
|
||||||
|
//! `librustc_mir/interpret/intrinsics.rs` and add a
|
||||||
|
//! `#[rustc_const_unstable(feature = "foo", issue = "01234")]` to the intrinsic.
|
||||||
|
//!
|
||||||
|
//! If an intrinsic is supposed to be used from a `const fn` with a `rustc_const_stable` attribute,
|
||||||
|
//! the intrinsic's attribute must be `rustc_const_stable`, too. Such a change should not be done
|
||||||
|
//! without T-lang consulation, because it bakes a feature into the language that cannot be
|
||||||
|
//! replicated in user code without compiler support.
|
||||||
//!
|
//!
|
||||||
//! # Volatiles
|
//! # Volatiles
|
||||||
//!
|
//!
|
||||||
@ -671,6 +687,7 @@ extern "rust-intrinsic" {
|
|||||||
///
|
///
|
||||||
/// The stabilized version of this intrinsic is
|
/// The stabilized version of this intrinsic is
|
||||||
/// [`std::mem::size_of`](../../std/mem/fn.size_of.html).
|
/// [`std::mem::size_of`](../../std/mem/fn.size_of.html).
|
||||||
|
#[rustc_const_stable(feature = "const_size_of", since = "1.40.0")]
|
||||||
pub fn size_of<T>() -> usize;
|
pub fn size_of<T>() -> usize;
|
||||||
|
|
||||||
/// Moves a value to an uninitialized memory location.
|
/// Moves a value to an uninitialized memory location.
|
||||||
@ -678,7 +695,9 @@ extern "rust-intrinsic" {
|
|||||||
/// Drop glue is not run on the destination.
|
/// Drop glue is not run on the destination.
|
||||||
pub fn move_val_init<T>(dst: *mut T, src: T);
|
pub fn move_val_init<T>(dst: *mut T, src: T);
|
||||||
|
|
||||||
|
#[rustc_const_stable(feature = "const_min_align_of", since = "1.40.0")]
|
||||||
pub fn min_align_of<T>() -> usize;
|
pub fn min_align_of<T>() -> usize;
|
||||||
|
#[rustc_const_unstable(feature = "const_pref_align_of", issue = "0")]
|
||||||
pub fn pref_align_of<T>() -> usize;
|
pub fn pref_align_of<T>() -> usize;
|
||||||
|
|
||||||
/// The size of the referenced value in bytes.
|
/// The size of the referenced value in bytes.
|
||||||
@ -689,11 +708,13 @@ extern "rust-intrinsic" {
|
|||||||
pub fn min_align_of_val<T: ?Sized>(_: &T) -> usize;
|
pub fn min_align_of_val<T: ?Sized>(_: &T) -> usize;
|
||||||
|
|
||||||
/// Gets a static string slice containing the name of a type.
|
/// Gets a static string slice containing the name of a type.
|
||||||
|
#[rustc_const_unstable(feature = "const_type_name", issue = "0")]
|
||||||
pub fn type_name<T: ?Sized>() -> &'static str;
|
pub fn type_name<T: ?Sized>() -> &'static str;
|
||||||
|
|
||||||
/// Gets an identifier which is globally unique to the specified type. This
|
/// Gets an identifier which is globally unique to the specified type. This
|
||||||
/// function will return the same value for a type regardless of whichever
|
/// function will return the same value for a type regardless of whichever
|
||||||
/// crate it is invoked in.
|
/// crate it is invoked in.
|
||||||
|
#[rustc_const_unstable(feature = "const_type_id", issue = "0")]
|
||||||
pub fn type_id<T: ?Sized + 'static>() -> u64;
|
pub fn type_id<T: ?Sized + 'static>() -> u64;
|
||||||
|
|
||||||
/// A guard for unsafe functions that cannot ever be executed if `T` is uninhabited:
|
/// A guard for unsafe functions that cannot ever be executed if `T` is uninhabited:
|
||||||
@ -701,6 +722,7 @@ extern "rust-intrinsic" {
|
|||||||
pub fn panic_if_uninhabited<T>();
|
pub fn panic_if_uninhabited<T>();
|
||||||
|
|
||||||
/// Gets a reference to a static `Location` indicating where it was called.
|
/// Gets a reference to a static `Location` indicating where it was called.
|
||||||
|
#[rustc_const_unstable(feature = "const_caller_location", issue = "47809")]
|
||||||
pub fn caller_location() -> &'static crate::panic::Location<'static>;
|
pub fn caller_location() -> &'static crate::panic::Location<'static>;
|
||||||
|
|
||||||
/// Creates a value initialized to zero.
|
/// Creates a value initialized to zero.
|
||||||
@ -957,6 +979,7 @@ extern "rust-intrinsic" {
|
|||||||
///
|
///
|
||||||
/// The stabilized version of this intrinsic is
|
/// The stabilized version of this intrinsic is
|
||||||
/// [`std::mem::needs_drop`](../../std/mem/fn.needs_drop.html).
|
/// [`std::mem::needs_drop`](../../std/mem/fn.needs_drop.html).
|
||||||
|
#[rustc_const_stable(feature = "const_needs_drop", since = "1.40.0")]
|
||||||
pub fn needs_drop<T>() -> bool;
|
pub fn needs_drop<T>() -> bool;
|
||||||
|
|
||||||
/// Calculates the offset from a pointer.
|
/// Calculates the offset from a pointer.
|
||||||
@ -1154,6 +1177,7 @@ extern "rust-intrinsic" {
|
|||||||
pub fn float_to_int_approx_unchecked<Float, Int>(value: Float) -> Int;
|
pub fn float_to_int_approx_unchecked<Float, Int>(value: Float) -> Int;
|
||||||
|
|
||||||
/// Returns the number of bits set in an integer type `T`
|
/// Returns the number of bits set in an integer type `T`
|
||||||
|
#[rustc_const_stable(feature = "const_ctpop", since = "1.40.0")]
|
||||||
pub fn ctpop<T>(x: T) -> T;
|
pub fn ctpop<T>(x: T) -> T;
|
||||||
|
|
||||||
/// Returns the number of leading unset bits (zeroes) in an integer type `T`.
|
/// Returns the number of leading unset bits (zeroes) in an integer type `T`.
|
||||||
@ -1181,6 +1205,7 @@ extern "rust-intrinsic" {
|
|||||||
/// let num_leading = ctlz(x);
|
/// let num_leading = ctlz(x);
|
||||||
/// assert_eq!(num_leading, 16);
|
/// assert_eq!(num_leading, 16);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[rustc_const_stable(feature = "const_ctlz", since = "1.40.0")]
|
||||||
pub fn ctlz<T>(x: T) -> T;
|
pub fn ctlz<T>(x: T) -> T;
|
||||||
|
|
||||||
/// Like `ctlz`, but extra-unsafe as it returns `undef` when
|
/// Like `ctlz`, but extra-unsafe as it returns `undef` when
|
||||||
@ -1197,6 +1222,7 @@ extern "rust-intrinsic" {
|
|||||||
/// let num_leading = unsafe { ctlz_nonzero(x) };
|
/// let num_leading = unsafe { ctlz_nonzero(x) };
|
||||||
/// assert_eq!(num_leading, 3);
|
/// assert_eq!(num_leading, 3);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[rustc_const_unstable(feature = "constctlz", issue = "0")]
|
||||||
pub fn ctlz_nonzero<T>(x: T) -> T;
|
pub fn ctlz_nonzero<T>(x: T) -> T;
|
||||||
|
|
||||||
/// Returns the number of trailing unset bits (zeroes) in an integer type `T`.
|
/// Returns the number of trailing unset bits (zeroes) in an integer type `T`.
|
||||||
@ -1224,6 +1250,7 @@ extern "rust-intrinsic" {
|
|||||||
/// let num_trailing = cttz(x);
|
/// let num_trailing = cttz(x);
|
||||||
/// assert_eq!(num_trailing, 16);
|
/// assert_eq!(num_trailing, 16);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[rustc_const_stable(feature = "const_cttz", since = "1.40.0")]
|
||||||
pub fn cttz<T>(x: T) -> T;
|
pub fn cttz<T>(x: T) -> T;
|
||||||
|
|
||||||
/// Like `cttz`, but extra-unsafe as it returns `undef` when
|
/// Like `cttz`, but extra-unsafe as it returns `undef` when
|
||||||
@ -1240,30 +1267,36 @@ extern "rust-intrinsic" {
|
|||||||
/// let num_trailing = unsafe { cttz_nonzero(x) };
|
/// let num_trailing = unsafe { cttz_nonzero(x) };
|
||||||
/// assert_eq!(num_trailing, 3);
|
/// assert_eq!(num_trailing, 3);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[rustc_const_unstable(feature = "const_cttz", issue = "0")]
|
||||||
pub fn cttz_nonzero<T>(x: T) -> T;
|
pub fn cttz_nonzero<T>(x: T) -> T;
|
||||||
|
|
||||||
/// Reverses the bytes in an integer type `T`.
|
/// Reverses the bytes in an integer type `T`.
|
||||||
|
#[rustc_const_stable(feature = "const_bswap", since = "1.40.0")]
|
||||||
pub fn bswap<T>(x: T) -> T;
|
pub fn bswap<T>(x: T) -> T;
|
||||||
|
|
||||||
/// Reverses the bits in an integer type `T`.
|
/// Reverses the bits in an integer type `T`.
|
||||||
|
#[rustc_const_stable(feature = "const_bitreverse", since = "1.40.0")]
|
||||||
pub fn bitreverse<T>(x: T) -> T;
|
pub fn bitreverse<T>(x: T) -> T;
|
||||||
|
|
||||||
/// Performs checked integer addition.
|
/// Performs checked integer addition.
|
||||||
/// The stabilized versions of this intrinsic are available on the integer
|
/// The stabilized versions of this intrinsic are available on the integer
|
||||||
/// primitives via the `overflowing_add` method. For example,
|
/// primitives via the `overflowing_add` method. For example,
|
||||||
/// [`std::u32::overflowing_add`](../../std/primitive.u32.html#method.overflowing_add)
|
/// [`std::u32::overflowing_add`](../../std/primitive.u32.html#method.overflowing_add)
|
||||||
|
#[rustc_const_stable(feature = "const_int_overflow", since = "1.40.0")]
|
||||||
pub fn add_with_overflow<T>(x: T, y: T) -> (T, bool);
|
pub fn add_with_overflow<T>(x: T, y: T) -> (T, bool);
|
||||||
|
|
||||||
/// Performs checked integer subtraction
|
/// Performs checked integer subtraction
|
||||||
/// The stabilized versions of this intrinsic are available on the integer
|
/// The stabilized versions of this intrinsic are available on the integer
|
||||||
/// primitives via the `overflowing_sub` method. For example,
|
/// primitives via the `overflowing_sub` method. For example,
|
||||||
/// [`std::u32::overflowing_sub`](../../std/primitive.u32.html#method.overflowing_sub)
|
/// [`std::u32::overflowing_sub`](../../std/primitive.u32.html#method.overflowing_sub)
|
||||||
|
#[rustc_const_stable(feature = "const_int_overflow", since = "1.40.0")]
|
||||||
pub fn sub_with_overflow<T>(x: T, y: T) -> (T, bool);
|
pub fn sub_with_overflow<T>(x: T, y: T) -> (T, bool);
|
||||||
|
|
||||||
/// Performs checked integer multiplication
|
/// Performs checked integer multiplication
|
||||||
/// The stabilized versions of this intrinsic are available on the integer
|
/// The stabilized versions of this intrinsic are available on the integer
|
||||||
/// primitives via the `overflowing_mul` method. For example,
|
/// primitives via the `overflowing_mul` method. For example,
|
||||||
/// [`std::u32::overflowing_mul`](../../std/primitive.u32.html#method.overflowing_mul)
|
/// [`std::u32::overflowing_mul`](../../std/primitive.u32.html#method.overflowing_mul)
|
||||||
|
#[rustc_const_stable(feature = "const_int_overflow", since = "1.40.0")]
|
||||||
pub fn mul_with_overflow<T>(x: T, y: T) -> (T, bool);
|
pub fn mul_with_overflow<T>(x: T, y: T) -> (T, bool);
|
||||||
|
|
||||||
/// Performs an exact division, resulting in undefined behavior where
|
/// Performs an exact division, resulting in undefined behavior where
|
||||||
@ -1279,9 +1312,11 @@ extern "rust-intrinsic" {
|
|||||||
|
|
||||||
/// Performs an unchecked left shift, resulting in undefined behavior when
|
/// Performs an unchecked left shift, resulting in undefined behavior when
|
||||||
/// y < 0 or y >= N, where N is the width of T in bits.
|
/// y < 0 or y >= N, where N is the width of T in bits.
|
||||||
|
#[rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0")]
|
||||||
pub fn unchecked_shl<T>(x: T, y: T) -> T;
|
pub fn unchecked_shl<T>(x: T, y: T) -> T;
|
||||||
/// Performs an unchecked right shift, resulting in undefined behavior when
|
/// Performs an unchecked right shift, resulting in undefined behavior when
|
||||||
/// y < 0 or y >= N, where N is the width of T in bits.
|
/// y < 0 or y >= N, where N is the width of T in bits.
|
||||||
|
#[rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0")]
|
||||||
pub fn unchecked_shr<T>(x: T, y: T) -> T;
|
pub fn unchecked_shr<T>(x: T, y: T) -> T;
|
||||||
|
|
||||||
/// Returns the result of an unchecked addition, resulting in
|
/// Returns the result of an unchecked addition, resulting in
|
||||||
@ -1300,39 +1335,46 @@ extern "rust-intrinsic" {
|
|||||||
/// The stabilized versions of this intrinsic are available on the integer
|
/// The stabilized versions of this intrinsic are available on the integer
|
||||||
/// primitives via the `rotate_left` method. For example,
|
/// primitives via the `rotate_left` method. For example,
|
||||||
/// [`std::u32::rotate_left`](../../std/primitive.u32.html#method.rotate_left)
|
/// [`std::u32::rotate_left`](../../std/primitive.u32.html#method.rotate_left)
|
||||||
|
#[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")]
|
||||||
pub fn rotate_left<T>(x: T, y: T) -> T;
|
pub fn rotate_left<T>(x: T, y: T) -> T;
|
||||||
|
|
||||||
/// Performs rotate right.
|
/// Performs rotate right.
|
||||||
/// The stabilized versions of this intrinsic are available on the integer
|
/// The stabilized versions of this intrinsic are available on the integer
|
||||||
/// primitives via the `rotate_right` method. For example,
|
/// primitives via the `rotate_right` method. For example,
|
||||||
/// [`std::u32::rotate_right`](../../std/primitive.u32.html#method.rotate_right)
|
/// [`std::u32::rotate_right`](../../std/primitive.u32.html#method.rotate_right)
|
||||||
|
#[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")]
|
||||||
pub fn rotate_right<T>(x: T, y: T) -> T;
|
pub fn rotate_right<T>(x: T, y: T) -> T;
|
||||||
|
|
||||||
/// Returns (a + b) mod 2<sup>N</sup>, where N is the width of T in bits.
|
/// Returns (a + b) mod 2<sup>N</sup>, where N is the width of T in bits.
|
||||||
/// The stabilized versions of this intrinsic are available on the integer
|
/// The stabilized versions of this intrinsic are available on the integer
|
||||||
/// primitives via the `wrapping_add` method. For example,
|
/// primitives via the `wrapping_add` method. For example,
|
||||||
/// [`std::u32::wrapping_add`](../../std/primitive.u32.html#method.wrapping_add)
|
/// [`std::u32::wrapping_add`](../../std/primitive.u32.html#method.wrapping_add)
|
||||||
|
#[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")]
|
||||||
pub fn wrapping_add<T>(a: T, b: T) -> T;
|
pub fn wrapping_add<T>(a: T, b: T) -> T;
|
||||||
/// Returns (a - b) mod 2<sup>N</sup>, where N is the width of T in bits.
|
/// Returns (a - b) mod 2<sup>N</sup>, where N is the width of T in bits.
|
||||||
/// The stabilized versions of this intrinsic are available on the integer
|
/// The stabilized versions of this intrinsic are available on the integer
|
||||||
/// primitives via the `wrapping_sub` method. For example,
|
/// primitives via the `wrapping_sub` method. For example,
|
||||||
/// [`std::u32::wrapping_sub`](../../std/primitive.u32.html#method.wrapping_sub)
|
/// [`std::u32::wrapping_sub`](../../std/primitive.u32.html#method.wrapping_sub)
|
||||||
|
#[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")]
|
||||||
pub fn wrapping_sub<T>(a: T, b: T) -> T;
|
pub fn wrapping_sub<T>(a: T, b: T) -> T;
|
||||||
/// Returns (a * b) mod 2<sup>N</sup>, where N is the width of T in bits.
|
/// Returns (a * b) mod 2<sup>N</sup>, where N is the width of T in bits.
|
||||||
/// The stabilized versions of this intrinsic are available on the integer
|
/// The stabilized versions of this intrinsic are available on the integer
|
||||||
/// primitives via the `wrapping_mul` method. For example,
|
/// primitives via the `wrapping_mul` method. For example,
|
||||||
/// [`std::u32::wrapping_mul`](../../std/primitive.u32.html#method.wrapping_mul)
|
/// [`std::u32::wrapping_mul`](../../std/primitive.u32.html#method.wrapping_mul)
|
||||||
|
#[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")]
|
||||||
pub fn wrapping_mul<T>(a: T, b: T) -> T;
|
pub fn wrapping_mul<T>(a: T, b: T) -> T;
|
||||||
|
|
||||||
/// Computes `a + b`, while saturating at numeric bounds.
|
/// Computes `a + b`, while saturating at numeric bounds.
|
||||||
/// The stabilized versions of this intrinsic are available on the integer
|
/// The stabilized versions of this intrinsic are available on the integer
|
||||||
/// primitives via the `saturating_add` method. For example,
|
/// primitives via the `saturating_add` method. For example,
|
||||||
/// [`std::u32::saturating_add`](../../std/primitive.u32.html#method.saturating_add)
|
/// [`std::u32::saturating_add`](../../std/primitive.u32.html#method.saturating_add)
|
||||||
|
#[rustc_const_stable(feature = "const_int_saturating", since = "1.40.0")]
|
||||||
pub fn saturating_add<T>(a: T, b: T) -> T;
|
pub fn saturating_add<T>(a: T, b: T) -> T;
|
||||||
/// Computes `a - b`, while saturating at numeric bounds.
|
/// Computes `a - b`, while saturating at numeric bounds.
|
||||||
/// The stabilized versions of this intrinsic are available on the integer
|
/// The stabilized versions of this intrinsic are available on the integer
|
||||||
/// primitives via the `saturating_sub` method. For example,
|
/// primitives via the `saturating_sub` method. For example,
|
||||||
/// [`std::u32::saturating_sub`](../../std/primitive.u32.html#method.saturating_sub)
|
/// [`std::u32::saturating_sub`](../../std/primitive.u32.html#method.saturating_sub)
|
||||||
|
#[rustc_const_stable(feature = "const_int_saturating", since = "1.40.0")]
|
||||||
pub fn saturating_sub<T>(a: T, b: T) -> T;
|
pub fn saturating_sub<T>(a: T, b: T) -> T;
|
||||||
|
|
||||||
/// Returns the value of the discriminant for the variant in 'v',
|
/// Returns the value of the discriminant for the variant in 'v',
|
||||||
@ -1354,6 +1396,7 @@ extern "rust-intrinsic" {
|
|||||||
pub fn nontemporal_store<T>(ptr: *mut T, val: T);
|
pub fn nontemporal_store<T>(ptr: *mut T, val: T);
|
||||||
|
|
||||||
/// See documentation of `<*const T>::offset_from` for details.
|
/// See documentation of `<*const T>::offset_from` for details.
|
||||||
|
#[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "0")]
|
||||||
pub fn ptr_offset_from<T>(ptr: *const T, base: *const T) -> isize;
|
pub fn ptr_offset_from<T>(ptr: *const T, base: *const T) -> isize;
|
||||||
|
|
||||||
/// Internal hook used by Miri to implement unwinding.
|
/// Internal hook used by Miri to implement unwinding.
|
||||||
|
@ -127,6 +127,8 @@
|
|||||||
#![feature(maybe_uninit_slice)]
|
#![feature(maybe_uninit_slice)]
|
||||||
#![feature(external_doc)]
|
#![feature(external_doc)]
|
||||||
#![feature(associated_type_bounds)]
|
#![feature(associated_type_bounds)]
|
||||||
|
#![feature(const_type_id)]
|
||||||
|
#![feature(const_caller_location)]
|
||||||
|
|
||||||
#[prelude_import]
|
#[prelude_import]
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
// the `caller_location` intrinsic, but once `#[track_caller]` is implemented,
|
// the `caller_location` intrinsic, but once `#[track_caller]` is implemented,
|
||||||
// `panicking::{panic, panic_fmt}` can use that instead of a `Location` argument.
|
// `panicking::{panic, panic_fmt}` can use that instead of a `Location` argument.
|
||||||
core_intrinsics,
|
core_intrinsics,
|
||||||
|
const_caller_location,
|
||||||
)]
|
)]
|
||||||
#[stable(feature = "core", since = "1.6.0")]
|
#[stable(feature = "core", since = "1.6.0")]
|
||||||
macro_rules! panic {
|
macro_rules! panic {
|
||||||
|
@ -99,9 +99,15 @@ pub trait Drop {
|
|||||||
/// Given that a [`panic!`] will call `drop` as it unwinds, any [`panic!`]
|
/// Given that a [`panic!`] will call `drop` as it unwinds, any [`panic!`]
|
||||||
/// in a `drop` implementation will likely abort.
|
/// in a `drop` implementation will likely abort.
|
||||||
///
|
///
|
||||||
|
/// Note that even if this panics, the value is considered to be dropped;
|
||||||
|
/// you must not cause `drop` to be called again. This is normally automatically
|
||||||
|
/// handled by the compiler, but when using unsafe code, can sometimes occur
|
||||||
|
/// unintentionally, particularly when using [`std::ptr::drop_in_place`].
|
||||||
|
///
|
||||||
/// [E0040]: ../../error-index.html#E0040
|
/// [E0040]: ../../error-index.html#E0040
|
||||||
/// [`panic!`]: ../macro.panic.html
|
/// [`panic!`]: ../macro.panic.html
|
||||||
/// [`std::mem::drop`]: ../../std/mem/fn.drop.html
|
/// [`std::mem::drop`]: ../../std/mem/fn.drop.html
|
||||||
|
/// [`std::ptr::drop_in_place`]: ../../std/ptr/fn.drop_in_place.html
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn drop(&mut self);
|
fn drop(&mut self);
|
||||||
}
|
}
|
||||||
|
@ -1043,9 +1043,9 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
|
|||||||
walk_list!(visitor, visit_label, opt_label);
|
walk_list!(visitor, visit_label, opt_label);
|
||||||
visitor.visit_block(block);
|
visitor.visit_block(block);
|
||||||
}
|
}
|
||||||
ExprKind::Assign(ref left_hand_expression, ref right_hand_expression) => {
|
ExprKind::Assign(ref lhs, ref rhs, _) => {
|
||||||
visitor.visit_expr(right_hand_expression);
|
visitor.visit_expr(rhs);
|
||||||
visitor.visit_expr(left_hand_expression)
|
visitor.visit_expr(lhs)
|
||||||
}
|
}
|
||||||
ExprKind::AssignOp(_, ref left_expression, ref right_expression) => {
|
ExprKind::AssignOp(_, ref left_expression, ref right_expression) => {
|
||||||
visitor.visit_expr(right_expression);
|
visitor.visit_expr(right_expression);
|
||||||
|
@ -3437,65 +3437,3 @@ fn body_ids(bodies: &BTreeMap<hir::BodyId, hir::Body<'hir>>) -> Vec<hir::BodyId>
|
|||||||
body_ids.sort_by_key(|b| bodies[b].value.span);
|
body_ids.sort_by_key(|b| bodies[b].value.span);
|
||||||
body_ids
|
body_ids
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks if the specified expression is a built-in range literal.
|
|
||||||
/// (See: `LoweringContext::lower_expr()`).
|
|
||||||
pub fn is_range_literal(sess: &Session, expr: &hir::Expr) -> bool {
|
|
||||||
use hir::{Path, QPath, ExprKind, TyKind};
|
|
||||||
|
|
||||||
// Returns whether the given path represents a (desugared) range,
|
|
||||||
// either in std or core, i.e. has either a `::std::ops::Range` or
|
|
||||||
// `::core::ops::Range` prefix.
|
|
||||||
fn is_range_path(path: &Path) -> bool {
|
|
||||||
let segs: Vec<_> = path.segments.iter().map(|seg| seg.ident.to_string()).collect();
|
|
||||||
let segs: Vec<_> = segs.iter().map(|seg| &**seg).collect();
|
|
||||||
|
|
||||||
// "{{root}}" is the equivalent of `::` prefix in `Path`.
|
|
||||||
if let ["{{root}}", std_core, "ops", range] = segs.as_slice() {
|
|
||||||
(*std_core == "std" || *std_core == "core") && range.starts_with("Range")
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Check whether a span corresponding to a range expression is a
|
|
||||||
// range literal, rather than an explicit struct or `new()` call.
|
|
||||||
fn is_lit(sess: &Session, span: &Span) -> bool {
|
|
||||||
let source_map = sess.source_map();
|
|
||||||
let end_point = source_map.end_point(*span);
|
|
||||||
|
|
||||||
if let Ok(end_string) = source_map.span_to_snippet(end_point) {
|
|
||||||
!(end_string.ends_with("}") || end_string.ends_with(")"))
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
match expr.kind {
|
|
||||||
// All built-in range literals but `..=` and `..` desugar to `Struct`s.
|
|
||||||
ExprKind::Struct(ref qpath, _, _) => {
|
|
||||||
if let QPath::Resolved(None, ref path) = **qpath {
|
|
||||||
return is_range_path(&path) && is_lit(sess, &expr.span);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// `..` desugars to its struct path.
|
|
||||||
ExprKind::Path(QPath::Resolved(None, ref path)) => {
|
|
||||||
return is_range_path(&path) && is_lit(sess, &expr.span);
|
|
||||||
}
|
|
||||||
|
|
||||||
// `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
|
|
||||||
ExprKind::Call(ref func, _) => {
|
|
||||||
if let ExprKind::Path(QPath::TypeRelative(ref ty, ref segment)) = func.kind {
|
|
||||||
if let TyKind::Path(QPath::Resolved(None, ref path)) = ty.kind {
|
|
||||||
let new_call = segment.ident.name == sym::new;
|
|
||||||
return is_range_path(&path) && is_lit(sess, &expr.span) && new_call;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
@ -122,8 +122,8 @@ impl LoweringContext<'_, '_> {
|
|||||||
self.lower_block(blk, opt_label.is_some()),
|
self.lower_block(blk, opt_label.is_some()),
|
||||||
self.lower_label(opt_label),
|
self.lower_label(opt_label),
|
||||||
),
|
),
|
||||||
ExprKind::Assign(ref el, ref er) => {
|
ExprKind::Assign(ref el, ref er, span) => {
|
||||||
hir::ExprKind::Assign(P(self.lower_expr(el)), P(self.lower_expr(er)))
|
hir::ExprKind::Assign(P(self.lower_expr(el)), P(self.lower_expr(er)), span)
|
||||||
}
|
}
|
||||||
ExprKind::AssignOp(op, ref el, ref er) => hir::ExprKind::AssignOp(
|
ExprKind::AssignOp(op, ref el, ref er) => hir::ExprKind::AssignOp(
|
||||||
self.lower_binop(op),
|
self.lower_binop(op),
|
||||||
@ -994,8 +994,11 @@ impl LoweringContext<'_, '_> {
|
|||||||
let (val_pat, val_pat_hid) = self.pat_ident(pat.span, val_ident);
|
let (val_pat, val_pat_hid) = self.pat_ident(pat.span, val_ident);
|
||||||
let val_expr = P(self.expr_ident(pat.span, val_ident, val_pat_hid));
|
let val_expr = P(self.expr_ident(pat.span, val_ident, val_pat_hid));
|
||||||
let next_expr = P(self.expr_ident(pat.span, next_ident, next_pat_hid));
|
let next_expr = P(self.expr_ident(pat.span, next_ident, next_pat_hid));
|
||||||
let assign =
|
let assign = P(self.expr(
|
||||||
P(self.expr(pat.span, hir::ExprKind::Assign(next_expr, val_expr), ThinVec::new()));
|
pat.span,
|
||||||
|
hir::ExprKind::Assign(next_expr, val_expr, pat.span),
|
||||||
|
ThinVec::new(),
|
||||||
|
));
|
||||||
let some_pat = self.pat_some(pat.span, val_pat);
|
let some_pat = self.pat_some(pat.span, val_pat);
|
||||||
self.arm(some_pat, assign)
|
self.arm(some_pat, assign)
|
||||||
};
|
};
|
||||||
|
@ -29,10 +29,10 @@ use syntax::ast::{AttrVec, Attribute, FloatTy, IntTy, Label, LitKind, StrStyle,
|
|||||||
pub use syntax::ast::{BorrowKind, ImplPolarity, IsAuto};
|
pub use syntax::ast::{BorrowKind, ImplPolarity, IsAuto};
|
||||||
pub use syntax::ast::{CaptureBy, Constness, Movability, Mutability, Unsafety};
|
pub use syntax::ast::{CaptureBy, Constness, Movability, Mutability, Unsafety};
|
||||||
use syntax::attr::{InlineAttr, OptimizeAttr};
|
use syntax::attr::{InlineAttr, OptimizeAttr};
|
||||||
use syntax::source_map::Spanned;
|
|
||||||
use syntax::symbol::{kw, Symbol};
|
|
||||||
use syntax::tokenstream::TokenStream;
|
use syntax::tokenstream::TokenStream;
|
||||||
use syntax::util::parser::ExprPrecedence;
|
use syntax::util::parser::ExprPrecedence;
|
||||||
|
use syntax_pos::source_map::{SourceMap, Spanned};
|
||||||
|
use syntax_pos::symbol::{kw, sym, Symbol};
|
||||||
use syntax_pos::{MultiSpan, Span, DUMMY_SP};
|
use syntax_pos::{MultiSpan, Span, DUMMY_SP};
|
||||||
|
|
||||||
/// HIR doesn't commit to a concrete storage type and has its own alias for a vector.
|
/// HIR doesn't commit to a concrete storage type and has its own alias for a vector.
|
||||||
@ -1564,6 +1564,68 @@ impl fmt::Debug for Expr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks if the specified expression is a built-in range literal.
|
||||||
|
/// (See: `LoweringContext::lower_expr()`).
|
||||||
|
///
|
||||||
|
/// FIXME(#60607): This function is a hack. If and when we have `QPath::Lang(...)`,
|
||||||
|
/// we can use that instead as simpler, more reliable mechanism, as opposed to using `SourceMap`.
|
||||||
|
pub fn is_range_literal(sm: &SourceMap, expr: &Expr) -> bool {
|
||||||
|
// Returns whether the given path represents a (desugared) range,
|
||||||
|
// either in std or core, i.e. has either a `::std::ops::Range` or
|
||||||
|
// `::core::ops::Range` prefix.
|
||||||
|
fn is_range_path(path: &Path) -> bool {
|
||||||
|
let segs: Vec<_> = path.segments.iter().map(|seg| seg.ident.to_string()).collect();
|
||||||
|
let segs: Vec<_> = segs.iter().map(|seg| &**seg).collect();
|
||||||
|
|
||||||
|
// "{{root}}" is the equivalent of `::` prefix in `Path`.
|
||||||
|
if let ["{{root}}", std_core, "ops", range] = segs.as_slice() {
|
||||||
|
(*std_core == "std" || *std_core == "core") && range.starts_with("Range")
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check whether a span corresponding to a range expression is a
|
||||||
|
// range literal, rather than an explicit struct or `new()` call.
|
||||||
|
fn is_lit(sm: &SourceMap, span: &Span) -> bool {
|
||||||
|
let end_point = sm.end_point(*span);
|
||||||
|
|
||||||
|
if let Ok(end_string) = sm.span_to_snippet(end_point) {
|
||||||
|
!(end_string.ends_with("}") || end_string.ends_with(")"))
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match expr.kind {
|
||||||
|
// All built-in range literals but `..=` and `..` desugar to `Struct`s.
|
||||||
|
ExprKind::Struct(ref qpath, _, _) => {
|
||||||
|
if let QPath::Resolved(None, ref path) = **qpath {
|
||||||
|
return is_range_path(&path) && is_lit(sm, &expr.span);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// `..` desugars to its struct path.
|
||||||
|
ExprKind::Path(QPath::Resolved(None, ref path)) => {
|
||||||
|
return is_range_path(&path) && is_lit(sm, &expr.span);
|
||||||
|
}
|
||||||
|
|
||||||
|
// `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
|
||||||
|
ExprKind::Call(ref func, _) => {
|
||||||
|
if let ExprKind::Path(QPath::TypeRelative(ref ty, ref segment)) = func.kind {
|
||||||
|
if let TyKind::Path(QPath::Resolved(None, ref path)) = ty.kind {
|
||||||
|
let new_call = segment.ident.name == sym::new;
|
||||||
|
return is_range_path(&path) && is_lit(sm, &expr.span) && new_call;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
|
#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
|
||||||
pub enum ExprKind {
|
pub enum ExprKind {
|
||||||
/// A `box x` expression.
|
/// A `box x` expression.
|
||||||
@ -1628,7 +1690,8 @@ pub enum ExprKind {
|
|||||||
Block(P<Block>, Option<Label>),
|
Block(P<Block>, Option<Label>),
|
||||||
|
|
||||||
/// An assignment (e.g., `a = foo()`).
|
/// An assignment (e.g., `a = foo()`).
|
||||||
Assign(P<Expr>, P<Expr>),
|
/// The `Span` argument is the span of the `=` token.
|
||||||
|
Assign(P<Expr>, P<Expr>, Span),
|
||||||
/// An assignment with an operator.
|
/// An assignment with an operator.
|
||||||
///
|
///
|
||||||
/// E.g., `a += 1`.
|
/// E.g., `a += 1`.
|
||||||
|
@ -1289,7 +1289,7 @@ impl<'a> State<'a> {
|
|||||||
self.ibox(0);
|
self.ibox(0);
|
||||||
self.print_block(&blk);
|
self.print_block(&blk);
|
||||||
}
|
}
|
||||||
hir::ExprKind::Assign(ref lhs, ref rhs) => {
|
hir::ExprKind::Assign(ref lhs, ref rhs, _) => {
|
||||||
let prec = AssocOp::Assign.precedence() as i8;
|
let prec = AssocOp::Assign.precedence() as i8;
|
||||||
self.print_expr_maybe_paren(&lhs, prec + 1);
|
self.print_expr_maybe_paren(&lhs, prec + 1);
|
||||||
self.s.space();
|
self.s.space();
|
||||||
@ -2265,7 +2265,7 @@ fn contains_exterior_struct_lit(value: &hir::Expr) -> bool {
|
|||||||
match value.kind {
|
match value.kind {
|
||||||
hir::ExprKind::Struct(..) => true,
|
hir::ExprKind::Struct(..) => true,
|
||||||
|
|
||||||
hir::ExprKind::Assign(ref lhs, ref rhs)
|
hir::ExprKind::Assign(ref lhs, ref rhs, _)
|
||||||
| hir::ExprKind::AssignOp(_, ref lhs, ref rhs)
|
| hir::ExprKind::AssignOp(_, ref lhs, ref rhs)
|
||||||
| hir::ExprKind::Binary(_, ref lhs, ref rhs) => {
|
| hir::ExprKind::Binary(_, ref lhs, ref rhs) => {
|
||||||
// `X { y: 1 } + X { y: 2 }`
|
// `X { y: 1 } + X { y: 2 }`
|
||||||
|
@ -2,7 +2,7 @@ use crate::ty::query::Providers;
|
|||||||
use crate::hir::def_id::DefId;
|
use crate::hir::def_id::DefId;
|
||||||
use crate::hir;
|
use crate::hir;
|
||||||
use crate::ty::TyCtxt;
|
use crate::ty::TyCtxt;
|
||||||
use syntax_pos::symbol::{sym, Symbol};
|
use syntax_pos::symbol::Symbol;
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
use crate::hir::map::blocks::FnLikeNode;
|
use crate::hir::map::blocks::FnLikeNode;
|
||||||
use syntax::attr;
|
use syntax::attr;
|
||||||
@ -41,51 +41,12 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the `def_id` refers to an intrisic which we've whitelisted
|
|
||||||
/// for being called from stable `const fn`s (`min_const_fn`).
|
|
||||||
///
|
|
||||||
/// Adding more intrinsics requires sign-off from @rust-lang/lang.
|
|
||||||
///
|
|
||||||
/// This list differs from the list in `is_const_intrinsic` in the sense that any item on this
|
|
||||||
/// list must be on the `is_const_intrinsic` list, too, because if an intrinsic is callable from
|
|
||||||
/// stable, it must be callable at all.
|
|
||||||
fn is_intrinsic_min_const_fn(self, def_id: DefId) -> bool {
|
|
||||||
match self.item_name(def_id) {
|
|
||||||
| sym::size_of
|
|
||||||
| sym::min_align_of
|
|
||||||
| sym::needs_drop
|
|
||||||
// Arithmetic:
|
|
||||||
| sym::add_with_overflow // ~> .overflowing_add
|
|
||||||
| sym::sub_with_overflow // ~> .overflowing_sub
|
|
||||||
| sym::mul_with_overflow // ~> .overflowing_mul
|
|
||||||
| sym::wrapping_add // ~> .wrapping_add
|
|
||||||
| sym::wrapping_sub // ~> .wrapping_sub
|
|
||||||
| sym::wrapping_mul // ~> .wrapping_mul
|
|
||||||
| sym::saturating_add // ~> .saturating_add
|
|
||||||
| sym::saturating_sub // ~> .saturating_sub
|
|
||||||
| sym::unchecked_shl // ~> .wrapping_shl
|
|
||||||
| sym::unchecked_shr // ~> .wrapping_shr
|
|
||||||
| sym::rotate_left // ~> .rotate_left
|
|
||||||
| sym::rotate_right // ~> .rotate_right
|
|
||||||
| sym::ctpop // ~> .count_ones
|
|
||||||
| sym::ctlz // ~> .leading_zeros
|
|
||||||
| sym::cttz // ~> .trailing_zeros
|
|
||||||
| sym::bswap // ~> .swap_bytes
|
|
||||||
| sym::bitreverse // ~> .reverse_bits
|
|
||||||
=> true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns `true` if this function must conform to `min_const_fn`
|
/// Returns `true` if this function must conform to `min_const_fn`
|
||||||
pub fn is_min_const_fn(self, def_id: DefId) -> bool {
|
pub fn is_min_const_fn(self, def_id: DefId) -> bool {
|
||||||
// Bail out if the signature doesn't contain `const`
|
// Bail out if the signature doesn't contain `const`
|
||||||
if !self.is_const_fn_raw(def_id) {
|
if !self.is_const_fn_raw(def_id) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if let Abi::RustIntrinsic = self.fn_sig(def_id).abi() {
|
|
||||||
return self.is_intrinsic_min_const_fn(def_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.features().staged_api {
|
if self.features().staged_api {
|
||||||
// In order for a libstd function to be considered min_const_fn
|
// In order for a libstd function to be considered min_const_fn
|
||||||
@ -134,62 +95,7 @@ pub fn provide(providers: &mut Providers<'_>) {
|
|||||||
fn is_const_intrinsic(tcx: TyCtxt<'_>, def_id: DefId) -> Option<bool> {
|
fn is_const_intrinsic(tcx: TyCtxt<'_>, def_id: DefId) -> Option<bool> {
|
||||||
match tcx.fn_sig(def_id).abi() {
|
match tcx.fn_sig(def_id).abi() {
|
||||||
Abi::RustIntrinsic |
|
Abi::RustIntrinsic |
|
||||||
Abi::PlatformIntrinsic => {
|
Abi::PlatformIntrinsic => Some(tcx.lookup_const_stability(def_id).is_some()),
|
||||||
// FIXME: deduplicate these two lists as much as possible
|
|
||||||
match tcx.item_name(def_id) {
|
|
||||||
// Keep this list in the same order as the match patterns in
|
|
||||||
// `librustc_mir/interpret/intrinsics.rs`
|
|
||||||
|
|
||||||
// This whitelist is a list of intrinsics that have a miri-engine implementation
|
|
||||||
// and can thus be called when enabling enough feature gates. The similar
|
|
||||||
// whitelist in `is_intrinsic_min_const_fn` (in this file), exists for allowing
|
|
||||||
// the intrinsics to be called by stable const fns.
|
|
||||||
| sym::caller_location
|
|
||||||
|
|
||||||
| sym::min_align_of
|
|
||||||
| sym::pref_align_of
|
|
||||||
| sym::needs_drop
|
|
||||||
| sym::size_of
|
|
||||||
| sym::type_id
|
|
||||||
| sym::type_name
|
|
||||||
|
|
||||||
| sym::ctpop
|
|
||||||
| sym::cttz
|
|
||||||
| sym::cttz_nonzero
|
|
||||||
| sym::ctlz
|
|
||||||
| sym::ctlz_nonzero
|
|
||||||
| sym::bswap
|
|
||||||
| sym::bitreverse
|
|
||||||
|
|
||||||
| sym::wrapping_add
|
|
||||||
| sym::wrapping_sub
|
|
||||||
| sym::wrapping_mul
|
|
||||||
| sym::add_with_overflow
|
|
||||||
| sym::sub_with_overflow
|
|
||||||
| sym::mul_with_overflow
|
|
||||||
|
|
||||||
| sym::saturating_add
|
|
||||||
| sym::saturating_sub
|
|
||||||
|
|
||||||
| sym::unchecked_shl
|
|
||||||
| sym::unchecked_shr
|
|
||||||
|
|
||||||
| sym::rotate_left
|
|
||||||
| sym::rotate_right
|
|
||||||
|
|
||||||
| sym::ptr_offset_from
|
|
||||||
|
|
||||||
| sym::transmute
|
|
||||||
|
|
||||||
| sym::simd_insert
|
|
||||||
|
|
||||||
| sym::simd_extract
|
|
||||||
|
|
||||||
=> Some(true),
|
|
||||||
|
|
||||||
_ => Some(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => None
|
_ => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,7 @@
|
|||||||
use crate::hir::def_id::DefId;
|
use crate::hir::def_id::DefId;
|
||||||
use lint::{LateContext, LintArray, LintContext};
|
use lint::{LateContext, LintArray, LintContext};
|
||||||
use lint::{LateLintPass, LintPass};
|
use lint::{LateLintPass, LintPass};
|
||||||
use rustc::hir::lowering::is_range_literal;
|
use rustc::hir::{is_range_literal, ExprKind, Node};
|
||||||
use rustc::hir::{ExprKind, Node};
|
|
||||||
use rustc::ty::layout::{self, IntegerExt, LayoutOf, SizeSkeleton, VariantIdx};
|
use rustc::ty::layout::{self, IntegerExt, LayoutOf, SizeSkeleton, VariantIdx};
|
||||||
use rustc::ty::subst::SubstsRef;
|
use rustc::ty::subst::SubstsRef;
|
||||||
use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
|
use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
|
||||||
@ -266,7 +265,7 @@ fn lint_int_literal<'a, 'tcx>(
|
|||||||
let par_id = cx.tcx.hir().get_parent_node(e.hir_id);
|
let par_id = cx.tcx.hir().get_parent_node(e.hir_id);
|
||||||
if let Node::Expr(par_e) = cx.tcx.hir().get(par_id) {
|
if let Node::Expr(par_e) = cx.tcx.hir().get(par_id) {
|
||||||
if let hir::ExprKind::Struct(..) = par_e.kind {
|
if let hir::ExprKind::Struct(..) = par_e.kind {
|
||||||
if is_range_literal(cx.sess(), par_e)
|
if is_range_literal(cx.sess().source_map(), par_e)
|
||||||
&& lint_overflowing_range_endpoint(cx, lit, v, max, e, par_e, t.name_str())
|
&& lint_overflowing_range_endpoint(cx, lit, v, max, e, par_e, t.name_str())
|
||||||
{
|
{
|
||||||
// The overflowing literal lint was overridden.
|
// The overflowing literal lint was overridden.
|
||||||
@ -318,7 +317,7 @@ fn lint_uint_literal<'a, 'tcx>(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::ExprKind::Struct(..) if is_range_literal(cx.sess(), par_e) => {
|
hir::ExprKind::Struct(..) if is_range_literal(cx.sess().source_map(), par_e) => {
|
||||||
let t = t.name_str();
|
let t = t.name_str();
|
||||||
if lint_overflowing_range_endpoint(cx, lit, lit_val, max, e, par_e, t) {
|
if lint_overflowing_range_endpoint(cx, lit, lit_val, max, e, par_e, t) {
|
||||||
// The overflowing literal lint was overridden.
|
// The overflowing literal lint was overridden.
|
||||||
|
@ -490,7 +490,7 @@ impl EarlyLintPass for UnusedParens {
|
|||||||
(value, "`return` value", false, Some(left), None)
|
(value, "`return` value", false, Some(left), None)
|
||||||
}
|
}
|
||||||
|
|
||||||
Assign(_, ref value) => (value, "assigned value", false, None, None),
|
Assign(_, ref value, _) => (value, "assigned value", false, None, None),
|
||||||
AssignOp(.., ref value) => (value, "assigned value", false, None, None),
|
AssignOp(.., ref value) => (value, "assigned value", false, None, None),
|
||||||
// either function/method call, or something this lint doesn't care about
|
// either function/method call, or something this lint doesn't care about
|
||||||
ref call_or_other => {
|
ref call_or_other => {
|
||||||
|
@ -227,7 +227,7 @@ fn make_mirror_unadjusted<'a, 'tcx>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr
|
|||||||
|
|
||||||
hir::ExprKind::Block(ref blk, _) => ExprKind::Block { body: &blk },
|
hir::ExprKind::Block(ref blk, _) => ExprKind::Block { body: &blk },
|
||||||
|
|
||||||
hir::ExprKind::Assign(ref lhs, ref rhs) => {
|
hir::ExprKind::Assign(ref lhs, ref rhs, _) => {
|
||||||
ExprKind::Assign { lhs: lhs.to_ref(), rhs: rhs.to_ref() }
|
ExprKind::Assign { lhs: lhs.to_ref(), rhs: rhs.to_ref() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -530,11 +530,12 @@ where
|
|||||||
// This can only be reached in ConstProp and non-rustc-MIR.
|
// This can only be reached in ConstProp and non-rustc-MIR.
|
||||||
throw_ub!(BoundsCheckFailed { len: min_length as u64, index: n as u64 });
|
throw_ub!(BoundsCheckFailed { len: min_length as u64, index: n as u64 });
|
||||||
}
|
}
|
||||||
assert!(offset < min_length);
|
|
||||||
|
|
||||||
let index = if from_end {
|
let index = if from_end {
|
||||||
|
assert!(0 < offset && offset - 1 < min_length);
|
||||||
n - u64::from(offset)
|
n - u64::from(offset)
|
||||||
} else {
|
} else {
|
||||||
|
assert!(offset < min_length);
|
||||||
u64::from(offset)
|
u64::from(offset)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -281,7 +281,9 @@ impl<'a> Parser<'a> {
|
|||||||
let binary = self.mk_binary(source_map::respan(cur_op_span, ast_op), lhs, rhs);
|
let binary = self.mk_binary(source_map::respan(cur_op_span, ast_op), lhs, rhs);
|
||||||
self.mk_expr(span, binary, AttrVec::new())
|
self.mk_expr(span, binary, AttrVec::new())
|
||||||
}
|
}
|
||||||
AssocOp::Assign => self.mk_expr(span, ExprKind::Assign(lhs, rhs), AttrVec::new()),
|
AssocOp::Assign => {
|
||||||
|
self.mk_expr(span, ExprKind::Assign(lhs, rhs, cur_op_span), AttrVec::new())
|
||||||
|
}
|
||||||
AssocOp::AssignOp(k) => {
|
AssocOp::AssignOp(k) => {
|
||||||
let aop = match k {
|
let aop = match k {
|
||||||
token::Plus => BinOpKind::Add,
|
token::Plus => BinOpKind::Add,
|
||||||
|
@ -737,8 +737,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||||||
for predicate in &generics.where_clause.predicates {
|
for predicate in &generics.where_clause.predicates {
|
||||||
if let WherePredicate::EqPredicate(ref predicate) = *predicate {
|
if let WherePredicate::EqPredicate(ref predicate) = *predicate {
|
||||||
self.err_handler()
|
self.err_handler()
|
||||||
.span_err(predicate.span, "equality constraints are not yet \
|
.struct_span_err(
|
||||||
supported in where clauses (see #20041)");
|
predicate.span,
|
||||||
|
"equality constraints are not yet supported in `where` clauses",
|
||||||
|
)
|
||||||
|
.note(
|
||||||
|
"for more information, see https://github.com/rust-lang/rust/issues/20041",
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1079,7 +1079,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
|||||||
.unwrap_or_else(|| span_bug!(expr.span, "continue to unknown label"))
|
.unwrap_or_else(|| span_bug!(expr.span, "continue to unknown label"))
|
||||||
}
|
}
|
||||||
|
|
||||||
hir::ExprKind::Assign(ref l, ref r) => {
|
hir::ExprKind::Assign(ref l, ref r, _) => {
|
||||||
// see comment on places in
|
// see comment on places in
|
||||||
// propagate_through_place_components()
|
// propagate_through_place_components()
|
||||||
let succ = self.write_place(&l, succ, ACC_WRITE);
|
let succ = self.write_place(&l, succ, ACC_WRITE);
|
||||||
@ -1373,7 +1373,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Liveness<'a, 'tcx> {
|
|||||||
|
|
||||||
fn check_expr<'tcx>(this: &mut Liveness<'_, 'tcx>, expr: &'tcx Expr) {
|
fn check_expr<'tcx>(this: &mut Liveness<'_, 'tcx>, expr: &'tcx Expr) {
|
||||||
match expr.kind {
|
match expr.kind {
|
||||||
hir::ExprKind::Assign(ref l, _) => {
|
hir::ExprKind::Assign(ref l, ..) => {
|
||||||
this.check_place(&l);
|
this.check_place(&l);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1251,7 +1251,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
match expr.kind {
|
match expr.kind {
|
||||||
hir::ExprKind::Assign(.., ref rhs) | hir::ExprKind::Match(ref rhs, ..) => {
|
hir::ExprKind::Assign(_, ref rhs, _) | hir::ExprKind::Match(ref rhs, ..) => {
|
||||||
// Do not report duplicate errors for `x = y` and `match x { ... }`.
|
// Do not report duplicate errors for `x = y` and `match x { ... }`.
|
||||||
if self.check_expr_pat_type(rhs.hir_id, rhs.span) {
|
if self.check_expr_pat_type(rhs.hir_id, rhs.span) {
|
||||||
return;
|
return;
|
||||||
|
@ -3,9 +3,7 @@ use rustc::infer::InferOk;
|
|||||||
use rustc::traits::{self, ObligationCause, ObligationCauseCode};
|
use rustc::traits::{self, ObligationCause, ObligationCauseCode};
|
||||||
|
|
||||||
use errors::{Applicability, DiagnosticBuilder};
|
use errors::{Applicability, DiagnosticBuilder};
|
||||||
use rustc::hir;
|
use rustc::hir::{self, is_range_literal, print, Node};
|
||||||
use rustc::hir::Node;
|
|
||||||
use rustc::hir::{lowering::is_range_literal, print};
|
|
||||||
use rustc::ty::adjustment::AllowTwoPhase;
|
use rustc::ty::adjustment::AllowTwoPhase;
|
||||||
use rustc::ty::{self, AssocItem, Ty};
|
use rustc::ty::{self, AssocItem, Ty};
|
||||||
use syntax::symbol::sym;
|
use syntax::symbol::sym;
|
||||||
@ -478,7 +476,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
// parenthesize if needed (Issue #46756)
|
// parenthesize if needed (Issue #46756)
|
||||||
hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true,
|
hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true,
|
||||||
// parenthesize borrows of range literals (Issue #54505)
|
// parenthesize borrows of range literals (Issue #54505)
|
||||||
_ if is_range_literal(self.tcx.sess, expr) => true,
|
_ if is_range_literal(self.tcx.sess.source_map(), expr) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
let sugg_expr = if needs_parens { format!("({})", src) } else { src };
|
let sugg_expr = if needs_parens { format!("({})", src) } else { src };
|
||||||
@ -492,7 +490,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
String::new()
|
String::new()
|
||||||
};
|
};
|
||||||
if let Some(hir::Node::Expr(hir::Expr {
|
if let Some(hir::Node::Expr(hir::Expr {
|
||||||
kind: hir::ExprKind::Assign(left_expr, _),
|
kind: hir::ExprKind::Assign(left_expr, ..),
|
||||||
..
|
..
|
||||||
})) = self.tcx.hir().find(self.tcx.hir().get_parent_node(expr.hir_id))
|
})) = self.tcx.hir().find(self.tcx.hir().get_parent_node(expr.hir_id))
|
||||||
{
|
{
|
||||||
|
@ -17,7 +17,7 @@ use crate::check::TupleArgumentsFlag::DontTupleArguments;
|
|||||||
use crate::util::common::ErrorReported;
|
use crate::util::common::ErrorReported;
|
||||||
use crate::util::nodemap::FxHashMap;
|
use crate::util::nodemap::FxHashMap;
|
||||||
|
|
||||||
use errors::{pluralize, Applicability, DiagnosticBuilder};
|
use errors::{pluralize, Applicability, DiagnosticBuilder, DiagnosticId};
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
use rustc::hir::def::{CtorKind, DefKind, Res};
|
use rustc::hir::def::{CtorKind, DefKind, Res};
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
@ -219,6 +219,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
ExprKind::Box(ref subexpr) => self.check_expr_box(subexpr, expected),
|
ExprKind::Box(ref subexpr) => self.check_expr_box(subexpr, expected),
|
||||||
ExprKind::Lit(ref lit) => self.check_lit(&lit, expected),
|
ExprKind::Lit(ref lit) => self.check_lit(&lit, expected),
|
||||||
ExprKind::Binary(op, ref lhs, ref rhs) => self.check_binop(expr, op, lhs, rhs),
|
ExprKind::Binary(op, ref lhs, ref rhs) => self.check_binop(expr, op, lhs, rhs),
|
||||||
|
ExprKind::Assign(ref lhs, ref rhs, ref span) => {
|
||||||
|
self.check_expr_assign(expr, expected, lhs, rhs, span)
|
||||||
|
}
|
||||||
ExprKind::AssignOp(op, ref lhs, ref rhs) => self.check_binop_assign(expr, op, lhs, rhs),
|
ExprKind::AssignOp(op, ref lhs, ref rhs) => self.check_binop_assign(expr, op, lhs, rhs),
|
||||||
ExprKind::Unary(unop, ref oprnd) => {
|
ExprKind::Unary(unop, ref oprnd) => {
|
||||||
self.check_expr_unary(unop, oprnd, expected, needs, expr)
|
self.check_expr_unary(unop, oprnd, expected, needs, expr)
|
||||||
@ -245,7 +248,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprKind::Ret(ref expr_opt) => self.check_expr_return(expr_opt.as_deref(), expr),
|
ExprKind::Ret(ref expr_opt) => self.check_expr_return(expr_opt.as_deref(), expr),
|
||||||
ExprKind::Assign(ref lhs, ref rhs) => self.check_expr_assign(expr, expected, lhs, rhs),
|
|
||||||
ExprKind::Loop(ref body, _, source) => {
|
ExprKind::Loop(ref body, _, source) => {
|
||||||
self.check_expr_loop(body, source, expected, expr)
|
self.check_expr_loop(body, source, expected, expr)
|
||||||
}
|
}
|
||||||
@ -723,6 +725,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_destructuring_place_expr(&self, expr: &'tcx hir::Expr) -> bool {
|
||||||
|
match &expr.kind {
|
||||||
|
ExprKind::Array(comps) | ExprKind::Tup(comps) => {
|
||||||
|
comps.iter().all(|e| self.is_destructuring_place_expr(e))
|
||||||
|
}
|
||||||
|
ExprKind::Struct(_path, fields, rest) => {
|
||||||
|
rest.as_ref().map(|e| self.is_destructuring_place_expr(e)).unwrap_or(true)
|
||||||
|
&& fields.iter().all(|f| self.is_destructuring_place_expr(&f.expr))
|
||||||
|
}
|
||||||
|
_ => expr.is_syntactic_place_expr(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn check_lhs_assignable(
|
||||||
|
&self,
|
||||||
|
lhs: &'tcx hir::Expr,
|
||||||
|
err_code: &'static str,
|
||||||
|
expr_span: &Span,
|
||||||
|
) {
|
||||||
|
if !lhs.is_syntactic_place_expr() {
|
||||||
|
let mut err = self.tcx.sess.struct_span_err_with_code(
|
||||||
|
*expr_span,
|
||||||
|
"invalid left-hand side of assignment",
|
||||||
|
DiagnosticId::Error(err_code.into()),
|
||||||
|
);
|
||||||
|
err.span_label(lhs.span, "cannot assign to this expression");
|
||||||
|
if self.is_destructuring_place_expr(lhs) {
|
||||||
|
err.note("destructuring assignments are not currently supported");
|
||||||
|
err.note("for more information, see https://github.com/rust-lang/rfcs/issues/372");
|
||||||
|
}
|
||||||
|
err.emit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Type check assignment expression `expr` of form `lhs = rhs`.
|
/// Type check assignment expression `expr` of form `lhs = rhs`.
|
||||||
/// The expected type is `()` and is passsed to the function for the purposes of diagnostics.
|
/// The expected type is `()` and is passsed to the function for the purposes of diagnostics.
|
||||||
fn check_expr_assign(
|
fn check_expr_assign(
|
||||||
@ -731,6 +767,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
expected: Expectation<'tcx>,
|
expected: Expectation<'tcx>,
|
||||||
lhs: &'tcx hir::Expr,
|
lhs: &'tcx hir::Expr,
|
||||||
rhs: &'tcx hir::Expr,
|
rhs: &'tcx hir::Expr,
|
||||||
|
span: &Span,
|
||||||
) -> Ty<'tcx> {
|
) -> Ty<'tcx> {
|
||||||
let lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace);
|
let lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace);
|
||||||
let rhs_ty = self.check_expr_coercable_to_type(&rhs, lhs_ty);
|
let rhs_ty = self.check_expr_coercable_to_type(&rhs, lhs_ty);
|
||||||
@ -752,10 +789,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
err.help(msg);
|
err.help(msg);
|
||||||
}
|
}
|
||||||
err.emit();
|
err.emit();
|
||||||
} else if !lhs.is_syntactic_place_expr() {
|
} else {
|
||||||
struct_span_err!(self.tcx.sess, expr.span, E0070, "invalid left-hand side expression")
|
self.check_lhs_assignable(lhs, "E0070", span);
|
||||||
.span_label(expr.span, "left-hand of expression not valid")
|
|
||||||
.emit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.require_type_is_sized(lhs_ty, lhs.span, traits::AssignmentLhsSized);
|
self.require_type_is_sized(lhs_ty, lhs.span, traits::AssignmentLhsSized);
|
||||||
|
@ -19,30 +19,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
&self,
|
&self,
|
||||||
expr: &'tcx hir::Expr,
|
expr: &'tcx hir::Expr,
|
||||||
op: hir::BinOp,
|
op: hir::BinOp,
|
||||||
lhs_expr: &'tcx hir::Expr,
|
lhs: &'tcx hir::Expr,
|
||||||
rhs_expr: &'tcx hir::Expr,
|
rhs: &'tcx hir::Expr,
|
||||||
) -> Ty<'tcx> {
|
) -> Ty<'tcx> {
|
||||||
let (lhs_ty, rhs_ty, return_ty) =
|
let (lhs_ty, rhs_ty, return_ty) =
|
||||||
self.check_overloaded_binop(expr, lhs_expr, rhs_expr, op, IsAssign::Yes);
|
self.check_overloaded_binop(expr, lhs, rhs, op, IsAssign::Yes);
|
||||||
|
|
||||||
let ty =
|
let ty =
|
||||||
if !lhs_ty.is_ty_var() && !rhs_ty.is_ty_var() && is_builtin_binop(lhs_ty, rhs_ty, op) {
|
if !lhs_ty.is_ty_var() && !rhs_ty.is_ty_var() && is_builtin_binop(lhs_ty, rhs_ty, op) {
|
||||||
self.enforce_builtin_binop_types(lhs_expr, lhs_ty, rhs_expr, rhs_ty, op);
|
self.enforce_builtin_binop_types(lhs, lhs_ty, rhs, rhs_ty, op);
|
||||||
self.tcx.mk_unit()
|
self.tcx.mk_unit()
|
||||||
} else {
|
} else {
|
||||||
return_ty
|
return_ty
|
||||||
};
|
};
|
||||||
|
|
||||||
if !lhs_expr.is_syntactic_place_expr() {
|
self.check_lhs_assignable(lhs, "E0067", &op.span);
|
||||||
struct_span_err!(
|
|
||||||
self.tcx.sess,
|
|
||||||
lhs_expr.span,
|
|
||||||
E0067,
|
|
||||||
"invalid left-hand side expression"
|
|
||||||
)
|
|
||||||
.span_label(lhs_expr.span, "invalid expression for left-hand side")
|
|
||||||
.emit();
|
|
||||||
}
|
|
||||||
ty
|
ty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,7 +286,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hir::ExprKind::Assign(ref lhs, ref rhs) => {
|
hir::ExprKind::Assign(ref lhs, ref rhs, _) => {
|
||||||
self.mutate_expr(lhs);
|
self.mutate_expr(lhs);
|
||||||
self.consume_expr(rhs);
|
self.consume_expr(rhs);
|
||||||
}
|
}
|
||||||
|
@ -138,6 +138,22 @@ function getSearchElement() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showSearchResults(search) {
|
||||||
|
if (search === null || typeof search === 'undefined') {
|
||||||
|
search = getSearchElement();
|
||||||
|
}
|
||||||
|
addClass(main, "hidden");
|
||||||
|
removeClass(search, "hidden");
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideSearchResults(search) {
|
||||||
|
if (search === null || typeof search === 'undefined') {
|
||||||
|
search = getSearchElement();
|
||||||
|
}
|
||||||
|
addClass(search, "hidden");
|
||||||
|
removeClass(main, "hidden");
|
||||||
|
}
|
||||||
|
|
||||||
// used for special search precedence
|
// used for special search precedence
|
||||||
var TY_PRIMITIVE = itemTypes.indexOf("primitive");
|
var TY_PRIMITIVE = itemTypes.indexOf("primitive");
|
||||||
var TY_KEYWORD = itemTypes.indexOf("keyword");
|
var TY_KEYWORD = itemTypes.indexOf("keyword");
|
||||||
@ -169,8 +185,7 @@ function getSearchElement() {
|
|||||||
if (ev !== null && search && !hasClass(search, "hidden") && ev.newURL) {
|
if (ev !== null && search && !hasClass(search, "hidden") && ev.newURL) {
|
||||||
// This block occurs when clicking on an element in the navbar while
|
// This block occurs when clicking on an element in the navbar while
|
||||||
// in a search.
|
// in a search.
|
||||||
addClass(search, "hidden");
|
hideSearchResults(search);
|
||||||
removeClass(main, "hidden");
|
|
||||||
var hash = ev.newURL.slice(ev.newURL.indexOf("#") + 1);
|
var hash = ev.newURL.slice(ev.newURL.indexOf("#") + 1);
|
||||||
if (browserSupportsHistoryApi()) {
|
if (browserSupportsHistoryApi()) {
|
||||||
history.replaceState(hash, "", "?search=#" + hash);
|
history.replaceState(hash, "", "?search=#" + hash);
|
||||||
@ -331,8 +346,7 @@ function getSearchElement() {
|
|||||||
displayHelp(false, ev, help);
|
displayHelp(false, ev, help);
|
||||||
} else if (hasClass(search, "hidden") === false) {
|
} else if (hasClass(search, "hidden") === false) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
addClass(search, "hidden");
|
hideSearchResults(search);
|
||||||
removeClass(main, "hidden");
|
|
||||||
document.title = titleBeforeSearch;
|
document.title = titleBeforeSearch;
|
||||||
}
|
}
|
||||||
defocusSearchBar();
|
defocusSearchBar();
|
||||||
@ -390,8 +404,8 @@ function getSearchElement() {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
document.onkeypress = handleShortcut;
|
document.addEventListener("keypress", handleShortcut);
|
||||||
document.onkeydown = handleShortcut;
|
document.addEventListener("keydown", handleShortcut);
|
||||||
|
|
||||||
var handleSourceHighlight = (function() {
|
var handleSourceHighlight = (function() {
|
||||||
var prev_line_id = 0;
|
var prev_line_id = 0;
|
||||||
@ -430,7 +444,7 @@ function getSearchElement() {
|
|||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
document.onclick = function(ev) {
|
document.addEventListener("click", function(ev) {
|
||||||
if (hasClass(ev.target, "collapse-toggle")) {
|
if (hasClass(ev.target, "collapse-toggle")) {
|
||||||
collapseDocs(ev.target, "toggle");
|
collapseDocs(ev.target, "toggle");
|
||||||
} else if (hasClass(ev.target.parentNode, "collapse-toggle")) {
|
} else if (hasClass(ev.target.parentNode, "collapse-toggle")) {
|
||||||
@ -452,7 +466,7 @@ function getSearchElement() {
|
|||||||
expandSection(a.hash.replace(/^#/, ""));
|
expandSection(a.hash.replace(/^#/, ""));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
|
|
||||||
var x = document.getElementsByClassName("version-selector");
|
var x = document.getElementsByClassName("version-selector");
|
||||||
if (x.length > 0) {
|
if (x.length > 0) {
|
||||||
@ -1264,8 +1278,7 @@ function getSearchElement() {
|
|||||||
}
|
}
|
||||||
dst = dst[0];
|
dst = dst[0];
|
||||||
if (window.location.pathname === dst.pathname) {
|
if (window.location.pathname === dst.pathname) {
|
||||||
addClass(getSearchElement(), "hidden");
|
hideSearchResults();
|
||||||
removeClass(main, "hidden");
|
|
||||||
document.location.href = dst.href;
|
document.location.href = dst.href;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1340,8 +1353,6 @@ function getSearchElement() {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
} else if (e.which === 16) { // shift
|
} else if (e.which === 16) { // shift
|
||||||
// Does nothing, it's just to avoid losing "focus" on the highlighted element.
|
// Does nothing, it's just to avoid losing "focus" on the highlighted element.
|
||||||
} else if (e.which === 27) { // escape
|
|
||||||
handleEscape(e);
|
|
||||||
} else if (actives[currentTab].length > 0) {
|
} else if (actives[currentTab].length > 0) {
|
||||||
removeClass(actives[currentTab][0], "highlighted");
|
removeClass(actives[currentTab][0], "highlighted");
|
||||||
}
|
}
|
||||||
@ -1491,10 +1502,9 @@ function getSearchElement() {
|
|||||||
"</div><div id=\"results\">" +
|
"</div><div id=\"results\">" +
|
||||||
ret_others[0] + ret_in_args[0] + ret_returned[0] + "</div>";
|
ret_others[0] + ret_in_args[0] + ret_returned[0] + "</div>";
|
||||||
|
|
||||||
addClass(main, "hidden");
|
|
||||||
var search = getSearchElement();
|
var search = getSearchElement();
|
||||||
removeClass(search, "hidden");
|
|
||||||
search.innerHTML = output;
|
search.innerHTML = output;
|
||||||
|
showSearchResults(search);
|
||||||
var tds = search.getElementsByTagName("td");
|
var tds = search.getElementsByTagName("td");
|
||||||
var td_width = 0;
|
var td_width = 0;
|
||||||
if (tds.length > 0) {
|
if (tds.length > 0) {
|
||||||
@ -1699,13 +1709,7 @@ function getSearchElement() {
|
|||||||
if (browserSupportsHistoryApi()) {
|
if (browserSupportsHistoryApi()) {
|
||||||
history.replaceState("", window.currentCrate + " - Rust", "?search=");
|
history.replaceState("", window.currentCrate + " - Rust", "?search=");
|
||||||
}
|
}
|
||||||
if (hasClass(main, "content")) {
|
hideSearchResults();
|
||||||
removeClass(main, "hidden");
|
|
||||||
}
|
|
||||||
var search_c = getSearchElement();
|
|
||||||
if (hasClass(search_c, "content")) {
|
|
||||||
addClass(search_c, "hidden");
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
searchTimeout = setTimeout(search, 500);
|
searchTimeout = setTimeout(search, 500);
|
||||||
}
|
}
|
||||||
@ -1718,6 +1722,10 @@ function getSearchElement() {
|
|||||||
search();
|
search();
|
||||||
};
|
};
|
||||||
search_input.onchange = function(e) {
|
search_input.onchange = function(e) {
|
||||||
|
if (e.target !== document.activeElement) {
|
||||||
|
// To prevent doing anything when it's from a blur event.
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Do NOT e.preventDefault() here. It will prevent pasting.
|
// Do NOT e.preventDefault() here. It will prevent pasting.
|
||||||
clearTimeout(searchTimeout);
|
clearTimeout(searchTimeout);
|
||||||
// zero-timeout necessary here because at the time of event handler execution the
|
// zero-timeout necessary here because at the time of event handler execution the
|
||||||
@ -1741,19 +1749,8 @@ function getSearchElement() {
|
|||||||
// Store the previous <title> so we can revert back to it later.
|
// Store the previous <title> so we can revert back to it later.
|
||||||
var previousTitle = document.title;
|
var previousTitle = document.title;
|
||||||
|
|
||||||
window.onpopstate = function(e) {
|
window.addEventListener("popstate", function(e) {
|
||||||
var params = getQueryStringParams();
|
var params = getQueryStringParams();
|
||||||
// When browsing back from search results the main page
|
|
||||||
// visibility must be reset.
|
|
||||||
if (!params.search) {
|
|
||||||
if (hasClass(main, "content")) {
|
|
||||||
removeClass(main, "hidden");
|
|
||||||
}
|
|
||||||
var search_c = getSearchElement();
|
|
||||||
if (hasClass(search_c, "content")) {
|
|
||||||
addClass(search_c, "hidden");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Revert to the previous title manually since the History
|
// Revert to the previous title manually since the History
|
||||||
// API ignores the title parameter.
|
// API ignores the title parameter.
|
||||||
document.title = previousTitle;
|
document.title = previousTitle;
|
||||||
@ -1765,18 +1762,21 @@ function getSearchElement() {
|
|||||||
// perform the search. This will empty the bar if there's
|
// perform the search. This will empty the bar if there's
|
||||||
// nothing there, which lets you really go back to a
|
// nothing there, which lets you really go back to a
|
||||||
// previous state with nothing in the bar.
|
// previous state with nothing in the bar.
|
||||||
if (params.search) {
|
if (params.search && params.search.length > 0) {
|
||||||
search_input.value = params.search;
|
search_input.value = params.search;
|
||||||
|
// Some browsers fire "onpopstate" for every page load
|
||||||
|
// (Chrome), while others fire the event only when actually
|
||||||
|
// popping a state (Firefox), which is why search() is
|
||||||
|
// called both here and at the end of the startSearch()
|
||||||
|
// function.
|
||||||
|
search(e);
|
||||||
} else {
|
} else {
|
||||||
search_input.value = "";
|
search_input.value = "";
|
||||||
|
// When browsing back from search results the main page
|
||||||
|
// visibility must be reset.
|
||||||
|
hideSearchResults();
|
||||||
}
|
}
|
||||||
// Some browsers fire "onpopstate" for every page load
|
});
|
||||||
// (Chrome), while others fire the event only when actually
|
|
||||||
// popping a state (Firefox), which is why search() is
|
|
||||||
// called both here and at the end of the startSearch()
|
|
||||||
// function.
|
|
||||||
search();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
search();
|
search();
|
||||||
}
|
}
|
||||||
@ -2522,9 +2522,9 @@ function getSearchElement() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function putBackSearch(search_input) {
|
function putBackSearch(search_input) {
|
||||||
if (search_input.value !== "") {
|
var search = getSearchElement();
|
||||||
addClass(main, "hidden");
|
if (search_input.value !== "" && hasClass(search, "hidden")) {
|
||||||
removeClass(getSearchElement(), "hidden");
|
showSearchResults(search);
|
||||||
if (browserSupportsHistoryApi()) {
|
if (browserSupportsHistoryApi()) {
|
||||||
history.replaceState(search_input.value,
|
history.replaceState(search_input.value,
|
||||||
"",
|
"",
|
||||||
@ -2541,10 +2541,9 @@ function getSearchElement() {
|
|||||||
|
|
||||||
var params = getQueryStringParams();
|
var params = getQueryStringParams();
|
||||||
if (params && params.search) {
|
if (params && params.search) {
|
||||||
addClass(main, "hidden");
|
|
||||||
var search = getSearchElement();
|
var search = getSearchElement();
|
||||||
removeClass(search, "hidden");
|
|
||||||
search.innerHTML = "<h3 style=\"text-align: center;\">Loading search results...</h3>";
|
search.innerHTML = "<h3 style=\"text-align: center;\">Loading search results...</h3>";
|
||||||
|
showSearchResults(search);
|
||||||
}
|
}
|
||||||
|
|
||||||
var sidebar_menu = document.getElementsByClassName("sidebar-menu")[0];
|
var sidebar_menu = document.getElementsByClassName("sidebar-menu")[0];
|
||||||
|
@ -72,7 +72,7 @@ use core::convert::TryInto;
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
||||||
pub struct Cursor<T> {
|
pub struct Cursor<T> {
|
||||||
inner: T,
|
inner: T,
|
||||||
pos: u64,
|
pos: u64,
|
||||||
@ -942,4 +942,16 @@ mod tests {
|
|||||||
c.set_position(<usize>::max_value() as u64 + 1);
|
c.set_position(<usize>::max_value() as u64 + 1);
|
||||||
assert!(c.write_all(&[1, 2, 3]).is_err());
|
assert!(c.write_all(&[1, 2, 3]).is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_partial_eq() {
|
||||||
|
assert_eq!(Cursor::new(Vec::<u8>::new()), Cursor::new(Vec::<u8>::new()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_eq() {
|
||||||
|
struct AssertEq<T: Eq>(pub T);
|
||||||
|
|
||||||
|
let _: AssertEq<Cursor<Vec<u8>>> = AssertEq(Cursor::new(Vec::new()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1216,7 +1216,8 @@ pub enum ExprKind {
|
|||||||
TryBlock(P<Block>),
|
TryBlock(P<Block>),
|
||||||
|
|
||||||
/// An assignment (`a = foo()`).
|
/// An assignment (`a = foo()`).
|
||||||
Assign(P<Expr>, P<Expr>),
|
/// The `Span` argument is the span of the `=` token.
|
||||||
|
Assign(P<Expr>, P<Expr>, Span),
|
||||||
/// An assignment with an operator.
|
/// An assignment with an operator.
|
||||||
///
|
///
|
||||||
/// E.g., `a += 1`.
|
/// E.g., `a += 1`.
|
||||||
|
@ -1168,7 +1168,7 @@ pub fn noop_visit_expr<T: MutVisitor>(Expr { kind, id, span, attrs }: &mut Expr,
|
|||||||
vis.visit_block(body);
|
vis.visit_block(body);
|
||||||
}
|
}
|
||||||
ExprKind::Await(expr) => vis.visit_expr(expr),
|
ExprKind::Await(expr) => vis.visit_expr(expr),
|
||||||
ExprKind::Assign(el, er) => {
|
ExprKind::Assign(el, er, _) => {
|
||||||
vis.visit_expr(el);
|
vis.visit_expr(el);
|
||||||
vis.visit_expr(er);
|
vis.visit_expr(er);
|
||||||
}
|
}
|
||||||
|
@ -2041,7 +2041,7 @@ impl<'a> State<'a> {
|
|||||||
self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX);
|
self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX);
|
||||||
self.s.word(".await");
|
self.s.word(".await");
|
||||||
}
|
}
|
||||||
ast::ExprKind::Assign(ref lhs, ref rhs) => {
|
ast::ExprKind::Assign(ref lhs, ref rhs, _) => {
|
||||||
let prec = AssocOp::Assign.precedence() as i8;
|
let prec = AssocOp::Assign.precedence() as i8;
|
||||||
self.print_expr_maybe_paren(lhs, prec + 1);
|
self.print_expr_maybe_paren(lhs, prec + 1);
|
||||||
self.s.space();
|
self.s.space();
|
||||||
|
@ -378,7 +378,7 @@ pub fn contains_exterior_struct_lit(value: &ast::Expr) -> bool {
|
|||||||
match value.kind {
|
match value.kind {
|
||||||
ast::ExprKind::Struct(..) => true,
|
ast::ExprKind::Struct(..) => true,
|
||||||
|
|
||||||
ast::ExprKind::Assign(ref lhs, ref rhs)
|
ast::ExprKind::Assign(ref lhs, ref rhs, _)
|
||||||
| ast::ExprKind::AssignOp(_, ref lhs, ref rhs)
|
| ast::ExprKind::AssignOp(_, ref lhs, ref rhs)
|
||||||
| ast::ExprKind::Binary(_, ref lhs, ref rhs) => {
|
| ast::ExprKind::Binary(_, ref lhs, ref rhs) => {
|
||||||
// X { y: 1 } + X { y: 2 }
|
// X { y: 1 } + X { y: 2 }
|
||||||
|
@ -766,9 +766,9 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
|
|||||||
visitor.visit_block(body);
|
visitor.visit_block(body);
|
||||||
}
|
}
|
||||||
ExprKind::Await(ref expr) => visitor.visit_expr(expr),
|
ExprKind::Await(ref expr) => visitor.visit_expr(expr),
|
||||||
ExprKind::Assign(ref left_hand_expression, ref right_hand_expression) => {
|
ExprKind::Assign(ref lhs, ref rhs, _) => {
|
||||||
visitor.visit_expr(left_hand_expression);
|
visitor.visit_expr(lhs);
|
||||||
visitor.visit_expr(right_hand_expression);
|
visitor.visit_expr(rhs);
|
||||||
}
|
}
|
||||||
ExprKind::AssignOp(_, ref left_expression, ref right_expression) => {
|
ExprKind::AssignOp(_, ref left_expression, ref right_expression) => {
|
||||||
visitor.visit_expr(left_expression);
|
visitor.visit_expr(left_expression);
|
||||||
|
@ -7,3 +7,5 @@
|
|||||||
all:
|
all:
|
||||||
$(RUSTC) -g -Z sanitizer=memory -Z print-link-args uninit.rs | $(CGREP) librustc_msan
|
$(RUSTC) -g -Z sanitizer=memory -Z print-link-args uninit.rs | $(CGREP) librustc_msan
|
||||||
$(TMPDIR)/uninit 2>&1 | $(CGREP) use-of-uninitialized-value
|
$(TMPDIR)/uninit 2>&1 | $(CGREP) use-of-uninitialized-value
|
||||||
|
$(RUSTC) -g -Z sanitizer=memory -Z print-link-args maybeuninit.rs | $(CGREP) librustc_msan
|
||||||
|
$(TMPDIR)/maybeuninit 2>&1 | $(CGREP) use-of-uninitialized-value
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
use std::mem::MaybeUninit;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// This is technically not sound -- but we're literally trying to test
|
||||||
|
// that the sanitizer catches this, so I guess "intentionally unsound"?
|
||||||
|
let xs: [u8; 4] = unsafe { MaybeUninit::uninit().assume_init() };
|
||||||
|
let y = xs[0] + xs[1];
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
use std::mem;
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
// This is technically not sound -- but we're literally trying to test
|
||||||
|
// that the sanitizer catches this, so I guess "intentionally unsound"?
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
let xs: [u8; 4] = unsafe { mem::uninitialized() };
|
let xs: [u8; 4] = unsafe { std::mem::uninitialized() };
|
||||||
let y = xs[0] + xs[1];
|
let y = xs[0] + xs[1];
|
||||||
}
|
}
|
||||||
|
@ -105,8 +105,7 @@ impl<U: Unsigned, B: Bit> Add<B0> for UInt<U, B> {
|
|||||||
impl<U: Unsigned> Add<U> for UTerm {
|
impl<U: Unsigned> Add<U> for UTerm {
|
||||||
type Output = U;
|
type Output = U;
|
||||||
fn add(self, _: U) -> Self::Output {
|
fn add(self, _: U) -> Self::Output {
|
||||||
#[allow(deprecated)]
|
unimplemented!()
|
||||||
unsafe { ::std::mem::uninitialized() }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,7 +136,7 @@ where
|
|||||||
{
|
{
|
||||||
type Output = UInt<Prod<Ul, UInt<Ur, B>>, B0>;
|
type Output = UInt<Prod<Ul, UInt<Ur, B>>, B0>;
|
||||||
fn mul(self, _: UInt<Ur, B>) -> Self::Output {
|
fn mul(self, _: UInt<Ur, B>) -> Self::Output {
|
||||||
unsafe { ::std::mem::uninitialized() }
|
unimplemented!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,8 +126,8 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) {
|
|||||||
DUMMY_SP)));
|
DUMMY_SP)));
|
||||||
},
|
},
|
||||||
12 => {
|
12 => {
|
||||||
iter_exprs(depth - 1, &mut |e| g(ExprKind::Assign(e, make_x())));
|
iter_exprs(depth - 1, &mut |e| g(ExprKind::Assign(e, make_x(), DUMMY_SP)));
|
||||||
iter_exprs(depth - 1, &mut |e| g(ExprKind::Assign(make_x(), e)));
|
iter_exprs(depth - 1, &mut |e| g(ExprKind::Assign(make_x(), e, DUMMY_SP)));
|
||||||
},
|
},
|
||||||
13 => {
|
13 => {
|
||||||
iter_exprs(depth - 1, &mut |e| g(ExprKind::Field(e, Ident::from_str("f"))));
|
iter_exprs(depth - 1, &mut |e| g(ExprKind::Field(e, Ident::from_str("f"))));
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
// ignore-sgx no processes
|
// ignore-sgx no processes
|
||||||
// ignore-musl FIXME #31506
|
// ignore-musl FIXME #31506
|
||||||
|
|
||||||
use std::mem;
|
use std::mem::MaybeUninit;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::env;
|
use std::env;
|
||||||
@ -28,8 +28,8 @@ fn main() {
|
|||||||
let args = env::args().skip(1).collect::<Vec<_>>();
|
let args = env::args().skip(1).collect::<Vec<_>>();
|
||||||
if args.len() > 0 {
|
if args.len() > 0 {
|
||||||
match &args[0][..] {
|
match &args[0][..] {
|
||||||
"main-thread" => recurse(&[]),
|
"main-thread" => recurse(&MaybeUninit::uninit()),
|
||||||
"child-thread" => thread::spawn(|| recurse(&[])).join().unwrap(),
|
"child-thread" => thread::spawn(|| recurse(&MaybeUninit::uninit())).join().unwrap(),
|
||||||
_ => panic!(),
|
_ => panic!(),
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@ -48,10 +48,11 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unconditional_recursion)]
|
#[allow(unconditional_recursion)]
|
||||||
fn recurse(array: &[u64]) {
|
fn recurse(array: &MaybeUninit<[u64; 1024]>) {
|
||||||
unsafe { black_box(array.as_ptr() as u64); }
|
unsafe {
|
||||||
#[allow(deprecated)]
|
black_box(array.as_ptr() as u64);
|
||||||
let local: [_; 1024] = unsafe { mem::uninitialized() };
|
}
|
||||||
|
let local: MaybeUninit<[u64; 1024]> = MaybeUninit::uninit();
|
||||||
recurse(&local);
|
recurse(&local);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
fn main() {
|
fn main() {
|
||||||
1 = 2; //~ ERROR invalid left-hand side expression
|
1 = 2; //~ ERROR invalid left-hand side of assignment
|
||||||
1 += 2; //~ ERROR invalid left-hand side expression
|
1 += 2; //~ ERROR invalid left-hand side of assignment
|
||||||
(1, 2) = (3, 4); //~ ERROR invalid left-hand side expression
|
(1, 2) = (3, 4); //~ ERROR invalid left-hand side of assignment
|
||||||
|
|
||||||
let (a, b) = (1, 2);
|
let (a, b) = (1, 2);
|
||||||
(a, b) = (3, 4); //~ ERROR invalid left-hand side expression
|
(a, b) = (3, 4); //~ ERROR invalid left-hand side of assignment
|
||||||
|
|
||||||
None = Some(3); //~ ERROR invalid left-hand side expression
|
None = Some(3); //~ ERROR invalid left-hand side of assignment
|
||||||
}
|
}
|
||||||
|
@ -1,32 +1,45 @@
|
|||||||
error[E0070]: invalid left-hand side expression
|
error[E0070]: invalid left-hand side of assignment
|
||||||
--> $DIR/bad-expr-lhs.rs:2:5
|
--> $DIR/bad-expr-lhs.rs:2:7
|
||||||
|
|
|
|
||||||
LL | 1 = 2;
|
LL | 1 = 2;
|
||||||
| ^^^^^ left-hand of expression not valid
|
| - ^
|
||||||
|
| |
|
||||||
|
| cannot assign to this expression
|
||||||
|
|
||||||
error[E0067]: invalid left-hand side expression
|
error[E0067]: invalid left-hand side of assignment
|
||||||
--> $DIR/bad-expr-lhs.rs:3:5
|
--> $DIR/bad-expr-lhs.rs:3:7
|
||||||
|
|
|
|
||||||
LL | 1 += 2;
|
LL | 1 += 2;
|
||||||
| ^ invalid expression for left-hand side
|
| - ^^
|
||||||
|
| |
|
||||||
|
| cannot assign to this expression
|
||||||
|
|
||||||
error[E0070]: invalid left-hand side expression
|
error[E0070]: invalid left-hand side of assignment
|
||||||
--> $DIR/bad-expr-lhs.rs:4:5
|
--> $DIR/bad-expr-lhs.rs:4:12
|
||||||
|
|
|
|
||||||
LL | (1, 2) = (3, 4);
|
LL | (1, 2) = (3, 4);
|
||||||
| ^^^^^^^^^^^^^^^ left-hand of expression not valid
|
| ------ ^
|
||||||
|
| |
|
||||||
|
| cannot assign to this expression
|
||||||
|
|
||||||
error[E0070]: invalid left-hand side expression
|
error[E0070]: invalid left-hand side of assignment
|
||||||
--> $DIR/bad-expr-lhs.rs:7:5
|
--> $DIR/bad-expr-lhs.rs:7:12
|
||||||
|
|
|
|
||||||
LL | (a, b) = (3, 4);
|
LL | (a, b) = (3, 4);
|
||||||
| ^^^^^^^^^^^^^^^ left-hand of expression not valid
|
| ------ ^
|
||||||
|
| |
|
||||||
|
| cannot assign to this expression
|
||||||
|
|
|
||||||
|
= note: destructuring assignments are not currently supported
|
||||||
|
= note: for more information, see https://github.com/rust-lang/rfcs/issues/372
|
||||||
|
|
||||||
error[E0070]: invalid left-hand side expression
|
error[E0070]: invalid left-hand side of assignment
|
||||||
--> $DIR/bad-expr-lhs.rs:9:5
|
--> $DIR/bad-expr-lhs.rs:9:10
|
||||||
|
|
|
|
||||||
LL | None = Some(3);
|
LL | None = Some(3);
|
||||||
| ^^^^^^^^^^^^^^ left-hand of expression not valid
|
| ---- ^
|
||||||
|
| |
|
||||||
|
| cannot assign to this expression
|
||||||
|
|
||||||
error: aborting due to 5 previous errors
|
error: aborting due to 5 previous errors
|
||||||
|
|
||||||
|
@ -5,6 +5,10 @@
|
|||||||
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
|
// Neither of the uninits below are currently accepted as not UB, however,
|
||||||
|
// this code does not run and is merely checking that we do not ICE on this pattern,
|
||||||
|
// so this is fine.
|
||||||
|
|
||||||
fn foo<const SIZE: usize>() {
|
fn foo<const SIZE: usize>() {
|
||||||
let arr: [u8; SIZE] = unsafe {
|
let arr: [u8; SIZE] = unsafe {
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
@ -13,4 +17,12 @@ fn foo<const SIZE: usize>() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn bar<const SIZE: usize>() {
|
||||||
|
let arr: [u8; SIZE] = unsafe {
|
||||||
|
let array: [u8; SIZE] = mem::MaybeUninit::uninit().assume_init();
|
||||||
|
array
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
#![feature(const_fn)]
|
#![feature(const_fn)]
|
||||||
#![feature(repr_simd)]
|
#![feature(repr_simd)]
|
||||||
#![feature(platform_intrinsics)]
|
#![feature(platform_intrinsics)]
|
||||||
|
#![feature(staged_api)]
|
||||||
|
#![stable(feature = "foo", since = "1.33.7")]
|
||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
|
|
||||||
#[repr(simd)] struct i8x1(i8);
|
#[repr(simd)] struct i8x1(i8);
|
||||||
@ -9,7 +11,9 @@
|
|||||||
#[repr(simd)] struct f32x3(f32, f32, f32);
|
#[repr(simd)] struct f32x3(f32, f32, f32);
|
||||||
|
|
||||||
extern "platform-intrinsic" {
|
extern "platform-intrinsic" {
|
||||||
|
#[rustc_const_stable(feature = "foo", since = "1.3.37")]
|
||||||
fn simd_insert<T, U>(x: T, idx: u32, val: U) -> T;
|
fn simd_insert<T, U>(x: T, idx: u32, val: U) -> T;
|
||||||
|
#[rustc_const_stable(feature = "foo", since = "1.3.37")]
|
||||||
fn simd_extract<T, U>(x: T, idx: u32) -> U;
|
fn simd_extract<T, U>(x: T, idx: u32) -> U;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#![feature(core_intrinsics)]
|
#![feature(core_intrinsics)]
|
||||||
#![feature(const_fn)]
|
#![feature(const_fn)]
|
||||||
|
#![feature(const_type_name)]
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
const fn type_name_wrapper<T>(_: &T) -> &'static str {
|
const fn type_name_wrapper<T>(_: &T) -> &'static str {
|
||||||
|
9
src/test/ui/consts/const_prop_slice_pat_ice.rs
Normal file
9
src/test/ui/consts/const_prop_slice_pat_ice.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
// check-pass
|
||||||
|
#![feature(slice_patterns)]
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
match &[0, 1] as &[i32] {
|
||||||
|
[a @ .., x] => {}
|
||||||
|
&[] => {}
|
||||||
|
}
|
||||||
|
}
|
25
src/test/ui/destructuring-assignment/note-unsupported.rs
Normal file
25
src/test/ui/destructuring-assignment/note-unsupported.rs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
struct S { x: u8, y: u8 }
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let (a, b) = (1, 2);
|
||||||
|
|
||||||
|
(a, b) = (3, 4); //~ ERROR invalid left-hand side of assignment
|
||||||
|
(a, b) += (3, 4); //~ ERROR invalid left-hand side of assignment
|
||||||
|
//~^ ERROR binary assignment operation `+=` cannot be applied
|
||||||
|
|
||||||
|
[a, b] = [3, 4]; //~ ERROR invalid left-hand side of assignment
|
||||||
|
[a, b] += [3, 4]; //~ ERROR invalid left-hand side of assignment
|
||||||
|
//~^ ERROR binary assignment operation `+=` cannot be applied
|
||||||
|
|
||||||
|
let s = S { x: 3, y: 4 };
|
||||||
|
|
||||||
|
S { x: a, y: b } = s; //~ ERROR invalid left-hand side of assignment
|
||||||
|
S { x: a, y: b } += s; //~ ERROR invalid left-hand side of assignment
|
||||||
|
//~^ ERROR binary assignment operation `+=` cannot be applied
|
||||||
|
|
||||||
|
S { x: a, ..s } = S { x: 3, y: 4 }; //~ ERROR invalid left-hand side of assignment
|
||||||
|
|
||||||
|
let c = 3;
|
||||||
|
|
||||||
|
((a, b), c) = ((3, 4), 5); //~ ERROR invalid left-hand side of assignment
|
||||||
|
}
|
122
src/test/ui/destructuring-assignment/note-unsupported.stderr
Normal file
122
src/test/ui/destructuring-assignment/note-unsupported.stderr
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
error[E0070]: invalid left-hand side of assignment
|
||||||
|
--> $DIR/note-unsupported.rs:6:12
|
||||||
|
|
|
||||||
|
LL | (a, b) = (3, 4);
|
||||||
|
| ------ ^
|
||||||
|
| |
|
||||||
|
| cannot assign to this expression
|
||||||
|
|
|
||||||
|
= note: destructuring assignments are not currently supported
|
||||||
|
= note: for more information, see https://github.com/rust-lang/rfcs/issues/372
|
||||||
|
|
||||||
|
error[E0368]: binary assignment operation `+=` cannot be applied to type `({integer}, {integer})`
|
||||||
|
--> $DIR/note-unsupported.rs:7:5
|
||||||
|
|
|
||||||
|
LL | (a, b) += (3, 4);
|
||||||
|
| ------^^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| cannot use `+=` on type `({integer}, {integer})`
|
||||||
|
|
|
||||||
|
= note: an implementation of `std::ops::AddAssign` might be missing for `({integer}, {integer})`
|
||||||
|
|
||||||
|
error[E0067]: invalid left-hand side of assignment
|
||||||
|
--> $DIR/note-unsupported.rs:7:12
|
||||||
|
|
|
||||||
|
LL | (a, b) += (3, 4);
|
||||||
|
| ------ ^^
|
||||||
|
| |
|
||||||
|
| cannot assign to this expression
|
||||||
|
|
|
||||||
|
= note: destructuring assignments are not currently supported
|
||||||
|
= note: for more information, see https://github.com/rust-lang/rfcs/issues/372
|
||||||
|
|
||||||
|
error[E0070]: invalid left-hand side of assignment
|
||||||
|
--> $DIR/note-unsupported.rs:10:12
|
||||||
|
|
|
||||||
|
LL | [a, b] = [3, 4];
|
||||||
|
| ------ ^
|
||||||
|
| |
|
||||||
|
| cannot assign to this expression
|
||||||
|
|
|
||||||
|
= note: destructuring assignments are not currently supported
|
||||||
|
= note: for more information, see https://github.com/rust-lang/rfcs/issues/372
|
||||||
|
|
||||||
|
error[E0368]: binary assignment operation `+=` cannot be applied to type `[{integer}; 2]`
|
||||||
|
--> $DIR/note-unsupported.rs:11:5
|
||||||
|
|
|
||||||
|
LL | [a, b] += [3, 4];
|
||||||
|
| ------^^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| cannot use `+=` on type `[{integer}; 2]`
|
||||||
|
|
|
||||||
|
= note: an implementation of `std::ops::AddAssign` might be missing for `[{integer}; 2]`
|
||||||
|
|
||||||
|
error[E0067]: invalid left-hand side of assignment
|
||||||
|
--> $DIR/note-unsupported.rs:11:12
|
||||||
|
|
|
||||||
|
LL | [a, b] += [3, 4];
|
||||||
|
| ------ ^^
|
||||||
|
| |
|
||||||
|
| cannot assign to this expression
|
||||||
|
|
|
||||||
|
= note: destructuring assignments are not currently supported
|
||||||
|
= note: for more information, see https://github.com/rust-lang/rfcs/issues/372
|
||||||
|
|
||||||
|
error[E0070]: invalid left-hand side of assignment
|
||||||
|
--> $DIR/note-unsupported.rs:16:22
|
||||||
|
|
|
||||||
|
LL | S { x: a, y: b } = s;
|
||||||
|
| ---------------- ^
|
||||||
|
| |
|
||||||
|
| cannot assign to this expression
|
||||||
|
|
|
||||||
|
= note: destructuring assignments are not currently supported
|
||||||
|
= note: for more information, see https://github.com/rust-lang/rfcs/issues/372
|
||||||
|
|
||||||
|
error[E0368]: binary assignment operation `+=` cannot be applied to type `S`
|
||||||
|
--> $DIR/note-unsupported.rs:17:5
|
||||||
|
|
|
||||||
|
LL | S { x: a, y: b } += s;
|
||||||
|
| ----------------^^^^^
|
||||||
|
| |
|
||||||
|
| cannot use `+=` on type `S`
|
||||||
|
|
|
||||||
|
= note: an implementation of `std::ops::AddAssign` might be missing for `S`
|
||||||
|
|
||||||
|
error[E0067]: invalid left-hand side of assignment
|
||||||
|
--> $DIR/note-unsupported.rs:17:22
|
||||||
|
|
|
||||||
|
LL | S { x: a, y: b } += s;
|
||||||
|
| ---------------- ^^
|
||||||
|
| |
|
||||||
|
| cannot assign to this expression
|
||||||
|
|
|
||||||
|
= note: destructuring assignments are not currently supported
|
||||||
|
= note: for more information, see https://github.com/rust-lang/rfcs/issues/372
|
||||||
|
|
||||||
|
error[E0070]: invalid left-hand side of assignment
|
||||||
|
--> $DIR/note-unsupported.rs:20:21
|
||||||
|
|
|
||||||
|
LL | S { x: a, ..s } = S { x: 3, y: 4 };
|
||||||
|
| --------------- ^
|
||||||
|
| |
|
||||||
|
| cannot assign to this expression
|
||||||
|
|
|
||||||
|
= note: destructuring assignments are not currently supported
|
||||||
|
= note: for more information, see https://github.com/rust-lang/rfcs/issues/372
|
||||||
|
|
||||||
|
error[E0070]: invalid left-hand side of assignment
|
||||||
|
--> $DIR/note-unsupported.rs:24:17
|
||||||
|
|
|
||||||
|
LL | ((a, b), c) = ((3, 4), 5);
|
||||||
|
| ----------- ^
|
||||||
|
| |
|
||||||
|
| cannot assign to this expression
|
||||||
|
|
|
||||||
|
= note: destructuring assignments are not currently supported
|
||||||
|
= note: for more information, see https://github.com/rust-lang/rfcs/issues/372
|
||||||
|
|
||||||
|
error: aborting due to 11 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0067, E0070, E0368.
|
||||||
|
For more information about an error, try `rustc --explain E0067`.
|
@ -8,11 +8,13 @@ LL | LinkedList::new() += 1;
|
|||||||
|
|
|
|
||||||
= note: an implementation of `std::ops::AddAssign` might be missing for `std::collections::LinkedList<_>`
|
= note: an implementation of `std::ops::AddAssign` might be missing for `std::collections::LinkedList<_>`
|
||||||
|
|
||||||
error[E0067]: invalid left-hand side expression
|
error[E0067]: invalid left-hand side of assignment
|
||||||
--> $DIR/E0067.rs:4:5
|
--> $DIR/E0067.rs:4:23
|
||||||
|
|
|
|
||||||
LL | LinkedList::new() += 1;
|
LL | LinkedList::new() += 1;
|
||||||
| ^^^^^^^^^^^^^^^^^ invalid expression for left-hand side
|
| ----------------- ^^
|
||||||
|
| |
|
||||||
|
| cannot assign to this expression
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
@ -1,14 +1,18 @@
|
|||||||
error[E0070]: invalid left-hand side expression
|
error[E0070]: invalid left-hand side of assignment
|
||||||
--> $DIR/E0070.rs:6:5
|
--> $DIR/E0070.rs:6:16
|
||||||
|
|
|
|
||||||
LL | SOME_CONST = 14;
|
LL | SOME_CONST = 14;
|
||||||
| ^^^^^^^^^^^^^^^ left-hand of expression not valid
|
| ---------- ^
|
||||||
|
| |
|
||||||
|
| cannot assign to this expression
|
||||||
|
|
||||||
error[E0070]: invalid left-hand side expression
|
error[E0070]: invalid left-hand side of assignment
|
||||||
--> $DIR/E0070.rs:7:5
|
--> $DIR/E0070.rs:7:7
|
||||||
|
|
|
|
||||||
LL | 1 = 3;
|
LL | 1 = 3;
|
||||||
| ^^^^^ left-hand of expression not valid
|
| - ^
|
||||||
|
| |
|
||||||
|
| cannot assign to this expression
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/E0070.rs:8:25
|
--> $DIR/E0070.rs:8:25
|
||||||
@ -16,11 +20,13 @@ error[E0308]: mismatched types
|
|||||||
LL | some_other_func() = 4;
|
LL | some_other_func() = 4;
|
||||||
| ^ expected `()`, found integer
|
| ^ expected `()`, found integer
|
||||||
|
|
||||||
error[E0070]: invalid left-hand side expression
|
error[E0070]: invalid left-hand side of assignment
|
||||||
--> $DIR/E0070.rs:8:5
|
--> $DIR/E0070.rs:8:23
|
||||||
|
|
|
|
||||||
LL | some_other_func() = 4;
|
LL | some_other_func() = 4;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^ left-hand of expression not valid
|
| ----------------- ^
|
||||||
|
| |
|
||||||
|
| cannot assign to this expression
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
fn main() {
|
fn main() {
|
||||||
// Check that the tail statement in the body unifies with something
|
// Check that the tail statement in the body unifies with something
|
||||||
for _ in 0..3 {
|
for _ in 0..3 {
|
||||||
#[allow(deprecated)]
|
// `()` is fine to zero-initialize as it is zero sized and inhabited.
|
||||||
unsafe { std::mem::uninitialized() }
|
unsafe { std::mem::zeroed() }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that the tail statement in the body can be unit
|
// Check that the tail statement in the body can be unit
|
||||||
|
@ -4,7 +4,7 @@ mod A {
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
A::C = 1;
|
A::C = 1;
|
||||||
//~^ ERROR: invalid left-hand side expression
|
//~^ ERROR: invalid left-hand side of assignment
|
||||||
//~| ERROR: mismatched types
|
//~| ERROR: mismatched types
|
||||||
//~| ERROR: struct `C` is private
|
//~| ERROR: struct `C` is private
|
||||||
}
|
}
|
||||||
|
@ -10,11 +10,13 @@ error[E0308]: mismatched types
|
|||||||
LL | A::C = 1;
|
LL | A::C = 1;
|
||||||
| ^ expected struct `A::C`, found integer
|
| ^ expected struct `A::C`, found integer
|
||||||
|
|
||||||
error[E0070]: invalid left-hand side expression
|
error[E0070]: invalid left-hand side of assignment
|
||||||
--> $DIR/issue-13407.rs:6:5
|
--> $DIR/issue-13407.rs:6:10
|
||||||
|
|
|
|
||||||
LL | A::C = 1;
|
LL | A::C = 1;
|
||||||
| ^^^^^^^^ left-hand of expression not valid
|
| ---- ^
|
||||||
|
| |
|
||||||
|
| cannot assign to this expression
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
macro_rules! not_a_place {
|
macro_rules! not_a_place {
|
||||||
($thing:expr) => {
|
($thing:expr) => {
|
||||||
$thing = 42;
|
$thing = 42;
|
||||||
//~^ ERROR invalid left-hand side expression
|
//~^ ERROR invalid left-hand side of assignment
|
||||||
|
$thing += 42;
|
||||||
|
//~^ ERROR invalid left-hand side of assignment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,12 +1,28 @@
|
|||||||
error[E0070]: invalid left-hand side expression
|
error[E0070]: invalid left-hand side of assignment
|
||||||
--> $DIR/issue-26093.rs:3:9
|
--> $DIR/issue-26093.rs:3:16
|
||||||
|
|
|
|
||||||
LL | $thing = 42;
|
LL | $thing = 42;
|
||||||
| ^^^^^^^^^^^ left-hand of expression not valid
|
| ^
|
||||||
...
|
...
|
||||||
LL | not_a_place!(99);
|
LL | not_a_place!(99);
|
||||||
| ----------------- in this macro invocation
|
| -----------------
|
||||||
|
| | |
|
||||||
|
| | cannot assign to this expression
|
||||||
|
| in this macro invocation
|
||||||
|
|
||||||
error: aborting due to previous error
|
error[E0067]: invalid left-hand side of assignment
|
||||||
|
--> $DIR/issue-26093.rs:5:16
|
||||||
|
|
|
||||||
|
LL | $thing += 42;
|
||||||
|
| ^^
|
||||||
|
...
|
||||||
|
LL | not_a_place!(99);
|
||||||
|
| -----------------
|
||||||
|
| | |
|
||||||
|
| | cannot assign to this expression
|
||||||
|
| in this macro invocation
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0070`.
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0067, E0070.
|
||||||
|
For more information about an error, try `rustc --explain E0067`.
|
||||||
|
@ -3,7 +3,7 @@ fn main () {
|
|||||||
//~^ ERROR expected one of `,` or `>`, found `=`
|
//~^ ERROR expected one of `,` or `>`, found `=`
|
||||||
//~| ERROR expected value, found struct `Vec`
|
//~| ERROR expected value, found struct `Vec`
|
||||||
//~| ERROR mismatched types
|
//~| ERROR mismatched types
|
||||||
//~| ERROR invalid left-hand side expression
|
//~| ERROR invalid left-hand side of assignment
|
||||||
//~| ERROR expected expression, found reserved identifier `_`
|
//~| ERROR expected expression, found reserved identifier `_`
|
||||||
//~| ERROR expected expression, found reserved identifier `_`
|
//~| ERROR expected expression, found reserved identifier `_`
|
||||||
let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect();
|
let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect();
|
||||||
|
@ -35,11 +35,13 @@ LL | let sr: Vec<(u32, _, _) = vec![];
|
|||||||
found struct `std::vec::Vec<_>`
|
found struct `std::vec::Vec<_>`
|
||||||
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||||
|
|
||||||
error[E0070]: invalid left-hand side expression
|
error[E0070]: invalid left-hand side of assignment
|
||||||
--> $DIR/issue-34334.rs:2:13
|
--> $DIR/issue-34334.rs:2:29
|
||||||
|
|
|
|
||||||
LL | let sr: Vec<(u32, _, _) = vec![];
|
LL | let sr: Vec<(u32, _, _) = vec![];
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ left-hand of expression not valid
|
| --------------- ^
|
||||||
|
| |
|
||||||
|
| cannot assign to this expression
|
||||||
|
|
||||||
error[E0599]: no method named `iter` found for type `()` in the current scope
|
error[E0599]: no method named `iter` found for type `()` in the current scope
|
||||||
--> $DIR/issue-34334.rs:9:36
|
--> $DIR/issue-34334.rs:9:36
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// This note is annotated because the purpose of the test
|
// This note is annotated because the purpose of the test
|
||||||
// is to ensure that certain other notes are not generated.
|
// is to ensure that certain other notes are not generated.
|
||||||
#![deny(unused_unsafe)] //~ NOTE
|
#![deny(unused_unsafe)] //~ NOTE
|
||||||
#![allow(deprecated)]
|
|
||||||
|
|
||||||
// (test that no note is generated on this unsafe fn)
|
// (test that no note is generated on this unsafe fn)
|
||||||
pub unsafe fn a() {
|
pub unsafe fn a() {
|
||||||
@ -20,8 +20,8 @@ pub fn b() {
|
|||||||
unsafe { /* unnecessary */ } //~ ERROR unnecessary `unsafe`
|
unsafe { /* unnecessary */ } //~ ERROR unnecessary `unsafe`
|
||||||
//~^ NOTE
|
//~^ NOTE
|
||||||
}
|
}
|
||||||
|
// `()` is fine to zero-initialize as it is zero sized and inhabited.
|
||||||
let () = ::std::mem::uninitialized();
|
let () = ::std::mem::zeroed();
|
||||||
|
|
||||||
inner()
|
inner()
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
// run-pass
|
// check-pass
|
||||||
|
|
||||||
trait FromUnchecked {
|
trait FromUnchecked {
|
||||||
unsafe fn from_unchecked();
|
fn from_unchecked();
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromUnchecked for [u8; 1] {
|
impl FromUnchecked for [u8; 1] {
|
||||||
unsafe fn from_unchecked() {
|
fn from_unchecked() {
|
||||||
#[allow(deprecated)]
|
let mut array: Self = [0; 1];
|
||||||
let mut array: Self = std::mem::uninitialized();
|
|
||||||
let _ptr = &mut array as *mut [u8] as *mut u8;
|
let _ptr = &mut array as *mut [u8] as *mut u8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,8 +69,10 @@ fn main() {
|
|||||||
unsafe {
|
unsafe {
|
||||||
// This should be safe, because we don't match on it unless it's fully formed,
|
// This should be safe, because we don't match on it unless it's fully formed,
|
||||||
// and it doesn't have a destructor.
|
// and it doesn't have a destructor.
|
||||||
#[allow(deprecated)]
|
//
|
||||||
let mut dest: MyEnum = mem::uninitialized();
|
// MyEnum is repr(C, u8) so it is guaranteed to have a separate discriminant and each
|
||||||
|
// variant can be zero initialized.
|
||||||
|
let mut dest: MyEnum = mem::zeroed();
|
||||||
while buf.len() > 0 {
|
while buf.len() > 0 {
|
||||||
match parse_my_enum(&mut dest, &mut buf) {
|
match parse_my_enum(&mut dest, &mut buf) {
|
||||||
Ok(()) => output.push(Ok(dest)),
|
Ok(()) => output.push(Ok(dest)),
|
||||||
|
@ -69,8 +69,11 @@ fn main() {
|
|||||||
unsafe {
|
unsafe {
|
||||||
// This should be safe, because we don't match on it unless it's fully formed,
|
// This should be safe, because we don't match on it unless it's fully formed,
|
||||||
// and it doesn't have a destructor.
|
// and it doesn't have a destructor.
|
||||||
#[allow(deprecated)]
|
//
|
||||||
let mut dest: MyEnum = mem::uninitialized();
|
// Furthermore, there are no types within MyEnum which cannot be initialized with zero,
|
||||||
|
// specifically, though padding and such are present, there are no references or similar
|
||||||
|
// types.
|
||||||
|
let mut dest: MyEnum = mem::zeroed();
|
||||||
while buf.len() > 0 {
|
while buf.len() > 0 {
|
||||||
match parse_my_enum(&mut dest, &mut buf) {
|
match parse_my_enum(&mut dest, &mut buf) {
|
||||||
Ok(()) => output.push(Ok(dest)),
|
Ok(()) => output.push(Ok(dest)),
|
||||||
|
@ -65,8 +65,10 @@ fn main() {
|
|||||||
unsafe {
|
unsafe {
|
||||||
// This should be safe, because we don't match on it unless it's fully formed,
|
// This should be safe, because we don't match on it unless it's fully formed,
|
||||||
// and it doesn't have a destructor.
|
// and it doesn't have a destructor.
|
||||||
#[allow(deprecated)]
|
//
|
||||||
let mut dest: MyEnum = mem::uninitialized();
|
// MyEnum is repr(u8) so it is guaranteed to have a separate discriminant and each variant
|
||||||
|
// can be zero initialized.
|
||||||
|
let mut dest: MyEnum = mem::zeroed();
|
||||||
while buf.len() > 0 {
|
while buf.len() > 0 {
|
||||||
match parse_my_enum(&mut dest, &mut buf) {
|
match parse_my_enum(&mut dest, &mut buf) {
|
||||||
Ok(()) => output.push(Ok(dest)),
|
Ok(()) => output.push(Ok(dest)),
|
||||||
|
@ -30,5 +30,5 @@ fn main() {
|
|||||||
// A test to check that not expecting `bool` behaves well:
|
// A test to check that not expecting `bool` behaves well:
|
||||||
let _: usize = 0 = 0;
|
let _: usize = 0 = 0;
|
||||||
//~^ ERROR mismatched types [E0308]
|
//~^ ERROR mismatched types [E0308]
|
||||||
//~| ERROR invalid left-hand side expression [E0070]
|
//~| ERROR invalid left-hand side of assignment [E0070]
|
||||||
}
|
}
|
||||||
|
@ -97,11 +97,13 @@ LL | || (0 = 0);
|
|||||||
| expected `bool`, found `()`
|
| expected `bool`, found `()`
|
||||||
| help: try comparing for equality: `0 == 0`
|
| help: try comparing for equality: `0 == 0`
|
||||||
|
|
||||||
error[E0070]: invalid left-hand side expression
|
error[E0070]: invalid left-hand side of assignment
|
||||||
--> $DIR/assignment-expected-bool.rs:31:20
|
--> $DIR/assignment-expected-bool.rs:31:22
|
||||||
|
|
|
|
||||||
LL | let _: usize = 0 = 0;
|
LL | let _: usize = 0 = 0;
|
||||||
| ^^^^^ left-hand of expression not valid
|
| - ^
|
||||||
|
| |
|
||||||
|
| cannot assign to this expression
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/assignment-expected-bool.rs:31:20
|
--> $DIR/assignment-expected-bool.rs:31:20
|
||||||
|
@ -26,7 +26,7 @@ fn main() {
|
|||||||
//~^ ERROR mismatched types
|
//~^ ERROR mismatched types
|
||||||
println!("{}", x);
|
println!("{}", x);
|
||||||
}
|
}
|
||||||
// "invalid left-hand side expression" error is suppresed
|
// "invalid left-hand side of assignment" error is suppresed
|
||||||
if 3 = x {
|
if 3 = x {
|
||||||
//~^ ERROR mismatched types
|
//~^ ERROR mismatched types
|
||||||
println!("{}", x);
|
println!("{}", x);
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#![allow(deprecated)]
|
use std::mem::zeroed;
|
||||||
|
|
||||||
enum Void {}
|
enum Void {}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
@ -8,21 +7,25 @@ fn main() {
|
|||||||
Ok(n) => n,
|
Ok(n) => n,
|
||||||
};
|
};
|
||||||
|
|
||||||
let x: &Void = unsafe { std::mem::uninitialized() };
|
// This is pretty much instant UB. However, we have no choice -- we need to
|
||||||
|
// test matching on a reference to `&Void`; we cannot do anything other than
|
||||||
|
// just accept the fact that this is UB if `main` did run, but it doesn't;
|
||||||
|
// this test only checks that these are feature-gated.
|
||||||
|
let x: &Void = unsafe { zeroed() };
|
||||||
let _ = match x {}; //~ ERROR non-exhaustive
|
let _ = match x {}; //~ ERROR non-exhaustive
|
||||||
|
|
||||||
let x: (Void,) = unsafe { std::mem::uninitialized() };
|
let x: (Void,) = unsafe { zeroed() };
|
||||||
let _ = match x {}; //~ ERROR non-exhaustive
|
let _ = match x {}; //~ ERROR non-exhaustive
|
||||||
|
|
||||||
let x: [Void; 1] = unsafe { std::mem::uninitialized() };
|
let x: [Void; 1] = unsafe { zeroed() };
|
||||||
let _ = match x {}; //~ ERROR non-exhaustive
|
let _ = match x {}; //~ ERROR non-exhaustive
|
||||||
|
|
||||||
let x: &[Void] = unsafe { std::mem::uninitialized() };
|
let x: &[Void] = unsafe { zeroed() };
|
||||||
let _ = match x { //~ ERROR non-exhaustive
|
let _ = match x { //~ ERROR non-exhaustive
|
||||||
&[] => (),
|
&[] => (),
|
||||||
};
|
};
|
||||||
|
|
||||||
let x: Void = unsafe { std::mem::uninitialized() };
|
let x: Void = unsafe { zeroed() };
|
||||||
let _ = match x {}; // okay
|
let _ = match x {}; // okay
|
||||||
|
|
||||||
let x: Result<u32, Void> = Ok(23);
|
let x: Result<u32, Void> = Ok(23);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
error[E0004]: non-exhaustive patterns: `Err(_)` not covered
|
error[E0004]: non-exhaustive patterns: `Err(_)` not covered
|
||||||
--> $DIR/uninhabited-matches-feature-gated.rs:7:19
|
--> $DIR/uninhabited-matches-feature-gated.rs:6:19
|
||||||
|
|
|
|
||||||
LL | let _ = match x {
|
LL | let _ = match x {
|
||||||
| ^ pattern `Err(_)` not covered
|
| ^ pattern `Err(_)` not covered
|
||||||
@ -7,7 +7,7 @@ LL | let _ = match x {
|
|||||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||||
|
|
||||||
error[E0004]: non-exhaustive patterns: type `&Void` is non-empty
|
error[E0004]: non-exhaustive patterns: type `&Void` is non-empty
|
||||||
--> $DIR/uninhabited-matches-feature-gated.rs:12:19
|
--> $DIR/uninhabited-matches-feature-gated.rs:15:19
|
||||||
|
|
|
|
||||||
LL | enum Void {}
|
LL | enum Void {}
|
||||||
| ------------ `Void` defined here
|
| ------------ `Void` defined here
|
||||||
@ -18,14 +18,6 @@ LL | let _ = match x {};
|
|||||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||||
|
|
||||||
error[E0004]: non-exhaustive patterns: type `(Void,)` is non-empty
|
error[E0004]: non-exhaustive patterns: type `(Void,)` is non-empty
|
||||||
--> $DIR/uninhabited-matches-feature-gated.rs:15:19
|
|
||||||
|
|
|
||||||
LL | let _ = match x {};
|
|
||||||
| ^
|
|
||||||
|
|
|
||||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
|
||||||
|
|
||||||
error[E0004]: non-exhaustive patterns: type `[Void; 1]` is non-empty
|
|
||||||
--> $DIR/uninhabited-matches-feature-gated.rs:18:19
|
--> $DIR/uninhabited-matches-feature-gated.rs:18:19
|
||||||
|
|
|
|
||||||
LL | let _ = match x {};
|
LL | let _ = match x {};
|
||||||
@ -33,16 +25,24 @@ LL | let _ = match x {};
|
|||||||
|
|
|
|
||||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||||
|
|
||||||
error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered
|
error[E0004]: non-exhaustive patterns: type `[Void; 1]` is non-empty
|
||||||
--> $DIR/uninhabited-matches-feature-gated.rs:21:19
|
--> $DIR/uninhabited-matches-feature-gated.rs:21:19
|
||||||
|
|
|
|
||||||
|
LL | let _ = match x {};
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||||
|
|
||||||
|
error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered
|
||||||
|
--> $DIR/uninhabited-matches-feature-gated.rs:24:19
|
||||||
|
|
|
||||||
LL | let _ = match x {
|
LL | let _ = match x {
|
||||||
| ^ pattern `&[_, ..]` not covered
|
| ^ pattern `&[_, ..]` not covered
|
||||||
|
|
|
|
||||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||||
|
|
||||||
error[E0004]: non-exhaustive patterns: `Err(_)` not covered
|
error[E0004]: non-exhaustive patterns: `Err(_)` not covered
|
||||||
--> $DIR/uninhabited-matches-feature-gated.rs:29:19
|
--> $DIR/uninhabited-matches-feature-gated.rs:32:19
|
||||||
|
|
|
|
||||||
LL | let _ = match x {
|
LL | let _ = match x {
|
||||||
| ^ pattern `Err(_)` not covered
|
| ^ pattern `Err(_)` not covered
|
||||||
@ -50,7 +50,7 @@ LL | let _ = match x {
|
|||||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||||
|
|
||||||
error[E0005]: refutable pattern in local binding: `Err(_)` not covered
|
error[E0005]: refutable pattern in local binding: `Err(_)` not covered
|
||||||
--> $DIR/uninhabited-matches-feature-gated.rs:34:9
|
--> $DIR/uninhabited-matches-feature-gated.rs:37:9
|
||||||
|
|
|
|
||||||
LL | let Ok(x) = x;
|
LL | let Ok(x) = x;
|
||||||
| ^^^^^ pattern `Err(_)` not covered
|
| ^^^^^ pattern `Err(_)` not covered
|
||||||
|
@ -1,17 +1,19 @@
|
|||||||
// run-pass
|
// build-pass
|
||||||
// Test the uninit() construct returning various empty types.
|
// Test the uninit() construct returning various empty types.
|
||||||
|
|
||||||
// pretty-expanded FIXME #23616
|
// pretty-expanded FIXME #23616
|
||||||
|
|
||||||
use std::mem;
|
use std::mem::MaybeUninit;
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
struct Foo;
|
struct Foo;
|
||||||
|
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
unsafe {
|
unsafe {
|
||||||
let _x: Foo = mem::uninitialized();
|
// `Foo` and `[Foo; 2]` are both zero sized and inhabited, so this is safe.
|
||||||
let _x: [Foo; 2] = mem::uninitialized();
|
let _x: Foo = MaybeUninit::uninit().assume_init();
|
||||||
|
let _x: [Foo; 2] = MaybeUninit::uninit().assume_init();
|
||||||
|
let _x: Foo = std::mem::uninitialized();
|
||||||
|
let _x: [Foo; 2] = std::mem::uninitialized();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
fn f() where u8 = u16 {}
|
fn f() where u8 = u16 {}
|
||||||
//~^ ERROR equality constraints are not yet supported in where clauses
|
//~^ ERROR equality constraints are not yet supported in `where` clauses
|
||||||
fn g() where for<'a> &'static (u8,) == u16, {}
|
fn g() where for<'a> &'static (u8,) == u16, {}
|
||||||
//~^ ERROR equality constraints are not yet supported in where clauses
|
//~^ ERROR equality constraints are not yet supported in `where` clauses
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -1,14 +1,18 @@
|
|||||||
error: equality constraints are not yet supported in where clauses (see #20041)
|
error: equality constraints are not yet supported in `where` clauses
|
||||||
--> $DIR/where-equality-constraints.rs:1:14
|
--> $DIR/where-equality-constraints.rs:1:14
|
||||||
|
|
|
|
||||||
LL | fn f() where u8 = u16 {}
|
LL | fn f() where u8 = u16 {}
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: for more information, see https://github.com/rust-lang/rust/issues/20041
|
||||||
|
|
||||||
error: equality constraints are not yet supported in where clauses (see #20041)
|
error: equality constraints are not yet supported in `where` clauses
|
||||||
--> $DIR/where-equality-constraints.rs:3:14
|
--> $DIR/where-equality-constraints.rs:3:14
|
||||||
|
|
|
|
||||||
LL | fn g() where for<'a> &'static (u8,) == u16, {}
|
LL | fn g() where for<'a> &'static (u8,) == u16, {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: for more information, see https://github.com/rust-lang/rust/issues/20041
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user