@@ -170,12 +170,14 @@ pub type CompileTimeInterpCx<'tcx> = InterpCx<'tcx, CompileTimeMachine<'tcx>>;
170
170
#[ derive( Debug , PartialEq , Eq , Copy , Clone ) ]
171
171
pub enum MemoryKind {
172
172
Heap ,
173
+ HeapLeaked ,
173
174
}
174
175
175
176
impl fmt:: Display for MemoryKind {
176
177
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
177
178
match self {
178
179
MemoryKind :: Heap => write ! ( f, "heap allocation" ) ,
180
+ MemoryKind :: HeapLeaked => write ! ( f, "leaked heap allocation" ) ,
179
181
}
180
182
}
181
183
}
@@ -185,6 +187,17 @@ impl interpret::MayLeak for MemoryKind {
185
187
fn may_leak ( self ) -> bool {
186
188
match self {
187
189
MemoryKind :: Heap => false ,
190
+ MemoryKind :: HeapLeaked => true ,
191
+ }
192
+ }
193
+ }
194
+
195
+ impl interpret:: IsConstHeap for MemoryKind {
196
+ #[ inline( always) ]
197
+ fn is_const_heap ( & self ) -> bool {
198
+ match self {
199
+ MemoryKind :: Heap => true ,
200
+ MemoryKind :: HeapLeaked => false ,
188
201
}
189
202
}
190
203
}
@@ -197,6 +210,13 @@ impl interpret::MayLeak for ! {
197
210
}
198
211
}
199
212
213
+ impl interpret:: IsConstHeap for ! {
214
+ #[ inline( always) ]
215
+ fn is_const_heap ( & self ) -> bool {
216
+ * self
217
+ }
218
+ }
219
+
200
220
impl < ' tcx > CompileTimeInterpCx < ' tcx > {
201
221
fn location_triple_for_span ( & self , span : Span ) -> ( Symbol , u32 , u32 ) {
202
222
let topmost = span. ctxt ( ) . outer_expn ( ) . expansion_cause ( ) . unwrap_or ( span) ;
@@ -457,6 +477,46 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
457
477
) ?;
458
478
}
459
479
}
480
+
481
+ sym:: const_leak => {
482
+ let ptr = ecx. read_pointer ( & args[ 0 ] ) ?;
483
+ let size = ecx. read_scalar ( & args[ 1 ] ) ?. to_target_usize ( ecx) ?;
484
+ let align = ecx. read_scalar ( & args[ 2 ] ) ?. to_target_usize ( ecx) ?;
485
+
486
+ let size = Size :: from_bytes ( size) ;
487
+ let align = match Align :: from_bytes ( align) {
488
+ Ok ( a) => a,
489
+ Err ( err) => throw_ub_custom ! (
490
+ fluent:: const_eval_invalid_align_details,
491
+ name = "const_leak" ,
492
+ err_kind = err. diag_ident( ) ,
493
+ align = err. align( )
494
+ ) ,
495
+ } ;
496
+
497
+ // If an allocation is created in an another const,
498
+ // we don't reallocate it.
499
+ let ( alloc_id, _, _) = ecx. ptr_get_alloc_id ( ptr, 0 ) ?;
500
+ let is_allocated_in_another_const = matches ! (
501
+ ecx. tcx. try_get_global_alloc( alloc_id) ,
502
+ Some ( interpret:: GlobalAlloc :: Memory ( _) )
503
+ ) ;
504
+
505
+ if is_allocated_in_another_const {
506
+ // just return the pointer that was passed in
507
+ ecx. write_pointer ( ptr, dest) ?;
508
+ } else {
509
+ let ptr = ecx. leak_const_heap_ptr (
510
+ ptr,
511
+ size,
512
+ align,
513
+ interpret:: MemoryKind :: Machine ( MemoryKind :: Heap ) ,
514
+ interpret:: MemoryKind :: Machine ( MemoryKind :: HeapLeaked ) ,
515
+ ) ?;
516
+ ecx. write_pointer ( ptr, dest) ?;
517
+ }
518
+ }
519
+
460
520
// The intrinsic represents whether the value is known to the optimizer (LLVM).
461
521
// We're not doing any optimizations here, so there is no optimizer that could know the value.
462
522
// (We know the value here in the machine of course, but this is the runtime of that code,
0 commit comments