5
5
6
6
use super :: validity:: RefTracking ;
7
7
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
8
- use rustc_errors:: ErrorReported ;
9
8
use rustc_hir as hir;
10
- use rustc_middle:: mir:: interpret:: { ErrorHandled , InterpResult } ;
9
+ use rustc_middle:: mir:: interpret:: InterpResult ;
11
10
use rustc_middle:: ty:: { self , query:: TyCtxtAt , Ty } ;
12
11
13
12
use rustc_ast:: ast:: Mutability ;
@@ -64,6 +63,7 @@ enum InternMode {
64
63
struct IsStaticOrFn ;
65
64
66
65
fn mutable_memory_in_const ( tcx : TyCtxtAt < ' _ > , kind : & str ) {
66
+ // FIXME: show this in validation instead so we can point at where in the value the error is?
67
67
tcx. sess . span_err ( tcx. span , & format ! ( "mutable memory ({}) is not allowed in constant" , kind) ) ;
68
68
}
69
69
@@ -79,7 +79,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>(
79
79
alloc_id : AllocId ,
80
80
mode : InternMode ,
81
81
ty : Option < Ty < ' tcx > > ,
82
- ) -> InterpResult < ' tcx , Option < IsStaticOrFn > > {
82
+ ) -> Option < IsStaticOrFn > {
83
83
trace ! ( "intern_shallow {:?} with {:?}" , alloc_id, mode) ;
84
84
// remove allocation
85
85
let tcx = ecx. tcx ;
@@ -97,7 +97,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>(
97
97
}
98
98
// treat dangling pointers like other statics
99
99
// just to stop trying to recurse into them
100
- return Ok ( Some ( IsStaticOrFn ) ) ;
100
+ return Some ( IsStaticOrFn ) ;
101
101
}
102
102
} ;
103
103
// This match is just a canary for future changes to `MemoryKind`, which most likely need
@@ -136,7 +136,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>(
136
136
let alloc = tcx. intern_const_alloc ( alloc) ;
137
137
leftover_allocations. extend ( alloc. relocations ( ) . iter ( ) . map ( |& ( _, ( ( ) , reloc) ) | reloc) ) ;
138
138
tcx. set_alloc_id_memory ( alloc_id, alloc) ;
139
- Ok ( None )
139
+ None
140
140
}
141
141
142
142
impl < ' rt , ' mir , ' tcx , M : CompileTimeMachine < ' mir , ' tcx > > InternVisitor < ' rt , ' mir , ' tcx , M > {
@@ -145,7 +145,7 @@ impl<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>> InternVisitor<'rt, 'mir
145
145
alloc_id : AllocId ,
146
146
mode : InternMode ,
147
147
ty : Option < Ty < ' tcx > > ,
148
- ) -> InterpResult < ' tcx , Option < IsStaticOrFn > > {
148
+ ) -> Option < IsStaticOrFn > {
149
149
intern_shallow (
150
150
self . ecx ,
151
151
self . leftover_allocations ,
@@ -213,7 +213,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir
213
213
if let Scalar :: Ptr ( vtable) = mplace. meta . unwrap_meta ( ) {
214
214
// Explicitly choose const mode here, since vtables are immutable, even
215
215
// if the reference of the fat pointer is mutable.
216
- self . intern_shallow ( vtable. alloc_id , InternMode :: ConstInner , None ) ? ;
216
+ self . intern_shallow ( vtable. alloc_id , InternMode :: ConstInner , None ) ;
217
217
} else {
218
218
// Let validation show the error message, but make sure it *does* error.
219
219
tcx. sess . delay_span_bug (
@@ -277,7 +277,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir
277
277
InternMode :: ConstInner
278
278
}
279
279
} ;
280
- match self . intern_shallow ( ptr. alloc_id , ref_mode, Some ( referenced_ty) ) ? {
280
+ match self . intern_shallow ( ptr. alloc_id , ref_mode, Some ( referenced_ty) ) {
281
281
// No need to recurse, these are interned already and statics may have
282
282
// cycles, so we don't want to recurse there
283
283
Some ( IsStaticOrFn ) => { }
@@ -304,12 +304,18 @@ pub enum InternKind {
304
304
ConstProp ,
305
305
}
306
306
307
+ /// Intern `ret` and everything it references.
308
+ ///
309
+ /// This *cannot raise an interpreter error*. Doing so is left to validation, which
310
+ /// trakcs where in the value we are and thus can show much better error messages.
311
+ /// Any errors here would anyway be turned into `const_err` lints, whereas validation failures
312
+ /// are hard errors.
307
313
pub fn intern_const_alloc_recursive < M : CompileTimeMachine < ' mir , ' tcx > > (
308
314
ecx : & mut InterpCx < ' mir , ' tcx , M > ,
309
315
intern_kind : InternKind ,
310
316
ret : MPlaceTy < ' tcx > ,
311
317
ignore_interior_mut_in_const : bool ,
312
- ) -> InterpResult < ' tcx >
318
+ )
313
319
where
314
320
' tcx : ' mir ,
315
321
{
@@ -338,7 +344,7 @@ where
338
344
ret. ptr . assert_ptr ( ) . alloc_id ,
339
345
base_intern_mode,
340
346
Some ( ret. layout . ty ) ,
341
- ) ? ;
347
+ ) ;
342
348
343
349
ref_tracking. track ( ( ret, base_intern_mode) , || ( ) ) ;
344
350
@@ -422,13 +428,16 @@ where
422
428
}
423
429
}
424
430
} else if ecx. memory . dead_alloc_map . contains_key ( & alloc_id) {
425
- // dangling pointer
426
- throw_ub_format ! ( "encountered dangling pointer in final constant" )
431
+ // Codegen does not like dangling pointers, and generally `tcx` assumes that
432
+ // all allocations referenced anywhere actually exist. So, make sure we error here.
433
+ ecx. tcx . sess . span_err (
434
+ ecx. tcx . span ,
435
+ "encountered dangling pointer in final constant" ,
436
+ ) ;
427
437
} else if ecx. tcx . get_global_alloc ( alloc_id) . is_none ( ) {
428
- // We have hit an `AllocId` that is neither in local or global memory and isn't marked
429
- // as dangling by local memory.
438
+ // We have hit an `AllocId` that is neither in local or global memory and isn't
439
+ // marked as dangling by local memory. That should be impossible .
430
440
span_bug ! ( ecx. tcx. span, "encountered unknown alloc id {:?}" , alloc_id) ;
431
441
}
432
442
}
433
- Ok ( ( ) )
434
443
}
0 commit comments