1 use rustc_data_structures::fx::FxHashSet;
6 fn visit_tags(&self, visit: &mut dyn FnMut(SbTag));
9 impl<T: VisitTags> VisitTags for Option<T> {
10 fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
11 if let Some(x) = self {
17 impl<T: VisitTags> VisitTags for std::cell::RefCell<T> {
18 fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
19 self.borrow().visit_tags(visit)
23 impl VisitTags for SbTag {
24 fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
29 impl VisitTags for Provenance {
30 fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
31 if let Provenance::Concrete { sb, .. } = self {
37 impl VisitTags for Pointer<Provenance> {
38 fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
39 let (prov, _offset) = self.into_parts();
40 prov.visit_tags(visit);
44 impl VisitTags for Pointer<Option<Provenance>> {
45 fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
46 let (prov, _offset) = self.into_parts();
47 prov.visit_tags(visit);
51 impl VisitTags for Scalar<Provenance> {
52 fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
54 Scalar::Ptr(ptr, _) => ptr.visit_tags(visit),
60 impl VisitTags for Immediate<Provenance> {
61 fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
63 Immediate::Scalar(s) => {
66 Immediate::ScalarPair(s1, s2) => {
70 Immediate::Uninit => {}
75 impl VisitTags for MemPlaceMeta<Provenance> {
76 fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
78 MemPlaceMeta::Meta(m) => m.visit_tags(visit),
79 MemPlaceMeta::None => {}
84 impl VisitTags for MemPlace<Provenance> {
85 fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
86 let MemPlace { ptr, meta } = self;
87 ptr.visit_tags(visit);
88 meta.visit_tags(visit);
92 impl VisitTags for MPlaceTy<'_, Provenance> {
93 fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
94 (**self).visit_tags(visit)
98 impl VisitTags for Place<Provenance> {
99 fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
101 Place::Ptr(p) => p.visit_tags(visit),
102 Place::Local { .. } => {
103 // Will be visited as part of the stack frame.
109 impl VisitTags for PlaceTy<'_, Provenance> {
110 fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
111 (**self).visit_tags(visit)
115 impl VisitTags for Operand<Provenance> {
116 fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
118 Operand::Immediate(imm) => {
119 imm.visit_tags(visit);
121 Operand::Indirect(p) => {
128 impl VisitTags for Allocation<Provenance, AllocExtra> {
129 fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
130 for (_size, prov) in self.provenance().iter() {
131 prov.visit_tags(visit);
134 self.extra.visit_tags(visit);
138 impl VisitTags for crate::MiriInterpCx<'_, '_> {
139 fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
141 self.memory.alloc_map().iter(|it| {
142 for (_id, (_kind, alloc)) in it {
143 alloc.visit_tags(visit);
147 // And all the other machine values.
148 self.machine.visit_tags(visit);
152 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
153 pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
154 fn garbage_collect_tags(&mut self) -> InterpResult<'tcx> {
155 let this = self.eval_context_mut();
156 // No reason to do anything at all if stacked borrows is off.
157 if this.machine.stacked_borrows.is_none() {
161 let mut tags = FxHashSet::default();
162 this.visit_tags(&mut |tag| {
165 self.remove_unreachable_tags(tags);
170 fn remove_unreachable_tags(&mut self, tags: FxHashSet<SbTag>) {
171 let this = self.eval_context_mut();
172 this.memory.alloc_map().iter(|it| {
173 for (_id, (_kind, alloc)) in it {
180 .remove_unreachable_tags(&tags);