Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 18 additions & 24 deletions compiler/rustc_const_eval/src/const_eval/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use tracing::debug;

use super::error::*;
use crate::diagnostics::{LongRunning, LongRunningWarn};
use crate::interpret::Immediate::ScalarPair;
use crate::interpret::{
self, AllocId, AllocInit, AllocRange, ConstAllocation, CtfeProvenance, FnArg, Frame,
GlobalAlloc, ImmTy, Immediate, InterpCx, InterpResult, OpTy, PlaceTy, Pointer, RangeSet,
Expand Down Expand Up @@ -699,7 +700,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
ecx.write_scalar(Scalar::from_target_usize(fields_num as u64, ecx), dest)?;
}

sym::type_id_field_representing_type => {
sym::type_id_field_representing => {
let ty = ecx.read_type_id(&args[0])?;
let variant_idx = ecx.read_target_usize(&args[1])? as usize;
let field_idx = ecx.read_target_usize(&args[2])? as usize;
Expand Down Expand Up @@ -796,6 +797,20 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
)?;
}

sym::type_id_name => {
let ty = ecx.read_type_id(&args[0])?;
ensure_monomorphic_enough(ty)?;
let name = crate::util::type_name(ecx.tcx(), ty);
let ptr = ecx.allocate_bytes_dedup(name.as_str().as_bytes())?;
ecx.write_immediate(
ScalarPair(
Scalar::from_pointer(ptr, ecx),
Scalar::from_target_usize(name.as_str().len() as u64, ecx),
),
dest,
)?;
}

sym::type_id_variant_non_exhaustive => {
let base = ecx.read_type_id(&args[0])?;

Expand Down Expand Up @@ -836,28 +851,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
ecx.write_scalar(Scalar::from_target_usize(offset, ecx), dest)?;
}

sym::field_representing_type_name => {
let frt_ty = ecx.read_type_id(&args[0])?;

let field_name = if let ty::Adt(def, args) = frt_ty.kind()
&& let Some(FieldInfo { name, .. }) =
def.field_representing_type_info(ecx.tcx.tcx, args)
{
name
} else {
span_bug!(ecx.cur_span(), "expected field representing type, got {frt_ty}")
};
let ptr = ecx.allocate_bytes_dedup(field_name.as_str().as_bytes())?;
ecx.write_immediate(
Immediate::ScalarPair(
Scalar::from_pointer(ptr, ecx),
Scalar::from_target_usize(field_name.as_str().len() as u64, ecx),
),
dest,
)?;
}

sym::field_representing_type_offset => {
sym::type_id_field_representing_field_offset => {
let frt_ty = ecx.read_type_id(&args[0])?;

let (ty, variant, field) = if let ty::Adt(def, args) = frt_ty.kind()
Expand All @@ -877,7 +871,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
ecx.write_scalar(Scalar::from_target_usize(offset, ecx), dest)?;
}

sym::field_representing_type_actual_type_id => {
sym::type_id_field_representing_outer_type_id => {
let frt_ty = ecx.read_type_id(&args[0])?;

let field_ty = if let ty::Adt(def, args) = frt_ty.kind()
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_const_eval/src/interpret/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ pub enum VarArgCompatible {

/// Directly returns an `Allocation` containing an absolute path representation of the given type.
pub(crate) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> (AllocId, u64) {
let path = crate::util::type_name(tcx, ty);
let path = crate::util::type_name_and_path(tcx, ty);
let bytes = path.into_bytes();
let len = bytes.len().try_into().unwrap();
(tcx.allocate_bytes_dedup(bytes, CTFE_ALLOC_SALT), len)
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_const_eval/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#![feature(deref_patterns)]
#![feature(slice_ptr_get)]
#![feature(trait_alias)]
#![feature(try_blocks)]
#![feature(unqualified_local_imports)]
#![feature(yeet_expr)]
#![warn(unqualified_local_imports)]
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_const_eval/src/util/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub use self::alignment::{most_packed_projection, place_unalignment};
pub use self::check_validity_requirement::check_validity_requirement;
pub(crate) use self::check_validity_requirement::validate_scalar_in_layout;
pub use self::compare_types::{relate_types, sub_types};
pub use self::type_name::type_name;
pub use self::type_name::{type_name, type_name_and_path};

/// Classify whether an operator is "left-homogeneous", i.e., the LHS has the
/// same type as the result.
Expand Down
36 changes: 34 additions & 2 deletions compiler/rustc_const_eval/src/util/type_name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use rustc_data_structures::intern::Interned;
use rustc_hir::def_id::{CrateNum, DefId};
use rustc_hir::definitions::DisambiguatedDefPathData;
use rustc_middle::ty::print::{PrettyPrinter, PrintError, Printer};
use rustc_middle::ty::{self, GenericArg, Ty, TyCtxt};
use rustc_middle::ty::{self, FieldInfo, GenericArg, Ty, TyCtxt};
use rustc_span::bug;

struct TypeNamePrinter<'tcx> {
Expand Down Expand Up @@ -213,8 +213,40 @@ impl Write for TypeNamePrinter<'_> {
}
}

pub fn type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> String {
pub fn type_name_and_path<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> String {
let mut p = TypeNamePrinter { tcx, path: String::new() };
p.print_type(ty).unwrap();
p.path
}

pub fn type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> String {
let mut s = String::new();

try {
match *ty.kind() {
ty::Adt(def, args)
if let Some(FieldInfo { name, .. }) =
def.field_representing_type_info(tcx, args) =>
{
write!(s, "{name}")?
}
ty::Adt(def, _) => write!(s, "{}", tcx.item_name(def.did()))?,
ty::Dynamic(data, _) => {
let trait_def_id = data
.iter()
.map(|b| b.skip_binder())
.find_map(|pred| match pred {
ty::ExistentialPredicate::Trait(tr) => Some(tr.def_id),
ty::ExistentialPredicate::AutoTrait(def_id) => Some(def_id),
_ => None,
})
.expect("There should be a principal trait");
write!(s, "{}", tcx.item_name(trait_def_id))?;
}
_ => (),
Comment thread
oli-obk marked this conversation as resolved.
Resolved
}
}
.unwrap();

s
}
16 changes: 8 additions & 8 deletions compiler/rustc_hir_analysis/src/check/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,6 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi
| sym::fadd_algebraic
| sym::fdiv_algebraic
| sym::field_offset
| sym::field_representing_type_actual_type_id
| sym::field_representing_type_name
| sym::field_representing_type_offset
| sym::floor
| sym::fma
| sym::fmul_algebraic
Expand Down Expand Up @@ -173,11 +170,14 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi
| sym::type_id_array_len
| sym::type_id_element_ty
| sym::type_id_eq
| sym::type_id_field_representing_type
| sym::type_id_field_representing
| sym::type_id_field_representing_field_offset
| sym::type_id_field_representing_outer_type_id
| sym::type_id_fields
| sym::type_id_function_ptr
| sym::type_id_generics
| sym::type_id_is_signed
| sym::type_id_name
| sym::type_id_non_exhaustive
| sym::type_id_points_mutably
| sym::type_id_points_to
Expand Down Expand Up @@ -294,7 +294,7 @@ pub(crate) fn check_intrinsic_type(
sym::type_id_array_len => (0, 0, vec![type_id_ty()], tcx.types.usize),
sym::type_id_element_ty => (0, 0, vec![type_id_ty()], Ty::new_option(tcx, type_id_ty())),
sym::type_id_eq => (0, 0, vec![type_id_ty(), type_id_ty()], tcx.types.bool),
sym::type_id_field_representing_type => {
sym::type_id_field_representing => {
(0, 0, vec![type_id_ty(), tcx.types.usize, tcx.types.usize], type_id_ty())
}
sym::type_id_fields => (0, 0, vec![type_id_ty(), tcx.types.usize], tcx.types.usize),
Expand Down Expand Up @@ -339,9 +339,9 @@ pub(crate) fn check_intrinsic_type(
vec![type_id_ty()],
tcx.type_of(tcx.lang_items().type_struct().unwrap()).no_bound_vars().unwrap(),
),
sym::field_representing_type_actual_type_id => (0, 0, vec![type_id_ty()], type_id_ty()),
sym::field_representing_type_name => (0, 0, vec![type_id_ty()], Ty::new_static_str(tcx)),
sym::field_representing_type_offset => (0, 0, vec![type_id_ty()], tcx.types.usize),
sym::type_id_field_representing_outer_type_id => (0, 0, vec![type_id_ty()], type_id_ty()),
sym::type_id_field_representing_field_offset => (0, 0, vec![type_id_ty()], tcx.types.usize),
sym::type_id_name => (0, 0, vec![type_id_ty()], Ty::new_static_str(tcx)),
sym::type_id_non_exhaustive => (0, 0, vec![type_id_ty()], tcx.types.bool),
sym::type_id_generics => (
0,
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -994,9 +994,6 @@ symbols! {
field_offset,
field_projections,
field_representing_type,
field_representing_type_actual_type_id,
field_representing_type_name,
field_representing_type_offset,
field_representing_type_raw,
field_type,
fields,
Expand Down Expand Up @@ -2209,11 +2206,14 @@ symbols! {
type_id_array_len,
type_id_element_ty,
type_id_eq,
type_id_field_representing_type,
type_id_field_representing,
type_id_field_representing_field_offset,
type_id_field_representing_outer_type_id,
type_id_fields,
type_id_function_ptr,
type_id_generics,
type_id_is_signed,
type_id_name,
type_id_non_exhaustive,
type_id_points_mutably,
type_id_points_to,
Expand Down
32 changes: 0 additions & 32 deletions library/core/src/intrinsics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2988,38 +2988,6 @@ pub const unsafe fn align_of_val<T: ?Sized>(ptr: *const T) -> usize;
#[rustc_comptime]
pub fn type_name<T: ?Sized>() -> &'static str;

/// Gets the actual field `TypeId` of the [`FieldRepresentingType`]'s `TypeId`.
///
/// The more user-friendly version of this intrinsic is [`core::mem::type_info::FieldId::type_id`].
///
/// [`FieldRepresentingType`]: crate::field::FieldRepresentingType
#[rustc_intrinsic]
#[unstable(feature = "core_intrinsics", issue = "none")]
#[rustc_comptime]
pub fn field_representing_type_actual_type_id(
_frt_type_id: crate::any::TypeId,
) -> crate::any::TypeId;

/// Gets the name of the field represented by the [`FieldRepresentingType`]'s `TypeId`.
///
/// The more user-friendly version of this intrinsic is [`core::mem::type_info::FieldId::name`].
///
/// [`FieldRepresentingType`]: crate::field::FieldRepresentingType
#[rustc_intrinsic]
#[unstable(feature = "core_intrinsics", issue = "none")]
#[rustc_comptime]
pub fn field_representing_type_name(_frt_type_id: crate::any::TypeId) -> &'static str;

/// Gets the name of the field represented by the [`FieldRepresentingType`]'s `TypeId`.
///
/// The more user-friendly version of this intrinsic is [`core::mem::type_info::FieldId::name`].
///
/// [`FieldRepresentingType`]: crate::field::FieldRepresentingType
#[rustc_intrinsic]
#[unstable(feature = "core_intrinsics", issue = "none")]
#[rustc_comptime]
pub fn field_representing_type_offset(_frt_type_id: crate::any::TypeId) -> usize;

/// Lowers in MIR to `Rvalue::Aggregate` with `AggregateKind::RawPtr`.
///
/// This is used to implement functions like `slice::from_raw_parts_mut` and
Expand Down
33 changes: 32 additions & 1 deletion library/core/src/intrinsics/reflection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,12 +160,34 @@ pub fn type_id_generics(_id: crate::any::TypeId) -> &'static [crate::mem::type_i
#[rustc_intrinsic]
#[unstable(feature = "core_intrinsics", issue = "none")]
#[rustc_comptime]
pub fn type_id_field_representing_type(
pub fn type_id_field_representing(
_id: crate::any::TypeId,
_variant_index: usize,
_field_index: usize,
) -> crate::any::TypeId;

/// Gets the actual field `TypeId` of the [`FieldRepresentingType`]'s `TypeId`.
///
/// The more user-friendly version of this intrinsic is [`core::mem::type_info::FieldId::type_id`].
///
/// [`FieldRepresentingType`]: crate::field::FieldRepresentingType
#[rustc_intrinsic]
#[unstable(feature = "core_intrinsics", issue = "none")]
#[rustc_comptime]
pub fn type_id_field_representing_outer_type_id(
_frt_type_id: crate::any::TypeId,
) -> crate::any::TypeId;

/// Gets the name of the field represented by the [`FieldRepresentingType`]'s `TypeId`.
///
/// The more user-friendly version of this intrinsic is [`core::mem::type_info::FieldId::name`].
///
/// [`FieldRepresentingType`]: crate::field::FieldRepresentingType
#[rustc_intrinsic]
#[unstable(feature = "core_intrinsics", issue = "none")]
#[rustc_comptime]
pub fn type_id_field_representing_field_offset(_frt_type_id: crate::any::TypeId) -> usize;

/// Given a `TypeId` that represents a pointer this returns the `TypeId` which that pointer
/// points to. When called on anything else this returns None.
///
Expand All @@ -192,3 +214,12 @@ pub fn type_id_points_mutably(_id: crate::any::TypeId) -> bool;
#[unstable(feature = "core_intrinsics", issue = "none")]
#[rustc_comptime]
pub fn type_id_function_ptr(_type_id: crate::any::TypeId) -> Option<crate::mem::type_info::FnPtr>;

/// Returns a non empty string when given a `TypeId` which represents a named
/// item such as struct, enum or trait. Otherwise returns an empty string.
///
/// The more user-friendly version of this intrinsic is [`core::any::TypeId::name`].
#[rustc_intrinsic]
#[unstable(feature = "core_intrinsics", issue = "none")]
#[rustc_comptime]
pub fn type_id_name(_type_id: crate::any::TypeId) -> &'static str;
34 changes: 30 additions & 4 deletions library/core/src/mem/type_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ pub enum TypeKind {
/// FIXME(#146922): add all the common types
/// non exhaustive list:
/// - Never
/// - Type (type alias)
Other,
}

Expand Down Expand Up @@ -551,7 +552,7 @@ impl TypeId {
#[rustc_comptime]
pub fn field(self, variant_index: usize, field_index: usize) -> FieldId {
FieldId {
frt_type_id: intrinsics::reflection::type_id_field_representing_type(
frt_type_id: intrinsics::reflection::type_id_field_representing(
self,
variant_index,
field_index,
Expand Down Expand Up @@ -656,6 +657,31 @@ impl TypeId {
pub fn function_ptr(self) -> Option<FnPtr> {
intrinsics::reflection::type_id_function_ptr(self)
}

/// Returns a non empty string when given a `TypeId` which represents a named item such
Comment thread
oli-obk marked this conversation as resolved.
Resolved
/// as struct, enum or trait. Otherwise returns an empty string.
/// ```
/// #![feature(type_info)]
/// # use std::any::TypeId;
///
/// struct Kitty;
/// enum Color {}
/// trait Cute {}
///
/// assert_eq!(const { TypeId::of::<Kitty>().name() },"Kitty");
/// assert_eq!(const { TypeId::of::<Vec<Kitty>>().name() },"Vec");
/// assert_eq!(const { TypeId::of::<Color>().name() }, "Color");
/// assert_eq!(const { TypeId::of::<dyn Cute>().name() }, "Cute");
///
/// assert_eq!(const { TypeId::of::<()>().name() }, "");
/// assert_eq!(const { TypeId::of::<fn(u8)>().name() }, "");
/// ```
#[unstable(feature = "type_info", issue = "146922")]
#[rustc_const_unstable(feature = "type_info", issue = "146922")]
#[rustc_comptime]
pub fn name(self) -> &'static str {
intrinsics::reflection::type_id_name(self)
}
}

/// Variant representing type ID. Representing a variant of an enum.
Expand Down Expand Up @@ -742,7 +768,7 @@ impl FieldId {
#[rustc_const_unstable(feature = "type_info", issue = "146922")]
#[rustc_comptime]
pub fn type_id(self) -> TypeId {
intrinsics::field_representing_type_actual_type_id(self.frt_type_id)
intrinsics::reflection::type_id_field_representing_outer_type_id(self.frt_type_id)
}

/// Returns the name of the field.
Expand All @@ -764,7 +790,7 @@ impl FieldId {
#[rustc_const_unstable(feature = "type_info", issue = "146922")]
#[rustc_comptime]
pub fn name(self) -> &'static str {
intrinsics::field_representing_type_name(self.frt_type_id)
intrinsics::reflection::type_id_name(self.frt_type_id)
}
/// Returns the offset of the field wrt to its containing type.
///
Expand All @@ -786,6 +812,6 @@ impl FieldId {
#[rustc_const_unstable(feature = "type_info", issue = "146922")]
#[rustc_comptime]
pub fn offset(self) -> usize {
intrinsics::field_representing_type_offset(self.frt_type_id)
intrinsics::reflection::type_id_field_representing_field_offset(self.frt_type_id)
}
}
Loading
Loading