about summary refs log tree commit diff
path: root/clippy_lints/src/utils/internal_lints
diff options
context:
space:
mode:
authorPhilipp Krones <hello@philkrones.com>2024-11-07 22:31:20 +0100
committerPhilipp Krones <hello@philkrones.com>2024-11-07 22:37:01 +0100
commit6ced8c33c058fa1df65a363abcdc5e2c5828fa66 (patch)
tree86a24d4cb4011e4f95093ed710c7bb35cdd95304 /clippy_lints/src/utils/internal_lints
parent4847c40c8b40cc2a1155204b934f7a3c29178782 (diff)
downloadrust-6ced8c33c058fa1df65a363abcdc5e2c5828fa66.tar.gz
rust-6ced8c33c058fa1df65a363abcdc5e2c5828fa66.zip
Merge commit 'f712eb5cdccd121d0569af12f20e6a0fabe4364d' into clippy-subtree-update
Diffstat (limited to 'clippy_lints/src/utils/internal_lints')
-rw-r--r--clippy_lints/src/utils/internal_lints/collapsible_calls.rs2
-rw-r--r--clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs14
-rw-r--r--clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs2
-rw-r--r--clippy_lints/src/utils/internal_lints/slow_symbol_comparisons.rs69
4 files changed, 77 insertions, 10 deletions
diff --git a/clippy_lints/src/utils/internal_lints/collapsible_calls.rs b/clippy_lints/src/utils/internal_lints/collapsible_calls.rs
index a3f9abe4f96..eaeb754a23f 100644
--- a/clippy_lints/src/utils/internal_lints/collapsible_calls.rs
+++ b/clippy_lints/src/utils/internal_lints/collapsible_calls.rs
@@ -79,7 +79,7 @@ impl<'tcx> LateLintPass<'tcx> for CollapsibleCalls {
 
         if let ExprKind::Call(func, [call_cx, call_lint, call_sp, call_msg, call_f]) = expr.kind
             && is_expr_path_def_path(cx, func, &["clippy_utils", "diagnostics", "span_lint_and_then"])
-            && let ExprKind::Closure(&Closure { body, .. }) = &call_f.kind
+            && let ExprKind::Closure(&Closure { body, .. }) = call_f.kind
             && let body = cx.tcx.hir().body(body)
             && let only_expr = peel_blocks_with_stmt(body.value)
             && let ExprKind::MethodCall(ps, recv, span_call_args, _) = &only_expr.kind
diff --git a/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs b/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
index 51235de9f29..af38e066559 100644
--- a/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
+++ b/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
@@ -21,7 +21,7 @@ declare_clippy_lint! {
     ///
     /// ### Why is this bad?
     /// The compiler only knows lints via a `LintPass`. Without
-    /// putting a lint to a `LintPass::get_lints()`'s return, the compiler will not
+    /// putting a lint to a `LintPass::lint_vec()`'s return, the compiler will not
     /// know the name of the lint.
     ///
     /// ### Known problems
@@ -123,7 +123,7 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
                     .expect("lints must have a description field");
 
                 if let ExprKind::Lit(Spanned {
-                    node: LitKind::Str(ref sym, _),
+                    node: LitKind::Str(sym, _),
                     ..
                 }) = field.expr.kind
                 {
@@ -159,8 +159,8 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
                 let body = cx.tcx.hir().body_owned_by(
                     impl_item_refs
                         .iter()
-                        .find(|iiref| iiref.ident.as_str() == "get_lints")
-                        .expect("LintPass needs to implement get_lints")
+                        .find(|iiref| iiref.ident.as_str() == "lint_vec")
+                        .expect("LintPass needs to implement lint_vec")
                         .id
                         .owner_id
                         .def_id,
@@ -218,9 +218,7 @@ pub(super) fn is_lint_ref_type(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool {
 
 fn check_invalid_clippy_version_attribute(cx: &LateContext<'_>, item: &'_ Item<'_>) {
     if let Some(value) = extract_clippy_version_value(cx, item) {
-        // The `sym!` macro doesn't work as it only expects a single token.
-        // It's better to keep it this way and have a direct `Symbol::intern` call here.
-        if value == Symbol::intern("pre 1.29.0") {
+        if value.as_str() == "pre 1.29.0" {
             return;
         }
 
@@ -251,7 +249,7 @@ fn check_invalid_clippy_version_attribute(cx: &LateContext<'_>, item: &'_ Item<'
 pub(super) fn extract_clippy_version_value(cx: &LateContext<'_>, item: &'_ Item<'_>) -> Option<Symbol> {
     let attrs = cx.tcx.hir().attrs(item.hir_id());
     attrs.iter().find_map(|attr| {
-        if let ast::AttrKind::Normal(ref attr_kind) = &attr.kind
+        if let ast::AttrKind::Normal(attr_kind) = &attr.kind
             // Identify attribute
             && let [tool_name, attr_name] = &attr_kind.item.path.segments[..]
             && tool_name.ident.name == sym::clippy
diff --git a/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs b/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs
index 63fcbd61528..68692246153 100644
--- a/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs
+++ b/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs
@@ -42,7 +42,7 @@ impl LateLintPass<'_> for MsrvAttrImpl {
                     .filter(|t| matches!(t.unpack(), GenericArgKind::Type(_)))
                     .any(|t| match_type(cx, t.expect_ty(), &paths::MSRV))
             })
-            && !items.iter().any(|item| item.ident.name == sym!(check_attributes))
+            && !items.iter().any(|item| item.ident.name.as_str() == "check_attributes")
         {
             let context = if is_late_pass { "LateContext" } else { "EarlyContext" };
             let lint_pass = if is_late_pass { "LateLintPass" } else { "EarlyLintPass" };
diff --git a/clippy_lints/src/utils/internal_lints/slow_symbol_comparisons.rs b/clippy_lints/src/utils/internal_lints/slow_symbol_comparisons.rs
new file mode 100644
index 00000000000..3742be0e103
--- /dev/null
+++ b/clippy_lints/src/utils/internal_lints/slow_symbol_comparisons.rs
@@ -0,0 +1,69 @@
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::ty::match_type;
+use clippy_utils::{match_function_call, paths};
+use rustc_errors::Applicability;
+use rustc_hir::{BinOpKind, Expr, ExprKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::declare_lint_pass;
+use rustc_span::Span;
+
+declare_clippy_lint! {
+    /// ### What it does
+    ///
+    /// Detects symbol comparision using `Symbol::intern`.
+    ///
+    /// ### Why is this bad?
+    ///
+    /// Comparision via `Symbol::as_str()` is faster if the interned symbols are not reused.
+    ///
+    /// ### Example
+    ///
+    /// None, see suggestion.
+    pub SLOW_SYMBOL_COMPARISONS,
+    internal,
+    "detects slow comparisions of symbol"
+}
+
+declare_lint_pass!(SlowSymbolComparisons => [SLOW_SYMBOL_COMPARISONS]);
+
+fn check_slow_comparison<'tcx>(
+    cx: &LateContext<'tcx>,
+    op1: &'tcx Expr<'tcx>,
+    op2: &'tcx Expr<'tcx>,
+) -> Option<(Span, String)> {
+    if match_type(cx, cx.typeck_results().expr_ty(op1), &paths::SYMBOL)
+        && let Some([symbol_name_expr]) = match_function_call(cx, op2, &paths::SYMBOL_INTERN)
+        && let Some(Constant::Str(symbol_name)) = ConstEvalCtxt::new(cx).eval_simple(symbol_name_expr)
+    {
+        Some((op1.span, symbol_name))
+    } else {
+        None
+    }
+}
+
+impl<'tcx> LateLintPass<'tcx> for SlowSymbolComparisons {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
+        if let ExprKind::Binary(op, left, right) = expr.kind
+            && (op.node == BinOpKind::Eq || op.node == BinOpKind::Ne)
+            && let Some((symbol_span, symbol_name)) =
+                check_slow_comparison(cx, left, right).or_else(|| check_slow_comparison(cx, right, left))
+        {
+            let mut applicability = Applicability::MachineApplicable;
+            span_lint_and_sugg(
+                cx,
+                SLOW_SYMBOL_COMPARISONS,
+                expr.span,
+                "comparing `Symbol` via `Symbol::intern`",
+                "use `Symbol::as_str` and check the string instead",
+                format!(
+                    "{}.as_str() {} \"{symbol_name}\"",
+                    snippet_with_applicability(cx, symbol_span, "symbol", &mut applicability),
+                    op.node.as_str()
+                ),
+                applicability,
+            );
+        };
+    }
+}