Skip to content

Commit e3b87f6

Browse files
committed
Auto merge of #931 - RalfJung:retag-makes-my-head-hurt, r=RalfJung
Stacked Borrows: don't read from memory during retagging Currently, retagging of a shared reference tries real hard to find the `UnsafeCell` and mark everything else as frozen. We even read enum discriminants to figure out the variant and determine if there is an `UnsafeCell` in there or not. Unfortunately, that leads to some very hard to analyze behavior: during retagging, we do read accesses, which are subject to the rules of Stacked Borrows and the existing tags! My head hurts when I try to think about this. It's just too recursive. This PR simplifies the semantics by treating enums like unions: if any variant has an `UnsafeCell`, the entire thing behaves like an `UnsafeCell`. This means retagging no longer has to read from memory, the way it affects the stack is entirely determined by the type.
2 parents 2661580 + f3ff100 commit e3b87f6

File tree

1 file changed

+20
-2
lines changed

1 file changed

+20
-2
lines changed

src/helpers.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -222,8 +222,26 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
222222
// This is `Freeze`, there cannot be an `UnsafeCell`
223223
Ok(())
224224
} else {
225-
// Proceed further
226-
self.walk_value(v)
225+
// We want to not actually read from memory for this visit. So, before
226+
// walking this value, we have to make sure it is not a
227+
// `Variants::Multiple`.
228+
match v.layout.variants {
229+
layout::Variants::Multiple { .. } => {
230+
// A multi-variant enum, or generator, or so.
231+
// Treat this like a union: without reading from memory,
232+
// we cannot determine the variant we are in. Reading from
233+
// memory would be subject to Stacked Borrows rules, leading
234+
// to all sorts of "funny" recursion.
235+
// We only end up here if the type is *not* freeze, so we just call the
236+
// `UnsafeCell` action.
237+
(self.unsafe_cell_action)(v)
238+
}
239+
layout::Variants::Single { .. } => {
240+
// Proceed further, try to find where exactly that `UnsafeCell`
241+
// is hiding.
242+
self.walk_value(v)
243+
}
244+
}
227245
}
228246
}
229247

0 commit comments

Comments
 (0)