@@ -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 , Expr , ExprKind , FnDecl , GenericArgs , HirId , Impl , ImplItem ,
64- ImplItemKind , Item , ItemKind , LangItem , MatchSource , Node , Param , Pat , PatKind , Path , PathSegment , QPath ,
65- TraitItem , TraitItemKind , TraitRef , TyKind ,
63+ def, Arm , BindingAnnotation , Block , Body , Constness , Destination , Expr , ExprKind , FnDecl , GenericArgs , HirId , Impl ,
64+ ImplItem , ImplItemKind , Item , ItemKind , LangItem , MatchSource , Node , Param , Pat , PatKind , Path , PathSegment , QPath ,
65+ Stmt , StmtKind , TraitItem , TraitItemKind , TraitRef , TyKind ,
6666} ;
6767use rustc_lint:: { LateContext , Level , Lint , LintContext } ;
6868use rustc_middle:: hir:: exports:: Export ;
@@ -1234,6 +1234,82 @@ pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
12341234 did. map_or ( false , |did| must_use_attr ( & cx. tcx . get_attrs ( did) ) . is_some ( ) )
12351235}
12361236
1237+ pub fn get_expr_use_node ( tcx : TyCtxt < ' tcx > , expr : & Expr < ' _ > ) -> Option < Node < ' tcx > > {
1238+ let map = tcx. hir ( ) ;
1239+ let mut child_id = expr. hir_id ;
1240+ let mut iter = map. parent_iter ( child_id) ;
1241+ loop {
1242+ match iter. next ( ) {
1243+ None => break None ,
1244+ Some ( ( id, Node :: Block ( _) ) ) => child_id = id,
1245+ Some ( ( id, Node :: Arm ( arm) ) ) if arm. body . hir_id == child_id => child_id = id,
1246+ Some ( ( _, Node :: Expr ( expr) ) ) => match expr. kind {
1247+ ExprKind :: Break (
1248+ Destination {
1249+ target_id : Ok ( dest) , ..
1250+ } ,
1251+ _,
1252+ ) => {
1253+ iter = map. parent_iter ( dest) ;
1254+ child_id = dest;
1255+ } ,
1256+ ExprKind :: DropTemps ( _) | ExprKind :: Block ( ..) => child_id = expr. hir_id ,
1257+ ExprKind :: If ( control_expr, ..) | ExprKind :: Match ( control_expr, ..)
1258+ if control_expr. hir_id != child_id =>
1259+ {
1260+ child_id = expr. hir_id
1261+ } ,
1262+ _ => break Some ( Node :: Expr ( expr) ) ,
1263+ } ,
1264+ Some ( ( _, node) ) => break Some ( node) ,
1265+ }
1266+ }
1267+ }
1268+
1269+ pub fn is_expr_used ( tcx : TyCtxt < ' _ > , expr : & Expr < ' _ > ) -> bool {
1270+ !matches ! (
1271+ get_expr_use_node( tcx, expr) ,
1272+ Some ( Node :: Stmt ( Stmt {
1273+ kind: StmtKind :: Expr ( _) | StmtKind :: Semi ( _) ,
1274+ ..
1275+ } ) )
1276+ )
1277+ }
1278+
1279+ pub fn get_expr_use_or_unification_node ( tcx : TyCtxt < ' tcx > , expr : & Expr < ' _ > ) -> Option < Node < ' tcx > > {
1280+ let map = tcx. hir ( ) ;
1281+ let mut child_id = expr. hir_id ;
1282+ let mut iter = map. parent_iter ( child_id) ;
1283+ loop {
1284+ match iter. next ( ) {
1285+ None => break None ,
1286+ Some ( ( id, Node :: Block ( _) ) ) => child_id = id,
1287+ Some ( ( id, Node :: Arm ( arm) ) ) if arm. body . hir_id == child_id => child_id = id,
1288+ Some ( ( _, Node :: Expr ( expr) ) ) => match expr. kind {
1289+ ExprKind :: Match ( _, [ arm] , _) if arm. hir_id == child_id => child_id = expr. hir_id ,
1290+ ExprKind :: Block ( ..) | ExprKind :: DropTemps ( _) => child_id = expr. hir_id ,
1291+ ExprKind :: If ( _, then_expr, None ) if then_expr. hir_id == child_id => break None ,
1292+ _ => break Some ( Node :: Expr ( expr) ) ,
1293+ } ,
1294+ Some ( ( _, node) ) => break Some ( node) ,
1295+ }
1296+ }
1297+ }
1298+
1299+ pub fn is_expr_used_or_unified ( tcx : TyCtxt < ' _ > , expr : & Expr < ' _ > ) -> bool {
1300+ !matches ! (
1301+ get_expr_use_or_unification_node( tcx, expr) ,
1302+ None | Some ( Node :: Stmt ( Stmt {
1303+ kind: StmtKind :: Expr ( _) | StmtKind :: Semi ( _) ,
1304+ ..
1305+ } ) )
1306+ )
1307+ }
1308+
1309+ pub fn is_expr_final_block_expr ( tcx : TyCtxt < ' _ > , expr : & Expr < ' _ > ) -> bool {
1310+ matches ! ( get_parent_node( tcx, expr. hir_id) , Some ( Node :: Block ( ..) ) )
1311+ }
1312+
12371313pub fn is_no_std_crate ( cx : & LateContext < ' _ > ) -> bool {
12381314 cx. tcx . hir ( ) . attrs ( hir:: CRATE_HIR_ID ) . iter ( ) . any ( |attr| {
12391315 if let ast:: AttrKind :: Normal ( ref attr, _) = attr. kind {
@@ -1403,28 +1479,43 @@ pub fn peel_hir_pat_refs(pat: &'a Pat<'a>) -> (&'a Pat<'a>, usize) {
14031479 peel ( pat, 0 )
14041480}
14051481
1482+ /// Peels of expressions while the given closure returns `Some`.
1483+ pub fn peel_hir_expr_while < ' tcx > (
1484+ mut expr : & ' tcx Expr < ' tcx > ,
1485+ mut f : impl FnMut ( & ' tcx Expr < ' tcx > ) -> Option < & ' tcx Expr < ' tcx > > ,
1486+ ) -> & ' tcx Expr < ' tcx > {
1487+ while let Some ( e) = f ( expr) {
1488+ expr = e;
1489+ }
1490+ expr
1491+ }
1492+
14061493/// Peels off up to the given number of references on the expression. Returns the underlying
14071494/// expression and the number of references removed.
14081495pub fn peel_n_hir_expr_refs ( expr : & ' a Expr < ' a > , count : usize ) -> ( & ' a Expr < ' a > , usize ) {
1409- fn f ( expr : & ' a Expr < ' a > , count : usize , target : usize ) -> ( & ' a Expr < ' a > , usize ) {
1410- match expr. kind {
1411- ExprKind :: AddrOf ( _, _, expr) if count != target => f ( expr, count + 1 , target) ,
1412- _ => ( expr, count) ,
1413- }
1414- }
1415- f ( expr, 0 , count)
1496+ let mut remaining = count;
1497+ let e = peel_hir_expr_while ( expr, |e| match e. kind {
1498+ ExprKind :: AddrOf ( BorrowKind :: Ref , _, e) if remaining != 0 => {
1499+ remaining -= 1 ;
1500+ Some ( e)
1501+ } ,
1502+ _ => None ,
1503+ } ) ;
1504+ ( e, count - remaining)
14161505}
14171506
14181507/// Peels off all references on the expression. Returns the underlying expression and the number of
14191508/// references removed.
14201509pub fn peel_hir_expr_refs ( expr : & ' a Expr < ' a > ) -> ( & ' a Expr < ' a > , usize ) {
1421- fn f ( expr : & ' a Expr < ' a > , count : usize ) -> ( & ' a Expr < ' a > , usize ) {
1422- match expr. kind {
1423- ExprKind :: AddrOf ( BorrowKind :: Ref , _, expr) => f ( expr, count + 1 ) ,
1424- _ => ( expr, count) ,
1425- }
1426- }
1427- f ( expr, 0 )
1510+ let mut count = 0 ;
1511+ let e = peel_hir_expr_while ( expr, |e| match e. kind {
1512+ ExprKind :: AddrOf ( BorrowKind :: Ref , _, e) => {
1513+ count += 1 ;
1514+ Some ( e)
1515+ } ,
1516+ _ => None ,
1517+ } ) ;
1518+ ( e, count)
14281519}
14291520
14301521#[ macro_export]
0 commit comments