@@ -450,6 +450,50 @@ pub fn intern_const_alloc_recursive<
450450 Ok ( ( ) )
451451}
452452
453+ /// Intern `ret`, checking it references no other allocation.
454+ #[ instrument( level = "debug" , skip( ecx) ) ]
455+ pub fn intern_const_alloc_for_constprop <
456+ ' mir ,
457+ ' tcx : ' mir ,
458+ T ,
459+ M : CompileTimeMachine < ' mir , ' tcx , T > ,
460+ > (
461+ ecx : & mut InterpCx < ' mir , ' tcx , M > ,
462+ ret : & MPlaceTy < ' tcx > ,
463+ ) -> InterpResult < ' tcx , ( ) > {
464+ let Some ( ( size, _align) ) = ecx. size_and_align_of_mplace ( ret) ? else {
465+ throw_inval ! ( ConstPropNonsense )
466+ } ;
467+
468+ let alloc_ref = ecx. get_ptr_alloc ( ret. ptr ( ) , size) ?. unwrap ( ) ;
469+ // Do not try interning a value that contains provenance.
470+ if alloc_ref. has_provenance ( ) {
471+ throw_inval ! ( ConstPropNonsense )
472+ }
473+
474+ // remove allocation
475+ let alloc_id = ret. ptr ( ) . provenance . unwrap ( ) ;
476+ let Some ( ( _, mut alloc) ) = ecx. memory . alloc_map . remove ( & alloc_id) else {
477+ // Pointer not found in local memory map. It is either a pointer to the global
478+ // map, or dangling.
479+ if ecx. tcx . try_get_global_alloc ( alloc_id) . is_none ( ) {
480+ throw_ub ! ( DeadLocal )
481+ }
482+ // The constant is already in global memory. Do nothing.
483+ return Ok ( ( ) ) ;
484+ } ;
485+
486+ alloc. mutability = Mutability :: Not ;
487+
488+ // link the alloc id to the actual allocation
489+ assert ! ( alloc. provenance( ) . ptrs( ) . is_empty( ) ) ;
490+
491+ let alloc = ecx. tcx . mk_const_alloc ( alloc) ;
492+ ecx. tcx . set_alloc_id_memory ( alloc_id, alloc) ;
493+
494+ Ok ( ( ) )
495+ }
496+
453497impl < ' mir , ' tcx : ' mir , M : super :: intern:: CompileTimeMachine < ' mir , ' tcx , !> >
454498 InterpCx < ' mir , ' tcx , M >
455499{
0 commit comments