@@ -123,7 +123,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
123123 Origin :: Mir ,
124124 ) ;
125125
126- self . add_closure_invoked_twice_with_moved_variable_suggestion (
126+ self . add_moved_or_invoked_closure_note (
127127 context. loc ,
128128 used_place,
129129 & mut err,
@@ -1331,7 +1331,8 @@ enum StorageDeadOrDrop<'tcx> {
13311331
13321332impl < ' cx , ' gcx , ' tcx > MirBorrowckCtxt < ' cx , ' gcx , ' tcx > {
13331333
1334- /// Adds a suggestion when a closure is invoked twice with a moved variable.
1334+ /// Adds a suggestion when a closure is invoked twice with a moved variable or when a closure
1335+ /// is moved after being invoked.
13351336 ///
13361337 /// ```text
13371338 /// note: closure cannot be invoked more than once because it moves the variable `dict` out of
@@ -1341,30 +1342,18 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
13411342 /// LL | for (key, value) in dict {
13421343 /// | ^^^^
13431344 /// ```
1344- pub ( super ) fn add_closure_invoked_twice_with_moved_variable_suggestion (
1345+ pub ( super ) fn add_moved_or_invoked_closure_note (
13451346 & self ,
13461347 location : Location ,
13471348 place : & Place < ' tcx > ,
13481349 diag : & mut DiagnosticBuilder < ' _ > ,
13491350 ) {
1351+ debug ! ( "add_moved_or_invoked_closure_note: location={:?} place={:?}" , location, place) ;
13501352 let mut target = place. local ( ) ;
1351- debug ! (
1352- "add_closure_invoked_twice_with_moved_variable_suggestion: location={:?} place={:?} \
1353- target={:?}",
1354- location, place, target,
1355- ) ;
13561353 for stmt in & self . mir [ location. block ] . statements [ location. statement_index ..] {
1357- debug ! (
1358- "add_closure_invoked_twice_with_moved_variable_suggestion: stmt={:?} \
1359- target={:?}",
1360- stmt, target,
1361- ) ;
1354+ debug ! ( "add_moved_or_invoked_closure_note: stmt={:?} target={:?}" , stmt, target) ;
13621355 if let StatementKind :: Assign ( into, box Rvalue :: Use ( from) ) = & stmt. kind {
1363- debug ! (
1364- "add_closure_invoked_twice_with_moved_variable_suggestion: into={:?} \
1365- from={:?}",
1366- into, from,
1367- ) ;
1356+ debug ! ( "add_fnonce_closure_note: into={:?} from={:?}" , into, from) ;
13681357 match from {
13691358 Operand :: Copy ( ref place) |
13701359 Operand :: Move ( ref place) if target == place. local ( ) =>
@@ -1374,12 +1363,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
13741363 }
13751364 }
13761365
1377-
1366+ // Check if we are attempting to call a closure after it has been invoked.
13781367 let terminator = self . mir [ location. block ] . terminator ( ) ;
1379- debug ! (
1380- "add_closure_invoked_twice_with_moved_variable_suggestion: terminator={:?}" ,
1381- terminator,
1382- ) ;
1368+ debug ! ( "add_moved_or_invoked_closure_note: terminator={:?}" , terminator) ;
13831369 if let TerminatorKind :: Call {
13841370 func : Operand :: Constant ( box Constant {
13851371 literal : ty:: Const { ty : & ty:: TyS { sty : ty:: TyKind :: FnDef ( id, _) , .. } , .. } ,
@@ -1388,41 +1374,59 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
13881374 args,
13891375 ..
13901376 } = & terminator. kind {
1391- debug ! ( "add_closure_invoked_twice_with_moved_variable_suggestion : id={:?}" , id) ;
1377+ debug ! ( "add_moved_or_invoked_closure_note : id={:?}" , id) ;
13921378 if self . infcx . tcx . parent ( id) == self . infcx . tcx . lang_items ( ) . fn_once_trait ( ) {
13931379 let closure = match args. first ( ) {
13941380 Some ( Operand :: Copy ( ref place) ) |
13951381 Some ( Operand :: Move ( ref place) ) if target == place. local ( ) =>
13961382 place. local ( ) . unwrap ( ) ,
13971383 _ => return ,
13981384 } ;
1399- debug ! (
1400- "add_closure_invoked_twice_with_moved_variable_suggestion: closure={:?}" ,
1401- closure,
1402- ) ;
14031385
1404- if let ty:: TyKind :: Closure ( did, _substs) = self . mir . local_decls [ closure] . ty . sty {
1405- let node_id = match self . infcx . tcx . hir ( ) . as_local_node_id ( did) {
1406- Some ( node_id) => node_id,
1407- _ => return ,
1408- } ;
1386+ debug ! ( "add_moved_or_invoked_closure_note: closure={:?}" , closure) ;
1387+ if let ty:: TyKind :: Closure ( did, _) = self . mir . local_decls [ closure] . ty . sty {
1388+ let node_id = self . infcx . tcx . hir ( ) . as_local_node_id ( did) . unwrap ( ) ;
14091389 let hir_id = self . infcx . tcx . hir ( ) . node_to_hir_id ( node_id) ;
14101390
1411- if let Some ( (
1412- span, name
1413- ) ) = self . infcx . tcx . typeck_tables_of ( did) . closure_kind_origins ( ) . get ( hir_id) {
1391+ if let Some ( ( span, name) ) = self . infcx . tcx . typeck_tables_of ( did)
1392+ . closure_kind_origins ( )
1393+ . get ( hir_id)
1394+ {
14141395 diag. span_note (
14151396 * span,
14161397 & format ! (
1417- "closure cannot be invoked more than once because it \
1418- moves the variable `{}` out of its environment",
1419- name,
1398+ "closure cannot be invoked more than once because it moves the \
1399+ variable `{}` out of its environment",
1400+ name,
14201401 ) ,
14211402 ) ;
1403+ return ;
14221404 }
14231405 }
14241406 }
14251407 }
1408+
1409+ // Check if we are just moving a closure after it has been invoked.
1410+ if let Some ( target) = target {
1411+ if let ty:: TyKind :: Closure ( did, _) = self . mir . local_decls [ target] . ty . sty {
1412+ let node_id = self . infcx . tcx . hir ( ) . as_local_node_id ( did) . unwrap ( ) ;
1413+ let hir_id = self . infcx . tcx . hir ( ) . node_to_hir_id ( node_id) ;
1414+
1415+ if let Some ( ( span, name) ) = self . infcx . tcx . typeck_tables_of ( did)
1416+ . closure_kind_origins ( )
1417+ . get ( hir_id)
1418+ {
1419+ diag. span_note (
1420+ * span,
1421+ & format ! (
1422+ "closure cannot be moved more than once as it is not `Copy` due to \
1423+ moving the variable `{}` out of its environment",
1424+ name
1425+ ) ,
1426+ ) ;
1427+ }
1428+ }
1429+ }
14261430 }
14271431
14281432 /// End-user visible description of `place` if one can be found. If the
0 commit comments