diff --git a/src/machine.rs b/src/machine.rs index 178dcf7786..eea2057ef6 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -1358,7 +1358,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { // where it mistakenly removes an important tag become visible. if ecx.machine.gc_interval > 0 && ecx.machine.since_gc >= ecx.machine.gc_interval { ecx.machine.since_gc = 0; - ecx.garbage_collect_tags()?; + ecx.run_provenance_gc(); } // These are our preemption points. diff --git a/src/provenance_gc.rs b/src/provenance_gc.rs index 0aaa44bee3..ec1097422e 100644 --- a/src/provenance_gc.rs +++ b/src/provenance_gc.rs @@ -149,12 +149,8 @@ impl VisitTags for crate::MiriInterpCx<'_, '_> { impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { - fn garbage_collect_tags(&mut self) -> InterpResult<'tcx> { + fn run_provenance_gc(&mut self) { let this = self.eval_context_mut(); - // No reason to do anything at all if stacked borrows is off. - if this.machine.borrow_tracker.is_none() { - return Ok(()); - } let mut tags = FxHashSet::default(); let mut alloc_ids = FxHashSet::default(); @@ -168,8 +164,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { }); self.remove_unreachable_tags(tags); self.remove_unreachable_allocs(alloc_ids); - - Ok(()) } fn remove_unreachable_tags(&mut self, tags: FxHashSet) { diff --git a/src/shims/foreign_items.rs b/src/shims/foreign_items.rs index 3462f03c30..b54e1982f9 100644 --- a/src/shims/foreign_items.rs +++ b/src/shims/foreign_items.rs @@ -459,6 +459,10 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // shim, add it to the corresponding submodule. match link_name.as_str() { // Miri-specific extern functions + "miri_run_provenance_gc" => { + let [] = this.check_shim(abi, Abi::Rust, link_name, args)?; + this.run_provenance_gc(); + } "miri_get_alloc_id" => { let [ptr] = this.check_shim(abi, Abi::Rust, link_name, args)?; let ptr = this.read_pointer(ptr)?; diff --git a/tests/pass/ptr_int_casts.rs b/tests/pass/ptr_int_casts.rs index 46678bf000..0a7b775ea0 100644 --- a/tests/pass/ptr_int_casts.rs +++ b/tests/pass/ptr_int_casts.rs @@ -4,6 +4,10 @@ use std::mem; use std::ptr; +extern "Rust" { + fn miri_run_provenance_gc(); +} + fn eq_ref(x: &T, y: &T) -> bool { x as *const _ == y as *const _ } @@ -47,25 +51,19 @@ fn ptr_int_casts() { // involving types other than usize assert_eq!((-1i32) as usize as *const i32 as usize, (-1i32) as usize); - // Stress-test that the GC doesn't delete context that would prevent us from casting from int + // Check that the GC doesn't delete context that would prevent us from casting from int // to pointer correctly after the allocation is dead. - let mut ptrs: Vec<*const u8> = Vec::new(); - let mut ints: Vec = Vec::new(); - - for _ in 0..100 { + let (ptr, int) = { let local = 0u8; let ptr = &local as *const u8; - ptrs.push(ptr); - ints.push(ptr as usize); - - let b = Box::new(0u8); - let ptr = &*b as *const u8; - ptrs.push(ptr); - ints.push(ptr as usize); - } - - let later_ints: Vec = ptrs.iter().map(|p| *p as usize).collect(); - assert_eq!(ints, later_ints); + (ptr, ptr as usize) + }; + // Manually run the GC, instead of just hoping that it runs at the right time. + unsafe { miri_run_provenance_gc() } + let later_int = ptr as usize; + assert_eq!(int, later_int); + let later_ptr = int as *const u8; + assert_eq!(ptr, later_ptr); } fn ptr_int_ops() {