about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-05-17 09:39:26 +0000
committerbors <bors@rust-lang.org>2022-05-17 09:39:26 +0000
commit735efc0c703812343a5e5d19b600dac73b8a89f0 (patch)
tree59db2d0d1eba880d8a0b83c2e1a64d346a288551
parent7355d971a954ed63293e4191f6677f60c1bc07d9 (diff)
parent0a6b69106eb1df116404a3be123baf100e6cdf21 (diff)
downloadrust-735efc0c703812343a5e5d19b600dac73b8a89f0.tar.gz
rust-735efc0c703812343a5e5d19b600dac73b8a89f0.zip
Auto merge of #97012 - oli-obk:🦀_intrinsics, r=davidtwco
Add a query for checking whether a function is an intrinsic.

work towards #93145

This will reduce churn when we add more ways to declare intrinsics

r? `@scottmcm`
-rw-r--r--compiler/rustc_const_eval/src/const_eval/fn_queries.rs6
-rw-r--r--compiler/rustc_const_eval/src/interpret/terminator.rs4
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs4
-rw-r--r--compiler/rustc_lint/src/builtin.rs4
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs4
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs1
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs9
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs1
-rw-r--r--compiler/rustc_middle/src/query/mod.rs5
-rw-r--r--compiler/rustc_middle/src/ty/util.rs9
-rw-r--r--compiler/rustc_mir_dataflow/src/rustc_peek.rs4
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs3
-rw-r--r--compiler/rustc_mir_transform/src/lower_intrinsics.rs4
-rw-r--r--compiler/rustc_passes/src/intrinsicck.rs4
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs8
-rw-r--r--compiler/rustc_typeck/src/check/coercion.rs22
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs3
17 files changed, 51 insertions, 44 deletions
diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
index 1f291db55be..777f4393458 100644
--- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
@@ -4,7 +4,6 @@ use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{DefIdTree, TyCtxt};
 use rustc_span::symbol::Symbol;
-use rustc_target::spec::abi::Abi;
 
 /// Whether the `def_id` is an unstable const fn and what feature gate is necessary to enable it
 pub fn is_unstable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Symbol> {
@@ -34,10 +33,7 @@ fn impl_constness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Constness {
         hir::Node::ForeignItem(hir::ForeignItem { kind: hir::ForeignItemKind::Fn(..), .. }) => {
             // Intrinsics use `rustc_const_{un,}stable` attributes to indicate constness. All other
             // foreign items cannot be evaluated at compile-time.
-            let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
-            let is_const = if let Abi::RustIntrinsic | Abi::PlatformIntrinsic =
-                tcx.hir().get_foreign_abi(hir_id)
-            {
+            let is_const = if tcx.is_intrinsic(def_id) {
                 tcx.lookup_const_stability(def_id).is_some()
             } else {
                 false
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index c2664565f15..25f9d4baca3 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -312,8 +312,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         };
 
         match instance.def {
-            ty::InstanceDef::Intrinsic(..) => {
-                assert!(caller_abi == Abi::RustIntrinsic || caller_abi == Abi::PlatformIntrinsic);
+            ty::InstanceDef::Intrinsic(def_id) => {
+                assert!(self.tcx.is_intrinsic(def_id));
                 // caller_fn_abi is not relevant here, we interpret the arguments directly for each intrinsic.
                 M::call_intrinsic(self, instance, args, ret, unwind)
             }
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index 8d3bbefb371..1104bbf4716 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -702,8 +702,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
 
     #[instrument(level = "debug", skip(self))]
     fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
-        use rustc_target::spec::abi::Abi::RustIntrinsic;
-
         self.super_terminator(terminator, location);
 
         match &terminator.kind {
@@ -885,7 +883,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                     return;
                 }
 
-                let is_intrinsic = tcx.fn_sig(callee).abi() == RustIntrinsic;
+                let is_intrinsic = tcx.is_intrinsic(callee);
 
                 if !tcx.is_const_fn_raw(callee) {
                     if tcx.trait_of_item(callee).is_some() {
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index a87083a082b..585edfc47e1 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -1252,7 +1252,6 @@ declare_lint_pass!(MutableTransmutes => [MUTABLE_TRANSMUTES]);
 
 impl<'tcx> LateLintPass<'tcx> for MutableTransmutes {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
-        use rustc_target::spec::abi::Abi::RustIntrinsic;
         if let Some((&ty::Ref(_, _, from_mt), &ty::Ref(_, _, to_mt))) =
             get_transmute_from_to(cx, expr).map(|(ty1, ty2)| (ty1.kind(), ty2.kind()))
         {
@@ -1287,8 +1286,7 @@ impl<'tcx> LateLintPass<'tcx> for MutableTransmutes {
         }
 
         fn def_id_is_transmute(cx: &LateContext<'_>, def_id: DefId) -> bool {
-            cx.tcx.fn_sig(def_id).abi() == RustIntrinsic
-                && cx.tcx.item_name(def_id) == sym::transmute
+            cx.tcx.is_intrinsic(def_id) && cx.tcx.item_name(def_id) == sym::transmute
         }
     }
 }
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index b25522cfd96..de1e96ebfe7 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -1752,6 +1752,10 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     fn get_may_have_doc_links(self, index: DefIndex) -> bool {
         self.root.tables.may_have_doc_links.get(self, index).is_some()
     }
+
+    fn get_is_intrinsic(self, index: DefIndex) -> bool {
+        self.root.tables.is_intrinsic.get(self, index).is_some()
+    }
 }
 
 impl CrateMetadata {
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 9f7ef3981c7..065224a2a65 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -224,6 +224,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
         tcx.arena.alloc_slice(&result)
     }
     defined_lib_features => { cdata.get_lib_features(tcx) }
+    is_intrinsic => { cdata.get_is_intrinsic(def_id.index) }
     defined_lang_items => { cdata.get_lang_items(tcx) }
     diagnostic_items => { cdata.get_diagnostic_items() }
     missing_lang_items => { cdata.get_missing_lang_items(tcx) }
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index ebf6a552170..39e6ddb316d 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1318,6 +1318,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         }
         if impl_item.kind == ty::AssocKind::Fn {
             record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
+            if tcx.is_intrinsic(def_id) {
+                self.tables.is_intrinsic.set(def_id.index, ());
+            }
         }
     }
 
@@ -1562,6 +1565,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         }
         if let hir::ItemKind::Fn(..) = item.kind {
             record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
+            if tcx.is_intrinsic(def_id) {
+                self.tables.is_intrinsic.set(def_id.index, ());
+            }
         }
         if let hir::ItemKind::Impl { .. } = item.kind {
             if let Some(trait_ref) = self.tcx.impl_trait_ref(def_id) {
@@ -1958,6 +1964,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         self.encode_item_type(def_id);
         if let hir::ForeignItemKind::Fn(..) = nitem.kind {
             record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
+            if tcx.is_intrinsic(def_id) {
+                self.tables.is_intrinsic.set(def_id.index, ());
+            }
         }
     }
 }
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index 356dad4b56b..1c5774db579 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -340,6 +340,7 @@ define_tables! {
     impl_parent: Table<DefIndex, RawDefId>,
     impl_polarity: Table<DefIndex, ty::ImplPolarity>,
     impl_constness: Table<DefIndex, hir::Constness>,
+    is_intrinsic: Table<DefIndex, ()>,
     impl_defaultness: Table<DefIndex, hir::Defaultness>,
     // FIXME(eddyb) perhaps compute this on the fly if cheap enough?
     coerce_unsized_info: Table<DefIndex, Lazy!(ty::adjustment::CoerceUnsizedInfo)>,
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 6d7ec247d04..f133494caaa 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -1601,6 +1601,11 @@ rustc_queries! {
         desc { "calculating the lib features defined in a crate" }
         separate_provide_extern
     }
+    /// Whether the function is an intrinsic
+    query is_intrinsic(def_id: DefId) -> bool {
+        desc { |tcx| "is_intrinsic({})", tcx.def_path_str(def_id) }
+        separate_provide_extern
+    }
     /// Returns the lang items defined in another crate by loading it from metadata.
     query get_lang_items(_: ()) -> LanguageItems {
         storage(ArenaCacheSelector<'tcx>)
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 10520670069..3fa5a140090 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -21,6 +21,7 @@ use rustc_hir::def_id::DefId;
 use rustc_macros::HashStable;
 use rustc_span::{sym, DUMMY_SP};
 use rustc_target::abi::{Integer, Size, TargetDataLayout};
+use rustc_target::spec::abi::Abi;
 use smallvec::SmallVec;
 use std::{fmt, iter};
 
@@ -1195,6 +1196,12 @@ pub fn is_doc_hidden(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
         .any(|items| items.iter().any(|item| item.has_name(sym::hidden)))
 }
 
+/// Determines whether an item is an intrinsic by Abi.
+pub fn is_intrinsic(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
+    matches!(tcx.fn_sig(def_id).abi(), Abi::RustIntrinsic | Abi::PlatformIntrinsic)
+}
+
 pub fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers { normalize_opaque_types, is_doc_hidden, ..*providers }
+    *providers =
+        ty::query::Providers { normalize_opaque_types, is_doc_hidden, is_intrinsic, ..*providers }
 }
diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs
index cc9ee1016c6..2f884887ad9 100644
--- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs
+++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs
@@ -1,6 +1,5 @@
 use rustc_span::symbol::sym;
 use rustc_span::Span;
-use rustc_target::spec::abi::Abi;
 
 use rustc_index::bit_set::BitSet;
 use rustc_middle::mir::MirPass;
@@ -193,9 +192,8 @@ impl PeekCall {
             &terminator.kind
         {
             if let ty::FnDef(def_id, substs) = *func.literal.ty().kind() {
-                let sig = tcx.fn_sig(def_id);
                 let name = tcx.item_name(def_id);
-                if sig.abi() != Abi::RustIntrinsic || name != sym::rustc_peek {
+                if !tcx.is_intrinsic(def_id) || name != sym::rustc_peek {
                     return None;
                 }
 
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index 012ce730755..5f8e6608ab5 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -418,8 +418,7 @@ impl<'tcx> Inliner<'tcx> {
                             }
                         }
                         // Don't give intrinsics the extra penalty for calls
-                        let f = tcx.fn_sig(def_id);
-                        if f.abi() == Abi::RustIntrinsic || f.abi() == Abi::PlatformIntrinsic {
+                        if tcx.is_intrinsic(def_id) {
                             cost += INSTR_COST;
                         } else {
                             cost += CALL_PENALTY;
diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
index 684d988ee9e..d0d0e09d525 100644
--- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs
+++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
@@ -6,7 +6,6 @@ use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
-use rustc_target::spec::abi::Abi;
 
 pub struct LowerIntrinsics;
 
@@ -139,8 +138,7 @@ fn resolve_rust_intrinsic<'tcx>(
     func_ty: Ty<'tcx>,
 ) -> Option<(Symbol, SubstsRef<'tcx>)> {
     if let ty::FnDef(def_id, substs) = *func_ty.kind() {
-        let fn_sig = func_ty.fn_sig(tcx);
-        if let Abi::RustIntrinsic | Abi::PlatformIntrinsic = fn_sig.abi() {
+        if tcx.is_intrinsic(def_id) {
             return Some((tcx.item_name(def_id), substs));
         }
     }
diff --git a/compiler/rustc_passes/src/intrinsicck.rs b/compiler/rustc_passes/src/intrinsicck.rs
index 95f6f7ef864..9c840777baf 100644
--- a/compiler/rustc_passes/src/intrinsicck.rs
+++ b/compiler/rustc_passes/src/intrinsicck.rs
@@ -14,7 +14,6 @@ use rustc_session::lint;
 use rustc_span::{sym, Span, Symbol, DUMMY_SP};
 use rustc_target::abi::{Pointer, VariantIdx};
 use rustc_target::asm::{InlineAsmRegOrRegClass, InlineAsmType};
-use rustc_target::spec::abi::Abi::RustIntrinsic;
 
 fn check_mod_intrinsics(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
     tcx.hir().deep_visit_item_likes_in_module(module_def_id, &mut ItemVisitor { tcx });
@@ -63,8 +62,7 @@ fn unpack_option_like<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
 
 impl<'tcx> ExprVisitor<'tcx> {
     fn def_id_is_transmute(&self, def_id: DefId) -> bool {
-        self.tcx.fn_sig(def_id).abi() == RustIntrinsic
-            && self.tcx.item_name(def_id) == sym::transmute
+        self.tcx.is_intrinsic(def_id) && self.tcx.item_name(def_id) == sym::transmute
     }
 
     fn check_transmute(&self, span: Span, from: Ty<'tcx>, to: Ty<'tcx>) {
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 143081d61fb..17eac2bb2c9 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -5,7 +5,6 @@ use rustc_middle::traits::CodegenObligationError;
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::{self, Binder, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitor};
 use rustc_span::{sym, DUMMY_SP};
-use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::traits;
 use traits::{translate_substs, Reveal};
 
@@ -155,12 +154,7 @@ fn inner_resolve_instance<'tcx>(
         let item_type = tcx.subst_and_normalize_erasing_regions(substs, param_env, ty);
 
         let def = match *item_type.kind() {
-            ty::FnDef(..)
-                if {
-                    let f = item_type.fn_sig(tcx);
-                    f.abi() == Abi::RustIntrinsic || f.abi() == Abi::PlatformIntrinsic
-                } =>
-            {
+            ty::FnDef(def_id, ..) if tcx.is_intrinsic(def_id) => {
                 debug!(" => intrinsic");
                 ty::InstanceDef::Intrinsic(def.did)
             }
diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs
index c563d57ed96..57d30799354 100644
--- a/compiler/rustc_typeck/src/check/coercion.rs
+++ b/compiler/rustc_typeck/src/check/coercion.rs
@@ -775,17 +775,19 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         match b.kind() {
             ty::FnPtr(b_sig) => {
                 let a_sig = a.fn_sig(self.tcx);
-                // Intrinsics are not coercible to function pointers
-                if a_sig.abi() == Abi::RustIntrinsic || a_sig.abi() == Abi::PlatformIntrinsic {
-                    return Err(TypeError::IntrinsicCast);
-                }
+                if let ty::FnDef(def_id, _) = *a.kind() {
+                    // Intrinsics are not coercible to function pointers
+                    if self.tcx.is_intrinsic(def_id) {
+                        return Err(TypeError::IntrinsicCast);
+                    }
 
-                // Safe `#[target_feature]` functions are not assignable to safe fn pointers (RFC 2396).
-                if let ty::FnDef(def_id, _) = *a.kind()
-                    && b_sig.unsafety() == hir::Unsafety::Normal
-                    && !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty()
-                {
-                    return Err(TypeError::TargetFeatureCast(def_id));
+                    // Safe `#[target_feature]` functions are not assignable to safe fn pointers (RFC 2396).
+
+                    if b_sig.unsafety() == hir::Unsafety::Normal
+                        && !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty()
+                    {
+                        return Err(TypeError::TargetFeatureCast(def_id));
+                    }
                 }
 
                 let InferOk { value: a_sig, obligations: o1 } =
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index 75808b1b174..66d373a1bf8 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -14,7 +14,6 @@ use rustc_middle::ty::{self, adjustment::PointerCast, Ty, TyCtxt};
 use rustc_semver::RustcVersion;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
-use rustc_target::spec::abi::Abi::RustIntrinsic;
 use std::borrow::Cow;
 
 type McfResult = Result<(), (Span, Cow<'static, str>)>;
@@ -323,7 +322,7 @@ fn check_terminator<'a, 'tcx>(
                 // within const fns. `transmute` is allowed in all other const contexts.
                 // This won't really scale to more intrinsics or functions. Let's allow const
                 // transmutes in const fn before we add more hacks to this.
-                if tcx.fn_sig(fn_def_id).abi() == RustIntrinsic && tcx.item_name(fn_def_id) == sym::transmute {
+                if tcx.is_intrinsic(fn_def_id) && tcx.item_name(fn_def_id) == sym::transmute {
                     return Err((
                         span,
                         "can only call `transmute` from const items, not `const fn`".into(),