|
1 | 1 | use crate::path_to_local_id;
|
| 2 | +use core::ops::ControlFlow; |
2 | 3 | use rustc_hir as hir;
|
3 | 4 | use rustc_hir::def::{DefKind, Res};
|
4 | 5 | use rustc_hir::intravisit::{self, walk_block, walk_expr, Visitor};
|
@@ -370,3 +371,36 @@ pub fn is_expr_unsafe<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> bool {
|
370 | 371 | v.visit_expr(e);
|
371 | 372 | v.is_unsafe
|
372 | 373 | }
|
| 374 | + |
| 375 | +/// Runs the given function for each sub expression producing the final value consumed the parent of |
| 376 | +/// the give expression. |
| 377 | +/// |
| 378 | +/// e.g. for the following expression |
| 379 | +/// ```rust,ignore |
| 380 | +/// if foo { |
| 381 | +/// f(0) |
| 382 | +/// } else { |
| 383 | +/// 1 + 1 |
| 384 | +/// } |
| 385 | +/// ``` |
| 386 | +/// this will pass both `f(0)` and `1+1` to the given function. |
| 387 | +pub fn for_each_value_source<'tcx, B>( |
| 388 | + e: &'tcx Expr<'tcx>, |
| 389 | + f: &mut impl FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B>, |
| 390 | +) -> ControlFlow<B> { |
| 391 | + match e.kind { |
| 392 | + ExprKind::Block(Block { expr: Some(e), .. }, _) => for_each_value_source(e, f), |
| 393 | + ExprKind::Match(_, arms, _) => { |
| 394 | + for arm in arms { |
| 395 | + for_each_value_source(arm.body, f)?; |
| 396 | + } |
| 397 | + ControlFlow::Continue(()) |
| 398 | + }, |
| 399 | + ExprKind::If(_, if_expr, Some(else_expr)) => { |
| 400 | + for_each_value_source(if_expr, f)?; |
| 401 | + for_each_value_source(else_expr, f) |
| 402 | + }, |
| 403 | + ExprKind::DropTemps(e) => for_each_value_source(e, f), |
| 404 | + _ => f(e), |
| 405 | + } |
| 406 | +} |
0 commit comments