1313//! but that would require relying on type information, and given how many ways Rust has to lie
1414//! about type information, we want to avoid doing that.
1515
16+ use hir:: def:: DefKind ;
1617use rustc_ast:: Mutability ;
1718use rustc_data_structures:: fx:: { FxHashSet , FxIndexMap } ;
1819use rustc_errors:: ErrorGuaranteed ;
1920use rustc_hir as hir;
20- use rustc_middle:: mir:: interpret:: { CtfeProvenance , InterpResult } ;
21+ use rustc_middle:: mir:: interpret:: { ConstAllocation , CtfeProvenance , InterpResult } ;
22+ use rustc_middle:: query:: TyCtxtAt ;
2123use rustc_middle:: ty:: layout:: TyAndLayout ;
24+ use rustc_span:: def_id:: LocalDefId ;
25+ use rustc_span:: sym;
2226
2327use super :: { AllocId , Allocation , InterpCx , MPlaceTy , Machine , MemoryKind , PlaceTy } ;
2428use crate :: const_eval;
@@ -33,7 +37,19 @@ pub trait CompileTimeMachine<'mir, 'tcx: 'mir, T> = Machine<
3337 FrameExtra = ( ) ,
3438 AllocExtra = ( ) ,
3539 MemoryMap = FxIndexMap < AllocId , ( MemoryKind < T > , Allocation ) > ,
36- > ;
40+ > + HasStaticRootDefId ;
41+
42+ pub trait HasStaticRootDefId {
43+ /// Returns the `DefId` of the static item that is currently being evaluated.
44+ /// Used for interning to be able to handle nested allocations.
45+ fn static_def_id ( & self ) -> Option < LocalDefId > ;
46+ }
47+
48+ impl HasStaticRootDefId for const_eval:: CompileTimeInterpreter < ' _ , ' _ > {
49+ fn static_def_id ( & self ) -> Option < LocalDefId > {
50+ Some ( self . static_root_ids ?. 1 )
51+ }
52+ }
3753
3854/// Intern an allocation. Returns `Err` if the allocation does not exist in the local memory.
3955///
@@ -67,10 +83,35 @@ fn intern_shallow<'rt, 'mir, 'tcx, T, M: CompileTimeMachine<'mir, 'tcx, T>>(
6783 }
6884 // link the alloc id to the actual allocation
6985 let alloc = ecx. tcx . mk_const_alloc ( alloc) ;
70- ecx. tcx . set_alloc_id_memory ( alloc_id, alloc) ;
86+ if let Some ( static_id) = ecx. machine . static_def_id ( ) {
87+ intern_as_new_static ( ecx. tcx , static_id, alloc_id, alloc) ;
88+ } else {
89+ ecx. tcx . set_alloc_id_memory ( alloc_id, alloc) ;
90+ }
7191 Ok ( alloc. 0 . 0 . provenance ( ) . ptrs ( ) . iter ( ) . map ( |& ( _, prov) | prov) )
7292}
7393
94+ /// Creates a new `DefId` and feeds all the right queries to make this `DefId`
95+ /// appear as if it were a user-written `static` (though it has no HIR).
96+ fn intern_as_new_static < ' tcx > (
97+ tcx : TyCtxtAt < ' tcx > ,
98+ static_id : LocalDefId ,
99+ alloc_id : AllocId ,
100+ alloc : ConstAllocation < ' tcx > ,
101+ ) {
102+ let feed = tcx. create_def (
103+ static_id,
104+ sym:: nested,
105+ DefKind :: Static { mt : alloc. 0 . mutability , nested : true } ,
106+ ) ;
107+ tcx. set_nested_alloc_id_static ( alloc_id, feed. def_id ( ) ) ;
108+ feed. codegen_fn_attrs ( tcx. codegen_fn_attrs ( static_id) . clone ( ) ) ;
109+ feed. eval_static_initializer ( Ok ( alloc) ) ;
110+ feed. generics_of ( tcx. generics_of ( static_id) . clone ( ) ) ;
111+ feed. def_ident_span ( tcx. def_ident_span ( static_id) ) ;
112+ feed. explicit_predicates_of ( tcx. explicit_predicates_of ( static_id) ) ;
113+ }
114+
74115/// How a constant value should be interned.
75116#[ derive( Copy , Clone , Debug , PartialEq , Hash , Eq ) ]
76117pub enum InternKind {
0 commit comments