Skip to content

Commit c082bc2

Browse files
committed
Auto merge of rust-lang#13136 - xFrednet:07797-restriction-and-then, r=blyxyas
Make restriction lint's use `span_lint_and_then` (a -> e) This migrates a few restriction lints to use `span_lint_and_then`. This change is motivated by rust-lang#7797. I'm also interested if it will have an impact on performance. With some of these lints, like [`clippy::implicit_return`](https://rust-lang.github.io/rust-clippy/master/index.html#/implicit_return) I expect an impact, as it was previously creating a suggestion **for every implicit return** which is just wild. I've also cleaned up some lint message. Mostly minor stuff. For example: suggestions with a longer message than `"try"` now use `SuggestionStyle::ShowAlways` --- `@blyxyas` Could you benchmark this PR? I want to get all the numbers :3 --- This also crashed our new lintcheck CI with the following message: > Error: $GITHUB_STEP_SUMMARY upload aborted, supports content up to a size of 1024k, got 46731k. For more information see: https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-markdown-summary Which is just wild. Like, I've [tested the first 20 lints](https://github.com/xFrednet/rust-clippy/actions/runs/10027528172) and got like four changes and then this. 50 MB of changed lint messages o.O. Looks like I'll create a separate PR to fix that step ^^ --- cc: rust-lang#7797 changelog: none r? `@blyxyas`
2 parents e17d254 + 0532104 commit c082bc2

34 files changed

+927
-470
lines changed

clippy_lints/src/as_conversions.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use clippy_utils::diagnostics::span_lint_and_help;
1+
use clippy_utils::diagnostics::span_lint_and_then;
22
use clippy_utils::is_from_proc_macro;
33
use rustc_hir::{Expr, ExprKind};
44
use rustc_lint::{LateContext, LateLintPass, LintContext};
@@ -52,13 +52,15 @@ impl<'tcx> LateLintPass<'tcx> for AsConversions {
5252
&& !in_external_macro(cx.sess(), expr.span)
5353
&& !is_from_proc_macro(cx, expr)
5454
{
55-
span_lint_and_help(
55+
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
56+
span_lint_and_then(
5657
cx,
5758
AS_CONVERSIONS,
5859
expr.span,
5960
"using a potentially dangerous silent `as` conversion",
60-
None,
61-
"consider using a safe wrapper for this conversion",
61+
|diag| {
62+
diag.help("consider using a safe wrapper for this conversion");
63+
},
6264
);
6365
}
6466
}

clippy_lints/src/assertions_on_result_states.rs

+18-29
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use clippy_utils::diagnostics::span_lint_and_sugg;
1+
use clippy_utils::diagnostics::span_lint_and_then;
22
use clippy_utils::macros::{find_assert_args, root_macro_call_first_node, PanicExpn};
33
use clippy_utils::source::snippet_with_context;
44
use clippy_utils::ty::{has_debug_impl, is_copy, is_type_diagnostic_item};
@@ -68,39 +68,28 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnResultStates {
6868
return;
6969
}
7070
}
71-
let semicolon = if is_expr_final_block_expr(cx.tcx, e) { ";" } else { "" };
72-
let mut app = Applicability::MachineApplicable;
73-
match method_segment.ident.as_str() {
71+
let (message, replacement) = match method_segment.ident.as_str() {
7472
"is_ok" if type_suitable_to_unwrap(cx, args.type_at(1)) => {
75-
span_lint_and_sugg(
76-
cx,
77-
ASSERTIONS_ON_RESULT_STATES,
78-
macro_call.span,
79-
"called `assert!` with `Result::is_ok`",
80-
"replace with",
81-
format!(
82-
"{}.unwrap(){semicolon}",
83-
snippet_with_context(cx, recv.span, condition.span.ctxt(), "..", &mut app).0
84-
),
85-
app,
86-
);
73+
("called `assert!` with `Result::is_ok`", "unwrap")
8774
},
8875
"is_err" if type_suitable_to_unwrap(cx, args.type_at(0)) => {
89-
span_lint_and_sugg(
90-
cx,
91-
ASSERTIONS_ON_RESULT_STATES,
92-
macro_call.span,
93-
"called `assert!` with `Result::is_err`",
94-
"replace with",
95-
format!(
96-
"{}.unwrap_err(){semicolon}",
97-
snippet_with_context(cx, recv.span, condition.span.ctxt(), "..", &mut app).0
98-
),
99-
app,
100-
);
76+
("called `assert!` with `Result::is_err`", "unwrap_err")
10177
},
102-
_ => (),
78+
_ => return,
10379
};
80+
span_lint_and_then(cx, ASSERTIONS_ON_RESULT_STATES, macro_call.span, message, |diag| {
81+
let semicolon = if is_expr_final_block_expr(cx.tcx, e) { ";" } else { "" };
82+
let mut app = Applicability::MachineApplicable;
83+
diag.span_suggestion(
84+
macro_call.span,
85+
"replace with",
86+
format!(
87+
"{}.{replacement}(){semicolon}",
88+
snippet_with_context(cx, recv.span, condition.span.ctxt(), "..", &mut app).0
89+
),
90+
app,
91+
);
92+
});
10493
}
10594
}
10695
}
+10-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::ALLOW_ATTRIBUTES;
2-
use clippy_utils::diagnostics::span_lint_and_sugg;
2+
use clippy_utils::diagnostics::span_lint_and_then;
33
use clippy_utils::is_from_proc_macro;
44
use rustc_ast::{AttrStyle, Attribute};
55
use rustc_errors::Applicability;
@@ -13,14 +13,14 @@ pub fn check<'cx>(cx: &LateContext<'cx>, attr: &'cx Attribute) {
1313
&& let Some(ident) = attr.ident()
1414
&& !is_from_proc_macro(cx, attr)
1515
{
16-
span_lint_and_sugg(
17-
cx,
18-
ALLOW_ATTRIBUTES,
19-
ident.span,
20-
"#[allow] attribute found",
21-
"replace it with",
22-
"expect".into(),
23-
Applicability::MachineApplicable,
24-
);
16+
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
17+
span_lint_and_then(cx, ALLOW_ATTRIBUTES, ident.span, "#[allow] attribute found", |diag| {
18+
diag.span_suggestion(
19+
ident.span,
20+
"replace it with",
21+
"expect",
22+
Applicability::MachineApplicable,
23+
);
24+
});
2525
}
2626
}

clippy_lints/src/attrs/allow_attributes_without_reason.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::{Attribute, ALLOW_ATTRIBUTES_WITHOUT_REASON};
2-
use clippy_utils::diagnostics::span_lint_and_help;
2+
use clippy_utils::diagnostics::span_lint_and_then;
33
use clippy_utils::is_from_proc_macro;
44
use rustc_ast::{MetaItemKind, NestedMetaItem};
55
use rustc_lint::{LateContext, LintContext};
@@ -21,12 +21,14 @@ pub(super) fn check<'cx>(cx: &LateContext<'cx>, name: Symbol, items: &[NestedMet
2121
return;
2222
}
2323

24-
span_lint_and_help(
24+
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
25+
span_lint_and_then(
2526
cx,
2627
ALLOW_ATTRIBUTES_WITHOUT_REASON,
2728
attr.span,
2829
format!("`{}` attribute without specifying a reason", name.as_str()),
29-
None,
30-
"try adding a reason at the end with `, reason = \"..\"`",
30+
|diag| {
31+
diag.help("try adding a reason at the end with `, reason = \"..\"`");
32+
},
3133
);
3234
}
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
use clippy_utils::diagnostics::span_lint_and_sugg;
1+
use clippy_utils::diagnostics::span_lint_and_then;
22
use clippy_utils::source::snippet_with_applicability;
3-
use rustc_errors::Applicability;
3+
use rustc_errors::{Applicability, SuggestionStyle};
44
use rustc_hir::Expr;
55
use rustc_lint::LateContext;
66
use rustc_middle::ty::{self, Ty};
@@ -14,21 +14,24 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
1414
_ => { /* continue to checks */ },
1515
}
1616

17-
match cast_from.kind() {
18-
ty::FnDef(..) | ty::FnPtr(_) => {
19-
let mut applicability = Applicability::MaybeIncorrect;
20-
let from_snippet = snippet_with_applicability(cx, cast_expr.span, "..", &mut applicability);
17+
if let ty::FnDef(..) | ty::FnPtr(_) = cast_from.kind() {
18+
let mut applicability = Applicability::MaybeIncorrect;
19+
let from_snippet = snippet_with_applicability(cx, cast_expr.span, "..", &mut applicability);
2120

22-
span_lint_and_sugg(
23-
cx,
24-
FN_TO_NUMERIC_CAST_ANY,
25-
expr.span,
26-
format!("casting function pointer `{from_snippet}` to `{cast_to}`"),
27-
"did you mean to invoke the function?",
28-
format!("{from_snippet}() as {cast_to}"),
29-
applicability,
30-
);
31-
},
32-
_ => {},
21+
span_lint_and_then(
22+
cx,
23+
FN_TO_NUMERIC_CAST_ANY,
24+
expr.span,
25+
format!("casting function pointer `{from_snippet}` to `{cast_to}`"),
26+
|diag| {
27+
diag.span_suggestion_with_style(
28+
expr.span,
29+
"did you mean to invoke the function?",
30+
format!("{from_snippet}() as {cast_to}"),
31+
applicability,
32+
SuggestionStyle::ShowAlways,
33+
);
34+
},
35+
);
3336
}
3437
}

clippy_lints/src/create_dir.rs

+17-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
use clippy_utils::diagnostics::span_lint_and_sugg;
2-
use clippy_utils::source::snippet;
3-
use rustc_errors::Applicability;
1+
use clippy_utils::diagnostics::span_lint_and_then;
2+
use clippy_utils::source::snippet_with_applicability;
3+
use rustc_errors::{Applicability, SuggestionStyle};
44
use rustc_hir::{Expr, ExprKind};
55
use rustc_lint::{LateContext, LateLintPass};
66
use rustc_session::declare_lint_pass;
@@ -39,14 +39,24 @@ impl LateLintPass<'_> for CreateDir {
3939
&& let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id()
4040
&& cx.tcx.is_diagnostic_item(sym::fs_create_dir, def_id)
4141
{
42-
span_lint_and_sugg(
42+
span_lint_and_then(
4343
cx,
4444
CREATE_DIR,
4545
expr.span,
4646
"calling `std::fs::create_dir` where there may be a better way",
47-
"consider calling `std::fs::create_dir_all` instead",
48-
format!("create_dir_all({})", snippet(cx, arg.span, "..")),
49-
Applicability::MaybeIncorrect,
47+
|diag| {
48+
let mut app = Applicability::MaybeIncorrect;
49+
diag.span_suggestion_with_style(
50+
expr.span,
51+
"consider calling `std::fs::create_dir_all` instead",
52+
format!(
53+
"create_dir_all({})",
54+
snippet_with_applicability(cx, arg.span, "..", &mut app)
55+
),
56+
app,
57+
SuggestionStyle::ShowAlways,
58+
);
59+
},
5060
);
5161
}
5262
}

clippy_lints/src/dbg_macro.rs

+57-51
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use clippy_config::Conf;
2-
use clippy_utils::diagnostics::span_lint_and_sugg;
2+
use clippy_utils::diagnostics::span_lint_and_then;
33
use clippy_utils::is_in_test;
44
use clippy_utils::macros::{macro_backtrace, MacroCall};
55
use clippy_utils::source::snippet_with_applicability;
@@ -65,61 +65,67 @@ impl LateLintPass<'_> for DbgMacro {
6565
// allows `dbg!` in test code if allow-dbg-in-test is set to true in clippy.toml
6666
!(self.allow_dbg_in_tests && is_in_test(cx.tcx, expr.hir_id))
6767
{
68-
let mut applicability = Applicability::MachineApplicable;
69-
70-
let (sugg_span, suggestion) = match expr.peel_drop_temps().kind {
71-
// dbg!()
72-
ExprKind::Block(..) => {
73-
// If the `dbg!` macro is a "free" statement and not contained within other expressions,
74-
// remove the whole statement.
75-
if let Node::Stmt(_) = cx.tcx.parent_hir_node(expr.hir_id)
76-
&& let Some(semi_span) = cx.sess().source_map().mac_call_stmt_semi_span(macro_call.span)
77-
{
78-
(macro_call.span.to(semi_span), String::new())
79-
} else {
80-
(macro_call.span, String::from("()"))
81-
}
82-
},
83-
// dbg!(1)
84-
ExprKind::Match(val, ..) => (
85-
macro_call.span,
86-
snippet_with_applicability(cx, val.span.source_callsite(), "..", &mut applicability).to_string(),
87-
),
88-
// dbg!(2, 3)
89-
ExprKind::Tup(
90-
[
91-
Expr {
92-
kind: ExprKind::Match(first, ..),
93-
..
94-
},
95-
..,
96-
Expr {
97-
kind: ExprKind::Match(last, ..),
98-
..
99-
},
100-
],
101-
) => {
102-
let snippet = snippet_with_applicability(
103-
cx,
104-
first.span.source_callsite().to(last.span.source_callsite()),
105-
"..",
106-
&mut applicability,
107-
);
108-
(macro_call.span, format!("({snippet})"))
109-
},
110-
_ => return,
111-
};
112-
11368
self.prev_ctxt = cur_syntax_ctxt;
11469

115-
span_lint_and_sugg(
70+
span_lint_and_then(
11671
cx,
11772
DBG_MACRO,
118-
sugg_span,
73+
macro_call.span,
11974
"the `dbg!` macro is intended as a debugging tool",
120-
"remove the invocation before committing it to a version control system",
121-
suggestion,
122-
applicability,
75+
|diag| {
76+
let mut applicability = Applicability::MachineApplicable;
77+
78+
let (sugg_span, suggestion) = match expr.peel_drop_temps().kind {
79+
// dbg!()
80+
ExprKind::Block(..) => {
81+
// If the `dbg!` macro is a "free" statement and not contained within other expressions,
82+
// remove the whole statement.
83+
if let Node::Stmt(_) = cx.tcx.parent_hir_node(expr.hir_id)
84+
&& let Some(semi_span) = cx.sess().source_map().mac_call_stmt_semi_span(macro_call.span)
85+
{
86+
(macro_call.span.to(semi_span), String::new())
87+
} else {
88+
(macro_call.span, String::from("()"))
89+
}
90+
},
91+
// dbg!(1)
92+
ExprKind::Match(val, ..) => (
93+
macro_call.span,
94+
snippet_with_applicability(cx, val.span.source_callsite(), "..", &mut applicability)
95+
.to_string(),
96+
),
97+
// dbg!(2, 3)
98+
ExprKind::Tup(
99+
[
100+
Expr {
101+
kind: ExprKind::Match(first, ..),
102+
..
103+
},
104+
..,
105+
Expr {
106+
kind: ExprKind::Match(last, ..),
107+
..
108+
},
109+
],
110+
) => {
111+
let snippet = snippet_with_applicability(
112+
cx,
113+
first.span.source_callsite().to(last.span.source_callsite()),
114+
"..",
115+
&mut applicability,
116+
);
117+
(macro_call.span, format!("({snippet})"))
118+
},
119+
_ => unreachable!(),
120+
};
121+
122+
diag.span_suggestion(
123+
sugg_span,
124+
"remove the invocation before committing it to a version control system",
125+
suggestion,
126+
applicability,
127+
);
128+
},
123129
);
124130
}
125131
}

clippy_lints/src/default_numeric_fallback.rs

+11-12
Original file line numberDiff line numberDiff line change
@@ -92,27 +92,26 @@ impl<'a, 'tcx> NumericFallbackVisitor<'a, 'tcx> {
9292
let (suffix, is_float) = match lit_ty.kind() {
9393
ty::Int(IntTy::I32) => ("i32", false),
9494
ty::Float(FloatTy::F64) => ("f64", true),
95-
// Default numeric fallback never results in other types.
9695
_ => return,
9796
};
98-
99-
let src = if let Some(src) = snippet_opt(self.cx, lit.span) {
100-
src
101-
} else {
102-
match lit.node {
103-
LitKind::Int(src, _) => format!("{src}"),
104-
LitKind::Float(src, _) => format!("{src}"),
105-
_ => return,
106-
}
107-
};
108-
let sugg = numeric_literal::format(&src, Some(suffix), is_float);
10997
span_lint_hir_and_then(
11098
self.cx,
11199
DEFAULT_NUMERIC_FALLBACK,
112100
emit_hir_id,
113101
lit.span,
114102
"default numeric fallback might occur",
115103
|diag| {
104+
let src = if let Some(src) = snippet_opt(self.cx, lit.span) {
105+
src
106+
} else {
107+
match lit.node {
108+
LitKind::Int(src, _) => format!("{src}"),
109+
LitKind::Float(src, _) => format!("{src}"),
110+
_ => unreachable!("Default numeric fallback never results in other types"),
111+
}
112+
};
113+
114+
let sugg = numeric_literal::format(&src, Some(suffix), is_float);
116115
diag.span_suggestion(lit.span, "consider adding suffix", sugg, Applicability::MaybeIncorrect);
117116
},
118117
);

0 commit comments

Comments
 (0)