@@ -183,24 +183,24 @@ enum State {
183183 } ,
184184 DerefedBorrow ( DerefedBorrow ) ,
185185 ExplicitDeref {
186- // Span and id of the top-level deref expression if the parent expression is a borrow.
187- deref_span_id : Option < ( Span , HirId ) > ,
186+ mutability : Option < Mutability > ,
188187 } ,
189188 ExplicitDerefField {
190189 name : Symbol ,
191190 } ,
192191 Reborrow {
193- deref_span : Span ,
194- deref_hir_id : HirId ,
192+ mutability : Mutability ,
193+ } ,
194+ Borrow {
195+ mutability : Mutability ,
195196 } ,
196- Borrow ,
197197}
198198
199199// A reference operation considered by this lint pass
200200enum RefOp {
201201 Method ( Mutability ) ,
202202 Deref ,
203- AddrOf ,
203+ AddrOf ( Mutability ) ,
204204}
205205
206206struct RefPat {
@@ -263,7 +263,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
263263 ) ) ;
264264 } else if position. is_deref_stable ( ) {
265265 self . state = Some ( (
266- State :: ExplicitDeref { deref_span_id : None } ,
266+ State :: ExplicitDeref { mutability : None } ,
267267 StateData { span : expr. span , hir_id : expr. hir_id , position } ,
268268 ) ) ;
269269 }
@@ -289,7 +289,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
289289 } ,
290290 ) ) ;
291291 } ,
292- RefOp :: AddrOf => {
292+ RefOp :: AddrOf ( mutability ) => {
293293 // Find the number of times the borrow is auto-derefed.
294294 let mut iter = adjustments. iter ( ) ;
295295 let mut deref_count = 0usize ;
@@ -359,7 +359,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
359359 ) ) ;
360360 } else if position. is_deref_stable ( ) {
361361 self . state = Some ( (
362- State :: Borrow ,
362+ State :: Borrow { mutability } ,
363363 StateData {
364364 span : expr. span ,
365365 hir_id : expr. hir_id ,
@@ -395,7 +395,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
395395 data,
396396 ) ) ;
397397 } ,
398- ( Some ( ( State :: DerefedBorrow ( state) , data) ) , RefOp :: AddrOf ) if state. count != 0 => {
398+ ( Some ( ( State :: DerefedBorrow ( state) , data) ) , RefOp :: AddrOf ( _ ) ) if state. count != 0 => {
399399 self . state = Some ( (
400400 State :: DerefedBorrow ( DerefedBorrow {
401401 count : state. count - 1 ,
@@ -404,12 +404,12 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
404404 data,
405405 ) ) ;
406406 } ,
407- ( Some ( ( State :: DerefedBorrow ( state) , data) ) , RefOp :: AddrOf ) => {
407+ ( Some ( ( State :: DerefedBorrow ( state) , data) ) , RefOp :: AddrOf ( mutability ) ) => {
408408 let position = data. position ;
409409 report ( cx, expr, State :: DerefedBorrow ( state) , data) ;
410410 if position. is_deref_stable ( ) {
411411 self . state = Some ( (
412- State :: Borrow ,
412+ State :: Borrow { mutability } ,
413413 StateData {
414414 span : expr. span ,
415415 hir_id : expr. hir_id ,
@@ -430,43 +430,28 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
430430 ) ) ;
431431 } else if position. is_deref_stable ( ) {
432432 self . state = Some ( (
433- State :: ExplicitDeref { deref_span_id : None } ,
433+ State :: ExplicitDeref { mutability : None } ,
434434 StateData { span : expr. span , hir_id : expr. hir_id , position } ,
435435 ) ) ;
436436 }
437437 } ,
438438
439- ( Some ( ( State :: Borrow , data) ) , RefOp :: Deref ) => {
439+ ( Some ( ( State :: Borrow { mutability } , data) ) , RefOp :: Deref ) => {
440440 if typeck. expr_ty ( sub_expr) . is_ref ( ) {
441- self . state = Some ( (
442- State :: Reborrow {
443- deref_span : expr. span ,
444- deref_hir_id : expr. hir_id ,
445- } ,
446- data,
447- ) ) ;
441+ self . state = Some ( ( State :: Reborrow { mutability } , data) ) ;
448442 } else {
449443 self . state = Some ( (
450444 State :: ExplicitDeref {
451- deref_span_id : Some ( ( expr . span , expr . hir_id ) ) ,
445+ mutability : Some ( mutability ) ,
452446 } ,
453447 data,
454448 ) ) ;
455449 }
456450 } ,
457- (
458- Some ( (
459- State :: Reborrow {
460- deref_span,
461- deref_hir_id,
462- } ,
463- data,
464- ) ) ,
465- RefOp :: Deref ,
466- ) => {
451+ ( Some ( ( State :: Reborrow { mutability } , data) ) , RefOp :: Deref ) => {
467452 self . state = Some ( (
468453 State :: ExplicitDeref {
469- deref_span_id : Some ( ( deref_span , deref_hir_id ) ) ,
454+ mutability : Some ( mutability ) ,
470455 } ,
471456 data,
472457 ) ) ;
@@ -573,7 +558,7 @@ fn try_parse_ref_op<'tcx>(
573558 ExprKind :: Unary ( UnOp :: Deref , sub_expr) if !typeck. expr_ty ( sub_expr) . is_unsafe_ptr ( ) => {
574559 return Some ( ( RefOp :: Deref , sub_expr) ) ;
575560 } ,
576- ExprKind :: AddrOf ( BorrowKind :: Ref , _ , sub_expr) => return Some ( ( RefOp :: AddrOf , sub_expr) ) ,
561+ ExprKind :: AddrOf ( BorrowKind :: Ref , mutability , sub_expr) => return Some ( ( RefOp :: AddrOf ( mutability ) , sub_expr) ) ,
577562 _ => return None ,
578563 } ;
579564 if tcx. is_diagnostic_item ( sym:: deref_method, def_id) {
@@ -1074,7 +1059,7 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data
10741059 diag. span_suggestion ( data. span , "change this to" , sugg, app) ;
10751060 } ) ;
10761061 } ,
1077- State :: ExplicitDeref { deref_span_id } => {
1062+ State :: ExplicitDeref { mutability } => {
10781063 if matches ! (
10791064 expr. kind,
10801065 ExprKind :: Block ( ..)
@@ -1088,29 +1073,33 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data
10881073 return ;
10891074 }
10901075
1091- let ( span , hir_id , precedence) = if let Some ( ( span , hir_id ) ) = deref_span_id
1076+ let ( prefix , precedence) = if let Some ( mutability ) = mutability
10921077 && !cx. typeck_results ( ) . expr_ty ( expr) . is_ref ( )
10931078 {
1094- ( span, hir_id, PREC_PREFIX )
1079+ let prefix = match mutability {
1080+ Mutability :: Not => "&" ,
1081+ Mutability :: Mut => "&mut " ,
1082+ } ;
1083+ ( prefix, 0 )
10951084 } else {
1096- ( data . span , data . hir_id , data. position . precedence ( ) )
1085+ ( "" , data. position . precedence ( ) )
10971086 } ;
10981087 span_lint_hir_and_then (
10991088 cx,
11001089 EXPLICIT_AUTO_DEREF ,
1101- hir_id,
1102- span,
1090+ data . hir_id ,
1091+ data . span ,
11031092 "deref which would be done by auto-deref" ,
11041093 |diag| {
11051094 let mut app = Applicability :: MachineApplicable ;
1106- let ( snip, snip_is_macro) = snippet_with_context ( cx, expr. span , span. ctxt ( ) , ".." , & mut app) ;
1095+ let ( snip, snip_is_macro) = snippet_with_context ( cx, expr. span , data . span . ctxt ( ) , ".." , & mut app) ;
11071096 let sugg =
11081097 if !snip_is_macro && expr. precedence ( ) . order ( ) < precedence && !has_enclosing_paren ( & snip) {
1109- format ! ( "({})" , snip)
1098+ format ! ( "{} ({})" , prefix , snip)
11101099 } else {
1111- snip . into ( )
1100+ format ! ( "{}{}" , prefix , snip )
11121101 } ;
1113- diag. span_suggestion ( span, "try this" , sugg, app) ;
1102+ diag. span_suggestion ( data . span , "try this" , sugg, app) ;
11141103 } ,
11151104 ) ;
11161105 } ,
@@ -1141,7 +1130,7 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data
11411130 } ,
11421131 ) ;
11431132 } ,
1144- State :: Borrow | State :: Reborrow { .. } => ( ) ,
1133+ State :: Borrow { .. } | State :: Reborrow { .. } => ( ) ,
11451134 }
11461135}
11471136
0 commit comments