diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index b02acce2d00bb..6481789c1dd00 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -1,6 +1,22 @@ //! Compiler intrinsics. //! //! 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 //! @@ -667,6 +683,7 @@ extern "rust-intrinsic" { /// /// The stabilized version of this intrinsic is /// [`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() -> usize; /// Moves a value to an uninitialized memory location. @@ -674,7 +691,9 @@ extern "rust-intrinsic" { /// Drop glue is not run on the destination. pub fn move_val_init(dst: *mut T, src: T); + #[rustc_const_stable(feature = "const_min_align_of", since = "1.40.0")] pub fn min_align_of() -> usize; + #[rustc_const_unstable(feature = "const_pref_align_of", issue = "0")] pub fn pref_align_of() -> usize; /// The size of the referenced value in bytes. @@ -685,11 +704,13 @@ extern "rust-intrinsic" { pub fn min_align_of_val(_: &T) -> usize; /// Gets a static string slice containing the name of a type. + #[rustc_const_unstable(feature = "const_type_name", issue = "0")] pub fn type_name() -> &'static str; /// Gets an identifier which is globally unique to the specified type. This /// function will return the same value for a type regardless of whichever /// crate it is invoked in. + #[rustc_const_unstable(feature = "const_type_id", issue = "0")] pub fn type_id() -> u64; /// A guard for unsafe functions that cannot ever be executed if `T` is uninhabited: @@ -697,6 +718,7 @@ extern "rust-intrinsic" { pub fn panic_if_uninhabited(); /// 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>; /// Creates a value initialized to zero. @@ -951,6 +973,7 @@ extern "rust-intrinsic" { /// /// The stabilized version of this intrinsic is /// [`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() -> bool; /// Calculates the offset from a pointer. @@ -1150,6 +1173,7 @@ extern "rust-intrinsic" { /// Returns the number of bits set in an integer type `T` + #[rustc_const_stable(feature = "const_ctpop", since = "1.40.0")] pub fn ctpop(x: T) -> T; /// Returns the number of leading unset bits (zeroes) in an integer type `T`. @@ -1177,6 +1201,7 @@ extern "rust-intrinsic" { /// let num_leading = ctlz(x); /// assert_eq!(num_leading, 16); /// ``` + #[rustc_const_stable(feature = "const_ctlz", since = "1.40.0")] pub fn ctlz(x: T) -> T; /// Like `ctlz`, but extra-unsafe as it returns `undef` when @@ -1193,6 +1218,7 @@ extern "rust-intrinsic" { /// let num_leading = unsafe { ctlz_nonzero(x) }; /// assert_eq!(num_leading, 3); /// ``` + #[rustc_const_unstable(feature = "constctlz", issue = "0")] pub fn ctlz_nonzero(x: T) -> T; /// Returns the number of trailing unset bits (zeroes) in an integer type `T`. @@ -1220,6 +1246,7 @@ extern "rust-intrinsic" { /// let num_trailing = cttz(x); /// assert_eq!(num_trailing, 16); /// ``` + #[rustc_const_stable(feature = "const_cttz", since = "1.40.0")] pub fn cttz(x: T) -> T; /// Like `cttz`, but extra-unsafe as it returns `undef` when @@ -1236,30 +1263,36 @@ extern "rust-intrinsic" { /// let num_trailing = unsafe { cttz_nonzero(x) }; /// assert_eq!(num_trailing, 3); /// ``` + #[rustc_const_unstable(feature = "const_cttz", issue = "0")] pub fn cttz_nonzero(x: T) -> T; /// Reverses the bytes in an integer type `T`. + #[rustc_const_stable(feature = "const_bswap", since = "1.40.0")] pub fn bswap(x: T) -> T; /// Reverses the bits in an integer type `T`. + #[rustc_const_stable(feature = "const_bitreverse", since = "1.40.0")] pub fn bitreverse(x: T) -> T; /// Performs checked integer addition. /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `overflowing_add` method. For example, /// [`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(x: T, y: T) -> (T, bool); /// Performs checked integer subtraction /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `overflowing_sub` method. For example, /// [`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(x: T, y: T) -> (T, bool); /// Performs checked integer multiplication /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `overflowing_mul` method. For example, /// [`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(x: T, y: T) -> (T, bool); /// Performs an exact division, resulting in undefined behavior where @@ -1275,9 +1308,11 @@ extern "rust-intrinsic" { /// Performs an unchecked left shift, resulting in undefined behavior when /// 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(x: T, y: T) -> T; /// Performs an unchecked right shift, resulting in undefined behavior when /// 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(x: T, y: T) -> T; /// Returns the result of an unchecked addition, resulting in @@ -1296,39 +1331,46 @@ extern "rust-intrinsic" { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `rotate_left` method. For example, /// [`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(x: T, y: T) -> T; /// Performs rotate right. /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `rotate_right` method. For example, /// [`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(x: T, y: T) -> T; /// Returns (a + b) mod 2N, where N is the width of T in bits. /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_add` method. For example, /// [`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(a: T, b: T) -> T; /// Returns (a - b) mod 2N, where N is the width of T in bits. /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_sub` method. For example, /// [`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(a: T, b: T) -> T; /// Returns (a * b) mod 2N, where N is the width of T in bits. /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_mul` method. For example, /// [`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(a: T, b: T) -> T; /// Computes `a + b`, while saturating at numeric bounds. /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `saturating_add` method. For example, /// [`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(a: T, b: T) -> T; /// Computes `a - b`, while saturating at numeric bounds. /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `saturating_sub` method. For example, /// [`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(a: T, b: T) -> T; /// Returns the value of the discriminant for the variant in 'v', @@ -1350,6 +1392,7 @@ extern "rust-intrinsic" { pub fn nontemporal_store(ptr: *mut T, val: T); /// See documentation of `<*const T>::offset_from` for details. + #[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "0")] pub fn ptr_offset_from(ptr: *const T, base: *const T) -> isize; /// Internal hook used by Miri to implement unwinding. diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index a2ab85e64baa1..74dc56c156aea 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -128,6 +128,8 @@ #![feature(maybe_uninit_slice)] #![feature(external_doc)] #![feature(associated_type_bounds)] +#![feature(const_type_id)] +#![feature(const_caller_location)] #[prelude_import] #[allow(unused)] diff --git a/src/libcore/macros/mod.rs b/src/libcore/macros/mod.rs index dd06da7a6d23e..b1475f2ad9fc4 100644 --- a/src/libcore/macros/mod.rs +++ b/src/libcore/macros/mod.rs @@ -5,6 +5,7 @@ // the `caller_location` intrinsic, but once `#[track_caller]` is implemented, // `panicking::{panic, panic_fmt}` can use that instead of a `Location` argument. core_intrinsics, + const_caller_location, )] #[stable(feature = "core", since = "1.6.0")] macro_rules! panic { diff --git a/src/librustc/ty/constness.rs b/src/librustc/ty/constness.rs index 897a3678c4004..7fe950ef7b7f6 100644 --- a/src/librustc/ty/constness.rs +++ b/src/librustc/ty/constness.rs @@ -2,7 +2,7 @@ use crate::ty::query::Providers; use crate::hir::def_id::DefId; use crate::hir; use crate::ty::TyCtxt; -use syntax_pos::symbol::{sym, Symbol}; +use syntax_pos::symbol::Symbol; use rustc_target::spec::abi::Abi; use crate::hir::map::blocks::FnLikeNode; 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` pub fn is_min_const_fn(self, def_id: DefId) -> bool { // Bail out if the signature doesn't contain `const` if !self.is_const_fn_raw(def_id) { 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 { // 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 { match tcx.fn_sig(def_id).abi() { Abi::RustIntrinsic | - Abi::PlatformIntrinsic => { - // 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) - } - } + Abi::PlatformIntrinsic => Some(tcx.lookup_const_stability(def_id).is_some()), _ => None } } diff --git a/src/test/ui/consts/const-eval/simd/insert_extract.rs b/src/test/ui/consts/const-eval/simd/insert_extract.rs index d3462d802ea4e..92231d4ced321 100644 --- a/src/test/ui/consts/const-eval/simd/insert_extract.rs +++ b/src/test/ui/consts/const-eval/simd/insert_extract.rs @@ -2,6 +2,8 @@ #![feature(const_fn)] #![feature(repr_simd)] #![feature(platform_intrinsics)] +#![feature(staged_api)] +#![stable(feature = "foo", since = "1.33.7")] #![allow(non_camel_case_types)] #[repr(simd)] struct i8x1(i8); @@ -9,7 +11,9 @@ #[repr(simd)] struct f32x3(f32, f32, f32); extern "platform-intrinsic" { + #[rustc_const_stable(feature = "foo", since = "1.3.37")] fn simd_insert(x: T, idx: u32, val: U) -> T; + #[rustc_const_stable(feature = "foo", since = "1.3.37")] fn simd_extract(x: T, idx: u32) -> U; } diff --git a/src/test/ui/consts/const-fn-type-name.rs b/src/test/ui/consts/const-fn-type-name.rs index 2bb1aeecf376d..72fac19c19173 100644 --- a/src/test/ui/consts/const-fn-type-name.rs +++ b/src/test/ui/consts/const-fn-type-name.rs @@ -2,6 +2,7 @@ #![feature(core_intrinsics)] #![feature(const_fn)] +#![feature(const_type_name)] #![allow(dead_code)] const fn type_name_wrapper(_: &T) -> &'static str {