Skip to content

Commit 0ab2c91

Browse files
committed
attributes: Add #[rustc_safe_intrinsic] builtin
1 parent 57ee5cf commit 0ab2c91

File tree

9 files changed

+24
-51
lines changed

9 files changed

+24
-51
lines changed

compiler/rustc_feature/src/builtin_attrs.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
499499
),
500500
ungated!(rustc_const_unstable, Normal, template!(List: r#"feature = "name""#), DuplicatesOk),
501501
ungated!(rustc_const_stable, Normal, template!(List: r#"feature = "name""#), DuplicatesOk),
502+
ungated!(rustc_safe_intrinsic, Normal, template!(Word), DuplicatesOk),
502503
ungated!(
503504
rustc_default_body_unstable, Normal,
504505
template!(List: r#"feature = "name", reason = "...", issue = "N""#), DuplicatesOk

compiler/rustc_hir_analysis/src/check/intrinsic.rs

Lines changed: 9 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use crate::errors::{
77
};
88
use crate::require_same_types;
99

10+
use hir::def_id::DefId;
1011
use rustc_errors::struct_span_err;
1112
use rustc_hir as hir;
1213
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
@@ -61,59 +62,19 @@ fn equate_intrinsic_type<'tcx>(
6162
}
6263

6364
/// Returns the unsafety of the given intrinsic.
64-
pub fn intrinsic_operation_unsafety(intrinsic: Symbol) -> hir::Unsafety {
65-
match intrinsic {
66-
// When adding a new intrinsic to this list,
67-
// it's usually worth updating that intrinsic's documentation
68-
// to note that it's safe to call, since
69-
// safe extern fns are otherwise unprecedented.
70-
sym::abort
71-
| sym::assert_inhabited
72-
| sym::assert_zero_valid
73-
| sym::assert_uninit_valid
74-
| sym::size_of
75-
| sym::min_align_of
76-
| sym::needs_drop
77-
| sym::caller_location
78-
| sym::add_with_overflow
79-
| sym::sub_with_overflow
80-
| sym::mul_with_overflow
81-
| sym::wrapping_add
82-
| sym::wrapping_sub
83-
| sym::wrapping_mul
84-
| sym::saturating_add
85-
| sym::saturating_sub
86-
| sym::rotate_left
87-
| sym::rotate_right
88-
| sym::ctpop
89-
| sym::ctlz
90-
| sym::cttz
91-
| sym::bswap
92-
| sym::bitreverse
93-
| sym::discriminant_value
94-
| sym::type_id
95-
| sym::likely
96-
| sym::unlikely
97-
| sym::ptr_guaranteed_cmp
98-
| sym::minnumf32
99-
| sym::minnumf64
100-
| sym::maxnumf32
101-
| sym::rustc_peek
102-
| sym::maxnumf64
103-
| sym::type_name
104-
| sym::forget
105-
| sym::black_box
106-
| sym::variant_count
107-
| sym::ptr_mask => hir::Unsafety::Normal,
108-
_ => hir::Unsafety::Unsafe,
65+
pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: DefId) -> hir::Unsafety {
66+
match tcx.has_attr(intrinsic_id, sym::rustc_safe_intrinsic) {
67+
true => hir::Unsafety::Normal,
68+
false => hir::Unsafety::Unsafe,
10969
}
11070
}
11171

11272
/// Remember to add all intrinsics here, in `compiler/rustc_codegen_llvm/src/intrinsic.rs`,
11373
/// and in `library/core/src/intrinsics.rs`.
11474
pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
11575
let param = |n| tcx.mk_ty_param(n, Symbol::intern(&format!("P{}", n)));
116-
let intrinsic_name = tcx.item_name(it.def_id.to_def_id());
76+
let intrinsic_id = it.def_id.to_def_id();
77+
let intrinsic_name = tcx.item_name(intrinsic_id);
11778
let name_str = intrinsic_name.as_str();
11879

11980
let bound_vars = tcx.mk_bound_variable_kinds(
@@ -160,7 +121,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
160121
};
161122
(n_tps, 0, inputs, output, hir::Unsafety::Unsafe)
162123
} else {
163-
let unsafety = intrinsic_operation_unsafety(intrinsic_name);
124+
let unsafety = intrinsic_operation_unsafety(tcx, intrinsic_id);
164125
let (n_tps, inputs, output) = match intrinsic_name {
165126
sym::abort => (0, Vec::new(), tcx.types.never),
166127
sym::unreachable => (0, Vec::new(), tcx.types.never),
@@ -351,7 +312,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
351312
(
352313
1,
353314
vec![
354-
tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)), param(0)),
315+
tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)), param(0))
355316
],
356317
tcx.mk_projection(discriminant_def_id, tcx.mk_substs([param(0).into()].iter())),
357318
)

compiler/rustc_hir_analysis/src/collect.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2544,7 +2544,7 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
25442544
abi: abi::Abi,
25452545
) -> ty::PolyFnSig<'tcx> {
25462546
let unsafety = if abi == abi::Abi::RustIntrinsic {
2547-
intrinsic_operation_unsafety(tcx.item_name(def_id))
2547+
intrinsic_operation_unsafety(tcx, def_id)
25482548
} else {
25492549
hir::Unsafety::Unsafe
25502550
};

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1282,6 +1282,7 @@ symbols! {
12821282
rustc_reallocator,
12831283
rustc_regions,
12841284
rustc_reservation_impl,
1285+
rustc_safe_intrinsic,
12851286
rustc_serialize,
12861287
rustc_skip_array_during_method_dispatch,
12871288
rustc_specialization_trait,

src/librustdoc/clean/types.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -689,7 +689,7 @@ impl Item {
689689
let abi = tcx.fn_sig(self.item_id.as_def_id().unwrap()).abi();
690690
hir::FnHeader {
691691
unsafety: if abi == Abi::RustIntrinsic {
692-
intrinsic_operation_unsafety(self.name.unwrap())
692+
intrinsic_operation_unsafety(tcx, self.item_id.as_def_id().unwrap())
693693
} else {
694694
hir::Unsafety::Unsafe
695695
},

src/test/rustdoc/safe-intrinsic.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
#![feature(intrinsics)]
22
#![feature(no_core)]
3+
#![feature(rustc_attrs)]
34

45
#![no_core]
56
#![crate_name = "foo"]
67

78
extern "rust-intrinsic" {
89
// @has 'foo/fn.abort.html'
910
// @has - '//pre[@class="rust fn"]' 'pub extern "rust-intrinsic" fn abort() -> !'
11+
#[rustc_safe_intrinsic]
1012
pub fn abort() -> !;
1113
// @has 'foo/fn.unreachable.html'
1214
// @has - '//pre[@class="rust fn"]' 'pub unsafe extern "rust-intrinsic" fn unreachable() -> !'

src/test/ui/error-codes/E0308.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#![feature(intrinsics)]
2+
#![feature(rustc_attrs)]
23

34
extern "rust-intrinsic" {
5+
#[rustc_safe_intrinsic]
46
fn size_of<T>(); //~ ERROR E0308
57
}
68

src/test/ui/error-codes/E0308.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0308]: intrinsic has wrong type
2-
--> $DIR/E0308.rs:4:5
2+
--> $DIR/E0308.rs:6:5
33
|
44
LL | fn size_of<T>();
55
| ^^^^^^^^^^^^^^^^ expected `()`, found `usize`

src/test/ui/intrinsics/intrinsics-integer.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
// run-pass
22

33
#![feature(intrinsics)]
4+
#![feature(rustc_attrs)]
45

56
mod rusti {
67
extern "rust-intrinsic" {
8+
#[rustc_safe_intrinsic]
79
pub fn ctpop<T>(x: T) -> T;
10+
#[rustc_safe_intrinsic]
811
pub fn ctlz<T>(x: T) -> T;
912
pub fn ctlz_nonzero<T>(x: T) -> T;
13+
#[rustc_safe_intrinsic]
1014
pub fn cttz<T>(x: T) -> T;
1115
pub fn cttz_nonzero<T>(x: T) -> T;
16+
#[rustc_safe_intrinsic]
1217
pub fn bswap<T>(x: T) -> T;
18+
#[rustc_safe_intrinsic]
1319
pub fn bitreverse<T>(x: T) -> T;
1420
}
1521
}

0 commit comments

Comments
 (0)