@@ -3,7 +3,8 @@ use rustc_ast::Mutability;
33use rustc_hir:: LangItem ;
44use rustc_middle:: span_bug;
55use rustc_middle:: ty:: layout:: TyAndLayout ;
6- use rustc_middle:: ty:: { self , Const , ScalarInt , Ty } ;
6+ use rustc_middle:: ty:: { self , Const , Region , ScalarInt , Ty } ;
7+ use rustc_span:: def_id:: DefId ;
78use rustc_span:: { Symbol , sym} ;
89
910use crate :: const_eval:: CompileTimeMachine ;
@@ -121,14 +122,19 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
121122
122123 variant
123124 }
125+ ty:: Dynamic ( predicates, region) => {
126+ let ( variant, variant_place) = downcast ( sym:: DynTrait ) ?;
127+ let dyn_place = self . project_field ( & variant_place, FieldIdx :: ZERO ) ?;
128+ self . write_dyn_trait_type_info ( dyn_place, * predicates, * region) ?;
129+ variant
130+ }
124131 ty:: Adt ( _, _)
125132 | ty:: Foreign ( _)
126133 | ty:: Pat ( _, _)
127134 | ty:: Slice ( _)
128135 | ty:: FnDef ( ..)
129136 | ty:: FnPtr ( ..)
130137 | ty:: UnsafeBinder ( ..)
131- | ty:: Dynamic ( ..)
132138 | ty:: Closure ( ..)
133139 | ty:: CoroutineClosure ( ..)
134140 | ty:: Coroutine ( ..)
@@ -167,6 +173,175 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
167173 interp_ok ( ( ) )
168174 }
169175
176+ fn write_dyn_trait_type_info (
177+ & mut self ,
178+ dyn_place : impl Writeable < ' tcx , CtfeProvenance > ,
179+ data : & ' tcx ty:: List < ty:: Binder < ' tcx , ty:: ExistentialPredicate < ' tcx > > > ,
180+ region : Region < ' tcx > ,
181+ ) -> InterpResult < ' tcx > {
182+ let tcx = self . tcx . tcx ;
183+
184+ // Find the principal trait ref (for super trait collection), collect auto traits,
185+ // and collect all projection predicates (used when computing TypeId for each supertrait).
186+ let mut principal: Option < ty:: Binder < ' tcx , ty:: ExistentialTraitRef < ' tcx > > > = None ;
187+ let mut auto_traits_def_ids: Vec < ty:: Binder < ' tcx , DefId > > = Vec :: new ( ) ;
188+ let mut projections: Vec < ty:: Binder < ' tcx , ty:: ExistentialProjection < ' tcx > > > = Vec :: new ( ) ;
189+
190+ for b in data. iter ( ) {
191+ match b. skip_binder ( ) {
192+ ty:: ExistentialPredicate :: Trait ( tr) => principal = Some ( b. rebind ( tr) ) ,
193+ ty:: ExistentialPredicate :: AutoTrait ( did) => auto_traits_def_ids. push ( b. rebind ( did) ) ,
194+ ty:: ExistentialPredicate :: Projection ( p) => projections. push ( b. rebind ( p) ) ,
195+ }
196+ }
197+
198+ // This is to make principal dyn type include Trait and projection predicates, excluding auto traits.
199+ let principal_ty: Option < Ty < ' tcx > > = principal. map ( |_tr| {
200+ let preds = tcx
201+ . mk_poly_existential_predicates_from_iter ( data. iter ( ) . filter ( |b| {
202+ !matches ! ( b. skip_binder( ) , ty:: ExistentialPredicate :: AutoTrait ( _) )
203+ } ) ) ;
204+ Ty :: new_dynamic ( tcx, preds, region)
205+ } ) ;
206+
207+ // DynTrait { predicates: &'static [Trait] }
208+ for ( field_idx, field) in
209+ dyn_place. layout ( ) . ty . ty_adt_def ( ) . unwrap ( ) . non_enum_variant ( ) . fields . iter_enumerated ( )
210+ {
211+ let field_place = self . project_field ( & dyn_place, field_idx) ?;
212+ match field. name {
213+ sym:: predicates => {
214+ self . write_dyn_trait_predicates_slice (
215+ & field_place,
216+ principal_ty,
217+ & auto_traits_def_ids,
218+ region,
219+ ) ?;
220+ }
221+ other => {
222+ span_bug ! ( self . tcx. def_span( field. did) , "unimplemented DynTrait field {other}" )
223+ }
224+ }
225+ }
226+
227+ interp_ok ( ( ) )
228+ }
229+
230+ fn mk_dyn_principal_auto_trait_ty (
231+ & self ,
232+ auto_trait_def_id : ty:: Binder < ' tcx , DefId > ,
233+ region : Region < ' tcx > ,
234+ ) -> Ty < ' tcx > {
235+ let tcx = self . tcx . tcx ;
236+
237+ // Preserve the binder vars from the original auto-trait predicate.
238+ let pred_inner = ty:: ExistentialPredicate :: AutoTrait ( auto_trait_def_id. skip_binder ( ) ) ;
239+ let pred = ty:: Binder :: bind_with_vars ( pred_inner, auto_trait_def_id. bound_vars ( ) ) ;
240+
241+ let preds = tcx. mk_poly_existential_predicates_from_iter ( [ pred] . into_iter ( ) ) ;
242+ Ty :: new_dynamic ( tcx, preds, region)
243+ }
244+
245+ fn write_dyn_trait_predicates_slice (
246+ & mut self ,
247+ slice_place : & impl Writeable < ' tcx , CtfeProvenance > ,
248+ principal_ty : Option < Ty < ' tcx > > ,
249+ auto_trait_def_ids : & [ ty:: Binder < ' tcx , DefId > ] ,
250+ region : Region < ' tcx > ,
251+ ) -> InterpResult < ' tcx > {
252+ let tcx = self . tcx . tcx ;
253+
254+ // total entries in DynTrait predicates
255+ let total_len = principal_ty. map ( |_| 1 ) . unwrap_or ( 0 ) + auto_trait_def_ids. len ( ) ;
256+
257+ // element type = DynTraitPredicate
258+ let slice_ty = slice_place. layout ( ) . ty . builtin_deref ( false ) . unwrap ( ) ; // [DynTraitPredicate]
259+ let elem_ty = slice_ty. sequence_element_type ( tcx) ; // DynTraitPredicate
260+
261+ let arr_layout = self . layout_of ( Ty :: new_array ( tcx, elem_ty, total_len as u64 ) ) ?;
262+ let arr_place = self . allocate ( arr_layout, MemoryKind :: Stack ) ?;
263+ let mut elems = self . project_array_fields ( & arr_place) ?;
264+
265+ // principal entry (if any) - NOT an auto trait
266+ if let Some ( principal_ty) = principal_ty {
267+ let Some ( ( _i, elem_place) ) = elems. next ( self ) ? else {
268+ span_bug ! ( self . tcx. span, "DynTrait.predicates length computed wrong (principal)" ) ;
269+ } ;
270+ self . write_dyn_trait_predicate ( elem_place, principal_ty, false ) ?;
271+ }
272+
273+ // auto trait entries - these ARE auto traits
274+ for auto in auto_trait_def_ids {
275+ let Some ( ( _i, elem_place) ) = elems. next ( self ) ? else {
276+ span_bug ! ( self . tcx. span, "DynTrait.predicates length computed wrong (auto)" ) ;
277+ } ;
278+ let auto_ty = self . mk_dyn_principal_auto_trait_ty ( * auto, region) ;
279+ self . write_dyn_trait_predicate ( elem_place, auto_ty, true ) ?;
280+ }
281+
282+ let arr_place = arr_place. map_provenance ( CtfeProvenance :: as_immutable) ;
283+ let imm = Immediate :: new_slice ( arr_place. ptr ( ) , total_len as u64 , self ) ;
284+ self . write_immediate ( imm, slice_place)
285+ }
286+
287+ fn write_dyn_trait_predicate (
288+ & mut self ,
289+ predicate_place : MPlaceTy < ' tcx > ,
290+ trait_ty : Ty < ' tcx > ,
291+ is_auto : bool ,
292+ ) -> InterpResult < ' tcx > {
293+ // DynTraitPredicate { trait_ty: Trait }
294+ for ( field_idx, field) in predicate_place
295+ . layout
296+ . ty
297+ . ty_adt_def ( )
298+ . unwrap ( )
299+ . non_enum_variant ( )
300+ . fields
301+ . iter_enumerated ( )
302+ {
303+ let field_place = self . project_field ( & predicate_place, field_idx) ?;
304+ match field. name {
305+ sym:: trait_ty => {
306+ // Now write the Trait struct
307+ self . write_trait ( field_place, trait_ty, is_auto) ?;
308+ }
309+ other => {
310+ span_bug ! (
311+ self . tcx. def_span( field. did) ,
312+ "unimplemented DynTraitPredicate field {other}"
313+ )
314+ }
315+ }
316+ }
317+ interp_ok ( ( ) )
318+ }
319+ fn write_trait (
320+ & mut self ,
321+ trait_place : MPlaceTy < ' tcx > ,
322+ trait_ty : Ty < ' tcx > ,
323+ is_auto : bool ,
324+ ) -> InterpResult < ' tcx > {
325+ // Trait { ty: TypeId, is_auto: bool }
326+ for ( field_idx, field) in
327+ trait_place. layout . ty . ty_adt_def ( ) . unwrap ( ) . non_enum_variant ( ) . fields . iter_enumerated ( )
328+ {
329+ let field_place = self . project_field ( & trait_place, field_idx) ?;
330+ match field. name {
331+ sym:: ty => {
332+ self . write_type_id ( trait_ty, & field_place) ?;
333+ }
334+ sym:: is_auto => {
335+ self . write_scalar ( Scalar :: from_bool ( is_auto) , & field_place) ?;
336+ }
337+ other => {
338+ span_bug ! ( self . tcx. def_span( field. did) , "unimplemented Trait field {other}" )
339+ }
340+ }
341+ }
342+ interp_ok ( ( ) )
343+ }
344+
170345 pub ( crate ) fn write_tuple_fields (
171346 & mut self ,
172347 tuple_place : impl Writeable < ' tcx , CtfeProvenance > ,
0 commit comments