about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMahmut Bulut <vertexclique@gmail.com>2019-06-14 16:55:36 +0300
committerOliver Scherer <github35764891676564198441@oli-obk.de>2019-12-03 10:20:15 +0100
commitf1bacb2dca610b0babeba526020e2b87899c2d44 (patch)
treedc79946f7e408b3e2d67ba1fb1df716061b85ceb
parent4787e97475de6be9487e3d9255a9c2d3c0bf9252 (diff)
downloadrust-f1bacb2dca610b0babeba526020e2b87899c2d44.tar.gz
rust-f1bacb2dca610b0babeba526020e2b87899c2d44.zip
Check intrinsics for callability in const fns
-rw-r--r--src/libcore/intrinsics.rs1
-rw-r--r--src/librustc/ty/constness.rs70
-rw-r--r--src/librustc_feature/active.rs4
-rw-r--r--src/librustc_metadata/rmeta/decoder.rs2
-rw-r--r--src/librustc_metadata/rmeta/encoder.rs6
-rw-r--r--src/librustc_mir/interpret/intrinsics.rs129
-rw-r--r--src/librustc_mir/transform/check_consts/ops.rs16
-rw-r--r--src/librustc_mir/transform/check_consts/validation.rs18
-rw-r--r--src/librustc_mir/transform/qualify_min_const_fn.rs42
-rw-r--r--src/libsyntax_pos/symbol.rs29
-rw-r--r--src/test/ui/consts/const-eval/const-eval-intrinsic-promotion.rs6
-rw-r--r--src/test/ui/consts/const-eval/const-eval-intrinsic-promotion.stderr13
-rw-r--r--src/test/ui/feature-gates/feature-gate-const_transmute.rs2
-rw-r--r--src/test/ui/feature-gates/feature-gate-const_transmute.stderr4
14 files changed, 212 insertions, 130 deletions
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index d4952f53bf7..19928f30f2e 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -939,6 +939,7 @@ extern "rust-intrinsic" {
     /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_unstable(feature = "const_transmute")]
     pub fn transmute<T, U>(e: T) -> U;
 
     /// Returns `true` if the actual type given as `T` requires drop
diff --git a/src/librustc/ty/constness.rs b/src/librustc/ty/constness.rs
index 676916f530a..0fb3f575b52 100644
--- a/src/librustc/ty/constness.rs
+++ b/src/librustc/ty/constness.rs
@@ -2,7 +2,8 @@ use crate::ty::query::Providers;
 use crate::hir::def_id::DefId;
 use crate::hir;
 use crate::ty::TyCtxt;
-use syntax_pos::symbol::Symbol;
+use syntax_pos::symbol::{sym, Symbol};
+use rustc_target::spec::abi::Abi;
 use crate::hir::map::blocks::FnLikeNode;
 use syntax::attr;
 
@@ -63,13 +64,76 @@ impl<'tcx> TyCtxt<'tcx> {
 
 
 pub fn provide(providers: &mut Providers<'_>) {
-    /// only checks whether the function has a `const` modifier
+    /// Const evaluability whitelist is here to check evaluability at the
+    /// top level beforehand.
+    fn is_const_intrinsic(tcx: TyCtxt<'_>, def_id: DefId) -> Option<bool> {
+        match tcx.fn_sig(def_id).abi() {
+            Abi::RustIntrinsic |
+            Abi::PlatformIntrinsic => {
+                match tcx.item_name(def_id) {
+                    // Keep this list in the same order as the match patterns in
+                    // `librustc_mir/interpret/intrinsics.rs`
+                    | 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
+        }
+    }
+
+    /// Checks whether the function has a `const` modifier or, in case it is an intrinsic, whether
+    /// said intrinsic is on the whitelist for being const callable.
     fn is_const_fn_raw(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
         let hir_id = tcx.hir().as_local_hir_id(def_id)
                               .expect("Non-local call to local provider is_const_fn");
 
         let node = tcx.hir().get(hir_id);
-        if let Some(fn_like) = FnLikeNode::from_node(node) {
+
+        if let Some(whitelisted) = is_const_intrinsic(tcx, def_id) {
+            whitelisted
+        } else if let Some(fn_like) = FnLikeNode::from_node(node) {
             fn_like.constness() == hir::Constness::Const
         } else if let hir::Node::Ctor(_) = node {
             true
diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs
index 16d8ada9f24..fc880b9e929 100644
--- a/src/librustc_feature/active.rs
+++ b/src/librustc_feature/active.rs
@@ -408,10 +408,6 @@ declare_features! (
     /// Allows using `#[doc(keyword = "...")]`.
     (active, doc_keyword, "1.28.0", Some(51315), None),
 
-    /// Allows reinterpretation of the bits of a value of one type as another
-    /// type during const eval.
-    (active, const_transmute, "1.29.0", Some(53605), None),
-
     /// Allows using `try {...}` expressions.
     (active, try_blocks, "1.29.0", Some(31436), None),
 
diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs
index 42db642cd4d..b494c9bdd38 100644
--- a/src/librustc_metadata/rmeta/decoder.rs
+++ b/src/librustc_metadata/rmeta/decoder.rs
@@ -1364,6 +1364,8 @@ impl<'a, 'tcx> CrateMetadata {
         let constness = match self.kind(id) {
             EntryKind::Method(data) => data.decode(self).fn_data.constness,
             EntryKind::Fn(data) => data.decode(self).constness,
+            // Some intrinsics can be const fn
+            EntryKind::ForeignFn(data) => data.decode(self).constness,
             EntryKind::Variant(..) | EntryKind::Struct(..) => hir::Constness::Const,
             _ => hir::Constness::NotConst,
         };
diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs
index 3a318ddc1e1..fb70e10c84f 100644
--- a/src/librustc_metadata/rmeta/encoder.rs
+++ b/src/librustc_metadata/rmeta/encoder.rs
@@ -1525,7 +1525,11 @@ impl EncodeContext<'tcx> {
             hir::ForeignItemKind::Fn(_, ref names, _) => {
                 let data = FnData {
                     asyncness: hir::IsAsync::NotAsync,
-                    constness: hir::Constness::NotConst,
+                    constness: if self.tcx.is_const_fn_raw(def_id) {
+                        hir::Constness::Const
+                    } else {
+                        hir::Constness::NotConst
+                    },
                     param_names: self.encode_fn_param_names(names),
                 };
                 EntryKind::ForeignFn(self.lazy(data))
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index 118dfcb3d9a..f6fdc51a8c2 100644
--- a/src/librustc_mir/interpret/intrinsics.rs
+++ b/src/librustc_mir/interpret/intrinsics.rs
@@ -2,7 +2,7 @@
 //! looking at their MIR. Intrinsics/functions supported here are shared by CTFE
 //! and miri.
 
-use syntax::symbol::Symbol;
+use syntax_pos::symbol::{sym, Symbol};
 use syntax_pos::Span;
 use rustc::ty;
 use rustc::ty::layout::{LayoutOf, Primitive, Size};
@@ -22,7 +22,7 @@ mod caller_location;
 mod type_name;
 
 fn numeric_intrinsic<'tcx, Tag>(
-    name: &str,
+    name: Symbol,
     bits: u128,
     kind: Primitive,
 ) -> InterpResult<'tcx, Scalar<Tag>> {
@@ -32,11 +32,11 @@ fn numeric_intrinsic<'tcx, Tag>(
     };
     let extra = 128 - size.bits() as u128;
     let bits_out = match name {
-        "ctpop" => bits.count_ones() as u128,
-        "ctlz" => bits.leading_zeros() as u128 - extra,
-        "cttz" => (bits << extra).trailing_zeros() as u128 - extra,
-        "bswap" => (bits << extra).swap_bytes(),
-        "bitreverse" => (bits << extra).reverse_bits(),
+        sym::ctpop => bits.count_ones() as u128,
+        sym::ctlz => bits.leading_zeros() as u128 - extra,
+        sym::cttz => (bits << extra).trailing_zeros() as u128 - extra,
+        sym::bswap => (bits << extra).swap_bytes(),
+        sym::bitreverse => (bits << extra).reverse_bits(),
         _ => bug!("not a numeric intrinsic: {}", name),
     };
     Ok(Scalar::from_uint(bits_out, size))
@@ -51,9 +51,9 @@ crate fn eval_nullary_intrinsic<'tcx>(
     substs: SubstsRef<'tcx>,
 ) -> InterpResult<'tcx, &'tcx ty::Const<'tcx>> {
     let tp_ty = substs.type_at(0);
-    let name = &*tcx.item_name(def_id).as_str();
+    let name = tcx.item_name(def_id);
     Ok(match name {
-        "type_name" => {
+        sym::type_name => {
             let alloc = type_name::alloc_type_name(tcx, tp_ty);
             tcx.mk_const(ty::Const {
                 val: ty::ConstKind::Value(ConstValue::Slice {
@@ -64,20 +64,20 @@ crate fn eval_nullary_intrinsic<'tcx>(
                 ty: tcx.mk_static_str(),
             })
         },
-        "needs_drop" => ty::Const::from_bool(tcx, tp_ty.needs_drop(tcx, param_env)),
-        "size_of" |
-        "min_align_of" |
-        "pref_align_of" => {
+        sym::needs_drop => ty::Const::from_bool(tcx, tp_ty.needs_drop(tcx, param_env)),
+        sym::size_of |
+        sym::min_align_of |
+        sym::pref_align_of => {
             let layout = tcx.layout_of(param_env.and(tp_ty)).map_err(|e| err_inval!(Layout(e)))?;
             let n = match name {
-                "pref_align_of" => layout.align.pref.bytes(),
-                "min_align_of" => layout.align.abi.bytes(),
-                "size_of" => layout.size.bytes(),
+                sym::pref_align_of => layout.align.pref.bytes(),
+                sym::min_align_of => layout.align.abi.bytes(),
+                sym::size_of => layout.size.bytes(),
                 _ => bug!(),
             };
             ty::Const::from_usize(tcx, n)
         },
-        "type_id" => ty::Const::from_bits(
+        sym::type_id => ty::Const::from_bits(
             tcx,
             tcx.type_id_hash(tp_ty).into(),
             param_env.and(tcx.types.u64),
@@ -96,30 +96,32 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         ret: Option<(PlaceTy<'tcx, M::PointerTag>, mir::BasicBlock)>,
     ) -> InterpResult<'tcx, bool> {
         let substs = instance.substs;
-        let intrinsic_name = &*self.tcx.item_name(instance.def_id()).as_str();
+        let intrinsic_name = self.tcx.item_name(instance.def_id());
 
         // We currently do not handle any intrinsics that are *allowed* to diverge,
         // but `transmute` could lack a return place in case of UB.
         let (dest, ret) = match ret {
             Some(p) => p,
             None => match intrinsic_name {
-                "transmute" => throw_ub!(Unreachable),
+                sym::transmute => throw_ub!(Unreachable),
                 _ => return Ok(false),
             }
         };
 
+        // Keep the patterns in this match ordered the same as the list in
+        // `src/librustc/ty/constness.rs`
         match intrinsic_name {
-            "caller_location" => {
+            sym::caller_location => {
                 let location = self.alloc_caller_location_for_span(span);
                 self.write_scalar(location.ptr, dest)?;
             }
 
-            "min_align_of" |
-            "pref_align_of" |
-            "needs_drop" |
-            "size_of" |
-            "type_id" |
-            "type_name" => {
+            sym::min_align_of |
+            sym::pref_align_of |
+            sym::needs_drop |
+            sym::size_of |
+            sym::type_id |
+            sym::type_name => {
                 let gid = GlobalId {
                     instance,
                     promoted: None,
@@ -129,13 +131,13 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 self.copy_op(val, dest)?;
             }
 
-            | "ctpop"
-            | "cttz"
-            | "cttz_nonzero"
-            | "ctlz"
-            | "ctlz_nonzero"
-            | "bswap"
-            | "bitreverse" => {
+            | sym::ctpop
+            | sym::cttz
+            | sym::cttz_nonzero
+            | sym::ctlz
+            | sym::ctlz_nonzero
+            | sym::bswap
+            | sym::bitreverse => {
                 let ty = substs.type_at(0);
                 let layout_of = self.layout_of(ty)?;
                 let val = self.read_scalar(args[0])?.not_undef()?;
@@ -144,31 +146,32 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     ty::layout::Abi::Scalar(ref scalar) => scalar.value,
                     _ => throw_unsup!(TypeNotPrimitive(ty)),
                 };
-                let out_val = if intrinsic_name.ends_with("_nonzero") {
-                    if bits == 0 {
-                        throw_ub_format!("`{}` called on 0", intrinsic_name);
-                    }
-                    numeric_intrinsic(intrinsic_name.trim_end_matches("_nonzero"), bits, kind)?
-                } else {
-                    numeric_intrinsic(intrinsic_name, bits, kind)?
+                let (nonzero, intrinsic_name) = match intrinsic_name {
+                    sym::cttz_nonzero => (true, sym::cttz),
+                    sym::ctlz_nonzero => (true, sym::ctlz),
+                    other => (false, other),
                 };
+                if nonzero && bits == 0 {
+                    throw_ub_format!("`{}_nonzero` called on 0", intrinsic_name);
+                }
+                let out_val = numeric_intrinsic(intrinsic_name, bits, kind)?;
                 self.write_scalar(out_val, dest)?;
             }
-            | "wrapping_add"
-            | "wrapping_sub"
-            | "wrapping_mul"
-            | "add_with_overflow"
-            | "sub_with_overflow"
-            | "mul_with_overflow" => {
+            | sym::wrapping_add
+            | sym::wrapping_sub
+            | sym::wrapping_mul
+            | sym::add_with_overflow
+            | sym::sub_with_overflow
+            | sym::mul_with_overflow => {
                 let lhs = self.read_immediate(args[0])?;
                 let rhs = self.read_immediate(args[1])?;
                 let (bin_op, ignore_overflow) = match intrinsic_name {
-                    "wrapping_add" => (BinOp::Add, true),
-                    "wrapping_sub" => (BinOp::Sub, true),
-                    "wrapping_mul" => (BinOp::Mul, true),
-                    "add_with_overflow" => (BinOp::Add, false),
-                    "sub_with_overflow" => (BinOp::Sub, false),
-                    "mul_with_overflow" => (BinOp::Mul, false),
+                    sym::wrapping_add => (BinOp::Add, true),
+                    sym::wrapping_sub => (BinOp::Sub, true),
+                    sym::wrapping_mul => (BinOp::Mul, true),
+                    sym::add_with_overflow => (BinOp::Add, false),
+                    sym::sub_with_overflow => (BinOp::Sub, false),
+                    sym::mul_with_overflow => (BinOp::Mul, false),
                     _ => bug!("Already checked for int ops")
                 };
                 if ignore_overflow {
@@ -177,10 +180,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     self.binop_with_overflow(bin_op, lhs, rhs, dest)?;
                 }
             }
-            "saturating_add" | "saturating_sub" => {
+            sym::saturating_add | sym::saturating_sub => {
                 let l = self.read_immediate(args[0])?;
                 let r = self.read_immediate(args[1])?;
-                let is_add = intrinsic_name == "saturating_add";
+                let is_add = intrinsic_name == sym::saturating_add;
                 let (val, overflowed, _ty) = self.overflowing_binary_op(if is_add {
                     BinOp::Add
                 } else {
@@ -220,12 +223,12 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 };
                 self.write_scalar(val, dest)?;
             }
-            "unchecked_shl" | "unchecked_shr" => {
+            sym::unchecked_shl | sym::unchecked_shr => {
                 let l = self.read_immediate(args[0])?;
                 let r = self.read_immediate(args[1])?;
                 let bin_op = match intrinsic_name {
-                    "unchecked_shl" => BinOp::Shl,
-                    "unchecked_shr" => BinOp::Shr,
+                    sym::unchecked_shl => BinOp::Shl,
+                    sym::unchecked_shr => BinOp::Shr,
                     _ => bug!("Already checked for int ops")
                 };
                 let (val, overflowed, _ty) = self.overflowing_binary_op(bin_op, l, r)?;
@@ -236,7 +239,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 }
                 self.write_scalar(val, dest)?;
             }
-            "rotate_left" | "rotate_right" => {
+            sym::rotate_left | sym::rotate_right => {
                 // rotate_left: (X << (S % BW)) | (X >> ((BW - S) % BW))
                 // rotate_right: (X << ((BW - S) % BW)) | (X >> (S % BW))
                 let layout = self.layout_of(substs.type_at(0))?;
@@ -247,7 +250,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let width_bits = layout.size.bits() as u128;
                 let shift_bits = raw_shift_bits % width_bits;
                 let inv_shift_bits = (width_bits - shift_bits) % width_bits;
-                let result_bits = if intrinsic_name == "rotate_left" {
+                let result_bits = if intrinsic_name == sym::rotate_left {
                     (val_bits << shift_bits) | (val_bits >> inv_shift_bits)
                 } else {
                     (val_bits >> shift_bits) | (val_bits << inv_shift_bits)
@@ -257,7 +260,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 self.write_scalar(result, dest)?;
             }
 
-            "ptr_offset_from" => {
+            sym::ptr_offset_from => {
                 let isize_layout = self.layout_of(self.tcx.types.isize)?;
                 let a = self.read_immediate(args[0])?.to_scalar()?;
                 let b = self.read_immediate(args[1])?.to_scalar()?;
@@ -303,10 +306,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 }
             }
 
-            "transmute" => {
+            sym::transmute => {
                 self.copy_op_transmute(args[0], dest)?;
             }
-            "simd_insert" => {
+            sym::simd_insert => {
                 let index = u64::from(self.read_scalar(args[1])?.to_u32()?);
                 let elem = args[2];
                 let input = args[0];
@@ -337,7 +340,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     self.copy_op(value, place)?;
                 }
             }
-            "simd_extract" => {
+            sym::simd_extract => {
                 let index = u64::from(self.read_scalar(args[1])?.to_u32()?);
                 let (len, e_ty) = args[0].layout.ty.simd_size_and_type(self.tcx.tcx);
                 assert!(
diff --git a/src/librustc_mir/transform/check_consts/ops.rs b/src/librustc_mir/transform/check_consts/ops.rs
index a4f12a4e54f..aec3cf04a97 100644
--- a/src/librustc_mir/transform/check_consts/ops.rs
+++ b/src/librustc_mir/transform/check_consts/ops.rs
@@ -327,22 +327,6 @@ impl NonConstOp for ThreadLocalAccess {
 }
 
 #[derive(Debug)]
-pub struct Transmute;
-impl NonConstOp for Transmute {
-    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
-        Some(tcx.features().const_transmute)
-    }
-
-    fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
-        feature_err(
-            &item.tcx.sess.parse_sess, sym::const_transmute, span,
-            &format!("The use of std::mem::transmute() is gated in {}s", item.const_kind())
-        )
-        .emit();
-    }
-}
-
-#[derive(Debug)]
 pub struct UnionAccess;
 impl NonConstOp for UnionAccess {
     fn is_allowed_in_item(&self, item: &Item<'_, '_>) -> bool {
diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs
index 9d477bfbae8..78e6d879c46 100644
--- a/src/librustc_mir/transform/check_consts/validation.rs
+++ b/src/librustc_mir/transform/check_consts/validation.rs
@@ -8,7 +8,6 @@ use rustc::traits::{self, TraitEngine};
 use rustc::ty::cast::CastTy;
 use rustc::ty::{self, TyCtxt};
 use rustc_index::bit_set::BitSet;
-use rustc_target::spec::abi::Abi;
 use rustc_error_codes::*;
 use syntax::symbol::sym;
 use syntax_pos::Span;
@@ -564,23 +563,6 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
                 };
 
                 // At this point, we are calling a function whose `DefId` is known...
-
-                if let Abi::RustIntrinsic | Abi::PlatformIntrinsic = self.tcx.fn_sig(def_id).abi() {
-                    assert!(!self.tcx.is_const_fn(def_id));
-
-                    if self.tcx.item_name(def_id) == sym::transmute {
-                        self.check_op(ops::Transmute);
-                        return;
-                    }
-
-                    // To preserve the current semantics, we return early, allowing all
-                    // intrinsics (except `transmute`) to pass unchecked to miri.
-                    //
-                    // FIXME: We should keep a whitelist of allowed intrinsics (or at least a
-                    // blacklist of unimplemented ones) and fail here instead.
-                    return;
-                }
-
                 if self.tcx.is_const_fn(def_id) {
                     return;
                 }
diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
index e40d6a5952e..b7e1b83ee05 100644
--- a/src/librustc_mir/transform/qualify_min_const_fn.rs
+++ b/src/librustc_mir/transform/qualify_min_const_fn.rs
@@ -415,28 +415,28 @@ fn check_terminator(
 ///
 /// Adding more intrinsics requires sign-off from @rust-lang/lang.
 fn is_intrinsic_whitelisted(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
-    match &*tcx.item_name(def_id).as_str() {
-        | "size_of"
-        | "min_align_of"
-        | "needs_drop"
+    match tcx.item_name(def_id) {
+        | sym::size_of
+        | sym::min_align_of
+        | sym::needs_drop
         // Arithmetic:
-        | "add_with_overflow" // ~> .overflowing_add
-        | "sub_with_overflow" // ~> .overflowing_sub
-        | "mul_with_overflow" // ~> .overflowing_mul
-        | "wrapping_add" // ~> .wrapping_add
-        | "wrapping_sub" // ~> .wrapping_sub
-        | "wrapping_mul" // ~> .wrapping_mul
-        | "saturating_add" // ~> .saturating_add
-        | "saturating_sub" // ~> .saturating_sub
-        | "unchecked_shl" // ~> .wrapping_shl
-        | "unchecked_shr" // ~> .wrapping_shr
-        | "rotate_left" // ~> .rotate_left
-        | "rotate_right" // ~> .rotate_right
-        | "ctpop" // ~> .count_ones
-        | "ctlz" // ~> .leading_zeros
-        | "cttz" // ~> .trailing_zeros
-        | "bswap" // ~> .swap_bytes
-        | "bitreverse" // ~> .reverse_bits
+        | 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,
     }
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index 3059b059691..0d0b8598cc6 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -121,6 +121,7 @@ symbols! {
         abi_vectorcall,
         abi_x86_interrupt,
         aborts,
+        add_with_overflow,
         advanced_slice_patterns,
         adx_target_feature,
         alias,
@@ -171,7 +172,10 @@ symbols! {
         box_patterns,
         box_syntax,
         braced_empty_structs,
+        bswap,
+        bitreverse,
         C,
+        caller_location,
         cdylib,
         cfg,
         cfg_attr,
@@ -226,6 +230,11 @@ symbols! {
         crate_name,
         crate_type,
         crate_visibility_modifier,
+        ctpop,
+        cttz,
+        cttz_nonzero,
+        ctlz,
+        ctlz_nonzero,
         custom_attribute,
         custom_derive,
         custom_inner_attributes,
@@ -430,6 +439,7 @@ symbols! {
         member_constraints,
         message,
         meta,
+        min_align_of,
         min_const_fn,
         min_const_unsafe_fn,
         mips_target_feature,
@@ -439,11 +449,13 @@ symbols! {
         more_struct_aliases,
         move_val_init,
         movbe_target_feature,
+        mul_with_overflow,
         must_use,
         naked,
         naked_functions,
         name,
         needs_allocator,
+        needs_drop,
         needs_panic_runtime,
         negate_unsigned,
         never,
@@ -519,6 +531,7 @@ symbols! {
         poll_with_tls_context,
         powerpc_target_feature,
         precise_pointer_size_matching,
+        pref_align_of,
         prelude,
         prelude_import,
         primitive,
@@ -535,6 +548,7 @@ symbols! {
         proc_macro_non_items,
         proc_macro_path_invoc,
         profiler_runtime,
+        ptr_offset_from,
         pub_restricted,
         pushpop_unsafe,
         quad_precision_float,
@@ -570,6 +584,8 @@ symbols! {
         Return,
         rhs,
         rlib,
+        rotate_left,
+        rotate_right,
         rt,
         rtm_target_feature,
         rust,
@@ -637,14 +653,19 @@ symbols! {
         rvalue_static_promotion,
         sanitize,
         sanitizer_runtime,
+        saturating_add,
+        saturating_sub,
         _Self,
         self_in_typedefs,
         self_struct_ctor,
         should_panic,
         simd,
+        simd_extract,
         simd_ffi,
+        simd_insert,
         since,
         size,
+        size_of,
         slice_patterns,
         slicing_syntax,
         soft,
@@ -672,6 +693,7 @@ symbols! {
         structural_match,
         struct_variant,
         sty,
+        sub_with_overflow,
         suggestion,
         target_feature,
         target_has_atomic,
@@ -707,6 +729,8 @@ symbols! {
         Ty,
         ty,
         type_alias_impl_trait,
+        type_id,
+        type_name,
         TyCtxt,
         TyKind,
         type_alias_enum_variants,
@@ -719,6 +743,8 @@ symbols! {
         u64,
         u8,
         unboxed_closures,
+        unchecked_shl,
+        unchecked_shr,
         underscore_const_names,
         underscore_imports,
         underscore_lifetimes,
@@ -752,6 +778,9 @@ symbols! {
         while_let,
         windows,
         windows_subsystem,
+        wrapping_add,
+        wrapping_sub,
+        wrapping_mul,
         Yield,
     }
 }
diff --git a/src/test/ui/consts/const-eval/const-eval-intrinsic-promotion.rs b/src/test/ui/consts/const-eval/const-eval-intrinsic-promotion.rs
new file mode 100644
index 00000000000..bdcf537859c
--- /dev/null
+++ b/src/test/ui/consts/const-eval/const-eval-intrinsic-promotion.rs
@@ -0,0 +1,6 @@
+#![feature(core_intrinsics)]
+fn main() {
+    // Test that calls to intrinsics are never promoted
+    let x: &'static usize =
+        &std::intrinsics::size_of::<i32>(); //~ ERROR temporary value dropped while borrowed
+}
diff --git a/src/test/ui/consts/const-eval/const-eval-intrinsic-promotion.stderr b/src/test/ui/consts/const-eval/const-eval-intrinsic-promotion.stderr
new file mode 100644
index 00000000000..78143042ece
--- /dev/null
+++ b/src/test/ui/consts/const-eval/const-eval-intrinsic-promotion.stderr
@@ -0,0 +1,13 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/const-eval-intrinsic-promotion.rs:5:10
+   |
+LL |     let x: &'static usize =
+   |            -------------- type annotation requires that borrow lasts for `'static`
+LL |         &std::intrinsics::size_of::<i32>();
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/feature-gates/feature-gate-const_transmute.rs b/src/test/ui/feature-gates/feature-gate-const_transmute.rs
index 6a5bbec77fd..da532643d94 100644
--- a/src/test/ui/feature-gates/feature-gate-const_transmute.rs
+++ b/src/test/ui/feature-gates/feature-gate-const_transmute.rs
@@ -4,6 +4,6 @@ use std::mem;
 struct Foo(u32);
 
 const TRANSMUTED_U32: u32 = unsafe { mem::transmute(Foo(3)) };
-//~^ ERROR The use of std::mem::transmute() is gated in constants
+//~^ ERROR `std::intrinsics::transmute` is not yet stable as a const fn
 
 fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-const_transmute.stderr b/src/test/ui/feature-gates/feature-gate-const_transmute.stderr
index 41b653d98dc..772e8d29478 100644
--- a/src/test/ui/feature-gates/feature-gate-const_transmute.stderr
+++ b/src/test/ui/feature-gates/feature-gate-const_transmute.stderr
@@ -1,12 +1,10 @@
-error[E0658]: The use of std::mem::transmute() is gated in constants
+error: `std::intrinsics::transmute` is not yet stable as a const fn
   --> $DIR/feature-gate-const_transmute.rs:6:38
    |
 LL | const TRANSMUTED_U32: u32 = unsafe { mem::transmute(Foo(3)) };
    |                                      ^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/53605
    = help: add `#![feature(const_transmute)]` to the crate attributes to enable
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0658`.