@@ -26,12 +26,9 @@ use rustc_middle::ty::layout::TyAndLayout;
2626use rustc_span:: def_id:: LocalDefId ;
2727use tracing:: { instrument, trace} ;
2828
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} ;
3330use crate :: const_eval:: DummyMachine ;
34- use crate :: errors :: { ConstHeapPtrInFinal , NestedStaticInThreadLocal } ;
31+ use crate :: { const_eval , errors } ;
3532
3633pub trait CompileTimeMachine < ' tcx , T > = Machine <
3734 ' tcx ,
@@ -63,7 +60,7 @@ pub enum DisallowInternReason {
6360///
6461/// This prevents us from interning `const_allocate` pointers that have not been made
6562/// global through `const_make_global`.
66- pub trait CanIntern {
63+ pub trait CanIntern : Copy {
6764 fn disallows_intern ( & self ) -> Option < DisallowInternReason > ;
6865}
6966
@@ -96,24 +93,22 @@ fn intern_shallow<'tcx, T: CanIntern, M: CompileTimeMachine<'tcx, T>>(
9693 alloc_id : AllocId ,
9794 mutability : Mutability ,
9895 disambiguator : Option < & mut DisambiguatorState > ,
99- ) -> Result < impl Iterator < Item = CtfeProvenance > + ' tcx , ( ) > {
96+ ) -> Result < impl Iterator < Item = CtfeProvenance > + ' tcx , InternError > {
10097 trace ! ( "intern_shallow {:?}" , alloc_id) ;
10198 // remove allocation
10299 // FIXME(#120456) - is `swap_remove` correct?
103100 let Some ( ( kind, mut alloc) ) = ecx. memory . alloc_map . swap_remove ( & alloc_id) else {
104- return Err ( ( ) ) ;
101+ return Err ( InternError :: DanglingPointer ) ;
105102 } ;
106103
107104 match kind {
108105 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.
115106 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 ) ;
117112 }
118113 } ,
119114 MemoryKind :: Machine ( _) | MemoryKind :: Stack | MemoryKind :: CallerLocation => { }
@@ -170,7 +165,7 @@ fn intern_as_new_static<'tcx>(
170165 tcx. set_nested_alloc_id_static ( alloc_id, feed. def_id ( ) ) ;
171166
172167 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) } ) ;
174169 }
175170
176171 // These do not inherit the codegen attrs of the parent static allocation, since
@@ -196,9 +191,10 @@ pub enum InternKind {
196191}
197192
198193#[ derive( Debug ) ]
199- pub enum InternResult {
200- FoundBadMutablePointer ,
201- FoundDanglingPointer ,
194+ pub enum InternError {
195+ BadMutablePointer ,
196+ DanglingPointer ,
197+ ConstAllocNotGlobal ,
202198}
203199
204200/// Intern `ret` and everything it references.
@@ -212,7 +208,7 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval
212208 ecx : & mut InterpCx < ' tcx , M > ,
213209 intern_kind : InternKind ,
214210 ret : & MPlaceTy < ' tcx > ,
215- ) -> Result < ( ) , InternResult > {
211+ ) -> Result < ( ) , InternError > {
216212 let mut disambiguator = DisambiguatorState :: new ( ) ;
217213
218214 // 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
269265 // We want to first report "dangling" and then "mutable", so we need to delay reporting these
270266 // errors.
271267 let mut result = Ok ( ( ) ) ;
268+ let mut found_bad_mutable_ptr = false ;
272269
273270 // Keep interning as long as there are things to intern.
274271 // 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
323320 // when there is memory there that someone might expect to be mutable, but we make it immutable.
324321 let dangling = !is_already_global && !ecx. memory . alloc_map . contains_key ( & alloc_id) ;
325322 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 ;
338324 }
339325 }
340326 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
355341 just_interned. insert ( alloc_id) ;
356342 match intern_shallow ( ecx, alloc_id, inner_mutability, Some ( & mut disambiguator) ) {
357343 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 ) ;
361347 }
362348 }
363349 }
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+ }
364363 result
365364}
366365
@@ -375,10 +374,7 @@ pub fn intern_const_alloc_for_constprop<'tcx, T: CanIntern, M: CompileTimeMachin
375374 return interp_ok ( ( ) ) ;
376375 }
377376 // 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 ( ) {
382378 // We are not doing recursive interning, so we don't currently support provenance.
383379 // (If this assertion ever triggers, we should just implement a
384380 // proper recursive interning loop -- or just call `intern_const_alloc_recursive`.
0 commit comments