3333
3434use metadata:: { csearch, decoder} ;
3535use middle:: { cfg, def, infer, pat_util, stability, traits} ;
36- use middle:: def:: * ;
3736use middle:: subst:: Substs ;
3837use middle:: ty:: { self , Ty } ;
3938use middle:: const_eval:: { eval_const_expr_partial, ConstVal } ;
@@ -2251,34 +2250,73 @@ impl LintPass for UnconditionalRecursion {
22512250 }
22522251 }
22532252
2254- // Check if the method call `id` refers to method `method`.
2253+ // Check if the expression `id` performs a call to `method`.
22552254 fn expr_refers_to_this_method ( tcx : & ty:: ctxt ,
22562255 method : & ty:: Method ,
22572256 id : ast:: NodeId ) -> bool {
2258- let method_call = ty:: MethodCall :: expr ( id) ;
2259- let callee = match tcx. tables . borrow ( ) . method_map . get ( & method_call) {
2260- Some ( & m) => m,
2261- None => return false
2262- } ;
2263- let callee_item = tcx. impl_or_trait_item ( callee. def_id ) ;
2257+ let tables = tcx. tables . borrow ( ) ;
2258+
2259+ // Check for method calls and overloaded operators.
2260+ if let Some ( m) = tables. method_map . get ( & ty:: MethodCall :: expr ( id) ) {
2261+ if method_call_refers_to_method ( tcx, method, m. def_id , m. substs , id) {
2262+ return true ;
2263+ }
2264+ }
2265+
2266+ // Check for overloaded autoderef method calls.
2267+ if let Some ( & ty:: AdjustDerefRef ( ref adj) ) = tables. adjustments . get ( & id) {
2268+ for i in 0 ..adj. autoderefs {
2269+ let method_call = ty:: MethodCall :: autoderef ( id, i as u32 ) ;
2270+ if let Some ( m) = tables. method_map . get ( & method_call) {
2271+ if method_call_refers_to_method ( tcx, method, m. def_id , m. substs , id) {
2272+ return true ;
2273+ }
2274+ }
2275+ }
2276+ }
2277+
2278+ // Check for calls to methods via explicit paths (e.g. `T::method()`).
2279+ match tcx. map . get ( id) {
2280+ ast_map:: NodeExpr ( & ast:: Expr { node : ast:: ExprCall ( ref callee, _) , .. } ) => {
2281+ match tcx. def_map . borrow ( ) . get ( & callee. id ) . map ( |d| d. full_def ( ) ) {
2282+ Some ( def:: DefMethod ( def_id) ) => {
2283+ let no_substs = & ty:: ItemSubsts :: empty ( ) ;
2284+ let ts = tables. item_substs . get ( & callee. id ) . unwrap_or ( no_substs) ;
2285+ method_call_refers_to_method ( tcx, method, def_id, & ts. substs , id)
2286+ }
2287+ _ => false
2288+ }
2289+ }
2290+ _ => false
2291+ }
2292+ }
2293+
2294+ // Check if the method call to the method with the ID `callee_id`
2295+ // and instantiated with `callee_substs` refers to method `method`.
2296+ fn method_call_refers_to_method < ' tcx > ( tcx : & ty:: ctxt < ' tcx > ,
2297+ method : & ty:: Method ,
2298+ callee_id : ast:: DefId ,
2299+ callee_substs : & Substs < ' tcx > ,
2300+ expr_id : ast:: NodeId ) -> bool {
2301+ let callee_item = tcx. impl_or_trait_item ( callee_id) ;
22642302
22652303 match callee_item. container ( ) {
22662304 // This is an inherent method, so the `def_id` refers
22672305 // directly to the method definition.
22682306 ty:: ImplContainer ( _) => {
2269- callee . def_id == method. def_id
2307+ callee_id == method. def_id
22702308 }
22712309
22722310 // A trait method, from any number of possible sources.
22732311 // Attempt to select a concrete impl before checking.
22742312 ty:: TraitContainer ( trait_def_id) => {
2275- let trait_substs = callee . substs . clone ( ) . method_to_trait ( ) ;
2313+ let trait_substs = callee_substs . clone ( ) . method_to_trait ( ) ;
22762314 let trait_substs = tcx. mk_substs ( trait_substs) ;
22772315 let trait_ref = ty:: TraitRef :: new ( trait_def_id, trait_substs) ;
22782316 let trait_ref = ty:: Binder ( trait_ref) ;
2279- let span = tcx. map . span ( id ) ;
2317+ let span = tcx. map . span ( expr_id ) ;
22802318 let obligation =
2281- traits:: Obligation :: new ( traits:: ObligationCause :: misc ( span, id ) ,
2319+ traits:: Obligation :: new ( traits:: ObligationCause :: misc ( span, expr_id ) ,
22822320 trait_ref. to_poly_trait_predicate ( ) ) ;
22832321
22842322 let param_env = ty:: ParameterEnvironment :: for_item ( tcx, method. def_id . node ) ;
@@ -2289,12 +2327,12 @@ impl LintPass for UnconditionalRecursion {
22892327 // If `T` is `Self`, then this call is inside
22902328 // a default method definition.
22912329 Ok ( Some ( traits:: VtableParam ( _) ) ) => {
2292- let self_ty = callee . substs . self_ty ( ) ;
2330+ let self_ty = callee_substs . self_ty ( ) ;
22932331 let on_self = self_ty. map_or ( false , |t| t. is_self ( ) ) ;
22942332 // We can only be recurring in a default
22952333 // method if we're being called literally
22962334 // on the `Self` type.
2297- on_self && callee . def_id == method. def_id
2335+ on_self && callee_id == method. def_id
22982336 }
22992337
23002338 // The `impl` is known, so we check that with a
@@ -2454,7 +2492,7 @@ impl LintPass for MutableTransmutes {
24542492 ast:: ExprPath ( ..) => ( ) ,
24552493 _ => return None
24562494 }
2457- if let DefFn ( did, _) = cx. tcx . resolve_expr ( expr) {
2495+ if let def :: DefFn ( did, _) = cx. tcx . resolve_expr ( expr) {
24582496 if !def_id_is_transmute ( cx, did) {
24592497 return None ;
24602498 }
0 commit comments