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 1f291db55be96..777f4393458e2 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 { @@ -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 c2664565f15cb..25f9d4baca304 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 8d3bbefb37186..1104bbf471682 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 a87083a082b3f..585edfc47e1b8 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 b25522cfd96a8..de1e96ebfe722 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 9f7ef3981c75b..065224a2a65d7 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 ebf6a5521702b..39e6ddb316d71 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 356dad4b56be1..1c5774db579a5 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, impl_polarity: Table, impl_constness: Table, + is_intrinsic: Table, impl_defaultness: Table, // FIXME(eddyb) perhaps compute this on the fly if cheap enough? coerce_unsized_info: Table, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 6d7ec247d0452..f133494caaa9a 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 10520670069b4..3fa5a140090a8 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 cc9ee1016c6db..2f884887ad9fe 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 012ce73075575..5f8e6608ab5c4 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 684d988ee9ed2..d0d0e09d5255a 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 95f6f7ef864a2..9c840777bafc1 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 143081d61fb37..17eac2bb2c9e9 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 c563d57ed96bb..57d3079935415 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 75808b1b17461..66d373a1bf81a 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(),