Skip to content

Commit 1de2705

Browse files
authored
Rollup merge of rust-lang#67466 - oli-obk:const_intrinsic, r=Centril
Require const stability attributes on intrinsics to be able to use them in constant contexts r? @Centril finally fixes rust-lang#61495 cc @RalfJung
2 parents 260514d + 63d2822 commit 1de2705

File tree

6 files changed

+53
-96
lines changed

6 files changed

+53
-96
lines changed

src/libcore/intrinsics.rs

+43
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,22 @@
11
//! Compiler intrinsics.
22
//!
33
//! The corresponding definitions are in `librustc_codegen_llvm/intrinsic.rs`.
4+
//! The corresponding const implementations are in `librustc_mir/interpret/intrinsics.rs`
5+
//!
6+
//! # Const intrinsics
7+
//!
8+
//! Note: any changes to the constness of intrinsics should be discussed with the language team.
9+
//! This includes changes in the stability of the constness.
10+
//!
11+
//! In order to make an intrinsic usable at compile-time, one needs to copy the implementation
12+
//! from https://github.com/rust-lang/miri/blob/master/src/shims/intrinsics.rs to
13+
//! `librustc_mir/interpret/intrinsics.rs` and add a
14+
//! `#[rustc_const_unstable(feature = "foo", issue = "01234")]` to the intrinsic.
15+
//!
16+
//! If an intrinsic is supposed to be used from a `const fn` with a `rustc_const_stable` attribute,
17+
//! the intrinsic's attribute must be `rustc_const_stable`, too. Such a change should not be done
18+
//! without T-lang consulation, because it bakes a feature into the language that cannot be
19+
//! replicated in user code without compiler support.
420
//!
521
//! # Volatiles
622
//!
@@ -671,14 +687,17 @@ extern "rust-intrinsic" {
671687
///
672688
/// The stabilized version of this intrinsic is
673689
/// [`std::mem::size_of`](../../std/mem/fn.size_of.html).
690+
#[rustc_const_stable(feature = "const_size_of", since = "1.40.0")]
674691
pub fn size_of<T>() -> usize;
675692

676693
/// Moves a value to an uninitialized memory location.
677694
///
678695
/// Drop glue is not run on the destination.
679696
pub fn move_val_init<T>(dst: *mut T, src: T);
680697

698+
#[rustc_const_stable(feature = "const_min_align_of", since = "1.40.0")]
681699
pub fn min_align_of<T>() -> usize;
700+
#[rustc_const_unstable(feature = "const_pref_align_of", issue = "0")]
682701
pub fn pref_align_of<T>() -> usize;
683702

684703
/// The size of the referenced value in bytes.
@@ -689,18 +708,21 @@ extern "rust-intrinsic" {
689708
pub fn min_align_of_val<T: ?Sized>(_: &T) -> usize;
690709

691710
/// Gets a static string slice containing the name of a type.
711+
#[rustc_const_unstable(feature = "const_type_name", issue = "0")]
692712
pub fn type_name<T: ?Sized>() -> &'static str;
693713

694714
/// Gets an identifier which is globally unique to the specified type. This
695715
/// function will return the same value for a type regardless of whichever
696716
/// crate it is invoked in.
717+
#[rustc_const_unstable(feature = "const_type_id", issue = "0")]
697718
pub fn type_id<T: ?Sized + 'static>() -> u64;
698719

699720
/// A guard for unsafe functions that cannot ever be executed if `T` is uninhabited:
700721
/// This will statically either panic, or do nothing.
701722
pub fn panic_if_uninhabited<T>();
702723

703724
/// Gets a reference to a static `Location` indicating where it was called.
725+
#[rustc_const_unstable(feature = "const_caller_location", issue = "47809")]
704726
pub fn caller_location() -> &'static crate::panic::Location<'static>;
705727

706728
/// Creates a value initialized to zero.
@@ -957,6 +979,7 @@ extern "rust-intrinsic" {
957979
///
958980
/// The stabilized version of this intrinsic is
959981
/// [`std::mem::needs_drop`](../../std/mem/fn.needs_drop.html).
982+
#[rustc_const_stable(feature = "const_needs_drop", since = "1.40.0")]
960983
pub fn needs_drop<T>() -> bool;
961984

962985
/// Calculates the offset from a pointer.
@@ -1154,6 +1177,7 @@ extern "rust-intrinsic" {
11541177
pub fn float_to_int_approx_unchecked<Float, Int>(value: Float) -> Int;
11551178

11561179
/// Returns the number of bits set in an integer type `T`
1180+
#[rustc_const_stable(feature = "const_ctpop", since = "1.40.0")]
11571181
pub fn ctpop<T>(x: T) -> T;
11581182

11591183
/// Returns the number of leading unset bits (zeroes) in an integer type `T`.
@@ -1181,6 +1205,7 @@ extern "rust-intrinsic" {
11811205
/// let num_leading = ctlz(x);
11821206
/// assert_eq!(num_leading, 16);
11831207
/// ```
1208+
#[rustc_const_stable(feature = "const_ctlz", since = "1.40.0")]
11841209
pub fn ctlz<T>(x: T) -> T;
11851210

11861211
/// Like `ctlz`, but extra-unsafe as it returns `undef` when
@@ -1197,6 +1222,7 @@ extern "rust-intrinsic" {
11971222
/// let num_leading = unsafe { ctlz_nonzero(x) };
11981223
/// assert_eq!(num_leading, 3);
11991224
/// ```
1225+
#[rustc_const_unstable(feature = "constctlz", issue = "0")]
12001226
pub fn ctlz_nonzero<T>(x: T) -> T;
12011227

12021228
/// Returns the number of trailing unset bits (zeroes) in an integer type `T`.
@@ -1224,6 +1250,7 @@ extern "rust-intrinsic" {
12241250
/// let num_trailing = cttz(x);
12251251
/// assert_eq!(num_trailing, 16);
12261252
/// ```
1253+
#[rustc_const_stable(feature = "const_cttz", since = "1.40.0")]
12271254
pub fn cttz<T>(x: T) -> T;
12281255

12291256
/// Like `cttz`, but extra-unsafe as it returns `undef` when
@@ -1240,30 +1267,36 @@ extern "rust-intrinsic" {
12401267
/// let num_trailing = unsafe { cttz_nonzero(x) };
12411268
/// assert_eq!(num_trailing, 3);
12421269
/// ```
1270+
#[rustc_const_unstable(feature = "const_cttz", issue = "0")]
12431271
pub fn cttz_nonzero<T>(x: T) -> T;
12441272

12451273
/// Reverses the bytes in an integer type `T`.
1274+
#[rustc_const_stable(feature = "const_bswap", since = "1.40.0")]
12461275
pub fn bswap<T>(x: T) -> T;
12471276

12481277
/// Reverses the bits in an integer type `T`.
1278+
#[rustc_const_stable(feature = "const_bitreverse", since = "1.40.0")]
12491279
pub fn bitreverse<T>(x: T) -> T;
12501280

12511281
/// Performs checked integer addition.
12521282
/// The stabilized versions of this intrinsic are available on the integer
12531283
/// primitives via the `overflowing_add` method. For example,
12541284
/// [`std::u32::overflowing_add`](../../std/primitive.u32.html#method.overflowing_add)
1285+
#[rustc_const_stable(feature = "const_int_overflow", since = "1.40.0")]
12551286
pub fn add_with_overflow<T>(x: T, y: T) -> (T, bool);
12561287

12571288
/// Performs checked integer subtraction
12581289
/// The stabilized versions of this intrinsic are available on the integer
12591290
/// primitives via the `overflowing_sub` method. For example,
12601291
/// [`std::u32::overflowing_sub`](../../std/primitive.u32.html#method.overflowing_sub)
1292+
#[rustc_const_stable(feature = "const_int_overflow", since = "1.40.0")]
12611293
pub fn sub_with_overflow<T>(x: T, y: T) -> (T, bool);
12621294

12631295
/// Performs checked integer multiplication
12641296
/// The stabilized versions of this intrinsic are available on the integer
12651297
/// primitives via the `overflowing_mul` method. For example,
12661298
/// [`std::u32::overflowing_mul`](../../std/primitive.u32.html#method.overflowing_mul)
1299+
#[rustc_const_stable(feature = "const_int_overflow", since = "1.40.0")]
12671300
pub fn mul_with_overflow<T>(x: T, y: T) -> (T, bool);
12681301

12691302
/// Performs an exact division, resulting in undefined behavior where
@@ -1279,9 +1312,11 @@ extern "rust-intrinsic" {
12791312

12801313
/// Performs an unchecked left shift, resulting in undefined behavior when
12811314
/// y < 0 or y >= N, where N is the width of T in bits.
1315+
#[rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0")]
12821316
pub fn unchecked_shl<T>(x: T, y: T) -> T;
12831317
/// Performs an unchecked right shift, resulting in undefined behavior when
12841318
/// y < 0 or y >= N, where N is the width of T in bits.
1319+
#[rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0")]
12851320
pub fn unchecked_shr<T>(x: T, y: T) -> T;
12861321

12871322
/// Returns the result of an unchecked addition, resulting in
@@ -1300,39 +1335,46 @@ extern "rust-intrinsic" {
13001335
/// The stabilized versions of this intrinsic are available on the integer
13011336
/// primitives via the `rotate_left` method. For example,
13021337
/// [`std::u32::rotate_left`](../../std/primitive.u32.html#method.rotate_left)
1338+
#[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")]
13031339
pub fn rotate_left<T>(x: T, y: T) -> T;
13041340

13051341
/// Performs rotate right.
13061342
/// The stabilized versions of this intrinsic are available on the integer
13071343
/// primitives via the `rotate_right` method. For example,
13081344
/// [`std::u32::rotate_right`](../../std/primitive.u32.html#method.rotate_right)
1345+
#[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")]
13091346
pub fn rotate_right<T>(x: T, y: T) -> T;
13101347

13111348
/// Returns (a + b) mod 2<sup>N</sup>, where N is the width of T in bits.
13121349
/// The stabilized versions of this intrinsic are available on the integer
13131350
/// primitives via the `wrapping_add` method. For example,
13141351
/// [`std::u32::wrapping_add`](../../std/primitive.u32.html#method.wrapping_add)
1352+
#[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")]
13151353
pub fn wrapping_add<T>(a: T, b: T) -> T;
13161354
/// Returns (a - b) mod 2<sup>N</sup>, where N is the width of T in bits.
13171355
/// The stabilized versions of this intrinsic are available on the integer
13181356
/// primitives via the `wrapping_sub` method. For example,
13191357
/// [`std::u32::wrapping_sub`](../../std/primitive.u32.html#method.wrapping_sub)
1358+
#[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")]
13201359
pub fn wrapping_sub<T>(a: T, b: T) -> T;
13211360
/// Returns (a * b) mod 2<sup>N</sup>, where N is the width of T in bits.
13221361
/// The stabilized versions of this intrinsic are available on the integer
13231362
/// primitives via the `wrapping_mul` method. For example,
13241363
/// [`std::u32::wrapping_mul`](../../std/primitive.u32.html#method.wrapping_mul)
1364+
#[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")]
13251365
pub fn wrapping_mul<T>(a: T, b: T) -> T;
13261366

13271367
/// Computes `a + b`, while saturating at numeric bounds.
13281368
/// The stabilized versions of this intrinsic are available on the integer
13291369
/// primitives via the `saturating_add` method. For example,
13301370
/// [`std::u32::saturating_add`](../../std/primitive.u32.html#method.saturating_add)
1371+
#[rustc_const_stable(feature = "const_int_saturating", since = "1.40.0")]
13311372
pub fn saturating_add<T>(a: T, b: T) -> T;
13321373
/// Computes `a - b`, while saturating at numeric bounds.
13331374
/// The stabilized versions of this intrinsic are available on the integer
13341375
/// primitives via the `saturating_sub` method. For example,
13351376
/// [`std::u32::saturating_sub`](../../std/primitive.u32.html#method.saturating_sub)
1377+
#[rustc_const_stable(feature = "const_int_saturating", since = "1.40.0")]
13361378
pub fn saturating_sub<T>(a: T, b: T) -> T;
13371379

13381380
/// Returns the value of the discriminant for the variant in 'v',
@@ -1354,6 +1396,7 @@ extern "rust-intrinsic" {
13541396
pub fn nontemporal_store<T>(ptr: *mut T, val: T);
13551397

13561398
/// See documentation of `<*const T>::offset_from` for details.
1399+
#[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "0")]
13571400
pub fn ptr_offset_from<T>(ptr: *const T, base: *const T) -> isize;
13581401

13591402
/// Internal hook used by Miri to implement unwinding.

src/libcore/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@
127127
#![feature(maybe_uninit_slice)]
128128
#![feature(external_doc)]
129129
#![feature(associated_type_bounds)]
130+
#![feature(const_type_id)]
131+
#![feature(const_caller_location)]
130132

131133
#[prelude_import]
132134
#[allow(unused)]

src/libcore/macros/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// the `caller_location` intrinsic, but once `#[track_caller]` is implemented,
66
// `panicking::{panic, panic_fmt}` can use that instead of a `Location` argument.
77
core_intrinsics,
8+
const_caller_location,
89
)]
910
#[stable(feature = "core", since = "1.6.0")]
1011
macro_rules! panic {

src/librustc/ty/constness.rs

+2-96
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::ty::query::Providers;
22
use crate::hir::def_id::DefId;
33
use crate::hir;
44
use crate::ty::TyCtxt;
5-
use syntax_pos::symbol::{sym, Symbol};
5+
use syntax_pos::symbol::Symbol;
66
use rustc_target::spec::abi::Abi;
77
use crate::hir::map::blocks::FnLikeNode;
88
use syntax::attr;
@@ -41,51 +41,12 @@ impl<'tcx> TyCtxt<'tcx> {
4141
}
4242
}
4343

44-
/// Returns `true` if the `def_id` refers to an intrisic which we've whitelisted
45-
/// for being called from stable `const fn`s (`min_const_fn`).
46-
///
47-
/// Adding more intrinsics requires sign-off from @rust-lang/lang.
48-
///
49-
/// This list differs from the list in `is_const_intrinsic` in the sense that any item on this
50-
/// list must be on the `is_const_intrinsic` list, too, because if an intrinsic is callable from
51-
/// stable, it must be callable at all.
52-
fn is_intrinsic_min_const_fn(self, def_id: DefId) -> bool {
53-
match self.item_name(def_id) {
54-
| sym::size_of
55-
| sym::min_align_of
56-
| sym::needs_drop
57-
// Arithmetic:
58-
| sym::add_with_overflow // ~> .overflowing_add
59-
| sym::sub_with_overflow // ~> .overflowing_sub
60-
| sym::mul_with_overflow // ~> .overflowing_mul
61-
| sym::wrapping_add // ~> .wrapping_add
62-
| sym::wrapping_sub // ~> .wrapping_sub
63-
| sym::wrapping_mul // ~> .wrapping_mul
64-
| sym::saturating_add // ~> .saturating_add
65-
| sym::saturating_sub // ~> .saturating_sub
66-
| sym::unchecked_shl // ~> .wrapping_shl
67-
| sym::unchecked_shr // ~> .wrapping_shr
68-
| sym::rotate_left // ~> .rotate_left
69-
| sym::rotate_right // ~> .rotate_right
70-
| sym::ctpop // ~> .count_ones
71-
| sym::ctlz // ~> .leading_zeros
72-
| sym::cttz // ~> .trailing_zeros
73-
| sym::bswap // ~> .swap_bytes
74-
| sym::bitreverse // ~> .reverse_bits
75-
=> true,
76-
_ => false,
77-
}
78-
}
79-
8044
/// Returns `true` if this function must conform to `min_const_fn`
8145
pub fn is_min_const_fn(self, def_id: DefId) -> bool {
8246
// Bail out if the signature doesn't contain `const`
8347
if !self.is_const_fn_raw(def_id) {
8448
return false;
8549
}
86-
if let Abi::RustIntrinsic = self.fn_sig(def_id).abi() {
87-
return self.is_intrinsic_min_const_fn(def_id);
88-
}
8950

9051
if self.features().staged_api {
9152
// In order for a libstd function to be considered min_const_fn
@@ -134,62 +95,7 @@ pub fn provide(providers: &mut Providers<'_>) {
13495
fn is_const_intrinsic(tcx: TyCtxt<'_>, def_id: DefId) -> Option<bool> {
13596
match tcx.fn_sig(def_id).abi() {
13697
Abi::RustIntrinsic |
137-
Abi::PlatformIntrinsic => {
138-
// FIXME: deduplicate these two lists as much as possible
139-
match tcx.item_name(def_id) {
140-
// Keep this list in the same order as the match patterns in
141-
// `librustc_mir/interpret/intrinsics.rs`
142-
143-
// This whitelist is a list of intrinsics that have a miri-engine implementation
144-
// and can thus be called when enabling enough feature gates. The similar
145-
// whitelist in `is_intrinsic_min_const_fn` (in this file), exists for allowing
146-
// the intrinsics to be called by stable const fns.
147-
| sym::caller_location
148-
149-
| sym::min_align_of
150-
| sym::pref_align_of
151-
| sym::needs_drop
152-
| sym::size_of
153-
| sym::type_id
154-
| sym::type_name
155-
156-
| sym::ctpop
157-
| sym::cttz
158-
| sym::cttz_nonzero
159-
| sym::ctlz
160-
| sym::ctlz_nonzero
161-
| sym::bswap
162-
| sym::bitreverse
163-
164-
| sym::wrapping_add
165-
| sym::wrapping_sub
166-
| sym::wrapping_mul
167-
| sym::add_with_overflow
168-
| sym::sub_with_overflow
169-
| sym::mul_with_overflow
170-
171-
| sym::saturating_add
172-
| sym::saturating_sub
173-
174-
| sym::unchecked_shl
175-
| sym::unchecked_shr
176-
177-
| sym::rotate_left
178-
| sym::rotate_right
179-
180-
| sym::ptr_offset_from
181-
182-
| sym::transmute
183-
184-
| sym::simd_insert
185-
186-
| sym::simd_extract
187-
188-
=> Some(true),
189-
190-
_ => Some(false)
191-
}
192-
}
98+
Abi::PlatformIntrinsic => Some(tcx.lookup_const_stability(def_id).is_some()),
19399
_ => None
194100
}
195101
}

src/test/ui/consts/const-eval/simd/insert_extract.rs

+4
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,18 @@
22
#![feature(const_fn)]
33
#![feature(repr_simd)]
44
#![feature(platform_intrinsics)]
5+
#![feature(staged_api)]
6+
#![stable(feature = "foo", since = "1.33.7")]
57
#![allow(non_camel_case_types)]
68

79
#[repr(simd)] struct i8x1(i8);
810
#[repr(simd)] struct u16x2(u16, u16);
911
#[repr(simd)] struct f32x3(f32, f32, f32);
1012

1113
extern "platform-intrinsic" {
14+
#[rustc_const_stable(feature = "foo", since = "1.3.37")]
1215
fn simd_insert<T, U>(x: T, idx: u32, val: U) -> T;
16+
#[rustc_const_stable(feature = "foo", since = "1.3.37")]
1317
fn simd_extract<T, U>(x: T, idx: u32) -> U;
1418
}
1519

src/test/ui/consts/const-fn-type-name.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#![feature(core_intrinsics)]
44
#![feature(const_fn)]
5+
#![feature(const_type_name)]
56
#![allow(dead_code)]
67

78
const fn type_name_wrapper<T>(_: &T) -> &'static str {

0 commit comments

Comments
 (0)