@@ -163,6 +163,14 @@ struct StateData {
163
163
hir_id : HirId ,
164
164
}
165
165
166
+ struct DerefedBorrow {
167
+ count : usize ,
168
+ required_precedence : i8 ,
169
+ msg : & ' static str ,
170
+ stability : AutoDerefStability ,
171
+ position : Position ,
172
+ }
173
+
166
174
enum State {
167
175
// Any number of deref method calls.
168
176
DerefMethod {
@@ -172,11 +180,7 @@ enum State {
172
180
/// The required mutability
173
181
target_mut : Mutability ,
174
182
} ,
175
- DerefedBorrow {
176
- count : usize ,
177
- required_precedence : i8 ,
178
- msg : & ' static str ,
179
- } ,
183
+ DerefedBorrow ( DerefedBorrow ) ,
180
184
ExplicitDeref {
181
185
deref_span : Span ,
182
186
deref_hir_id : HirId ,
@@ -344,17 +348,16 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
344
348
345
349
if deref_count >= required_refs {
346
350
self . state = Some ( (
347
- State :: DerefedBorrow {
351
+ State :: DerefedBorrow ( DerefedBorrow {
348
352
// One of the required refs is for the current borrow expression, the remaining ones
349
353
// can't be removed without breaking the code. See earlier comment.
350
354
count : deref_count - required_refs,
351
355
required_precedence,
352
356
msg,
353
- } ,
354
- StateData {
355
- span : expr. span ,
356
- hir_id : expr. hir_id ,
357
- } ,
357
+ stability,
358
+ position,
359
+ } ) ,
360
+ StateData { span : expr. span , hir_id : expr. hir_id } ,
358
361
) ) ;
359
362
} else if stability. is_deref_stable ( ) {
360
363
self . state = Some ( (
@@ -393,26 +396,47 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
393
396
data,
394
397
) ) ;
395
398
} ,
396
- (
397
- Some ( (
398
- State :: DerefedBorrow {
399
- count,
400
- required_precedence,
401
- msg,
402
- } ,
403
- data,
404
- ) ) ,
405
- RefOp :: AddrOf ,
406
- ) if count != 0 => {
399
+ ( Some ( ( State :: DerefedBorrow ( state) , data) ) , RefOp :: AddrOf ) if state. count != 0 => {
407
400
self . state = Some ( (
408
- State :: DerefedBorrow {
409
- count : count - 1 ,
410
- required_precedence,
411
- msg,
412
- } ,
401
+ State :: DerefedBorrow ( DerefedBorrow {
402
+ count : state. count - 1 ,
403
+ ..state
404
+ } ) ,
413
405
data,
414
406
) ) ;
415
407
} ,
408
+ ( Some ( ( State :: DerefedBorrow ( state) , data) ) , RefOp :: AddrOf ) => {
409
+ let stability = state. stability ;
410
+ report ( cx, expr, State :: DerefedBorrow ( state) , data) ;
411
+ if stability. is_deref_stable ( ) {
412
+ self . state = Some ( (
413
+ State :: Borrow ,
414
+ StateData {
415
+ span : expr. span ,
416
+ hir_id : expr. hir_id ,
417
+ } ,
418
+ ) ) ;
419
+ }
420
+ } ,
421
+ ( Some ( ( State :: DerefedBorrow ( state) , data) ) , RefOp :: Deref ) => {
422
+ let stability = state. stability ;
423
+ let position = state. position ;
424
+ report ( cx, expr, State :: DerefedBorrow ( state) , data) ;
425
+ if let Position :: FieldAccess ( name) = position
426
+ && !ty_contains_field ( typeck. expr_ty ( sub_expr) , name)
427
+ {
428
+ self . state = Some ( (
429
+ State :: ExplicitDerefField { name } ,
430
+ StateData { span : expr. span , hir_id : expr. hir_id } ,
431
+ ) ) ;
432
+ } else if stability. is_deref_stable ( ) {
433
+ self . state = Some ( (
434
+ State :: ExplicitDeref { deref_span : expr. span , deref_hir_id : expr. hir_id } ,
435
+ StateData { span : expr. span , hir_id : expr. hir_id } ,
436
+ ) ) ;
437
+ }
438
+ } ,
439
+
416
440
( Some ( ( State :: Borrow , data) ) , RefOp :: Deref ) => {
417
441
if typeck. expr_ty ( sub_expr) . is_ref ( ) {
418
442
self . state = Some ( (
@@ -942,15 +966,11 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data
942
966
app,
943
967
) ;
944
968
} ,
945
- State :: DerefedBorrow {
946
- required_precedence,
947
- msg,
948
- ..
949
- } => {
969
+ State :: DerefedBorrow ( state) => {
950
970
let mut app = Applicability :: MachineApplicable ;
951
971
let snip = snippet_with_context ( cx, expr. span , data. span . ctxt ( ) , ".." , & mut app) . 0 ;
952
- span_lint_hir_and_then ( cx, NEEDLESS_BORROW , data. hir_id , data. span , msg, |diag| {
953
- let sugg = if required_precedence > expr. precedence ( ) . order ( ) && !has_enclosing_paren ( & snip) {
972
+ span_lint_hir_and_then ( cx, NEEDLESS_BORROW , data. hir_id , data. span , state . msg , |diag| {
973
+ let sugg = if state . required_precedence > expr. precedence ( ) . order ( ) && !has_enclosing_paren ( & snip) {
954
974
format ! ( "({})" , snip)
955
975
} else {
956
976
snip. into ( )
0 commit comments