@@ -19,9 +19,12 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
19
19
use rustc_hir as hir;
20
20
use rustc_hir:: definitions:: { DefPathData , DisambiguatorState } ;
21
21
use rustc_middle:: middle:: codegen_fn_attrs:: CodegenFnAttrs ;
22
- use rustc_middle:: mir:: interpret:: { ConstAllocation , CtfeProvenance , InterpResult } ;
22
+ use rustc_middle:: mir:: interpret:: {
23
+ AllocBytes , ConstAllocation , CtfeProvenance , InterpResult , Provenance ,
24
+ } ;
23
25
use rustc_middle:: query:: TyCtxtAt ;
24
26
use rustc_middle:: span_bug;
27
+ use rustc_middle:: ty:: TyCtxt ;
25
28
use rustc_middle:: ty:: layout:: TyAndLayout ;
26
29
use rustc_span:: def_id:: LocalDefId ;
27
30
use tracing:: { instrument, trace} ;
@@ -52,39 +55,30 @@ impl HasStaticRootDefId for const_eval::CompileTimeMachine<'_> {
52
55
}
53
56
}
54
57
55
- /// Intern an allocation. Returns `Err` if the allocation does not exist in the local memory.
56
- ///
57
- /// `mutability` can be used to force immutable interning: if it is `Mutability::Not`, the
58
- /// allocation is interned immutably; if it is `Mutability::Mut`, then the allocation *must be*
59
- /// already mutable (as a sanity check).
60
- ///
61
- /// Returns an iterator over all relocations referred to by this allocation.
62
- fn intern_shallow < ' tcx , M : CompileTimeMachine < ' tcx > > (
63
- ecx : & mut InterpCx < ' tcx , M > ,
64
- alloc_id : AllocId ,
58
+ fn prepare_alloc < ' tcx , Prov : Provenance , Extra , Bytes : AllocBytes > (
59
+ tcx : TyCtxt < ' tcx > ,
60
+ kind : MemoryKind < const_eval:: MemoryKind > ,
61
+ alloc : & mut Allocation < Prov , Extra , Bytes > ,
65
62
mutability : Mutability ,
66
- disambiguator : Option < & mut DisambiguatorState > ,
67
- ) -> Result < impl Iterator < Item = CtfeProvenance > + ' tcx , InternError > {
68
- trace ! ( "intern_shallow {:?}" , alloc_id) ;
69
- // remove allocation
70
- // FIXME(#120456) - is `swap_remove` correct?
71
- let Some ( ( kind, mut alloc) ) = ecx. memory . alloc_map . swap_remove ( & alloc_id) else {
72
- return Err ( InternError :: DanglingPointer ) ;
73
- } ;
74
-
63
+ ) -> Result < ( ) , InternError > {
75
64
match kind {
76
65
MemoryKind :: Machine ( const_eval:: MemoryKind :: Heap { was_made_global } ) => {
77
66
if !was_made_global {
78
67
// Attempting to intern a `const_allocate`d pointer that was not made global via
79
- // `const_make_global`. We want to error here, but we have to first put the
80
- // allocation back into the `alloc_map` to keep things in a consistent state.
81
- ecx. memory . alloc_map . insert ( alloc_id, ( kind, alloc) ) ;
68
+ // `const_make_global`.
69
+ tcx. dcx ( ) . delayed_bug ( "non-global heap allocation in const value" ) ;
82
70
return Err ( InternError :: ConstAllocNotGlobal ) ;
83
71
}
84
72
}
85
73
MemoryKind :: Stack | MemoryKind :: CallerLocation => { }
86
74
}
87
75
76
+ if !alloc. provenance_merge_bytes ( & tcx) {
77
+ // Per-byte provenance is not supported by backends, so we cannot accept it here.
78
+ tcx. dcx ( ) . delayed_bug ( "partial pointer in const value" ) ;
79
+ return Err ( InternError :: PartialPointer ) ;
80
+ }
81
+
88
82
// Set allocation mutability as appropriate. This is used by LLVM to put things into
89
83
// read-only memory, and also by Miri when evaluating other globals that
90
84
// access this one.
@@ -97,6 +91,36 @@ fn intern_shallow<'tcx, M: CompileTimeMachine<'tcx>>(
97
91
assert_eq ! ( alloc. mutability, Mutability :: Mut ) ;
98
92
}
99
93
}
94
+ Ok ( ( ) )
95
+ }
96
+
97
+ /// Intern an allocation. Returns `Err` if the allocation does not exist in the local memory.
98
+ ///
99
+ /// `mutability` can be used to force immutable interning: if it is `Mutability::Not`, the
100
+ /// allocation is interned immutably; if it is `Mutability::Mut`, then the allocation *must be*
101
+ /// already mutable (as a sanity check).
102
+ ///
103
+ /// Returns an iterator over all relocations referred to by this allocation.
104
+ fn intern_shallow < ' tcx , M : CompileTimeMachine < ' tcx > > (
105
+ ecx : & mut InterpCx < ' tcx , M > ,
106
+ alloc_id : AllocId ,
107
+ mutability : Mutability ,
108
+ disambiguator : Option < & mut DisambiguatorState > ,
109
+ ) -> Result < impl Iterator < Item = CtfeProvenance > + ' tcx , InternError > {
110
+ trace ! ( "intern_shallow {:?}" , alloc_id) ;
111
+ // remove allocation
112
+ // FIXME(#120456) - is `swap_remove` correct?
113
+ let Some ( ( kind, mut alloc) ) = ecx. memory . alloc_map . swap_remove ( & alloc_id) else {
114
+ return Err ( InternError :: DanglingPointer ) ;
115
+ } ;
116
+
117
+ if let Err ( err) = prepare_alloc ( * ecx. tcx , kind, & mut alloc, mutability) {
118
+ // We want to error here, but we have to first put the
119
+ // allocation back into the `alloc_map` to keep things in a consistent state.
120
+ ecx. memory . alloc_map . insert ( alloc_id, ( kind, alloc) ) ;
121
+ return Err ( err) ;
122
+ }
123
+
100
124
// link the alloc id to the actual allocation
101
125
let alloc = ecx. tcx . mk_const_alloc ( alloc) ;
102
126
if let Some ( static_id) = ecx. machine . static_def_id ( ) {
@@ -166,6 +190,7 @@ pub enum InternError {
166
190
BadMutablePointer ,
167
191
DanglingPointer ,
168
192
ConstAllocNotGlobal ,
193
+ PartialPointer ,
169
194
}
170
195
171
196
/// Intern `ret` and everything it references.
@@ -221,21 +246,18 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx>>(
221
246
let mut todo: Vec < _ > = if is_static {
222
247
// Do not steal the root allocation, we need it later to create the return value of `eval_static_initializer`.
223
248
// But still change its mutability to match the requested one.
224
- let alloc = ecx. memory . alloc_map . get_mut ( & base_alloc_id) . unwrap ( ) ;
225
- alloc . 1 . mutability = base_mutability;
226
- alloc. 1 . provenance ( ) . ptrs ( ) . iter ( ) . map ( |& ( _, prov) | prov) . collect ( )
249
+ let ( kind , alloc) = ecx. memory . alloc_map . get_mut ( & base_alloc_id) . unwrap ( ) ;
250
+ prepare_alloc ( * ecx . tcx , * kind , alloc , base_mutability) ? ;
251
+ alloc. provenance ( ) . ptrs ( ) . iter ( ) . map ( |& ( _, prov) | prov) . collect ( )
227
252
} else {
228
- intern_shallow ( ecx, base_alloc_id, base_mutability, Some ( & mut disambiguator) )
229
- . unwrap ( )
230
- . collect ( )
253
+ intern_shallow ( ecx, base_alloc_id, base_mutability, Some ( & mut disambiguator) ) ?. collect ( )
231
254
} ;
232
255
// We need to distinguish "has just been interned" from "was already in `tcx`",
233
256
// so we track this in a separate set.
234
257
let mut just_interned: FxHashSet < _ > = std:: iter:: once ( base_alloc_id) . collect ( ) ;
235
258
// Whether we encountered a bad mutable pointer.
236
259
// We want to first report "dangling" and then "mutable", so we need to delay reporting these
237
260
// errors.
238
- let mut result = Ok ( ( ) ) ;
239
261
let mut found_bad_mutable_ptr = false ;
240
262
241
263
// Keep interning as long as there are things to intern.
@@ -310,28 +332,23 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx>>(
310
332
// okay with losing some potential for immutability here. This can anyway only affect
311
333
// `static mut`.
312
334
just_interned. insert ( alloc_id) ;
313
- match intern_shallow ( ecx, alloc_id, inner_mutability, Some ( & mut disambiguator) ) {
314
- Ok ( nested) => todo. extend ( nested) ,
315
- Err ( err) => {
316
- ecx. tcx . dcx ( ) . delayed_bug ( "error during const interning" ) ;
317
- result = Err ( err) ;
318
- }
319
- }
335
+ let next = intern_shallow ( ecx, alloc_id, inner_mutability, Some ( & mut disambiguator) ) ?;
336
+ todo. extend ( next) ;
320
337
}
321
- if found_bad_mutable_ptr && result . is_ok ( ) {
338
+ if found_bad_mutable_ptr {
322
339
// We found a mutable pointer inside a const where inner allocations should be immutable,
323
340
// and there was no other error. This should usually never happen! However, this can happen
324
341
// in unleash-miri mode, so report it as a normal error then.
325
342
if ecx. tcx . sess . opts . unstable_opts . unleash_the_miri_inside_of_you {
326
- result = Err ( InternError :: BadMutablePointer ) ;
343
+ return Err ( InternError :: BadMutablePointer ) ;
327
344
} else {
328
345
span_bug ! (
329
346
ecx. tcx. span,
330
347
"the static const safety checks accepted a mutable pointer they should not have accepted"
331
348
) ;
332
349
}
333
350
}
334
- result
351
+ Ok ( ( ) )
335
352
}
336
353
337
354
/// Intern `ret`. This function assumes that `ret` references no other allocation.
0 commit comments