@@ -163,6 +163,14 @@ struct StateData {
163163 hir_id : HirId ,
164164}
165165
166+ struct DerefedBorrow {
167+ count : usize ,
168+ required_precedence : i8 ,
169+ msg : & ' static str ,
170+ stability : AutoDerefStability ,
171+ position : Position ,
172+ }
173+
166174enum State {
167175 // Any number of deref method calls.
168176 DerefMethod {
@@ -172,11 +180,7 @@ enum State {
172180 /// The required mutability
173181 target_mut : Mutability ,
174182 } ,
175- DerefedBorrow {
176- count : usize ,
177- required_precedence : i8 ,
178- msg : & ' static str ,
179- } ,
183+ DerefedBorrow ( DerefedBorrow ) ,
180184 ExplicitDeref {
181185 deref_span : Span ,
182186 deref_hir_id : HirId ,
@@ -344,17 +348,16 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
344348
345349 if deref_count >= required_refs {
346350 self . state = Some ( (
347- State :: DerefedBorrow {
351+ State :: DerefedBorrow ( DerefedBorrow {
348352 // One of the required refs is for the current borrow expression, the remaining ones
349353 // can't be removed without breaking the code. See earlier comment.
350354 count : deref_count - required_refs,
351355 required_precedence,
352356 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 } ,
358361 ) ) ;
359362 } else if stability. is_deref_stable ( ) {
360363 self . state = Some ( (
@@ -393,26 +396,47 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
393396 data,
394397 ) ) ;
395398 } ,
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 => {
407400 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+ } ) ,
413405 data,
414406 ) ) ;
415407 } ,
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+
416440 ( Some ( ( State :: Borrow , data) ) , RefOp :: Deref ) => {
417441 if typeck. expr_ty ( sub_expr) . is_ref ( ) {
418442 self . state = Some ( (
@@ -942,15 +966,11 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data
942966 app,
943967 ) ;
944968 } ,
945- State :: DerefedBorrow {
946- required_precedence,
947- msg,
948- ..
949- } => {
969+ State :: DerefedBorrow ( state) => {
950970 let mut app = Applicability :: MachineApplicable ;
951971 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) {
954974 format ! ( "({})" , snip)
955975 } else {
956976 snip. into ( )
0 commit comments