Skip to content

Commit 37bf8f8

Browse files
committed
rustc_safe_intrinsic: Keep list of safe intrinsics within the compiler
1 parent 99d57ee commit 37bf8f8

File tree

1 file changed

+59
-3
lines changed

1 file changed

+59
-3
lines changed

compiler/rustc_hir_analysis/src/check/intrinsic.rs

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::errors::{
88
use crate::require_same_types;
99

1010
use hir::def_id::DefId;
11-
use rustc_errors::struct_span_err;
11+
use rustc_errors::{struct_span_err, DiagnosticMessage};
1212
use rustc_hir as hir;
1313
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
1414
use rustc_middle::ty::{self, TyCtxt};
@@ -63,10 +63,66 @@ fn equate_intrinsic_type<'tcx>(
6363

6464
/// Returns the unsafety of the given intrinsic.
6565
pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: DefId) -> hir::Unsafety {
66-
match tcx.has_attr(intrinsic_id, sym::rustc_safe_intrinsic) {
66+
let has_safe_attr = match tcx.has_attr(intrinsic_id, sym::rustc_safe_intrinsic) {
6767
true => hir::Unsafety::Normal,
6868
false => hir::Unsafety::Unsafe,
69+
};
70+
let is_in_list = match tcx.item_name(intrinsic_id) {
71+
// When adding a new intrinsic to this list,
72+
// it's usually worth updating that intrinsic's documentation
73+
// to note that it's safe to call, since
74+
// safe extern fns are otherwise unprecedented.
75+
sym::abort
76+
| sym::assert_inhabited
77+
| sym::assert_zero_valid
78+
| sym::assert_uninit_valid
79+
| sym::size_of
80+
| sym::min_align_of
81+
| sym::needs_drop
82+
| sym::caller_location
83+
| sym::add_with_overflow
84+
| sym::sub_with_overflow
85+
| sym::mul_with_overflow
86+
| sym::wrapping_add
87+
| sym::wrapping_sub
88+
| sym::wrapping_mul
89+
| sym::saturating_add
90+
| sym::saturating_sub
91+
| sym::rotate_left
92+
| sym::rotate_right
93+
| sym::ctpop
94+
| sym::ctlz
95+
| sym::cttz
96+
| sym::bswap
97+
| sym::bitreverse
98+
| sym::discriminant_value
99+
| sym::type_id
100+
| sym::likely
101+
| sym::unlikely
102+
| sym::ptr_guaranteed_cmp
103+
| sym::minnumf32
104+
| sym::minnumf64
105+
| sym::maxnumf32
106+
| sym::rustc_peek
107+
| sym::maxnumf64
108+
| sym::type_name
109+
| sym::forget
110+
| sym::black_box
111+
| sym::variant_count
112+
| sym::ptr_mask => hir::Unsafety::Normal,
113+
_ => hir::Unsafety::Unsafe,
114+
};
115+
116+
if has_safe_attr != is_in_list {
117+
tcx.sess.struct_span_err(
118+
tcx.def_span(intrinsic_id),
119+
DiagnosticMessage::Str(format!(
120+
"intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `{}`",
121+
tcx.item_name(intrinsic_id)
122+
))).emit();
69123
}
124+
125+
is_in_list
70126
}
71127

72128
/// Remember to add all intrinsics here, in `compiler/rustc_codegen_llvm/src/intrinsic.rs`,
@@ -312,7 +368,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
312368
(
313369
1,
314370
vec![
315-
tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)), param(0))
371+
tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)), param(0)),
316372
],
317373
tcx.mk_projection(discriminant_def_id, tcx.mk_substs([param(0).into()].iter())),
318374
)

0 commit comments

Comments
 (0)