Skip to content
Merged
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
35 changes: 34 additions & 1 deletion compiler/rustc_const_eval/src/const_eval/type_info.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use rustc_abi::FieldIdx;
use rustc_ast::Mutability;
use rustc_hir::LangItem;
use rustc_middle::mir::interpret::{CtfeProvenance, Scalar};
use rustc_middle::span_bug;
Expand Down Expand Up @@ -103,12 +104,19 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
let (variant, _variant_place) = downcast(sym::Str)?;
variant
}
ty::Ref(_, ty, mutability) => {
let (variant, variant_place) = downcast(sym::Reference)?;
let reference_place =
self.project_field(&variant_place, FieldIdx::ZERO)?;
self.write_reference_type_info(reference_place, *ty, *mutability)?;

variant
}
ty::Adt(_, _)
| ty::Foreign(_)
| ty::Pat(_, _)
| ty::Slice(_)
| ty::RawPtr(..)
| ty::Ref(..)
| ty::FnDef(..)
| ty::FnPtr(..)
| ty::UnsafeBinder(..)
Expand Down Expand Up @@ -279,4 +287,29 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
}
interp_ok(())
}

pub(crate) fn write_reference_type_info(
&mut self,
place: impl Writeable<'tcx, CtfeProvenance>,
ty: Ty<'tcx>,
mutability: Mutability,
) -> InterpResult<'tcx> {
// Iterate over all fields of `type_info::Reference`.
for (field_idx, field) in
place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated()
{
let field_place = self.project_field(&place, field_idx)?;

match field.name {
// Write the `TypeId` of the reference's inner type to the `ty` field.
sym::pointee => self.write_type_id(ty, &field_place)?,
// Write the boolean representing the reference's mutability to the `mutable` field.
sym::mutable => {
self.write_scalar(Scalar::from_bool(mutability.is_mut()), &field_place)?
}
other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"),
}
}
interp_ok(())
}
}
2 changes: 2 additions & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@ symbols! {
RefCell,
RefCellRef,
RefCellRefMut,
Reference,
Relaxed,
Release,
Result,
Expand Down Expand Up @@ -1521,6 +1522,7 @@ symbols! {
must_use,
mut_preserve_binding_mode_2024,
mut_ref,
mutable,
naked,
naked_asm,
naked_functions,
Expand Down
13 changes: 13 additions & 0 deletions library/core/src/mem/type_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ pub enum TypeKind {
Float(Float),
/// String slice type.
Str(Str),
/// References.
Reference(Reference),
/// FIXME(#146922): add all the common types
Other,
}
Expand Down Expand Up @@ -133,3 +135,14 @@ pub struct Float {
pub struct Str {
// No additional information to provide for now.
}

/// Compile-time type information about references.
#[derive(Debug)]
#[non_exhaustive]
#[unstable(feature = "type_info", issue = "146922")]
pub struct Reference {
/// The type of the value being referred to.
pub pointee: TypeId,
/// Whether this reference is mutable or not.
pub mutable: bool,
}
32 changes: 31 additions & 1 deletion library/coretests/tests/mem/type_info.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::any::TypeId;
use std::any::{Any, TypeId};
use std::mem::type_info::{Type, TypeKind};

#[test]
Expand Down Expand Up @@ -95,3 +95,33 @@ fn test_primitives() {
let Type { kind: Str(_ty), size, .. } = (const { Type::of::<str>() }) else { panic!() };
assert_eq!(size, None);
}

#[test]
fn test_references() {
// Immutable reference.
match const { Type::of::<&u8>() }.kind {
TypeKind::Reference(reference) => {
assert_eq!(reference.pointee, TypeId::of::<u8>());
assert!(!reference.mutable);
}
_ => unreachable!(),
}

// Mutable pointer.
match const { Type::of::<&mut u64>() }.kind {
TypeKind::Reference(reference) => {
assert_eq!(reference.pointee, TypeId::of::<u64>());
assert!(reference.mutable);
}
_ => unreachable!(),
}

// Wide pointer.
match const { Type::of::<&dyn Any>() }.kind {
TypeKind::Reference(reference) => {
assert_eq!(reference.pointee, TypeId::of::<dyn Any>());
assert!(!reference.mutable);
}
_ => unreachable!(),
}
}
43 changes: 40 additions & 3 deletions tests/ui/reflection/dump.bit32.run.stdout
Original file line number Diff line number Diff line change
Expand Up @@ -155,19 +155,34 @@ Type {
),
}
Type {
kind: Other,
kind: Reference(
Reference {
pointee: TypeId(0xda1b6da9bd297bb2900de9303aadea79),
mutable: false,
},
),
size: Some(
8,
),
}
Type {
kind: Other,
kind: Reference(
Reference {
pointee: TypeId(0x474ccf3b5db264ef53916706f7d7bb2c),
mutable: false,
},
),
size: Some(
8,
),
}
Type {
kind: Other,
kind: Reference(
Reference {
pointee: TypeId(0x641e3def269c37acc6dcb92bf8c5f196),
mutable: false,
},
),
size: Some(
8,
),
Expand All @@ -182,3 +197,25 @@ Type {
kind: Other,
size: None,
}
Type {
kind: Reference(
Reference {
pointee: TypeId(0x0596b48cc04376e64d5c788c2aa46bdb),
mutable: false,
},
),
size: Some(
4,
),
}
Type {
kind: Reference(
Reference {
pointee: TypeId(0x0596b48cc04376e64d5c788c2aa46bdb),
mutable: true,
},
),
size: Some(
4,
),
}
43 changes: 40 additions & 3 deletions tests/ui/reflection/dump.bit64.run.stdout
Original file line number Diff line number Diff line change
Expand Up @@ -155,19 +155,34 @@ Type {
),
}
Type {
kind: Other,
kind: Reference(
Reference {
pointee: TypeId(0xda1b6da9bd297bb2900de9303aadea79),
mutable: false,
},
),
size: Some(
16,
),
}
Type {
kind: Other,
kind: Reference(
Reference {
pointee: TypeId(0x474ccf3b5db264ef53916706f7d7bb2c),
mutable: false,
},
),
size: Some(
16,
),
}
Type {
kind: Other,
kind: Reference(
Reference {
pointee: TypeId(0x641e3def269c37acc6dcb92bf8c5f196),
mutable: false,
},
),
size: Some(
16,
),
Expand All @@ -182,3 +197,25 @@ Type {
kind: Other,
size: None,
}
Type {
kind: Reference(
Reference {
pointee: TypeId(0x0596b48cc04376e64d5c788c2aa46bdb),
mutable: false,
},
),
size: Some(
8,
),
}
Type {
kind: Reference(
Reference {
pointee: TypeId(0x0596b48cc04376e64d5c788c2aa46bdb),
mutable: true,
},
),
size: Some(
8,
),
}
1 change: 1 addition & 0 deletions tests/ui/reflection/dump.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,6 @@ fn main() {
Foo, Bar,
&Unsized, &str, &[u8],
str, [u8],
&u8, &mut u8,
}
}
Loading