Skip to content

Commit

Permalink
Add lint to check for slow symbol comparisons
Browse files Browse the repository at this point in the history
  • Loading branch information
GnomedDev committed Oct 13, 2024
1 parent 236751d commit 6b1779b
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 0 deletions.
2 changes: 2 additions & 0 deletions clippy_lints/src/declared_lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ pub static LINTS: &[&crate::LintInfo] = &[
#[cfg(feature = "internal")]
crate::utils::internal_lints::produce_ice::PRODUCE_ICE_INFO,
#[cfg(feature = "internal")]
crate::utils::internal_lints::slow_symbol_comparisons::SLOW_SYMBOL_COMPARISONS_INFO,
#[cfg(feature = "internal")]
crate::utils::internal_lints::unnecessary_def_path::UNNECESSARY_DEF_PATH_INFO,
#[cfg(feature = "internal")]
crate::utils::internal_lints::unsorted_clippy_utils_paths::UNSORTED_CLIPPY_UTILS_PATHS_INFO,
Expand Down
1 change: 1 addition & 0 deletions clippy_lints/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
store.register_late_pass(|_| {
Box::new(utils::internal_lints::almost_standard_lint_formulation::AlmostStandardFormulation::new())
});
store.register_late_pass(|_| Box::new(utils::internal_lints::slow_symbol_comparisons::SlowSymbolComparisons));
}

store.register_late_pass(move |_| Box::new(operators::arithmetic_side_effects::ArithmeticSideEffects::new(conf)));
Expand Down
1 change: 1 addition & 0 deletions clippy_lints/src/utils/internal_lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ pub mod lint_without_lint_pass;
pub mod msrv_attr_impl;
pub mod outer_expn_data_pass;
pub mod produce_ice;
pub mod slow_symbol_comparisons;
pub mod unnecessary_def_path;
pub mod unsorted_clippy_utils_paths;
69 changes: 69 additions & 0 deletions clippy_lints/src/utils/internal_lints/slow_symbol_comparisons.rs
Original file line number Diff line number Diff line change
@@ -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,
);
};
}
}

0 comments on commit 6b1779b

Please sign in to comment.