Skip to content

Commit df8fbc3

Browse files
committed
Add lint to check for slow symbol comparisons
1 parent 05f3793 commit df8fbc3

File tree

4 files changed

+63
-0
lines changed

4 files changed

+63
-0
lines changed

clippy_lints/src/declared_lints.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ pub static LINTS: &[&crate::LintInfo] = &[
2828
#[cfg(feature = "internal")]
2929
crate::utils::internal_lints::produce_ice::PRODUCE_ICE_INFO,
3030
#[cfg(feature = "internal")]
31+
crate::utils::internal_lints::slow_symbol_comparisons::SLOW_SYMBOL_COMPARISONS_INFO,
32+
#[cfg(feature = "internal")]
3133
crate::utils::internal_lints::unnecessary_def_path::UNNECESSARY_DEF_PATH_INFO,
3234
#[cfg(feature = "internal")]
3335
crate::utils::internal_lints::unsorted_clippy_utils_paths::UNSORTED_CLIPPY_UTILS_PATHS_INFO,

clippy_lints/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
601601
store.register_late_pass(|_| {
602602
Box::new(utils::internal_lints::almost_standard_lint_formulation::AlmostStandardFormulation::new())
603603
});
604+
store.register_late_pass(|_| Box::new(utils::internal_lints::slow_symbol_comparisons::SlowSymbolComparisons));
604605
}
605606

606607
store.register_late_pass(move |_| Box::new(operators::arithmetic_side_effects::ArithmeticSideEffects::new(conf)));

clippy_lints/src/utils/internal_lints.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ pub mod lint_without_lint_pass;
66
pub mod msrv_attr_impl;
77
pub mod outer_expn_data_pass;
88
pub mod produce_ice;
9+
pub mod slow_symbol_comparisons;
910
pub mod unnecessary_def_path;
1011
pub mod unsorted_clippy_utils_paths;
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
use clippy_utils::consts::{ConstEvalCtxt, Constant};
2+
use clippy_utils::diagnostics::span_lint_and_sugg;
3+
use clippy_utils::source::snippet_with_applicability;
4+
use clippy_utils::ty::match_type;
5+
use clippy_utils::{match_function_call, paths};
6+
use rustc_errors::Applicability;
7+
use rustc_hir::{BinOpKind, Expr, ExprKind};
8+
use rustc_lint::{LateContext, LateLintPass};
9+
use rustc_session::declare_lint_pass;
10+
11+
declare_clippy_lint! {
12+
/// ### What it does
13+
///
14+
/// Detects symbol comparision using `Symbol::intern`.
15+
///
16+
/// ### Why is this bad?
17+
///
18+
/// Comparision via `Symbol::as_str()` is faster.
19+
///
20+
/// ### Example
21+
/// ```no_run
22+
/// meth_name == sym!(push)
23+
/// ```
24+
/// Use instead:
25+
/// ```no_run
26+
/// meth_name.as_str() == "push"
27+
/// ```
28+
#[clippy::version = "1.83.0"]
29+
pub SLOW_SYMBOL_COMPARISONS,
30+
internal,
31+
"detects slow comparisions of symbol"
32+
}
33+
34+
declare_lint_pass!(SlowSymbolComparisons => [SLOW_SYMBOL_COMPARISONS]);
35+
36+
impl<'tcx> LateLintPass<'tcx> for SlowSymbolComparisons {
37+
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
38+
if let ExprKind::Binary(op, left, right) = expr.kind
39+
&& op.node == BinOpKind::Eq
40+
&& match_type(cx, cx.typeck_results().expr_ty(left), &paths::SYMBOL)
41+
&& let Some([symbol_name_expr]) = match_function_call(cx, right, &paths::SYMBOL_INTERN)
42+
&& let Some(Constant::Str(symbol_name)) = ConstEvalCtxt::new(cx).eval_simple(symbol_name_expr)
43+
{
44+
let mut applicability = Applicability::MachineApplicable;
45+
span_lint_and_sugg(
46+
cx,
47+
SLOW_SYMBOL_COMPARISONS,
48+
expr.span,
49+
"comparing `Symbol` via `Symbol::intern`",
50+
"use `Symbol::as_str` and check the string instead",
51+
format!(
52+
"{}.as_str() == \"{symbol_name}\"",
53+
snippet_with_applicability(cx, left.span, "symbol", &mut applicability)
54+
),
55+
applicability,
56+
);
57+
};
58+
}
59+
}

0 commit comments

Comments
 (0)