@@ -4,9 +4,12 @@ use rustc_abi::{FieldIdx, VariantIdx};
44use rustc_ast:: Mutability ;
55use rustc_hir:: LangItem ;
66use rustc_middle:: mir:: interpret:: { CtfeProvenance , Scalar } ;
7- use rustc_middle:: span_bug;
87use rustc_middle:: ty:: layout:: TyAndLayout ;
9- use rustc_middle:: ty:: { self , AdtDef , AdtKind , Const , GenericArgs , ScalarInt , Ty , VariantDef } ;
8+ use rustc_middle:: ty:: {
9+ self , AdtDef , AdtKind , Const , ConstKind , GenericArgKind , GenericArgs , Region , ScalarInt , Ty ,
10+ VariantDef ,
11+ } ;
12+ use rustc_middle:: { bug, span_bug} ;
1013use rustc_span:: { Symbol , sym} ;
1114
1215use crate :: const_eval:: CompileTimeMachine ;
@@ -30,6 +33,37 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
3033 interp_ok ( ( variant_id, self . project_downcast ( place, variant_id) ?) )
3134 }
3235
36+ // A general method to write an array to a static slice place.
37+ fn project_write_array (
38+ & mut self ,
39+ slice_place : impl Writeable < ' tcx , CtfeProvenance > ,
40+ len : usize ,
41+ writer : impl Fn ( & mut Self , /* index */ usize , 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 as u64 ) ) ?;
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 as usize , 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 as u64 , self ) ;
64+ self . write_immediate ( ptr, & slice_place)
65+ }
66+
3367 /// Writes a `core::mem::type_info::TypeInfo` for a given type, `ty` to the given place.
3468 pub ( crate ) fn write_type_info (
3569 & mut self ,
@@ -183,6 +217,7 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
183217 interp_ok ( ( ) )
184218 }
185219
220+ // TODO(type_info): Remove this method, use `project_write_array` as it's more general.
186221 pub ( crate ) fn write_tuple_fields (
187222 & mut self ,
188223 tuple_place : impl Writeable < ' tcx , CtfeProvenance > ,
@@ -314,6 +349,18 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
314349 let field_place = self . project_field ( & place, field_idx) ?;
315350
316351 match field. name {
352+ sym:: generics => {
353+ self . project_write_array ( field_place, generics. len ( ) , |this, i, place| {
354+ match generics[ i] . kind ( ) {
355+ GenericArgKind :: Lifetime ( region) => {
356+ this. write_generic_lifetime ( region, place)
357+ }
358+ GenericArgKind :: Type ( ty) => this. write_generic_type ( ty, place) ,
359+ GenericArgKind :: Const ( c) => this. write_generic_const ( c, place) ,
360+ }
361+ } ) ?;
362+ }
363+ // TODO(type_info): Use method `project_write_array` as it's more general.
317364 sym:: fields => {
318365 let fields_slice_place = field_place;
319366 let field_type = fields_slice_place
@@ -356,6 +403,66 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
356403 interp_ok ( ( ) )
357404 }
358405
406+ fn write_generic_lifetime (
407+ & mut self ,
408+ _region : Region < ' tcx > ,
409+ place : MPlaceTy < ' tcx > ,
410+ ) -> InterpResult < ' tcx > {
411+ let ( variant_idx, _) = self . downcast ( & place, sym:: Lifetime ) ?;
412+ self . write_discriminant ( variant_idx, & place) ?;
413+ interp_ok ( ( ) )
414+ }
415+
416+ fn write_generic_type ( & mut self , ty : Ty < ' tcx > , place : MPlaceTy < ' tcx > ) -> InterpResult < ' tcx > {
417+ let ( variant_idx, variant_place) = self . downcast ( & place, sym:: Type ) ?;
418+ let generic_type_place = self . project_field ( & variant_place, FieldIdx :: ZERO ) ?;
419+
420+ for ( field_idx, field_def) in generic_type_place
421+ . layout ( )
422+ . ty
423+ . ty_adt_def ( )
424+ . unwrap ( )
425+ . non_enum_variant ( )
426+ . fields
427+ . iter_enumerated ( )
428+ {
429+ let field_place = self . project_field ( & generic_type_place, field_idx) ?;
430+ match field_def. name {
431+ sym:: ty => self . write_type_id ( ty, & field_place) ?,
432+ other => span_bug ! ( self . tcx. def_span( field_def. did) , "unimplemented field {other}" ) ,
433+ }
434+ }
435+
436+ self . write_discriminant ( variant_idx, & place) ?;
437+ interp_ok ( ( ) )
438+ }
439+
440+ fn write_generic_const ( & mut self , c : Const < ' tcx > , place : MPlaceTy < ' tcx > ) -> InterpResult < ' tcx > {
441+ let ConstKind :: Value ( c) = c. kind ( ) else { bug ! ( "expected a computed const, got {c:?}" ) } ;
442+
443+ let ( variant_idx, variant_place) = self . downcast ( & place, sym:: Const ) ?;
444+ let const_place = self . project_field ( & variant_place, FieldIdx :: ZERO ) ?;
445+
446+ for ( field_idx, field_def) in const_place
447+ . layout ( )
448+ . ty
449+ . ty_adt_def ( )
450+ . unwrap ( )
451+ . non_enum_variant ( )
452+ . fields
453+ . iter_enumerated ( )
454+ {
455+ let field_place = self . project_field ( & const_place, field_idx) ?;
456+ match field_def. name {
457+ sym:: ty => self . write_type_id ( c. ty , & field_place) ?,
458+ other => span_bug ! ( self . tcx. def_span( field_def. did) , "unimplemented field {other}" ) ,
459+ }
460+ }
461+
462+ self . write_discriminant ( variant_idx, & place) ?;
463+ interp_ok ( ( ) )
464+ }
465+
359466 fn write_int_type_info (
360467 & mut self ,
361468 place : impl Writeable < ' tcx , CtfeProvenance > ,
0 commit comments