1
- use rustc:: mir:: { self , ClearCrossCrate , Local , LocalInfo , Location , ReadOnlyBodyAndCache } ;
1
+ use rustc:: mir:: { self , ClearCrossCrate , Local , LocalInfo , Location } ;
2
2
use rustc:: mir:: { Mutability , Place , PlaceRef , ProjectionElem } ;
3
3
use rustc:: ty:: { self , Ty , TyCtxt } ;
4
4
use rustc_hir as hir;
5
5
use rustc_hir:: Node ;
6
6
use rustc_index:: vec:: Idx ;
7
+ use rustc_span:: source_map:: DesugaringKind ;
7
8
use rustc_span:: symbol:: kw;
8
9
use rustc_span:: Span ;
9
10
@@ -338,24 +339,53 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
338
339
339
340
match self . local_names [ local] {
340
341
Some ( name) if !local_decl. from_compiler_desugaring ( ) => {
341
- let suggestion = match local_decl. local_info {
342
+ let label = match local_decl. local_info {
342
343
LocalInfo :: User ( ClearCrossCrate :: Set (
343
344
mir:: BindingForm :: ImplicitSelf ( _) ,
344
- ) ) => Some ( suggest_ampmut_self ( self . infcx . tcx , local_decl) ) ,
345
+ ) ) => {
346
+ let ( span, suggestion) =
347
+ suggest_ampmut_self ( self . infcx . tcx , local_decl) ;
348
+ Some ( ( true , span, suggestion) )
349
+ }
345
350
346
351
LocalInfo :: User ( ClearCrossCrate :: Set ( mir:: BindingForm :: Var (
347
352
mir:: VarBindingForm {
348
353
binding_mode : ty:: BindingMode :: BindByValue ( _) ,
349
354
opt_ty_info,
350
355
..
351
356
} ,
352
- ) ) ) => Some ( suggest_ampmut (
353
- self . infcx . tcx ,
354
- self . body ,
355
- local,
356
- local_decl,
357
- opt_ty_info,
358
- ) ) ,
357
+ ) ) ) => {
358
+ // check if the RHS is from desugaring
359
+ let locations = self . body . find_assignments ( local) ;
360
+ let opt_assignment_rhs_span = locations
361
+ . first ( )
362
+ . map ( |& location| self . body . source_info ( location) . span ) ;
363
+ let opt_desugaring_kind =
364
+ opt_assignment_rhs_span. and_then ( |span| span. desugaring_kind ( ) ) ;
365
+ match opt_desugaring_kind {
366
+ // on for loops, RHS points to the iterator part
367
+ Some ( DesugaringKind :: ForLoop ) => Some ( (
368
+ false ,
369
+ opt_assignment_rhs_span. unwrap ( ) ,
370
+ format ! (
371
+ "this iterator yields `{SIGIL}` {DESC}s" ,
372
+ SIGIL = pointer_sigil,
373
+ DESC = pointer_desc
374
+ ) ,
375
+ ) ) ,
376
+ // don't create labels for compiler-generated spans
377
+ Some ( _) => None ,
378
+ None => {
379
+ let ( span, suggestion) = suggest_ampmut (
380
+ self . infcx . tcx ,
381
+ local_decl,
382
+ opt_assignment_rhs_span,
383
+ opt_ty_info,
384
+ ) ;
385
+ Some ( ( true , span, suggestion) )
386
+ }
387
+ }
388
+ }
359
389
360
390
LocalInfo :: User ( ClearCrossCrate :: Set ( mir:: BindingForm :: Var (
361
391
mir:: VarBindingForm {
@@ -365,7 +395,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
365
395
) ) ) => {
366
396
let pattern_span = local_decl. source_info . span ;
367
397
suggest_ref_mut ( self . infcx . tcx , pattern_span)
368
- . map ( |replacement| ( pattern_span, replacement) )
398
+ . map ( |replacement| ( true , pattern_span, replacement) )
369
399
}
370
400
371
401
LocalInfo :: User ( ClearCrossCrate :: Clear ) => {
@@ -375,13 +405,22 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
375
405
_ => unreachable ! ( ) ,
376
406
} ;
377
407
378
- if let Some ( ( err_help_span, suggested_code) ) = suggestion {
379
- err. span_suggestion (
380
- err_help_span,
381
- & format ! ( "consider changing this to be a mutable {}" , pointer_desc) ,
382
- suggested_code,
383
- Applicability :: MachineApplicable ,
384
- ) ;
408
+ match label {
409
+ Some ( ( true , err_help_span, suggested_code) ) => {
410
+ err. span_suggestion (
411
+ err_help_span,
412
+ & format ! (
413
+ "consider changing this to be a mutable {}" ,
414
+ pointer_desc
415
+ ) ,
416
+ suggested_code,
417
+ Applicability :: MachineApplicable ,
418
+ ) ;
419
+ }
420
+ Some ( ( false , err_label_span, message) ) => {
421
+ err. span_label ( err_label_span, & message) ;
422
+ }
423
+ None => { }
385
424
}
386
425
err. span_label (
387
426
span,
@@ -581,14 +620,11 @@ fn suggest_ampmut_self<'tcx>(
581
620
// by trying (3.), then (2.) and finally falling back on (1.).
582
621
fn suggest_ampmut < ' tcx > (
583
622
tcx : TyCtxt < ' tcx > ,
584
- body : ReadOnlyBodyAndCache < ' _ , ' tcx > ,
585
- local : Local ,
586
623
local_decl : & mir:: LocalDecl < ' tcx > ,
624
+ opt_assignment_rhs_span : Option < Span > ,
587
625
opt_ty_info : Option < Span > ,
588
626
) -> ( Span , String ) {
589
- let locations = body. find_assignments ( local) ;
590
- if !locations. is_empty ( ) {
591
- let assignment_rhs_span = body. source_info ( locations[ 0 ] ) . span ;
627
+ if let Some ( assignment_rhs_span) = opt_assignment_rhs_span {
592
628
if let Ok ( src) = tcx. sess . source_map ( ) . span_to_snippet ( assignment_rhs_span) {
593
629
if let ( true , Some ( ws_pos) ) =
594
630
( src. starts_with ( "&'" ) , src. find ( |c : char | -> bool { c. is_whitespace ( ) } ) )
0 commit comments