};
let flow_inits = flow_inits; // remove mut
+ let movable_generator = !match tcx.hir.get(id) {
+ hir::map::Node::NodeExpr(&hir::Expr {
+ node: hir::ExprClosure(.., Some(hir::GeneratorMovability::Static)),
+ ..
+ }) => true,
+ _ => false,
+ };
+
let mut mbcx = MirBorrowckCtxt {
tcx: tcx,
mir: mir,
node_id: id,
move_data: &mdpe.move_data,
param_env: param_env,
+ movable_generator,
locals_are_invalidated_at_exit: match tcx.hir.body_owner_kind(id) {
hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => false,
hir::BodyOwnerKind::Fn => true,
node_id: ast::NodeId,
move_data: &'cx MoveData<'tcx>,
param_env: ParamEnv<'gcx>,
+ movable_generator: bool,
/// This keeps track of whether local variables are free-ed when the function
/// exits even without a `StorageDead`, which appears to be the case for
/// constants.
drop: _,
} => {
self.consume_operand(ContextKind::Yield.new(loc), (value, span), flow_state);
+
+ if self.movable_generator {
+ // Look for any active borrows to locals
+ let domain = flow_state.borrows.operator();
+ let data = domain.borrows();
+ flow_state.borrows.with_elems_outgoing(|borrows| {
+ for i in borrows {
+ let borrow = &data[i.borrow_index()];
+ self.check_for_local_borrow(borrow, span);
+ }
+ });
+ }
}
TerminatorKind::Resume | TerminatorKind::Return | TerminatorKind::GeneratorDrop => {
}
}
+ /// Reports an error if this is a borrow of local data.
+ /// This is called for all Yield statements on movable generators
+ fn check_for_local_borrow(
+ &mut self,
+ borrow: &BorrowData<'tcx>,
+ yield_span: Span)
+ {
+ fn borrow_of_local_data<'tcx>(place: &Place<'tcx>) -> bool {
+ match place {
+ Place::Static(..) => false,
+ Place::Local(..) => true,
+ Place::Projection(box proj) => {
+ match proj.elem {
+ // Reborrow of already borrowed data is ignored
+ // Any errors will be caught on the initial borrow
+ ProjectionElem::Deref => false,
+
+ // For interior references and downcasts, find out if the base is local
+ ProjectionElem::Field(..) |
+ ProjectionElem::Index(..) |
+ ProjectionElem::ConstantIndex { .. } |
+ ProjectionElem::Subslice { .. } |
+ ProjectionElem::Downcast(..) => {
+ borrow_of_local_data(&proj.base)
+ }
+ }
+ }
+ }
+ }
+
+ debug!("check_for_local_borrow({:?})", borrow);
+
+ if borrow_of_local_data(&borrow.borrowed_place) {
+ self.tcx.cannot_borrow_across_generator_yield(self.retrieve_borrow_span(borrow),
+ yield_span,
+ Origin::Mir).emit();
+ }
+ }
+
fn check_activations(
&mut self,
location: Location,
--- /dev/null
+// Copyright 2018 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.
+
+// compile-flags: -Z borrowck=compare
+
+#![feature(generators)]
+#![feature(nll)]
+
+fn main() {
+ || {
+ // The reference in `_a` is a Legal with NLL since it ends before the yield
+ let _a = &mut true; //~ ERROR borrow may still be in use when generator yields (Ast)
+ let b = &mut true; //~ ERROR borrow may still be in use when generator yields (Ast)
+ //~^ borrow may still be in use when generator yields (Mir)
+ yield ();
+ println!("{}", b);
+ };
+}
--- /dev/null
+error[E0626]: borrow may still be in use when generator yields (Mir)
+ --> $DIR/generator-with-nll.rs:20:17
+ |
+20 | let b = &mut true; //~ ERROR borrow may still be in use when generator yields (Ast)
+ | ^^^^^^^^^
+21 | //~^ borrow may still be in use when generator yields (Mir)
+22 | yield ();
+ | -------- possible yield occurs here
+
+error[E0626]: borrow may still be in use when generator yields (Ast)
+ --> $DIR/generator-with-nll.rs:19:23
+ |
+19 | let _a = &mut true; //~ ERROR borrow may still be in use when generator yields (Ast)
+ | ^^^^
+...
+22 | yield ();
+ | -------- possible yield occurs here
+
+error[E0626]: borrow may still be in use when generator yields (Ast)
+ --> $DIR/generator-with-nll.rs:20:22
+ |
+20 | let b = &mut true; //~ ERROR borrow may still be in use when generator yields (Ast)
+ | ^^^^
+21 | //~^ borrow may still be in use when generator yields (Mir)
+22 | yield ();
+ | -------- possible yield occurs here
+
+error: aborting due to 3 previous errors
+