Assert that locals have storage when used
The validator in visit_local asserts that local has a stroage when used, but visit_local is never called so validation is ineffective. Use super_statement and super_terminator to ensure that locals are visited.
This commit is contained in:
parent
4f7612ac14
commit
3b7157dc1a
3 changed files with 23 additions and 11 deletions
|
@ -5,10 +5,10 @@ use crate::dataflow::{Analysis, ResultsCursor};
|
||||||
use crate::util::storage::AlwaysLiveLocals;
|
use crate::util::storage::AlwaysLiveLocals;
|
||||||
|
|
||||||
use super::MirPass;
|
use super::MirPass;
|
||||||
use rustc_middle::mir::{
|
use rustc_index::bit_set::BitSet;
|
||||||
interpret::Scalar,
|
use rustc_middle::mir::interpret::Scalar;
|
||||||
visit::{PlaceContext, Visitor},
|
use rustc_middle::mir::traversal;
|
||||||
};
|
use rustc_middle::mir::visit::{PlaceContext, Visitor};
|
||||||
use rustc_middle::mir::{
|
use rustc_middle::mir::{
|
||||||
AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPhase, Operand, PlaceRef,
|
AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPhase, Operand, PlaceRef,
|
||||||
Rvalue, SourceScope, Statement, StatementKind, Terminator, TerminatorKind, VarDebugInfo,
|
Rvalue, SourceScope, Statement, StatementKind, Terminator, TerminatorKind, VarDebugInfo,
|
||||||
|
@ -52,6 +52,7 @@ impl<'tcx> MirPass<'tcx> for Validator {
|
||||||
tcx,
|
tcx,
|
||||||
param_env,
|
param_env,
|
||||||
mir_phase,
|
mir_phase,
|
||||||
|
reachable_blocks: traversal::reachable_as_bitset(body),
|
||||||
storage_liveness,
|
storage_liveness,
|
||||||
place_cache: Vec::new(),
|
place_cache: Vec::new(),
|
||||||
}
|
}
|
||||||
|
@ -157,6 +158,7 @@ struct TypeChecker<'a, 'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
param_env: ParamEnv<'tcx>,
|
param_env: ParamEnv<'tcx>,
|
||||||
mir_phase: MirPhase,
|
mir_phase: MirPhase,
|
||||||
|
reachable_blocks: BitSet<BasicBlock>,
|
||||||
storage_liveness: ResultsCursor<'a, 'tcx, MaybeStorageLive>,
|
storage_liveness: ResultsCursor<'a, 'tcx, MaybeStorageLive>,
|
||||||
place_cache: Vec<PlaceRef<'tcx>>,
|
place_cache: Vec<PlaceRef<'tcx>>,
|
||||||
}
|
}
|
||||||
|
@ -232,7 +234,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
|
|
||||||
impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
||||||
fn visit_local(&mut self, local: &Local, context: PlaceContext, location: Location) {
|
fn visit_local(&mut self, local: &Local, context: PlaceContext, location: Location) {
|
||||||
if context.is_use() {
|
if self.reachable_blocks.contains(location.block) && context.is_use() {
|
||||||
// Uses of locals must occur while the local's storage is allocated.
|
// Uses of locals must occur while the local's storage is allocated.
|
||||||
self.storage_liveness.seek_after_primary_effect(location);
|
self.storage_liveness.seek_after_primary_effect(location);
|
||||||
let locals_with_storage = self.storage_liveness.get();
|
let locals_with_storage = self.storage_liveness.get();
|
||||||
|
@ -249,6 +251,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
|
fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
|
||||||
|
// This check is somewhat expensive, so only run it when -Zvalidate-mir is passed.
|
||||||
|
if self.tcx.sess.opts.debugging_opts.validate_mir {
|
||||||
// `Operand::Copy` is only supposed to be used with `Copy` types.
|
// `Operand::Copy` is only supposed to be used with `Copy` types.
|
||||||
if let Operand::Copy(place) = operand {
|
if let Operand::Copy(place) = operand {
|
||||||
let ty = place.ty(&self.body.local_decls, self.tcx).ty;
|
let ty = place.ty(&self.body.local_decls, self.tcx).ty;
|
||||||
|
@ -258,6 +262,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
||||||
self.fail(location, format!("`Operand::Copy` with non-`Copy` type {}", ty));
|
self.fail(location, format!("`Operand::Copy` with non-`Copy` type {}", ty));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.super_operand(operand, location);
|
self.super_operand(operand, location);
|
||||||
}
|
}
|
||||||
|
@ -341,6 +346,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.super_statement(statement, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
|
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
|
||||||
|
@ -489,6 +496,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
||||||
| TerminatorKind::Unreachable
|
| TerminatorKind::Unreachable
|
||||||
| TerminatorKind::GeneratorDrop => {}
|
| TerminatorKind::GeneratorDrop => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.super_terminator(terminator, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_source_scope(&mut self, scope: &SourceScope) {
|
fn visit_source_scope(&mut self, scope: &SourceScope) {
|
||||||
|
|
|
@ -23,6 +23,7 @@ pub trait Receiver { }
|
||||||
pub struct Result<T, E> { _a: T, _b: E }
|
pub struct Result<T, E> { _a: T, _b: E }
|
||||||
|
|
||||||
impl Copy for usize {}
|
impl Copy for usize {}
|
||||||
|
impl Copy for &usize {}
|
||||||
|
|
||||||
#[lang = "drop_in_place"]
|
#[lang = "drop_in_place"]
|
||||||
pub unsafe fn drop_in_place<T: ?Sized>(_: *mut T) {}
|
pub unsafe fn drop_in_place<T: ?Sized>(_: *mut T) {}
|
||||||
|
|
|
@ -14,6 +14,8 @@ trait Sized {}
|
||||||
|
|
||||||
#[lang = "copy"]
|
#[lang = "copy"]
|
||||||
trait Copy {}
|
trait Copy {}
|
||||||
|
impl Copy for bool {}
|
||||||
|
impl Copy for &bool {}
|
||||||
|
|
||||||
#[lang = "freeze"]
|
#[lang = "freeze"]
|
||||||
trait Freeze {}
|
trait Freeze {}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue