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.
This commit is contained in:
commit
ce7f0f1aa0
21 changed files with 113 additions and 10 deletions
|
@ -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
|
||||
}
|
||||
|
@ -19,6 +20,7 @@ Example:
|
|||
#![feature(intrinsics)]
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
#[rustc_safe_intrinsic]
|
||||
fn size_of<T>() -> usize; // ok!
|
||||
}
|
||||
```
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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!
|
||||
}
|
||||
```
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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};
|
||||
|
@ -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
|
||||
|
@ -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(
|
||||
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -788,6 +788,7 @@ extern "rust-intrinsic" {
|
|||
/// uninitialized at that point in the control flow.
|
||||
///
|
||||
/// This intrinsic should not be used outside of the compiler.
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn rustc_peek<T>(_: T) -> T;
|
||||
|
||||
/// Aborts the execution of the process.
|
||||
|
@ -805,6 +806,7 @@ extern "rust-intrinsic" {
|
|||
/// On Unix, the
|
||||
/// process will probably terminate with a signal like `SIGABRT`, `SIGILL`, `SIGTRAP`, `SIGSEGV` or
|
||||
/// `SIGBUS`. The precise behaviour is not guaranteed and not stable.
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn abort() -> !;
|
||||
|
||||
/// Informs the optimizer that this point in the code is not reachable,
|
||||
|
@ -843,6 +845,7 @@ extern "rust-intrinsic" {
|
|||
///
|
||||
/// This intrinsic does not have a stable counterpart.
|
||||
#[rustc_const_unstable(feature = "const_likely", issue = "none")]
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn likely(b: bool) -> bool;
|
||||
|
||||
/// Hints to the compiler that branch condition is likely to be false.
|
||||
|
@ -857,6 +860,7 @@ extern "rust-intrinsic" {
|
|||
///
|
||||
/// This intrinsic does not have a stable counterpart.
|
||||
#[rustc_const_unstable(feature = "const_likely", issue = "none")]
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn unlikely(b: bool) -> bool;
|
||||
|
||||
/// Executes a breakpoint trap, for inspection by a debugger.
|
||||
|
@ -876,6 +880,7 @@ extern "rust-intrinsic" {
|
|||
///
|
||||
/// The stabilized version of this intrinsic is [`core::mem::size_of`].
|
||||
#[rustc_const_stable(feature = "const_size_of", since = "1.40.0")]
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn size_of<T>() -> usize;
|
||||
|
||||
/// The minimum alignment of a type.
|
||||
|
@ -887,6 +892,7 @@ extern "rust-intrinsic" {
|
|||
///
|
||||
/// The stabilized version of this intrinsic is [`core::mem::align_of`].
|
||||
#[rustc_const_stable(feature = "const_min_align_of", since = "1.40.0")]
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn min_align_of<T>() -> usize;
|
||||
/// The preferred alignment of a type.
|
||||
///
|
||||
|
@ -915,6 +921,7 @@ extern "rust-intrinsic" {
|
|||
///
|
||||
/// The stabilized version of this intrinsic is [`core::any::type_name`].
|
||||
#[rustc_const_unstable(feature = "const_type_name", issue = "63084")]
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn type_name<T: ?Sized>() -> &'static str;
|
||||
|
||||
/// Gets an identifier which is globally unique to the specified type. This
|
||||
|
@ -928,6 +935,7 @@ extern "rust-intrinsic" {
|
|||
///
|
||||
/// The stabilized version of this intrinsic is [`core::any::TypeId::of`].
|
||||
#[rustc_const_unstable(feature = "const_type_id", issue = "77125")]
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn type_id<T: ?Sized + 'static>() -> u64;
|
||||
|
||||
/// A guard for unsafe functions that cannot ever be executed if `T` is uninhabited:
|
||||
|
@ -935,6 +943,7 @@ extern "rust-intrinsic" {
|
|||
///
|
||||
/// This intrinsic does not have a stable counterpart.
|
||||
#[rustc_const_stable(feature = "const_assert_type", since = "1.59.0")]
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn assert_inhabited<T>();
|
||||
|
||||
/// A guard for unsafe functions that cannot ever be executed if `T` does not permit
|
||||
|
@ -942,6 +951,7 @@ extern "rust-intrinsic" {
|
|||
///
|
||||
/// This intrinsic does not have a stable counterpart.
|
||||
#[rustc_const_unstable(feature = "const_assert_type2", issue = "none")]
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn assert_zero_valid<T>();
|
||||
|
||||
/// A guard for unsafe functions that cannot ever be executed if `T` has invalid
|
||||
|
@ -949,6 +959,7 @@ extern "rust-intrinsic" {
|
|||
///
|
||||
/// This intrinsic does not have a stable counterpart.
|
||||
#[rustc_const_unstable(feature = "const_assert_type2", issue = "none")]
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn assert_uninit_valid<T>();
|
||||
|
||||
/// Gets a reference to a static `Location` indicating where it was called.
|
||||
|
@ -960,6 +971,7 @@ extern "rust-intrinsic" {
|
|||
///
|
||||
/// Consider using [`core::panic::Location::caller`] instead.
|
||||
#[rustc_const_unstable(feature = "const_caller_location", issue = "76156")]
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn caller_location() -> &'static crate::panic::Location<'static>;
|
||||
|
||||
/// Moves a value out of scope without running drop glue.
|
||||
|
@ -972,6 +984,7 @@ extern "rust-intrinsic" {
|
|||
/// Therefore, implementations must not require the user to uphold
|
||||
/// any safety invariants.
|
||||
#[rustc_const_unstable(feature = "const_intrinsic_forget", issue = "none")]
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn forget<T: ?Sized>(_: T);
|
||||
|
||||
/// Reinterprets the bits of a value of one type as another type.
|
||||
|
@ -1251,6 +1264,7 @@ extern "rust-intrinsic" {
|
|||
///
|
||||
/// The stabilized version of this intrinsic is [`mem::needs_drop`](crate::mem::needs_drop).
|
||||
#[rustc_const_stable(feature = "const_needs_drop", since = "1.40.0")]
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn needs_drop<T: ?Sized>() -> bool;
|
||||
|
||||
/// Calculates the offset from a pointer.
|
||||
|
@ -1295,6 +1309,7 @@ extern "rust-intrinsic" {
|
|||
/// any safety invariants.
|
||||
///
|
||||
/// Consider using [`pointer::mask`] instead.
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn ptr_mask<T>(ptr: *const T, mask: usize) -> *const T;
|
||||
|
||||
/// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with
|
||||
|
@ -1486,6 +1501,7 @@ extern "rust-intrinsic" {
|
|||
///
|
||||
/// The stabilized version of this intrinsic is
|
||||
/// [`f32::min`]
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn minnumf32(x: f32, y: f32) -> f32;
|
||||
/// Returns the minimum of two `f64` values.
|
||||
///
|
||||
|
@ -1496,6 +1512,7 @@ extern "rust-intrinsic" {
|
|||
///
|
||||
/// The stabilized version of this intrinsic is
|
||||
/// [`f64::min`]
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn minnumf64(x: f64, y: f64) -> f64;
|
||||
/// Returns the maximum of two `f32` values.
|
||||
///
|
||||
|
@ -1506,6 +1523,7 @@ extern "rust-intrinsic" {
|
|||
///
|
||||
/// The stabilized version of this intrinsic is
|
||||
/// [`f32::max`]
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn maxnumf32(x: f32, y: f32) -> f32;
|
||||
/// Returns the maximum of two `f64` values.
|
||||
///
|
||||
|
@ -1516,6 +1534,7 @@ extern "rust-intrinsic" {
|
|||
///
|
||||
/// The stabilized version of this intrinsic is
|
||||
/// [`f64::max`]
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn maxnumf64(x: f64, y: f64) -> f64;
|
||||
|
||||
/// Copies the sign from `y` to `x` for `f32` values.
|
||||
|
@ -1636,6 +1655,7 @@ extern "rust-intrinsic" {
|
|||
/// primitives via the `count_ones` method. For example,
|
||||
/// [`u32::count_ones`]
|
||||
#[rustc_const_stable(feature = "const_ctpop", since = "1.40.0")]
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn ctpop<T: Copy>(x: T) -> T;
|
||||
|
||||
/// Returns the number of leading unset bits (zeroes) in an integer type `T`.
|
||||
|
@ -1673,6 +1693,7 @@ extern "rust-intrinsic" {
|
|||
/// assert_eq!(num_leading, 16);
|
||||
/// ```
|
||||
#[rustc_const_stable(feature = "const_ctlz", since = "1.40.0")]
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn ctlz<T: Copy>(x: T) -> T;
|
||||
|
||||
/// Like `ctlz`, but extra-unsafe as it returns `undef` when
|
||||
|
@ -1729,6 +1750,7 @@ extern "rust-intrinsic" {
|
|||
/// assert_eq!(num_trailing, 16);
|
||||
/// ```
|
||||
#[rustc_const_stable(feature = "const_cttz", since = "1.40.0")]
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn cttz<T: Copy>(x: T) -> T;
|
||||
|
||||
/// Like `cttz`, but extra-unsafe as it returns `undef` when
|
||||
|
@ -1761,6 +1783,7 @@ extern "rust-intrinsic" {
|
|||
/// primitives via the `swap_bytes` method. For example,
|
||||
/// [`u32::swap_bytes`]
|
||||
#[rustc_const_stable(feature = "const_bswap", since = "1.40.0")]
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn bswap<T: Copy>(x: T) -> T;
|
||||
|
||||
/// Reverses the bits in an integer type `T`.
|
||||
|
@ -1774,6 +1797,7 @@ extern "rust-intrinsic" {
|
|||
/// primitives via the `reverse_bits` method. For example,
|
||||
/// [`u32::reverse_bits`]
|
||||
#[rustc_const_stable(feature = "const_bitreverse", since = "1.40.0")]
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn bitreverse<T: Copy>(x: T) -> T;
|
||||
|
||||
/// Performs checked integer addition.
|
||||
|
@ -1787,6 +1811,7 @@ extern "rust-intrinsic" {
|
|||
/// primitives via the `overflowing_add` method. For example,
|
||||
/// [`u32::overflowing_add`]
|
||||
#[rustc_const_stable(feature = "const_int_overflow", since = "1.40.0")]
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn add_with_overflow<T: Copy>(x: T, y: T) -> (T, bool);
|
||||
|
||||
/// Performs checked integer subtraction
|
||||
|
@ -1800,6 +1825,7 @@ extern "rust-intrinsic" {
|
|||
/// primitives via the `overflowing_sub` method. For example,
|
||||
/// [`u32::overflowing_sub`]
|
||||
#[rustc_const_stable(feature = "const_int_overflow", since = "1.40.0")]
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn sub_with_overflow<T: Copy>(x: T, y: T) -> (T, bool);
|
||||
|
||||
/// Performs checked integer multiplication
|
||||
|
@ -1813,6 +1839,7 @@ extern "rust-intrinsic" {
|
|||
/// primitives via the `overflowing_mul` method. For example,
|
||||
/// [`u32::overflowing_mul`]
|
||||
#[rustc_const_stable(feature = "const_int_overflow", since = "1.40.0")]
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn mul_with_overflow<T: Copy>(x: T, y: T) -> (T, bool);
|
||||
|
||||
/// Performs an exact division, resulting in undefined behavior where
|
||||
|
@ -1887,6 +1914,7 @@ extern "rust-intrinsic" {
|
|||
/// primitives via the `rotate_left` method. For example,
|
||||
/// [`u32::rotate_left`]
|
||||
#[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")]
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn rotate_left<T: Copy>(x: T, y: T) -> T;
|
||||
|
||||
/// Performs rotate right.
|
||||
|
@ -1900,6 +1928,7 @@ extern "rust-intrinsic" {
|
|||
/// primitives via the `rotate_right` method. For example,
|
||||
/// [`u32::rotate_right`]
|
||||
#[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")]
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn rotate_right<T: Copy>(x: T, y: T) -> T;
|
||||
|
||||
/// Returns (a + b) mod 2<sup>N</sup>, where N is the width of T in bits.
|
||||
|
@ -1913,6 +1942,7 @@ extern "rust-intrinsic" {
|
|||
/// primitives via the `wrapping_add` method. For example,
|
||||
/// [`u32::wrapping_add`]
|
||||
#[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")]
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn wrapping_add<T: Copy>(a: T, b: T) -> T;
|
||||
/// Returns (a - b) mod 2<sup>N</sup>, where N is the width of T in bits.
|
||||
///
|
||||
|
@ -1925,6 +1955,7 @@ extern "rust-intrinsic" {
|
|||
/// primitives via the `wrapping_sub` method. For example,
|
||||
/// [`u32::wrapping_sub`]
|
||||
#[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")]
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn wrapping_sub<T: Copy>(a: T, b: T) -> T;
|
||||
/// Returns (a * b) mod 2<sup>N</sup>, where N is the width of T in bits.
|
||||
///
|
||||
|
@ -1937,6 +1968,7 @@ extern "rust-intrinsic" {
|
|||
/// primitives via the `wrapping_mul` method. For example,
|
||||
/// [`u32::wrapping_mul`]
|
||||
#[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")]
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn wrapping_mul<T: Copy>(a: T, b: T) -> T;
|
||||
|
||||
/// Computes `a + b`, saturating at numeric bounds.
|
||||
|
@ -1950,6 +1982,7 @@ extern "rust-intrinsic" {
|
|||
/// primitives via the `saturating_add` method. For example,
|
||||
/// [`u32::saturating_add`]
|
||||
#[rustc_const_stable(feature = "const_int_saturating", since = "1.40.0")]
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn saturating_add<T: Copy>(a: T, b: T) -> T;
|
||||
/// Computes `a - b`, saturating at numeric bounds.
|
||||
///
|
||||
|
@ -1962,6 +1995,7 @@ extern "rust-intrinsic" {
|
|||
/// primitives via the `saturating_sub` method. For example,
|
||||
/// [`u32::saturating_sub`]
|
||||
#[rustc_const_stable(feature = "const_int_saturating", since = "1.40.0")]
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn saturating_sub<T: Copy>(a: T, b: T) -> T;
|
||||
|
||||
/// Returns the value of the discriminant for the variant in 'v';
|
||||
|
@ -1974,6 +2008,7 @@ extern "rust-intrinsic" {
|
|||
///
|
||||
/// The stabilized version of this intrinsic is [`core::mem::discriminant`].
|
||||
#[rustc_const_unstable(feature = "const_discriminant", issue = "69821")]
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn discriminant_value<T>(v: &T) -> <T as DiscriminantKind>::Discriminant;
|
||||
|
||||
/// Returns the number of variants of the type `T` cast to a `usize`;
|
||||
|
@ -1986,6 +2021,7 @@ extern "rust-intrinsic" {
|
|||
///
|
||||
/// The to-be-stabilized version of this intrinsic is [`mem::variant_count`].
|
||||
#[rustc_const_unstable(feature = "variant_count", issue = "73662")]
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn variant_count<T>() -> usize;
|
||||
|
||||
/// Rust's "try catch" construct which invokes the function pointer `try_fn`
|
||||
|
@ -2019,6 +2055,7 @@ extern "rust-intrinsic" {
|
|||
/// Therefore, implementations must not require the user to uphold
|
||||
/// any safety invariants.
|
||||
#[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn ptr_guaranteed_cmp<T>(ptr: *const T, other: *const T) -> u8;
|
||||
|
||||
/// Allocates a block of memory at compile time.
|
||||
|
@ -2069,6 +2106,7 @@ extern "rust-intrinsic" {
|
|||
///
|
||||
/// [`std::hint::black_box`]: crate::hint::black_box
|
||||
#[rustc_const_unstable(feature = "const_black_box", issue = "none")]
|
||||
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
|
||||
pub fn black_box<T>(dummy: T) -> T;
|
||||
|
||||
/// `ptr` must point to a vtable.
|
||||
|
|
|
@ -689,7 +689,7 @@ impl Item {
|
|||
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,5 +1,7 @@
|
|||
#![feature(intrinsics)]
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
#[rustc_safe_intrinsic]
|
||||
fn size_of<T, U>() -> usize; //~ ERROR E0094
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0094]: intrinsic has wrong number of type parameters: found 2, expected 1
|
||||
--> $DIR/E0094.rs:3:15
|
||||
--> $DIR/E0094.rs:5:15
|
||||
|
|
||||
LL | fn size_of<T, U>() -> usize;
|
||||
| ^^^^^^ expected 1 type parameter
|
||||
|
|
|
@ -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`
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
extern "rust-intrinsic" {
|
||||
// Real example from libcore
|
||||
#[rustc_safe_intrinsic]
|
||||
fn type_id<T: ?Sized + 'static>() -> u64;
|
||||
|
||||
// Silent bounds made explicit to make sure they are actually
|
||||
|
@ -10,6 +11,7 @@ extern "rust-intrinsic" {
|
|||
|
||||
// Bounds aren't checked right now, so this should work
|
||||
// even though it's incorrect.
|
||||
#[rustc_safe_intrinsic]
|
||||
fn size_of<T: Clone>() -> usize;
|
||||
|
||||
// Unresolved bounds should still error.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0405]: cannot find trait `NoSuchTrait` in this scope
|
||||
--> $DIR/extern-with-type-bounds.rs:16:20
|
||||
--> $DIR/extern-with-type-bounds.rs:18:20
|
||||
|
|
||||
LL | fn align_of<T: NoSuchTrait>() -> usize;
|
||||
| ^^^^^^^^^^^ not found in this scope
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
mod rusti {
|
||||
extern "rust-intrinsic" {
|
||||
pub fn pref_align_of<T>() -> usize;
|
||||
#[rustc_safe_intrinsic]
|
||||
pub fn min_align_of<T>() -> 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;
|
||||
}
|
||||
}
|
||||
|
|
11
src/test/ui/intrinsics/safe-intrinsic-mismatch.rs
Normal file
11
src/test/ui/intrinsics/safe-intrinsic-mismatch.rs
Normal file
|
@ -0,0 +1,11 @@
|
|||
#![feature(intrinsics)]
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
fn size_of<T>() -> usize; //~ ERROR intrinsic safety mismatch
|
||||
|
||||
#[rustc_safe_intrinsic]
|
||||
fn assume(b: bool); //~ ERROR intrinsic safety mismatch
|
||||
}
|
||||
|
||||
fn main() {}
|
14
src/test/ui/intrinsics/safe-intrinsic-mismatch.stderr
Normal file
14
src/test/ui/intrinsics/safe-intrinsic-mismatch.stderr
Normal file
|
@ -0,0 +1,14 @@
|
|||
error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `size_of`
|
||||
--> $DIR/safe-intrinsic-mismatch.rs:5:5
|
||||
|
|
||||
LL | fn size_of<T>() -> usize;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `assume`
|
||||
--> $DIR/safe-intrinsic-mismatch.rs:8:5
|
||||
|
|
||||
LL | fn assume(b: bool);
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
|
@ -10,6 +10,7 @@ use std::mem;
|
|||
mod rusti {
|
||||
extern "rust-intrinsic" {
|
||||
pub fn pref_align_of<T>() -> usize;
|
||||
#[rustc_safe_intrinsic]
|
||||
pub fn min_align_of<T>() -> usize;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ use std::mem;
|
|||
mod rusti {
|
||||
extern "rust-intrinsic" {
|
||||
pub fn pref_align_of<T>() -> usize;
|
||||
#[rustc_safe_intrinsic]
|
||||
pub fn min_align_of<T>() -> usize;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue