Skip to content

Commit b87e90b

Browse files
authored
Use interned symbols instead of strings in more places (#14840)
This patch series makes heavy use of interned symbols when matching against known method names: - the first commit reorders the current list of symbols in `clippy_utils::sym` - the second commit adds symbol reordering and order checking to `clippy dev fmt` / `clippy dev fmt --check` - the third commit converts many uses of string matching during linting to symbols matching The symbols are kept as-is (not rendered as strings) as much as possible to avoid needing locking the interner as much as possible. Static strings have been kept when they are only used when emitting a diagnostic, as there is no benefit in using interned strings for de-interning them right after. changelog: none r? @Alexendoo
2 parents d4e7e5b + e16801e commit b87e90b

File tree

87 files changed

+946
-703
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

87 files changed

+946
-703
lines changed

clippy_dev/src/fmt.rs

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1-
use crate::utils::{ClippyInfo, ErrAction, UpdateMode, panic_action, run_with_args_split, run_with_output};
1+
use crate::utils::{
2+
ClippyInfo, ErrAction, FileUpdater, UpdateMode, UpdateStatus, panic_action, run_with_args_split, run_with_output,
3+
};
24
use itertools::Itertools;
35
use rustc_lexer::{TokenKind, tokenize};
6+
use std::fmt::Write;
47
use std::fs;
58
use std::io::{self, Read};
69
use std::ops::ControlFlow;
@@ -225,6 +228,38 @@ fn fmt_conf(check: bool) -> Result<(), Error> {
225228
Ok(())
226229
}
227230

231+
/// Format the symbols list
232+
fn fmt_syms(update_mode: UpdateMode) {
233+
FileUpdater::default().update_file_checked(
234+
"cargo dev fmt",
235+
update_mode,
236+
"clippy_utils/src/sym.rs",
237+
&mut |_, text: &str, new_text: &mut String| {
238+
let (pre, conf) = text.split_once("generate! {\n").expect("can't find generate! call");
239+
let (conf, post) = conf.split_once("\n}\n").expect("can't find end of generate! call");
240+
let mut lines = conf
241+
.lines()
242+
.map(|line| {
243+
let line = line.trim();
244+
line.strip_suffix(',').unwrap_or(line).trim_end()
245+
})
246+
.collect::<Vec<_>>();
247+
lines.sort_unstable();
248+
write!(
249+
new_text,
250+
"{pre}generate! {{\n {},\n}}\n{post}",
251+
lines.join(",\n "),
252+
)
253+
.unwrap();
254+
if text == new_text {
255+
UpdateStatus::Unchanged
256+
} else {
257+
UpdateStatus::Changed
258+
}
259+
},
260+
);
261+
}
262+
228263
fn run_rustfmt(clippy: &ClippyInfo, update_mode: UpdateMode) {
229264
let mut rustfmt_path = String::from_utf8(run_with_output(
230265
"rustup which rustfmt",
@@ -337,7 +372,7 @@ pub fn run(clippy: &ClippyInfo, update_mode: UpdateMode) {
337372
return;
338373
}
339374
run_rustfmt(clippy, update_mode);
340-
375+
fmt_syms(update_mode);
341376
if let Err(e) = fmt_conf(update_mode.is_check()) {
342377
e.display();
343378
process::exit(1);

clippy_lints/src/assertions_on_result_states.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,13 @@ use clippy_utils::macros::{PanicExpn, find_assert_args, root_macro_call_first_no
33
use clippy_utils::source::snippet_with_context;
44
use clippy_utils::ty::{has_debug_impl, is_copy, is_type_diagnostic_item};
55
use clippy_utils::usage::local_used_after_expr;
6-
use clippy_utils::{is_expr_final_block_expr, path_res};
6+
use clippy_utils::{is_expr_final_block_expr, path_res, sym};
77
use rustc_errors::Applicability;
88
use rustc_hir::def::Res;
99
use rustc_hir::{Expr, ExprKind};
1010
use rustc_lint::{LateContext, LateLintPass};
1111
use rustc_middle::ty::{self, Ty};
1212
use rustc_session::declare_lint_pass;
13-
use rustc_span::sym;
1413

1514
declare_clippy_lint! {
1615
/// ### What it does
@@ -68,11 +67,11 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnResultStates {
6867
return;
6968
}
7069
}
71-
let (message, replacement) = match method_segment.ident.as_str() {
72-
"is_ok" if type_suitable_to_unwrap(cx, args.type_at(1)) => {
70+
let (message, replacement) = match method_segment.ident.name {
71+
sym::is_ok if type_suitable_to_unwrap(cx, args.type_at(1)) => {
7372
("called `assert!` with `Result::is_ok`", "unwrap")
7473
},
75-
"is_err" if type_suitable_to_unwrap(cx, args.type_at(0)) => {
74+
sym::is_err if type_suitable_to_unwrap(cx, args.type_at(0)) => {
7675
("called `assert!` with `Result::is_err`", "unwrap_err")
7776
},
7877
_ => return,

clippy_lints/src/casts/cast_possible_truncation.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,15 @@ fn apply_reductions(cx: &LateContext<'_>, nbits: u64, expr: &Expr<'_>, signed: b
5656
if signed {
5757
return nbits;
5858
}
59-
let max_bits = if method.ident.as_str() == "min" {
59+
let max_bits = if method.ident.name == sym::min {
6060
get_constant_bits(cx, right)
6161
} else {
6262
None
6363
};
6464
apply_reductions(cx, nbits, left, signed).min(max_bits.unwrap_or(u64::MAX))
6565
},
6666
ExprKind::MethodCall(method, _, [lo, hi], _) => {
67-
if method.ident.as_str() == "clamp"
67+
if method.ident.name == sym::clamp
6868
//FIXME: make this a diagnostic item
6969
&& let (Some(lo_bits), Some(hi_bits)) = (get_constant_bits(cx, lo), get_constant_bits(cx, hi))
7070
{

clippy_lints/src/casts/cast_sign_loss.rs

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@ use std::ops::ControlFlow;
44
use clippy_utils::consts::{ConstEvalCtxt, Constant};
55
use clippy_utils::diagnostics::span_lint;
66
use clippy_utils::visitors::{Descend, for_each_expr_without_closures};
7-
use clippy_utils::{method_chain_args, sext};
7+
use clippy_utils::{method_chain_args, sext, sym};
88
use rustc_hir::{BinOpKind, Expr, ExprKind};
99
use rustc_lint::LateContext;
1010
use rustc_middle::ty::{self, Ty};
11+
use rustc_span::Symbol;
1112

1213
use super::CAST_SIGN_LOSS;
1314

@@ -16,24 +17,24 @@ use super::CAST_SIGN_LOSS;
1617
///
1718
/// Methods that can overflow and return a negative value must not be included in this list,
1819
/// because casting their return values can still result in sign loss.
19-
const METHODS_RET_POSITIVE: &[&str] = &[
20-
"checked_abs",
21-
"saturating_abs",
22-
"isqrt",
23-
"checked_isqrt",
24-
"rem_euclid",
25-
"checked_rem_euclid",
26-
"wrapping_rem_euclid",
20+
const METHODS_RET_POSITIVE: &[Symbol] = &[
21+
sym::checked_abs,
22+
sym::saturating_abs,
23+
sym::isqrt,
24+
sym::checked_isqrt,
25+
sym::rem_euclid,
26+
sym::checked_rem_euclid,
27+
sym::wrapping_rem_euclid,
2728
];
2829

2930
/// A list of methods that act like `pow()`. See `pow_call_result_sign()` for details.
3031
///
3132
/// Methods that can overflow and return a negative value must not be included in this list,
3233
/// because casting their return values can still result in sign loss.
33-
const METHODS_POW: &[&str] = &["pow", "saturating_pow", "checked_pow"];
34+
const METHODS_POW: &[Symbol] = &[sym::pow, sym::saturating_pow, sym::checked_pow];
3435

3536
/// A list of methods that act like `unwrap()`, and don't change the sign of the inner value.
36-
const METHODS_UNWRAP: &[&str] = &["unwrap", "unwrap_unchecked", "expect", "into_ok"];
37+
const METHODS_UNWRAP: &[Symbol] = &[sym::unwrap, sym::unwrap_unchecked, sym::expect, sym::into_ok];
3738

3839
pub(super) fn check<'cx>(
3940
cx: &LateContext<'cx>,
@@ -129,7 +130,7 @@ fn expr_sign<'cx, 'tcx>(cx: &LateContext<'cx>, mut expr: &'tcx Expr<'tcx>, ty: i
129130

130131
// Calling on methods that always return non-negative values.
131132
if let ExprKind::MethodCall(path, caller, args, ..) = expr.kind {
132-
let mut method_name = path.ident.name.as_str();
133+
let mut method_name = path.ident.name;
133134

134135
// Peel unwrap(), expect(), etc.
135136
while let Some(&found_name) = METHODS_UNWRAP.iter().find(|&name| &method_name == name)
@@ -138,7 +139,7 @@ fn expr_sign<'cx, 'tcx>(cx: &LateContext<'cx>, mut expr: &'tcx Expr<'tcx>, ty: i
138139
{
139140
// The original type has changed, but we can't use `ty` here anyway, because it has been
140141
// moved.
141-
method_name = inner_path.ident.name.as_str();
142+
method_name = inner_path.ident.name;
142143
expr = recv;
143144
}
144145

clippy_lints/src/casts/confusing_method_to_numeric_cast.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
use clippy_utils::diagnostics::span_lint_and_then;
22
use clippy_utils::source::snippet_with_applicability;
3+
use clippy_utils::sym;
34
use rustc_errors::Applicability;
45
use rustc_hir::Expr;
56
use rustc_lint::LateContext;
67
use rustc_middle::ty::{self, GenericArg, Ty};
8+
use rustc_span::Symbol;
79
use rustc_span::def_id::DefId;
8-
use rustc_span::{Symbol, sym};
910

1011
use super::CONFUSING_METHOD_TO_NUMERIC_CAST;
1112

@@ -25,7 +26,6 @@ fn get_const_name_and_ty_name(
2526
method_def_id: DefId,
2627
generics: &[GenericArg<'_>],
2728
) -> Option<(&'static str, &'static str)> {
28-
let method_name = method_name.as_str();
2929
let diagnostic_name = cx.tcx.get_diagnostic_name(method_def_id);
3030

3131
let ty_name = if diagnostic_name.is_some_and(|diag| diag == sym::cmp_ord_min || diag == sym::cmp_ord_max) {
@@ -39,14 +39,21 @@ fn get_const_name_and_ty_name(
3939
}
4040
} else if let Some(impl_id) = cx.tcx.impl_of_method(method_def_id)
4141
&& let Some(ty_name) = get_primitive_ty_name(cx.tcx.type_of(impl_id).instantiate_identity())
42-
&& ["min", "max", "minimum", "maximum", "min_value", "max_value"].contains(&method_name)
42+
&& matches!(
43+
method_name,
44+
sym::min | sym::max | sym::minimum | sym::maximum | sym::min_value | sym::max_value
45+
)
4346
{
4447
ty_name
4548
} else {
4649
return None;
4750
};
4851

49-
let const_name = if method_name.starts_with("max") { "MAX" } else { "MIN" };
52+
let const_name = if matches!(method_name, sym::max | sym::maximum | sym::max_value) {
53+
"MAX"
54+
} else {
55+
"MIN"
56+
};
5057
Some((const_name, ty_name))
5158
}
5259

clippy_lints/src/casts/ptr_cast_constness.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
use clippy_utils::diagnostics::span_lint_and_sugg;
22
use clippy_utils::msrvs::{self, Msrv};
3-
use clippy_utils::std_or_core;
43
use clippy_utils::sugg::Sugg;
4+
use clippy_utils::{std_or_core, sym};
55
use rustc_errors::Applicability;
66
use rustc_hir::{Expr, ExprKind, Mutability, QPath};
77
use rustc_lint::LateContext;
88
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
9-
use rustc_span::sym;
109

1110
use super::PTR_CAST_CONSTNESS;
1211

@@ -78,9 +77,9 @@ pub(super) fn check_null_ptr_cast_method(cx: &LateContext<'_>, expr: &Expr<'_>)
7877
&& let ExprKind::Call(func, []) = cast_expr.kind
7978
&& let ExprKind::Path(QPath::Resolved(None, path)) = func.kind
8079
&& let Some(defid) = path.res.opt_def_id()
81-
&& let method = match (cx.tcx.get_diagnostic_name(defid), method.ident.as_str()) {
82-
(Some(sym::ptr_null), "cast_mut") => "null_mut",
83-
(Some(sym::ptr_null_mut), "cast_const") => "null",
80+
&& let method = match (cx.tcx.get_diagnostic_name(defid), method.ident.name) {
81+
(Some(sym::ptr_null), sym::cast_mut) => "null_mut",
82+
(Some(sym::ptr_null_mut), sym::cast_const) => "null",
8483
_ => return,
8584
}
8685
&& let Some(prefix) = std_or_core(cx)

clippy_lints/src/cognitive_complexity.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@ use clippy_utils::diagnostics::span_lint_and_help;
33
use clippy_utils::source::{IntoSpan, SpanRangeExt};
44
use clippy_utils::ty::is_type_diagnostic_item;
55
use clippy_utils::visitors::for_each_expr_without_closures;
6-
use clippy_utils::{LimitStack, get_async_fn_body, is_async_fn};
6+
use clippy_utils::{LimitStack, get_async_fn_body, is_async_fn, sym};
77
use core::ops::ControlFlow;
88
use rustc_hir::intravisit::FnKind;
99
use rustc_hir::{Attribute, Body, Expr, ExprKind, FnDecl};
1010
use rustc_lint::{LateContext, LateLintPass, LintContext};
1111
use rustc_session::impl_lint_pass;
12+
use rustc_span::Span;
1213
use rustc_span::def_id::LocalDefId;
13-
use rustc_span::{Span, sym};
1414

1515
declare_clippy_lint! {
1616
/// ### What it does
@@ -157,9 +157,9 @@ impl<'tcx> LateLintPass<'tcx> for CognitiveComplexity {
157157
}
158158

159159
fn check_attributes(&mut self, cx: &LateContext<'tcx>, attrs: &'tcx [Attribute]) {
160-
self.limit.push_attrs(cx.sess(), attrs, "cognitive_complexity");
160+
self.limit.push_attrs(cx.sess(), attrs, sym::cognitive_complexity);
161161
}
162162
fn check_attributes_post(&mut self, cx: &LateContext<'tcx>, attrs: &'tcx [Attribute]) {
163-
self.limit.pop_attrs(cx.sess(), attrs, "cognitive_complexity");
163+
self.limit.pop_attrs(cx.sess(), attrs, sym::cognitive_complexity);
164164
}
165165
}

clippy_lints/src/doc/missing_headers.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,8 @@ fn find_panic(cx: &LateContext<'_>, body_id: BodyId) -> Option<Span> {
113113
}
114114

115115
// check for `unwrap` and `expect` for both `Option` and `Result`
116-
if let Some(arglists) = method_chain_args(expr, &["unwrap"]).or_else(|| method_chain_args(expr, &["expect"]))
116+
if let Some(arglists) =
117+
method_chain_args(expr, &[sym::unwrap]).or_else(|| method_chain_args(expr, &[sym::expect]))
117118
&& let receiver_ty = typeck.expr_ty(arglists[0].0).peel_refs()
118119
&& matches!(
119120
get_type_diagnostic_name(cx, receiver_ty),

clippy_lints/src/explicit_write.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
use clippy_utils::diagnostics::span_lint_and_sugg;
22
use clippy_utils::macros::{FormatArgsStorage, format_args_inputs_span};
33
use clippy_utils::source::snippet_with_applicability;
4-
use clippy_utils::{is_expn_of, path_def_id};
4+
use clippy_utils::{is_expn_of, path_def_id, sym};
55
use rustc_errors::Applicability;
66
use rustc_hir::def::Res;
77
use rustc_hir::{BindingMode, Block, BlockCheckMode, Expr, ExprKind, Node, PatKind, QPath, Stmt, StmtKind};
88
use rustc_lint::{LateContext, LateLintPass};
99
use rustc_session::impl_lint_pass;
10-
use rustc_span::{ExpnId, sym};
10+
use rustc_span::ExpnId;
1111

1212
declare_clippy_lint! {
1313
/// ### What it does
@@ -72,9 +72,9 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite {
7272
};
7373

7474
// ordering is important here, since `writeln!` uses `write!` internally
75-
let calling_macro = if is_expn_of(write_call.span, "writeln").is_some() {
75+
let calling_macro = if is_expn_of(write_call.span, sym::writeln).is_some() {
7676
Some("writeln")
77-
} else if is_expn_of(write_call.span, "write").is_some() {
77+
} else if is_expn_of(write_call.span, sym::write).is_some() {
7878
Some("write")
7979
} else {
8080
None

clippy_lints/src/fallible_impl_from.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ fn lint_impl_body(cx: &LateContext<'_>, impl_span: Span, impl_items: &[hir::Impl
8282
}
8383

8484
// check for `unwrap`
85-
if let Some(arglists) = method_chain_args(expr, &["unwrap"]) {
85+
if let Some(arglists) = method_chain_args(expr, &[sym::unwrap]) {
8686
let receiver_ty = self.typeck_results.expr_ty(arglists[0].0).peel_refs();
8787
if is_type_diagnostic_item(self.lcx, receiver_ty, sym::Option)
8888
|| is_type_diagnostic_item(self.lcx, receiver_ty, sym::Result)

0 commit comments

Comments
 (0)