@@ -110,15 +110,11 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
110110 variant
111111 }
112112 ty:: Adt ( adt_def, generics) => {
113- // TODO(type_info): Handle enum and union
114- if !adt_def. is_struct ( ) {
113+ // TODO(type_info): Handle union
114+ if !adt_def. is_struct ( ) && !adt_def . is_enum ( ) {
115115 self . downcast ( & field_dest, sym:: Other ) ?. 0
116116 } else {
117- let ( variant, variant_place) =
118- self . downcast ( & field_dest, sym:: Struct ) ?;
119- let place = self . project_field ( & variant_place, FieldIdx :: ZERO ) ?;
120- self . write_adt_type_info ( place, ( ty, * adt_def) , generics) ?;
121- variant
117+ self . write_adt_type_info ( & field_dest, ( ty, * adt_def) , generics) ?
122118 }
123119 }
124120 ty:: Bool => {
@@ -253,6 +249,21 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
253249 self . write_immediate ( ptr, & fields_slice_place)
254250 }
255251
252+ // Write fields for struct, enum variants
253+ fn write_variant_fields (
254+ & mut self ,
255+ place : impl Writeable < ' tcx , CtfeProvenance > ,
256+ variant_def : & ' tcx VariantDef ,
257+ variant_layout : TyAndLayout < ' tcx > ,
258+ generics : & ' tcx GenericArgs < ' tcx > ,
259+ ) -> InterpResult < ' tcx > {
260+ self . project_write_array ( place, variant_def. fields . len ( ) as u64 , |this, i, place| {
261+ let field_def = & variant_def. fields [ FieldIdx :: from_usize ( i as usize ) ] ;
262+ let field_ty = field_def. ty ( * this. tcx , generics) ;
263+ this. write_field ( field_ty, place, variant_layout, Some ( field_def. name ) , i)
264+ } )
265+ }
266+
256267 fn write_field (
257268 & mut self ,
258269 field_ty : Ty < ' tcx > ,
@@ -318,20 +329,31 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
318329 // FIXME(type_info): No semver considerations for now
319330 pub ( crate ) fn write_adt_type_info (
320331 & mut self ,
321- place : impl Writeable < ' tcx , CtfeProvenance > ,
332+ place : & ( impl Writeable < ' tcx , CtfeProvenance > + ' tcx ) ,
322333 adt : ( Ty < ' tcx > , AdtDef < ' tcx > ) ,
323334 generics : & ' tcx GenericArgs < ' tcx > ,
324- ) -> InterpResult < ' tcx > {
335+ ) -> InterpResult < ' tcx , VariantIdx > {
325336 let ( adt_ty, adt_def) = adt;
326- match adt_def. adt_kind ( ) {
327- AdtKind :: Struct => self . write_struct_type_info (
328- place,
329- ( adt_ty, adt_def. variant ( VariantIdx :: ZERO ) ) ,
330- generics,
331- ) ,
337+ let variant_idx = match adt_def. adt_kind ( ) {
338+ AdtKind :: Struct => {
339+ let ( variant, variant_place) = self . downcast ( place, sym:: Struct ) ?;
340+ let place = self . project_field ( & variant_place, FieldIdx :: ZERO ) ?;
341+ self . write_struct_type_info (
342+ place,
343+ ( adt_ty, adt_def. variant ( VariantIdx :: ZERO ) ) ,
344+ generics,
345+ ) ?;
346+ variant
347+ }
348+ AdtKind :: Enum => {
349+ let ( variant, variant_place) = self . downcast ( place, sym:: Enum ) ?;
350+ let place = self . project_field ( & variant_place, FieldIdx :: ZERO ) ?;
351+ self . write_enum_type_info ( place, adt, generics) ?;
352+ variant
353+ }
332354 AdtKind :: Union => todo ! ( ) ,
333- AdtKind :: Enum => todo ! ( ) ,
334- }
355+ } ;
356+ interp_ok ( variant_idx )
335357 }
336358
337359 pub ( crate ) fn write_struct_type_info (
@@ -350,15 +372,9 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
350372
351373 match field. name {
352374 sym:: generics => self . write_generics ( field_place, generics) ?,
353- sym:: fields => self . project_write_array (
354- field_place,
355- struct_def. fields . len ( ) as u64 ,
356- |this, i, place| {
357- let field_def = & struct_def. fields [ FieldIdx :: from_usize ( i as usize ) ] ;
358- let field_ty = field_def. ty ( * this. tcx , generics) ;
359- this. write_field ( field_ty, place, struct_layout, Some ( field_def. name ) , i)
360- } ,
361- ) ?,
375+ sym:: fields => {
376+ self . write_variant_fields ( field_place, struct_def, struct_layout, generics) ?
377+ }
362378 sym:: non_exhaustive => {
363379 let is_non_exhaustive = struct_def. is_field_list_non_exhaustive ( ) ;
364380 self . write_scalar ( Scalar :: from_bool ( is_non_exhaustive) , & field_place) ?
@@ -371,6 +387,77 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
371387 interp_ok ( ( ) )
372388 }
373389
390+ pub ( crate ) fn write_enum_type_info (
391+ & mut self ,
392+ place : impl Writeable < ' tcx , CtfeProvenance > ,
393+ enum_ : ( Ty < ' tcx > , AdtDef < ' tcx > ) ,
394+ generics : & ' tcx GenericArgs < ' tcx > ,
395+ ) -> InterpResult < ' tcx > {
396+ let ( enum_ty, enum_def) = enum_;
397+ let enum_layout = self . layout_of ( enum_ty) ?;
398+
399+ for ( field_idx, field) in
400+ place. layout ( ) . ty . ty_adt_def ( ) . unwrap ( ) . non_enum_variant ( ) . fields . iter_enumerated ( )
401+ {
402+ let field_place = self . project_field ( & place, field_idx) ?;
403+
404+ match field. name {
405+ sym:: generics => self . write_generics ( field_place, generics) ?,
406+ sym:: variants => {
407+ self . project_write_array (
408+ field_place,
409+ enum_def. variants ( ) . len ( ) as u64 ,
410+ |this, i, place| {
411+ let variant_idx = VariantIdx :: from_usize ( i as usize ) ;
412+ let variant_def = & enum_def. variants ( ) [ variant_idx] ;
413+ let variant_layout = enum_layout. for_variant ( this, variant_idx) ;
414+ // TODO(type_info): Is it correct to use enum_ty here? If yes, leave some explanation.
415+ this. write_enum_variant ( place, ( variant_layout, & variant_def) , generics)
416+ } ,
417+ ) ?;
418+ }
419+ sym:: non_exhaustive => {
420+ let is_non_exhaustive = enum_def. is_variant_list_non_exhaustive ( ) ;
421+ self . write_scalar ( Scalar :: from_bool ( is_non_exhaustive) , & field_place) ?
422+ }
423+ other => span_bug ! ( self . tcx. def_span( field. did) , "unimplemented field {other}" ) ,
424+ }
425+ }
426+
427+ interp_ok ( ( ) )
428+ }
429+
430+ fn write_enum_variant (
431+ & mut self ,
432+ place : impl Writeable < ' tcx , CtfeProvenance > ,
433+ variant : ( TyAndLayout < ' tcx > , & ' tcx VariantDef ) ,
434+ generics : & ' tcx GenericArgs < ' tcx > ,
435+ ) -> InterpResult < ' tcx > {
436+ let ( variant_layout, variant_def) = variant;
437+
438+ for ( field_idx, field_def) in
439+ place. layout ( ) . ty . ty_adt_def ( ) . unwrap ( ) . non_enum_variant ( ) . fields . iter_enumerated ( )
440+ {
441+ let field_place = self . project_field ( & place, field_idx) ?;
442+ match field_def. name {
443+ sym:: name => {
444+ let name_place = self . allocate_str_dedup ( variant_def. name . as_str ( ) ) ?;
445+ let ptr = self . mplace_to_ref ( & name_place) ?;
446+ self . write_immediate ( * ptr, & field_place) ?
447+ }
448+ sym:: fields => {
449+ self . write_variant_fields ( field_place, & variant_def, variant_layout, generics) ?
450+ }
451+ sym:: non_exhaustive => {
452+ let is_non_exhaustive = variant_def. is_field_list_non_exhaustive ( ) ;
453+ self . write_scalar ( Scalar :: from_bool ( is_non_exhaustive) , & field_place) ?
454+ }
455+ other => span_bug ! ( self . tcx. def_span( field_def. did) , "unimplemented field {other}" ) ,
456+ }
457+ }
458+ interp_ok ( ( ) )
459+ }
460+
374461 fn write_generics (
375462 & mut self ,
376463 place : impl Writeable < ' tcx , CtfeProvenance > ,
0 commit comments