@@ -4,7 +4,7 @@ use rustc_middle::ty;
4
4
use rustc_mir_dataflow:: move_paths:: {
5
5
IllegalMoveOrigin , IllegalMoveOriginKind , LookupResult , MoveError , MovePathIndex ,
6
6
} ;
7
- use rustc_span:: Span ;
7
+ use rustc_span:: { BytePos , Span } ;
8
8
9
9
use crate :: diagnostics:: { DescribePlaceOpt , UseSpans } ;
10
10
use crate :: prefixes:: PrefixSet ;
@@ -148,7 +148,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
148
148
match_span : Span ,
149
149
statement_span : Span ,
150
150
) {
151
- debug ! ( "append_binding_error(match_place={:?}, match_span={:?})" , match_place , match_span ) ;
151
+ debug ! ( ?match_place , ?match_span , "append_binding_error" ) ;
152
152
153
153
let from_simple_let = match_place. is_none ( ) ;
154
154
let match_place = match_place. unwrap_or ( move_from) ;
@@ -160,7 +160,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
160
160
if let GroupedMoveError :: MovesFromPlace { span, binds_to, .. } = ge
161
161
&& match_span == * span
162
162
{
163
- debug ! ( "appending local({:?}) to list" , bind_to ) ;
163
+ debug ! ( "appending local({bind_to :?}) to list" ) ;
164
164
if !binds_to. is_empty ( ) {
165
165
binds_to. push ( bind_to) ;
166
166
}
@@ -198,7 +198,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
198
198
} = ge
199
199
{
200
200
if match_span == * span && mpi == * other_mpi {
201
- debug ! ( "appending local({:?}) to list" , bind_to ) ;
201
+ debug ! ( "appending local({bind_to :?}) to list" ) ;
202
202
binds_to. push ( bind_to) ;
203
203
return ;
204
204
}
@@ -410,15 +410,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
410
410
fn add_move_hints ( & self , error : GroupedMoveError < ' tcx > , err : & mut Diagnostic , span : Span ) {
411
411
match error {
412
412
GroupedMoveError :: MovesFromPlace { mut binds_to, move_from, .. } => {
413
- if let Ok ( snippet) = self . infcx . tcx . sess . source_map ( ) . span_to_snippet ( span) {
414
- err. span_suggestion (
415
- span,
416
- "consider borrowing here" ,
417
- format ! ( "&{snippet}" ) ,
418
- Applicability :: Unspecified ,
419
- ) ;
420
- }
421
-
413
+ self . add_borrow_suggestions ( err, span) ;
422
414
if binds_to. is_empty ( ) {
423
415
let place_ty = move_from. ty ( self . body , self . infcx . tcx ) . ty ;
424
416
let place_desc = match self . describe_place ( move_from. as_ref ( ) ) {
@@ -461,39 +453,75 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
461
453
}
462
454
}
463
455
456
+ fn add_borrow_suggestions ( & self , err : & mut Diagnostic , span : Span ) {
457
+ match self . infcx . tcx . sess . source_map ( ) . span_to_snippet ( span) {
458
+ Ok ( snippet) if snippet. starts_with ( '*' ) => {
459
+ err. span_suggestion_verbose (
460
+ span. with_hi ( span. lo ( ) + BytePos ( 1 ) ) ,
461
+ "consider removing the dereference here" ,
462
+ String :: new ( ) ,
463
+ Applicability :: MaybeIncorrect ,
464
+ ) ;
465
+ }
466
+ _ => {
467
+ err. span_suggestion_verbose (
468
+ span. shrink_to_lo ( ) ,
469
+ "consider borrowing here" ,
470
+ "&" . to_string ( ) ,
471
+ Applicability :: MaybeIncorrect ,
472
+ ) ;
473
+ }
474
+ }
475
+ }
476
+
464
477
fn add_move_error_suggestions ( & self , err : & mut Diagnostic , binds_to : & [ Local ] ) {
465
- let mut suggestions: Vec < ( Span , & str , String ) > = Vec :: new ( ) ;
478
+ let mut suggestions: Vec < ( Span , String , String ) > = Vec :: new ( ) ;
466
479
for local in binds_to {
467
480
let bind_to = & self . body . local_decls [ * local] ;
468
481
if let Some ( box LocalInfo :: User ( ClearCrossCrate :: Set ( BindingForm :: Var (
469
482
VarBindingForm { pat_span, .. } ,
470
483
) ) ) ) = bind_to. local_info
471
484
{
472
- if let Ok ( pat_snippet) = self . infcx . tcx . sess . source_map ( ) . span_to_snippet ( pat_span)
485
+ let Ok ( pat_snippet) =
486
+ self . infcx . tcx . sess . source_map ( ) . span_to_snippet ( pat_span) else { continue ; } ;
487
+ let Some ( stripped) = pat_snippet. strip_prefix ( '&' ) else {
488
+ suggestions. push ( (
489
+ bind_to. source_info . span . shrink_to_lo ( ) ,
490
+ "consider borrowing the pattern binding" . to_string ( ) ,
491
+ "ref " . to_string ( ) ,
492
+ ) ) ;
493
+ continue ;
494
+ } ;
495
+ let inner_pat_snippet = stripped. trim_start ( ) ;
496
+ let ( pat_span, suggestion, to_remove) = if inner_pat_snippet. starts_with ( "mut" )
497
+ && inner_pat_snippet[ "mut" . len ( ) ..] . starts_with ( rustc_lexer:: is_whitespace)
473
498
{
474
- if let Some ( stripped) = pat_snippet. strip_prefix ( '&' ) {
475
- let pat_snippet = stripped. trim_start ( ) ;
476
- let ( suggestion, to_remove) = if pat_snippet. starts_with ( "mut" )
477
- && pat_snippet[ "mut" . len ( ) ..] . starts_with ( rustc_lexer:: is_whitespace)
478
- {
479
- ( pat_snippet[ "mut" . len ( ) ..] . trim_start ( ) , "&mut" )
480
- } else {
481
- ( pat_snippet, "&" )
482
- } ;
483
- suggestions. push ( ( pat_span, to_remove, suggestion. to_owned ( ) ) ) ;
484
- }
485
- }
499
+ let inner_pat_snippet = inner_pat_snippet[ "mut" . len ( ) ..] . trim_start ( ) ;
500
+ let pat_span = pat_span. with_hi (
501
+ pat_span. lo ( )
502
+ + BytePos ( ( pat_snippet. len ( ) - inner_pat_snippet. len ( ) ) as u32 ) ,
503
+ ) ;
504
+ ( pat_span, String :: new ( ) , "mutable borrow" )
505
+ } else {
506
+ let pat_span = pat_span. with_hi (
507
+ pat_span. lo ( )
508
+ + BytePos (
509
+ ( pat_snippet. len ( ) - inner_pat_snippet. trim_start ( ) . len ( ) ) as u32 ,
510
+ ) ,
511
+ ) ;
512
+ ( pat_span, String :: new ( ) , "borrow" )
513
+ } ;
514
+ suggestions. push ( (
515
+ pat_span,
516
+ format ! ( "consider removing the {to_remove}" ) ,
517
+ suggestion. to_string ( ) ,
518
+ ) ) ;
486
519
}
487
520
}
488
521
suggestions. sort_unstable_by_key ( |& ( span, _, _) | span) ;
489
522
suggestions. dedup_by_key ( |& mut ( span, _, _) | span) ;
490
- for ( span, to_remove, suggestion) in suggestions {
491
- err. span_suggestion (
492
- span,
493
- & format ! ( "consider removing the `{to_remove}`" ) ,
494
- suggestion,
495
- Applicability :: MachineApplicable ,
496
- ) ;
523
+ for ( span, msg, suggestion) in suggestions {
524
+ err. span_suggestion_verbose ( span, & msg, suggestion, Applicability :: MachineApplicable ) ;
497
525
}
498
526
}
499
527
@@ -521,8 +549,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
521
549
522
550
if binds_to. len ( ) > 1 {
523
551
err. note (
524
- "move occurs because these variables have types that \
525
- don't implement the `Copy` trait",
552
+ "move occurs because these variables have types that don't implement the `Copy` \
553
+ trait",
526
554
) ;
527
555
}
528
556
}
0 commit comments