mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
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`
This commit is contained in:
commit
735efc0c70
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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) }
|
||||
|
@ -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, ());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)>,
|
||||
|
@ -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>)
|
||||
|
@ -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)))
|
||||
}
|
||||
|
||||
pub fn provide(providers: &mut ty::query::Providers) {
|
||||
*providers = ty::query::Providers { normalize_opaque_types, is_doc_hidden, ..*providers }
|
||||
/// 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, is_intrinsic, ..*providers }
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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>) {
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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 } =
|
||||
|
@ -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(),
|
||||
|
Loading…
Reference in New Issue
Block a user