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