1- use rustc_abi:: FieldIdx ;
1+ use std:: borrow:: Cow ;
2+
3+ use rustc_abi:: { FieldIdx , VariantIdx } ;
24use rustc_ast:: Mutability ;
35use rustc_hir:: LangItem ;
46use rustc_middle:: mir:: interpret:: { CtfeProvenance , Scalar } ;
57use rustc_middle:: span_bug;
68use rustc_middle:: ty:: layout:: TyAndLayout ;
7- use rustc_middle:: ty:: { self , Const , ScalarInt , Ty } ;
9+ use rustc_middle:: ty:: { self , AdtDef , AdtKind , Const , GenericArgs , ScalarInt , Ty , VariantDef } ;
810use rustc_span:: { Symbol , sym} ;
911
1012use crate :: const_eval:: CompileTimeMachine ;
1113use crate :: interpret:: {
12- Immediate , InterpCx , InterpResult , MPlaceTy , MemoryKind , Writeable , interp_ok,
14+ Immediate , InterpCx , InterpResult , MPlaceTy , MemoryKind , Projectable , Writeable , interp_ok,
1315} ;
1416
1517impl < ' tcx > InterpCx < ' tcx , CompileTimeMachine < ' tcx > > {
18+ fn downcast (
19+ & self ,
20+ place : & ( impl Writeable < ' tcx , CtfeProvenance > + ' tcx ) ,
21+ name : Symbol ,
22+ ) -> InterpResult < ' tcx , ( VariantIdx , impl Writeable < ' tcx , CtfeProvenance > + ' tcx ) > {
23+ let variants = place. layout ( ) . ty . ty_adt_def ( ) . unwrap ( ) . variants ( ) ;
24+ let variant_id = variants
25+ . iter_enumerated ( )
26+ . find ( |( _idx, var) | var. name == name)
27+ . unwrap_or_else ( || panic ! ( "got {name} but expected one of {variants:#?}" ) )
28+ . 0 ;
29+
30+ interp_ok ( ( variant_id, self . project_downcast ( place, variant_id) ?) )
31+ }
32+
1633 /// Writes a `core::mem::type_info::TypeInfo` for a given type, `ty` to the given place.
1734 pub ( crate ) fn write_type_info (
1835 & mut self ,
1936 ty : Ty < ' tcx > ,
20- dest : & impl Writeable < ' tcx , CtfeProvenance > ,
37+ dest : & ( impl Writeable < ' tcx , CtfeProvenance > + ' tcx ) ,
2138 ) -> InterpResult < ' tcx > {
2239 let ty_struct = self . tcx . require_lang_item ( LangItem :: Type , self . tcx . span ) ;
2340 let ty_struct = self . tcx . type_of ( ty_struct) . no_bound_vars ( ) . unwrap ( ) ;
@@ -26,22 +43,13 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
2643 // Fill all fields of the `TypeInfo` struct.
2744 for ( idx, field) in ty_struct. fields . iter_enumerated ( ) {
2845 let field_dest = self . project_field ( dest, idx) ?;
29- let downcast = |name : Symbol | {
30- let variants = field_dest. layout ( ) . ty . ty_adt_def ( ) . unwrap ( ) . variants ( ) ;
31- let variant_id = variants
32- . iter_enumerated ( )
33- . find ( |( _idx, var) | var. name == name)
34- . unwrap_or_else ( || panic ! ( "got {name} but expected one of {variants:#?}" ) )
35- . 0 ;
36-
37- interp_ok ( ( variant_id, self . project_downcast ( & field_dest, variant_id) ?) )
38- } ;
3946 let ptr_bit_width = || self . tcx . data_layout . pointer_size ( ) . bits ( ) ;
4047 match field. name {
4148 sym:: kind => {
4249 let variant_index = match ty. kind ( ) {
4350 ty:: Tuple ( fields) => {
44- let ( variant, variant_place) = downcast ( sym:: Tuple ) ?;
51+ let ( variant, variant_place) =
52+ self . downcast ( & field_dest, sym:: Tuple ) ?;
4553 // project to the single tuple variant field of `type_info::Tuple` struct type
4654 let tuple_place = self . project_field ( & variant_place, FieldIdx :: ZERO ) ?;
4755 assert_eq ! (
@@ -59,23 +67,38 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
5967 variant
6068 }
6169 ty:: Array ( ty, len) => {
62- let ( variant, variant_place) = downcast ( sym:: Array ) ?;
70+ let ( variant, variant_place) =
71+ self . downcast ( & field_dest, sym:: Array ) ?;
6372 let array_place = self . project_field ( & variant_place, FieldIdx :: ZERO ) ?;
6473
6574 self . write_array_type_info ( array_place, * ty, * len) ?;
6675
6776 variant
6877 }
78+ ty:: Adt ( adt_def, generics) => {
79+ // TODO(type_info): Handle enum and union
80+ if !adt_def. is_struct ( ) {
81+ self . downcast ( & field_dest, sym:: Other ) ?. 0
82+ } else {
83+ let ( variant, variant_place) =
84+ self . downcast ( & field_dest, sym:: Struct ) ?;
85+ let place = self . project_field ( & variant_place, FieldIdx :: ZERO ) ?;
86+ self . write_adt_type_info ( place, ( ty, * adt_def) , generics) ?;
87+ variant
88+ }
89+ }
6990 ty:: Bool => {
70- let ( variant, _variant_place) = downcast ( sym:: Bool ) ?;
91+ let ( variant, _variant_place) =
92+ self . downcast ( & field_dest, sym:: Bool ) ?;
7193 variant
7294 }
7395 ty:: Char => {
74- let ( variant, _variant_place) = downcast ( sym:: Char ) ?;
96+ let ( variant, _variant_place) =
97+ self . downcast ( & field_dest, sym:: Char ) ?;
7598 variant
7699 }
77100 ty:: Int ( int_ty) => {
78- let ( variant, variant_place) = downcast ( sym:: Int ) ?;
101+ let ( variant, variant_place) = self . downcast ( & field_dest , sym:: Int ) ?;
79102 let place = self . project_field ( & variant_place, FieldIdx :: ZERO ) ?;
80103 self . write_int_type_info (
81104 place,
@@ -85,7 +108,7 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
85108 variant
86109 }
87110 ty:: Uint ( uint_ty) => {
88- let ( variant, variant_place) = downcast ( sym:: Int ) ?;
111+ let ( variant, variant_place) = self . downcast ( & field_dest , sym:: Int ) ?;
89112 let place = self . project_field ( & variant_place, FieldIdx :: ZERO ) ?;
90113 self . write_int_type_info (
91114 place,
@@ -95,25 +118,26 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
95118 variant
96119 }
97120 ty:: Float ( float_ty) => {
98- let ( variant, variant_place) = downcast ( sym:: Float ) ?;
121+ let ( variant, variant_place) =
122+ self . downcast ( & field_dest, sym:: Float ) ?;
99123 let place = self . project_field ( & variant_place, FieldIdx :: ZERO ) ?;
100124 self . write_float_type_info ( place, float_ty. bit_width ( ) ) ?;
101125 variant
102126 }
103127 ty:: Str => {
104- let ( variant, _variant_place) = downcast ( sym:: Str ) ?;
128+ let ( variant, _variant_place) = self . downcast ( & field_dest , sym:: Str ) ?;
105129 variant
106130 }
107131 ty:: Ref ( _, ty, mutability) => {
108- let ( variant, variant_place) = downcast ( sym:: Reference ) ?;
132+ let ( variant, variant_place) =
133+ self . downcast ( & field_dest, sym:: Reference ) ?;
109134 let reference_place =
110135 self . project_field ( & variant_place, FieldIdx :: ZERO ) ?;
111136 self . write_reference_type_info ( reference_place, * ty, * mutability) ?;
112137
113138 variant
114139 }
115- ty:: Adt ( _, _)
116- | ty:: Foreign ( _)
140+ ty:: Foreign ( _)
117141 | ty:: Pat ( _, _)
118142 | ty:: Slice ( _)
119143 | ty:: RawPtr ( ..)
@@ -131,14 +155,14 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
131155 | ty:: Bound ( ..)
132156 | ty:: Placeholder ( _)
133157 | ty:: Infer ( ..)
134- | ty:: Error ( _) => downcast ( sym:: Other ) ?. 0 ,
158+ | ty:: Error ( _) => self . downcast ( & field_dest , sym:: Other ) ?. 0 ,
135159 } ;
136160 self . write_discriminant ( variant_index, & field_dest) ?
137161 }
138162 sym:: size => {
139163 let layout = self . layout_of ( ty) ?;
140164 let variant_index = if layout. is_sized ( ) {
141- let ( variant, variant_place) = downcast ( sym:: Some ) ?;
165+ let ( variant, variant_place) = self . downcast ( & field_dest , sym:: Some ) ?;
142166 let size_field_place =
143167 self . project_field ( & variant_place, FieldIdx :: ZERO ) ?;
144168 self . write_scalar (
@@ -148,7 +172,7 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
148172 ) ?;
149173 variant
150174 } else {
151- downcast ( sym:: None ) ?. 0
175+ self . downcast ( & field_dest , sym:: None ) ?. 0
152176 } ;
153177 self . write_discriminant ( variant_index, & field_dest) ?;
154178 }
@@ -184,7 +208,7 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
184208
185209 while let Some ( ( i, place) ) = fields_places. next ( self ) ? {
186210 let field_ty = fields[ i as usize ] ;
187- self . write_field ( field_ty, place, tuple_layout, i) ?;
211+ self . write_field ( field_ty, place, tuple_layout, None , i) ?;
188212 }
189213
190214 let fields_place = fields_place. map_provenance ( CtfeProvenance :: as_immutable) ;
@@ -199,13 +223,23 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
199223 field_ty : Ty < ' tcx > ,
200224 place : MPlaceTy < ' tcx > ,
201225 layout : TyAndLayout < ' tcx > ,
226+ name : Option < Symbol > ,
202227 idx : u64 ,
203228 ) -> InterpResult < ' tcx > {
204229 for ( field_idx, field_ty_field) in
205230 place. layout . ty . ty_adt_def ( ) . unwrap ( ) . non_enum_variant ( ) . fields . iter_enumerated ( )
206231 {
207232 let field_place = self . project_field ( & place, field_idx) ?;
208233 match field_ty_field. name {
234+ sym:: name => {
235+ let name = match name. as_ref ( ) {
236+ Some ( name) => Cow :: Borrowed ( name. as_str ( ) ) ,
237+ None => Cow :: Owned ( idx. to_string ( ) ) , // For tuples
238+ } ;
239+ let name_place = self . allocate_str_dedup ( & name) ?;
240+ let ptr = self . mplace_to_ref ( & name_place) ?;
241+ self . write_immediate ( * ptr, & field_place) ?
242+ }
209243 sym:: ty => self . write_type_id ( field_ty, & field_place) ?,
210244 sym:: offset => {
211245 let offset = layout. fields . offset ( idx as usize ) ;
@@ -246,6 +280,82 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
246280 interp_ok ( ( ) )
247281 }
248282
283+ // FIXME(type_info): No semver considerations for now
284+ pub ( crate ) fn write_adt_type_info (
285+ & mut self ,
286+ place : impl Writeable < ' tcx , CtfeProvenance > ,
287+ adt : ( Ty < ' tcx > , AdtDef < ' tcx > ) ,
288+ generics : & ' tcx GenericArgs < ' tcx > ,
289+ ) -> InterpResult < ' tcx > {
290+ let ( adt_ty, adt_def) = adt;
291+ match adt_def. adt_kind ( ) {
292+ AdtKind :: Struct => self . write_struct_type_info (
293+ place,
294+ ( adt_ty, adt_def. variant ( VariantIdx :: ZERO ) ) ,
295+ generics,
296+ ) ,
297+ AdtKind :: Union => todo ! ( ) ,
298+ AdtKind :: Enum => todo ! ( ) ,
299+ }
300+ }
301+
302+ pub ( crate ) fn write_struct_type_info (
303+ & mut self ,
304+ place : impl Writeable < ' tcx , CtfeProvenance > ,
305+ struct_ : ( Ty < ' tcx > , & ' tcx VariantDef ) ,
306+ generics : & ' tcx GenericArgs < ' tcx > ,
307+ ) -> InterpResult < ' tcx > {
308+ let ( struct_ty, struct_def) = struct_;
309+ let struct_layout = self . layout_of ( struct_ty) ?;
310+
311+ for ( field_idx, field) in
312+ place. layout ( ) . ty . ty_adt_def ( ) . unwrap ( ) . non_enum_variant ( ) . fields . iter_enumerated ( )
313+ {
314+ let field_place = self . project_field ( & place, field_idx) ?;
315+
316+ match field. name {
317+ sym:: fields => {
318+ let fields_slice_place = field_place;
319+ let field_type = fields_slice_place
320+ . layout ( )
321+ . ty
322+ . builtin_deref ( false )
323+ . unwrap ( )
324+ . sequence_element_type ( self . tcx . tcx ) ;
325+ let fields_layout = self . layout_of ( Ty :: new_array (
326+ self . tcx . tcx ,
327+ field_type,
328+ struct_def. fields . len ( ) as u64 ,
329+ ) ) ?;
330+ let fields_place = self . allocate ( fields_layout, MemoryKind :: Stack ) ?;
331+ let mut fields_places = self . project_array_fields ( & fields_place) ?;
332+
333+ for field_def in & struct_def. fields {
334+ let ( i, place) = fields_places. next ( self ) ?. unwrap ( ) ;
335+ let field_ty = field_def. ty ( * self . tcx , generics) ;
336+ self . write_field ( field_ty, place, struct_layout, Some ( field_def. name ) , i) ?;
337+ }
338+
339+ let fields_place = fields_place. map_provenance ( CtfeProvenance :: as_immutable) ;
340+ let ptr = Immediate :: new_slice (
341+ fields_place. ptr ( ) ,
342+ struct_def. fields . len ( ) as u64 ,
343+ self ,
344+ ) ;
345+ self . write_immediate ( ptr, & fields_slice_place) ?
346+ }
347+ sym:: non_exhaustive => {
348+ let is_non_exhaustive = struct_def. is_field_list_non_exhaustive ( ) ;
349+ self . write_scalar ( Scalar :: from_bool ( is_non_exhaustive) , & field_place) ?
350+ }
351+ // TODO(type_info): Write more info
352+ other => span_bug ! ( self . tcx. def_span( field. did) , "unimplemented field {other}" ) ,
353+ }
354+ }
355+
356+ interp_ok ( ( ) )
357+ }
358+
249359 fn write_int_type_info (
250360 & mut self ,
251361 place : impl Writeable < ' tcx , CtfeProvenance > ,
0 commit comments