@@ -196,6 +196,7 @@ impl fmt::Debug for AllocId {
196196enum AllocDiscriminant {
197197 Alloc ,
198198 Fn ,
199+ Vtable ,
199200 Static ,
200201}
201202
@@ -215,6 +216,12 @@ pub fn specialized_encode_alloc_id<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>>(
215216 AllocDiscriminant :: Fn . encode ( encoder) ;
216217 fn_instance. encode ( encoder) ;
217218 }
219+ GlobalAlloc :: Vtable ( ty, poly_trait_ref) => {
220+ trace ! ( "encoding {:?} with {ty:#?}, {poly_trait_ref:#?}" , alloc_id) ;
221+ AllocDiscriminant :: Vtable . encode ( encoder) ;
222+ ty. encode ( encoder) ;
223+ poly_trait_ref. encode ( encoder) ;
224+ }
218225 GlobalAlloc :: Static ( did) => {
219226 assert ! ( !tcx. is_thread_local_static( did) ) ;
220227 // References to statics doesn't need to know about their allocations,
@@ -305,7 +312,7 @@ impl<'s> AllocDecodingSession<'s> {
305312 State :: InProgress ( TinyList :: new_single ( self . session_id ) , alloc_id) ;
306313 Some ( alloc_id)
307314 }
308- AllocDiscriminant :: Fn | AllocDiscriminant :: Static => {
315+ AllocDiscriminant :: Fn | AllocDiscriminant :: Static | AllocDiscriminant :: Vtable => {
309316 // Fns and statics cannot be cyclic, and their `AllocId`
310317 // is determined later by interning.
311318 * entry =
@@ -355,6 +362,15 @@ impl<'s> AllocDecodingSession<'s> {
355362 let alloc_id = decoder. interner ( ) . create_fn_alloc ( instance) ;
356363 alloc_id
357364 }
365+ AllocDiscriminant :: Vtable => {
366+ assert ! ( alloc_id. is_none( ) ) ;
367+ trace ! ( "creating static alloc ID" ) ;
368+ let ty = <Ty < ' _ > as Decodable < D > >:: decode ( decoder) ;
369+ let poly_trait_ref = <Option < ty:: PolyExistentialTraitRef < ' _ > > as Decodable < D > >:: decode ( decoder) ;
370+ trace ! ( "decoded vtable alloc instance: {ty:?}, {poly_trait_ref:?}" ) ;
371+ let alloc_id = decoder. interner ( ) . create_vtable_alloc ( ty, poly_trait_ref) ;
372+ alloc_id
373+ }
358374 AllocDiscriminant :: Static => {
359375 assert ! ( alloc_id. is_none( ) ) ;
360376 trace ! ( "creating extern static alloc ID" ) ;
@@ -380,6 +396,8 @@ impl<'s> AllocDecodingSession<'s> {
380396pub enum GlobalAlloc < ' tcx > {
381397 /// The alloc ID is used as a function pointer.
382398 Function ( Instance < ' tcx > ) ,
399+ /// This alloc ID points to a symbolic (not-reified) vtable.
400+ Vtable ( Ty < ' tcx > , Option < ty:: PolyExistentialTraitRef < ' tcx > > ) ,
383401 /// The alloc ID points to a "lazy" static variable that did not get computed (yet).
384402 /// This is also used to break the cycle in recursive statics.
385403 Static ( DefId ) ,
@@ -407,6 +425,16 @@ impl<'tcx> GlobalAlloc<'tcx> {
407425 _ => bug ! ( "expected function, got {:?}" , self ) ,
408426 }
409427 }
428+
429+ /// Panics if the `GlobalAlloc` is not `GlobalAlloc::Vtable`
430+ #[ track_caller]
431+ #[ inline]
432+ pub fn unwrap_vtable ( & self ) -> ( Ty < ' tcx > , Option < ty:: PolyExistentialTraitRef < ' tcx > > ) {
433+ match * self {
434+ GlobalAlloc :: Vtable ( ty, poly_trait_ref) => ( ty, poly_trait_ref) ,
435+ _ => bug ! ( "expected vtable, got {:?}" , self ) ,
436+ }
437+ }
410438}
411439
412440pub ( crate ) struct AllocMap < ' tcx > {
@@ -454,12 +482,12 @@ impl<'tcx> TyCtxt<'tcx> {
454482 }
455483
456484 /// Reserves a new ID *if* this allocation has not been dedup-reserved before.
457- /// Should only be used for function pointers and statics, we don't want
458- /// to dedup IDs for "real" memory!
485+ /// Should only be used for "symbolic" allocations ( function pointers, vtables, statics) , we
486+ /// don't want to dedup IDs for "real" memory!
459487 fn reserve_and_set_dedup ( self , alloc : GlobalAlloc < ' tcx > ) -> AllocId {
460488 let mut alloc_map = self . alloc_map . lock ( ) ;
461489 match alloc {
462- GlobalAlloc :: Function ( ..) | GlobalAlloc :: Static ( ..) => { }
490+ GlobalAlloc :: Function ( ..) | GlobalAlloc :: Static ( ..) | GlobalAlloc :: Vtable ( .. ) => { }
463491 GlobalAlloc :: Memory ( ..) => bug ! ( "Trying to dedup-reserve memory with real data!" ) ,
464492 }
465493 if let Some ( & alloc_id) = alloc_map. dedup . get ( & alloc) {
@@ -504,6 +532,11 @@ impl<'tcx> TyCtxt<'tcx> {
504532 }
505533 }
506534
535+ /// Generates an `AllocId` for a (symbolic, not-reified) vtable. Will get deduplicated.
536+ pub fn create_vtable_alloc ( self , ty : Ty < ' tcx > , poly_trait_ref : Option < ty:: PolyExistentialTraitRef < ' tcx > > ) -> AllocId {
537+ self . reserve_and_set_dedup ( GlobalAlloc :: Vtable ( ty, poly_trait_ref) )
538+ }
539+
507540 /// Interns the `Allocation` and return a new `AllocId`, even if there's already an identical
508541 /// `Allocation` with a different `AllocId`.
509542 /// Statics with identical content will still point to the same `Allocation`, i.e.,
0 commit comments