@@ -34,6 +34,7 @@ use super::FnCtxt;
34
34
35
35
use crate :: expr_use_visitor as euv;
36
36
use rustc_data_structures:: fx:: FxIndexMap ;
37
+ use rustc_errors:: Applicability ;
37
38
use rustc_hir as hir;
38
39
use rustc_hir:: def_id:: DefId ;
39
40
use rustc_hir:: def_id:: LocalDefId ;
@@ -91,7 +92,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InferBorrowKindVisitor<'a, 'tcx> {
91
92
if let hir:: ExprKind :: Closure ( cc, _, body_id, _, _) = expr. kind {
92
93
let body = self . fcx . tcx . hir ( ) . body ( body_id) ;
93
94
self . visit_body ( body) ;
94
- self . fcx . analyze_closure ( expr. hir_id , expr. span , body, cc) ;
95
+ self . fcx . analyze_closure ( expr. hir_id , expr. span , body_id , body, cc) ;
95
96
}
96
97
97
98
intravisit:: walk_expr ( self , expr) ;
@@ -104,6 +105,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
104
105
& self ,
105
106
closure_hir_id : hir:: HirId ,
106
107
span : Span ,
108
+ body_id : hir:: BodyId ,
107
109
body : & ' tcx hir:: Body < ' tcx > ,
108
110
capture_clause : hir:: CaptureBy ,
109
111
) {
@@ -167,7 +169,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
167
169
168
170
let closure_hir_id = self . tcx . hir ( ) . local_def_id_to_hir_id ( local_def_id) ;
169
171
if should_do_migration_analysis ( self . tcx , closure_hir_id) {
170
- self . perform_2229_migration_anaysis ( closure_def_id, capture_clause, span) ;
172
+ self . perform_2229_migration_anaysis ( closure_def_id, body_id , capture_clause, span) ;
171
173
}
172
174
173
175
// We now fake capture information for all variables that are mentioned within the closure
@@ -465,6 +467,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
465
467
fn perform_2229_migration_anaysis (
466
468
& self ,
467
469
closure_def_id : DefId ,
470
+ body_id : hir:: BodyId ,
468
471
capture_clause : hir:: CaptureBy ,
469
472
span : Span ,
470
473
) {
@@ -488,7 +491,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
488
491
let mut diagnostics_builder = lint. build (
489
492
"drop order affected for closure because of `capture_disjoint_fields`" ,
490
493
) ;
491
- diagnostics_builder. note ( & migrations_text) ;
494
+ let closure_body_span = self . tcx . hir ( ) . span ( body_id. hir_id ) ;
495
+ let ( sugg, app) =
496
+ match self . tcx . sess . source_map ( ) . span_to_snippet ( closure_body_span) {
497
+ Ok ( s) => (
498
+ format ! ( "{{ {} {} }}" , migrations_text, s) ,
499
+ Applicability :: MachineApplicable ,
500
+ ) ,
501
+ Err ( _) => ( migrations_text. clone ( ) , Applicability :: HasPlaceholders ) ,
502
+ } ;
503
+
504
+ diagnostics_builder. span_suggestion (
505
+ closure_body_span,
506
+ & format ! ( "You can restore original behavior adding `{}` to the closure/generator" , migrations_text) ,
507
+ sugg,
508
+ app,
509
+ ) ;
492
510
diagnostics_builder. emit ( ) ;
493
511
} ,
494
512
) ;
@@ -1517,10 +1535,14 @@ fn should_do_migration_analysis(tcx: TyCtxt<'_>, closure_id: hir::HirId) -> bool
1517
1535
1518
1536
fn migration_suggestion_for_2229 ( tcx : TyCtxt < ' _ > , need_migrations : & Vec < hir:: HirId > ) -> String {
1519
1537
let need_migrations_strings =
1520
- need_migrations. iter ( ) . map ( |v| format ! ( "{}" , var_name( tcx, * v) ) ) . collect :: < Vec < _ > > ( ) ;
1538
+ need_migrations. iter ( ) . map ( |v| format ! ( "& {}" , var_name( tcx, * v) ) ) . collect :: < Vec < _ > > ( ) ;
1521
1539
let migrations_list_concat = need_migrations_strings. join ( ", " ) ;
1522
1540
1523
- format ! ( "drop(&({}));" , migrations_list_concat)
1541
+ if 1 == need_migrations. len ( ) {
1542
+ format ! ( "let _ = {};" , migrations_list_concat)
1543
+ } else {
1544
+ format ! ( "let _ = ({});" , migrations_list_concat)
1545
+ }
1524
1546
}
1525
1547
1526
1548
/// Helper function to determine if we need to escalate CaptureKind from
0 commit comments