remove support for rustc_safe_intrinsic attribute; use rustc_intrinsic functions instead

This commit is contained in:
Ralf Jung 2024-11-07 08:59:43 +01:00
parent 78bb5ee79e
commit e3010e84db
42 changed files with 380 additions and 348 deletions

View File

@ -616,25 +616,70 @@ pub union MaybeUninit<T> {
}
pub mod intrinsics {
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
pub fn abort() -> !;
#[rustc_safe_intrinsic]
pub fn size_of<T>() -> usize;
pub fn size_of_val<T: ?::Sized>(val: *const T) -> usize;
#[rustc_safe_intrinsic]
pub fn min_align_of<T>() -> usize;
pub fn min_align_of_val<T: ?::Sized>(val: *const T) -> usize;
pub fn copy<T>(src: *const T, dst: *mut T, count: usize);
pub fn transmute<T, U>(e: T) -> U;
pub fn ctlz_nonzero<T>(x: T) -> u32;
#[rustc_safe_intrinsic]
pub fn needs_drop<T: ?::Sized>() -> bool;
#[rustc_safe_intrinsic]
pub fn bitreverse<T>(x: T) -> T;
#[rustc_safe_intrinsic]
pub fn bswap<T>(x: T) -> T;
pub fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub fn abort() -> ! {
loop {}
}
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub fn size_of<T>() -> usize {
loop {}
}
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub unsafe fn size_of_val<T: ?::Sized>(_val: *const T) -> usize {
loop {}
}
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub fn min_align_of<T>() -> usize {
loop {}
}
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub unsafe fn min_align_of_val<T: ?::Sized>(_val: *const T) -> usize {
loop {}
}
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub unsafe fn copy<T>(_src: *const T, _dst: *mut T, _count: usize) {
loop {}
}
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub unsafe fn transmute<T, U>(_e: T) -> U {
loop {}
}
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub unsafe fn ctlz_nonzero<T>(_x: T) -> u32 {
loop {}
}
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub fn needs_drop<T: ?::Sized>() -> bool {
loop {}
}
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub fn bitreverse<T>(_x: T) -> T {
loop {}
}
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub fn bswap<T>(_x: T) -> T {
loop {}
}
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub unsafe fn write_bytes<T>(_dst: *mut T, _val: u8, _count: usize) {
loop {}
}
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub unsafe fn unreachable() -> ! {
loop {}
}
}

View File

@ -579,28 +579,70 @@ pub union MaybeUninit<T> {
}
pub mod intrinsics {
use crate::Sized;
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
pub fn abort() -> !;
#[rustc_safe_intrinsic]
pub fn size_of<T>() -> usize;
pub fn size_of_val<T: ?Sized>(val: *const T) -> usize;
#[rustc_safe_intrinsic]
pub fn min_align_of<T>() -> usize;
pub fn min_align_of_val<T: ?Sized>(val: *const T) -> usize;
pub fn copy<T>(src: *const T, dst: *mut T, count: usize);
pub fn transmute<T, U>(e: T) -> U;
pub fn ctlz_nonzero<T>(x: T) -> u32;
#[rustc_safe_intrinsic]
pub fn needs_drop<T: ?Sized>() -> bool;
#[rustc_safe_intrinsic]
pub fn bitreverse<T>(x: T) -> T;
#[rustc_safe_intrinsic]
pub fn bswap<T>(x: T) -> T;
pub fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
pub fn unreachable() -> !;
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub fn abort() -> ! {
loop {}
}
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub fn size_of<T>() -> usize {
loop {}
}
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub unsafe fn size_of_val<T: ?::Sized>(_val: *const T) -> usize {
loop {}
}
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub fn min_align_of<T>() -> usize {
loop {}
}
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub unsafe fn min_align_of_val<T: ?::Sized>(_val: *const T) -> usize {
loop {}
}
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub unsafe fn copy<T>(_src: *const T, _dst: *mut T, _count: usize) {
loop {}
}
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub unsafe fn transmute<T, U>(_e: T) -> U {
loop {}
}
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub unsafe fn ctlz_nonzero<T>(_x: T) -> u32 {
loop {}
}
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub fn needs_drop<T: ?::Sized>() -> bool {
loop {}
}
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub fn bitreverse<T>(_x: T) -> T {
loop {}
}
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub fn bswap<T>(_x: T) -> T {
loop {}
}
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub unsafe fn write_bytes<T>(_dst: *mut T, _val: u8, _count: usize) {
loop {}
}
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub unsafe fn unreachable() -> ! {
loop {}
}
}

View File

@ -33,9 +33,11 @@ trait Receiver {
mod intrinsics {
use super::Sized;
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
pub fn abort() -> !;
#[rustc_nounwind]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub fn abort() -> ! {
loop {}
}
}

View File

@ -33,9 +33,11 @@ trait Receiver {
mod intrinsics {
use super::Sized;
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
pub fn abort() -> !;
#[rustc_nounwind]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub fn abort() -> ! {
loop {}
}
}

View File

@ -106,9 +106,11 @@ fn panic_bounds_check(index: usize, len: usize) -> ! {
}
mod intrinsics {
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
pub fn abort() -> !;
#[rustc_nounwind]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub fn abort() -> ! {
loop {}
}
}

View File

@ -56,9 +56,11 @@ mod libc {
}
mod intrinsics {
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
pub fn abort() -> !;
#[rustc_nounwind]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub fn abort() -> ! {
loop {}
}
}

View File

@ -98,9 +98,11 @@ fn panic_bounds_check(index: usize, len: usize) -> ! {
}
mod intrinsics {
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
pub fn abort() -> !;
#[rustc_nounwind]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub fn abort() -> ! {
loop {}
}
}

View File

@ -109,9 +109,11 @@ fn panic_bounds_check(index: usize, len: usize) -> ! {
}
mod intrinsics {
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
pub fn abort() -> !;
#[rustc_nounwind]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub fn abort() -> ! {
loop {}
}
}

View File

@ -103,9 +103,11 @@ fn panic_bounds_check(index: usize, len: usize) -> ! {
}
mod intrinsics {
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
pub fn abort() -> !;
#[rustc_nounwind]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub fn abort() -> ! {
loop {}
}
}

View File

@ -58,9 +58,11 @@ mod libc {
}
mod intrinsics {
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
pub fn abort() -> !;
#[rustc_nounwind]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub fn abort() -> ! {
loop {}
}
}

View File

@ -64,9 +64,11 @@ mod libc {
}
mod intrinsics {
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
pub fn abort() -> !;
#[rustc_nounwind]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub fn abort() -> ! {
loop {}
}
}

View File

@ -103,9 +103,11 @@ fn panic_bounds_check(index: usize, len: usize) -> ! {
}
mod intrinsics {
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
pub fn abort() -> !;
#[rustc_nounwind]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub fn abort() -> ! {
loop {}
}
}

View File

@ -103,9 +103,11 @@ fn panic_bounds_check(index: usize, len: usize) -> ! {
mod intrinsics {
use super::Sized;
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
pub fn abort() -> !;
#[rustc_nounwind]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub fn abort() -> ! {
loop {}
}
}

View File

@ -46,9 +46,11 @@ trait Receiver {
mod intrinsics {
use super::Sized;
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
pub fn abort() -> !;
#[rustc_nounwind]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub fn abort() -> ! {
loop {}
}
}

View File

@ -3,13 +3,15 @@ An invalid number of generic parameters was passed to an intrinsic function.
Erroneous code example:
```compile_fail,E0094
#![feature(intrinsics, rustc_attrs)]
#![feature(intrinsics)]
#![allow(internal_features)]
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
fn size_of<T, U>() -> usize; // error: intrinsic has wrong number
// of type parameters
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
fn size_of<T, U>() -> usize // error: intrinsic has wrong number
// of type parameters
{
loop {}
}
```
@ -18,11 +20,13 @@ and verify with the function declaration in the Rust source code.
Example:
```
#![feature(intrinsics, rustc_attrs)]
#![feature(intrinsics)]
#![allow(internal_features)]
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
fn size_of<T>() -> usize; // ok!
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
fn size_of<T>() -> usize // ok!
{
loop {}
}
```

View File

@ -4,12 +4,11 @@ You used a function or type which doesn't fit the requirements for where it was
used. Erroneous code examples:
```compile_fail
#![feature(intrinsics, rustc_attrs)]
#![feature(intrinsics)]
#![allow(internal_features)]
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
fn size_of<T>(); // error: intrinsic has wrong type
fn unreachable(); // error: intrinsic has wrong type
}
// or:
@ -41,12 +40,11 @@ impl Foo {
For the first code example, please check the function definition. Example:
```
#![feature(intrinsics, rustc_attrs)]
#![feature(intrinsics)]
#![allow(internal_features)]
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
fn size_of<T>() -> usize; // ok!
fn unreachable() -> !; // ok!
}
```

View File

@ -997,23 +997,18 @@ pub struct BuiltinAttribute {
rustc_doc_primitive, Normal, template!(NameValueStr: "primitive name"), ErrorFollowing,
EncodeCrossCrate::Yes, r#"`rustc_doc_primitive` is a rustc internal attribute"#,
),
rustc_attr!(
rustc_safe_intrinsic, Normal, template!(Word), WarnFollowing,
EncodeCrossCrate::No,
"the `#[rustc_safe_intrinsic]` attribute is used internally to mark intrinsics as safe"
),
rustc_attr!(
rustc_intrinsic, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes,
gated!(
rustc_intrinsic, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes, intrinsics,
"the `#[rustc_intrinsic]` attribute is used to declare intrinsics with function bodies",
),
gated!(
rustc_intrinsic_must_be_overridden, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes, intrinsics,
"the `#[rustc_intrinsic_must_be_overridden]` attribute is used to declare intrinsics without real bodies",
),
rustc_attr!(
rustc_no_mir_inline, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes,
"#[rustc_no_mir_inline] prevents the MIR inliner from inlining a function while not affecting codegen"
),
rustc_attr!(
rustc_intrinsic_must_be_overridden, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes,
"the `#[rustc_intrinsic_must_be_overridden]` attribute is used to declare intrinsics without real bodies",
),
// ==========================================================================
// Internal attributes, Testing:

View File

@ -3,7 +3,7 @@
use rustc_abi::ExternAbi;
use rustc_errors::codes::*;
use rustc_errors::{DiagMessage, struct_span_code_err};
use rustc_hir as hir;
use rustc_hir::{self as hir, Safety};
use rustc_middle::bug;
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
use rustc_middle::ty::{self, Ty, TyCtxt};
@ -75,10 +75,8 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -
let has_safe_attr = if tcx.has_attr(intrinsic_id, sym::rustc_intrinsic) {
tcx.fn_sig(intrinsic_id).skip_binder().safety()
} else {
match tcx.has_attr(intrinsic_id, sym::rustc_safe_intrinsic) {
true => hir::Safety::Safe,
false => hir::Safety::Unsafe,
}
// Old-style intrinsics are never safe
Safety::Unsafe
};
let is_in_list = match tcx.item_name(intrinsic_id.into()) {
// When adding a new intrinsic to this list,

View File

@ -1785,9 +1785,9 @@ pub fn is_doc_notable_trait(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
/// the compiler to make some assumptions about its shape; if the user doesn't use a feature gate, they may
/// cause an ICE that we otherwise may want to prevent.
pub fn intrinsic_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::IntrinsicDef> {
if (matches!(tcx.fn_sig(def_id).skip_binder().abi(), ExternAbi::RustIntrinsic)
&& tcx.features().intrinsics())
|| (tcx.has_attr(def_id, sym::rustc_intrinsic) && tcx.features().rustc_attrs())
if tcx.features().intrinsics()
&& (matches!(tcx.fn_sig(def_id).skip_binder().abi(), ExternAbi::RustIntrinsic)
|| tcx.has_attr(def_id, sym::rustc_intrinsic))
{
Some(ty::IntrinsicDef {
name: tcx.item_name(def_id.into()),

View File

@ -679,10 +679,6 @@ passes_rustc_pub_transparent =
attribute should be applied to `#[repr(transparent)]` types
.label = not a `#[repr(transparent)]` type
passes_rustc_safe_intrinsic =
attribute should be applied to intrinsic functions
.label = not an intrinsic function
passes_rustc_std_internal_symbol =
attribute should be applied to functions or statics
.label = not a function or static

View File

@ -210,9 +210,6 @@ fn check_attributes(
| [sym::rustc_promotable, ..] => self.check_stability_promotable(attr, target),
[sym::link_ordinal, ..] => self.check_link_ordinal(attr, span, target),
[sym::rustc_confusables, ..] => self.check_confusables(attr, target),
[sym::rustc_safe_intrinsic, ..] => {
self.check_rustc_safe_intrinsic(hir_id, attr, span, target)
}
[sym::cold, ..] => self.check_cold(hir_id, attr, span, target),
[sym::link, ..] => self.check_link(hir_id, attr, span, target),
[sym::link_name, ..] => self.check_link_name(hir_id, attr, span, target),
@ -2055,25 +2052,6 @@ fn check_rustc_allow_const_fn_unstable(
}
}
fn check_rustc_safe_intrinsic(
&self,
hir_id: HirId,
attr: &Attribute,
span: Span,
target: Target,
) {
if let Target::ForeignFn = target
&& let hir::Node::Item(Item {
kind: ItemKind::ForeignMod { abi: Abi::RustIntrinsic, .. },
..
}) = self.tcx.parent_hir_node(hir_id)
{
return;
}
self.dcx().emit_err(errors::RustcSafeIntrinsic { attr_span: attr.span, span });
}
fn check_rustc_std_internal_symbol(&self, attr: &Attribute, span: Span, target: Target) {
match target {
Target::Fn | Target::Static => {}

View File

@ -641,15 +641,6 @@ pub(crate) struct RustcAllowConstFnUnstable {
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(passes_rustc_safe_intrinsic)]
pub(crate) struct RustcSafeIntrinsic {
#[primary_span]
pub attr_span: Span,
#[label]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(passes_rustc_std_internal_symbol)]
pub(crate) struct RustcStdInternalSymbol {

View File

@ -1733,7 +1733,6 @@
rustc_reallocator,
rustc_regions,
rustc_reservation_impl,
rustc_safe_intrinsic,
rustc_serialize,
rustc_skip_during_method_dispatch,
rustc_specialization_trait,

View File

@ -904,38 +904,6 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
#[rustc_nounwind]
pub fn prefetch_write_instruction<T>(data: *const T, locality: i32);
/// Magic intrinsic that derives its meaning from attributes
/// attached to the function.
///
/// For example, dataflow uses this to inject static assertions so
/// that `rustc_peek(potentially_uninitialized)` would actually
/// double-check that dataflow did indeed compute that it is
/// uninitialized at that point in the control flow.
///
/// This intrinsic should not be used outside of the compiler.
#[rustc_safe_intrinsic]
#[rustc_nounwind]
pub fn rustc_peek<T>(_: T) -> T;
/// Aborts the execution of the process.
///
/// Note that, unlike most intrinsics, this is safe to call;
/// it does not require an `unsafe` block.
/// Therefore, implementations must not require the user to uphold
/// any safety invariants.
///
/// [`std::process::abort`](../../std/process/fn.abort.html) is to be preferred if possible,
/// as its behavior is more user-friendly and more stable.
///
/// The current implementation of `intrinsics::abort` is to invoke an invalid instruction,
/// on most platforms.
/// On Unix, the
/// process will probably terminate with a signal like `SIGABRT`, `SIGILL`, `SIGTRAP`, `SIGSEGV` or
/// `SIGBUS`. The precise behavior is not guaranteed and not stable.
#[rustc_safe_intrinsic]
#[rustc_nounwind]
pub fn abort() -> !;
/// Executes a breakpoint trap, for inspection by a debugger.
///
/// This intrinsic does not have a stable counterpart.
@ -943,6 +911,44 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
pub fn breakpoint();
}
/// Magic intrinsic that derives its meaning from attributes
/// attached to the function.
///
/// For example, dataflow uses this to inject static assertions so
/// that `rustc_peek(potentially_uninitialized)` would actually
/// double-check that dataflow did indeed compute that it is
/// uninitialized at that point in the control flow.
///
/// This intrinsic should not be used outside of the compiler.
#[rustc_nounwind]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub fn rustc_peek<T>(_: T) -> T {
unreachable!()
}
/// Aborts the execution of the process.
///
/// Note that, unlike most intrinsics, this is safe to call;
/// it does not require an `unsafe` block.
/// Therefore, implementations must not require the user to uphold
/// any safety invariants.
///
/// [`std::process::abort`](../../std/process/fn.abort.html) is to be preferred if possible,
/// as its behavior is more user-friendly and more stable.
///
/// The current implementation of `intrinsics::abort` is to invoke an invalid instruction,
/// on most platforms.
/// On Unix, the
/// process will probably terminate with a signal like `SIGABRT`, `SIGILL`, `SIGTRAP`, `SIGSEGV` or
/// `SIGBUS`. The precise behavior is not guaranteed and not stable.
#[rustc_nounwind]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub fn abort() -> ! {
unreachable!()
}
/// Informs the optimizer that this point in the code is not reachable,
/// enabling further optimizations.
///
@ -1512,19 +1518,22 @@ pub const fn needs_drop<T: ?Sized>() -> bool {
unreachable!()
}
extern "rust-intrinsic" {
/// Masks out bits of the pointer according to a mask.
///
/// Note that, unlike most intrinsics, this is safe to call;
/// it does not require an `unsafe` block.
/// Therefore, implementations must not require the user to uphold
/// any safety invariants.
///
/// Consider using [`pointer::mask`] instead.
#[rustc_safe_intrinsic]
#[rustc_nounwind]
pub fn ptr_mask<T>(ptr: *const T, mask: usize) -> *const T;
/// Masks out bits of the pointer according to a mask.
///
/// Note that, unlike most intrinsics, this is safe to call;
/// it does not require an `unsafe` block.
/// Therefore, implementations must not require the user to uphold
/// any safety invariants.
///
/// Consider using [`pointer::mask`] instead.
#[rustc_nounwind]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub fn ptr_mask<T>(_ptr: *const T, _mask: usize) -> *const T {
unreachable!()
}
extern "rust-intrinsic" {
/// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with
/// a size of `count` * `size_of::<T>()` and an alignment of
/// `min_align_of::<T>()`
@ -2140,41 +2149,6 @@ pub const fn needs_drop<T: ?Sized>() -> bool {
#[rustc_nounwind]
pub fn frem_fast<T: Copy>(a: T, b: T) -> T;
/// Float addition that allows optimizations based on algebraic rules.
///
/// This intrinsic does not have a stable counterpart.
#[rustc_nounwind]
#[rustc_safe_intrinsic]
pub fn fadd_algebraic<T: Copy>(a: T, b: T) -> T;
/// Float subtraction that allows optimizations based on algebraic rules.
///
/// This intrinsic does not have a stable counterpart.
#[rustc_nounwind]
#[rustc_safe_intrinsic]
pub fn fsub_algebraic<T: Copy>(a: T, b: T) -> T;
/// Float multiplication that allows optimizations based on algebraic rules.
///
/// This intrinsic does not have a stable counterpart.
#[rustc_nounwind]
#[rustc_safe_intrinsic]
pub fn fmul_algebraic<T: Copy>(a: T, b: T) -> T;
/// Float division that allows optimizations based on algebraic rules.
///
/// This intrinsic does not have a stable counterpart.
#[rustc_nounwind]
#[rustc_safe_intrinsic]
pub fn fdiv_algebraic<T: Copy>(a: T, b: T) -> T;
/// Float remainder that allows optimizations based on algebraic rules.
///
/// This intrinsic does not have a stable counterpart.
#[rustc_nounwind]
#[rustc_safe_intrinsic]
pub fn frem_algebraic<T: Copy>(a: T, b: T) -> T;
/// Converts with LLVMs fptoui/fptosi, which may return undef for values out of range
/// (<https://github.com/rust-lang/rust/issues/10184>)
///
@ -2183,6 +2157,56 @@ pub const fn needs_drop<T: ?Sized>() -> bool {
pub fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
}
/// Float addition that allows optimizations based on algebraic rules.
///
/// This intrinsic does not have a stable counterpart.
#[rustc_nounwind]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub fn fadd_algebraic<T: Copy>(_a: T, _b: T) -> T {
unimplemented!()
}
/// Float subtraction that allows optimizations based on algebraic rules.
///
/// This intrinsic does not have a stable counterpart.
#[rustc_nounwind]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub fn fsub_algebraic<T: Copy>(_a: T, _b: T) -> T {
unimplemented!()
}
/// Float multiplication that allows optimizations based on algebraic rules.
///
/// This intrinsic does not have a stable counterpart.
#[rustc_nounwind]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub fn fmul_algebraic<T: Copy>(_a: T, _b: T) -> T {
unimplemented!()
}
/// Float division that allows optimizations based on algebraic rules.
///
/// This intrinsic does not have a stable counterpart.
#[rustc_nounwind]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub fn fdiv_algebraic<T: Copy>(_a: T, _b: T) -> T {
unimplemented!()
}
/// Float remainder that allows optimizations based on algebraic rules.
///
/// This intrinsic does not have a stable counterpart.
#[rustc_nounwind]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub fn frem_algebraic<T: Copy>(_a: T, _b: T) -> T {
unimplemented!()
}
/// Returns the number of bits set in an integer type `T`
///
/// Note that, unlike most intrinsics, this is safe to call;

View File

@ -18,7 +18,7 @@ All intrinsic fallback bodies are automatically made cross-crate inlineable (lik
by the codegen backend, but not the MIR inliner.
```rust
#![feature(rustc_attrs)]
#![feature(intrinsics)]
#![allow(internal_features)]
#[rustc_intrinsic]
@ -28,7 +28,7 @@ const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {}
Since these are just regular functions, it is perfectly ok to create the intrinsic twice:
```rust
#![feature(rustc_attrs)]
#![feature(intrinsics)]
#![allow(internal_features)]
#[rustc_intrinsic]

View File

@ -1,4 +1,4 @@
#![feature(rustc_attrs)]
#![feature(intrinsics, rustc_attrs)]
#[rustc_intrinsic]
#[rustc_nounwind]

View File

@ -50,9 +50,10 @@ enum Ordering {
Greater = 1,
}
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
fn three_way_compare<T: Copy>(lhs: T, rhs: T) -> Ordering;
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
fn three_way_compare<T: Copy>(lhs: T, rhs: T) -> Ordering {
loop {}
}
// ^^^^^ core

View File

@ -5,18 +5,17 @@
#![no_core]
#![crate_name = "foo"]
extern "rust-intrinsic" {
//@ has 'foo/fn.abort.html'
//@ has - '//pre[@class="rust item-decl"]' 'pub extern "rust-intrinsic" fn abort() -> !'
#[rustc_safe_intrinsic]
pub fn abort() -> !;
//@ has 'foo/fn.unreachable.html'
//@ has - '//pre[@class="rust item-decl"]' 'pub unsafe extern "rust-intrinsic" fn unreachable() -> !'
pub fn unreachable() -> !;
//@ has 'foo/fn.abort.html'
//@ has - '//pre[@class="rust item-decl"]' 'pub fn abort() -> !'
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub fn abort() -> ! {
loop {}
}
extern "C" {
//@ has 'foo/fn.needs_drop.html'
//@ has - '//pre[@class="rust item-decl"]' 'pub unsafe extern "C" fn needs_drop() -> !'
pub fn needs_drop() -> !;
//@ has 'foo/fn.unreachable.html'
//@ has - '//pre[@class="rust item-decl"]' 'pub unsafe fn unreachable() -> !'
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub unsafe fn unreachable() -> ! {
loop {}
}

View File

@ -1,9 +1,10 @@
#![feature(intrinsics, rustc_attrs)]
#![feature(intrinsics)]
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
fn size_of<T, U>() -> usize; //~ ERROR E0094
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
fn size_of<T, U>() -> usize {
//~^ ERROR E0094
loop {}
}
fn main() {
}
fn main() {}

View File

@ -1,8 +1,8 @@
error[E0094]: intrinsic has wrong number of type parameters: found 2, expected 1
--> $DIR/E0094.rs:5:15
--> $DIR/E0094.rs:5:11
|
LL | fn size_of<T, U>() -> usize;
| ^^^^^^ expected 1 type parameter
LL | fn size_of<T, U>() -> usize {
| ^^^^^^ expected 1 type parameter
error: aborting due to 1 previous error

View File

@ -1,10 +1,11 @@
#![feature(intrinsics)]
#![feature(rustc_attrs)]
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
fn size_of<T>(); //~ ERROR E0308
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
fn size_of<T>() {
//~^ ERROR E0308
loop {}
}
fn main() {
}
fn main() {}

View File

@ -1,11 +1,11 @@
error[E0308]: intrinsic has wrong type
--> $DIR/E0308.rs:6:20
--> $DIR/E0308.rs:6:16
|
LL | fn size_of<T>();
| ^ expected `usize`, found `()`
LL | fn size_of<T>() {
| ^ expected `usize`, found `()`
|
= note: expected signature `extern "rust-intrinsic" fn() -> usize`
found signature `extern "rust-intrinsic" fn() -> ()`
= note: expected signature `fn() -> usize`
found signature `fn() -> ()`
error: aborting due to 1 previous error

View File

@ -1,18 +1,17 @@
#![feature(intrinsics, rustc_attrs)]
extern "rust-intrinsic" {
// Real example from libcore
#[rustc_safe_intrinsic]
fn type_id<T: ?Sized + 'static>() -> u64;
// Intrinsics are the only (?) extern blocks supporting generics.
// Once intrinsics have to be declared via `#[rustc_intrinsic]`,
// the entire support for generics in extern fn can probably be removed.
extern "rust-intrinsic" {
// Silent bounds made explicit to make sure they are actually
// resolved.
fn transmute<T: Sized, U: Sized>(val: T) -> U;
// Bounds aren't checked right now, so this should work
// even though it's incorrect.
#[rustc_safe_intrinsic]
fn size_of<T: Clone>() -> usize;
fn size_of_val<T: Clone>(x: *const T) -> usize;
// Unresolved bounds should still error.
fn align_of<T: NoSuchTrait>() -> usize;

View File

@ -1,5 +1,5 @@
error[E0405]: cannot find trait `NoSuchTrait` in this scope
--> $DIR/extern-with-type-bounds.rs:18:20
--> $DIR/extern-with-type-bounds.rs:17:20
|
LL | fn align_of<T: NoSuchTrait>() -> usize;
| ^^^^^^^^^^^ not found in this scope

View File

@ -1,6 +1,6 @@
//! Check that `vtable_size` gets overridden by llvm backend even if there is no
//! `rustc_intrinsic_must_be_overridden` attribute on this usage.
#![feature(rustc_attrs)]
#![feature(intrinsics)]
//@run-pass
#[rustc_intrinsic]

View File

@ -1,6 +0,0 @@
#[rustc_safe_intrinsic]
//~^ ERROR the `#[rustc_safe_intrinsic]` attribute is used internally to mark intrinsics as safe
//~| ERROR attribute should be applied to intrinsic functions
fn safe() {}
fn main() {}

View File

@ -1,21 +0,0 @@
error[E0658]: the `#[rustc_safe_intrinsic]` attribute is used internally to mark intrinsics as safe
--> $DIR/feature-gate-safe-intrinsic.rs:1:1
|
LL | #[rustc_safe_intrinsic]
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error: attribute should be applied to intrinsic functions
--> $DIR/feature-gate-safe-intrinsic.rs:1:1
|
LL | #[rustc_safe_intrinsic]
| ^^^^^^^^^^^^^^^^^^^^^^^
...
LL | fn safe() {}
| ------------ not an intrinsic function
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0658`.

View File

@ -1,14 +1,8 @@
//@ run-pass
#![feature(intrinsics, rustc_attrs)]
#![feature(core_intrinsics, rustc_attrs)]
mod rusti {
extern "rust-intrinsic" {
pub fn pref_align_of<T>() -> usize;
#[rustc_safe_intrinsic]
pub fn min_align_of<T>() -> usize;
}
}
use std::intrinsics as rusti;
#[cfg(any(
target_os = "android",

View File

@ -1,24 +1,8 @@
//@ run-pass
#![feature(intrinsics)]
#![feature(rustc_attrs)]
#![feature(core_intrinsics)]
mod rusti {
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
pub fn ctpop<T>(x: T) -> u32;
#[rustc_safe_intrinsic]
pub fn ctlz<T>(x: T) -> u32;
pub fn ctlz_nonzero<T>(x: T) -> u32;
#[rustc_safe_intrinsic]
pub fn cttz<T>(x: T) -> u32;
pub fn cttz_nonzero<T>(x: T) -> u32;
#[rustc_safe_intrinsic]
pub fn bswap<T>(x: T) -> T;
#[rustc_safe_intrinsic]
pub fn bitreverse<T>(x: T) -> T;
}
}
use std::intrinsics as rusti;
pub fn main() {
use rusti::*;

View File

@ -1,6 +1,6 @@
//! Check that intrinsics that do not get overridden, but are marked as such,
//! cause an error instead of silently invoking the body.
#![feature(rustc_attrs)]
#![feature(intrinsics)]
//@ build-fail
//@ failure-status:101
//@ normalize-stderr-test: ".*note: .*\n\n" -> ""

View File

@ -3,17 +3,10 @@
#![allow(unused_unsafe)]
// Issue #2303
#![feature(intrinsics, rustc_attrs)]
#![feature(core_intrinsics, rustc_attrs)]
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;
}
}
use std::intrinsics;
// This is the type with the questionable alignment
#[derive(Debug)]
@ -41,12 +34,12 @@ pub fn main() {
// Send it through the shape code
let y = format!("{:?}", x);
println!("align inner = {:?}", rusti::min_align_of::<Inner>());
println!("align inner = {:?}", intrinsics::min_align_of::<Inner>());
println!("size outer = {:?}", mem::size_of::<Outer>());
println!("y = {:?}", y);
// per clang/gcc the alignment of `inner` is 4 on x86.
assert_eq!(rusti::min_align_of::<Inner>(), m::align());
assert_eq!(intrinsics::min_align_of::<Inner>(), m::align());
// per clang/gcc the size of `outer` should be 12
// because `inner`s alignment was 4.

View File

@ -4,17 +4,10 @@
// Issue #2303
#![feature(intrinsics, rustc_attrs)]
#![feature(core_intrinsics, rustc_attrs)]
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;
}
}
use std::intrinsics;
// This is the type with the questionable alignment
#[derive(Debug)]
@ -90,12 +83,12 @@ pub fn main() {
let y = format!("{:?}", x);
println!("align inner = {:?}", rusti::min_align_of::<Inner>());
println!("align inner = {:?}", intrinsics::min_align_of::<Inner>());
println!("size outer = {:?}", mem::size_of::<Outer>());
println!("y = {:?}", y);
// per clang/gcc the alignment of `Inner` is 4 on x86.
assert_eq!(rusti::min_align_of::<Inner>(), m::m::align());
assert_eq!(intrinsics::min_align_of::<Inner>(), m::m::align());
// per clang/gcc the size of `Outer` should be 12
// because `Inner`s alignment was 4.