@@ -209,12 +209,21 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
209209 } ;
210210 let flow_inits = flow_inits; // remove mut
211211
212+ let movable_generator = !match tcx. hir . get ( id) {
213+ hir:: map:: Node :: NodeExpr ( & hir:: Expr {
214+ node : hir:: ExprClosure ( .., Some ( hir:: GeneratorMovability :: Static ) ) ,
215+ ..
216+ } ) => true ,
217+ _ => false ,
218+ } ;
219+
212220 let mut mbcx = MirBorrowckCtxt {
213221 tcx : tcx,
214222 mir : mir,
215223 node_id : id,
216224 move_data : & mdpe. move_data ,
217225 param_env : param_env,
226+ movable_generator,
218227 locals_are_invalidated_at_exit : match tcx. hir . body_owner_kind ( id) {
219228 hir:: BodyOwnerKind :: Const | hir:: BodyOwnerKind :: Static ( _) => false ,
220229 hir:: BodyOwnerKind :: Fn => true ,
@@ -277,6 +286,7 @@ pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
277286 node_id : ast:: NodeId ,
278287 move_data : & ' cx MoveData < ' tcx > ,
279288 param_env : ParamEnv < ' gcx > ,
289+ movable_generator : bool ,
280290 /// This keeps track of whether local variables are free-ed when the function
281291 /// exits even without a `StorageDead`, which appears to be the case for
282292 /// constants.
@@ -534,6 +544,18 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
534544 drop : _,
535545 } => {
536546 self . consume_operand ( ContextKind :: Yield . new ( loc) , ( value, span) , flow_state) ;
547+
548+ if self . movable_generator {
549+ // Look for any active borrows to locals
550+ let domain = flow_state. borrows . operator ( ) ;
551+ let data = domain. borrows ( ) ;
552+ flow_state. borrows . with_elems_outgoing ( |borrows| {
553+ for i in borrows {
554+ let borrow = & data[ i. borrow_index ( ) ] ;
555+ self . check_for_local_borrow ( borrow, span) ;
556+ }
557+ } ) ;
558+ }
537559 }
538560
539561 TerminatorKind :: Resume | TerminatorKind :: Return | TerminatorKind :: GeneratorDrop => {
@@ -1099,6 +1121,45 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
10991121 }
11001122 }
11011123
1124+ /// Reports an error if this is a borrow of local data.
1125+ /// This is called for all Yield statements on movable generators
1126+ fn check_for_local_borrow (
1127+ & mut self ,
1128+ borrow : & BorrowData < ' tcx > ,
1129+ yield_span : Span )
1130+ {
1131+ fn borrow_of_local_data < ' tcx > ( place : & Place < ' tcx > ) -> bool {
1132+ match place {
1133+ Place :: Static ( ..) => false ,
1134+ Place :: Local ( ..) => true ,
1135+ Place :: Projection ( box proj) => {
1136+ match proj. elem {
1137+ // Reborrow of already borrowed data is ignored
1138+ // Any errors will be caught on the initial borrow
1139+ ProjectionElem :: Deref => false ,
1140+
1141+ // For interior references and downcasts, find out if the base is local
1142+ ProjectionElem :: Field ( ..) |
1143+ ProjectionElem :: Index ( ..) |
1144+ ProjectionElem :: ConstantIndex { .. } |
1145+ ProjectionElem :: Subslice { .. } |
1146+ ProjectionElem :: Downcast ( ..) => {
1147+ borrow_of_local_data ( & proj. base )
1148+ }
1149+ }
1150+ }
1151+ }
1152+ }
1153+
1154+ debug ! ( "check_for_local_borrow({:?})" , borrow) ;
1155+
1156+ if borrow_of_local_data ( & borrow. borrowed_place ) {
1157+ self . tcx . cannot_borrow_across_generator_yield ( self . retrieve_borrow_span ( borrow) ,
1158+ yield_span,
1159+ Origin :: Mir ) . emit ( ) ;
1160+ }
1161+ }
1162+
11021163 fn check_activations (
11031164 & mut self ,
11041165 location : Location ,
0 commit comments