@@ -72,7 +72,7 @@ use rustc_hir::LangItem::{ResultErr, ResultOk};
7272use rustc_hir:: {
7373 def, Arm , BindingAnnotation , Block , Body , Constness , Destination , Expr , ExprKind , FnDecl , GenericArgs , HirId , Impl ,
7474 ImplItem , ImplItemKind , IsAsync , Item , ItemKind , LangItem , Local , MatchSource , Node , Param , Pat , PatKind , Path ,
75- PathSegment , QPath , Stmt , StmtKind , TraitItem , TraitItemKind , TraitRef , TyKind ,
75+ PathSegment , QPath , Stmt , StmtKind , TraitItem , TraitItemKind , TraitRef , TyKind , UnOp ,
7676} ;
7777use rustc_lint:: { LateContext , Level , Lint , LintContext } ;
7878use rustc_middle:: hir:: exports:: Export ;
@@ -326,16 +326,6 @@ pub fn is_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, diag_item: Symbol)
326326 . map_or ( false , |did| is_diag_trait_item ( cx, did, diag_item) )
327327}
328328
329- /// Checks if an expression references a variable of the given name.
330- pub fn match_var ( expr : & Expr < ' _ > , var : Symbol ) -> bool {
331- if let ExprKind :: Path ( QPath :: Resolved ( None , path) ) = expr. kind {
332- if let [ p] = path. segments {
333- return p. ident . name == var;
334- }
335- }
336- false
337- }
338-
339329pub fn last_path_segment < ' tcx > ( path : & QPath < ' tcx > ) -> & ' tcx PathSegment < ' tcx > {
340330 match * path {
341331 QPath :: Resolved ( _, path) => path. segments . last ( ) . expect ( "A path must have at least one segment" ) ,
@@ -707,16 +697,6 @@ pub fn get_item_name(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<Symbol> {
707697 }
708698}
709699
710- /// Gets the name of a `Pat`, if any.
711- pub fn get_pat_name ( pat : & Pat < ' _ > ) -> Option < Symbol > {
712- match pat. kind {
713- PatKind :: Binding ( .., ref spname, _) => Some ( spname. name ) ,
714- PatKind :: Path ( ref qpath) => single_segment_path ( qpath) . map ( |ps| ps. ident . name ) ,
715- PatKind :: Box ( p) | PatKind :: Ref ( p, _) => get_pat_name ( & * p) ,
716- _ => None ,
717- }
718- }
719-
720700pub struct ContainsName {
721701 pub name : Symbol ,
722702 pub result : bool ,
@@ -1404,47 +1384,42 @@ pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
14041384/// Checks if an expression represents the identity function
14051385/// Only examines closures and `std::convert::identity`
14061386pub fn is_expr_identity_function ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > ) -> bool {
1407- /// Returns true if the expression is a binding to the given pattern
1408- fn is_expr_pat_binding ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > , pat : & Pat < ' _ > ) -> bool {
1409- if let PatKind :: Binding ( _, _, ident, _) = pat. kind {
1410- if match_var ( expr, ident. name ) {
1411- return !( cx. typeck_results ( ) . hir_owner == expr. hir_id . owner && is_adjusted ( cx, expr) ) ;
1412- }
1413- }
1414-
1415- false
1416- }
1417-
14181387 /// Checks if a function's body represents the identity function. Looks for bodies of the form:
14191388 /// * `|x| x`
14201389 /// * `|x| return x`
14211390 /// * `|x| { return x }`
14221391 /// * `|x| { return x; }`
14231392 fn is_body_identity_function ( cx : & LateContext < ' _ > , func : & Body < ' _ > ) -> bool {
1424- let body = remove_blocks ( & func. value ) ;
1425-
1426- let value_pat = if let [ value_param] = func. params {
1427- value_param. pat
1428- } else {
1429- return false ;
1393+ let id = if_chain ! {
1394+ if let [ param] = func. params;
1395+ if let PatKind :: Binding ( _, id, _, _) = param. pat. kind;
1396+ then {
1397+ id
1398+ } else {
1399+ return false ;
1400+ }
14301401 } ;
14311402
1432- match body. kind {
1433- ExprKind :: Path ( QPath :: Resolved ( None , _) ) => is_expr_pat_binding ( cx, body, value_pat) ,
1434- ExprKind :: Ret ( Some ( ret_val) ) => is_expr_pat_binding ( cx, ret_val, value_pat) ,
1435- ExprKind :: Block ( block, _) => {
1436- if_chain ! {
1437- if let & [ block_stmt] = & block. stmts;
1438- if let StmtKind :: Semi ( expr) | StmtKind :: Expr ( expr) = block_stmt. kind;
1439- if let ExprKind :: Ret ( Some ( ret_val) ) = expr. kind;
1440- then {
1441- is_expr_pat_binding( cx, ret_val, value_pat)
1442- } else {
1443- false
1403+ let mut expr = & func. value ;
1404+ loop {
1405+ match expr. kind {
1406+ #[ rustfmt:: skip]
1407+ ExprKind :: Block ( & Block { stmts : [ ] , expr : Some ( e) , .. } , _, )
1408+ | ExprKind :: Ret ( Some ( e) ) => expr = e,
1409+ #[ rustfmt:: skip]
1410+ ExprKind :: Block ( & Block { stmts : [ stmt] , expr : None , .. } , _) => {
1411+ if_chain ! {
1412+ if let StmtKind :: Semi ( e) | StmtKind :: Expr ( e) = stmt. kind;
1413+ if let ExprKind :: Ret ( Some ( ret_val) ) = e. kind;
1414+ then {
1415+ expr = ret_val;
1416+ } else {
1417+ return false ;
1418+ }
14441419 }
1445- }
1446- } ,
1447- _ => false ,
1420+ } ,
1421+ _ => return path_to_local_id ( expr , id ) && cx . typeck_results ( ) . expr_adjustments ( expr ) . is_empty ( ) ,
1422+ }
14481423 }
14491424 }
14501425
@@ -1710,6 +1685,19 @@ pub fn peel_hir_expr_refs(expr: &'a Expr<'a>) -> (&'a Expr<'a>, usize) {
17101685 ( e, count)
17111686}
17121687
1688+ /// Removes `AddrOf` operators (`&`) or deref operators (`*`), but only if a reference type is
1689+ /// dereferenced. An overloaded deref such as `Vec` to slice would not be removed.
1690+ pub fn peel_ref_operators < ' hir > ( cx : & LateContext < ' _ > , mut expr : & ' hir Expr < ' hir > ) -> & ' hir Expr < ' hir > {
1691+ loop {
1692+ match expr. kind {
1693+ ExprKind :: AddrOf ( _, _, e) => expr = e,
1694+ ExprKind :: Unary ( UnOp :: Deref , e) if cx. typeck_results ( ) . expr_ty ( e) . is_ref ( ) => expr = e,
1695+ _ => break ,
1696+ }
1697+ }
1698+ expr
1699+ }
1700+
17131701#[ macro_export]
17141702macro_rules! unwrap_cargo_metadata {
17151703 ( $cx: ident, $lint: ident, $deps: expr) => { {
0 commit comments