about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/manual_is_power_of_two.rs20
-rw-r--r--tests/ui/manual_is_power_of_two.fixed2
-rw-r--r--tests/ui/manual_is_power_of_two.rs2
-rw-r--r--tests/ui/manual_is_power_of_two.stderr20
4 files changed, 29 insertions, 15 deletions
diff --git a/clippy_lints/src/manual_is_power_of_two.rs b/clippy_lints/src/manual_is_power_of_two.rs
index b9866ff9ffb..b4cd988329d 100644
--- a/clippy_lints/src/manual_is_power_of_two.rs
+++ b/clippy_lints/src/manual_is_power_of_two.rs
@@ -2,9 +2,10 @@ use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::sugg::Sugg;
+use clippy_utils::ty::ty_from_hir_ty;
 use clippy_utils::{SpanlessEq, is_in_const_context, is_integer_literal};
 use rustc_errors::Applicability;
-use rustc_hir::{BinOpKind, Expr, ExprKind};
+use rustc_hir::{BinOpKind, Expr, ExprKind, QPath};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::impl_lint_pass;
@@ -90,16 +91,19 @@ impl<'tcx> LateLintPass<'tcx> for ManualIsPowerOfTwo {
     }
 }
 
-/// Return the unsigned integer receiver of `.count_ones()`
+/// Return the unsigned integer receiver of `.count_ones()` or the argument of
+/// `<int-type>::count_ones(…)`.
 fn count_ones_receiver<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> {
-    if let ExprKind::MethodCall(method_name, receiver, [], _) = expr.kind
-        && method_name.ident.as_str() == "count_ones"
-        && matches!(cx.typeck_results().expr_ty_adjusted(receiver).kind(), ty::Uint(_))
+    let (method, ty, receiver) = if let ExprKind::MethodCall(method_name, receiver, [], _) = expr.kind {
+        (method_name, cx.typeck_results().expr_ty_adjusted(receiver), receiver)
+    } else if let ExprKind::Call(func, [arg]) = expr.kind
+        && let ExprKind::Path(QPath::TypeRelative(ty, func_name)) = func.kind
     {
-        Some(receiver)
+        (func_name, ty_from_hir_ty(cx, ty), arg)
     } else {
-        None
-    }
+        return None;
+    };
+    (method.ident.as_str() == "count_ones" && matches!(ty.kind(), ty::Uint(_))).then_some(receiver)
 }
 
 /// Return `greater` if `smaller == greater - 1`
diff --git a/tests/ui/manual_is_power_of_two.fixed b/tests/ui/manual_is_power_of_two.fixed
index 216db87a09b..8a1ab785dfb 100644
--- a/tests/ui/manual_is_power_of_two.fixed
+++ b/tests/ui/manual_is_power_of_two.fixed
@@ -20,6 +20,8 @@ fn main() {
     //~^ manual_is_power_of_two
     let _ = a.is_power_of_two();
     //~^ manual_is_power_of_two
+    let _ = a.is_power_of_two();
+    //~^ manual_is_power_of_two
 
     // Test different orders of expression
     let _ = a.is_power_of_two();
diff --git a/tests/ui/manual_is_power_of_two.rs b/tests/ui/manual_is_power_of_two.rs
index 2ff29c37f3e..57a3b05e033 100644
--- a/tests/ui/manual_is_power_of_two.rs
+++ b/tests/ui/manual_is_power_of_two.rs
@@ -18,6 +18,8 @@ fn main() {
 
     let _ = a.count_ones() == 1;
     //~^ manual_is_power_of_two
+    let _ = u64::count_ones(a) == 1;
+    //~^ manual_is_power_of_two
     let _ = a & (a - 1) == 0;
     //~^ manual_is_power_of_two
 
diff --git a/tests/ui/manual_is_power_of_two.stderr b/tests/ui/manual_is_power_of_two.stderr
index 043991f8ae8..5781a093d5f 100644
--- a/tests/ui/manual_is_power_of_two.stderr
+++ b/tests/ui/manual_is_power_of_two.stderr
@@ -10,44 +10,50 @@ LL |     let _ = a.count_ones() == 1;
 error: manually reimplementing `is_power_of_two`
   --> tests/ui/manual_is_power_of_two.rs:21:13
    |
+LL |     let _ = u64::count_ones(a) == 1;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()`
+
+error: manually reimplementing `is_power_of_two`
+  --> tests/ui/manual_is_power_of_two.rs:23:13
+   |
 LL |     let _ = a & (a - 1) == 0;
    |             ^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()`
 
 error: manually reimplementing `is_power_of_two`
-  --> tests/ui/manual_is_power_of_two.rs:25:13
+  --> tests/ui/manual_is_power_of_two.rs:27:13
    |
 LL |     let _ = 1 == a.count_ones();
    |             ^^^^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()`
 
 error: manually reimplementing `is_power_of_two`
-  --> tests/ui/manual_is_power_of_two.rs:27:13
+  --> tests/ui/manual_is_power_of_two.rs:29:13
    |
 LL |     let _ = (a - 1) & a == 0;
    |             ^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()`
 
 error: manually reimplementing `is_power_of_two`
-  --> tests/ui/manual_is_power_of_two.rs:29:13
+  --> tests/ui/manual_is_power_of_two.rs:31:13
    |
 LL |     let _ = 0 == a & (a - 1);
    |             ^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()`
 
 error: manually reimplementing `is_power_of_two`
-  --> tests/ui/manual_is_power_of_two.rs:31:13
+  --> tests/ui/manual_is_power_of_two.rs:33:13
    |
 LL |     let _ = 0 == (a - 1) & a;
    |             ^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()`
 
 error: manually reimplementing `is_power_of_two`
-  --> tests/ui/manual_is_power_of_two.rs:41:13
+  --> tests/ui/manual_is_power_of_two.rs:43:13
    |
 LL |     let _ = i as u32 & (i as u32 - 1) == 0;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `(i as u32).is_power_of_two()`
 
 error: manually reimplementing `is_power_of_two`
-  --> tests/ui/manual_is_power_of_two.rs:56:5
+  --> tests/ui/manual_is_power_of_two.rs:58:5
    |
 LL |     a & (a - 1) == 0
    |     ^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()`
 
-error: aborting due to 8 previous errors
+error: aborting due to 9 previous errors