Skip to content

Commit f26a2c2

Browse files
committed
feat: Support references in reflection type info
1 parent 503745e commit f26a2c2

6 files changed

Lines changed: 122 additions & 5 deletions

File tree

compiler/rustc_const_eval/src/const_eval/type_info.rs

Lines changed: 34 additions & 1 deletion
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, Scalar};
45
use rustc_middle::span_bug;
@@ -103,12 +104,19 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
103104
let (variant, _variant_place) = downcast(sym::Str)?;
104105
variant
105106
}
107+
ty::Ref(_, ty, mutability) => {
108+
let (variant, variant_place) = downcast(sym::Reference)?;
109+
let reference_place =
110+
self.project_field(&variant_place, FieldIdx::ZERO)?;
111+
self.write_reference_type_info(reference_place, *ty, *mutability)?;
112+
113+
variant
114+
}
106115
ty::Adt(_, _)
107116
| ty::Foreign(_)
108117
| ty::Pat(_, _)
109118
| ty::Slice(_)
110119
| ty::RawPtr(..)
111-
| ty::Ref(..)
112120
| ty::FnDef(..)
113121
| ty::FnPtr(..)
114122
| ty::UnsafeBinder(..)
@@ -279,4 +287,29 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
279287
}
280288
interp_ok(())
281289
}
290+
291+
pub(crate) fn write_reference_type_info(
292+
&mut self,
293+
place: impl Writeable<'tcx, CtfeProvenance>,
294+
ty: Ty<'tcx>,
295+
mutability: Mutability,
296+
) -> InterpResult<'tcx> {
297+
// Iterate over all fields of `type_info::Reference`.
298+
for (field_idx, field) in
299+
place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated()
300+
{
301+
let field_place = self.project_field(&place, field_idx)?;
302+
303+
match field.name {
304+
// Write the `TypeId` of the reference's inner type to the `ty` field.
305+
sym::referee => self.write_type_id(ty, &field_place)?,
306+
// Write the boolean representing the reference's mutability to the `mutable` field.
307+
sym::mutable => {
308+
self.write_scalar(Scalar::from_bool(mutability.is_mut()), &field_place)?
309+
}
310+
other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"),
311+
}
312+
}
313+
interp_ok(())
314+
}
282315
}

compiler/rustc_span/src/symbol.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,7 @@ symbols! {
343343
RefCell,
344344
RefCellRef,
345345
RefCellRefMut,
346+
Reference,
346347
Relaxed,
347348
Release,
348349
Result,
@@ -1521,6 +1522,7 @@ symbols! {
15211522
must_use,
15221523
mut_preserve_binding_mode_2024,
15231524
mut_ref,
1525+
mutable,
15241526
naked,
15251527
naked_asm,
15261528
naked_functions,
@@ -1843,6 +1845,7 @@ symbols! {
18431845
ref_pat_eat_one_layer_2024_structural,
18441846
ref_pat_everywhere,
18451847
ref_unwind_safe_trait,
1848+
referee,
18461849
reference,
18471850
reflect,
18481851
reg,

library/core/src/mem/type_info.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ pub enum TypeKind {
5555
Float(Float),
5656
/// String slice type.
5757
Str(Str),
58+
/// References.
59+
Reference(Reference),
5860
/// FIXME(#146922): add all the common types
5961
Other,
6062
}
@@ -133,3 +135,14 @@ pub struct Float {
133135
pub struct Str {
134136
// No additional information to provide for now.
135137
}
138+
139+
/// Compile-time type information about references.
140+
#[derive(Debug)]
141+
#[non_exhaustive]
142+
#[unstable(feature = "type_info", issue = "146922")]
143+
pub struct Reference {
144+
/// The type of the value being referred to.
145+
pub referee: TypeId,
146+
/// Whether this reference is mutable or not.
147+
pub mutable: bool,
148+
}

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]
@@ -95,3 +95,33 @@ fn test_primitives() {
9595
let Type { kind: Str(_ty), size, .. } = (const { Type::of::<str>() }) else { panic!() };
9696
assert_eq!(size, None);
9797
}
98+
99+
#[test]
100+
fn test_references() {
101+
// Immutable reference.
102+
match const { Type::of::<&u8>() }.kind {
103+
TypeKind::Reference(reference) => {
104+
assert_eq!(reference.referee, TypeId::of::<u8>());
105+
assert!(!reference.mutable);
106+
}
107+
_ => unreachable!(),
108+
}
109+
110+
// Mutable pointer.
111+
match const { Type::of::<&mut u64>() }.kind {
112+
TypeKind::Reference(reference) => {
113+
assert_eq!(reference.referee, TypeId::of::<u64>());
114+
assert!(reference.mutable);
115+
}
116+
_ => unreachable!(),
117+
}
118+
119+
// Wide pointer.
120+
match const { Type::of::<&dyn Any>() }.kind {
121+
TypeKind::Reference(reference) => {
122+
assert_eq!(reference.referee, TypeId::of::<dyn Any>());
123+
assert!(!reference.mutable);
124+
}
125+
_ => unreachable!(),
126+
}
127+
}

tests/ui/reflection/dump.bit64.run.stdout

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,19 +155,34 @@ Type {
155155
),
156156
}
157157
Type {
158-
kind: Other,
158+
kind: Reference(
159+
Reference {
160+
referee: TypeId(0xda1b6da9bd297bb2900de9303aadea79),
161+
mutable: false,
162+
},
163+
),
159164
size: Some(
160165
16,
161166
),
162167
}
163168
Type {
164-
kind: Other,
169+
kind: Reference(
170+
Reference {
171+
referee: TypeId(0x474ccf3b5db264ef53916706f7d7bb2c),
172+
mutable: false,
173+
},
174+
),
165175
size: Some(
166176
16,
167177
),
168178
}
169179
Type {
170-
kind: Other,
180+
kind: Reference(
181+
Reference {
182+
referee: TypeId(0x641e3def269c37acc6dcb92bf8c5f196),
183+
mutable: false,
184+
},
185+
),
171186
size: Some(
172187
16,
173188
),
@@ -182,3 +197,25 @@ Type {
182197
kind: Other,
183198
size: None,
184199
}
200+
Type {
201+
kind: Reference(
202+
Reference {
203+
referee: TypeId(0x0596b48cc04376e64d5c788c2aa46bdb),
204+
mutable: false,
205+
},
206+
),
207+
size: Some(
208+
8,
209+
),
210+
}
211+
Type {
212+
kind: Reference(
213+
Reference {
214+
referee: TypeId(0x0596b48cc04376e64d5c788c2aa46bdb),
215+
mutable: true,
216+
},
217+
),
218+
size: Some(
219+
8,
220+
),
221+
}

tests/ui/reflection/dump.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,6 @@ fn main() {
4040
Foo, Bar,
4141
&Unsized, &str, &[u8],
4242
str, [u8],
43+
&u8, &mut u8,
4344
}
4445
}

0 commit comments

Comments
 (0)