Auto merge of #46100 - KiChjang:mass-dead-check, r=nikomatsakis
Kill the storage for all locals on returning terminators Fixes #45704.
This commit is contained in:
commit
2ca00a9489
@ -373,10 +373,41 @@ fn visit_terminator_entry(&mut self,
|
||||
Consume, (value, span), flow_state);
|
||||
}
|
||||
|
||||
TerminatorKind::Goto { target: _ } |
|
||||
TerminatorKind::Resume |
|
||||
TerminatorKind::Return |
|
||||
TerminatorKind::GeneratorDrop |
|
||||
TerminatorKind::GeneratorDrop => {
|
||||
// Returning from the function implicitly kills storage for all locals and statics.
|
||||
// Often, the storage will already have been killed by an explicit
|
||||
// StorageDead, but we don't always emit those (notably on unwind paths),
|
||||
// so this "extra check" serves as a kind of backup.
|
||||
let domain = flow_state.borrows.base_results.operator();
|
||||
for borrow in domain.borrows() {
|
||||
let root_lvalue = self.prefixes(
|
||||
&borrow.lvalue,
|
||||
PrefixSet::All
|
||||
).last().unwrap();
|
||||
match root_lvalue {
|
||||
Lvalue::Static(_) => {
|
||||
self.access_lvalue(
|
||||
ContextKind::StorageDead.new(loc),
|
||||
(&root_lvalue, self.mir.source_info(borrow.location).span),
|
||||
(Deep, Write(WriteKind::StorageDeadOrDrop)),
|
||||
flow_state
|
||||
);
|
||||
}
|
||||
Lvalue::Local(_) => {
|
||||
self.access_lvalue(
|
||||
ContextKind::StorageDead.new(loc),
|
||||
(&root_lvalue, self.mir.source_info(borrow.location).span),
|
||||
(Shallow(None), Write(WriteKind::StorageDeadOrDrop)),
|
||||
flow_state
|
||||
);
|
||||
}
|
||||
Lvalue::Projection(_) => ()
|
||||
}
|
||||
}
|
||||
}
|
||||
TerminatorKind::Goto { target: _ } |
|
||||
TerminatorKind::Unreachable |
|
||||
TerminatorKind::FalseEdges { .. } => {
|
||||
// no data used, thus irrelevant to borrowck
|
||||
|
@ -233,6 +233,35 @@ fn statement_effect(&self,
|
||||
fn terminator_effect(&self,
|
||||
sets: &mut BlockSets<BorrowIndex>,
|
||||
location: Location) {
|
||||
let block = &self.mir.basic_blocks().get(location.block).unwrap_or_else(|| {
|
||||
panic!("could not find block at location {:?}", location);
|
||||
});
|
||||
match block.terminator().kind {
|
||||
mir::TerminatorKind::Resume |
|
||||
mir::TerminatorKind::Return |
|
||||
mir::TerminatorKind::GeneratorDrop => {
|
||||
// When we return from the function, then all `ReScope`-style regions
|
||||
// are guaranteed to have ended.
|
||||
// Normally, there would be `EndRegion` statements that come before,
|
||||
// and hence most of these loans will already be dead -- but, in some cases
|
||||
// like unwind paths, we do not always emit `EndRegion` statements, so we
|
||||
// add some kills here as a "backup" and to avoid spurious error messages.
|
||||
for (borrow_index, borrow_data) in self.borrows.iter_enumerated() {
|
||||
if let ReScope(..) = borrow_data.region {
|
||||
sets.kill(&borrow_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
mir::TerminatorKind::SwitchInt {..} |
|
||||
mir::TerminatorKind::Drop {..} |
|
||||
mir::TerminatorKind::DropAndReplace {..} |
|
||||
mir::TerminatorKind::Call {..} |
|
||||
mir::TerminatorKind::Assert {..} |
|
||||
mir::TerminatorKind::Yield {..} |
|
||||
mir::TerminatorKind::Goto {..} |
|
||||
mir::TerminatorKind::FalseEdges {..} |
|
||||
mir::TerminatorKind::Unreachable => {}
|
||||
}
|
||||
self.kill_loans_out_of_scope_at_location(sets, location);
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,20 @@
|
||||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// revisions: ast mir
|
||||
//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir
|
||||
|
||||
fn cplusplus_mode(x: isize) -> &'static isize {
|
||||
&x //[ast]~ ERROR `x` does not live long enough
|
||||
//[mir]~^ ERROR `x` does not live long enough (Ast)
|
||||
//[mir]~| ERROR borrowed value does not live long enough (Mir)
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,24 @@
|
||||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// revisions: ast mir
|
||||
//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir
|
||||
|
||||
#![feature(thread_local)]
|
||||
|
||||
#[thread_local]
|
||||
static FOO: u8 = 3;
|
||||
|
||||
fn assert_static(_t: &'static u8) {}
|
||||
fn main() {
|
||||
assert_static(&FOO); //[ast]~ ERROR [E0597]
|
||||
//[mir]~^ ERROR (Ast) [E0597]
|
||||
//[mir]~| ERROR (Mir) [E0597]
|
||||
}
|
@ -13,6 +13,7 @@
|
||||
// including) the call to `use_x`. The `else` branch is not included.
|
||||
|
||||
// ignore-tidy-linelength
|
||||
// ignore-test #46267
|
||||
// compile-flags:-Znll -Zverbose
|
||||
// ^^^^^^^^^ force compiler to dump more region information
|
||||
|
||||
|
19
src/test/run-fail/borrowck-local-borrow.rs
Normal file
19
src/test/run-fail/borrowck-local-borrow.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
// error-pattern:panic 1
|
||||
|
||||
// revisions: ast mir
|
||||
//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir
|
||||
|
||||
fn main() {
|
||||
let x = 2;
|
||||
let y = &x;
|
||||
panic!("panic 1");
|
||||
}
|
Loading…
Reference in New Issue
Block a user