From 70b960b879528b6ef5f8df4e0f8e2d8b72e1d221 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sun, 28 Aug 2022 13:07:33 -0400 Subject: [PATCH 1/2] Skip field retagging on ZSTs, it can take forever --- src/stacked_borrows/mod.rs | 8 ++++++++ .../stacked-borrows/zst-field-retagging-terminates.rs | 5 +++++ 2 files changed, 13 insertions(+) create mode 100644 tests/pass/stacked-borrows/zst-field-retagging-terminates.rs diff --git a/src/stacked_borrows/mod.rs b/src/stacked_borrows/mod.rs index 66fdd685def5..5cdcaecc17d2 100644 --- a/src/stacked_borrows/mod.rs +++ b/src/stacked_borrows/mod.rs @@ -973,6 +973,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx } fn visit_value(&mut self, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> { + // If this place is smaller than a pointer, we know that it can't contain any + // pointers we need to retag, so we can stop recursion early. + // This optimization is crucial for ZSTs, because they can contain way more fields + // than we can ever visit. + if !place.layout.is_unsized() && place.layout.size < self.ecx.pointer_size() { + return Ok(()); + } + if let Some((ref_kind, protector)) = qualify(place.layout.ty, self.kind) { self.retag_place(place, ref_kind, self.retag_cause, protector)?; } else if matches!(place.layout.ty.kind(), ty::RawPtr(..)) { diff --git a/tests/pass/stacked-borrows/zst-field-retagging-terminates.rs b/tests/pass/stacked-borrows/zst-field-retagging-terminates.rs new file mode 100644 index 000000000000..2099c5ad1496 --- /dev/null +++ b/tests/pass/stacked-borrows/zst-field-retagging-terminates.rs @@ -0,0 +1,5 @@ +//@compile-flags: -Zmiri-retag-fields +fn main() { + let array = [(); usize::MAX]; + drop(array); // Pass the array to a function, retagging its fields +} From c9b36b4dedab0c1b44f0357ddbf4ebc3a702e259 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 29 Aug 2022 07:46:03 -0400 Subject: [PATCH 2/2] clarify test purpose --- tests/pass/stacked-borrows/zst-field-retagging-terminates.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/pass/stacked-borrows/zst-field-retagging-terminates.rs b/tests/pass/stacked-borrows/zst-field-retagging-terminates.rs index 2099c5ad1496..ce3c8b7d5f1a 100644 --- a/tests/pass/stacked-borrows/zst-field-retagging-terminates.rs +++ b/tests/pass/stacked-borrows/zst-field-retagging-terminates.rs @@ -1,4 +1,5 @@ //@compile-flags: -Zmiri-retag-fields +// Checks that the test does not run forever (which relies on a fast path). fn main() { let array = [(); usize::MAX]; drop(array); // Pass the array to a function, retagging its fields