@@ -61,10 +61,10 @@ use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
6161use rustc_hir:: def_id:: { DefId , LOCAL_CRATE } ;
6262use rustc_hir:: intravisit:: { self , NestedVisitorMap , Visitor } ;
6363use rustc_hir:: {
64- def, Arm , BindingAnnotation , Block , Body , Constness , CrateItem , Expr , ExprKind , FnDecl , ForeignItem , GenericArgs ,
65- GenericParam , HirId , Impl , ImplItem , ImplItemKind , Item , ItemKind , LangItem , Lifetime , Local , MacroDef ,
66- MatchSource , Node , Param , Pat , PatKind , Path , PathSegment , QPath , Stmt , StructField , TraitItem , TraitItemKind ,
67- TraitRef , TyKind , Variant , Visibility ,
64+ def, Arm , BindingAnnotation , Block , Body , Constness , CrateItem , Destination , Expr , ExprKind , FnDecl , ForeignItem ,
65+ GenericArgs , GenericParam , HirId , Impl , ImplItem , ImplItemKind , Item , ItemKind , LangItem , Lifetime , Local ,
66+ MacroDef , MatchSource , Node , Param , Pat , PatKind , Path , PathSegment , QPath , Stmt , StmtKind , StructField , TraitItem ,
67+ TraitItemKind , TraitRef , TyKind , Variant , Visibility ,
6868} ;
6969use rustc_lint:: { LateContext , Level , Lint , LintContext } ;
7070use rustc_middle:: hir:: exports:: Export ;
@@ -1254,6 +1254,82 @@ pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
12541254 did. map_or ( false , |did| must_use_attr ( & cx. tcx . get_attrs ( did) ) . is_some ( ) )
12551255}
12561256
1257+ pub fn get_expr_use_node ( tcx : TyCtxt < ' tcx > , expr : & Expr < ' _ > ) -> Option < Node < ' tcx > > {
1258+ let map = tcx. hir ( ) ;
1259+ let mut child_id = expr. hir_id ;
1260+ let mut iter = map. parent_iter ( child_id) ;
1261+ loop {
1262+ match iter. next ( ) {
1263+ None => break None ,
1264+ Some ( ( id, Node :: Block ( _) ) ) => child_id = id,
1265+ Some ( ( id, Node :: Arm ( arm) ) ) if arm. body . hir_id == child_id => child_id = id,
1266+ Some ( ( _, Node :: Expr ( expr) ) ) => match expr. kind {
1267+ ExprKind :: Break (
1268+ Destination {
1269+ target_id : Ok ( dest) , ..
1270+ } ,
1271+ _,
1272+ ) => {
1273+ iter = map. parent_iter ( dest) ;
1274+ child_id = dest;
1275+ } ,
1276+ ExprKind :: DropTemps ( _) | ExprKind :: Block ( ..) => child_id = expr. hir_id ,
1277+ ExprKind :: If ( control_expr, ..) | ExprKind :: Match ( control_expr, ..)
1278+ if control_expr. hir_id != child_id =>
1279+ {
1280+ child_id = expr. hir_id
1281+ } ,
1282+ _ => break Some ( Node :: Expr ( expr) ) ,
1283+ } ,
1284+ Some ( ( _, node) ) => break Some ( node) ,
1285+ }
1286+ }
1287+ }
1288+
1289+ pub fn is_expr_used ( tcx : TyCtxt < ' _ > , expr : & Expr < ' _ > ) -> bool {
1290+ !matches ! (
1291+ get_expr_use_node( tcx, expr) ,
1292+ Some ( Node :: Stmt ( Stmt {
1293+ kind: StmtKind :: Expr ( _) | StmtKind :: Semi ( _) ,
1294+ ..
1295+ } ) )
1296+ )
1297+ }
1298+
1299+ pub fn get_expr_use_or_unification_node ( tcx : TyCtxt < ' tcx > , expr : & Expr < ' _ > ) -> Option < Node < ' tcx > > {
1300+ let map = tcx. hir ( ) ;
1301+ let mut child_id = expr. hir_id ;
1302+ let mut iter = map. parent_iter ( child_id) ;
1303+ loop {
1304+ match iter. next ( ) {
1305+ None => break None ,
1306+ Some ( ( id, Node :: Block ( _) ) ) => child_id = id,
1307+ Some ( ( id, Node :: Arm ( arm) ) ) if arm. body . hir_id == child_id => child_id = id,
1308+ Some ( ( _, Node :: Expr ( expr) ) ) => match expr. kind {
1309+ ExprKind :: Match ( _, [ arm] , _) if arm. hir_id == child_id => child_id = expr. hir_id ,
1310+ ExprKind :: Block ( ..) | ExprKind :: DropTemps ( _) => child_id = expr. hir_id ,
1311+ ExprKind :: If ( _, then_expr, None ) if then_expr. hir_id == child_id => break None ,
1312+ _ => break Some ( Node :: Expr ( expr) ) ,
1313+ } ,
1314+ Some ( ( _, node) ) => break Some ( node) ,
1315+ }
1316+ }
1317+ }
1318+
1319+ pub fn is_expr_used_or_unified ( tcx : TyCtxt < ' _ > , expr : & Expr < ' _ > ) -> bool {
1320+ !matches ! (
1321+ get_expr_use_or_unification_node( tcx, expr) ,
1322+ None | Some ( Node :: Stmt ( Stmt {
1323+ kind: StmtKind :: Expr ( _) | StmtKind :: Semi ( _) ,
1324+ ..
1325+ } ) )
1326+ )
1327+ }
1328+
1329+ pub fn is_expr_final_block_expr ( tcx : TyCtxt < ' _ > , expr : & Expr < ' _ > ) -> bool {
1330+ matches ! ( get_parent_node( tcx, expr. hir_id) , Some ( Node :: Block ( ..) ) )
1331+ }
1332+
12571333pub fn is_no_std_crate ( cx : & LateContext < ' _ > ) -> bool {
12581334 cx. tcx . hir ( ) . attrs ( hir:: CRATE_HIR_ID ) . iter ( ) . any ( |attr| {
12591335 if let ast:: AttrKind :: Normal ( ref attr, _) = attr. kind {
@@ -1413,28 +1489,43 @@ pub fn peel_hir_pat_refs(pat: &'a Pat<'a>) -> (&'a Pat<'a>, usize) {
14131489 peel ( pat, 0 )
14141490}
14151491
1492+ /// Peels of expressions while the given closure returns `Some`.
1493+ pub fn peel_hir_expr_while < ' tcx > (
1494+ mut expr : & ' tcx Expr < ' tcx > ,
1495+ mut f : impl FnMut ( & ' tcx Expr < ' tcx > ) -> Option < & ' tcx Expr < ' tcx > > ,
1496+ ) -> & ' tcx Expr < ' tcx > {
1497+ while let Some ( e) = f ( expr) {
1498+ expr = e;
1499+ }
1500+ expr
1501+ }
1502+
14161503/// Peels off up to the given number of references on the expression. Returns the underlying
14171504/// expression and the number of references removed.
14181505pub fn peel_n_hir_expr_refs ( expr : & ' a Expr < ' a > , count : usize ) -> ( & ' a Expr < ' a > , usize ) {
1419- fn f ( expr : & ' a Expr < ' a > , count : usize , target : usize ) -> ( & ' a Expr < ' a > , usize ) {
1420- match expr. kind {
1421- ExprKind :: AddrOf ( _, _, expr) if count != target => f ( expr, count + 1 , target) ,
1422- _ => ( expr, count) ,
1423- }
1424- }
1425- f ( expr, 0 , count)
1506+ let mut remaining = count;
1507+ let e = peel_hir_expr_while ( expr, |e| match e. kind {
1508+ ExprKind :: AddrOf ( BorrowKind :: Ref , _, e) if remaining != 0 => {
1509+ remaining -= 1 ;
1510+ Some ( e)
1511+ } ,
1512+ _ => None ,
1513+ } ) ;
1514+ ( e, count - remaining)
14261515}
14271516
14281517/// Peels off all references on the expression. Returns the underlying expression and the number of
14291518/// references removed.
14301519pub fn peel_hir_expr_refs ( expr : & ' a Expr < ' a > ) -> ( & ' a Expr < ' a > , usize ) {
1431- fn f ( expr : & ' a Expr < ' a > , count : usize ) -> ( & ' a Expr < ' a > , usize ) {
1432- match expr. kind {
1433- ExprKind :: AddrOf ( BorrowKind :: Ref , _, expr) => f ( expr, count + 1 ) ,
1434- _ => ( expr, count) ,
1435- }
1436- }
1437- f ( expr, 0 )
1520+ let mut count = 0 ;
1521+ let e = peel_hir_expr_while ( expr, |e| match e. kind {
1522+ ExprKind :: AddrOf ( BorrowKind :: Ref , _, e) => {
1523+ count += 1 ;
1524+ Some ( e)
1525+ } ,
1526+ _ => None ,
1527+ } ) ;
1528+ ( e, count)
14381529}
14391530
14401531#[ macro_export]
0 commit comments