@@ -60,9 +60,9 @@ use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
6060use rustc_hir:: def_id:: { DefId , LOCAL_CRATE } ;
6161use rustc_hir:: intravisit:: { self , NestedVisitorMap , Visitor } ;
6262use rustc_hir:: {
63- def, Arm , BindingAnnotation , Block , Body , Constness , CrateItem , Expr , ExprKind , FieldDef , FnDecl , ForeignItem ,
64- GenericArgs , GenericParam , HirId , Impl , ImplItem , ImplItemKind , Item , ItemKind , LangItem , Lifetime , Local ,
65- MacroDef , MatchSource , Node , Param , Pat , PatKind , Path , PathSegment , QPath , Stmt , TraitItem , TraitItemKind ,
63+ def, Arm , BindingAnnotation , Block , Body , Constness , CrateItem , Destination , Expr , ExprKind , FieldDef , FnDecl ,
64+ ForeignItem , GenericArgs , GenericParam , HirId , Impl , ImplItem , ImplItemKind , Item , ItemKind , LangItem , Lifetime ,
65+ Local , MacroDef , MatchSource , Node , Param , Pat , PatKind , Path , PathSegment , QPath , Stmt , TraitItem , TraitItemKind ,
6666 TraitRef , TyKind , Variant , Visibility ,
6767} ;
6868use rustc_lint:: { LateContext , Level , Lint , LintContext } ;
@@ -1262,6 +1262,82 @@ pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
12621262 did. map_or ( false , |did| must_use_attr ( & cx. tcx . get_attrs ( did) ) . is_some ( ) )
12631263}
12641264
1265+ pub fn get_expr_use_node ( tcx : TyCtxt < ' tcx > , expr : & Expr < ' _ > ) -> Option < Node < ' tcx > > {
1266+ let map = tcx. hir ( ) ;
1267+ let mut child_id = expr. hir_id ;
1268+ let mut iter = map. parent_iter ( child_id) ;
1269+ loop {
1270+ match iter. next ( ) {
1271+ None => break None ,
1272+ Some ( ( id, Node :: Block ( _) ) ) => child_id = id,
1273+ Some ( ( id, Node :: Arm ( arm) ) ) if arm. body . hir_id == child_id => child_id = id,
1274+ Some ( ( _, Node :: Expr ( expr) ) ) => match expr. kind {
1275+ ExprKind :: Break (
1276+ Destination {
1277+ target_id : Ok ( dest) , ..
1278+ } ,
1279+ _,
1280+ ) => {
1281+ iter = map. parent_iter ( dest) ;
1282+ child_id = dest;
1283+ } ,
1284+ ExprKind :: DropTemps ( _) | ExprKind :: Block ( ..) => child_id = expr. hir_id ,
1285+ ExprKind :: If ( control_expr, ..) | ExprKind :: Match ( control_expr, ..)
1286+ if control_expr. hir_id != child_id =>
1287+ {
1288+ child_id = expr. hir_id
1289+ } ,
1290+ _ => break Some ( Node :: Expr ( expr) ) ,
1291+ } ,
1292+ Some ( ( _, node) ) => break Some ( node) ,
1293+ }
1294+ }
1295+ }
1296+
1297+ pub fn is_expr_used ( tcx : TyCtxt < ' _ > , expr : & Expr < ' _ > ) -> bool {
1298+ !matches ! (
1299+ get_expr_use_node( tcx, expr) ,
1300+ Some ( Node :: Stmt ( Stmt {
1301+ kind: StmtKind :: Expr ( _) | StmtKind :: Semi ( _) ,
1302+ ..
1303+ } ) )
1304+ )
1305+ }
1306+
1307+ pub fn get_expr_use_or_unification_node ( tcx : TyCtxt < ' tcx > , expr : & Expr < ' _ > ) -> Option < Node < ' tcx > > {
1308+ let map = tcx. hir ( ) ;
1309+ let mut child_id = expr. hir_id ;
1310+ let mut iter = map. parent_iter ( child_id) ;
1311+ loop {
1312+ match iter. next ( ) {
1313+ None => break None ,
1314+ Some ( ( id, Node :: Block ( _) ) ) => child_id = id,
1315+ Some ( ( id, Node :: Arm ( arm) ) ) if arm. body . hir_id == child_id => child_id = id,
1316+ Some ( ( _, Node :: Expr ( expr) ) ) => match expr. kind {
1317+ ExprKind :: Match ( _, [ arm] , _) if arm. hir_id == child_id => child_id = expr. hir_id ,
1318+ ExprKind :: Block ( ..) | ExprKind :: DropTemps ( _) => child_id = expr. hir_id ,
1319+ ExprKind :: If ( _, then_expr, None ) if then_expr. hir_id == child_id => break None ,
1320+ _ => break Some ( Node :: Expr ( expr) ) ,
1321+ } ,
1322+ Some ( ( _, node) ) => break Some ( node) ,
1323+ }
1324+ }
1325+ }
1326+
1327+ pub fn is_expr_used_or_unified ( tcx : TyCtxt < ' _ > , expr : & Expr < ' _ > ) -> bool {
1328+ !matches ! (
1329+ get_expr_use_or_unification_node( tcx, expr) ,
1330+ None | Some ( Node :: Stmt ( Stmt {
1331+ kind: StmtKind :: Expr ( _) | StmtKind :: Semi ( _) ,
1332+ ..
1333+ } ) )
1334+ )
1335+ }
1336+
1337+ pub fn is_expr_final_block_expr ( tcx : TyCtxt < ' _ > , expr : & Expr < ' _ > ) -> bool {
1338+ matches ! ( get_parent_node( tcx, expr. hir_id) , Some ( Node :: Block ( ..) ) )
1339+ }
1340+
12651341pub fn is_no_std_crate ( cx : & LateContext < ' _ > ) -> bool {
12661342 cx. tcx . hir ( ) . attrs ( hir:: CRATE_HIR_ID ) . iter ( ) . any ( |attr| {
12671343 if let ast:: AttrKind :: Normal ( ref attr, _) = attr. kind {
@@ -1431,28 +1507,43 @@ pub fn peel_hir_pat_refs(pat: &'a Pat<'a>) -> (&'a Pat<'a>, usize) {
14311507 peel ( pat, 0 )
14321508}
14331509
1510+ /// Peels of expressions while the given closure returns `Some`.
1511+ pub fn peel_hir_expr_while < ' tcx > (
1512+ mut expr : & ' tcx Expr < ' tcx > ,
1513+ mut f : impl FnMut ( & ' tcx Expr < ' tcx > ) -> Option < & ' tcx Expr < ' tcx > > ,
1514+ ) -> & ' tcx Expr < ' tcx > {
1515+ while let Some ( e) = f ( expr) {
1516+ expr = e;
1517+ }
1518+ expr
1519+ }
1520+
14341521/// Peels off up to the given number of references on the expression. Returns the underlying
14351522/// expression and the number of references removed.
14361523pub fn peel_n_hir_expr_refs ( expr : & ' a Expr < ' a > , count : usize ) -> ( & ' a Expr < ' a > , usize ) {
1437- fn f ( expr : & ' a Expr < ' a > , count : usize , target : usize ) -> ( & ' a Expr < ' a > , usize ) {
1438- match expr. kind {
1439- ExprKind :: AddrOf ( _, _, expr) if count != target => f ( expr, count + 1 , target) ,
1440- _ => ( expr, count) ,
1441- }
1442- }
1443- f ( expr, 0 , count)
1524+ let mut remaining = count;
1525+ let e = peel_hir_expr_while ( expr, |e| match e. kind {
1526+ ExprKind :: AddrOf ( BorrowKind :: Ref , _, e) if remaining != 0 => {
1527+ remaining -= 1 ;
1528+ Some ( e)
1529+ } ,
1530+ _ => None ,
1531+ } ) ;
1532+ ( e, count - remaining)
14441533}
14451534
14461535/// Peels off all references on the expression. Returns the underlying expression and the number of
14471536/// references removed.
14481537pub fn peel_hir_expr_refs ( expr : & ' a Expr < ' a > ) -> ( & ' a Expr < ' a > , usize ) {
1449- fn f ( expr : & ' a Expr < ' a > , count : usize ) -> ( & ' a Expr < ' a > , usize ) {
1450- match expr. kind {
1451- ExprKind :: AddrOf ( BorrowKind :: Ref , _, expr) => f ( expr, count + 1 ) ,
1452- _ => ( expr, count) ,
1453- }
1454- }
1455- f ( expr, 0 )
1538+ let mut count = 0 ;
1539+ let e = peel_hir_expr_while ( expr, |e| match e. kind {
1540+ ExprKind :: AddrOf ( BorrowKind :: Ref , _, e) => {
1541+ count += 1 ;
1542+ Some ( e)
1543+ } ,
1544+ _ => None ,
1545+ } ) ;
1546+ ( e, count)
14561547}
14571548
14581549#[ macro_export]
0 commit comments