mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
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.
This commit is contained in:
commit
7d782b7ff4
@ -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 => {}
|
||||
|
30
tests/ui/mir/validate/storage-live.rs
Normal file
30
tests/ui/mir/validate/storage-live.rs
Normal file
@ -0,0 +1,30 @@
|
||||
// compile-flags: -Zvalidate-mir -Ztreat-err-as-bug
|
||||
// failure-status: 101
|
||||
// error-pattern: broken MIR in
|
||||
// error-pattern: StorageLive(_1) which already has storage here
|
||||
// normalize-stderr-test "note: .*\n\n" -> ""
|
||||
// normalize-stderr-test "thread 'rustc' panicked.*\n" -> ""
|
||||
// normalize-stderr-test "storage_live\[....\]" -> "storage_live[HASH]"
|
||||
// rustc-env:RUST_BACKTRACE=0
|
||||
|
||||
#![feature(custom_mir, core_intrinsics)]
|
||||
|
||||
extern crate core;
|
||||
use core::intrinsics::mir::*;
|
||||
use core::ptr::{addr_of, addr_of_mut};
|
||||
|
||||
#[custom_mir(dialect = "built")]
|
||||
fn multiple_storage() {
|
||||
mir!(
|
||||
let a: usize;
|
||||
{
|
||||
StorageLive(a);
|
||||
StorageLive(a);
|
||||
Return()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
multiple_storage()
|
||||
}
|
13
tests/ui/mir/validate/storage-live.stderr
Normal file
13
tests/ui/mir/validate/storage-live.stderr
Normal file
@ -0,0 +1,13 @@
|
||||
error: internal compiler error: broken MIR in Item(WithOptConstParam { did: DefId(0:8 ~ storage_live[HASH]::multiple_storage), const_param_did: None }) (before pass CheckPackedRef) at bb0[1]:
|
||||
StorageLive(_1) which already has storage here
|
||||
--> $DIR/storage-live.rs:22:13
|
||||
|
|
||||
LL | StorageLive(a);
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: the compiler unexpectedly panicked. this is a bug.
|
||||
|
||||
query stack during panic:
|
||||
#0 [mir_const] preparing `multiple_storage` for borrow checking
|
||||
#1 [mir_promoted] processing MIR for `multiple_storage`
|
||||
end of query stack
|
Loading…
Reference in New Issue
Block a user