1- use rustc_abi:: FieldIdx ;
1+ mod adt;
2+
3+ use std:: borrow:: Cow ;
4+
5+ use rustc_abi:: { FieldIdx , VariantIdx } ;
26use rustc_ast:: Mutability ;
37use rustc_hir:: LangItem ;
48use rustc_middle:: span_bug;
@@ -8,11 +12,58 @@ use rustc_span::{Symbol, sym};
812
913use crate :: const_eval:: CompileTimeMachine ;
1014use crate :: interpret:: {
11- CtfeProvenance , Immediate , InterpCx , InterpResult , MPlaceTy , MemoryKind , Scalar , Writeable ,
12- interp_ok,
15+ CtfeProvenance , Immediate , InterpCx , InterpResult , MPlaceTy , MemoryKind , Projectable , Scalar ,
16+ Writeable , interp_ok,
1317} ;
1418
1519impl < ' tcx > InterpCx < ' tcx , CompileTimeMachine < ' tcx > > {
20+ /// Equivalent to `project_downcast`, but identifies the variant by name instead of index.
21+ fn downcast < ' a > (
22+ & self ,
23+ place : & ( impl Writeable < ' tcx , CtfeProvenance > + ' a ) ,
24+ name : Symbol ,
25+ ) -> InterpResult < ' tcx , ( VariantIdx , impl Writeable < ' tcx , CtfeProvenance > + ' a ) > {
26+ let variants = place. layout ( ) . ty . ty_adt_def ( ) . unwrap ( ) . variants ( ) ;
27+ let variant_idx = variants
28+ . iter_enumerated ( )
29+ . find ( |( _idx, var) | var. name == name)
30+ . unwrap_or_else ( || panic ! ( "got {name} but expected one of {variants:#?}" ) )
31+ . 0 ;
32+
33+ interp_ok ( ( variant_idx, self . project_downcast ( place, variant_idx) ?) )
34+ }
35+
36+ // A general method to write an array to a static slice place.
37+ fn allocate_fill_and_write_slice_ptr (
38+ & mut self ,
39+ slice_place : impl Writeable < ' tcx , CtfeProvenance > ,
40+ len : u64 ,
41+ writer : impl Fn ( & mut Self , /* index */ u64 , MPlaceTy < ' tcx > ) -> InterpResult < ' tcx > ,
42+ ) -> InterpResult < ' tcx > {
43+ // Array element type
44+ let field_ty = slice_place
45+ . layout ( )
46+ . ty
47+ . builtin_deref ( false )
48+ . unwrap ( )
49+ . sequence_element_type ( self . tcx . tcx ) ;
50+
51+ // Allocate an array
52+ let array_layout = self . layout_of ( Ty :: new_array ( self . tcx . tcx , field_ty, len) ) ?;
53+ let array_place = self . allocate ( array_layout, MemoryKind :: Stack ) ?;
54+
55+ // Fill the array fields
56+ let mut field_places = self . project_array_fields ( & array_place) ?;
57+ while let Some ( ( i, place) ) = field_places. next ( self ) ? {
58+ writer ( self , i, place) ?;
59+ }
60+
61+ // Write the slice pointing to the array
62+ let array_place = array_place. map_provenance ( CtfeProvenance :: as_immutable) ;
63+ let ptr = Immediate :: new_slice ( array_place. ptr ( ) , len, self ) ;
64+ self . write_immediate ( ptr, & slice_place)
65+ }
66+
1667 /// Writes a `core::mem::type_info::TypeInfo` for a given type, `ty` to the given place.
1768 pub ( crate ) fn write_type_info (
1869 & mut self ,
@@ -26,22 +77,13 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
2677 // Fill all fields of the `TypeInfo` struct.
2778 for ( idx, field) in ty_struct. fields . iter_enumerated ( ) {
2879 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- } ;
3980 let ptr_bit_width = || self . tcx . data_layout . pointer_size ( ) . bits ( ) ;
4081 match field. name {
4182 sym:: kind => {
4283 let variant_index = match ty. kind ( ) {
4384 ty:: Tuple ( fields) => {
44- let ( variant, variant_place) = downcast ( sym:: Tuple ) ?;
85+ let ( variant, variant_place) =
86+ self . downcast ( & field_dest, sym:: Tuple ) ?;
4587 // project to the single tuple variant field of `type_info::Tuple` struct type
4688 let tuple_place = self . project_field ( & variant_place, FieldIdx :: ZERO ) ?;
4789 assert_eq ! (
@@ -55,35 +97,42 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
5597 . fields
5698 . len( )
5799 ) ;
58- self . write_tuple_fields ( tuple_place, fields, ty) ?;
100+ self . write_tuple_type_info ( tuple_place, fields, ty) ?;
59101 variant
60102 }
61103 ty:: Array ( ty, len) => {
62- let ( variant, variant_place) = downcast ( sym:: Array ) ?;
104+ let ( variant, variant_place) =
105+ self . downcast ( & field_dest, sym:: Array ) ?;
63106 let array_place = self . project_field ( & variant_place, FieldIdx :: ZERO ) ?;
64107
65108 self . write_array_type_info ( array_place, * ty, * len) ?;
66109
67110 variant
68111 }
69112 ty:: Slice ( ty) => {
70- let ( variant, variant_place) = downcast ( sym:: Slice ) ?;
113+ let ( variant, variant_place) =
114+ self . downcast ( & field_dest, sym:: Slice ) ?;
71115 let slice_place = self . project_field ( & variant_place, FieldIdx :: ZERO ) ?;
72116
73117 self . write_slice_type_info ( slice_place, * ty) ?;
74118
75119 variant
76120 }
121+ ty:: Adt ( adt_def, generics) => {
122+ self . write_adt_type_info ( & field_dest, ( ty, * adt_def) , generics) ?
123+ }
77124 ty:: Bool => {
78- let ( variant, _variant_place) = downcast ( sym:: Bool ) ?;
125+ let ( variant, _variant_place) =
126+ self . downcast ( & field_dest, sym:: Bool ) ?;
79127 variant
80128 }
81129 ty:: Char => {
82- let ( variant, _variant_place) = downcast ( sym:: Char ) ?;
130+ let ( variant, _variant_place) =
131+ self . downcast ( & field_dest, sym:: Char ) ?;
83132 variant
84133 }
85134 ty:: Int ( int_ty) => {
86- let ( variant, variant_place) = downcast ( sym:: Int ) ?;
135+ let ( variant, variant_place) = self . downcast ( & field_dest , sym:: Int ) ?;
87136 let place = self . project_field ( & variant_place, FieldIdx :: ZERO ) ?;
88137 self . write_int_type_info (
89138 place,
@@ -93,7 +142,7 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
93142 variant
94143 }
95144 ty:: Uint ( uint_ty) => {
96- let ( variant, variant_place) = downcast ( sym:: Int ) ?;
145+ let ( variant, variant_place) = self . downcast ( & field_dest , sym:: Int ) ?;
97146 let place = self . project_field ( & variant_place, FieldIdx :: ZERO ) ?;
98147 self . write_int_type_info (
99148 place,
@@ -103,25 +152,28 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
103152 variant
104153 }
105154 ty:: Float ( float_ty) => {
106- let ( variant, variant_place) = downcast ( sym:: Float ) ?;
155+ let ( variant, variant_place) =
156+ self . downcast ( & field_dest, sym:: Float ) ?;
107157 let place = self . project_field ( & variant_place, FieldIdx :: ZERO ) ?;
108158 self . write_float_type_info ( place, float_ty. bit_width ( ) ) ?;
109159 variant
110160 }
111161 ty:: Str => {
112- let ( variant, _variant_place) = downcast ( sym:: Str ) ?;
162+ let ( variant, _variant_place) = self . downcast ( & field_dest , sym:: Str ) ?;
113163 variant
114164 }
115165 ty:: Ref ( _, ty, mutability) => {
116- let ( variant, variant_place) = downcast ( sym:: Reference ) ?;
166+ let ( variant, variant_place) =
167+ self . downcast ( & field_dest, sym:: Reference ) ?;
117168 let reference_place =
118169 self . project_field ( & variant_place, FieldIdx :: ZERO ) ?;
119170 self . write_reference_type_info ( reference_place, * ty, * mutability) ?;
120171
121172 variant
122173 }
123174 ty:: RawPtr ( ty, mutability) => {
124- let ( variant, variant_place) = downcast ( sym:: Pointer ) ?;
175+ let ( variant, variant_place) =
176+ self . downcast ( & field_dest, sym:: Pointer ) ?;
125177 let pointer_place =
126178 self . project_field ( & variant_place, FieldIdx :: ZERO ) ?;
127179
@@ -130,13 +182,13 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
130182 variant
131183 }
132184 ty:: Dynamic ( predicates, region) => {
133- let ( variant, variant_place) = downcast ( sym:: DynTrait ) ?;
185+ let ( variant, variant_place) =
186+ self . downcast ( & field_dest, sym:: DynTrait ) ?;
134187 let dyn_place = self . project_field ( & variant_place, FieldIdx :: ZERO ) ?;
135188 self . write_dyn_trait_type_info ( dyn_place, * predicates, * region) ?;
136189 variant
137190 }
138- ty:: Adt ( _, _)
139- | ty:: Foreign ( _)
191+ ty:: Foreign ( _)
140192 | ty:: Pat ( _, _)
141193 | ty:: FnDef ( ..)
142194 | ty:: FnPtr ( ..)
@@ -151,14 +203,14 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
151203 | ty:: Bound ( ..)
152204 | ty:: Placeholder ( _)
153205 | ty:: Infer ( ..)
154- | ty:: Error ( _) => downcast ( sym:: Other ) ?. 0 ,
206+ | ty:: Error ( _) => self . downcast ( & field_dest , sym:: Other ) ?. 0 ,
155207 } ;
156208 self . write_discriminant ( variant_index, & field_dest) ?
157209 }
158210 sym:: size => {
159211 let layout = self . layout_of ( ty) ?;
160212 let variant_index = if layout. is_sized ( ) {
161- let ( variant, variant_place) = downcast ( sym:: Some ) ?;
213+ let ( variant, variant_place) = self . downcast ( & field_dest , sym:: Some ) ?;
162214 let size_field_place =
163215 self . project_field ( & variant_place, FieldIdx :: ZERO ) ?;
164216 self . write_scalar (
@@ -168,7 +220,7 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
168220 ) ?;
169221 variant
170222 } else {
171- downcast ( sym:: None ) ?. 0
223+ self . downcast ( & field_dest , sym:: None ) ?. 0
172224 } ;
173225 self . write_discriminant ( variant_index, & field_dest) ?;
174226 }
@@ -179,54 +231,32 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
179231 interp_ok ( ( ) )
180232 }
181233
182- pub ( crate ) fn write_tuple_fields (
183- & mut self ,
184- tuple_place : impl Writeable < ' tcx , CtfeProvenance > ,
185- fields : & [ Ty < ' tcx > ] ,
186- tuple_ty : Ty < ' tcx > ,
187- ) -> InterpResult < ' tcx > {
188- // project into the `type_info::Tuple::fields` field
189- let fields_slice_place = self . project_field ( & tuple_place, FieldIdx :: ZERO ) ?;
190- // get the `type_info::Field` type from `fields: &[Field]`
191- let field_type = fields_slice_place
192- . layout ( )
193- . ty
194- . builtin_deref ( false )
195- . unwrap ( )
196- . sequence_element_type ( self . tcx . tcx ) ;
197- // Create an array with as many elements as the number of fields in the inspected tuple
198- let fields_layout =
199- self . layout_of ( Ty :: new_array ( self . tcx . tcx , field_type, fields. len ( ) as u64 ) ) ?;
200- let fields_place = self . allocate ( fields_layout, MemoryKind :: Stack ) ?;
201- let mut fields_places = self . project_array_fields ( & fields_place) ?;
202-
203- let tuple_layout = self . layout_of ( tuple_ty) ?;
204-
205- while let Some ( ( i, place) ) = fields_places. next ( self ) ? {
206- let field_ty = fields[ i as usize ] ;
207- self . write_field ( field_ty, place, tuple_layout, i) ?;
208- }
209-
210- let fields_place = fields_place. map_provenance ( CtfeProvenance :: as_immutable) ;
211-
212- let ptr = Immediate :: new_slice ( fields_place. ptr ( ) , fields. len ( ) as u64 , self ) ;
213-
214- self . write_immediate ( ptr, & fields_slice_place)
215- }
216-
217234 fn write_field (
218235 & mut self ,
219236 field_ty : Ty < ' tcx > ,
220237 place : MPlaceTy < ' tcx > ,
221238 layout : TyAndLayout < ' tcx > ,
239+ name : Option < Symbol > ,
222240 idx : u64 ,
223241 ) -> InterpResult < ' tcx > {
224242 for ( field_idx, field_ty_field) in
225243 place. layout . ty . ty_adt_def ( ) . unwrap ( ) . non_enum_variant ( ) . fields . iter_enumerated ( )
226244 {
227245 let field_place = self . project_field ( & place, field_idx) ?;
228246 match field_ty_field. name {
229- sym:: ty => self . write_type_id ( field_ty, & field_place) ?,
247+ sym:: name => {
248+ let name = match name. as_ref ( ) {
249+ Some ( name) => Cow :: Borrowed ( name. as_str ( ) ) ,
250+ None => Cow :: Owned ( idx. to_string ( ) ) , // For tuples
251+ } ;
252+ let name_place = self . allocate_str_dedup ( & name) ?;
253+ let ptr = self . mplace_to_ref ( & name_place) ?;
254+ self . write_immediate ( * ptr, & field_place) ?
255+ }
256+ sym:: ty => {
257+ let field_ty = self . tcx . erase_and_anonymize_regions ( field_ty) ;
258+ self . write_type_id ( field_ty, & field_place) ?
259+ }
230260 sym:: offset => {
231261 let offset = layout. fields . offset ( idx as usize ) ;
232262 self . write_scalar (
@@ -242,6 +272,24 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
242272 interp_ok ( ( ) )
243273 }
244274
275+ pub ( crate ) fn write_tuple_type_info (
276+ & mut self ,
277+ tuple_place : impl Writeable < ' tcx , CtfeProvenance > ,
278+ fields : & [ Ty < ' tcx > ] ,
279+ tuple_ty : Ty < ' tcx > ,
280+ ) -> InterpResult < ' tcx > {
281+ let tuple_layout = self . layout_of ( tuple_ty) ?;
282+ let fields_slice_place = self . project_field ( & tuple_place, FieldIdx :: ZERO ) ?;
283+ self . allocate_fill_and_write_slice_ptr (
284+ fields_slice_place,
285+ fields. len ( ) as u64 ,
286+ |this, i, place| {
287+ let field_ty = fields[ i as usize ] ;
288+ this. write_field ( field_ty, place, tuple_layout, None , i)
289+ } ,
290+ )
291+ }
292+
245293 pub ( crate ) fn write_array_type_info (
246294 & mut self ,
247295 place : impl Writeable < ' tcx , CtfeProvenance > ,
0 commit comments