Skip to content

Commit 993d8ae

Browse files
committed
Auto merge of rust-lang#12567 - Alexendoo:format-args-storage, r=flip1995
Fix `FormatArgs` storage when `-Zthreads` > 1 Fixes rust-lang#11886 The initial way I thought of was a little gross so I never opened a PR for it, I thought of a nicer way today that no longer involves any `thread_local`s or `static`s `rustc_data_strucutres::sync::{Lrc, OnceLock}` implement `DynSend` + `DynSync` so we can pass them to the lint passes that need the storage changelog: none r? `@flip1995`
2 parents 60267b2 + c187bff commit 993d8ae

File tree

10 files changed

+151
-94
lines changed

10 files changed

+151
-94
lines changed

clippy_lints/src/explicit_write.rs

+15-5
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
use clippy_utils::diagnostics::span_lint_and_sugg;
2-
use clippy_utils::macros::{find_format_args, format_args_inputs_span};
2+
use clippy_utils::macros::{format_args_inputs_span, FormatArgsStorage};
33
use clippy_utils::source::snippet_with_applicability;
44
use clippy_utils::{is_expn_of, path_def_id};
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};
9-
use rustc_session::declare_lint_pass;
9+
use rustc_session::impl_lint_pass;
1010
use rustc_span::{sym, ExpnId};
1111

1212
declare_clippy_lint! {
@@ -38,7 +38,17 @@ declare_clippy_lint! {
3838
"using the `write!()` family of functions instead of the `print!()` family of functions, when using the latter would work"
3939
}
4040

41-
declare_lint_pass!(ExplicitWrite => [EXPLICIT_WRITE]);
41+
pub struct ExplicitWrite {
42+
format_args: FormatArgsStorage,
43+
}
44+
45+
impl ExplicitWrite {
46+
pub fn new(format_args: FormatArgsStorage) -> Self {
47+
Self { format_args }
48+
}
49+
}
50+
51+
impl_lint_pass!(ExplicitWrite => [EXPLICIT_WRITE]);
4252

4353
impl<'tcx> LateLintPass<'tcx> for ExplicitWrite {
4454
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
@@ -57,7 +67,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite {
5767
Some(sym::io_stderr) => ("stderr", "e"),
5868
_ => return,
5969
};
60-
let Some(format_args) = find_format_args(cx, write_arg, ExpnId::root()) else {
70+
let Some(format_args) = self.format_args.get(cx, write_arg, ExpnId::root()) else {
6171
return;
6272
};
6373

@@ -83,7 +93,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite {
8393
};
8494
let mut applicability = Applicability::MachineApplicable;
8595
let inputs_snippet =
86-
snippet_with_applicability(cx, format_args_inputs_span(&format_args), "..", &mut applicability);
96+
snippet_with_applicability(cx, format_args_inputs_span(format_args), "..", &mut applicability);
8797
span_lint_and_sugg(
8898
cx,
8999
EXPLICIT_WRITE,

clippy_lints/src/format.rs

+15-4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
use clippy_utils::diagnostics::span_lint_and_sugg;
2-
use clippy_utils::macros::{find_format_arg_expr, find_format_args, root_macro_call_first_node};
2+
use clippy_utils::macros::{find_format_arg_expr, root_macro_call_first_node, FormatArgsStorage};
33
use clippy_utils::source::{snippet_opt, snippet_with_context};
44
use clippy_utils::sugg::Sugg;
55
use rustc_ast::{FormatArgsPiece, FormatOptions, FormatTrait};
66
use rustc_errors::Applicability;
77
use rustc_hir::{Expr, ExprKind};
88
use rustc_lint::{LateContext, LateLintPass};
99
use rustc_middle::ty;
10-
use rustc_session::declare_lint_pass;
10+
use rustc_session::impl_lint_pass;
1111
use rustc_span::{sym, Span};
1212

1313
declare_clippy_lint! {
@@ -39,13 +39,24 @@ declare_clippy_lint! {
3939
"useless use of `format!`"
4040
}
4141

42-
declare_lint_pass!(UselessFormat => [USELESS_FORMAT]);
42+
#[allow(clippy::module_name_repetitions)]
43+
pub struct UselessFormat {
44+
format_args: FormatArgsStorage,
45+
}
46+
47+
impl UselessFormat {
48+
pub fn new(format_args: FormatArgsStorage) -> Self {
49+
Self { format_args }
50+
}
51+
}
52+
53+
impl_lint_pass!(UselessFormat => [USELESS_FORMAT]);
4354

4455
impl<'tcx> LateLintPass<'tcx> for UselessFormat {
4556
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
4657
if let Some(macro_call) = root_macro_call_first_node(cx, expr)
4758
&& cx.tcx.is_diagnostic_item(sym::format_macro, macro_call.def_id)
48-
&& let Some(format_args) = find_format_args(cx, expr, macro_call.expn)
59+
&& let Some(format_args) = self.format_args.get(cx, expr, macro_call.expn)
4960
{
5061
let mut applicability = Applicability::MachineApplicable;
5162
let call_site = macro_call.span;

clippy_lints/src/format_args.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ use clippy_config::msrvs::{self, Msrv};
33
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
44
use clippy_utils::is_diag_trait_item;
55
use clippy_utils::macros::{
6-
find_format_arg_expr, find_format_args, format_arg_removal_span, format_placeholder_format_span, is_assert_macro,
7-
is_format_macro, is_panic, matching_root_macro_call, root_macro_call_first_node, FormatParamUsage, MacroCall,
6+
find_format_arg_expr, format_arg_removal_span, format_placeholder_format_span, is_assert_macro, is_format_macro,
7+
is_panic, matching_root_macro_call, root_macro_call_first_node, FormatArgsStorage, FormatParamUsage, MacroCall,
88
};
99
use clippy_utils::source::snippet_opt;
1010
use clippy_utils::ty::{implements_trait, is_type_lang_item};
@@ -167,15 +167,18 @@ impl_lint_pass!(FormatArgs => [
167167
UNUSED_FORMAT_SPECS,
168168
]);
169169

170+
#[allow(clippy::struct_field_names)]
170171
pub struct FormatArgs {
172+
format_args: FormatArgsStorage,
171173
msrv: Msrv,
172174
ignore_mixed: bool,
173175
}
174176

175177
impl FormatArgs {
176178
#[must_use]
177-
pub fn new(msrv: Msrv, allow_mixed_uninlined_format_args: bool) -> Self {
179+
pub fn new(format_args: FormatArgsStorage, msrv: Msrv, allow_mixed_uninlined_format_args: bool) -> Self {
178180
Self {
181+
format_args,
179182
msrv,
180183
ignore_mixed: allow_mixed_uninlined_format_args,
181184
}
@@ -186,13 +189,13 @@ impl<'tcx> LateLintPass<'tcx> for FormatArgs {
186189
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
187190
if let Some(macro_call) = root_macro_call_first_node(cx, expr)
188191
&& is_format_macro(cx, macro_call.def_id)
189-
&& let Some(format_args) = find_format_args(cx, expr, macro_call.expn)
192+
&& let Some(format_args) = self.format_args.get(cx, expr, macro_call.expn)
190193
{
191194
let linter = FormatArgsExpr {
192195
cx,
193196
expr,
194197
macro_call: &macro_call,
195-
format_args: &format_args,
198+
format_args,
196199
ignore_mixed: self.ignore_mixed,
197200
};
198201

clippy_lints/src/format_impl.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
2-
use clippy_utils::macros::{find_format_arg_expr, find_format_args, is_format_macro, root_macro_call_first_node};
2+
use clippy_utils::macros::{find_format_arg_expr, is_format_macro, root_macro_call_first_node, FormatArgsStorage};
33
use clippy_utils::{get_parent_as_impl, is_diag_trait_item, path_to_local, peel_ref_operators};
44
use rustc_ast::{FormatArgsPiece, FormatTrait};
55
use rustc_errors::Applicability;
@@ -99,13 +99,15 @@ struct FormatTraitNames {
9999

100100
#[derive(Default)]
101101
pub struct FormatImpl {
102+
format_args: FormatArgsStorage,
102103
// Whether we are inside Display or Debug trait impl - None for neither
103104
format_trait_impl: Option<FormatTraitNames>,
104105
}
105106

106107
impl FormatImpl {
107-
pub fn new() -> Self {
108+
pub fn new(format_args: FormatArgsStorage) -> Self {
108109
Self {
110+
format_args,
109111
format_trait_impl: None,
110112
}
111113
}
@@ -129,6 +131,7 @@ impl<'tcx> LateLintPass<'tcx> for FormatImpl {
129131
if let Some(format_trait_impl) = self.format_trait_impl {
130132
let linter = FormatImplExpr {
131133
cx,
134+
format_args: &self.format_args,
132135
expr,
133136
format_trait_impl,
134137
};
@@ -141,6 +144,7 @@ impl<'tcx> LateLintPass<'tcx> for FormatImpl {
141144

142145
struct FormatImplExpr<'a, 'tcx> {
143146
cx: &'a LateContext<'tcx>,
147+
format_args: &'a FormatArgsStorage,
144148
expr: &'tcx Expr<'tcx>,
145149
format_trait_impl: FormatTraitNames,
146150
}
@@ -175,7 +179,7 @@ impl<'a, 'tcx> FormatImplExpr<'a, 'tcx> {
175179
if let Some(outer_macro) = root_macro_call_first_node(self.cx, self.expr)
176180
&& let macro_def_id = outer_macro.def_id
177181
&& is_format_macro(self.cx, macro_def_id)
178-
&& let Some(format_args) = find_format_args(self.cx, self.expr, outer_macro.expn)
182+
&& let Some(format_args) = self.format_args.get(self.cx, self.expr, outer_macro.expn)
179183
{
180184
for piece in &format_args.template {
181185
if let FormatArgsPiece::Placeholder(placeholder) = piece

clippy_lints/src/lib.rs

+30-12
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,6 @@ extern crate clippy_utils;
6060
#[macro_use]
6161
extern crate declare_clippy_lint;
6262

63-
use std::collections::BTreeMap;
64-
65-
use rustc_data_structures::fx::FxHashSet;
66-
use rustc_lint::{Lint, LintId};
67-
6863
#[cfg(feature = "internal")]
6964
pub mod deprecated_lints;
7065
#[cfg_attr(feature = "internal", allow(clippy::missing_clippy_version_attribute))]
@@ -384,6 +379,10 @@ mod zero_sized_map_values;
384379
// end lints modules, do not remove this comment, it’s used in `update_lints`
385380

386381
use clippy_config::{get_configuration_metadata, Conf};
382+
use clippy_utils::macros::FormatArgsStorage;
383+
use rustc_data_structures::fx::FxHashSet;
384+
use rustc_lint::{Lint, LintId};
385+
use std::collections::BTreeMap;
387386

388387
/// Register all pre expansion lints
389388
///
@@ -615,6 +614,14 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
615614
}
616615
}
617616

617+
let format_args_storage = FormatArgsStorage::default();
618+
let format_args = format_args_storage.clone();
619+
store.register_early_pass(move || {
620+
Box::new(utils::format_args_collector::FormatArgsCollector::new(
621+
format_args.clone(),
622+
))
623+
});
624+
618625
// all the internal lints
619626
#[cfg(feature = "internal")]
620627
{
@@ -655,7 +662,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
655662
.collect(),
656663
))
657664
});
658-
store.register_early_pass(|| Box::<utils::format_args_collector::FormatArgsCollector>::default());
659665
store.register_late_pass(|_| Box::new(utils::dump_hir::DumpHir));
660666
store.register_late_pass(|_| Box::new(utils::author::Author));
661667
store.register_late_pass(move |_| {
@@ -697,13 +703,15 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
697703
store.register_late_pass(|_| Box::new(non_octal_unix_permissions::NonOctalUnixPermissions));
698704
store.register_early_pass(|| Box::new(unnecessary_self_imports::UnnecessarySelfImports));
699705
store.register_late_pass(move |_| Box::new(approx_const::ApproxConstant::new(msrv())));
706+
let format_args = format_args_storage.clone();
700707
store.register_late_pass(move |_| {
701708
Box::new(methods::Methods::new(
702709
avoid_breaking_exported_api,
703710
msrv(),
704711
allow_expect_in_tests,
705712
allow_unwrap_in_tests,
706713
allowed_dotfiles.clone(),
714+
format_args.clone(),
707715
))
708716
});
709717
store.register_late_pass(move |_| Box::new(matches::Matches::new(msrv())));
@@ -768,7 +776,8 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
768776
store.register_late_pass(|_| Box::<regex::Regex>::default());
769777
store.register_late_pass(move |_| Box::new(copies::CopyAndPaste::new(ignore_interior_mutability.clone())));
770778
store.register_late_pass(|_| Box::new(copy_iterator::CopyIterator));
771-
store.register_late_pass(|_| Box::new(format::UselessFormat));
779+
let format_args = format_args_storage.clone();
780+
store.register_late_pass(move |_| Box::new(format::UselessFormat::new(format_args.clone())));
772781
store.register_late_pass(|_| Box::new(swap::Swap));
773782
store.register_late_pass(|_| Box::new(overflow_check_conditional::OverflowCheckConditional));
774783
store.register_late_pass(|_| Box::<new_without_default::NewWithoutDefault>::default());
@@ -792,7 +801,8 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
792801
store.register_late_pass(|_| Box::new(partialeq_ne_impl::PartialEqNeImpl));
793802
store.register_late_pass(|_| Box::new(unused_io_amount::UnusedIoAmount));
794803
store.register_late_pass(move |_| Box::new(large_enum_variant::LargeEnumVariant::new(enum_variant_size_threshold)));
795-
store.register_late_pass(|_| Box::new(explicit_write::ExplicitWrite));
804+
let format_args = format_args_storage.clone();
805+
store.register_late_pass(move |_| Box::new(explicit_write::ExplicitWrite::new(format_args.clone())));
796806
store.register_late_pass(|_| Box::new(needless_pass_by_value::NeedlessPassByValue));
797807
store.register_late_pass(move |tcx| {
798808
Box::new(pass_by_ref_or_value::PassByRefOrValue::new(
@@ -834,7 +844,8 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
834844
store.register_late_pass(move |_| Box::new(mut_key::MutableKeyType::new(ignore_interior_mutability.clone())));
835845
store.register_early_pass(|| Box::new(reference::DerefAddrOf));
836846
store.register_early_pass(|| Box::new(double_parens::DoubleParens));
837-
store.register_late_pass(|_| Box::new(format_impl::FormatImpl::new()));
847+
let format_args = format_args_storage.clone();
848+
store.register_late_pass(move |_| Box::new(format_impl::FormatImpl::new(format_args.clone())));
838849
store.register_early_pass(|| Box::new(unsafe_removed_from_name::UnsafeNameRemoval));
839850
store.register_early_pass(|| Box::new(else_if_without_else::ElseIfWithoutElse));
840851
store.register_early_pass(|| Box::new(int_plus_one::IntPlusOne));
@@ -960,8 +971,14 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
960971
accept_comment_above_attributes,
961972
))
962973
});
963-
store
964-
.register_late_pass(move |_| Box::new(format_args::FormatArgs::new(msrv(), allow_mixed_uninlined_format_args)));
974+
let format_args = format_args_storage.clone();
975+
store.register_late_pass(move |_| {
976+
Box::new(format_args::FormatArgs::new(
977+
format_args.clone(),
978+
msrv(),
979+
allow_mixed_uninlined_format_args,
980+
))
981+
});
965982
store.register_late_pass(|_| Box::new(trailing_empty_array::TrailingEmptyArray));
966983
store.register_early_pass(|| Box::new(octal_escapes::OctalEscapes));
967984
store.register_late_pass(|_| Box::new(needless_late_init::NeedlessLateInit));
@@ -972,7 +989,8 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
972989
store.register_late_pass(|_| Box::new(default_union_representation::DefaultUnionRepresentation));
973990
store.register_late_pass(|_| Box::<only_used_in_recursion::OnlyUsedInRecursion>::default());
974991
store.register_late_pass(move |_| Box::new(dbg_macro::DbgMacro::new(allow_dbg_in_tests)));
975-
store.register_late_pass(move |_| Box::new(write::Write::new(allow_print_in_tests)));
992+
let format_args = format_args_storage.clone();
993+
store.register_late_pass(move |_| Box::new(write::Write::new(format_args.clone(), allow_print_in_tests)));
976994
store.register_late_pass(move |_| {
977995
Box::new(cargo::Cargo {
978996
ignore_publish: cargo_ignore_publish,

clippy_lints/src/methods/expect_fun_call.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use clippy_utils::diagnostics::span_lint_and_sugg;
2-
use clippy_utils::macros::{find_format_args, format_args_inputs_span, root_macro_call_first_node};
2+
use clippy_utils::macros::{format_args_inputs_span, root_macro_call_first_node, FormatArgsStorage};
33
use clippy_utils::source::snippet_with_applicability;
44
use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
55
use rustc_errors::Applicability;
@@ -16,6 +16,7 @@ use super::EXPECT_FUN_CALL;
1616
#[allow(clippy::too_many_lines)]
1717
pub(super) fn check<'tcx>(
1818
cx: &LateContext<'tcx>,
19+
format_args_storage: &FormatArgsStorage,
1920
expr: &hir::Expr<'_>,
2021
method_span: Span,
2122
name: &str,
@@ -134,9 +135,9 @@ pub(super) fn check<'tcx>(
134135
// Special handling for `format!` as arg_root
135136
if let Some(macro_call) = root_macro_call_first_node(cx, arg_root) {
136137
if cx.tcx.is_diagnostic_item(sym::format_macro, macro_call.def_id)
137-
&& let Some(format_args) = find_format_args(cx, arg_root, macro_call.expn)
138+
&& let Some(format_args) = format_args_storage.get(cx, arg_root, macro_call.expn)
138139
{
139-
let span = format_args_inputs_span(&format_args);
140+
let span = format_args_inputs_span(format_args);
140141
let sugg = snippet_with_applicability(cx, span, "..", &mut applicability);
141142
span_lint_and_sugg(
142143
cx,

clippy_lints/src/methods/mod.rs

+14-1
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ use bind_instead_of_map::BindInsteadOfMap;
133133
use clippy_config::msrvs::{self, Msrv};
134134
use clippy_utils::consts::{constant, Constant};
135135
use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
136+
use clippy_utils::macros::FormatArgsStorage;
136137
use clippy_utils::ty::{contains_ty_adt_constructor_opaque, implements_trait, is_copy, is_type_diagnostic_item};
137138
use clippy_utils::{contains_return, is_bool, is_trait_method, iter_input_pats, peel_blocks, return_ty};
138139
pub use path_ends_with_ext::DEFAULT_ALLOWED_DOTFILES;
@@ -4087,12 +4088,14 @@ declare_clippy_lint! {
40874088
suspicious,
40884089
"is_empty() called on strings known at compile time"
40894090
}
4091+
40904092
pub struct Methods {
40914093
avoid_breaking_exported_api: bool,
40924094
msrv: Msrv,
40934095
allow_expect_in_tests: bool,
40944096
allow_unwrap_in_tests: bool,
40954097
allowed_dotfiles: FxHashSet<String>,
4098+
format_args: FormatArgsStorage,
40964099
}
40974100

40984101
impl Methods {
@@ -4103,6 +4106,7 @@ impl Methods {
41034106
allow_expect_in_tests: bool,
41044107
allow_unwrap_in_tests: bool,
41054108
mut allowed_dotfiles: FxHashSet<String>,
4109+
format_args: FormatArgsStorage,
41064110
) -> Self {
41074111
allowed_dotfiles.extend(DEFAULT_ALLOWED_DOTFILES.iter().map(ToString::to_string));
41084112

@@ -4112,6 +4116,7 @@ impl Methods {
41124116
allow_expect_in_tests,
41134117
allow_unwrap_in_tests,
41144118
allowed_dotfiles,
4119+
format_args,
41154120
}
41164121
}
41174122
}
@@ -4281,7 +4286,15 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
42814286
ExprKind::MethodCall(method_call, receiver, args, _) => {
42824287
let method_span = method_call.ident.span;
42834288
or_fun_call::check(cx, expr, method_span, method_call.ident.as_str(), receiver, args);
4284-
expect_fun_call::check(cx, expr, method_span, method_call.ident.as_str(), receiver, args);
4289+
expect_fun_call::check(
4290+
cx,
4291+
&self.format_args,
4292+
expr,
4293+
method_span,
4294+
method_call.ident.as_str(),
4295+
receiver,
4296+
args,
4297+
);
42854298
clone_on_copy::check(cx, expr, method_call.ident.name, receiver, args);
42864299
clone_on_ref_ptr::check(cx, expr, method_call.ident.name, receiver, args);
42874300
inefficient_to_string::check(cx, expr, method_call.ident.name, receiver, args);

0 commit comments

Comments
 (0)