@@ -4,7 +4,7 @@ use rustc_middle::ty;
44use rustc_mir_dataflow:: move_paths:: {
55 IllegalMoveOrigin , IllegalMoveOriginKind , LookupResult , MoveError , MovePathIndex ,
66} ;
7- use rustc_span:: Span ;
7+ use rustc_span:: { BytePos , Span } ;
88
99use crate :: diagnostics:: { DescribePlaceOpt , UseSpans } ;
1010use crate :: prefixes:: PrefixSet ;
@@ -148,7 +148,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
148148 match_span : Span ,
149149 statement_span : Span ,
150150 ) {
151- debug ! ( "append_binding_error(match_place={:?}, match_span={:?})" , match_place , match_span ) ;
151+ debug ! ( ?match_place , ?match_span , "append_binding_error" ) ;
152152
153153 let from_simple_let = match_place. is_none ( ) ;
154154 let match_place = match_place. unwrap_or ( move_from) ;
@@ -160,7 +160,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
160160 if let GroupedMoveError :: MovesFromPlace { span, binds_to, .. } = ge
161161 && match_span == * span
162162 {
163- debug ! ( "appending local({:?}) to list" , bind_to ) ;
163+ debug ! ( "appending local({bind_to :?}) to list" ) ;
164164 if !binds_to. is_empty ( ) {
165165 binds_to. push ( bind_to) ;
166166 }
@@ -198,7 +198,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
198198 } = ge
199199 {
200200 if match_span == * span && mpi == * other_mpi {
201- debug ! ( "appending local({:?}) to list" , bind_to ) ;
201+ debug ! ( "appending local({bind_to :?}) to list" ) ;
202202 binds_to. push ( bind_to) ;
203203 return ;
204204 }
@@ -410,15 +410,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
410410 fn add_move_hints ( & self , error : GroupedMoveError < ' tcx > , err : & mut Diagnostic , span : Span ) {
411411 match error {
412412 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) ;
422414 if binds_to. is_empty ( ) {
423415 let place_ty = move_from. ty ( self . body , self . infcx . tcx ) . ty ;
424416 let place_desc = match self . describe_place ( move_from. as_ref ( ) ) {
@@ -461,39 +453,75 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
461453 }
462454 }
463455
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+
464477 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 ( ) ;
466479 for local in binds_to {
467480 let bind_to = & self . body . local_decls [ * local] ;
468481 if let Some ( box LocalInfo :: User ( ClearCrossCrate :: Set ( BindingForm :: Var (
469482 VarBindingForm { pat_span, .. } ,
470483 ) ) ) ) = bind_to. local_info
471484 {
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)
473498 {
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+ ) ) ;
486519 }
487520 }
488521 suggestions. sort_unstable_by_key ( |& ( span, _, _) | span) ;
489522 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 ) ;
497525 }
498526 }
499527
@@ -521,8 +549,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
521549
522550 if binds_to. len ( ) > 1 {
523551 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",
526554 ) ;
527555 }
528556 }
0 commit comments