Auto merge of #132717 - RalfJung:rustc_safe_intrinsic, r=compiler-errors

remove support for rustc_safe_intrinsic attribute; use rustc_intrinsic functions instead

This brings us one step closer towards removing support for `extern "rust-intrinsic"` blocks, in favor of `#[rustc_intrinsic]` functions.

Also move `#[rustc_intrinsic]` under the `intrinsics` feature gate, to match the `extern "rust-intrinsic"` style.
This commit is contained in:
bors 2024-11-08 10:28:47 +00:00
commit 209799f3b9
42 changed files with 380 additions and 348 deletions

View File

@ -616,25 +616,70 @@ pub union MaybeUninit<T> {
} }
pub mod intrinsics { pub mod intrinsics {
extern "rust-intrinsic" { #[rustc_intrinsic]
#[rustc_safe_intrinsic] #[rustc_intrinsic_must_be_overridden]
pub fn abort() -> !; pub fn abort() -> ! {
#[rustc_safe_intrinsic] loop {}
pub fn size_of<T>() -> usize; }
pub fn size_of_val<T: ?::Sized>(val: *const T) -> usize; #[rustc_intrinsic]
#[rustc_safe_intrinsic] #[rustc_intrinsic_must_be_overridden]
pub fn min_align_of<T>() -> usize; pub fn size_of<T>() -> usize {
pub fn min_align_of_val<T: ?::Sized>(val: *const T) -> usize; loop {}
pub fn copy<T>(src: *const T, dst: *mut T, count: usize); }
pub fn transmute<T, U>(e: T) -> U; #[rustc_intrinsic]
pub fn ctlz_nonzero<T>(x: T) -> u32; #[rustc_intrinsic_must_be_overridden]
#[rustc_safe_intrinsic] pub unsafe fn size_of_val<T: ?::Sized>(_val: *const T) -> usize {
pub fn needs_drop<T: ?::Sized>() -> bool; loop {}
#[rustc_safe_intrinsic] }
pub fn bitreverse<T>(x: T) -> T; #[rustc_intrinsic]
#[rustc_safe_intrinsic] #[rustc_intrinsic_must_be_overridden]
pub fn bswap<T>(x: T) -> T; pub fn min_align_of<T>() -> usize {
pub fn write_bytes<T>(dst: *mut T, val: u8, count: 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 { pub mod intrinsics {
use crate::Sized; #[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
extern "rust-intrinsic" { pub fn abort() -> ! {
#[rustc_safe_intrinsic] loop {}
pub fn abort() -> !; }
#[rustc_safe_intrinsic] #[rustc_intrinsic]
pub fn size_of<T>() -> usize; #[rustc_intrinsic_must_be_overridden]
pub fn size_of_val<T: ?Sized>(val: *const T) -> usize; pub fn size_of<T>() -> usize {
#[rustc_safe_intrinsic] loop {}
pub fn min_align_of<T>() -> usize; }
pub fn min_align_of_val<T: ?Sized>(val: *const T) -> usize; #[rustc_intrinsic]
pub fn copy<T>(src: *const T, dst: *mut T, count: usize); #[rustc_intrinsic_must_be_overridden]
pub fn transmute<T, U>(e: T) -> U; pub unsafe fn size_of_val<T: ?::Sized>(_val: *const T) -> usize {
pub fn ctlz_nonzero<T>(x: T) -> u32; loop {}
#[rustc_safe_intrinsic] }
pub fn needs_drop<T: ?Sized>() -> bool; #[rustc_intrinsic]
#[rustc_safe_intrinsic] #[rustc_intrinsic_must_be_overridden]
pub fn bitreverse<T>(x: T) -> T; pub fn min_align_of<T>() -> usize {
#[rustc_safe_intrinsic] loop {}
pub fn bswap<T>(x: T) -> T; }
pub fn write_bytes<T>(dst: *mut T, val: u8, count: usize); #[rustc_intrinsic]
pub fn unreachable() -> !; #[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 @@ pub(crate) unsafe auto trait Freeze {}
mod intrinsics { mod intrinsics {
use super::Sized; use super::Sized;
extern "rust-intrinsic" { #[rustc_nounwind]
#[rustc_safe_intrinsic] #[rustc_intrinsic]
pub fn abort() -> !; #[rustc_intrinsic_must_be_overridden]
pub fn abort() -> ! {
loop {}
} }
} }

View File

@ -33,9 +33,11 @@ pub(crate) unsafe auto trait Freeze {}
mod intrinsics { mod intrinsics {
use super::Sized; use super::Sized;
extern "rust-intrinsic" { #[rustc_nounwind]
#[rustc_safe_intrinsic] #[rustc_intrinsic]
pub fn abort() -> !; #[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 { mod intrinsics {
extern "rust-intrinsic" { #[rustc_nounwind]
#[rustc_safe_intrinsic] #[rustc_intrinsic]
pub fn abort() -> !; #[rustc_intrinsic_must_be_overridden]
pub fn abort() -> ! {
loop {}
} }
} }

View File

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

View File

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

View File

@ -64,9 +64,11 @@ mod libc {
} }
mod intrinsics { mod intrinsics {
extern "rust-intrinsic" { #[rustc_nounwind]
#[rustc_safe_intrinsic] #[rustc_intrinsic]
pub fn abort() -> !; #[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 { mod intrinsics {
extern "rust-intrinsic" { #[rustc_nounwind]
#[rustc_safe_intrinsic] #[rustc_intrinsic]
pub fn abort() -> !; #[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 { mod intrinsics {
use super::Sized; use super::Sized;
extern "rust-intrinsic" { #[rustc_nounwind]
#[rustc_safe_intrinsic] #[rustc_intrinsic]
pub fn abort() -> !; #[rustc_intrinsic_must_be_overridden]
pub fn abort() -> ! {
loop {}
} }
} }

View File

@ -46,9 +46,11 @@ pub(crate) unsafe auto trait Freeze {}
mod intrinsics { mod intrinsics {
use super::Sized; use super::Sized;
extern "rust-intrinsic" { #[rustc_nounwind]
#[rustc_safe_intrinsic] #[rustc_intrinsic]
pub fn abort() -> !; #[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: Erroneous code example:
```compile_fail,E0094 ```compile_fail,E0094
#![feature(intrinsics, rustc_attrs)] #![feature(intrinsics)]
#![allow(internal_features)] #![allow(internal_features)]
extern "rust-intrinsic" { #[rustc_intrinsic]
#[rustc_safe_intrinsic] #[rustc_intrinsic_must_be_overridden]
fn size_of<T, U>() -> usize; // error: intrinsic has wrong number fn size_of<T, U>() -> usize // error: intrinsic has wrong number
// of type parameters // of type parameters
{
loop {}
} }
``` ```
@ -18,11 +20,13 @@ and verify with the function declaration in the Rust source code.
Example: Example:
``` ```
#![feature(intrinsics, rustc_attrs)] #![feature(intrinsics)]
#![allow(internal_features)] #![allow(internal_features)]
extern "rust-intrinsic" { #[rustc_intrinsic]
#[rustc_safe_intrinsic] #[rustc_intrinsic_must_be_overridden]
fn size_of<T>() -> usize; // ok! 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: used. Erroneous code examples:
```compile_fail ```compile_fail
#![feature(intrinsics, rustc_attrs)] #![feature(intrinsics)]
#![allow(internal_features)] #![allow(internal_features)]
extern "rust-intrinsic" { extern "rust-intrinsic" {
#[rustc_safe_intrinsic] fn unreachable(); // error: intrinsic has wrong type
fn size_of<T>(); // error: intrinsic has wrong type
} }
// or: // or:
@ -41,12 +40,11 @@ impl Foo {
For the first code example, please check the function definition. Example: For the first code example, please check the function definition. Example:
``` ```
#![feature(intrinsics, rustc_attrs)] #![feature(intrinsics)]
#![allow(internal_features)] #![allow(internal_features)]
extern "rust-intrinsic" { extern "rust-intrinsic" {
#[rustc_safe_intrinsic] fn unreachable() -> !; // ok!
fn size_of<T>() -> usize; // ok!
} }
``` ```

View File

@ -997,23 +997,18 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
rustc_doc_primitive, Normal, template!(NameValueStr: "primitive name"), ErrorFollowing, rustc_doc_primitive, Normal, template!(NameValueStr: "primitive name"), ErrorFollowing,
EncodeCrossCrate::Yes, r#"`rustc_doc_primitive` is a rustc internal attribute"#, EncodeCrossCrate::Yes, r#"`rustc_doc_primitive` is a rustc internal attribute"#,
), ),
rustc_attr!( gated!(
rustc_safe_intrinsic, Normal, template!(Word), WarnFollowing, rustc_intrinsic, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes, intrinsics,
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,
"the `#[rustc_intrinsic]` attribute is used to declare intrinsics with function bodies", "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_attr!(
rustc_no_mir_inline, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes, 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_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: // Internal attributes, Testing:

View File

@ -3,7 +3,7 @@
use rustc_abi::ExternAbi; use rustc_abi::ExternAbi;
use rustc_errors::codes::*; use rustc_errors::codes::*;
use rustc_errors::{DiagMessage, struct_span_code_err}; 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::bug;
use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
use rustc_middle::ty::{self, Ty, TyCtxt}; 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) { let has_safe_attr = if tcx.has_attr(intrinsic_id, sym::rustc_intrinsic) {
tcx.fn_sig(intrinsic_id).skip_binder().safety() tcx.fn_sig(intrinsic_id).skip_binder().safety()
} else { } else {
match tcx.has_attr(intrinsic_id, sym::rustc_safe_intrinsic) { // Old-style intrinsics are never safe
true => hir::Safety::Safe, Safety::Unsafe
false => hir::Safety::Unsafe,
}
}; };
let is_in_list = match tcx.item_name(intrinsic_id.into()) { let is_in_list = match tcx.item_name(intrinsic_id.into()) {
// When adding a new intrinsic to this list, // 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 /// 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. /// cause an ICE that we otherwise may want to prevent.
pub fn intrinsic_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::IntrinsicDef> { pub fn intrinsic_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::IntrinsicDef> {
if (matches!(tcx.fn_sig(def_id).skip_binder().abi(), ExternAbi::RustIntrinsic) if tcx.features().intrinsics()
&& tcx.features().intrinsics()) && (matches!(tcx.fn_sig(def_id).skip_binder().abi(), ExternAbi::RustIntrinsic)
|| (tcx.has_attr(def_id, sym::rustc_intrinsic) && tcx.features().rustc_attrs()) || tcx.has_attr(def_id, sym::rustc_intrinsic))
{ {
Some(ty::IntrinsicDef { Some(ty::IntrinsicDef {
name: tcx.item_name(def_id.into()), 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 attribute should be applied to `#[repr(transparent)]` types
.label = not a `#[repr(transparent)]` type .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 = passes_rustc_std_internal_symbol =
attribute should be applied to functions or statics attribute should be applied to functions or statics
.label = not a function or static .label = not a function or static

View File

@ -210,9 +210,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| [sym::rustc_promotable, ..] => self.check_stability_promotable(attr, target), | [sym::rustc_promotable, ..] => self.check_stability_promotable(attr, target),
[sym::link_ordinal, ..] => self.check_link_ordinal(attr, span, target), [sym::link_ordinal, ..] => self.check_link_ordinal(attr, span, target),
[sym::rustc_confusables, ..] => self.check_confusables(attr, 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::cold, ..] => self.check_cold(hir_id, attr, span, target),
[sym::link, ..] => self.check_link(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), [sym::link_name, ..] => self.check_link_name(hir_id, attr, span, target),
@ -2055,25 +2052,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
} }
} }
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) { fn check_rustc_std_internal_symbol(&self, attr: &Attribute, span: Span, target: Target) {
match target { match target {
Target::Fn | Target::Static => {} Target::Fn | Target::Static => {}

View File

@ -641,15 +641,6 @@ pub(crate) struct RustcAllowConstFnUnstable {
pub span: Span, 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)] #[derive(Diagnostic)]
#[diag(passes_rustc_std_internal_symbol)] #[diag(passes_rustc_std_internal_symbol)]
pub(crate) struct RustcStdInternalSymbol { pub(crate) struct RustcStdInternalSymbol {

View File

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

View File

@ -904,38 +904,6 @@ extern "rust-intrinsic" {
#[rustc_nounwind] #[rustc_nounwind]
pub fn prefetch_write_instruction<T>(data: *const T, locality: i32); 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. /// Executes a breakpoint trap, for inspection by a debugger.
/// ///
/// This intrinsic does not have a stable counterpart. /// This intrinsic does not have a stable counterpart.
@ -943,6 +911,44 @@ extern "rust-intrinsic" {
pub fn breakpoint(); 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, /// Informs the optimizer that this point in the code is not reachable,
/// enabling further optimizations. /// enabling further optimizations.
/// ///
@ -1512,19 +1518,22 @@ pub const unsafe fn arith_offset<T>(_dst: *const T, _offset: isize) -> *const T
unreachable!() unreachable!()
} }
extern "rust-intrinsic" { /// Masks out bits of the pointer according to a mask.
/// Masks out bits of the pointer according to a mask. ///
/// /// Note that, unlike most intrinsics, this is safe to call;
/// Note that, unlike most intrinsics, this is safe to call; /// it does not require an `unsafe` block.
/// it does not require an `unsafe` block. /// Therefore, implementations must not require the user to uphold
/// Therefore, implementations must not require the user to uphold /// any safety invariants.
/// any safety invariants. ///
/// /// Consider using [`pointer::mask`] instead.
/// Consider using [`pointer::mask`] instead. #[rustc_nounwind]
#[rustc_safe_intrinsic] #[rustc_intrinsic]
#[rustc_nounwind] #[rustc_intrinsic_must_be_overridden]
pub fn ptr_mask<T>(ptr: *const T, mask: usize) -> *const T; 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 /// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with
/// a size of `count` * `size_of::<T>()` and an alignment of /// a size of `count` * `size_of::<T>()` and an alignment of
/// `min_align_of::<T>()` /// `min_align_of::<T>()`
@ -2140,41 +2149,6 @@ extern "rust-intrinsic" {
#[rustc_nounwind] #[rustc_nounwind]
pub fn frem_fast<T: Copy>(a: T, b: T) -> T; 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 /// Converts with LLVMs fptoui/fptosi, which may return undef for values out of range
/// (<https://github.com/rust-lang/rust/issues/10184>) /// (<https://github.com/rust-lang/rust/issues/10184>)
/// ///
@ -2183,6 +2157,56 @@ extern "rust-intrinsic" {
pub fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int; 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` /// Returns the number of bits set in an integer type `T`
/// ///
/// Note that, unlike most intrinsics, this is safe to call; /// 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. by the codegen backend, but not the MIR inliner.
```rust ```rust
#![feature(rustc_attrs)] #![feature(intrinsics)]
#![allow(internal_features)] #![allow(internal_features)]
#[rustc_intrinsic] #[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: Since these are just regular functions, it is perfectly ok to create the intrinsic twice:
```rust ```rust
#![feature(rustc_attrs)] #![feature(intrinsics)]
#![allow(internal_features)] #![allow(internal_features)]
#[rustc_intrinsic] #[rustc_intrinsic]

View File

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

View File

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

View File

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

View File

@ -1,9 +1,10 @@
#![feature(intrinsics, rustc_attrs)] #![feature(intrinsics)]
extern "rust-intrinsic" { #[rustc_intrinsic]
#[rustc_safe_intrinsic] #[rustc_intrinsic_must_be_overridden]
fn size_of<T, U>() -> usize; //~ ERROR E0094 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 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; LL | fn size_of<T, U>() -> usize {
| ^^^^^^ expected 1 type parameter | ^^^^^^ expected 1 type parameter
error: aborting due to 1 previous error error: aborting due to 1 previous error

View File

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

View File

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

View File

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

View File

@ -1,5 +1,5 @@
error[E0405]: cannot find trait `NoSuchTrait` in this scope 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; LL | fn align_of<T: NoSuchTrait>() -> usize;
| ^^^^^^^^^^^ not found in this scope | ^^^^^^^^^^^ 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 //! Check that `vtable_size` gets overridden by llvm backend even if there is no
//! `rustc_intrinsic_must_be_overridden` attribute on this usage. //! `rustc_intrinsic_must_be_overridden` attribute on this usage.
#![feature(rustc_attrs)] #![feature(intrinsics)]
//@run-pass //@run-pass
#[rustc_intrinsic] #[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 //@ run-pass
#![feature(intrinsics, rustc_attrs)] #![feature(core_intrinsics, rustc_attrs)]
mod rusti { use std::intrinsics as rusti;
extern "rust-intrinsic" {
pub fn pref_align_of<T>() -> usize;
#[rustc_safe_intrinsic]
pub fn min_align_of<T>() -> usize;
}
}
#[cfg(any( #[cfg(any(
target_os = "android", target_os = "android",

View File

@ -1,24 +1,8 @@
//@ run-pass //@ run-pass
#![feature(intrinsics)] #![feature(core_intrinsics)]
#![feature(rustc_attrs)]
mod rusti { use std::intrinsics as 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;
}
}
pub fn main() { pub fn main() {
use rusti::*; use rusti::*;

View File

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

View File

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

View File

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