@@ -4,7 +4,10 @@ use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, OverloadedDer
4
4
use rustc_session:: { declare_lint, declare_lint_pass} ;
5
5
use rustc_span:: sym;
6
6
7
- use crate :: lints:: { ImplicitUnsafeAutorefsDiag , ImplicitUnsafeAutorefsSuggestion } ;
7
+ use crate :: lints:: {
8
+ ImplicitUnsafeAutorefsDiag , ImplicitUnsafeAutorefsMethodNote , ImplicitUnsafeAutorefsOrigin ,
9
+ ImplicitUnsafeAutorefsSuggestion ,
10
+ } ;
8
11
use crate :: { LateContext , LateLintPass , LintContext } ;
9
12
10
13
declare_lint ! {
@@ -92,25 +95,37 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitAutorefs {
92
95
&& let adjustments = peel_derefs_adjustments ( & * * adjustments)
93
96
// 3. An automatically inserted reference (might come from a deref).
94
97
&& let [ adjustment] = adjustments
95
- && let Some ( borrow_mutbl) = has_implicit_borrow ( adjustment)
98
+ && let Some ( ( borrow_mutbl, through_overloaded_deref ) ) = has_implicit_borrow ( adjustment)
96
99
&& let ExprKind :: Unary ( UnOp :: Deref , dereferenced) =
97
100
// 2. Any number of place projections.
98
101
peel_place_mappers ( inner) . kind
99
102
// 1. Deref of a raw pointer.
100
103
&& 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 ,
108
108
}
109
+ && method_did. map ( |did| cx. tcx . has_attr ( did, sym:: rustc_no_implicit_autorefs) ) . unwrap_or ( true )
109
110
{
110
111
cx. emit_span_lint (
111
112
DANGEROUS_IMPLICIT_AUTOREFS ,
112
113
expr. span . source_callsite ( ) ,
113
114
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
+ } ) ,
114
129
suggestion : ImplicitUnsafeAutorefsSuggestion {
115
130
mutbl : borrow_mutbl. ref_prefix_str ( ) ,
116
131
deref : if is_coming_from_deref { "*" } else { "" } ,
@@ -146,11 +161,12 @@ fn peel_derefs_adjustments<'a>(mut adjs: &'a [Adjustment<'a>]) -> &'a [Adjustmen
146
161
147
162
/// Test if some adjustment has some implicit borrow.
148
163
///
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 ) > {
151
167
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 ) ) ,
154
170
Adjust :: NeverToAny
155
171
| Adjust :: Pointer ( ..)
156
172
| Adjust :: ReborrowPin ( ..)
0 commit comments