attr: Handle `rustc_const_{un}stable` properly
Since extern functions cannot be marked as const (they take no qualifiers) but some intrinsics are const, while still being `extern "rust-intrinsic", we need to be able to handle the `#[rustc_const_stable]` and `#[rustc_const_unstable]` attribute. Technically, this simply indicates that a certain intrinsic is constant and can be used in const contexts, such as `size_of` or `offset`. We also need to mark all const intrinsics with `rustc_const_stable` in the testsuite.
This commit is contained in:
parent
7beea479c5
commit
084f959076
|
@ -235,11 +235,48 @@ ConstChecker::check_function_call (HirId fn_id, Location locus)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto maybe_fn = mappings.lookup_hir_item (fn_id);
|
auto maybe_fn = mappings.lookup_hir_item (fn_id);
|
||||||
if (!maybe_fn || maybe_fn->get_item_kind () != Item::ItemKind::Function)
|
if (maybe_fn && maybe_fn->get_item_kind () != Item::ItemKind::Function)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto fn = static_cast<Function *> (maybe_fn);
|
// There are const extern functions (intrinsics)
|
||||||
if (!fn->get_qualifiers ().is_const ())
|
// TODO: Should we check the ABI is only "rust intrinsics"? Is that handled
|
||||||
|
// elsewhere?
|
||||||
|
HirId parent_block;
|
||||||
|
auto maybe_extern_item
|
||||||
|
= mappings.lookup_hir_extern_item (fn_id, &parent_block);
|
||||||
|
if (maybe_extern_item
|
||||||
|
&& maybe_extern_item->get_extern_kind ()
|
||||||
|
!= ExternalItem::ExternKind::Function)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto is_error = false;
|
||||||
|
if (maybe_fn)
|
||||||
|
{
|
||||||
|
auto fn = static_cast<Function *> (maybe_fn);
|
||||||
|
if (!fn->get_qualifiers ().is_const ())
|
||||||
|
is_error = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maybe_extern_item)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
auto fn = static_cast<ExternalFunctionItem *> (maybe_extern_item);
|
||||||
|
auto is_const_extern = std::any_of (
|
||||||
|
fn->get_outer_attrs ().begin (), fn->get_outer_attrs ().end (),
|
||||||
|
[] (const AST::Attribute &attr) {
|
||||||
|
// `starts_with` in C++11...
|
||||||
|
// FIXME: Is it really how we want to handle `rustc_const_stable`
|
||||||
|
// and `rustc_const_unstable`?
|
||||||
|
// TODO: Add these attributes to the attribute check and handle
|
||||||
|
// `stable` and `unstable` as well
|
||||||
|
return attr.get_path ().as_string ().rfind ("rustc_const_", 0) == 0;
|
||||||
|
});
|
||||||
|
if (!is_const_extern)
|
||||||
|
is_error = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_error)
|
||||||
rust_error_at (locus, "only functions marked as %<const%> are allowed to "
|
rust_error_at (locus, "only functions marked as %<const%> are allowed to "
|
||||||
"be called from constant contexts");
|
"be called from constant contexts");
|
||||||
}
|
}
|
||||||
|
@ -522,6 +559,9 @@ ConstChecker::visit (Function &function)
|
||||||
if (const_fn)
|
if (const_fn)
|
||||||
const_context.enter (function.get_mappings ().get_hirid ());
|
const_context.enter (function.get_mappings ().get_hirid ());
|
||||||
|
|
||||||
|
for (auto ¶m : function.get_function_params ())
|
||||||
|
param.get_type ()->accept_vis (*this);
|
||||||
|
|
||||||
function.get_definition ()->accept_vis (*this);
|
function.get_definition ()->accept_vis (*this);
|
||||||
|
|
||||||
if (const_fn)
|
if (const_fn)
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
// { dg-additional-options "-w" }
|
||||||
|
|
||||||
|
mod intrinsics {
|
||||||
|
extern "rust-intrinsic" {
|
||||||
|
pub fn wrapping_add<T>(a: T, b: T) -> T;
|
||||||
|
pub fn rotate_left<T>(a: T, b: T) -> T;
|
||||||
|
pub fn rotate_right<T>(a: T, b: T) -> T;
|
||||||
|
pub fn offset<T>(ptr: *const T, count: isize) -> *const T;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod mem {
|
||||||
|
extern "rust-intrinsic" {
|
||||||
|
#[rustc_const_stable(feature = "const_transmute", since = "1.46.0")]
|
||||||
|
pub fn transmute<T, U>(_: T) -> U;
|
||||||
|
pub fn size_of<T>() -> usize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_uint {
|
||||||
|
($($ty:ident = $lang:literal),*) => {
|
||||||
|
$(
|
||||||
|
impl $ty {
|
||||||
|
pub fn wrapping_add(self, rhs: Self) -> Self {
|
||||||
|
// intrinsics::wrapping_add(self, rhs)
|
||||||
|
self + rhs
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rotate_left(self, n: u32) -> Self {
|
||||||
|
unsafe {
|
||||||
|
intrinsics::rotate_left(self, n as Self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rotate_right(self, n: u32) -> Self {
|
||||||
|
unsafe {
|
||||||
|
intrinsics::rotate_right(self, n as Self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_le(self) -> Self {
|
||||||
|
#[cfg(target_endian = "little")]
|
||||||
|
{
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn from_le_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
|
||||||
|
// { dg-error "only functions marked as .const. are allowed to be called from constant contexts" "" { target *-*-* } .-1 }
|
||||||
|
Self::from_le(Self::from_ne_bytes(bytes))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn from_le(x: Self) -> Self {
|
||||||
|
#[cfg(target_endian = "little")]
|
||||||
|
{
|
||||||
|
x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
|
||||||
|
// { dg-error "only functions marked as .const. are allowed to be called from constant contexts" "" { target *-*-* } .-1 }
|
||||||
|
unsafe { mem::transmute(bytes) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_uint!(
|
||||||
|
u8 = "u8",
|
||||||
|
u16 = "u16",
|
||||||
|
u32 = "u32",
|
||||||
|
u64 = "u64",
|
||||||
|
u128 = "u128",
|
||||||
|
usize = "usize"
|
||||||
|
);
|
|
@ -1,4 +1,5 @@
|
||||||
extern "rust-intrinsic" {
|
extern "rust-intrinsic" {
|
||||||
|
#[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
|
||||||
pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
|
pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ extern "C" {
|
||||||
|
|
||||||
mod intrinsics {
|
mod intrinsics {
|
||||||
extern "rust-intrinsic" {
|
extern "rust-intrinsic" {
|
||||||
|
#[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
|
||||||
pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
|
pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// { dg-additional-options "-w" }
|
// { dg-additional-options "-w" }
|
||||||
extern "rust-intrinsic" {
|
extern "rust-intrinsic" {
|
||||||
|
#[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
|
||||||
pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
|
pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,22 @@
|
||||||
// { dg-additional-options "-w" }
|
// { dg-additional-options "-w" }
|
||||||
mod intrinsics {
|
mod intrinsics {
|
||||||
extern "rust-intrinsic" {
|
extern "rust-intrinsic" {
|
||||||
|
#[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")]
|
||||||
pub fn wrapping_add<T>(a: T, b: T) -> T;
|
pub fn wrapping_add<T>(a: T, b: T) -> T;
|
||||||
|
#[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")]
|
||||||
pub fn rotate_left<T>(a: T, b: T) -> T;
|
pub fn rotate_left<T>(a: T, b: T) -> T;
|
||||||
|
#[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")]
|
||||||
pub fn rotate_right<T>(a: T, b: T) -> T;
|
pub fn rotate_right<T>(a: T, b: T) -> T;
|
||||||
|
#[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
|
||||||
pub fn offset<T>(ptr: *const T, count: isize) -> *const T;
|
pub fn offset<T>(ptr: *const T, count: isize) -> *const T;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mod mem {
|
mod mem {
|
||||||
extern "rust-intrinsic" {
|
extern "rust-intrinsic" {
|
||||||
|
#[rustc_const_stable(feature = "const_transmute", since = "1.46.0")]
|
||||||
fn transmute<T, U>(_: T) -> U;
|
fn transmute<T, U>(_: T) -> U;
|
||||||
|
#[rustc_const_stable(feature = "const_size_of", since = "1.40.0")]
|
||||||
fn size_of<T>() -> usize;
|
fn size_of<T>() -> usize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// { dg-additional-options "-w" }
|
// { dg-additional-options "-w" }
|
||||||
extern "rust-intrinsic" {
|
extern "rust-intrinsic" {
|
||||||
|
#[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
|
||||||
pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
|
pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// { dg-additional-options "-w" }
|
// { dg-additional-options "-w" }
|
||||||
extern "rust-intrinsic" {
|
extern "rust-intrinsic" {
|
||||||
|
#[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
|
||||||
pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
|
pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// { dg-additional-options "-w" }
|
// { dg-additional-options "-w" }
|
||||||
// { dg-output "slice_access=3\n" }
|
// { dg-output "slice_access=3\n" }
|
||||||
extern "rust-intrinsic" {
|
extern "rust-intrinsic" {
|
||||||
|
#[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
|
||||||
fn offset<T>(dst: *const T, offset: isize) -> *const T;
|
fn offset<T>(dst: *const T, offset: isize) -> *const T;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// { dg-output "" }
|
// { dg-output "" }
|
||||||
mod intrinsics {
|
mod intrinsics {
|
||||||
extern "rust-intrinsic" {
|
extern "rust-intrinsic" {
|
||||||
|
#[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
|
||||||
pub fn offset<T>(ptr: *const T, count: isize) -> *const T;
|
pub fn offset<T>(ptr: *const T, count: isize) -> *const T;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// { dg-additional-options "-w" }
|
// { dg-additional-options "-w" }
|
||||||
extern "rust-intrinsic" {
|
extern "rust-intrinsic" {
|
||||||
|
#[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
|
||||||
pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
|
pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// { dg-additional-options "-w" }
|
// { dg-additional-options "-w" }
|
||||||
extern "rust-intrinsic" {
|
extern "rust-intrinsic" {
|
||||||
|
#[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
|
||||||
pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
|
pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// { dg-output "t1sz=5 t2sz=10" }
|
// { dg-output "t1sz=5 t2sz=10" }
|
||||||
mod mem {
|
mod mem {
|
||||||
extern "rust-intrinsic" {
|
extern "rust-intrinsic" {
|
||||||
|
#[rustc_const_stable(feature = "const_transmute", since = "1.46.0")]
|
||||||
fn transmute<T, U>(_: T) -> U;
|
fn transmute<T, U>(_: T) -> U;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue