Skip to content

Commit

Permalink
core: Mark all safe intrinsics with #[rustc_safe_intrinsic]
Browse files Browse the repository at this point in the history
  • Loading branch information
CohenArthur committed Sep 27, 2022
1 parent 0ab2c91 commit 99d57ee
Show file tree
Hide file tree
Showing 10 changed files with 51 additions and 2 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
38 changes: 38 additions & 0 deletions library/core/src/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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,
Expand Down Expand Up @@ -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.
Expand All @@ -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.
Expand All @@ -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.
Expand All @@ -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.
///
Expand Down Expand Up @@ -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
Expand All @@ -928,27 +935,31 @@ 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:
/// This will statically either panic, or do nothing.
///
/// 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
/// zero-initialization: This will statically either panic, or do nothing.
///
/// 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
/// bit patterns: This will statically either panic, or do nothing.
///
/// 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.
Expand All @@ -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.
Expand All @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
///
Expand All @@ -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.
///
Expand All @@ -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.
///
Expand All @@ -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.
Expand Down Expand Up @@ -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`.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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`.
Expand All @@ -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.
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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.
Expand All @@ -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.
Expand All @@ -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.
///
Expand All @@ -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.
///
Expand All @@ -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.
Expand All @@ -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.
///
Expand All @@ -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';
Expand All @@ -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`;
Expand All @@ -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`
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down
2 changes: 2 additions & 0 deletions src/test/ui/error-codes/E0094.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#![feature(intrinsics)]

extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
fn size_of<T, U>() -> usize; //~ ERROR E0094
}

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/error-codes/E0094.stderr
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 2 additions & 0 deletions src/test/ui/extern/extern-with-type-bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/extern/extern-with-type-bounds.stderr
Original file line number Diff line number Diff line change
@@ -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
Expand Down
1 change: 1 addition & 0 deletions src/test/ui/intrinsics/intrinsic-alignment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand Down
1 change: 1 addition & 0 deletions src/test/ui/structs-enums/rec-align-u32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand Down
1 change: 1 addition & 0 deletions src/test/ui/structs-enums/rec-align-u64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand Down

0 comments on commit 99d57ee

Please sign in to comment.