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
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);
}
--- /dev/null
+// 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() {}
--- /dev/null
+// 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]
+}
--- /dev/null
+// 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");
+}