Skip to content

Commit ce7f0f1

Browse files
committed
Auto merge of #100719 - CohenArthur:rust-safe-intrinsic-attribute, r=wesleywiser
Add `#[rustc_safe_intrinsic]` This PR adds the `#[rustc_safe_intrinsic]` attribute as mentionned on Zulip. The goal of this attribute is to avoid keeping a list of symbols as the source for stable intrinsics, and instead rely on an attribute. This is similar to `#[rustc_const_stable]` and `#[rustc_const_unstable]`, which among other things, are used to mark the constness of intrinsic functions.
2 parents 307dd93 + b1b8649 commit ce7f0f1

File tree

21 files changed

+113
-10
lines changed

21 files changed

+113
-10
lines changed

compiler/rustc_error_codes/src/error_codes/E0094.md

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Erroneous code example:
66
#![feature(intrinsics)]
77
88
extern "rust-intrinsic" {
9+
#[rustc_safe_intrinsic]
910
fn size_of<T, U>() -> usize; // error: intrinsic has wrong number
1011
// of type parameters
1112
}
@@ -19,6 +20,7 @@ Example:
1920
#![feature(intrinsics)]
2021
2122
extern "rust-intrinsic" {
23+
#[rustc_safe_intrinsic]
2224
fn size_of<T>() -> usize; // ok!
2325
}
2426
```

compiler/rustc_error_codes/src/error_codes/E0211.md

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ used. Erroneous code examples:
77
#![feature(intrinsics)]
88
99
extern "rust-intrinsic" {
10+
#[rustc_safe_intrinsic]
1011
fn size_of<T>(); // error: intrinsic has wrong type
1112
}
1213
@@ -42,6 +43,7 @@ For the first code example, please check the function definition. Example:
4243
#![feature(intrinsics)]
4344
4445
extern "rust-intrinsic" {
46+
#[rustc_safe_intrinsic]
4547
fn size_of<T>() -> usize; // ok!
4648
}
4749
```

compiler/rustc_feature/src/builtin_attrs.rs

+1
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

+22-5
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ use crate::errors::{
77
};
88
use crate::require_same_types;
99

10-
use rustc_errors::struct_span_err;
10+
use hir::def_id::DefId;
11+
use rustc_errors::{struct_span_err, DiagnosticMessage};
1112
use rustc_hir as hir;
1213
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
1314
use rustc_middle::ty::{self, TyCtxt};
@@ -61,8 +62,12 @@ 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 {
65+
pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: DefId) -> hir::Unsafety {
66+
let has_safe_attr = match tcx.has_attr(intrinsic_id, sym::rustc_safe_intrinsic) {
67+
true => hir::Unsafety::Normal,
68+
false => hir::Unsafety::Unsafe,
69+
};
70+
let is_in_list = match tcx.item_name(intrinsic_id) {
6671
// When adding a new intrinsic to this list,
6772
// it's usually worth updating that intrinsic's documentation
6873
// to note that it's safe to call, since
@@ -106,14 +111,26 @@ pub fn intrinsic_operation_unsafety(intrinsic: Symbol) -> hir::Unsafety {
106111
| sym::variant_count
107112
| sym::ptr_mask => hir::Unsafety::Normal,
108113
_ => 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();
109123
}
124+
125+
is_in_list
110126
}
111127

112128
/// Remember to add all intrinsics here, in `compiler/rustc_codegen_llvm/src/intrinsic.rs`,
113129
/// and in `library/core/src/intrinsics.rs`.
114130
pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
115131
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());
132+
let intrinsic_id = it.def_id.to_def_id();
133+
let intrinsic_name = tcx.item_name(intrinsic_id);
117134
let name_str = intrinsic_name.as_str();
118135

119136
let bound_vars = tcx.mk_bound_variable_kinds(
@@ -160,7 +177,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
160177
};
161178
(n_tps, 0, inputs, output, hir::Unsafety::Unsafe)
162179
} else {
163-
let unsafety = intrinsic_operation_unsafety(intrinsic_name);
180+
let unsafety = intrinsic_operation_unsafety(tcx, intrinsic_id);
164181
let (n_tps, inputs, output) = match intrinsic_name {
165182
sym::abort => (0, Vec::new(), tcx.types.never),
166183
sym::unreachable => (0, Vec::new(), tcx.types.never),

compiler/rustc_hir_analysis/src/collect.rs

+1-1
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

+1
Original file line numberDiff line numberDiff line change
@@ -1296,6 +1296,7 @@ symbols! {
12961296
rustc_reallocator,
12971297
rustc_regions,
12981298
rustc_reservation_impl,
1299+
rustc_safe_intrinsic,
12991300
rustc_serialize,
13001301
rustc_skip_array_during_method_dispatch,
13011302
rustc_specialization_trait,

0 commit comments

Comments
 (0)