@@ -4,7 +4,10 @@ use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, OverloadedDer
44use rustc_session:: { declare_lint, declare_lint_pass} ;
55use rustc_span:: sym;
66
7- use crate :: lints:: { ImplicitUnsafeAutorefsDiag , ImplicitUnsafeAutorefsSuggestion } ;
7+ use crate :: lints:: {
8+ ImplicitUnsafeAutorefsDiag , ImplicitUnsafeAutorefsMethodNote , ImplicitUnsafeAutorefsOrigin ,
9+ ImplicitUnsafeAutorefsSuggestion ,
10+ } ;
811use crate :: { LateContext , LateLintPass , LintContext } ;
912
1013declare_lint ! {
@@ -92,25 +95,37 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitAutorefs {
9295 && let adjustments = peel_derefs_adjustments ( & * * adjustments)
9396 // 3. An automatically inserted reference (might come from a deref).
9497 && let [ adjustment] = adjustments
95- && let Some ( borrow_mutbl) = has_implicit_borrow ( adjustment)
98+ && let Some ( ( borrow_mutbl, through_overloaded_deref ) ) = has_implicit_borrow ( adjustment)
9699 && let ExprKind :: Unary ( UnOp :: Deref , dereferenced) =
97100 // 2. Any number of place projections.
98101 peel_place_mappers ( inner) . kind
99102 // 1. Deref of a raw pointer.
100103 && typeck. expr_ty ( dereferenced) . is_raw_ptr ( )
101- // PERF: 5. b. A method call annotated with `#[rustc_no_implicit_refs]`
102- && match expr. kind {
103- ExprKind :: MethodCall ( ..) => matches ! (
104- cx. typeck_results( ) . type_dependent_def_id( expr. hir_id) ,
105- Some ( def_id) if cx. tcx. has_attr( def_id, sym:: rustc_no_implicit_autorefs)
106- ) ,
107- _ => true ,
104+ && let method_did = match expr. kind {
105+ // PERF: 5. b. A method call annotated with `#[rustc_no_implicit_refs]`
106+ ExprKind :: MethodCall ( ..) => cx. typeck_results ( ) . type_dependent_def_id ( expr. hir_id ) ,
107+ _ => None ,
108108 }
109+ && method_did. map ( |did| cx. tcx . has_attr ( did, sym:: rustc_no_implicit_autorefs) ) . unwrap_or ( true )
109110 {
110111 cx. emit_span_lint (
111112 DANGEROUS_IMPLICIT_AUTOREFS ,
112113 expr. span . source_callsite ( ) ,
113114 ImplicitUnsafeAutorefsDiag {
115+ raw_ptr_span : dereferenced. span ,
116+ raw_ptr_ty : typeck. expr_ty ( dereferenced) ,
117+ origin : if through_overloaded_deref {
118+ ImplicitUnsafeAutorefsOrigin :: OverloadedDeref
119+ } else {
120+ ImplicitUnsafeAutorefsOrigin :: Autoref {
121+ autoref_span : inner. span ,
122+ autoref_ty : typeck. expr_ty_adjusted ( inner) ,
123+ }
124+ } ,
125+ method : method_did. map ( |did| ImplicitUnsafeAutorefsMethodNote {
126+ def_span : cx. tcx . def_span ( did) ,
127+ method_name : cx. tcx . item_name ( did) ,
128+ } ) ,
114129 suggestion : ImplicitUnsafeAutorefsSuggestion {
115130 mutbl : borrow_mutbl. ref_prefix_str ( ) ,
116131 deref : if is_coming_from_deref { "*" } else { "" } ,
@@ -146,11 +161,12 @@ fn peel_derefs_adjustments<'a>(mut adjs: &'a [Adjustment<'a>]) -> &'a [Adjustmen
146161
147162/// Test if some adjustment has some implicit borrow.
148163///
149- /// Returns `Some(mutability)` if the argument adjustment has implicit borrow in it.
150- fn has_implicit_borrow ( Adjustment { kind, .. } : & Adjustment < ' _ > ) -> Option < Mutability > {
164+ /// Returns `Some((mutability, was_an_overloaded_deref))` if the argument adjustment is
165+ /// an implicit borrow (or has an implicit borrow via an overloaded deref).
166+ fn has_implicit_borrow ( Adjustment { kind, .. } : & Adjustment < ' _ > ) -> Option < ( Mutability , bool ) > {
151167 match kind {
152- & Adjust :: Deref ( Some ( OverloadedDeref { mutbl, .. } ) ) => Some ( mutbl) ,
153- & Adjust :: Borrow ( AutoBorrow :: Ref ( mutbl) ) => Some ( mutbl. into ( ) ) ,
168+ & Adjust :: Deref ( Some ( OverloadedDeref { mutbl, .. } ) ) => Some ( ( mutbl, true ) ) ,
169+ & Adjust :: Borrow ( AutoBorrow :: Ref ( mutbl) ) => Some ( ( mutbl. into ( ) , false ) ) ,
154170 Adjust :: NeverToAny
155171 | Adjust :: Pointer ( ..)
156172 | Adjust :: ReborrowPin ( ..)
0 commit comments