Stop backends from needing to support nullary intrinsics
This commit is contained in:
@@ -660,7 +660,7 @@ pub mod intrinsics {
|
||||
#[rustc_intrinsic]
|
||||
pub unsafe fn ctlz_nonzero<T>(x: T) -> u32;
|
||||
#[rustc_intrinsic]
|
||||
pub fn needs_drop<T: ?::Sized>() -> bool;
|
||||
pub const fn needs_drop<T: ?::Sized>() -> bool;
|
||||
#[rustc_intrinsic]
|
||||
pub fn bitreverse<T>(x: T) -> T;
|
||||
#[rustc_intrinsic]
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
#![feature(no_core, lang_items, never_type, linkage, extern_types, thread_local, repr_simd)]
|
||||
#![feature(
|
||||
no_core,
|
||||
lang_items,
|
||||
never_type,
|
||||
linkage,
|
||||
extern_types,
|
||||
thread_local,
|
||||
repr_simd,
|
||||
rustc_private
|
||||
)]
|
||||
#![no_core]
|
||||
#![allow(dead_code, non_camel_case_types, internal_features)]
|
||||
|
||||
@@ -207,10 +216,14 @@ fn main() {
|
||||
assert_eq!(intrinsics::align_of::<u16>() as u8, 2);
|
||||
assert_eq!(intrinsics::align_of_val(&a) as u8, intrinsics::align_of::<&str>() as u8);
|
||||
|
||||
assert!(!intrinsics::needs_drop::<u8>());
|
||||
assert!(!intrinsics::needs_drop::<[u8]>());
|
||||
assert!(intrinsics::needs_drop::<NoisyDrop>());
|
||||
assert!(intrinsics::needs_drop::<NoisyDropUnsized>());
|
||||
let u8_needs_drop = const { intrinsics::needs_drop::<u8>() };
|
||||
assert!(!u8_needs_drop);
|
||||
let slice_needs_drop = const { intrinsics::needs_drop::<[u8]>() };
|
||||
assert!(!slice_needs_drop);
|
||||
let noisy_drop = const { intrinsics::needs_drop::<NoisyDrop>() };
|
||||
assert!(noisy_drop);
|
||||
let noisy_unsized_drop = const { intrinsics::needs_drop::<NoisyDropUnsized>() };
|
||||
assert!(noisy_unsized_drop);
|
||||
|
||||
Unique { pointer: NonNull(1 as *mut &str), _marker: PhantomData } as Unique<dyn SomeTrait>;
|
||||
|
||||
|
||||
@@ -812,21 +812,6 @@ fn codegen_regular_intrinsic_call<'tcx>(
|
||||
dest.write_cvalue(fx, val);
|
||||
}
|
||||
|
||||
sym::needs_drop | sym::type_id | sym::type_name | sym::variant_count => {
|
||||
intrinsic_args!(fx, args => (); intrinsic);
|
||||
|
||||
let const_val = fx
|
||||
.tcx
|
||||
.const_eval_instance(
|
||||
ty::TypingEnv::fully_monomorphized(),
|
||||
instance,
|
||||
source_info.span,
|
||||
)
|
||||
.unwrap();
|
||||
let val = crate::constant::codegen_const_value(fx, const_val, ret.layout().ty);
|
||||
ret.write_cvalue(fx, val);
|
||||
}
|
||||
|
||||
sym::ptr_offset_from | sym::ptr_offset_from_unsigned => {
|
||||
intrinsic_args!(fx, args => (ptr, base); intrinsic);
|
||||
let ptr = ptr.load_scalar(fx);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
)]
|
||||
#![no_core]
|
||||
#![allow(dead_code, internal_features, non_camel_case_types)]
|
||||
#![rustfmt::skip]
|
||||
|
||||
extern crate mini_core;
|
||||
|
||||
@@ -197,10 +198,10 @@ fn main() {
|
||||
assert_eq!(intrinsics::align_of::<u16>() as u8, 2);
|
||||
assert_eq!(intrinsics::align_of_val(&a) as u8, intrinsics::align_of::<&str>() as u8);
|
||||
|
||||
assert!(!intrinsics::needs_drop::<u8>());
|
||||
assert!(!intrinsics::needs_drop::<[u8]>());
|
||||
assert!(intrinsics::needs_drop::<NoisyDrop>());
|
||||
assert!(intrinsics::needs_drop::<NoisyDropUnsized>());
|
||||
assert!(!const { intrinsics::needs_drop::<u8>() });
|
||||
assert!(!const { intrinsics::needs_drop::<[u8]>() });
|
||||
assert!(const { intrinsics::needs_drop::<NoisyDrop>() });
|
||||
assert!(const { intrinsics::needs_drop::<NoisyDropUnsized>() });
|
||||
|
||||
Unique {
|
||||
pointer: 0 as *const &str,
|
||||
|
||||
@@ -150,10 +150,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
}
|
||||
value
|
||||
}
|
||||
sym::needs_drop | sym::type_id | sym::type_name | sym::variant_count => {
|
||||
let value = bx.tcx().const_eval_instance(bx.typing_env(), instance, span).unwrap();
|
||||
OperandRef::from_const(bx, value, result.layout.ty).immediate_or_packed_pair(bx)
|
||||
}
|
||||
sym::arith_offset => {
|
||||
let ty = fn_args.type_at(0);
|
||||
let layout = bx.layout_of(ty);
|
||||
|
||||
@@ -742,7 +742,7 @@ impl TypeId {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_type_id", issue = "77125")]
|
||||
pub const fn of<T: ?Sized + 'static>() -> TypeId {
|
||||
let t: u128 = intrinsics::type_id::<T>();
|
||||
let t: u128 = const { intrinsics::type_id::<T>() };
|
||||
let t1 = (t >> 64) as u64;
|
||||
let t2 = t as u64;
|
||||
|
||||
@@ -824,7 +824,7 @@ impl fmt::Debug for TypeId {
|
||||
#[stable(feature = "type_name", since = "1.38.0")]
|
||||
#[rustc_const_unstable(feature = "const_type_name", issue = "63084")]
|
||||
pub const fn type_name<T: ?Sized>() -> &'static str {
|
||||
intrinsics::type_name::<T>()
|
||||
const { intrinsics::type_name::<T>() }
|
||||
}
|
||||
|
||||
/// Returns the type name of the pointed-to value as a string slice.
|
||||
|
||||
@@ -839,10 +839,10 @@ pub const unsafe fn transmute_unchecked<Src, Dst>(src: Src) -> Dst;
|
||||
/// If the actual type neither requires drop glue nor implements
|
||||
/// `Copy`, then the return value of this function is unspecified.
|
||||
///
|
||||
/// 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.
|
||||
/// Note that, unlike most intrinsics, this can only be called at compile-time
|
||||
/// as backends do not have an implementation for it. The only caller (its
|
||||
/// stable counterpart), wraps this intrinsic call in a `const` block so that
|
||||
/// backends only see an evaluated constant.
|
||||
///
|
||||
/// The stabilized version of this intrinsic is [`mem::needs_drop`](crate::mem::needs_drop).
|
||||
#[rustc_intrinsic_const_stable_indirect]
|
||||
@@ -2655,10 +2655,10 @@ pub const fn align_of<T>() -> usize;
|
||||
/// Returns the number of variants of the type `T` cast to a `usize`;
|
||||
/// if `T` has no variants, returns `0`. Uninhabited variants will be counted.
|
||||
///
|
||||
/// 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.
|
||||
/// Note that, unlike most intrinsics, this can only be called at compile-time
|
||||
/// as backends do not have an implementation for it. The only caller (its
|
||||
/// stable counterpart), wraps this intrinsic call in a `const` block so that
|
||||
/// backends only see an evaluated constant.
|
||||
///
|
||||
/// The to-be-stabilized version of this intrinsic is [`crate::mem::variant_count`].
|
||||
#[rustc_nounwind]
|
||||
@@ -2694,10 +2694,10 @@ pub const unsafe fn align_of_val<T: ?Sized>(ptr: *const T) -> usize;
|
||||
|
||||
/// Gets a static string slice containing the name of a type.
|
||||
///
|
||||
/// 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.
|
||||
/// Note that, unlike most intrinsics, this can only be called at compile-time
|
||||
/// as backends do not have an implementation for it. The only caller (its
|
||||
/// stable counterpart), wraps this intrinsic call in a `const` block so that
|
||||
/// backends only see an evaluated constant.
|
||||
///
|
||||
/// The stabilized version of this intrinsic is [`core::any::type_name`].
|
||||
#[rustc_nounwind]
|
||||
@@ -2709,10 +2709,10 @@ pub const fn type_name<T: ?Sized>() -> &'static str;
|
||||
/// function will return the same value for a type regardless of whichever
|
||||
/// crate it is invoked in.
|
||||
///
|
||||
/// 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.
|
||||
/// Note that, unlike most intrinsics, this can only be called at compile-time
|
||||
/// as backends do not have an implementation for it. The only caller (its
|
||||
/// stable counterpart), wraps this intrinsic call in a `const` block so that
|
||||
/// backends only see an evaluated constant.
|
||||
///
|
||||
/// The stabilized version of this intrinsic is [`core::any::TypeId::of`].
|
||||
#[rustc_nounwind]
|
||||
|
||||
@@ -616,7 +616,7 @@ pub const unsafe fn align_of_val_raw<T: ?Sized>(val: *const T) -> usize {
|
||||
#[rustc_const_stable(feature = "const_mem_needs_drop", since = "1.36.0")]
|
||||
#[rustc_diagnostic_item = "needs_drop"]
|
||||
pub const fn needs_drop<T: ?Sized>() -> bool {
|
||||
intrinsics::needs_drop::<T>()
|
||||
const { intrinsics::needs_drop::<T>() }
|
||||
}
|
||||
|
||||
/// Returns the value of type `T` represented by the all-zero byte-pattern.
|
||||
@@ -1215,7 +1215,7 @@ pub const fn discriminant<T>(v: &T) -> Discriminant<T> {
|
||||
#[rustc_const_unstable(feature = "variant_count", issue = "73662")]
|
||||
#[rustc_diagnostic_item = "mem_variant_count"]
|
||||
pub const fn variant_count<T>() -> usize {
|
||||
intrinsics::variant_count::<T>()
|
||||
const { intrinsics::variant_count::<T>() }
|
||||
}
|
||||
|
||||
/// Provides associated constants for various useful properties of types,
|
||||
|
||||
@@ -19,12 +19,6 @@ extern crate rustc_driver;
|
||||
extern crate rustc_interface;
|
||||
extern crate stable_mir;
|
||||
|
||||
use stable_mir::crate_def::CrateDef;
|
||||
use stable_mir::mir::alloc::GlobalAlloc;
|
||||
use stable_mir::mir::mono::{Instance, InstanceKind, StaticDef};
|
||||
use stable_mir::mir::{Body, TerminatorKind};
|
||||
use stable_mir::ty::{Allocation, ConstantKind, RigidTy, TyKind};
|
||||
use stable_mir::{CrateItem, CrateItems, ItemKind};
|
||||
use std::ascii::Char;
|
||||
use std::assert_matches::assert_matches;
|
||||
use std::cmp::{max, min};
|
||||
@@ -33,6 +27,13 @@ use std::ffi::CStr;
|
||||
use std::io::Write;
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
use stable_mir::crate_def::CrateDef;
|
||||
use stable_mir::mir::Body;
|
||||
use stable_mir::mir::alloc::GlobalAlloc;
|
||||
use stable_mir::mir::mono::{Instance, StaticDef};
|
||||
use stable_mir::ty::{Allocation, ConstantKind};
|
||||
use stable_mir::{CrateItem, CrateItems, ItemKind};
|
||||
|
||||
const CRATE_NAME: &str = "input";
|
||||
|
||||
/// This function uses the Stable MIR APIs to get information about the test crate.
|
||||
@@ -44,7 +45,6 @@ fn test_stable_mir() -> ControlFlow<()> {
|
||||
check_len(*get_item(&items, (ItemKind::Static, "LEN")).unwrap());
|
||||
check_cstr(*get_item(&items, (ItemKind::Static, "C_STR")).unwrap());
|
||||
check_other_consts(*get_item(&items, (ItemKind::Fn, "other_consts")).unwrap());
|
||||
check_type_id(*get_item(&items, (ItemKind::Fn, "check_type_id")).unwrap());
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
|
||||
@@ -107,7 +107,9 @@ fn check_other_consts(item: CrateItem) {
|
||||
// Instance body will force constant evaluation.
|
||||
let body = Instance::try_from(item).unwrap().body().unwrap();
|
||||
let assigns = collect_consts(&body);
|
||||
assert_eq!(assigns.len(), 8);
|
||||
assert_eq!(assigns.len(), 10);
|
||||
let mut char_id = None;
|
||||
let mut bool_id = None;
|
||||
for (name, alloc) in assigns {
|
||||
match name.as_str() {
|
||||
"_max_u128" => {
|
||||
@@ -149,35 +151,21 @@ fn check_other_consts(item: CrateItem) {
|
||||
assert_eq!(max(first, second) as u32, u32::MAX);
|
||||
assert_eq!(min(first, second), 10);
|
||||
}
|
||||
"_bool_id" => {
|
||||
bool_id = Some(alloc);
|
||||
}
|
||||
"_char_id" => {
|
||||
char_id = Some(alloc);
|
||||
}
|
||||
_ => {
|
||||
unreachable!("{name} -- {alloc:?}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Check that we can retrieve the type id of char and bool, and that they have different values.
|
||||
fn check_type_id(item: CrateItem) {
|
||||
let body = Instance::try_from(item).unwrap().body().unwrap();
|
||||
let mut ids: Vec<u128> = vec![];
|
||||
for term in body.blocks.iter().map(|bb| &bb.terminator) {
|
||||
match &term.kind {
|
||||
TerminatorKind::Call { func, destination, .. } => {
|
||||
let TyKind::RigidTy(ty) = func.ty(body.locals()).unwrap().kind() else {
|
||||
unreachable!()
|
||||
};
|
||||
let RigidTy::FnDef(def, args) = ty else { unreachable!() };
|
||||
let instance = Instance::resolve(def, &args).unwrap();
|
||||
assert_eq!(instance.kind, InstanceKind::Intrinsic);
|
||||
let dest_ty = destination.ty(body.locals()).unwrap();
|
||||
let alloc = instance.try_const_eval(dest_ty).unwrap();
|
||||
ids.push(alloc.read_uint().unwrap());
|
||||
}
|
||||
_ => { /* Do nothing */ }
|
||||
}
|
||||
}
|
||||
assert_eq!(ids.len(), 2);
|
||||
assert_ne!(ids[0], ids[1]);
|
||||
let bool_id = bool_id.unwrap();
|
||||
let char_id = char_id.unwrap();
|
||||
// FIXME(stable_mir): add `read_ptr` to `Allocation`
|
||||
assert_ne!(bool_id, char_id);
|
||||
}
|
||||
|
||||
/// Collects all the constant assignments.
|
||||
@@ -235,6 +223,7 @@ fn generate_input(path: &str) -> std::io::Result<()> {
|
||||
file,
|
||||
r#"
|
||||
#![feature(core_intrinsics)]
|
||||
#![expect(internal_features)]
|
||||
use std::intrinsics::type_id;
|
||||
|
||||
static LEN: usize = 2;
|
||||
@@ -254,11 +243,8 @@ fn generate_input(path: &str) -> std::io::Result<()> {
|
||||
let _ptr = &BAR;
|
||||
let _null_ptr: *const u8 = NULL;
|
||||
let _tuple = TUPLE;
|
||||
}}
|
||||
|
||||
fn check_type_id() {{
|
||||
let _char_id = type_id::<char>();
|
||||
let _bool_id = type_id::<bool>();
|
||||
let _char_id = const {{ type_id::<char>() }};
|
||||
let _bool_id = const {{ type_id::<bool>() }};
|
||||
}}
|
||||
|
||||
pub fn main() {{
|
||||
|
||||
Reference in New Issue
Block a user