Skip to content

Commit 2a7b6c5

Browse files
committed
feat: support pointers in type info
1 parent 2fd6efc commit 2a7b6c5

6 files changed

Lines changed: 96 additions & 3 deletions

File tree

compiler/rustc_const_eval/src/const_eval/type_info.rs

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use rustc_abi::FieldIdx;
2+
use rustc_ast::Mutability;
23
use rustc_hir::LangItem;
34
use rustc_middle::mir::interpret::CtfeProvenance;
45
use rustc_middle::span_bug;
@@ -8,7 +9,7 @@ use rustc_span::{Symbol, sym};
89

910
use crate::const_eval::CompileTimeMachine;
1011
use crate::interpret::{
11-
Immediate, InterpCx, InterpResult, MPlaceTy, MemoryKind, Writeable, interp_ok,
12+
Immediate, InterpCx, InterpResult, MPlaceTy, MemoryKind, Scalar, Writeable, interp_ok,
1213
};
1314

1415
impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
@@ -64,6 +65,15 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
6465

6566
variant
6667
}
68+
ty::RawPtr(ty, mutability) => {
69+
let (variant, variant_place) = downcast(sym::Pointer)?;
70+
let pointer_place =
71+
self.project_field(&variant_place, FieldIdx::ZERO)?;
72+
73+
self.write_pointer_type_info(pointer_place, *ty, *mutability)?;
74+
75+
variant
76+
}
6777
// For now just merge all primitives into one `Leaf` variant with no data
6878
ty::Uint(_) | ty::Int(_) | ty::Float(_) | ty::Char | ty::Bool => {
6979
downcast(sym::Leaf)?.0
@@ -73,7 +83,6 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
7383
| ty::Str
7484
| ty::Pat(_, _)
7585
| ty::Slice(_)
76-
| ty::RawPtr(..)
7786
| ty::Ref(..)
7887
| ty::FnDef(..)
7988
| ty::FnPtr(..)
@@ -203,4 +212,30 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
203212

204213
interp_ok(())
205214
}
215+
216+
pub(crate) fn write_pointer_type_info(
217+
&mut self,
218+
place: impl Writeable<'tcx, CtfeProvenance>,
219+
ty: Ty<'tcx>,
220+
mutability: Mutability,
221+
) -> InterpResult<'tcx> {
222+
// Iterate over all fields of `type_info::Pointer`.
223+
for (field_idx, field) in
224+
place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated()
225+
{
226+
let field_place = self.project_field(&place, field_idx)?;
227+
228+
match field.name {
229+
// Write the `TypeId` of the pointer's inner type to the `ty` field.
230+
sym::pointee => self.write_type_id(ty, &field_place)?,
231+
// Write the boolean representing the pointer's mutability to the `mutable` field.
232+
sym::mutable => {
233+
self.write_scalar(Scalar::from_bool(mutability.is_mut()), &field_place)?
234+
}
235+
other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"),
236+
}
237+
}
238+
239+
interp_ok(())
240+
}
206241
}

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1515,6 +1515,7 @@ symbols! {
15151515
must_use,
15161516
mut_preserve_binding_mode_2024,
15171517
mut_ref,
1518+
mutable,
15181519
naked,
15191520
naked_asm,
15201521
naked_functions,

library/core/src/mem/type_info.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ pub enum TypeKind {
4545
Tuple(Tuple),
4646
/// Arrays.
4747
Array(Array),
48+
/// Pointers.
49+
Pointer(Pointer),
4850
/// Primitives
4951
/// FIXME(#146922): disambiguate further
5052
Leaf,
@@ -82,3 +84,14 @@ pub struct Array {
8284
/// The length of the array.
8385
pub len: usize,
8486
}
87+
88+
/// Compile-time type information about pointers.
89+
#[derive(Debug)]
90+
#[non_exhaustive]
91+
#[unstable(feature = "type_info", issue = "146922")]
92+
pub struct Pointer {
93+
/// The type of the value being pointed to.
94+
pub pointee: TypeId,
95+
/// Whether this pointer is mutable or not.
96+
pub mutable: bool,
97+
}

library/coretests/tests/mem/type_info.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::any::TypeId;
1+
use std::any::{Any, TypeId};
22
use std::mem::type_info::{Type, TypeKind};
33

44
#[test]
@@ -54,3 +54,33 @@ fn test_tuples() {
5454
}
5555
}
5656
}
57+
58+
#[test]
59+
fn test_pointers() {
60+
// Immutable pointer.
61+
match const { Type::of::<*const u8>() }.kind {
62+
TypeKind::Pointer(pointer) => {
63+
assert_eq!(pointer.pointee, TypeId::of::<u8>());
64+
assert!(!pointer.mutable);
65+
}
66+
_ => unreachable!(),
67+
}
68+
69+
// Mutable pointer.
70+
match const { Type::of::<*mut u64>() }.kind {
71+
TypeKind::Pointer(pointer) => {
72+
assert_eq!(pointer.pointee, TypeId::of::<u64>());
73+
assert!(pointer.mutable);
74+
}
75+
_ => unreachable!(),
76+
}
77+
78+
// Wide pointer.
79+
match const { Type::of::<*const dyn Any>() }.kind {
80+
TypeKind::Pointer(pointer) => {
81+
assert_eq!(pointer.pointee, TypeId::of::<dyn Any>());
82+
assert!(!pointer.mutable);
83+
}
84+
_ => unreachable!(),
85+
}
86+
}

tests/ui/reflection/dump.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,6 @@ fn main() {
3030
println!("{:#?}", const { Type::of::<&[u8]>() }.kind);
3131
println!("{:#?}", const { Type::of::<str>() }.kind);
3232
println!("{:#?}", const { Type::of::<[u8]>() }.kind);
33+
println!("{:#?}", const { Type::of::<*mut u8>() }.kind);
34+
println!("{:#?}", const { Type::of::<*const Unsized>() }.kind);
3335
}

tests/ui/reflection/dump.run.stdout

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,15 @@ Other
2929
Other
3030
Other
3131
Other
32+
Pointer(
33+
Pointer {
34+
pointee: TypeId(0x0596b48cc04376e64d5c788c2aa46bdb),
35+
mutable: true,
36+
},
37+
)
38+
Pointer(
39+
Pointer {
40+
pointee: TypeId(0xda1b6da9bd297bb2900de9303aadea79),
41+
mutable: false,
42+
},
43+
)

0 commit comments

Comments
 (0)