@@ -72,7 +72,7 @@ use rustc_hir::LangItem::{ResultErr, ResultOk};
72
72
use rustc_hir:: {
73
73
def, Arm , BindingAnnotation , Block , Body , Constness , Destination , Expr , ExprKind , FnDecl , GenericArgs , HirId , Impl ,
74
74
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 ,
76
76
} ;
77
77
use rustc_lint:: { LateContext , Level , Lint , LintContext } ;
78
78
use rustc_middle:: hir:: exports:: Export ;
@@ -326,16 +326,6 @@ pub fn is_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, diag_item: Symbol)
326
326
. map_or ( false , |did| is_diag_trait_item ( cx, did, diag_item) )
327
327
}
328
328
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
-
339
329
pub fn last_path_segment < ' tcx > ( path : & QPath < ' tcx > ) -> & ' tcx PathSegment < ' tcx > {
340
330
match * path {
341
331
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> {
707
697
}
708
698
}
709
699
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
-
720
700
pub struct ContainsName {
721
701
pub name : Symbol ,
722
702
pub result : bool ,
@@ -1404,47 +1384,42 @@ pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
1404
1384
/// Checks if an expression represents the identity function
1405
1385
/// Only examines closures and `std::convert::identity`
1406
1386
pub 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
-
1418
1387
/// Checks if a function's body represents the identity function. Looks for bodies of the form:
1419
1388
/// * `|x| x`
1420
1389
/// * `|x| return x`
1421
1390
/// * `|x| { return x }`
1422
1391
/// * `|x| { return x; }`
1423
1392
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
+ }
1430
1401
} ;
1431
1402
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
+ }
1444
1419
}
1445
- }
1446
- } ,
1447
- _ => false ,
1420
+ } ,
1421
+ _ => return path_to_local_id ( expr , id ) && cx . typeck_results ( ) . expr_adjustments ( expr ) . is_empty ( ) ,
1422
+ }
1448
1423
}
1449
1424
}
1450
1425
@@ -1710,6 +1685,19 @@ pub fn peel_hir_expr_refs(expr: &'a Expr<'a>) -> (&'a Expr<'a>, usize) {
1710
1685
( e, count)
1711
1686
}
1712
1687
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
+
1713
1701
#[ macro_export]
1714
1702
macro_rules! unwrap_cargo_metadata {
1715
1703
( $cx: ident, $lint: ident, $deps: expr) => { {
0 commit comments