Skip to content

Commit

Permalink
Auto merge of #100719 - CohenArthur:rust-safe-intrinsic-attribute, r=…
Browse files Browse the repository at this point in the history
…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.
  • Loading branch information
bors committed Sep 28, 2022
2 parents 307dd93 + b1b8649 commit ce7f0f1
Show file tree
Hide file tree
Showing 21 changed files with 113 additions and 10 deletions.
2 changes: 2 additions & 0 deletions compiler/rustc_error_codes/src/error_codes/E0094.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Erroneous code example:
#![feature(intrinsics)]
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
fn size_of<T, U>() -> usize; // error: intrinsic has wrong number
// of type parameters
}
Expand All @@ -19,6 +20,7 @@ Example:
#![feature(intrinsics)]
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
fn size_of<T>() -> usize; // ok!
}
```
2 changes: 2 additions & 0 deletions compiler/rustc_error_codes/src/error_codes/E0211.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ used. Erroneous code examples:
#![feature(intrinsics)]
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
fn size_of<T>(); // error: intrinsic has wrong type
}
Expand Down Expand Up @@ -42,6 +43,7 @@ For the first code example, please check the function definition. Example:
#![feature(intrinsics)]
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
fn size_of<T>() -> usize; // ok!
}
```
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_feature/src/builtin_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,7 @@ pub const BUILTIN_ATTRIBUTES: &[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
Expand Down
27 changes: 22 additions & 5 deletions compiler/rustc_hir_analysis/src/check/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ use crate::errors::{
};
use crate::require_same_types;

use rustc_errors::struct_span_err;
use hir::def_id::DefId;
use rustc_errors::{struct_span_err, DiagnosticMessage};
use rustc_hir as hir;
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
use rustc_middle::ty::{self, TyCtxt};
Expand Down Expand Up @@ -61,8 +62,12 @@ fn equate_intrinsic_type<'tcx>(
}

/// Returns the unsafety of the given intrinsic.
pub fn intrinsic_operation_unsafety(intrinsic: Symbol) -> hir::Unsafety {
match intrinsic {
pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: DefId) -> hir::Unsafety {
let has_safe_attr = match tcx.has_attr(intrinsic_id, sym::rustc_safe_intrinsic) {
true => hir::Unsafety::Normal,
false => hir::Unsafety::Unsafe,
};
let is_in_list = match tcx.item_name(intrinsic_id) {
// 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
Expand Down Expand Up @@ -106,14 +111,26 @@ pub fn intrinsic_operation_unsafety(intrinsic: Symbol) -> hir::Unsafety {
| sym::variant_count
| sym::ptr_mask => hir::Unsafety::Normal,
_ => hir::Unsafety::Unsafe,
};

if has_safe_attr != is_in_list {
tcx.sess.struct_span_err(
tcx.def_span(intrinsic_id),
DiagnosticMessage::Str(format!(
"intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `{}`",
tcx.item_name(intrinsic_id)
))).emit();
}

is_in_list
}

/// Remember to add all intrinsics here, in `compiler/rustc_codegen_llvm/src/intrinsic.rs`,
/// 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(
Expand Down Expand Up @@ -160,7 +177,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),
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
};
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1296,6 +1296,7 @@ symbols! {
rustc_reallocator,
rustc_regions,
rustc_reservation_impl,
rustc_safe_intrinsic,
rustc_serialize,
rustc_skip_array_during_method_dispatch,
rustc_specialization_trait,
Expand Down
Loading

0 comments on commit ce7f0f1

Please sign in to comment.