@@ -209,12 +209,21 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
209
209
} ;
210
210
let flow_inits = flow_inits; // remove mut
211
211
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
+
212
220
let mut mbcx = MirBorrowckCtxt {
213
221
tcx : tcx,
214
222
mir : mir,
215
223
node_id : id,
216
224
move_data : & mdpe. move_data ,
217
225
param_env : param_env,
226
+ movable_generator,
218
227
locals_are_invalidated_at_exit : match tcx. hir . body_owner_kind ( id) {
219
228
hir:: BodyOwnerKind :: Const | hir:: BodyOwnerKind :: Static ( _) => false ,
220
229
hir:: BodyOwnerKind :: Fn => true ,
@@ -277,6 +286,7 @@ pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
277
286
node_id : ast:: NodeId ,
278
287
move_data : & ' cx MoveData < ' tcx > ,
279
288
param_env : ParamEnv < ' gcx > ,
289
+ movable_generator : bool ,
280
290
/// This keeps track of whether local variables are free-ed when the function
281
291
/// exits even without a `StorageDead`, which appears to be the case for
282
292
/// constants.
@@ -534,6 +544,18 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
534
544
drop : _,
535
545
} => {
536
546
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
+ }
537
559
}
538
560
539
561
TerminatorKind :: Resume | TerminatorKind :: Return | TerminatorKind :: GeneratorDrop => {
@@ -1099,6 +1121,45 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
1099
1121
}
1100
1122
}
1101
1123
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
+
1102
1163
fn check_activations (
1103
1164
& mut self ,
1104
1165
location : Location ,
0 commit comments