From 79dd70fd9bd2de5a0b2dd4697905571f39012dc7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 28 Aug 2019 18:41:30 +0200 Subject: [PATCH 1/2] Stacked Borrows: don't read from memory during retagging --- src/helpers.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/helpers.rs b/src/helpers.rs index 330d6bc996..e5203becd5 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -222,8 +222,23 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // This is `Freeze`, there cannot be an `UnsafeCell` Ok(()) } else { - // Proceed further - self.walk_value(v) + // We want to not actually read from memory for this visit. So, before + // walking this value, we have to make sure it is not a + // `Variants::Multiple`. + match v.layout.variants { + layout::Variants::Multiple { .. } => { + // A multi-variant enum, or generator, or so. + // Treat this like a union: without reading from memory, + // we cannot determine the variant we are in. Reading from + // memory would be subject to Stacked Borrows rules, leading + // to all sorts of "funny" recursion. + self.visit_union(v) + } + layout::Variants::Single { .. } => { + // Proceed further + self.walk_value(v) + } + } } } From f3ff10005ab1bdb7c4c0d43ee54d55563911f5ea Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 28 Aug 2019 18:45:10 +0200 Subject: [PATCH 2/2] small optimization --- src/helpers.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/helpers.rs b/src/helpers.rs index e5203becd5..3eafb28b89 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -232,10 +232,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // we cannot determine the variant we are in. Reading from // memory would be subject to Stacked Borrows rules, leading // to all sorts of "funny" recursion. - self.visit_union(v) + // We only end up here if the type is *not* freeze, so we just call the + // `UnsafeCell` action. + (self.unsafe_cell_action)(v) } layout::Variants::Single { .. } => { - // Proceed further + // Proceed further, try to find where exactly that `UnsafeCell` + // is hiding. self.walk_value(v) } }