@@ -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 } ;
@@ -1260,6 +1260,82 @@ pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
12601260 did. map_or ( false , |did| must_use_attr ( & cx. tcx . get_attrs ( did) ) . is_some ( ) )
12611261}
12621262
1263+ pub fn get_expr_use_node ( tcx : TyCtxt < ' tcx > , expr : & Expr < ' _ > ) -> Option < Node < ' tcx > > {
1264+ let map = tcx. hir ( ) ;
1265+ let mut child_id = expr. hir_id ;
1266+ let mut iter = map. parent_iter ( child_id) ;
1267+ loop {
1268+ match iter. next ( ) {
1269+ None => break None ,
1270+ Some ( ( id, Node :: Block ( _) ) ) => child_id = id,
1271+ Some ( ( id, Node :: Arm ( arm) ) ) if arm. body . hir_id == child_id => child_id = id,
1272+ Some ( ( _, Node :: Expr ( expr) ) ) => match expr. kind {
1273+ ExprKind :: Break (
1274+ Destination {
1275+ target_id : Ok ( dest) , ..
1276+ } ,
1277+ _,
1278+ ) => {
1279+ iter = map. parent_iter ( dest) ;
1280+ child_id = dest;
1281+ } ,
1282+ ExprKind :: DropTemps ( _) | ExprKind :: Block ( ..) => child_id = expr. hir_id ,
1283+ ExprKind :: If ( control_expr, ..) | ExprKind :: Match ( control_expr, ..)
1284+ if control_expr. hir_id != child_id =>
1285+ {
1286+ child_id = expr. hir_id
1287+ } ,
1288+ _ => break Some ( Node :: Expr ( expr) ) ,
1289+ } ,
1290+ Some ( ( _, node) ) => break Some ( node) ,
1291+ }
1292+ }
1293+ }
1294+
1295+ pub fn is_expr_used ( tcx : TyCtxt < ' _ > , expr : & Expr < ' _ > ) -> bool {
1296+ !matches ! (
1297+ get_expr_use_node( tcx, expr) ,
1298+ Some ( Node :: Stmt ( Stmt {
1299+ kind: StmtKind :: Expr ( _) | StmtKind :: Semi ( _) ,
1300+ ..
1301+ } ) )
1302+ )
1303+ }
1304+
1305+ pub fn get_expr_use_or_unification_node ( tcx : TyCtxt < ' tcx > , expr : & Expr < ' _ > ) -> Option < Node < ' tcx > > {
1306+ let map = tcx. hir ( ) ;
1307+ let mut child_id = expr. hir_id ;
1308+ let mut iter = map. parent_iter ( child_id) ;
1309+ loop {
1310+ match iter. next ( ) {
1311+ None => break None ,
1312+ Some ( ( id, Node :: Block ( _) ) ) => child_id = id,
1313+ Some ( ( id, Node :: Arm ( arm) ) ) if arm. body . hir_id == child_id => child_id = id,
1314+ Some ( ( _, Node :: Expr ( expr) ) ) => match expr. kind {
1315+ ExprKind :: Match ( _, [ arm] , _) if arm. hir_id == child_id => child_id = expr. hir_id ,
1316+ ExprKind :: Block ( ..) | ExprKind :: DropTemps ( _) => child_id = expr. hir_id ,
1317+ ExprKind :: If ( _, then_expr, None ) if then_expr. hir_id == child_id => break None ,
1318+ _ => break Some ( Node :: Expr ( expr) ) ,
1319+ } ,
1320+ Some ( ( _, node) ) => break Some ( node) ,
1321+ }
1322+ }
1323+ }
1324+
1325+ pub fn is_expr_used_or_unified ( tcx : TyCtxt < ' _ > , expr : & Expr < ' _ > ) -> bool {
1326+ !matches ! (
1327+ get_expr_use_or_unification_node( tcx, expr) ,
1328+ None | Some ( Node :: Stmt ( Stmt {
1329+ kind: StmtKind :: Expr ( _) | StmtKind :: Semi ( _) ,
1330+ ..
1331+ } ) )
1332+ )
1333+ }
1334+
1335+ pub fn is_expr_final_block_expr ( tcx : TyCtxt < ' _ > , expr : & Expr < ' _ > ) -> bool {
1336+ matches ! ( get_parent_node( tcx, expr. hir_id) , Some ( Node :: Block ( ..) ) )
1337+ }
1338+
12631339pub fn is_no_std_crate ( cx : & LateContext < ' _ > ) -> bool {
12641340 cx. tcx . hir ( ) . attrs ( hir:: CRATE_HIR_ID ) . iter ( ) . any ( |attr| {
12651341 if let ast:: AttrKind :: Normal ( ref attr, _) = attr. kind {
@@ -1419,28 +1495,43 @@ pub fn peel_hir_pat_refs(pat: &'a Pat<'a>) -> (&'a Pat<'a>, usize) {
14191495 peel ( pat, 0 )
14201496}
14211497
1498+ /// Peels of expressions while the given closure returns `Some`.
1499+ pub fn peel_hir_expr_while < ' tcx > (
1500+ mut expr : & ' tcx Expr < ' tcx > ,
1501+ mut f : impl FnMut ( & ' tcx Expr < ' tcx > ) -> Option < & ' tcx Expr < ' tcx > > ,
1502+ ) -> & ' tcx Expr < ' tcx > {
1503+ while let Some ( e) = f ( expr) {
1504+ expr = e;
1505+ }
1506+ expr
1507+ }
1508+
14221509/// Peels off up to the given number of references on the expression. Returns the underlying
14231510/// expression and the number of references removed.
14241511pub fn peel_n_hir_expr_refs ( expr : & ' a Expr < ' a > , count : usize ) -> ( & ' a Expr < ' a > , usize ) {
1425- fn f ( expr : & ' a Expr < ' a > , count : usize , target : usize ) -> ( & ' a Expr < ' a > , usize ) {
1426- match expr. kind {
1427- ExprKind :: AddrOf ( _, _, expr) if count != target => f ( expr, count + 1 , target) ,
1428- _ => ( expr, count) ,
1429- }
1430- }
1431- f ( expr, 0 , count)
1512+ let mut remaining = count;
1513+ let e = peel_hir_expr_while ( expr, |e| match e. kind {
1514+ ExprKind :: AddrOf ( BorrowKind :: Ref , _, e) if remaining != 0 => {
1515+ remaining -= 1 ;
1516+ Some ( e)
1517+ } ,
1518+ _ => None ,
1519+ } ) ;
1520+ ( e, count - remaining)
14321521}
14331522
14341523/// Peels off all references on the expression. Returns the underlying expression and the number of
14351524/// references removed.
14361525pub fn peel_hir_expr_refs ( expr : & ' a Expr < ' a > ) -> ( & ' a Expr < ' a > , usize ) {
1437- fn f ( expr : & ' a Expr < ' a > , count : usize ) -> ( & ' a Expr < ' a > , usize ) {
1438- match expr. kind {
1439- ExprKind :: AddrOf ( BorrowKind :: Ref , _, expr) => f ( expr, count + 1 ) ,
1440- _ => ( expr, count) ,
1441- }
1442- }
1443- f ( expr, 0 )
1526+ let mut count = 0 ;
1527+ let e = peel_hir_expr_while ( expr, |e| match e. kind {
1528+ ExprKind :: AddrOf ( BorrowKind :: Ref , _, e) => {
1529+ count += 1 ;
1530+ Some ( e)
1531+ } ,
1532+ _ => None ,
1533+ } ) ;
1534+ ( e, count)
14441535}
14451536
14461537#[ macro_export]
0 commit comments