@@ -26,12 +26,9 @@ use rustc_middle::ty::layout::TyAndLayout;
26
26
use rustc_span:: def_id:: LocalDefId ;
27
27
use tracing:: { instrument, trace} ;
28
28
29
- use super :: {
30
- AllocId , Allocation , InterpCx , MPlaceTy , Machine , MemoryKind , PlaceTy , err_ub, interp_ok,
31
- } ;
32
- use crate :: const_eval;
29
+ use super :: { AllocId , Allocation , InterpCx , MPlaceTy , Machine , MemoryKind , PlaceTy , interp_ok} ;
33
30
use crate :: const_eval:: DummyMachine ;
34
- use crate :: errors :: { ConstHeapPtrInFinal , NestedStaticInThreadLocal } ;
31
+ use crate :: { const_eval , errors } ;
35
32
36
33
pub trait CompileTimeMachine < ' tcx , T > = Machine <
37
34
' tcx ,
@@ -63,7 +60,7 @@ pub enum DisallowInternReason {
63
60
///
64
61
/// This prevents us from interning `const_allocate` pointers that have not been made
65
62
/// global through `const_make_global`.
66
- pub trait CanIntern {
63
+ pub trait CanIntern : Copy {
67
64
fn disallows_intern ( & self ) -> Option < DisallowInternReason > ;
68
65
}
69
66
@@ -96,24 +93,22 @@ fn intern_shallow<'tcx, T: CanIntern, M: CompileTimeMachine<'tcx, T>>(
96
93
alloc_id : AllocId ,
97
94
mutability : Mutability ,
98
95
disambiguator : Option < & mut DisambiguatorState > ,
99
- ) -> Result < impl Iterator < Item = CtfeProvenance > + ' tcx , ( ) > {
96
+ ) -> Result < impl Iterator < Item = CtfeProvenance > + ' tcx , InternError > {
100
97
trace ! ( "intern_shallow {:?}" , alloc_id) ;
101
98
// remove allocation
102
99
// FIXME(#120456) - is `swap_remove` correct?
103
100
let Some ( ( kind, mut alloc) ) = ecx. memory . alloc_map . swap_remove ( & alloc_id) else {
104
- return Err ( ( ) ) ;
101
+ return Err ( InternError :: DanglingPointer ) ;
105
102
} ;
106
103
107
104
match kind {
108
105
MemoryKind :: Machine ( x) if let Some ( reason) = x. disallows_intern ( ) => match reason {
109
- // Attempting to intern a `const_allocate`d pointer that was not made global via
110
- // `const_make_global`. This is an error, but if we return `Err` now, things
111
- // become inconsistent because we already removed the allocation from `alloc_map`.
112
- // So instead we just emit an error and then continue interning as usual.
113
- // We *could* do this check before removing the allocation from `alloc_map`, but then
114
- // it would be much harder to ensure that we only error once for each allocation.
115
106
DisallowInternReason :: ConstHeap => {
116
- ecx. tcx . dcx ( ) . emit_err ( ConstHeapPtrInFinal { span : ecx. tcx . span } ) ;
107
+ // Attempting to intern a `const_allocate`d pointer that was not made global via
108
+ // `const_make_global`. We want to error here, but we have to first put the
109
+ // allocation back into the `alloc_map` to keep things in a consistent state.
110
+ ecx. memory . alloc_map . insert ( alloc_id, ( kind, alloc) ) ;
111
+ return Err ( InternError :: ConstAllocNotGlobal ) ;
117
112
}
118
113
} ,
119
114
MemoryKind :: Machine ( _) | MemoryKind :: Stack | MemoryKind :: CallerLocation => { }
@@ -170,7 +165,7 @@ fn intern_as_new_static<'tcx>(
170
165
tcx. set_nested_alloc_id_static ( alloc_id, feed. def_id ( ) ) ;
171
166
172
167
if tcx. is_thread_local_static ( static_id. into ( ) ) {
173
- tcx. dcx ( ) . emit_err ( NestedStaticInThreadLocal { span : tcx. def_span ( static_id) } ) ;
168
+ tcx. dcx ( ) . emit_err ( errors :: NestedStaticInThreadLocal { span : tcx. def_span ( static_id) } ) ;
174
169
}
175
170
176
171
// These do not inherit the codegen attrs of the parent static allocation, since
@@ -196,9 +191,10 @@ pub enum InternKind {
196
191
}
197
192
198
193
#[ derive( Debug ) ]
199
- pub enum InternResult {
200
- FoundBadMutablePointer ,
201
- FoundDanglingPointer ,
194
+ pub enum InternError {
195
+ BadMutablePointer ,
196
+ DanglingPointer ,
197
+ ConstAllocNotGlobal ,
202
198
}
203
199
204
200
/// Intern `ret` and everything it references.
@@ -212,7 +208,7 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval
212
208
ecx : & mut InterpCx < ' tcx , M > ,
213
209
intern_kind : InternKind ,
214
210
ret : & MPlaceTy < ' tcx > ,
215
- ) -> Result < ( ) , InternResult > {
211
+ ) -> Result < ( ) , InternError > {
216
212
let mut disambiguator = DisambiguatorState :: new ( ) ;
217
213
218
214
// We are interning recursively, and for mutability we are distinguishing the "root" allocation
@@ -269,6 +265,7 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval
269
265
// We want to first report "dangling" and then "mutable", so we need to delay reporting these
270
266
// errors.
271
267
let mut result = Ok ( ( ) ) ;
268
+ let mut found_bad_mutable_ptr = false ;
272
269
273
270
// Keep interning as long as there are things to intern.
274
271
// We show errors if there are dangling pointers, or mutable pointers in immutable contexts
@@ -323,18 +320,7 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval
323
320
// when there is memory there that someone might expect to be mutable, but we make it immutable.
324
321
let dangling = !is_already_global && !ecx. memory . alloc_map . contains_key ( & alloc_id) ;
325
322
if !dangling {
326
- // Found a mutable pointer inside a const where inner allocations should be
327
- // immutable.
328
- if !ecx. tcx . sess . opts . unstable_opts . unleash_the_miri_inside_of_you {
329
- span_bug ! (
330
- ecx. tcx. span,
331
- "the static const safety checks accepted a mutable pointer they should not have accepted"
332
- ) ;
333
- }
334
- // Prefer dangling pointer errors over mutable pointer errors
335
- if result. is_ok ( ) {
336
- result = Err ( InternResult :: FoundBadMutablePointer ) ;
337
- }
323
+ found_bad_mutable_ptr = true ;
338
324
}
339
325
}
340
326
if ecx. tcx . try_get_global_alloc ( alloc_id) . is_some ( ) {
@@ -355,12 +341,25 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval
355
341
just_interned. insert ( alloc_id) ;
356
342
match intern_shallow ( ecx, alloc_id, inner_mutability, Some ( & mut disambiguator) ) {
357
343
Ok ( nested) => todo. extend ( nested) ,
358
- Err ( ( ) ) => {
359
- ecx. tcx . dcx ( ) . delayed_bug ( "found dangling pointer during const interning" ) ;
360
- result = Err ( InternResult :: FoundDanglingPointer ) ;
344
+ Err ( err ) => {
345
+ ecx. tcx . dcx ( ) . delayed_bug ( "error during const interning" ) ;
346
+ result = Err ( err ) ;
361
347
}
362
348
}
363
349
}
350
+ if found_bad_mutable_ptr && result. is_ok ( ) {
351
+ // We found a mutable pointer inside a const where inner allocations should be immutable,
352
+ // and there was no other error. This should usually never happen! However, this can happen
353
+ // in unleash-miri mode, so report it as a normal error then.
354
+ if ecx. tcx . sess . opts . unstable_opts . unleash_the_miri_inside_of_you {
355
+ result = Err ( InternError :: BadMutablePointer ) ;
356
+ } else {
357
+ span_bug ! (
358
+ ecx. tcx. span,
359
+ "the static const safety checks accepted a mutable pointer they should not have accepted"
360
+ ) ;
361
+ }
362
+ }
364
363
result
365
364
}
366
365
@@ -375,10 +374,7 @@ pub fn intern_const_alloc_for_constprop<'tcx, T: CanIntern, M: CompileTimeMachin
375
374
return interp_ok ( ( ) ) ;
376
375
}
377
376
// Move allocation to `tcx`.
378
- if let Some ( _) = intern_shallow ( ecx, alloc_id, Mutability :: Not , None )
379
- . map_err ( |( ) | err_ub ! ( DeadLocal ) ) ?
380
- . next ( )
381
- {
377
+ if let Some ( _) = intern_shallow ( ecx, alloc_id, Mutability :: Not , None ) . unwrap ( ) . next ( ) {
382
378
// We are not doing recursive interning, so we don't currently support provenance.
383
379
// (If this assertion ever triggers, we should just implement a
384
380
// proper recursive interning loop -- or just call `intern_const_alloc_recursive`.
0 commit comments