attributes: Add #[rustc_safe_intrinsic] builtin
This commit is contained in:
parent
57ee5cf5a9
commit
0ab2c91a2d
@ -499,6 +499,7 @@ pub struct BuiltinAttribute {
|
||||
),
|
||||
ungated!(rustc_const_unstable, Normal, template!(List: r#"feature = "name""#), DuplicatesOk),
|
||||
ungated!(rustc_const_stable, Normal, template!(List: r#"feature = "name""#), DuplicatesOk),
|
||||
ungated!(rustc_safe_intrinsic, Normal, template!(Word), DuplicatesOk),
|
||||
ungated!(
|
||||
rustc_default_body_unstable, Normal,
|
||||
template!(List: r#"feature = "name", reason = "...", issue = "N""#), DuplicatesOk
|
||||
|
@ -7,6 +7,7 @@
|
||||
};
|
||||
use crate::require_same_types;
|
||||
|
||||
use hir::def_id::DefId;
|
||||
use rustc_errors::struct_span_err;
|
||||
use rustc_hir as hir;
|
||||
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
|
||||
@ -61,51 +62,10 @@ fn equate_intrinsic_type<'tcx>(
|
||||
}
|
||||
|
||||
/// Returns the unsafety of the given intrinsic.
|
||||
pub fn intrinsic_operation_unsafety(intrinsic: Symbol) -> hir::Unsafety {
|
||||
match intrinsic {
|
||||
// When adding a new intrinsic to this list,
|
||||
// it's usually worth updating that intrinsic's documentation
|
||||
// to note that it's safe to call, since
|
||||
// safe extern fns are otherwise unprecedented.
|
||||
sym::abort
|
||||
| sym::assert_inhabited
|
||||
| sym::assert_zero_valid
|
||||
| sym::assert_uninit_valid
|
||||
| sym::size_of
|
||||
| sym::min_align_of
|
||||
| sym::needs_drop
|
||||
| sym::caller_location
|
||||
| sym::add_with_overflow
|
||||
| sym::sub_with_overflow
|
||||
| sym::mul_with_overflow
|
||||
| sym::wrapping_add
|
||||
| sym::wrapping_sub
|
||||
| sym::wrapping_mul
|
||||
| sym::saturating_add
|
||||
| sym::saturating_sub
|
||||
| sym::rotate_left
|
||||
| sym::rotate_right
|
||||
| sym::ctpop
|
||||
| sym::ctlz
|
||||
| sym::cttz
|
||||
| sym::bswap
|
||||
| sym::bitreverse
|
||||
| sym::discriminant_value
|
||||
| sym::type_id
|
||||
| sym::likely
|
||||
| sym::unlikely
|
||||
| sym::ptr_guaranteed_cmp
|
||||
| sym::minnumf32
|
||||
| sym::minnumf64
|
||||
| sym::maxnumf32
|
||||
| sym::rustc_peek
|
||||
| sym::maxnumf64
|
||||
| sym::type_name
|
||||
| sym::forget
|
||||
| sym::black_box
|
||||
| sym::variant_count
|
||||
| sym::ptr_mask => hir::Unsafety::Normal,
|
||||
_ => hir::Unsafety::Unsafe,
|
||||
pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: DefId) -> hir::Unsafety {
|
||||
match tcx.has_attr(intrinsic_id, sym::rustc_safe_intrinsic) {
|
||||
true => hir::Unsafety::Normal,
|
||||
false => hir::Unsafety::Unsafe,
|
||||
}
|
||||
}
|
||||
|
||||
@ -113,7 +73,8 @@ pub fn intrinsic_operation_unsafety(intrinsic: Symbol) -> hir::Unsafety {
|
||||
/// and in `library/core/src/intrinsics.rs`.
|
||||
pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
|
||||
let param = |n| tcx.mk_ty_param(n, Symbol::intern(&format!("P{}", n)));
|
||||
let intrinsic_name = tcx.item_name(it.def_id.to_def_id());
|
||||
let intrinsic_id = it.def_id.to_def_id();
|
||||
let intrinsic_name = tcx.item_name(intrinsic_id);
|
||||
let name_str = intrinsic_name.as_str();
|
||||
|
||||
let bound_vars = tcx.mk_bound_variable_kinds(
|
||||
@ -160,7 +121,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
|
||||
};
|
||||
(n_tps, 0, inputs, output, hir::Unsafety::Unsafe)
|
||||
} else {
|
||||
let unsafety = intrinsic_operation_unsafety(intrinsic_name);
|
||||
let unsafety = intrinsic_operation_unsafety(tcx, intrinsic_id);
|
||||
let (n_tps, inputs, output) = match intrinsic_name {
|
||||
sym::abort => (0, Vec::new(), tcx.types.never),
|
||||
sym::unreachable => (0, Vec::new(), tcx.types.never),
|
||||
@ -351,7 +312,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
|
||||
(
|
||||
1,
|
||||
vec![
|
||||
tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)), param(0)),
|
||||
tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)), param(0))
|
||||
],
|
||||
tcx.mk_projection(discriminant_def_id, tcx.mk_substs([param(0).into()].iter())),
|
||||
)
|
||||
|
@ -2544,7 +2544,7 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
|
||||
abi: abi::Abi,
|
||||
) -> ty::PolyFnSig<'tcx> {
|
||||
let unsafety = if abi == abi::Abi::RustIntrinsic {
|
||||
intrinsic_operation_unsafety(tcx.item_name(def_id))
|
||||
intrinsic_operation_unsafety(tcx, def_id)
|
||||
} else {
|
||||
hir::Unsafety::Unsafe
|
||||
};
|
||||
|
@ -1282,6 +1282,7 @@
|
||||
rustc_reallocator,
|
||||
rustc_regions,
|
||||
rustc_reservation_impl,
|
||||
rustc_safe_intrinsic,
|
||||
rustc_serialize,
|
||||
rustc_skip_array_during_method_dispatch,
|
||||
rustc_specialization_trait,
|
||||
|
@ -689,7 +689,7 @@ fn build_fn_header(
|
||||
let abi = tcx.fn_sig(self.item_id.as_def_id().unwrap()).abi();
|
||||
hir::FnHeader {
|
||||
unsafety: if abi == Abi::RustIntrinsic {
|
||||
intrinsic_operation_unsafety(self.name.unwrap())
|
||||
intrinsic_operation_unsafety(tcx, self.item_id.as_def_id().unwrap())
|
||||
} else {
|
||||
hir::Unsafety::Unsafe
|
||||
},
|
||||
|
@ -1,5 +1,6 @@
|
||||
#![feature(intrinsics)]
|
||||
#![feature(no_core)]
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
#![no_core]
|
||||
#![crate_name = "foo"]
|
||||
@ -7,6 +8,7 @@
|
||||
extern "rust-intrinsic" {
|
||||
// @has 'foo/fn.abort.html'
|
||||
// @has - '//pre[@class="rust fn"]' 'pub extern "rust-intrinsic" fn abort() -> !'
|
||||
#[rustc_safe_intrinsic]
|
||||
pub fn abort() -> !;
|
||||
// @has 'foo/fn.unreachable.html'
|
||||
// @has - '//pre[@class="rust fn"]' 'pub unsafe extern "rust-intrinsic" fn unreachable() -> !'
|
||||
|
@ -1,6 +1,8 @@
|
||||
#![feature(intrinsics)]
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
#[rustc_safe_intrinsic]
|
||||
fn size_of<T>(); //~ ERROR E0308
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0308]: intrinsic has wrong type
|
||||
--> $DIR/E0308.rs:4:5
|
||||
--> $DIR/E0308.rs:6:5
|
||||
|
|
||||
LL | fn size_of<T>();
|
||||
| ^^^^^^^^^^^^^^^^ expected `()`, found `usize`
|
||||
|
@ -1,15 +1,21 @@
|
||||
// run-pass
|
||||
|
||||
#![feature(intrinsics)]
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
mod rusti {
|
||||
extern "rust-intrinsic" {
|
||||
#[rustc_safe_intrinsic]
|
||||
pub fn ctpop<T>(x: T) -> T;
|
||||
#[rustc_safe_intrinsic]
|
||||
pub fn ctlz<T>(x: T) -> T;
|
||||
pub fn ctlz_nonzero<T>(x: T) -> T;
|
||||
#[rustc_safe_intrinsic]
|
||||
pub fn cttz<T>(x: T) -> T;
|
||||
pub fn cttz_nonzero<T>(x: T) -> T;
|
||||
#[rustc_safe_intrinsic]
|
||||
pub fn bswap<T>(x: T) -> T;
|
||||
#[rustc_safe_intrinsic]
|
||||
pub fn bitreverse<T>(x: T) -> T;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user