13
13
//! but that would require relying on type information, and given how many ways Rust has to lie
14
14
//! about type information, we want to avoid doing that.
15
15
16
+ use hir:: def:: DefKind ;
16
17
use rustc_ast:: Mutability ;
17
18
use rustc_data_structures:: fx:: { FxHashSet , FxIndexMap } ;
18
19
use rustc_errors:: ErrorGuaranteed ;
19
20
use 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 ;
21
23
use rustc_middle:: ty:: layout:: TyAndLayout ;
24
+ use rustc_span:: def_id:: LocalDefId ;
25
+ use rustc_span:: sym;
22
26
23
27
use super :: { AllocId , Allocation , InterpCx , MPlaceTy , Machine , MemoryKind , PlaceTy } ;
24
28
use crate :: const_eval;
@@ -33,7 +37,19 @@ pub trait CompileTimeMachine<'mir, 'tcx: 'mir, T> = Machine<
33
37
FrameExtra = ( ) ,
34
38
AllocExtra = ( ) ,
35
39
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
+ }
37
53
38
54
/// Intern an allocation. Returns `Err` if the allocation does not exist in the local memory.
39
55
///
@@ -67,10 +83,35 @@ fn intern_shallow<'rt, 'mir, 'tcx, T, M: CompileTimeMachine<'mir, 'tcx, T>>(
67
83
}
68
84
// link the alloc id to the actual allocation
69
85
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
+ }
71
91
Ok ( alloc. 0 . 0 . provenance ( ) . ptrs ( ) . iter ( ) . map ( |& ( _, prov) | prov) )
72
92
}
73
93
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
+
74
115
/// How a constant value should be interned.
75
116
#[ derive( Copy , Clone , Debug , PartialEq , Hash , Eq ) ]
76
117
pub enum InternKind {
0 commit comments