@@ -4,7 +4,8 @@ use rustc_hir::LangItem;
44use rustc_middle:: mir:: interpret:: { CtfeProvenance , Scalar } ;
55use rustc_middle:: span_bug;
66use rustc_middle:: ty:: layout:: TyAndLayout ;
7- use rustc_middle:: ty:: { self , Const , ScalarInt , Ty } ;
7+ use rustc_middle:: ty:: { self , Const , Region , ScalarInt , Ty } ;
8+ use rustc_span:: def_id:: DefId ;
89use rustc_span:: { Symbol , sym} ;
910
1011use crate :: const_eval:: CompileTimeMachine ;
@@ -112,6 +113,12 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
112113
113114 variant
114115 }
116+ ty:: Dynamic ( predicates, region) => {
117+ let ( variant, variant_place) = downcast ( sym:: DynTrait ) ?;
118+ let dyn_place = self . project_field ( & variant_place, FieldIdx :: ZERO ) ?;
119+ self . write_dyn_trait_type_info ( dyn_place, * predicates, * region) ?;
120+ variant
121+ }
115122 ty:: Adt ( _, _)
116123 | ty:: Foreign ( _)
117124 | ty:: Pat ( _, _)
@@ -120,7 +127,6 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
120127 | ty:: FnDef ( ..)
121128 | ty:: FnPtr ( ..)
122129 | ty:: UnsafeBinder ( ..)
123- | ty:: Dynamic ( ..)
124130 | ty:: Closure ( ..)
125131 | ty:: CoroutineClosure ( ..)
126132 | ty:: Coroutine ( ..)
@@ -159,6 +165,140 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
159165 interp_ok ( ( ) )
160166 }
161167
168+ fn write_dyn_trait_type_info (
169+ & mut self ,
170+ dyn_place : impl Writeable < ' tcx , CtfeProvenance > ,
171+ data : & ' tcx ty:: List < ty:: Binder < ' tcx , ty:: ExistentialPredicate < ' tcx > > > ,
172+ region : Region < ' tcx > ,
173+ ) -> InterpResult < ' tcx > {
174+ let tcx = self . tcx . tcx ;
175+
176+ // Find the principal trait ref (for super trait collection), collect auto traits,
177+ // and collect all projection predicates (used when computing TypeId for each supertrait).
178+ let mut principal: Option < ty:: Binder < ' tcx , ty:: ExistentialTraitRef < ' tcx > > > = None ;
179+ let mut auto_traits_def_ids: Vec < ty:: Binder < ' tcx , DefId > > = Vec :: new ( ) ;
180+ let mut projections: Vec < ty:: Binder < ' tcx , ty:: ExistentialProjection < ' tcx > > > = Vec :: new ( ) ;
181+
182+ for b in data. iter ( ) {
183+ match b. skip_binder ( ) {
184+ ty:: ExistentialPredicate :: Trait ( tr) => principal = Some ( b. rebind ( tr) ) ,
185+ ty:: ExistentialPredicate :: AutoTrait ( did) => auto_traits_def_ids. push ( b. rebind ( did) ) ,
186+ ty:: ExistentialPredicate :: Projection ( p) => projections. push ( b. rebind ( p) ) ,
187+ }
188+ }
189+
190+ // This is to make principal dyn type include Trait and projection predicates, excluding auto traits.
191+ let principal_ty: Option < Ty < ' tcx > > = principal. map ( |_tr| {
192+ let preds = tcx
193+ . mk_poly_existential_predicates_from_iter ( data. iter ( ) . filter ( |b| {
194+ !matches ! ( b. skip_binder( ) , ty:: ExistentialPredicate :: AutoTrait ( _) )
195+ } ) ) ;
196+ Ty :: new_dynamic ( tcx, preds, region)
197+ } ) ;
198+
199+ // DynTrait { predicates: &'static [Trait] }
200+ for ( field_idx, field) in
201+ dyn_place. layout ( ) . ty . ty_adt_def ( ) . unwrap ( ) . non_enum_variant ( ) . fields . iter_enumerated ( )
202+ {
203+ let field_place = self . project_field ( & dyn_place, field_idx) ?;
204+ match field. name {
205+ sym:: predicates => {
206+ self . write_dyn_trait_predicates_slice (
207+ & field_place,
208+ principal_ty,
209+ & auto_traits_def_ids,
210+ region,
211+ ) ?;
212+ }
213+ other => {
214+ span_bug ! ( self . tcx. def_span( field. did) , "unimplemented DynTrait field {other}" )
215+ }
216+ }
217+ }
218+
219+ interp_ok ( ( ) )
220+ }
221+
222+ fn mk_dyn_principal_auto_trait_ty (
223+ & self ,
224+ auto_trait_def_id : ty:: Binder < ' tcx , DefId > ,
225+ region : Region < ' tcx > ,
226+ ) -> Ty < ' tcx > {
227+ let tcx = self . tcx . tcx ;
228+
229+ // Preserve the binder vars from the original auto-trait predicate.
230+ let pred_inner = ty:: ExistentialPredicate :: AutoTrait ( auto_trait_def_id. skip_binder ( ) ) ;
231+ let pred = ty:: Binder :: bind_with_vars ( pred_inner, auto_trait_def_id. bound_vars ( ) ) ;
232+
233+ let preds = tcx. mk_poly_existential_predicates_from_iter ( [ pred] . into_iter ( ) ) ;
234+ Ty :: new_dynamic ( tcx, preds, region)
235+ }
236+
237+ fn write_dyn_trait_predicates_slice (
238+ & mut self ,
239+ slice_place : & impl Writeable < ' tcx , CtfeProvenance > ,
240+ principal_ty : Option < Ty < ' tcx > > ,
241+ auto_trait_def_ids : & [ ty:: Binder < ' tcx , DefId > ] ,
242+ region : Region < ' tcx > ,
243+ ) -> InterpResult < ' tcx > {
244+ let tcx = self . tcx . tcx ;
245+
246+ // total entries in DynTrait predicates
247+ let total_len = principal_ty. map ( |_| 1 ) . unwrap_or ( 0 ) + auto_trait_def_ids. len ( ) ;
248+
249+ // element type = Trait
250+ let slice_ty = slice_place. layout ( ) . ty . builtin_deref ( false ) . unwrap ( ) ; // [Trait]
251+ let elem_ty = slice_ty. sequence_element_type ( tcx) ; // Trait
252+
253+ let arr_layout = self . layout_of ( Ty :: new_array ( tcx, elem_ty, total_len as u64 ) ) ?;
254+ let arr_place = self . allocate ( arr_layout, MemoryKind :: Stack ) ?;
255+ let mut elems = self . project_array_fields ( & arr_place) ?;
256+
257+ // principal entry (if any)
258+ if let Some ( principal_ty) = principal_ty {
259+ let Some ( ( _i, elem_place) ) = elems. next ( self ) ? else {
260+ span_bug ! ( self . tcx. span, "DynTrait.predicates length computed wrong (principal)" ) ;
261+ } ;
262+ self . write_dyn_trait_trait ( elem_place, principal_ty, false ) ?;
263+ }
264+
265+ // auto trait entries
266+ for auto in auto_trait_def_ids {
267+ let Some ( ( _i, elem_place) ) = elems. next ( self ) ? else {
268+ span_bug ! ( self . tcx. span, "DynTrait.predicates length computed wrong (auto)" ) ;
269+ } ;
270+ let auto_ty = self . mk_dyn_principal_auto_trait_ty ( * auto, region) ;
271+ self . write_dyn_trait_trait ( elem_place, auto_ty, true ) ?;
272+ }
273+ let arr_place = arr_place. map_provenance ( CtfeProvenance :: as_immutable) ;
274+ let imm = Immediate :: new_slice ( arr_place. ptr ( ) , total_len as u64 , self ) ;
275+ self . write_immediate ( imm, slice_place)
276+ }
277+
278+ fn write_dyn_trait_trait (
279+ & mut self ,
280+ trait_place : MPlaceTy < ' tcx > ,
281+ trait_ty : Ty < ' tcx > ,
282+ is_auto : bool ,
283+ ) -> InterpResult < ' tcx > {
284+ // Trait { super_traits: &'static [TypeId], is_auto: bool }
285+ for ( field_idx, field) in
286+ trait_place. layout . ty . ty_adt_def ( ) . unwrap ( ) . non_enum_variant ( ) . fields . iter_enumerated ( )
287+ {
288+ let field_place = self . project_field ( & trait_place, field_idx) ?;
289+ match field. name {
290+ sym:: ty => {
291+ self . write_type_id ( trait_ty, & field_place) ?;
292+ }
293+ sym:: is_auto => self . write_scalar ( Scalar :: from_bool ( is_auto) , & field_place) ?,
294+ other => {
295+ span_bug ! ( self . tcx. def_span( field. did) , "unimplemented Trait field {other}" )
296+ }
297+ }
298+ }
299+ interp_ok ( ( ) )
300+ }
301+
162302 pub ( crate ) fn write_tuple_fields (
163303 & mut self ,
164304 tuple_place : impl Writeable < ' tcx , CtfeProvenance > ,
0 commit comments