@@ -15,7 +15,7 @@ use rustc_lint::{LateContext, LateLintPass};
1515use rustc_middle:: hir:: map:: Map ;
1616use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
1717use rustc_span:: source_map:: Span ;
18- use rustc_span:: symbol:: { kw, Symbol } ;
18+ use rustc_span:: symbol:: { kw, Ident , Symbol } ;
1919
2020declare_clippy_lint ! {
2121 /// ### What it does
@@ -85,7 +85,7 @@ declare_lint_pass!(Lifetimes => [NEEDLESS_LIFETIMES, EXTRA_UNUSED_LIFETIMES]);
8585impl < ' tcx > LateLintPass < ' tcx > for Lifetimes {
8686 fn check_item ( & mut self , cx : & LateContext < ' tcx > , item : & ' tcx Item < ' _ > ) {
8787 if let ItemKind :: Fn ( ref sig, ref generics, id) = item. kind {
88- check_fn_inner ( cx, sig. decl , Some ( id) , generics, item. span , true ) ;
88+ check_fn_inner ( cx, sig. decl , Some ( id) , None , generics, item. span , true ) ;
8989 }
9090 }
9191
@@ -96,6 +96,7 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes {
9696 cx,
9797 sig. decl ,
9898 Some ( id) ,
99+ None ,
99100 & item. generics ,
100101 item. span ,
101102 report_extra_lifetimes,
@@ -105,11 +106,11 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes {
105106
106107 fn check_trait_item ( & mut self , cx : & LateContext < ' tcx > , item : & ' tcx TraitItem < ' _ > ) {
107108 if let TraitItemKind :: Fn ( ref sig, ref body) = item. kind {
108- let body = match * body {
109- TraitFn :: Required ( _ ) => None ,
110- TraitFn :: Provided ( id) => Some ( id) ,
109+ let ( body, trait_sig ) = match * body {
110+ TraitFn :: Required ( sig ) => ( None , Some ( sig ) ) ,
111+ TraitFn :: Provided ( id) => ( Some ( id) , None ) ,
111112 } ;
112- check_fn_inner ( cx, sig. decl , body, & item. generics , item. span , true ) ;
113+ check_fn_inner ( cx, sig. decl , body, trait_sig , & item. generics , item. span , true ) ;
113114 }
114115 }
115116}
@@ -126,6 +127,7 @@ fn check_fn_inner<'tcx>(
126127 cx : & LateContext < ' tcx > ,
127128 decl : & ' tcx FnDecl < ' _ > ,
128129 body : Option < BodyId > ,
130+ trait_sig : Option < & [ Ident ] > ,
129131 generics : & ' tcx Generics < ' _ > ,
130132 span : Span ,
131133 report_extra_lifetimes : bool ,
@@ -167,7 +169,7 @@ fn check_fn_inner<'tcx>(
167169 }
168170 }
169171 }
170- if could_use_elision ( cx, decl, body, generics. params ) {
172+ if could_use_elision ( cx, decl, body, trait_sig , generics. params ) {
171173 span_lint (
172174 cx,
173175 NEEDLESS_LIFETIMES ,
@@ -181,10 +183,31 @@ fn check_fn_inner<'tcx>(
181183 }
182184}
183185
186+ // elision doesn't work for explicit self types, see rust-lang/rust#69064
187+ fn explicit_self_type < ' tcx > ( cx : & LateContext < ' tcx > , func : & FnDecl < ' tcx > , ident : Option < Ident > ) -> bool {
188+ if_chain ! {
189+ if let Some ( ident) = ident;
190+ if ident. name == kw:: SelfLower ;
191+ if !func. implicit_self. has_implicit_self( ) ;
192+
193+ if let Some ( self_ty) = func. inputs. first( ) ;
194+ then {
195+ let mut visitor = RefVisitor :: new( cx) ;
196+ visitor. visit_ty( self_ty) ;
197+
198+ !visitor. all_lts( ) . is_empty( )
199+ }
200+ else {
201+ false
202+ }
203+ }
204+ }
205+
184206fn could_use_elision < ' tcx > (
185207 cx : & LateContext < ' tcx > ,
186208 func : & ' tcx FnDecl < ' _ > ,
187209 body : Option < BodyId > ,
210+ trait_sig : Option < & [ Ident ] > ,
188211 named_generics : & ' tcx [ GenericParam < ' _ > ] ,
189212) -> bool {
190213 // There are two scenarios where elision works:
@@ -235,11 +258,24 @@ fn could_use_elision<'tcx>(
235258 let input_lts = input_visitor. lts ;
236259 let output_lts = output_visitor. lts ;
237260
261+ if let Some ( trait_sig) = trait_sig {
262+ if explicit_self_type ( cx, func, trait_sig. first ( ) . copied ( ) ) {
263+ return false ;
264+ }
265+ }
266+
238267 if let Some ( body_id) = body {
268+ let body = cx. tcx . hir ( ) . body ( body_id) ;
269+
270+ let first_ident = body. params . first ( ) . and_then ( |param| param. pat . simple_ident ( ) ) ;
271+ if explicit_self_type ( cx, func, first_ident) {
272+ return false ;
273+ }
274+
239275 let mut checker = BodyLifetimeChecker {
240276 lifetimes_used_in_body : false ,
241277 } ;
242- checker. visit_expr ( & cx . tcx . hir ( ) . body ( body_id ) . value ) ;
278+ checker. visit_expr ( & body. value ) ;
243279 if checker. lifetimes_used_in_body {
244280 return false ;
245281 }
0 commit comments