about summary refs log tree commit diff
path: root/compiler/rustc_const_eval
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-02-27 11:41:41 +0000
committerbors <bors@rust-lang.org>2023-02-27 11:41:41 +0000
commit7d782b7ff4d57170e110211565209ecc5bbb3907 (patch)
tree8554515c247bf460d6be7509310350d6fb750d4c /compiler/rustc_const_eval
parent49b9cc5139dd4d11ef78dc08c1f9170de5b1ca39 (diff)
parentbf46b9cb281cd196ca6227b2b72ef64dee390b5a (diff)
downloadrust-7d782b7ff4d57170e110211565209ecc5bbb3907.tar.gz
rust-7d782b7ff4d57170e110211565209ecc5bbb3907.zip
Auto merge of #108175 - cjgillot:validate-storage, r=tmiasko
MIR-Validate StorageLive.

`StorageLive` statements on a local which already has storage is banned by miri.

This check is easy enough, and can detect bugs in MIR opts.
Diffstat (limited to 'compiler/rustc_const_eval')
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs22
1 files changed, 20 insertions, 2 deletions
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index 068491646f4..fb37eb79a33 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -755,8 +755,26 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                     self.fail(location, format!("explicit `{:?}` is forbidden", kind));
                 }
             }
-            StatementKind::StorageLive(..)
-            | StatementKind::StorageDead(..)
+            StatementKind::StorageLive(local) => {
+                // We check that the local is not live when entering a `StorageLive` for it.
+                // Technically, violating this restriction is only UB and not actually indicative
+                // of not well-formed MIR. This means that an optimization which turns MIR that
+                // already has UB into MIR that fails this check is not necessarily wrong. However,
+                // we have no such optimizations at the moment, and so we include this check anyway
+                // to help us catch bugs. If you happen to write an optimization that might cause
+                // this to incorrectly fire, feel free to remove this check.
+                if self.reachable_blocks.contains(location.block) {
+                    self.storage_liveness.seek_before_primary_effect(location);
+                    let locals_with_storage = self.storage_liveness.get();
+                    if locals_with_storage.contains(*local) {
+                        self.fail(
+                            location,
+                            format!("StorageLive({local:?}) which already has storage here"),
+                        );
+                    }
+                }
+            }
+            StatementKind::StorageDead(_)
             | StatementKind::Coverage(_)
             | StatementKind::ConstEvalCounter
             | StatementKind::Nop => {}