Make restriction lint's use span_lint_and_then (q -> s)

This commit is contained in:
xFrednet 2024-07-22 20:32:27 +02:00
parent 1ec502569e
commit 7de9c20145
No known key found for this signature in database
GPG Key ID: F5C59D0E669E5302
12 changed files with 163 additions and 101 deletions

View File

@ -1,4 +1,4 @@
use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::diagnostics::span_lint_and_then;
use rustc_hir::{Pat, PatKind, QPath}; use rustc_hir::{Pat, PatKind, QPath};
use rustc_lint::LateContext; use rustc_lint::LateContext;
use rustc_middle::ty; use rustc_middle::ty;
@ -15,13 +15,15 @@ pub(crate) fn check(cx: &LateContext<'_>, pat: &Pat<'_>) {
&& fields.len() == def.non_enum_variant().fields.len() && fields.len() == def.non_enum_variant().fields.len()
&& !def.non_enum_variant().is_field_list_non_exhaustive() && !def.non_enum_variant().is_field_list_non_exhaustive()
{ {
span_lint_and_help( #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
span_lint_and_then(
cx, cx,
REST_PAT_IN_FULLY_BOUND_STRUCTS, REST_PAT_IN_FULLY_BOUND_STRUCTS,
pat.span, pat.span,
"unnecessary use of `..` pattern in struct binding. All fields were already bound", "unnecessary use of `..` pattern in struct binding. All fields were already bound",
None, |diag| {
"consider removing `..` from this binding", diag.help("consider removing `..` from this binding");
},
); );
} }
} }

View File

@ -1,4 +1,4 @@
use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::diagnostics::span_lint_and_then;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_lint::EarlyContext; use rustc_lint::EarlyContext;
use rustc_span::Span; use rustc_span::Span;
@ -12,24 +12,36 @@ pub(super) fn check(cx: &EarlyContext<'_>, lit_span: Span, lit_snip: &str, suffi
// Do not lint when literal is unsuffixed. // Do not lint when literal is unsuffixed.
if !suffix.is_empty() { if !suffix.is_empty() {
if lit_snip.as_bytes()[maybe_last_sep_idx] == b'_' { if lit_snip.as_bytes()[maybe_last_sep_idx] == b'_' {
span_lint_and_sugg( #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
span_lint_and_then(
cx, cx,
SEPARATED_LITERAL_SUFFIX, SEPARATED_LITERAL_SUFFIX,
lit_span, lit_span,
format!("{sugg_type} type suffix should not be separated by an underscore"), format!("{sugg_type} type suffix should not be separated by an underscore"),
"remove the underscore", |diag| {
format!("{}{suffix}", &lit_snip[..maybe_last_sep_idx]), diag.span_suggestion(
Applicability::MachineApplicable, lit_span,
"remove the underscore",
format!("{}{suffix}", &lit_snip[..maybe_last_sep_idx]),
Applicability::MachineApplicable,
);
},
); );
} else { } else {
span_lint_and_sugg( #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
span_lint_and_then(
cx, cx,
UNSEPARATED_LITERAL_SUFFIX, UNSEPARATED_LITERAL_SUFFIX,
lit_span, lit_span,
format!("{sugg_type} type suffix should be separated by an underscore"), format!("{sugg_type} type suffix should be separated by an underscore"),
"add an underscore", |diag| {
format!("{}_{suffix}", &lit_snip[..=maybe_last_sep_idx]), diag.span_suggestion(
Applicability::MachineApplicable, lit_span,
"add an underscore",
format!("{}_{suffix}", &lit_snip[..=maybe_last_sep_idx]),
Applicability::MachineApplicable,
);
},
); );
} }
} }

View File

@ -1,4 +1,4 @@
use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::macros::span_is_local; use clippy_utils::macros::span_is_local;
use rustc_hir::{Expr, ExprKind, MatchSource}; use rustc_hir::{Expr, ExprKind, MatchSource};
@ -39,13 +39,15 @@ impl<'tcx> LateLintPass<'tcx> for QuestionMarkUsed {
return; return;
} }
span_lint_and_help( #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
span_lint_and_then(
cx, cx,
QUESTION_MARK_USED, QUESTION_MARK_USED,
expr.span, expr.span,
"question mark operator was used", "question mark operator was used",
None, |diag| {
"consider using a custom macro or match expression", diag.help("consider using a custom macro or match expression");
},
); );
} }
} }

View File

@ -1,4 +1,4 @@
use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::diagnostics::span_lint_and_then;
use rustc_ast::ast::{BindingMode, Pat, PatKind}; use rustc_ast::ast::{BindingMode, Pat, PatKind};
use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::declare_lint_pass; use rustc_session::declare_lint_pass;
@ -33,14 +33,10 @@ impl EarlyLintPass for RefPatterns {
if let PatKind::Ident(BindingMode::REF, _, _) = pat.kind if let PatKind::Ident(BindingMode::REF, _, _) = pat.kind
&& !pat.span.from_expansion() && !pat.span.from_expansion()
{ {
span_lint_and_help( #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
cx, span_lint_and_then(cx, REF_PATTERNS, pat.span, "usage of ref pattern", |diag| {
REF_PATTERNS, diag.help("consider using `&` for clarity instead");
pat.span, });
"usage of ref pattern",
None,
"consider using `&` for clarity instead",
);
} }
} }
} }

View File

@ -1,4 +1,4 @@
use clippy_utils::diagnostics::span_lint_and_note; use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet; use clippy_utils::source::snippet;
use clippy_utils::visitors::is_local_used; use clippy_utils::visitors::is_local_used;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
@ -194,14 +194,9 @@ fn lint_shadow(cx: &LateContext<'_>, pat: &Pat<'_>, shadowed: HirId, span: Span)
(SHADOW_UNRELATED, msg) (SHADOW_UNRELATED, msg)
}, },
}; };
span_lint_and_note( span_lint_and_then(cx, lint, span, msg, |diag| {
cx, diag.span_note(cx.tcx.hir().span(shadowed), "previous binding is here");
lint, });
span,
msg,
Some(cx.tcx.hir().span(shadowed)),
"previous binding is here",
);
} }
/// Returns true if the expression is a simple transformation of a local binding such as `&x` /// Returns true if the expression is a simple transformation of a local binding such as `&x`

View File

@ -1,4 +1,4 @@
use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::diagnostics::span_lint_and_then;
use rustc_ast::ast::{GenericParam, GenericParamKind}; use rustc_ast::ast::{GenericParam, GenericParamKind};
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
use rustc_middle::lint::in_external_macro; use rustc_middle::lint::in_external_macro;
@ -48,13 +48,15 @@ impl EarlyLintPass for SingleCharLifetimeNames {
if let GenericParamKind::Lifetime = param.kind { if let GenericParamKind::Lifetime = param.kind {
if !param.is_placeholder && param.ident.as_str().len() <= 2 { if !param.is_placeholder && param.ident.as_str().len() <= 2 {
span_lint_and_help( #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
span_lint_and_then(
ctx, ctx,
SINGLE_CHAR_LIFETIME_NAMES, SINGLE_CHAR_LIFETIME_NAMES,
param.ident.span, param.ident.span,
"single-character lifetime names are likely uninformative", "single-character lifetime names are likely uninformative",
None, |diag| {
"use a more informative name", diag.help("use a more informative name");
},
); );
} }
} }

View File

@ -1,6 +1,6 @@
use clippy_config::msrvs::Msrv; use clippy_config::msrvs::Msrv;
use clippy_config::Conf; use clippy_config::Conf;
use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_from_proc_macro; use clippy_utils::is_from_proc_macro;
use rustc_attr::{StabilityLevel, StableSince}; use rustc_attr::{StabilityLevel, StableSince};
use rustc_errors::Applicability; use rustc_errors::Applicability;
@ -136,14 +136,20 @@ impl<'tcx> LateLintPass<'tcx> for StdReexports {
_ => return, _ => return,
}; };
if first_segment.ident.span != self.prev_span { if first_segment.ident.span != self.prev_span {
span_lint_and_sugg( #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
span_lint_and_then(
cx, cx,
lint, lint,
first_segment.ident.span, first_segment.ident.span,
format!("used import from `{used_mod}` instead of `{replace_with}`"), format!("used import from `{used_mod}` instead of `{replace_with}`"),
format!("consider importing the item from `{replace_with}`"), |diag| {
replace_with.to_string(), diag.span_suggestion(
Applicability::MachineApplicable, first_segment.ident.span,
format!("consider importing the item from `{replace_with}`"),
replace_with.to_string(),
Applicability::MachineApplicable,
);
},
); );
self.prev_span = first_segment.ident.span; self.prev_span = first_segment.ident.span;
} }

View File

@ -1,4 +1,4 @@
use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg}; use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
use clippy_utils::source::{snippet, snippet_with_applicability}; use clippy_utils::source::{snippet, snippet_with_applicability};
use clippy_utils::ty::is_type_lang_item; use clippy_utils::ty::is_type_lang_item;
use clippy_utils::{ use clippy_utils::{
@ -399,17 +399,16 @@ impl<'tcx> LateLintPass<'tcx> for StrToString {
&& let ty::Ref(_, ty, ..) = ty.kind() && let ty::Ref(_, ty, ..) = ty.kind()
&& ty.is_str() && ty.is_str()
{ {
let mut applicability = Applicability::MachineApplicable; span_lint_and_then(
let snippet = snippet_with_applicability(cx, self_arg.span, "..", &mut applicability);
span_lint_and_sugg(
cx, cx,
STR_TO_STRING, STR_TO_STRING,
expr.span, expr.span,
"`to_string()` called on a `&str`", "`to_string()` called on a `&str`",
"try", |diag| {
format!("{snippet}.to_owned()"), let mut applicability = Applicability::MachineApplicable;
applicability, let snippet = snippet_with_applicability(cx, self_arg.span, "..", &mut applicability);
diag.span_suggestion(expr.span, "try", format!("{snippet}.to_owned()"), applicability);
},
); );
} }
} }
@ -455,13 +454,15 @@ impl<'tcx> LateLintPass<'tcx> for StringToString {
&& let ty = cx.typeck_results().expr_ty(self_arg) && let ty = cx.typeck_results().expr_ty(self_arg)
&& is_type_lang_item(cx, ty, LangItem::String) && is_type_lang_item(cx, ty, LangItem::String)
{ {
span_lint_and_help( #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
span_lint_and_then(
cx, cx,
STRING_TO_STRING, STRING_TO_STRING,
expr.span, expr.span,
"`to_string()` called on a `String`", "`to_string()` called on a `String`",
None, |diag| {
"consider using `.clone()`", diag.help("consider using `.clone()`");
},
); );
} }
} }

View File

@ -1,4 +1,4 @@
use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::numeric_literal::NumericLiteral; use clippy_utils::numeric_literal::NumericLiteral;
use clippy_utils::source::snippet; use clippy_utils::source::snippet;
use rustc_ast::LitKind; use rustc_ast::LitKind;
@ -43,14 +43,19 @@ impl LateLintPass<'_> for ConfusingXorAndPow {
&& NumericLiteral::from_lit_kind(&snippet(cx, lit_right.span, ".."), &lit_right.node) && NumericLiteral::from_lit_kind(&snippet(cx, lit_right.span, ".."), &lit_right.node)
.is_some_and(|x| x.is_decimal()) .is_some_and(|x| x.is_decimal())
{ {
span_lint_and_sugg( span_lint_and_then(
cx, cx,
SUSPICIOUS_XOR_USED_AS_POW, SUSPICIOUS_XOR_USED_AS_POW,
expr.span, expr.span,
"`^` is not the exponentiation operator", "`^` is not the exponentiation operator",
"did you mean to write", |diag| {
format!("{}.pow({})", lit_left.node, lit_right.node), diag.span_suggestion_verbose(
Applicability::MaybeIncorrect, expr.span,
"did you mean to write",
format!("{}.pow({})", lit_left.node, lit_right.node),
Applicability::MaybeIncorrect,
);
},
); );
} }
} }

View File

@ -1,4 +1,4 @@
use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet_with_applicability; use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{path_def_id, qpath_generic_tys}; use clippy_utils::{path_def_id, qpath_generic_tys};
use rustc_errors::Applicability; use rustc_errors::Applicability;
@ -13,14 +13,15 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
let app = Applicability::Unspecified; let app = Applicability::Unspecified;
if cx.tcx.is_diagnostic_item(sym::Rc, def_id) { if cx.tcx.is_diagnostic_item(sym::Rc, def_id) {
if let Some(alternate) = match_buffer_type(cx, qpath) { if let Some(alternate) = match_buffer_type(cx, qpath) {
span_lint_and_sugg( #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
span_lint_and_then(
cx, cx,
RC_BUFFER, RC_BUFFER,
hir_ty.span, hir_ty.span,
"usage of `Rc<T>` when T is a buffer type", "usage of `Rc<T>` when T is a buffer type",
"try", |diag| {
format!("Rc<{alternate}>"), diag.span_suggestion(hir_ty.span, "try", format!("Rc<{alternate}>"), app);
app, },
); );
} else { } else {
let Some(ty) = qpath_generic_tys(qpath).next() else { let Some(ty) = qpath_generic_tys(qpath).next() else {
@ -35,31 +36,37 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
Some(ty) => ty.span, Some(ty) => ty.span,
None => return false, None => return false,
}; };
let mut applicability = app; span_lint_and_then(
span_lint_and_sugg(
cx, cx,
RC_BUFFER, RC_BUFFER,
hir_ty.span, hir_ty.span,
"usage of `Rc<T>` when T is a buffer type", "usage of `Rc<T>` when T is a buffer type",
"try", |diag| {
format!( let mut applicability = app;
"Rc<[{}]>", diag.span_suggestion(
snippet_with_applicability(cx, inner_span, "..", &mut applicability) hir_ty.span,
), "try",
app, format!(
"Rc<[{}]>",
snippet_with_applicability(cx, inner_span, "..", &mut applicability)
),
app,
);
},
); );
return true; return true;
} }
} else if cx.tcx.is_diagnostic_item(sym::Arc, def_id) { } else if cx.tcx.is_diagnostic_item(sym::Arc, def_id) {
if let Some(alternate) = match_buffer_type(cx, qpath) { if let Some(alternate) = match_buffer_type(cx, qpath) {
span_lint_and_sugg( #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
span_lint_and_then(
cx, cx,
RC_BUFFER, RC_BUFFER,
hir_ty.span, hir_ty.span,
"usage of `Arc<T>` when T is a buffer type", "usage of `Arc<T>` when T is a buffer type",
"try", |diag| {
format!("Arc<{alternate}>"), diag.span_suggestion(hir_ty.span, "try", format!("Arc<{alternate}>"), app);
app, },
); );
} else if let Some(ty) = qpath_generic_tys(qpath).next() { } else if let Some(ty) = qpath_generic_tys(qpath).next() {
let Some(id) = path_def_id(cx, ty) else { return false }; let Some(id) = path_def_id(cx, ty) else { return false };
@ -71,18 +78,23 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
Some(ty) => ty.span, Some(ty) => ty.span,
None => return false, None => return false,
}; };
let mut applicability = app; span_lint_and_then(
span_lint_and_sugg(
cx, cx,
RC_BUFFER, RC_BUFFER,
hir_ty.span, hir_ty.span,
"usage of `Arc<T>` when T is a buffer type", "usage of `Arc<T>` when T is a buffer type",
"try", |diag| {
format!( let mut applicability = app;
"Arc<[{}]>", diag.span_suggestion(
snippet_with_applicability(cx, inner_span, "..", &mut applicability) hir_ty.span,
), "try",
app, format!(
"Arc<[{}]>",
snippet_with_applicability(cx, inner_span, "..", &mut applicability)
),
app,
);
},
); );
return true; return true;
} }

View File

@ -1,4 +1,4 @@
use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::{path_def_id, qpath_generic_tys}; use clippy_utils::{path_def_id, qpath_generic_tys};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::{self as hir, QPath}; use rustc_hir::{self as hir, QPath};
@ -13,14 +13,10 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
&& let Some(id) = path_def_id(cx, arg) && let Some(id) = path_def_id(cx, arg)
&& cx.tcx.is_diagnostic_item(sym::Mutex, id) && cx.tcx.is_diagnostic_item(sym::Mutex, id)
{ {
span_lint_and_help( #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
cx, span_lint_and_then(cx, RC_MUTEX, hir_ty.span, "usage of `Rc<Mutex<_>>`", |diag| {
RC_MUTEX, diag.help("consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead");
hir_ty.span, });
"usage of `Rc<Mutex<_>>`",
None,
"consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead",
);
return true; return true;
} }

View File

@ -2,51 +2,84 @@ error: `^` is not the exponentiation operator
--> tests/ui/suspicious_xor_used_as_pow.rs:19:13 --> tests/ui/suspicious_xor_used_as_pow.rs:19:13
| |
LL | let _ = 2 ^ 5; LL | let _ = 2 ^ 5;
| ^^^^^ help: did you mean to write: `2.pow(5)` | ^^^^^
| |
= note: `-D clippy::suspicious-xor-used-as-pow` implied by `-D warnings` = note: `-D clippy::suspicious-xor-used-as-pow` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::suspicious_xor_used_as_pow)]` = help: to override `-D warnings` add `#[allow(clippy::suspicious_xor_used_as_pow)]`
help: did you mean to write
|
LL | let _ = 2.pow(5);
| ~~~~~~~~
error: `^` is not the exponentiation operator error: `^` is not the exponentiation operator
--> tests/ui/suspicious_xor_used_as_pow.rs:22:13 --> tests/ui/suspicious_xor_used_as_pow.rs:22:13
| |
LL | let _ = 2i32 ^ 9i32; LL | let _ = 2i32 ^ 9i32;
| ^^^^^^^^^^^ help: did you mean to write: `2i32.pow(9i32)` | ^^^^^^^^^^^
|
help: did you mean to write
|
LL | let _ = 2i32.pow(9i32);
| ~~~~~~~~~~~~~~
error: `^` is not the exponentiation operator error: `^` is not the exponentiation operator
--> tests/ui/suspicious_xor_used_as_pow.rs:24:13 --> tests/ui/suspicious_xor_used_as_pow.rs:24:13
| |
LL | let _ = 2i32 ^ 2i32; LL | let _ = 2i32 ^ 2i32;
| ^^^^^^^^^^^ help: did you mean to write: `2i32.pow(2i32)` | ^^^^^^^^^^^
|
help: did you mean to write
|
LL | let _ = 2i32.pow(2i32);
| ~~~~~~~~~~~~~~
error: `^` is not the exponentiation operator error: `^` is not the exponentiation operator
--> tests/ui/suspicious_xor_used_as_pow.rs:26:13 --> tests/ui/suspicious_xor_used_as_pow.rs:26:13
| |
LL | let _ = 50i32 ^ 3i32; LL | let _ = 50i32 ^ 3i32;
| ^^^^^^^^^^^^ help: did you mean to write: `50i32.pow(3i32)` | ^^^^^^^^^^^^
|
help: did you mean to write
|
LL | let _ = 50i32.pow(3i32);
| ~~~~~~~~~~~~~~~
error: `^` is not the exponentiation operator error: `^` is not the exponentiation operator
--> tests/ui/suspicious_xor_used_as_pow.rs:28:13 --> tests/ui/suspicious_xor_used_as_pow.rs:28:13
| |
LL | let _ = 5i32 ^ 8i32; LL | let _ = 5i32 ^ 8i32;
| ^^^^^^^^^^^ help: did you mean to write: `5i32.pow(8i32)` | ^^^^^^^^^^^
|
help: did you mean to write
|
LL | let _ = 5i32.pow(8i32);
| ~~~~~~~~~~~~~~
error: `^` is not the exponentiation operator error: `^` is not the exponentiation operator
--> tests/ui/suspicious_xor_used_as_pow.rs:30:13 --> tests/ui/suspicious_xor_used_as_pow.rs:30:13
| |
LL | let _ = 2i32 ^ 32i32; LL | let _ = 2i32 ^ 32i32;
| ^^^^^^^^^^^^ help: did you mean to write: `2i32.pow(32i32)` | ^^^^^^^^^^^^
|
help: did you mean to write
|
LL | let _ = 2i32.pow(32i32);
| ~~~~~~~~~~~~~~~
error: `^` is not the exponentiation operator error: `^` is not the exponentiation operator
--> tests/ui/suspicious_xor_used_as_pow.rs:13:9 --> tests/ui/suspicious_xor_used_as_pow.rs:13:9
| |
LL | 1 ^ 2 // should warn even if inside macro LL | 1 ^ 2 // should warn even if inside macro
| ^^^^^ help: did you mean to write: `1.pow(2)` | ^^^^^
... ...
LL | macro_test_inside!(); LL | macro_test_inside!();
| -------------------- in this macro invocation | -------------------- in this macro invocation
| |
= note: this error originates in the macro `macro_test_inside` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `macro_test_inside` (in Nightly builds, run with -Z macro-backtrace for more info)
help: did you mean to write
|
LL | 1.pow(2) // should warn even if inside macro
| ~~~~~~~~
error: aborting due to 7 previous errors error: aborting due to 7 previous errors