Rollup merge of #132492 - RalfJung:const-intrinsics, r=compiler-errors

remove support for extern-block const intrinsics

This converts all const-callable intrinsics into the "new" form of a regular `fn` with `#[rustc_intrinsic]` attribute. That simplifies some of the logic since those functions can be marked `const fn` like regular functions, so intrinsics no longer need a special case to be considered const-callable at all.

I also added a new attribute `#[rustc_const_stable_intrinsic]` to mark an intrinsic as being ready to be exposed on stable. Previously we used the `#[rustc_const_stable_indirect]` attribute for that, but that attribute had a dual role -- when used on a regular function, it is an entirely safe marker to make this function part of recursive const stability, but on an intrinsic it is a trusted marker requiring special care. It's not great for the same attribute to be sometimes fully checked and safe, and sometimes trusted and requiring special care, so I split this into two attributes.

This also fixes https://github.com/rust-lang/rust/issues/122652 by accepting intrinsics as const-stable if they have a fallback body that is recursively const-stable.

The library changes are best reviewed with whitespace hidden.

r? `@compiler-errors`
This commit is contained in:
Jubilee 2024-11-04 20:40:46 -08:00 committed by GitHub
commit 23ef001d66
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
32 changed files with 1341 additions and 1276 deletions

View File

@ -273,8 +273,7 @@ pub fn find_stability(
/// Collects stability info from `rustc_const_stable`/`rustc_const_unstable`/`rustc_promotable`
/// attributes in `attrs`. Returns `None` if no stability attributes are found.
///
/// `is_const_fn` indicates whether this is a function marked as `const`. It will always
/// be false for intrinsics in an `extern` block!
/// `is_const_fn` indicates whether this is a function marked as `const`.
pub fn find_const_stability(
sess: &Session,
attrs: &[Attribute],
@ -330,7 +329,7 @@ pub fn find_const_stability(
}
}
// Merge promotable and not_exposed_on_stable into stability info
// Merge promotable and const_stable_indirect into stability info
if promotable {
match &mut const_stab {
Some((stab, _)) => stab.promotable = promotable,
@ -352,10 +351,7 @@ pub fn find_const_stability(
})
}
}
_ => {
// We ignore the `#[rustc_const_stable_indirect]` here, it should be picked up by
// the `default_const_unstable` logic.
}
_ => {}
}
}
// Make sure if `const_stable_indirect` is present, that is recorded. Also make sure all `const

View File

@ -399,7 +399,7 @@ const_eval_uninhabited_enum_variant_written =
const_eval_unmarked_const_fn_exposed = `{$def_path}` cannot be (indirectly) exposed to stable
.help = either mark the callee as `#[rustc_const_stable_indirect]`, or the caller as `#[rustc_const_unstable]`
const_eval_unmarked_intrinsic_exposed = intrinsic `{$def_path}` cannot be (indirectly) exposed to stable
.help = mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_indirect]` (but this requires team approval)
.help = mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval)
const_eval_unreachable = entering unreachable code
const_eval_unreachable_unwind =

View File

@ -736,16 +736,25 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
// Intrinsics are language primitives, not regular calls, so treat them separately.
if let Some(intrinsic) = tcx.intrinsic(callee) {
// We use `intrinsic.const_stable` to determine if this can be safely exposed to
// stable code, rather than `const_stable_indirect`. This is to make
// `#[rustc_const_stable_indirect]` an attribute that is always safe to add.
// We also ask is_safe_to_expose_on_stable_const_fn; this determines whether the intrinsic
// fallback body is safe to expose on stable.
let is_const_stable = intrinsic.const_stable
|| (!intrinsic.must_be_overridden
&& tcx.is_const_fn(callee)
&& is_safe_to_expose_on_stable_const_fn(tcx, callee));
match tcx.lookup_const_stability(callee) {
None => {
// Non-const intrinsic.
self.check_op(ops::IntrinsicNonConst { name: intrinsic.name });
}
Some(ConstStability { feature: None, const_stable_indirect, .. }) => {
Some(ConstStability { feature: None, .. }) => {
// Intrinsic does not need a separate feature gate (we rely on the
// regular stability checker). However, we have to worry about recursive
// const stability.
if !const_stable_indirect && self.enforce_recursive_const_stability() {
if !is_const_stable && self.enforce_recursive_const_stability() {
self.dcx().emit_err(errors::UnmarkedIntrinsicExposed {
span: self.span,
def_path: self.tcx.def_path_str(callee),
@ -755,17 +764,19 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
Some(ConstStability {
feature: Some(feature),
level: StabilityLevel::Unstable { .. },
const_stable_indirect,
..
}) => {
self.check_op(ops::IntrinsicUnstable {
name: intrinsic.name,
feature,
const_stable_indirect,
const_stable: is_const_stable,
});
}
Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }) => {
// All good.
// All good. Note that a `#[rustc_const_stable]` intrinsic (meaning it
// can be *directly* invoked from stable const code) does not always
// have the `#[rustc_const_stable_intrinsic]` attribute (which controls
// exposing an intrinsic indirectly); we accept this call anyway.
}
}
// This completes the checks for intrinsics.

View File

@ -354,14 +354,14 @@ impl<'tcx> NonConstOp<'tcx> for IntrinsicNonConst {
pub(crate) struct IntrinsicUnstable {
pub name: Symbol,
pub feature: Symbol,
pub const_stable_indirect: bool,
pub const_stable: bool,
}
impl<'tcx> NonConstOp<'tcx> for IntrinsicUnstable {
fn status_in_item(&self, _ccx: &ConstCx<'_, 'tcx>) -> Status {
Status::Unstable {
gate: self.feature,
safe_to_expose_on_stable: self.const_stable_indirect,
safe_to_expose_on_stable: self.const_stable,
// We do *not* want to suggest to mark the intrinsic as `const_stable_indirect`,
// that's not a trivial change!
is_function_call: false,

View File

@ -25,15 +25,9 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness {
hir::Constness::Const
}
hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) => impl_.constness,
hir::Node::ForeignItem(hir::ForeignItem { kind: hir::ForeignItemKind::Fn(..), .. }) => {
// Intrinsics use `rustc_const_{un,}stable` attributes to indicate constness. All other
// foreign items cannot be evaluated at compile-time.
let is_const = if tcx.intrinsic(def_id).is_some() {
tcx.lookup_const_stability(def_id).is_some()
} else {
false
};
if is_const { hir::Constness::Const } else { hir::Constness::NotConst }
hir::Node::ForeignItem(_) => {
// Foreign items cannot be evaluated at compile-time.
hir::Constness::NotConst
}
hir::Node::Expr(e) if let hir::ExprKind::Closure(c) = e.kind => c.constness,
_ => {

View File

@ -837,6 +837,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
rustc_const_stable_indirect, Normal,
template!(Word), WarnFollowing, EncodeCrossCrate::No, IMPL_DETAIL,
),
rustc_attr!(
rustc_const_stable_intrinsic, Normal,
template!(Word), WarnFollowing, EncodeCrossCrate::No, IMPL_DETAIL,
),
gated!(
rustc_allow_const_fn_unstable, Normal,
template!(Word, List: "feat1, feat2, ..."), DuplicatesOk, EncodeCrossCrate::No,

View File

@ -9,6 +9,8 @@ pub struct IntrinsicDef {
pub name: Symbol,
/// Whether the intrinsic has no meaningful body and all backends need to shim all calls to it.
pub must_be_overridden: bool,
/// Whether the intrinsic can be invoked from stable const fn
pub const_stable: bool,
}
impl TyCtxt<'_> {

View File

@ -1789,6 +1789,7 @@ pub fn intrinsic_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::Intrinsi
Some(ty::IntrinsicDef {
name: tcx.item_name(def_id.into()),
must_be_overridden: tcx.has_attr(def_id, sym::rustc_intrinsic_must_be_overridden),
const_stable: tcx.has_attr(def_id, sym::rustc_const_stable_intrinsic),
})
} else {
None

View File

@ -106,7 +106,6 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
def_id: LocalDefId,
item_sp: Span,
fn_sig: Option<&'tcx hir::FnSig<'tcx>>,
is_foreign_item: bool,
kind: AnnotationKind,
inherit_deprecation: InheritDeprecation,
inherit_const_stability: InheritConstStability,
@ -175,11 +174,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
// implied), check if the function/method is const or the parent impl block is const.
if let Some(fn_sig) = fn_sig
&& !fn_sig.header.is_const()
// We have to exclude foreign items as they might be intrinsics. Sadly we can't check
// their ABI; `fn_sig.abi` is *not* correct for foreign functions.
&& !is_foreign_item
&& const_stab.is_some()
&& (!self.in_trait_impl || !self.tcx.is_const_fn(def_id.to_def_id()))
{
self.tcx.dcx().emit_err(errors::MissingConstErr { fn_sig_span: fn_sig.span });
}
@ -398,7 +393,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
ctor_def_id,
i.span,
None,
/* is_foreign_item */ false,
AnnotationKind::Required,
InheritDeprecation::Yes,
InheritConstStability::No,
@ -417,7 +411,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
i.owner_id.def_id,
i.span,
fn_sig,
/* is_foreign_item */ false,
kind,
InheritDeprecation::Yes,
const_stab_inherit,
@ -437,7 +430,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
ti.owner_id.def_id,
ti.span,
fn_sig,
/* is_foreign_item */ false,
AnnotationKind::Required,
InheritDeprecation::Yes,
InheritConstStability::No,
@ -461,7 +453,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
ii.owner_id.def_id,
ii.span,
fn_sig,
/* is_foreign_item */ false,
kind,
InheritDeprecation::Yes,
InheritConstStability::No,
@ -477,7 +468,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
var.def_id,
var.span,
None,
/* is_foreign_item */ false,
AnnotationKind::Required,
InheritDeprecation::Yes,
InheritConstStability::No,
@ -488,7 +478,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
ctor_def_id,
var.span,
None,
/* is_foreign_item */ false,
AnnotationKind::Required,
InheritDeprecation::Yes,
InheritConstStability::No,
@ -507,7 +496,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
s.def_id,
s.span,
None,
/* is_foreign_item */ false,
AnnotationKind::Required,
InheritDeprecation::Yes,
InheritConstStability::No,
@ -527,7 +515,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
i.owner_id.def_id,
i.span,
fn_sig,
/* is_foreign_item */ true,
AnnotationKind::Required,
InheritDeprecation::Yes,
InheritConstStability::No,
@ -550,7 +537,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
p.def_id,
p.span,
None,
/* is_foreign_item */ false,
kind,
InheritDeprecation::No,
InheritConstStability::No,
@ -712,7 +698,6 @@ fn stability_index(tcx: TyCtxt<'_>, (): ()) -> Index {
CRATE_DEF_ID,
tcx.hir().span(CRATE_HIR_ID),
None,
/* is_foreign_item */ false,
AnnotationKind::Required,
InheritDeprecation::Yes,
InheritConstStability::No,

View File

@ -1663,6 +1663,7 @@ symbols! {
rustc_const_panic_str,
rustc_const_stable,
rustc_const_stable_indirect,
rustc_const_stable_intrinsic,
rustc_const_unstable,
rustc_conversion_suggestion,
rustc_deallocator,

File diff suppressed because it is too large Load Diff

View File

@ -107,6 +107,7 @@
//
// Library features:
// tidy-alphabetical-start
#![cfg_attr(bootstrap, feature(const_exact_div))]
#![cfg_attr(bootstrap, feature(const_fmt_arguments_new))]
#![feature(array_ptr_get)]
#![feature(asm_experimental_arch)]
@ -116,7 +117,6 @@
#![feature(const_black_box)]
#![feature(const_char_encode_utf16)]
#![feature(const_eval_select)]
#![feature(const_exact_div)]
#![feature(const_float_methods)]
#![feature(const_heap)]
#![feature(const_nonnull_new)]

View File

@ -1,4 +1,5 @@
// tidy-alphabetical-start
#![cfg_attr(bootstrap, feature(const_three_way_compare))]
#![cfg_attr(bootstrap, feature(strict_provenance))]
#![cfg_attr(not(bootstrap), feature(strict_provenance_lints))]
#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))]
@ -22,7 +23,6 @@
#![feature(const_nonnull_new)]
#![feature(const_option_ext)]
#![feature(const_pin_2)]
#![feature(const_three_way_compare)]
#![feature(const_trait_impl)]
#![feature(core_intrinsics)]
#![feature(core_io_borrowed_buf)]

View File

@ -1,20 +1,26 @@
#![feature(intrinsics)]
#![feature(intrinsics, rustc_attrs)]
#![feature(staged_api)]
#![crate_name = "foo"]
#![stable(since="1.0.0", feature="rust1")]
extern "rust-intrinsic" {
//@ has 'foo/fn.transmute.html'
//@ has - '//pre[@class="rust item-decl"]' 'pub const unsafe extern "rust-intrinsic" fn transmute<T, U>(_: T) -> U'
#[stable(since="1.0.0", feature="rust1")]
#[rustc_const_stable(feature = "const_transmute", since = "1.56.0")]
pub fn transmute<T, U>(_: T) -> U;
//@ has 'foo/fn.transmute.html'
//@ has - '//pre[@class="rust item-decl"]' 'pub const unsafe fn transmute<T, U>(_: T) -> U'
#[stable(since="1.0.0", feature="rust1")]
#[rustc_const_stable(feature = "const_transmute", since = "1.56.0")]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub const unsafe fn transmute<T, U>(_: T) -> U {
loop {}
}
//@ has 'foo/fn.unreachable.html'
//@ has - '//pre[@class="rust item-decl"]' 'pub unsafe extern "rust-intrinsic" fn unreachable() -> !'
#[stable(since="1.0.0", feature="rust1")]
pub fn unreachable() -> !;
//@ has 'foo/fn.unreachable.html'
//@ has - '//pre[@class="rust item-decl"]' 'pub unsafe fn unreachable() -> !'
#[stable(since="1.0.0", feature="rust1")]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub unsafe fn unreachable() -> ! {
loop {}
}
extern "C" {

View File

@ -1,4 +1,4 @@
error[E0277]: expected a `FnOnce(&str)` closure, found `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}`
error[E0277]: expected a `FnOnce(&str)` closure, found `unsafe fn(_) -> _ {std::intrinsics::transmute::<_, _>}`
--> $DIR/coerce-unsafe-to-closure.rs:2:44
|
LL | let x: Option<&[u8]> = Some("foo").map(std::mem::transmute);
@ -6,7 +6,7 @@ LL | let x: Option<&[u8]> = Some("foo").map(std::mem::transmute);
| |
| required by a bound introduced by this call
|
= help: the trait `FnOnce(&str)` is not implemented for fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}`
= help: the trait `FnOnce(&str)` is not implemented for fn item `unsafe fn(_) -> _ {std::intrinsics::transmute::<_, _>}`
= note: unsafe function cannot be called generically without an unsafe block
note: required by a bound in `Option::<T>::map`
--> $SRC_DIR/core/src/option.rs:LL:COL

View File

@ -1,26 +1,13 @@
#![feature(staged_api, rustc_attrs, intrinsics)]
#![stable(since="1.0.0", feature = "stable")]
#[stable(since="1.0.0", feature = "stable")]
pub mod old_way {
extern "rust-intrinsic" {
#[unstable(feature = "unstable", issue = "42")]
pub fn size_of_val<T>(x: *const T) -> usize;
#[unstable(feature = "unstable", issue = "42")]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 }
#[unstable(feature = "unstable", issue = "42")]
#[rustc_const_unstable(feature = "unstable", issue = "42")]
pub fn min_align_of_val<T>(x: *const T) -> usize;
}
}
#[stable(since="1.0.0", feature = "stable")]
pub mod new_way {
#[unstable(feature = "unstable", issue = "42")]
#[rustc_intrinsic]
pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 }
#[unstable(feature = "unstable", issue = "42")]
#[rustc_const_unstable(feature = "unstable", issue = "42")]
#[rustc_intrinsic]
pub const unsafe fn min_align_of_val<T>(x: *const T) -> usize { 42 }
}
#[unstable(feature = "unstable", issue = "42")]
#[rustc_const_unstable(feature = "unstable", issue = "42")]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub const unsafe fn min_align_of_val<T>(x: *const T) -> usize { 42 }

View File

@ -1,7 +1,6 @@
//@ check-fail
#![feature(core_intrinsics)]
#![feature(const_intrinsic_compare_bytes)]
use std::intrinsics::compare_bytes;
use std::mem::MaybeUninit;

View File

@ -1,47 +1,47 @@
error[E0080]: evaluation of constant value failed
--> $DIR/const-compare-bytes-ub.rs:10:9
--> $DIR/const-compare-bytes-ub.rs:9:9
|
LL | compare_bytes(0 as *const u8, 2 as *const u8, 1)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 1 byte of memory, but got a null pointer
error[E0080]: evaluation of constant value failed
--> $DIR/const-compare-bytes-ub.rs:14:9
--> $DIR/const-compare-bytes-ub.rs:13:9
|
LL | compare_bytes(1 as *const u8, 0 as *const u8, 1)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 1 byte of memory, but got 0x1[noalloc] which is a dangling pointer (it has no provenance)
error[E0080]: evaluation of constant value failed
--> $DIR/const-compare-bytes-ub.rs:18:9
--> $DIR/const-compare-bytes-ub.rs:17:9
|
LL | compare_bytes(1 as *const u8, 2 as *const u8, 1)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 1 byte of memory, but got 0x1[noalloc] which is a dangling pointer (it has no provenance)
error[E0080]: evaluation of constant value failed
--> $DIR/const-compare-bytes-ub.rs:22:9
--> $DIR/const-compare-bytes-ub.rs:21:9
|
LL | compare_bytes([1, 2, 3].as_ptr(), [1, 2, 3, 4].as_ptr(), 4)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got ALLOC0 which is only 3 bytes from the end of the allocation
error[E0080]: evaluation of constant value failed
--> $DIR/const-compare-bytes-ub.rs:26:9
--> $DIR/const-compare-bytes-ub.rs:25:9
|
LL | compare_bytes([1, 2, 3, 4].as_ptr(), [1, 2, 3].as_ptr(), 4)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got ALLOC1 which is only 3 bytes from the end of the allocation
error[E0080]: evaluation of constant value failed
--> $DIR/const-compare-bytes-ub.rs:30:9
--> $DIR/const-compare-bytes-ub.rs:29:9
|
LL | compare_bytes(MaybeUninit::uninit().as_ptr(), [1].as_ptr(), 1)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at ALLOC2[0x0..0x1], but memory is uninitialized at [0x0..0x1], and this operation requires initialized memory
error[E0080]: evaluation of constant value failed
--> $DIR/const-compare-bytes-ub.rs:34:9
--> $DIR/const-compare-bytes-ub.rs:33:9
|
LL | compare_bytes([1].as_ptr(), MaybeUninit::uninit().as_ptr(), 1)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at ALLOC3[0x0..0x1], but memory is uninitialized at [0x0..0x1], and this operation requires initialized memory
error[E0080]: evaluation of constant value failed
--> $DIR/const-compare-bytes-ub.rs:38:9
--> $DIR/const-compare-bytes-ub.rs:37:9
|
LL | compare_bytes([&1].as_ptr().cast(), [&2].as_ptr().cast(), std::mem::size_of::<usize>())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer

View File

@ -1,7 +1,6 @@
//@ run-pass
#![feature(core_intrinsics)]
#![feature(const_intrinsic_compare_bytes)]
use std::intrinsics::compare_bytes;
fn main() {

View File

@ -1,6 +1,6 @@
//@ run-pass
#![feature(repr_simd)]
#![feature(intrinsics)]
#![feature(intrinsics, rustc_attrs)]
#![feature(staged_api)]
#![stable(feature = "foo", since = "1.3.37")]
#![allow(non_camel_case_types)]
@ -10,14 +10,18 @@
#[repr(simd)] struct u16x2([u16; 2]);
#[repr(simd)] struct f32x4([f32; 4]);
extern "rust-intrinsic" {
#[stable(feature = "foo", since = "1.3.37")]
#[rustc_const_stable(feature = "foo", since = "1.3.37")]
fn simd_insert<T, U>(x: T, idx: u32, val: U) -> T;
#[stable(feature = "foo", since = "1.3.37")]
#[rustc_const_stable(feature = "foo", since = "1.3.37")]
#[rustc_intrinsic]
const unsafe fn simd_insert<T, U>(_x: T, _idx: u32, _val: U) -> T {
unimplemented!()
}
#[stable(feature = "foo", since = "1.3.37")]
#[rustc_const_stable(feature = "foo", since = "1.3.37")]
fn simd_extract<T, U>(x: T, idx: u32) -> U;
#[stable(feature = "foo", since = "1.3.37")]
#[rustc_const_stable(feature = "foo", since = "1.3.37")]
#[rustc_intrinsic]
const unsafe fn simd_extract<T, U>(_x: T, _idx: u32) -> U {
unimplemented!()
}
fn main() {

View File

@ -14,63 +14,51 @@ fn main() {
const fn const_main() {
let x = 42;
unsafe {
unstable_intrinsic::old_way::size_of_val(&x);
//~^ERROR: unstable library feature `unstable`
//~|ERROR: cannot call non-const intrinsic
unstable_intrinsic::old_way::min_align_of_val(&x);
//~^ERROR: unstable library feature `unstable`
//~|ERROR: not yet stable as a const intrinsic
unstable_intrinsic::new_way::size_of_val(&x);
unstable_intrinsic::size_of_val(&x);
//~^ERROR: unstable library feature `unstable`
//~|ERROR: cannot be (indirectly) exposed to stable
unstable_intrinsic::new_way::min_align_of_val(&x);
unstable_intrinsic::min_align_of_val(&x);
//~^ERROR: unstable library feature `unstable`
//~|ERROR: not yet stable as a const intrinsic
old_way::size_of_val(&x);
//~^ERROR: cannot call non-const intrinsic
old_way::min_align_of_val(&x);
//~^ERROR: cannot use `#[feature(local)]`
new_way::size_of_val(&x);
size_of_val(&x);
//~^ERROR: cannot be (indirectly) exposed to stable
new_way::min_align_of_val(&x);
min_align_of_val(&x);
//~^ERROR: cannot use `#[feature(local)]`
}
}
#[stable(since="1.0.0", feature = "stable")]
pub mod old_way {
extern "rust-intrinsic" {
#[unstable(feature = "local", issue = "42")]
pub fn size_of_val<T>(x: *const T) -> usize;
#[unstable(feature = "local", issue = "42")]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 }
#[unstable(feature = "local", issue = "42")]
#[rustc_const_unstable(feature = "local", issue = "42")]
pub fn min_align_of_val<T>(x: *const T) -> usize;
}
}
#[stable(since="1.0.0", feature = "stable")]
pub mod new_way {
#[unstable(feature = "local", issue = "42")]
#[rustc_intrinsic]
pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 }
#[unstable(feature = "local", issue = "42")]
#[rustc_const_unstable(feature = "local", issue = "42")]
#[rustc_intrinsic]
pub const unsafe fn min_align_of_val<T>(x: *const T) -> usize { 42 }
}
#[unstable(feature = "local", issue = "42")]
#[rustc_const_unstable(feature = "local", issue = "42")]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub const unsafe fn min_align_of_val<T>(x: *const T) -> usize { 42 }
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
#[inline]
pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
// Const stability attributes are not inherited from parent items.
extern "rust-intrinsic" {
fn copy<T>(src: *const T, dst: *mut T, count: usize);
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
unimplemented!()
}
unsafe { copy(src, dst, count) }
//~^ ERROR cannot call non-const intrinsic
//~^ ERROR cannot be (indirectly) exposed to stable
}
// Ensure that a fallback body is recursively-const-checked.
mod fallback {
#[rustc_intrinsic]
const unsafe fn copy<T>(src: *const T, _dst: *mut T, _count: usize) {
super::size_of_val(src);
//~^ ERROR cannot be (indirectly) exposed to stable
}
}

View File

@ -1,8 +1,8 @@
error[E0658]: use of unstable library feature `unstable`
--> $DIR/const-unstable-intrinsic.rs:17:9
|
LL | unstable_intrinsic::old_way::size_of_val(&x);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | unstable_intrinsic::size_of_val(&x);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #42 <https://github.com/rust-lang/rust/issues/42> for more information
= help: add `#![feature(unstable)]` to the crate attributes to enable
@ -11,74 +11,42 @@ LL | unstable_intrinsic::old_way::size_of_val(&x);
error[E0658]: use of unstable library feature `unstable`
--> $DIR/const-unstable-intrinsic.rs:20:9
|
LL | unstable_intrinsic::old_way::min_align_of_val(&x);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | unstable_intrinsic::min_align_of_val(&x);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #42 <https://github.com/rust-lang/rust/issues/42> for more information
= help: add `#![feature(unstable)]` 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[E0658]: use of unstable library feature `unstable`
--> $DIR/const-unstable-intrinsic.rs:23:9
|
LL | unstable_intrinsic::new_way::size_of_val(&x);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #42 <https://github.com/rust-lang/rust/issues/42> for more information
= help: add `#![feature(unstable)]` 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[E0658]: use of unstable library feature `unstable`
--> $DIR/const-unstable-intrinsic.rs:26:9
|
LL | unstable_intrinsic::new_way::min_align_of_val(&x);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #42 <https://github.com/rust-lang/rust/issues/42> for more information
= help: add `#![feature(unstable)]` 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: cannot call non-const intrinsic `size_of_val` in constant functions
error: intrinsic `unstable_intrinsic::size_of_val` cannot be (indirectly) exposed to stable
--> $DIR/const-unstable-intrinsic.rs:17:9
|
LL | unstable_intrinsic::old_way::size_of_val(&x);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | unstable_intrinsic::size_of_val(&x);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval)
error: `min_align_of_val` is not yet stable as a const intrinsic
--> $DIR/const-unstable-intrinsic.rs:20:9
|
LL | unstable_intrinsic::old_way::min_align_of_val(&x);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | unstable_intrinsic::min_align_of_val(&x);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: add `#![feature(unstable)]` to the crate attributes to enable
error: intrinsic `unstable_intrinsic::new_way::size_of_val` cannot be (indirectly) exposed to stable
--> $DIR/const-unstable-intrinsic.rs:23:9
error: intrinsic `size_of_val` cannot be (indirectly) exposed to stable
--> $DIR/const-unstable-intrinsic.rs:24:9
|
LL | unstable_intrinsic::new_way::size_of_val(&x);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | size_of_val(&x);
| ^^^^^^^^^^^^^^^
|
= help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_indirect]` (but this requires team approval)
error: `min_align_of_val` is not yet stable as a const intrinsic
--> $DIR/const-unstable-intrinsic.rs:26:9
|
LL | unstable_intrinsic::new_way::min_align_of_val(&x);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: add `#![feature(unstable)]` to the crate attributes to enable
error: cannot call non-const intrinsic `size_of_val` in constant functions
--> $DIR/const-unstable-intrinsic.rs:30:9
|
LL | old_way::size_of_val(&x);
| ^^^^^^^^^^^^^^^^^^^^^^^^
= help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval)
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local)]`
--> $DIR/const-unstable-intrinsic.rs:32:9
--> $DIR/const-unstable-intrinsic.rs:26:9
|
LL | old_way::min_align_of_val(&x);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | min_align_of_val(&x);
| ^^^^^^^^^^^^^^^^^^^^
|
help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
@ -91,37 +59,22 @@ LL + #[rustc_allow_const_fn_unstable(local)]
LL | const fn const_main() {
|
error: intrinsic `new_way::size_of_val` cannot be (indirectly) exposed to stable
--> $DIR/const-unstable-intrinsic.rs:34:9
|
LL | new_way::size_of_val(&x);
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_indirect]` (but this requires team approval)
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local)]`
--> $DIR/const-unstable-intrinsic.rs:36:9
|
LL | new_way::min_align_of_val(&x);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
LL | const fn const_main() {
|
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
LL + #[rustc_allow_const_fn_unstable(local)]
LL | const fn const_main() {
|
error: cannot call non-const intrinsic `copy` in constant functions
--> $DIR/const-unstable-intrinsic.rs:74:14
error: intrinsic `copy::copy` cannot be (indirectly) exposed to stable
--> $DIR/const-unstable-intrinsic.rs:53:14
|
LL | unsafe { copy(src, dst, count) }
| ^^^^^^^^^^^^^^^^^^^^^
|
= help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval)
error: aborting due to 13 previous errors
error: intrinsic `size_of_val` cannot be (indirectly) exposed to stable
--> $DIR/const-unstable-intrinsic.rs:61:9
|
LL | super::size_of_val(src);
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval)
error: aborting due to 8 previous errors
For more information about this error, try `rustc --explain E0658`.

View File

@ -1,17 +1,21 @@
#![stable(feature = "dummy", since = "1.0.0")]
// ignore-tidy-linelength
#![feature(intrinsics, staged_api)]
#![feature(intrinsics, staged_api, rustc_attrs)]
use std::mem;
extern "rust-intrinsic" {
#[stable(feature = "dummy", since = "1.0.0")]
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
#[stable(feature = "dummy", since = "1.0.0")]
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
#[rustc_intrinsic]
const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
unimplemented!()
}
#[stable(feature = "dummy", since = "1.0.0")]
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
fn copy<T>(src: *const T, dst: *mut T, count: usize);
#[stable(feature = "dummy", since = "1.0.0")]
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
#[rustc_intrinsic]
const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
unimplemented!()
}
const COPY_ZERO: () = unsafe {

View File

@ -1,23 +1,23 @@
error[E0080]: evaluation of constant value failed
--> $DIR/copy-intrinsic.rs:30:5
--> $DIR/copy-intrinsic.rs:34:5
|
LL | copy_nonoverlapping(0x100 as *const i32, dangle, 1);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got 0x100[noalloc] which is a dangling pointer (it has no provenance)
error[E0080]: evaluation of constant value failed
--> $DIR/copy-intrinsic.rs:39:5
--> $DIR/copy-intrinsic.rs:43:5
|
LL | copy_nonoverlapping(dangle, 0x100 as *mut i32, 1);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got ALLOC0+0x28 which is at or beyond the end of the allocation of size 4 bytes
error[E0080]: evaluation of constant value failed
--> $DIR/copy-intrinsic.rs:46:5
--> $DIR/copy-intrinsic.rs:50:5
|
LL | copy(&x, &mut y, 1usize << (mem::size_of::<usize>() * 8 - 1));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow computing total size of `copy`
error[E0080]: evaluation of constant value failed
--> $DIR/copy-intrinsic.rs:52:5
--> $DIR/copy-intrinsic.rs:56:5
|
LL | copy_nonoverlapping(&x, &mut y, 1usize << (mem::size_of::<usize>() * 8 - 1));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow computing total size of `copy_nonoverlapping`

View File

@ -1,5 +1,4 @@
#![feature(core_intrinsics)]
#![feature(const_intrinsic_raw_eq)]
const RAW_EQ_PADDING: bool = unsafe {
std::intrinsics::raw_eq(&(1_u8, 2_u16), &(1_u8, 2_u16))

View File

@ -1,11 +1,11 @@
error[E0080]: evaluation of constant value failed
--> $DIR/intrinsic-raw_eq-const-bad.rs:5:5
--> $DIR/intrinsic-raw_eq-const-bad.rs:4:5
|
LL | std::intrinsics::raw_eq(&(1_u8, 2_u16), &(1_u8, 2_u16))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at ALLOC0[0x0..0x4], but memory is uninitialized at [0x1..0x2], and this operation requires initialized memory
error[E0080]: evaluation of constant value failed
--> $DIR/intrinsic-raw_eq-const-bad.rs:11:5
--> $DIR/intrinsic-raw_eq-const-bad.rs:10:5
|
LL | std::intrinsics::raw_eq(&(&0), &(&1))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
@ -14,7 +14,7 @@ LL | std::intrinsics::raw_eq(&(&0), &(&1))
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error[E0080]: evaluation of constant value failed
--> $DIR/intrinsic-raw_eq-const-bad.rs:19:5
--> $DIR/intrinsic-raw_eq-const-bad.rs:18:5
|
LL | std::intrinsics::raw_eq(aref, aref)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ accessing memory with alignment 1, but alignment 4 is required

View File

@ -1,7 +1,6 @@
//@ run-pass
#![feature(core_intrinsics)]
#![feature(const_intrinsic_raw_eq)]
pub fn main() {
use std::intrinsics::raw_eq;

View File

@ -7,9 +7,9 @@ LL | let _: unsafe extern "rust-intrinsic" fn(isize) -> usize = std::mem::tr
| expected due to this
|
= note: expected fn pointer `unsafe extern "rust-intrinsic" fn(isize) -> usize`
found fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}`
found fn item `unsafe fn(_) -> _ {std::intrinsics::transmute::<_, _>}`
error[E0606]: casting `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}` as `unsafe extern "rust-intrinsic" fn(isize) -> usize` is invalid
error[E0606]: casting `unsafe fn(_) -> _ {std::intrinsics::transmute::<_, _>}` as `unsafe extern "rust-intrinsic" fn(isize) -> usize` is invalid
--> $DIR/reify-intrinsic.rs:11:13
|
LL | let _ = std::mem::transmute as unsafe extern "rust-intrinsic" fn(isize) -> usize;

View File

@ -21,11 +21,12 @@ enum Foo {
Bar,
}
extern "rust-intrinsic" {
#[stable(feature = "intrinsics_for_test", since = "3.3.3")]
#[rustc_const_stable(feature = "intrinsics_for_test", since = "3.3.3")]
#[rustc_safe_intrinsic]
fn size_of<T>() -> usize;
#[stable(feature = "intrinsics_for_test", since = "3.3.3")]
#[rustc_const_stable(feature = "intrinsics_for_test", since = "3.3.3")]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
const fn size_of<T>() -> usize {
loop {}
}
#[lang="sized"]

View File

@ -36,10 +36,4 @@ impl const Bar for Foo {
pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 }
//~^ ERROR function has missing const stability attribute
extern "rust-intrinsic" {
#[stable(feature = "stable", since = "1.0.0")]
#[rustc_const_stable_indirect]
pub fn min_align_of_val<T>(x: *const T) -> usize;
}
fn main() {}

View File

@ -18,10 +18,12 @@ trait Sized {}
trait Copy {}
impl Copy for bool {}
extern "rust-intrinsic" {
#[stable(feature = "test", since = "1.0.0")]
#[rustc_const_stable(feature = "test", since = "1.0.0")]
fn unreachable() -> !;
#[stable(feature = "test", since = "1.0.0")]
#[rustc_const_stable(feature = "test", since = "1.0.0")]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
const unsafe fn unreachable() -> ! {
loop {}
}
#[rustc_builtin_macro]

View File

@ -16,10 +16,12 @@ trait Sized {}
trait Copy {}
impl Copy for bool {}
extern "rust-intrinsic" {
#[stable(feature = "test", since = "1.0.0")]
#[rustc_const_stable(feature = "test", since = "1.0.0")]
fn unreachable() -> !;
#[stable(feature = "test", since = "1.0.0")]
#[rustc_const_stable(feature = "test", since = "1.0.0")]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
const unsafe fn unreachable() -> ! {
loop {}
}
#[rustc_builtin_macro]