diff options
| author | hamidreza kalbasi <hamidrezakalbasi@protonmail.com> | 2021-07-29 16:38:17 +0430 |
|---|---|---|
| committer | hamidreza kalbasi <hamidrezakalbasi@protonmail.com> | 2021-08-09 02:15:10 +0430 |
| commit | 6d36d1a835370a01cbee58aba038ea0bd712c82b (patch) | |
| tree | a24834d33f14fc62ab83300853a8ae9a2519178e /clippy_utils | |
| parent | dbb10b87f8e4365298ed33a6ed96bffe66a1951e (diff) | |
| download | rust-6d36d1a835370a01cbee58aba038ea0bd712c82b.tar.gz rust-6d36d1a835370a01cbee58aba038ea0bd712c82b.zip | |
merge XOR_SWAP with MANUAL_SWAP
Diffstat (limited to 'clippy_utils')
| -rw-r--r-- | clippy_utils/src/lib.rs | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 59f878f8b20..e930338270c 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -558,6 +558,54 @@ pub fn trait_ref_of_method<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Optio None } +/// This method will return tuple of projection stack and root of the expression, +/// used in `can_mut_borrow_both`. +/// +/// For example, if `e` represents the `v[0].a.b[x]` +/// this method will return a tuple, composed of a `Vec` +/// containing the `Expr`s for `v[0], v[0].a, v[0].a.b, v[0].a.b[x]` +/// and a `Expr` for root of them, `v` +fn projection_stack<'a, 'hir>(mut e: &'a Expr<'hir>) -> (Vec<&'a Expr<'hir>>, &'a Expr<'hir>) { + let mut result = vec![]; + let root = loop { + match e.kind { + ExprKind::Index(ep, _) | ExprKind::Field(ep, _) => { + result.push(e); + e = ep; + }, + _ => break e, + }; + }; + result.reverse(); + (result, root) +} + +/// Checks if two expressions can be mutably borrowed simultaneously +/// and they aren't dependent on borrowing same thing twice +pub fn can_mut_borrow_both(cx: &LateContext<'_>, e1: &Expr<'_>, e2: &Expr<'_>) -> bool { + let (s1, r1) = projection_stack(e1); + let (s2, r2) = projection_stack(e2); + if !eq_expr_value(cx, r1, r2) { + return true; + } + for (x1, x2) in s1.iter().zip(s2.iter()) { + match (&x1.kind, &x2.kind) { + (ExprKind::Field(_, i1), ExprKind::Field(_, i2)) => { + if i1 != i2 { + return true; + } + }, + (ExprKind::Index(_, i1), ExprKind::Index(_, i2)) => { + if !eq_expr_value(cx, i1, i2) { + return false; + } + }, + _ => return false, + } + } + false +} + /// Checks if the top level expression can be moved into a closure as is. pub fn can_move_expr_to_closure_no_visit(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, jump_targets: &[HirId]) -> bool { match expr.kind { |
