Skip to content

Commit 2ca00a9

Browse files
committed
Auto merge of #46100 - KiChjang:mass-dead-check, r=nikomatsakis
Kill the storage for all locals on returning terminators Fixes #45704.
2 parents 2c11555 + efa3ed2 commit 2ca00a9

File tree

6 files changed

+126
-2
lines changed

6 files changed

+126
-2
lines changed

src/librustc_mir/borrow_check.rs

+33-2
Original file line numberDiff line numberDiff line change
@@ -373,10 +373,41 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
373373
Consume, (value, span), flow_state);
374374
}
375375

376-
TerminatorKind::Goto { target: _ } |
377376
TerminatorKind::Resume |
378377
TerminatorKind::Return |
379-
TerminatorKind::GeneratorDrop |
378+
TerminatorKind::GeneratorDrop => {
379+
// Returning from the function implicitly kills storage for all locals and statics.
380+
// Often, the storage will already have been killed by an explicit
381+
// StorageDead, but we don't always emit those (notably on unwind paths),
382+
// so this "extra check" serves as a kind of backup.
383+
let domain = flow_state.borrows.base_results.operator();
384+
for borrow in domain.borrows() {
385+
let root_lvalue = self.prefixes(
386+
&borrow.lvalue,
387+
PrefixSet::All
388+
).last().unwrap();
389+
match root_lvalue {
390+
Lvalue::Static(_) => {
391+
self.access_lvalue(
392+
ContextKind::StorageDead.new(loc),
393+
(&root_lvalue, self.mir.source_info(borrow.location).span),
394+
(Deep, Write(WriteKind::StorageDeadOrDrop)),
395+
flow_state
396+
);
397+
}
398+
Lvalue::Local(_) => {
399+
self.access_lvalue(
400+
ContextKind::StorageDead.new(loc),
401+
(&root_lvalue, self.mir.source_info(borrow.location).span),
402+
(Shallow(None), Write(WriteKind::StorageDeadOrDrop)),
403+
flow_state
404+
);
405+
}
406+
Lvalue::Projection(_) => ()
407+
}
408+
}
409+
}
410+
TerminatorKind::Goto { target: _ } |
380411
TerminatorKind::Unreachable |
381412
TerminatorKind::FalseEdges { .. } => {
382413
// no data used, thus irrelevant to borrowck

src/librustc_mir/dataflow/impls/borrows.rs

+29
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,35 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
233233
fn terminator_effect(&self,
234234
sets: &mut BlockSets<BorrowIndex>,
235235
location: Location) {
236+
let block = &self.mir.basic_blocks().get(location.block).unwrap_or_else(|| {
237+
panic!("could not find block at location {:?}", location);
238+
});
239+
match block.terminator().kind {
240+
mir::TerminatorKind::Resume |
241+
mir::TerminatorKind::Return |
242+
mir::TerminatorKind::GeneratorDrop => {
243+
// When we return from the function, then all `ReScope`-style regions
244+
// are guaranteed to have ended.
245+
// Normally, there would be `EndRegion` statements that come before,
246+
// and hence most of these loans will already be dead -- but, in some cases
247+
// like unwind paths, we do not always emit `EndRegion` statements, so we
248+
// add some kills here as a "backup" and to avoid spurious error messages.
249+
for (borrow_index, borrow_data) in self.borrows.iter_enumerated() {
250+
if let ReScope(..) = borrow_data.region {
251+
sets.kill(&borrow_index);
252+
}
253+
}
254+
}
255+
mir::TerminatorKind::SwitchInt {..} |
256+
mir::TerminatorKind::Drop {..} |
257+
mir::TerminatorKind::DropAndReplace {..} |
258+
mir::TerminatorKind::Call {..} |
259+
mir::TerminatorKind::Assert {..} |
260+
mir::TerminatorKind::Yield {..} |
261+
mir::TerminatorKind::Goto {..} |
262+
mir::TerminatorKind::FalseEdges {..} |
263+
mir::TerminatorKind::Unreachable => {}
264+
}
236265
self.kill_loans_out_of_scope_at_location(sets, location);
237266
}
238267

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// revisions: ast mir
12+
//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir
13+
14+
fn cplusplus_mode(x: isize) -> &'static isize {
15+
&x //[ast]~ ERROR `x` does not live long enough
16+
//[mir]~^ ERROR `x` does not live long enough (Ast)
17+
//[mir]~| ERROR borrowed value does not live long enough (Mir)
18+
}
19+
20+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// revisions: ast mir
12+
//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir
13+
14+
#![feature(thread_local)]
15+
16+
#[thread_local]
17+
static FOO: u8 = 3;
18+
19+
fn assert_static(_t: &'static u8) {}
20+
fn main() {
21+
assert_static(&FOO); //[ast]~ ERROR [E0597]
22+
//[mir]~^ ERROR (Ast) [E0597]
23+
//[mir]~| ERROR (Mir) [E0597]
24+
}

src/test/mir-opt/nll/region-liveness-drop-no-may-dangle.rs

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
// including) the call to `use_x`. The `else` branch is not included.
1414

1515
// ignore-tidy-linelength
16+
// ignore-test #46267
1617
// compile-flags:-Znll -Zverbose
1718
// ^^^^^^^^^ force compiler to dump more region information
1819

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
// error-pattern:panic 1
11+
12+
// revisions: ast mir
13+
//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir
14+
15+
fn main() {
16+
let x = 2;
17+
let y = &x;
18+
panic!("panic 1");
19+
}

0 commit comments

Comments
 (0)