1- use rustc:: mir:: { self , ClearCrossCrate , Local , LocalInfo , Location , ReadOnlyBodyAndCache } ;
1+ use rustc:: mir:: { self , ClearCrossCrate , Local , LocalInfo , Location } ;
22use rustc:: mir:: { Mutability , Place , PlaceRef , ProjectionElem } ;
33use rustc:: ty:: { self , Ty , TyCtxt } ;
44use rustc_hir as hir;
55use rustc_hir:: Node ;
66use rustc_index:: vec:: Idx ;
7+ use rustc_span:: source_map:: DesugaringKind ;
78use rustc_span:: symbol:: kw;
89use rustc_span:: Span ;
910
@@ -338,24 +339,53 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
338339
339340 match self . local_names [ local] {
340341 Some ( name) if !local_decl. from_compiler_desugaring ( ) => {
341- let suggestion = match local_decl. local_info {
342+ let label = match local_decl. local_info {
342343 LocalInfo :: User ( ClearCrossCrate :: Set (
343344 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+ }
345350
346351 LocalInfo :: User ( ClearCrossCrate :: Set ( mir:: BindingForm :: Var (
347352 mir:: VarBindingForm {
348353 binding_mode : ty:: BindingMode :: BindByValue ( _) ,
349354 opt_ty_info,
350355 ..
351356 } ,
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+ }
359389
360390 LocalInfo :: User ( ClearCrossCrate :: Set ( mir:: BindingForm :: Var (
361391 mir:: VarBindingForm {
@@ -365,7 +395,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
365395 ) ) ) => {
366396 let pattern_span = local_decl. source_info . span ;
367397 suggest_ref_mut ( self . infcx . tcx , pattern_span)
368- . map ( |replacement| ( pattern_span, replacement) )
398+ . map ( |replacement| ( true , pattern_span, replacement) )
369399 }
370400
371401 LocalInfo :: User ( ClearCrossCrate :: Clear ) => {
@@ -375,13 +405,22 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
375405 _ => unreachable ! ( ) ,
376406 } ;
377407
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 => { }
385424 }
386425 err. span_label (
387426 span,
@@ -581,14 +620,11 @@ fn suggest_ampmut_self<'tcx>(
581620// by trying (3.), then (2.) and finally falling back on (1.).
582621fn suggest_ampmut < ' tcx > (
583622 tcx : TyCtxt < ' tcx > ,
584- body : ReadOnlyBodyAndCache < ' _ , ' tcx > ,
585- local : Local ,
586623 local_decl : & mir:: LocalDecl < ' tcx > ,
624+ opt_assignment_rhs_span : Option < Span > ,
587625 opt_ty_info : Option < Span > ,
588626) -> ( 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 {
592628 if let Ok ( src) = tcx. sess . source_map ( ) . span_to_snippet ( assignment_rhs_span) {
593629 if let ( true , Some ( ws_pos) ) =
594630 ( src. starts_with ( "&'" ) , src. find ( |c : char | -> bool { c. is_whitespace ( ) } ) )
0 commit comments