Skip to content

Commit cfb3881

Browse files
committed
Auto merge of #13145 - xFrednet:07797-restriction-and-then-why, r=Jarcho
Make restriction lint's use `span_lint_and_then` (q -> w) This migrates a few restriction lints to use `span_lint_and_then`. This change is motivated by #7797. I've also cleaned up some lint message. Mostly minor stuff. For example: suggestions with a longer message than `"try"` now use `SuggestionStyle::ShowAlways` --- cc: #7797 sister PR of: #13136 changelog: none
2 parents 5f6d07b + 4bf4c47 commit cfb3881

17 files changed

+244
-168
lines changed

clippy_lints/src/matches/match_wild_enum.rs

+19-15
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_sugg, span_lint_and_then};
22
use clippy_utils::ty::is_type_diagnostic_item;
33
use clippy_utils::{is_refutable, peel_hir_pat_refs, recurse_or_patterns};
44
use rustc_errors::Applicability;
@@ -148,23 +148,27 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) {
148148
Applicability::MaybeIncorrect,
149149
),
150150
variants => {
151-
let mut suggestions: Vec<_> = variants.iter().copied().map(format_suggestion).collect();
152-
let message = if adt_def.is_variant_list_non_exhaustive() || has_external_hidden {
153-
suggestions.push("_".into());
154-
"wildcard matches known variants and will also match future added variants"
151+
let (message, add_wildcard) = if adt_def.is_variant_list_non_exhaustive() || has_external_hidden {
152+
(
153+
"wildcard matches known variants and will also match future added variants",
154+
true,
155+
)
155156
} else {
156-
"wildcard match will also match any future added variants"
157+
("wildcard match will also match any future added variants", false)
157158
};
158159

159-
span_lint_and_sugg(
160-
cx,
161-
WILDCARD_ENUM_MATCH_ARM,
162-
wildcard_span,
163-
message,
164-
"try",
165-
suggestions.join(" | "),
166-
Applicability::MaybeIncorrect,
167-
);
160+
span_lint_and_then(cx, WILDCARD_ENUM_MATCH_ARM, wildcard_span, message, |diag| {
161+
let mut suggestions: Vec<_> = variants.iter().copied().map(format_suggestion).collect();
162+
if add_wildcard {
163+
suggestions.push("_".into());
164+
}
165+
diag.span_suggestion(
166+
wildcard_span,
167+
"try",
168+
suggestions.join(" | "),
169+
Applicability::MaybeIncorrect,
170+
);
171+
});
168172
},
169173
};
170174
}

clippy_lints/src/matches/rest_pat_in_fully_bound_struct.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 rustc_hir::{Pat, PatKind, QPath};
33
use rustc_lint::LateContext;
44
use rustc_middle::ty;
@@ -15,13 +15,15 @@ pub(crate) fn check(cx: &LateContext<'_>, pat: &Pat<'_>) {
1515
&& fields.len() == def.non_enum_variant().fields.len()
1616
&& !def.non_enum_variant().is_field_list_non_exhaustive()
1717
{
18-
span_lint_and_help(
18+
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
19+
span_lint_and_then(
1920
cx,
2021
REST_PAT_IN_FULLY_BOUND_STRUCTS,
2122
pat.span,
2223
"unnecessary use of `..` pattern in struct binding. All fields were already bound",
23-
None,
24-
"consider removing `..` from this binding",
24+
|diag| {
25+
diag.help("consider removing `..` from this binding");
26+
},
2527
);
2628
}
2729
}

clippy_lints/src/matches/try_err.rs

+19-20
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::source::snippet_with_applicability;
33
use clippy_utils::ty::is_type_diagnostic_item;
44
use clippy_utils::{get_parent_expr, is_res_lang_ctor, path_res};
@@ -48,29 +48,28 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, scrutine
4848
return;
4949
};
5050

51-
let expr_err_ty = cx.typeck_results().expr_ty(err_arg);
52-
let span = hygiene::walk_chain(err_arg.span, try_arg.span.ctxt());
53-
let mut applicability = Applicability::MachineApplicable;
54-
let origin_snippet = snippet_with_applicability(cx, span, "_", &mut applicability);
55-
let ret_prefix = if get_parent_expr(cx, expr).map_or(false, |e| matches!(e.kind, ExprKind::Ret(_))) {
56-
"" // already returns
57-
} else {
58-
"return "
59-
};
60-
let suggestion = if err_ty == expr_err_ty {
61-
format!("{ret_prefix}{prefix}{origin_snippet}{suffix}")
62-
} else {
63-
format!("{ret_prefix}{prefix}{origin_snippet}.into(){suffix}")
64-
};
65-
66-
span_lint_and_sugg(
51+
span_lint_and_then(
6752
cx,
6853
TRY_ERR,
6954
expr.span,
7055
"returning an `Err(_)` with the `?` operator",
71-
"try",
72-
suggestion,
73-
applicability,
56+
|diag| {
57+
let expr_err_ty = cx.typeck_results().expr_ty(err_arg);
58+
let span = hygiene::walk_chain(err_arg.span, try_arg.span.ctxt());
59+
let mut applicability = Applicability::MachineApplicable;
60+
let origin_snippet = snippet_with_applicability(cx, span, "_", &mut applicability);
61+
let ret_prefix = if get_parent_expr(cx, expr).map_or(false, |e| matches!(e.kind, ExprKind::Ret(_))) {
62+
"" // already returns
63+
} else {
64+
"return "
65+
};
66+
let suggestion = if err_ty == expr_err_ty {
67+
format!("{ret_prefix}{prefix}{origin_snippet}{suffix}")
68+
} else {
69+
format!("{ret_prefix}{prefix}{origin_snippet}.into(){suffix}")
70+
};
71+
diag.span_suggestion(expr.span, "try", suggestion, applicability);
72+
},
7473
);
7574
}
7675
}

clippy_lints/src/methods/verbose_file_reads.rs

+5-2
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_trait_method;
33
use clippy_utils::ty::is_type_diagnostic_item;
44
use rustc_hir::{Expr, ExprKind, QPath};
@@ -23,6 +23,9 @@ pub(super) fn check<'tcx>(
2323
&& matches!(recv.kind, ExprKind::Path(QPath::Resolved(None, _)))
2424
&& is_type_diagnostic_item(cx, cx.typeck_results().expr_ty_adjusted(recv).peel_refs(), sym::File)
2525
{
26-
span_lint_and_help(cx, VERBOSE_FILE_READS, expr.span, msg, None, help);
26+
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
27+
span_lint_and_then(cx, VERBOSE_FILE_READS, expr.span, msg, |diag| {
28+
diag.help(help);
29+
});
2730
}
2831
}

clippy_lints/src/misc_early/literal_suffix.rs

+21-9
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 rustc_errors::Applicability;
33
use rustc_lint::EarlyContext;
44
use rustc_span::Span;
@@ -12,24 +12,36 @@ pub(super) fn check(cx: &EarlyContext<'_>, lit_span: Span, lit_snip: &str, suffi
1212
// Do not lint when literal is unsuffixed.
1313
if !suffix.is_empty() {
1414
if lit_snip.as_bytes()[maybe_last_sep_idx] == b'_' {
15-
span_lint_and_sugg(
15+
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
16+
span_lint_and_then(
1617
cx,
1718
SEPARATED_LITERAL_SUFFIX,
1819
lit_span,
1920
format!("{sugg_type} type suffix should not be separated by an underscore"),
20-
"remove the underscore",
21-
format!("{}{suffix}", &lit_snip[..maybe_last_sep_idx]),
22-
Applicability::MachineApplicable,
21+
|diag| {
22+
diag.span_suggestion(
23+
lit_span,
24+
"remove the underscore",
25+
format!("{}{suffix}", &lit_snip[..maybe_last_sep_idx]),
26+
Applicability::MachineApplicable,
27+
);
28+
},
2329
);
2430
} else {
25-
span_lint_and_sugg(
31+
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
32+
span_lint_and_then(
2633
cx,
2734
UNSEPARATED_LITERAL_SUFFIX,
2835
lit_span,
2936
format!("{sugg_type} type suffix should be separated by an underscore"),
30-
"add an underscore",
31-
format!("{}_{suffix}", &lit_snip[..=maybe_last_sep_idx]),
32-
Applicability::MachineApplicable,
37+
|diag| {
38+
diag.span_suggestion(
39+
lit_span,
40+
"add an underscore",
41+
format!("{}_{suffix}", &lit_snip[..=maybe_last_sep_idx]),
42+
Applicability::MachineApplicable,
43+
);
44+
},
3345
);
3446
}
3547
}

clippy_lints/src/misc_early/unneeded_field_pattern.rs

+12-9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
1+
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
22
use clippy_utils::source::snippet_opt;
33
use rustc_ast::ast::{Pat, PatKind};
44
use rustc_lint::EarlyContext;
@@ -21,13 +21,15 @@ pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) {
2121
}
2222
}
2323
if !pfields.is_empty() && wilds == pfields.len() {
24-
span_lint_and_help(
24+
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
25+
span_lint_and_then(
2526
cx,
2627
UNNEEDED_FIELD_PATTERN,
2728
pat.span,
2829
"all the struct fields are matched to a wildcard pattern, consider using `..`",
29-
None,
30-
format!("try with `{type_name} {{ .. }}` instead"),
30+
|diag| {
31+
diag.help(format!("try with `{type_name} {{ .. }}` instead"));
32+
},
3133
);
3234
return;
3335
}
@@ -56,14 +58,15 @@ pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) {
5658
}
5759
}
5860

59-
span_lint_and_help(
61+
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
62+
span_lint_and_then(
6063
cx,
6164
UNNEEDED_FIELD_PATTERN,
6265
field.span,
63-
"you matched a field with a wildcard pattern, consider using `..` \
64-
instead",
65-
None,
66-
format!("try with `{type_name} {{ {}, .. }}`", normal[..].join(", ")),
66+
"you matched a field with a wildcard pattern, consider using `..` instead",
67+
|diag| {
68+
diag.help(format!("try with `{type_name} {{ {}, .. }}`", normal[..].join(", ")));
69+
},
6770
);
6871
}
6972
}

clippy_lints/src/question_mark_used.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

33
use clippy_utils::macros::span_is_local;
44
use rustc_hir::{Expr, ExprKind, MatchSource};
@@ -39,13 +39,15 @@ impl<'tcx> LateLintPass<'tcx> for QuestionMarkUsed {
3939
return;
4040
}
4141

42-
span_lint_and_help(
42+
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
43+
span_lint_and_then(
4344
cx,
4445
QUESTION_MARK_USED,
4546
expr.span,
4647
"question mark operator was used",
47-
None,
48-
"consider using a custom macro or match expression",
48+
|diag| {
49+
diag.help("consider using a custom macro or match expression");
50+
},
4951
);
5052
}
5153
}

clippy_lints/src/ref_patterns.rs

+5-9
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 rustc_ast::ast::{BindingMode, Pat, PatKind};
33
use rustc_lint::{EarlyContext, EarlyLintPass};
44
use rustc_session::declare_lint_pass;
@@ -33,14 +33,10 @@ impl EarlyLintPass for RefPatterns {
3333
if let PatKind::Ident(BindingMode::REF, _, _) = pat.kind
3434
&& !pat.span.from_expansion()
3535
{
36-
span_lint_and_help(
37-
cx,
38-
REF_PATTERNS,
39-
pat.span,
40-
"usage of ref pattern",
41-
None,
42-
"consider using `&` for clarity instead",
43-
);
36+
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
37+
span_lint_and_then(cx, REF_PATTERNS, pat.span, "usage of ref pattern", |diag| {
38+
diag.help("consider using `&` for clarity instead");
39+
});
4440
}
4541
}
4642
}

clippy_lints/src/shadow.rs

+4-9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use clippy_utils::diagnostics::span_lint_and_note;
1+
use clippy_utils::diagnostics::span_lint_and_then;
22
use clippy_utils::source::snippet;
33
use clippy_utils::visitors::is_local_used;
44
use rustc_data_structures::fx::FxHashMap;
@@ -194,14 +194,9 @@ fn lint_shadow(cx: &LateContext<'_>, pat: &Pat<'_>, shadowed: HirId, span: Span)
194194
(SHADOW_UNRELATED, msg)
195195
},
196196
};
197-
span_lint_and_note(
198-
cx,
199-
lint,
200-
span,
201-
msg,
202-
Some(cx.tcx.hir().span(shadowed)),
203-
"previous binding is here",
204-
);
197+
span_lint_and_then(cx, lint, span, msg, |diag| {
198+
diag.span_note(cx.tcx.hir().span(shadowed), "previous binding is here");
199+
});
205200
}
206201

207202
/// Returns true if the expression is a simple transformation of a local binding such as `&x`

clippy_lints/src/single_char_lifetime_names.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 rustc_ast::ast::{GenericParam, GenericParamKind};
33
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
44
use rustc_middle::lint::in_external_macro;
@@ -48,13 +48,15 @@ impl EarlyLintPass for SingleCharLifetimeNames {
4848

4949
if let GenericParamKind::Lifetime = param.kind {
5050
if !param.is_placeholder && param.ident.as_str().len() <= 2 {
51-
span_lint_and_help(
51+
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
52+
span_lint_and_then(
5253
ctx,
5354
SINGLE_CHAR_LIFETIME_NAMES,
5455
param.ident.span,
5556
"single-character lifetime names are likely uninformative",
56-
None,
57-
"use a more informative name",
57+
|diag| {
58+
diag.help("use a more informative name");
59+
},
5860
);
5961
}
6062
}

clippy_lints/src/strings.rs

+12-11
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg};
1+
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
22
use clippy_utils::source::{snippet, snippet_with_applicability};
33
use clippy_utils::ty::is_type_lang_item;
44
use clippy_utils::{
@@ -399,17 +399,16 @@ impl<'tcx> LateLintPass<'tcx> for StrToString {
399399
&& let ty::Ref(_, ty, ..) = ty.kind()
400400
&& ty.is_str()
401401
{
402-
let mut applicability = Applicability::MachineApplicable;
403-
let snippet = snippet_with_applicability(cx, self_arg.span, "..", &mut applicability);
404-
405-
span_lint_and_sugg(
402+
span_lint_and_then(
406403
cx,
407404
STR_TO_STRING,
408405
expr.span,
409406
"`to_string()` called on a `&str`",
410-
"try",
411-
format!("{snippet}.to_owned()"),
412-
applicability,
407+
|diag| {
408+
let mut applicability = Applicability::MachineApplicable;
409+
let snippet = snippet_with_applicability(cx, self_arg.span, "..", &mut applicability);
410+
diag.span_suggestion(expr.span, "try", format!("{snippet}.to_owned()"), applicability);
411+
},
413412
);
414413
}
415414
}
@@ -455,13 +454,15 @@ impl<'tcx> LateLintPass<'tcx> for StringToString {
455454
&& let ty = cx.typeck_results().expr_ty(self_arg)
456455
&& is_type_lang_item(cx, ty, LangItem::String)
457456
{
458-
span_lint_and_help(
457+
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
458+
span_lint_and_then(
459459
cx,
460460
STRING_TO_STRING,
461461
expr.span,
462462
"`to_string()` called on a `String`",
463-
None,
464-
"consider using `.clone()`",
463+
|diag| {
464+
diag.help("consider using `.clone()`");
465+
},
465466
);
466467
}
467468
}

0 commit comments

Comments
 (0)