@@ -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,
@@ -1329,7 +1329,8 @@ enum StorageDeadOrDrop<'tcx> {
13291329
13301330impl < ' cx , ' gcx , ' tcx > MirBorrowckCtxt < ' cx , ' gcx , ' tcx > {
13311331
1332- /// Adds a suggestion when a closure is invoked twice with a moved variable.
1332+ /// Adds a suggestion when a closure is invoked twice with a moved variable or when a closure
1333+ /// is moved after being invoked.
13331334 ///
13341335 /// ```text
13351336 /// note: closure cannot be invoked more than once because it moves the variable `dict` out of
@@ -1339,30 +1340,18 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
13391340 /// LL | for (key, value) in dict {
13401341 /// | ^^^^
13411342 /// ```
1342- pub ( super ) fn add_closure_invoked_twice_with_moved_variable_suggestion (
1343+ pub ( super ) fn add_moved_or_invoked_closure_note (
13431344 & self ,
13441345 location : Location ,
13451346 place : & Place < ' tcx > ,
13461347 diag : & mut DiagnosticBuilder < ' _ > ,
13471348 ) {
1349+ debug ! ( "add_moved_or_invoked_closure_note: location={:?} place={:?}" , location, place) ;
13481350 let mut target = place. local ( ) ;
1349- debug ! (
1350- "add_closure_invoked_twice_with_moved_variable_suggestion: location={:?} place={:?} \
1351- target={:?}",
1352- location, place, target,
1353- ) ;
13541351 for stmt in & self . mir [ location. block ] . statements [ location. statement_index ..] {
1355- debug ! (
1356- "add_closure_invoked_twice_with_moved_variable_suggestion: stmt={:?} \
1357- target={:?}",
1358- stmt, target,
1359- ) ;
1352+ debug ! ( "add_moved_or_invoked_closure_note: stmt={:?} target={:?}" , stmt, target) ;
13601353 if let StatementKind :: Assign ( into, box Rvalue :: Use ( from) ) = & stmt. kind {
1361- debug ! (
1362- "add_closure_invoked_twice_with_moved_variable_suggestion: into={:?} \
1363- from={:?}",
1364- into, from,
1365- ) ;
1354+ debug ! ( "add_fnonce_closure_note: into={:?} from={:?}" , into, from) ;
13661355 match from {
13671356 Operand :: Copy ( ref place) |
13681357 Operand :: Move ( ref place) if target == place. local ( ) =>
@@ -1372,12 +1361,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
13721361 }
13731362 }
13741363
1375-
1364+ // Check if we are attempting to call a closure after it has been invoked.
13761365 let terminator = self . mir [ location. block ] . terminator ( ) ;
1377- debug ! (
1378- "add_closure_invoked_twice_with_moved_variable_suggestion: terminator={:?}" ,
1379- terminator,
1380- ) ;
1366+ debug ! ( "add_moved_or_invoked_closure_note: terminator={:?}" , terminator) ;
13811367 if let TerminatorKind :: Call {
13821368 func : Operand :: Constant ( box Constant {
13831369 literal : ty:: LazyConst :: Evaluated ( ty:: Const {
@@ -1389,41 +1375,59 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
13891375 args,
13901376 ..
13911377 } = & terminator. kind {
1392- debug ! ( "add_closure_invoked_twice_with_moved_variable_suggestion : id={:?}" , id) ;
1378+ debug ! ( "add_moved_or_invoked_closure_note : id={:?}" , id) ;
13931379 if self . infcx . tcx . parent ( id) == self . infcx . tcx . lang_items ( ) . fn_once_trait ( ) {
13941380 let closure = match args. first ( ) {
13951381 Some ( Operand :: Copy ( ref place) ) |
13961382 Some ( Operand :: Move ( ref place) ) if target == place. local ( ) =>
13971383 place. local ( ) . unwrap ( ) ,
13981384 _ => return ,
13991385 } ;
1400- debug ! (
1401- "add_closure_invoked_twice_with_moved_variable_suggestion: closure={:?}" ,
1402- closure,
1403- ) ;
14041386
1405- if let ty:: TyKind :: Closure ( did, _substs) = self . mir . local_decls [ closure] . ty . sty {
1406- let node_id = match self . infcx . tcx . hir ( ) . as_local_node_id ( did) {
1407- Some ( node_id) => node_id,
1408- _ => return ,
1409- } ;
1387+ debug ! ( "add_moved_or_invoked_closure_note: closure={:?}" , closure) ;
1388+ if let ty:: TyKind :: Closure ( did, _) = self . mir . local_decls [ closure] . ty . sty {
1389+ let node_id = self . infcx . tcx . hir ( ) . as_local_node_id ( did) . unwrap ( ) ;
14101390 let hir_id = self . infcx . tcx . hir ( ) . node_to_hir_id ( node_id) ;
14111391
1412- if let Some ( (
1413- span, name
1414- ) ) = self . infcx . tcx . typeck_tables_of ( did) . closure_kind_origins ( ) . get ( hir_id) {
1392+ if let Some ( ( span, name) ) = self . infcx . tcx . typeck_tables_of ( did)
1393+ . closure_kind_origins ( )
1394+ . get ( hir_id)
1395+ {
14151396 diag. span_note (
14161397 * span,
14171398 & format ! (
1418- "closure cannot be invoked more than once because it \
1419- moves the variable `{}` out of its environment",
1420- name,
1399+ "closure cannot be invoked more than once because it moves the \
1400+ variable `{}` out of its environment",
1401+ name,
14211402 ) ,
14221403 ) ;
1404+ return ;
14231405 }
14241406 }
14251407 }
14261408 }
1409+
1410+ // Check if we are just moving a closure after it has been invoked.
1411+ if let Some ( target) = target {
1412+ if let ty:: TyKind :: Closure ( did, _) = self . mir . local_decls [ target] . ty . sty {
1413+ let node_id = self . infcx . tcx . hir ( ) . as_local_node_id ( did) . unwrap ( ) ;
1414+ let hir_id = self . infcx . tcx . hir ( ) . node_to_hir_id ( node_id) ;
1415+
1416+ if let Some ( ( span, name) ) = self . infcx . tcx . typeck_tables_of ( did)
1417+ . closure_kind_origins ( )
1418+ . get ( hir_id)
1419+ {
1420+ diag. span_note (
1421+ * span,
1422+ & format ! (
1423+ "closure cannot be moved more than once as it is not `Copy` due to \
1424+ moving the variable `{}` out of its environment",
1425+ name
1426+ ) ,
1427+ ) ;
1428+ }
1429+ }
1430+ }
14271431 }
14281432
14291433 /// End-user visible description of `place` if one can be found. If the
0 commit comments