Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 6, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 19 additions & 15 deletions clippy_lints/src/matches/match_wild_enum.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{is_refutable, peel_hir_pat_refs, recurse_or_patterns};
use rustc_errors::Applicability;
@@ -148,23 +148,27 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) {
Applicability::MaybeIncorrect,
),
variants => {
let mut suggestions: Vec<_> = variants.iter().copied().map(format_suggestion).collect();
let message = if adt_def.is_variant_list_non_exhaustive() || has_external_hidden {
suggestions.push("_".into());
"wildcard matches known variants and will also match future added variants"
let (message, add_wildcard) = if adt_def.is_variant_list_non_exhaustive() || has_external_hidden {
(
"wildcard matches known variants and will also match future added variants",
true,
)
} else {
"wildcard match will also match any future added variants"
("wildcard match will also match any future added variants", false)
};

span_lint_and_sugg(
cx,
WILDCARD_ENUM_MATCH_ARM,
wildcard_span,
message,
"try",
suggestions.join(" | "),
Applicability::MaybeIncorrect,
);
span_lint_and_then(cx, WILDCARD_ENUM_MATCH_ARM, wildcard_span, message, |diag| {
let mut suggestions: Vec<_> = variants.iter().copied().map(format_suggestion).collect();
if add_wildcard {
suggestions.push("_".into());
}
diag.span_suggestion(
wildcard_span,
"try",
suggestions.join(" | "),
Applicability::MaybeIncorrect,
);
});
},
};
}
10 changes: 6 additions & 4 deletions clippy_lints/src/matches/rest_pat_in_fully_bound_struct.rs
Original file line number Diff line number Diff line change
@@ -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_lint::LateContext;
use rustc_middle::ty;
@@ -15,13 +15,15 @@ pub(crate) fn check(cx: &LateContext<'_>, pat: &Pat<'_>) {
&& fields.len() == def.non_enum_variant().fields.len()
&& !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,
REST_PAT_IN_FULLY_BOUND_STRUCTS,
pat.span,
"unnecessary use of `..` pattern in struct binding. All fields were already bound",
None,
"consider removing `..` from this binding",
|diag| {
diag.help("consider removing `..` from this binding");
},
);
}
}
39 changes: 19 additions & 20 deletions clippy_lints/src/matches/try_err.rs
Original file line number Diff line number Diff line change
@@ -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::ty::is_type_diagnostic_item;
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
return;
};

let expr_err_ty = cx.typeck_results().expr_ty(err_arg);
let span = hygiene::walk_chain(err_arg.span, try_arg.span.ctxt());
let mut applicability = Applicability::MachineApplicable;
let origin_snippet = snippet_with_applicability(cx, span, "_", &mut applicability);
let ret_prefix = if get_parent_expr(cx, expr).map_or(false, |e| matches!(e.kind, ExprKind::Ret(_))) {
"" // already returns
} else {
"return "
};
let suggestion = if err_ty == expr_err_ty {
format!("{ret_prefix}{prefix}{origin_snippet}{suffix}")
} else {
format!("{ret_prefix}{prefix}{origin_snippet}.into(){suffix}")
};

span_lint_and_sugg(
span_lint_and_then(
cx,
TRY_ERR,
expr.span,
"returning an `Err(_)` with the `?` operator",
"try",
suggestion,
applicability,
|diag| {
let expr_err_ty = cx.typeck_results().expr_ty(err_arg);
let span = hygiene::walk_chain(err_arg.span, try_arg.span.ctxt());
let mut applicability = Applicability::MachineApplicable;
let origin_snippet = snippet_with_applicability(cx, span, "_", &mut applicability);
let ret_prefix = if get_parent_expr(cx, expr).map_or(false, |e| matches!(e.kind, ExprKind::Ret(_))) {
"" // already returns
} else {
"return "
};
let suggestion = if err_ty == expr_err_ty {
format!("{ret_prefix}{prefix}{origin_snippet}{suffix}")
} else {
format!("{ret_prefix}{prefix}{origin_snippet}.into(){suffix}")
};
diag.span_suggestion(expr.span, "try", suggestion, applicability);
},
);
}
}
7 changes: 5 additions & 2 deletions clippy_lints/src/methods/verbose_file_reads.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_trait_method;
use clippy_utils::ty::is_type_diagnostic_item;
use rustc_hir::{Expr, ExprKind, QPath};
@@ -23,6 +23,9 @@ pub(super) fn check<'tcx>(
&& matches!(recv.kind, ExprKind::Path(QPath::Resolved(None, _)))
&& is_type_diagnostic_item(cx, cx.typeck_results().expr_ty_adjusted(recv).peel_refs(), sym::File)
{
span_lint_and_help(cx, VERBOSE_FILE_READS, expr.span, msg, None, help);
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
span_lint_and_then(cx, VERBOSE_FILE_READS, expr.span, msg, |diag| {
diag.help(help);
});
}
}
30 changes: 21 additions & 9 deletions clippy_lints/src/misc_early/literal_suffix.rs
Original file line number Diff line number Diff line change
@@ -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_lint::EarlyContext;
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.
if !suffix.is_empty() {
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,
SEPARATED_LITERAL_SUFFIX,
lit_span,
format!("{sugg_type} type suffix should not be separated by an underscore"),
"remove the underscore",
format!("{}{suffix}", &lit_snip[..maybe_last_sep_idx]),
Applicability::MachineApplicable,
|diag| {
diag.span_suggestion(
lit_span,
"remove the underscore",
format!("{}{suffix}", &lit_snip[..maybe_last_sep_idx]),
Applicability::MachineApplicable,
);
},
);
} else {
span_lint_and_sugg(
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
span_lint_and_then(
cx,
UNSEPARATED_LITERAL_SUFFIX,
lit_span,
format!("{sugg_type} type suffix should be separated by an underscore"),
"add an underscore",
format!("{}_{suffix}", &lit_snip[..=maybe_last_sep_idx]),
Applicability::MachineApplicable,
|diag| {
diag.span_suggestion(
lit_span,
"add an underscore",
format!("{}_{suffix}", &lit_snip[..=maybe_last_sep_idx]),
Applicability::MachineApplicable,
);
},
);
}
}
21 changes: 12 additions & 9 deletions clippy_lints/src/misc_early/unneeded_field_pattern.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
use clippy_utils::source::snippet_opt;
use rustc_ast::ast::{Pat, PatKind};
use rustc_lint::EarlyContext;
@@ -21,13 +21,15 @@ pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) {
}
}
if !pfields.is_empty() && wilds == pfields.len() {
span_lint_and_help(
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
span_lint_and_then(
cx,
UNNEEDED_FIELD_PATTERN,
pat.span,
"all the struct fields are matched to a wildcard pattern, consider using `..`",
None,
format!("try with `{type_name} {{ .. }}` instead"),
|diag| {
diag.help(format!("try with `{type_name} {{ .. }}` instead"));
},
);
return;
}
@@ -56,14 +58,15 @@ pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) {
}
}

span_lint_and_help(
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
span_lint_and_then(
cx,
UNNEEDED_FIELD_PATTERN,
field.span,
"you matched a field with a wildcard pattern, consider using `..` \
instead",
None,
format!("try with `{type_name} {{ {}, .. }}`", normal[..].join(", ")),
"you matched a field with a wildcard pattern, consider using `..` instead",
|diag| {
diag.help(format!("try with `{type_name} {{ {}, .. }}`", normal[..].join(", ")));
},
);
}
}
10 changes: 6 additions & 4 deletions clippy_lints/src/question_mark_used.rs
Original file line number Diff line number Diff line change
@@ -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 rustc_hir::{Expr, ExprKind, MatchSource};
@@ -39,13 +39,15 @@ impl<'tcx> LateLintPass<'tcx> for QuestionMarkUsed {
return;
}

span_lint_and_help(
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
span_lint_and_then(
cx,
QUESTION_MARK_USED,
expr.span,
"question mark operator was used",
None,
"consider using a custom macro or match expression",
|diag| {
diag.help("consider using a custom macro or match expression");
},
);
}
}
14 changes: 5 additions & 9 deletions clippy_lints/src/ref_patterns.rs
Original file line number Diff line number Diff line change
@@ -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_lint::{EarlyContext, EarlyLintPass};
use rustc_session::declare_lint_pass;
@@ -33,14 +33,10 @@ impl EarlyLintPass for RefPatterns {
if let PatKind::Ident(BindingMode::REF, _, _) = pat.kind
&& !pat.span.from_expansion()
{
span_lint_and_help(
cx,
REF_PATTERNS,
pat.span,
"usage of ref pattern",
None,
"consider using `&` for clarity instead",
);
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
span_lint_and_then(cx, REF_PATTERNS, pat.span, "usage of ref pattern", |diag| {
diag.help("consider using `&` for clarity instead");
});
}
}
}
13 changes: 4 additions & 9 deletions clippy_lints/src/shadow.rs
Original file line number Diff line number Diff line change
@@ -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::visitors::is_local_used;
use rustc_data_structures::fx::FxHashMap;
@@ -194,14 +194,9 @@ fn lint_shadow(cx: &LateContext<'_>, pat: &Pat<'_>, shadowed: HirId, span: Span)
(SHADOW_UNRELATED, msg)
},
};
span_lint_and_note(
cx,
lint,
span,
msg,
Some(cx.tcx.hir().span(shadowed)),
"previous binding is here",
);
span_lint_and_then(cx, lint, span, msg, |diag| {
diag.span_note(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`
10 changes: 6 additions & 4 deletions clippy_lints/src/single_char_lifetime_names.rs
Original file line number Diff line number Diff line change
@@ -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_lint::{EarlyContext, EarlyLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
@@ -48,13 +48,15 @@ impl EarlyLintPass for SingleCharLifetimeNames {

if let GenericParamKind::Lifetime = param.kind {
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,
SINGLE_CHAR_LIFETIME_NAMES,
param.ident.span,
"single-character lifetime names are likely uninformative",
None,
"use a more informative name",
|diag| {
diag.help("use a more informative name");
},
);
}
}
16 changes: 11 additions & 5 deletions clippy_lints/src/std_instead_of_core.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use clippy_config::msrvs::Msrv;
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 rustc_attr::{StabilityLevel, StableSince};
use rustc_errors::Applicability;
@@ -136,14 +136,20 @@ impl<'tcx> LateLintPass<'tcx> for StdReexports {
_ => return,
};
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,
lint,
first_segment.ident.span,
format!("used import from `{used_mod}` instead of `{replace_with}`"),
format!("consider importing the item from `{replace_with}`"),
replace_with.to_string(),
Applicability::MachineApplicable,
|diag| {
diag.span_suggestion(
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;
}
23 changes: 12 additions & 11 deletions clippy_lints/src/strings.rs
Original file line number Diff line number Diff line change
@@ -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::ty::is_type_lang_item;
use clippy_utils::{
@@ -399,17 +399,16 @@ impl<'tcx> LateLintPass<'tcx> for StrToString {
&& let ty::Ref(_, ty, ..) = ty.kind()
&& ty.is_str()
{
let mut applicability = Applicability::MachineApplicable;
let snippet = snippet_with_applicability(cx, self_arg.span, "..", &mut applicability);

span_lint_and_sugg(
span_lint_and_then(
cx,
STR_TO_STRING,
expr.span,
"`to_string()` called on a `&str`",
"try",
format!("{snippet}.to_owned()"),
applicability,
|diag| {
let mut applicability = Applicability::MachineApplicable;
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)
&& 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,
STRING_TO_STRING,
expr.span,
"`to_string()` called on a `String`",
None,
"consider using `.clone()`",
|diag| {
diag.help("consider using `.clone()`");
},
);
}
}
15 changes: 10 additions & 5 deletions clippy_lints/src/suspicious_xor_used_as_pow.rs
Original file line number Diff line number Diff line change
@@ -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::source::snippet;
use rustc_ast::LitKind;
@@ -43,14 +43,19 @@ impl LateLintPass<'_> for ConfusingXorAndPow {
&& NumericLiteral::from_lit_kind(&snippet(cx, lit_right.span, ".."), &lit_right.node)
.is_some_and(|x| x.is_decimal())
{
span_lint_and_sugg(
span_lint_and_then(
cx,
SUSPICIOUS_XOR_USED_AS_POW,
expr.span,
"`^` is not the exponentiation operator",
"did you mean to write",
format!("{}.pow({})", lit_left.node, lit_right.node),
Applicability::MaybeIncorrect,
|diag| {
diag.span_suggestion_verbose(
expr.span,
"did you mean to write",
format!("{}.pow({})", lit_left.node, lit_right.node),
Applicability::MaybeIncorrect,
);
},
);
}
}
10 changes: 6 additions & 4 deletions clippy_lints/src/tests_outside_test_module.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use clippy_utils::diagnostics::span_lint_and_note;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::{is_in_cfg_test, is_in_test_function};
use rustc_hir::intravisit::FnKind;
use rustc_hir::{Body, FnDecl};
@@ -61,13 +61,15 @@ impl LateLintPass<'_> for TestsOutsideTestModule {
&& is_in_test_function(cx.tcx, body.id().hir_id)
&& !is_in_cfg_test(cx.tcx, body.id().hir_id)
{
span_lint_and_note(
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
span_lint_and_then(
cx,
TESTS_OUTSIDE_TEST_MODULE,
sp,
"this function marked with #[test] is outside a #[cfg(test)] module",
None,
"move it to a testing module marked with #[cfg(test)]",
|diag| {
diag.note("move it to a testing module marked with #[cfg(test)]");
},
);
}
}
62 changes: 37 additions & 25 deletions clippy_lints/src/types/rc_buffer.rs
Original file line number Diff line number Diff line change
@@ -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::{path_def_id, qpath_generic_tys};
use rustc_errors::Applicability;
@@ -13,14 +13,15 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
let app = Applicability::Unspecified;
if cx.tcx.is_diagnostic_item(sym::Rc, def_id) {
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,
RC_BUFFER,
hir_ty.span,
"usage of `Rc<T>` when T is a buffer type",
"try",
format!("Rc<{alternate}>"),
app,
|diag| {
diag.span_suggestion(hir_ty.span, "try", format!("Rc<{alternate}>"), app);
},
);
} 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,
None => return false,
};
let mut applicability = app;
span_lint_and_sugg(
span_lint_and_then(
cx,
RC_BUFFER,
hir_ty.span,
"usage of `Rc<T>` when T is a buffer type",
"try",
format!(
"Rc<[{}]>",
snippet_with_applicability(cx, inner_span, "..", &mut applicability)
),
app,
|diag| {
let mut applicability = app;
diag.span_suggestion(
hir_ty.span,
"try",
format!(
"Rc<[{}]>",
snippet_with_applicability(cx, inner_span, "..", &mut applicability)
),
app,
);
},
);
return true;
}
} else if cx.tcx.is_diagnostic_item(sym::Arc, def_id) {
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,
RC_BUFFER,
hir_ty.span,
"usage of `Arc<T>` when T is a buffer type",
"try",
format!("Arc<{alternate}>"),
app,
|diag| {
diag.span_suggestion(hir_ty.span, "try", format!("Arc<{alternate}>"), app);
},
);
} else if let Some(ty) = qpath_generic_tys(qpath).next() {
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,
None => return false,
};
let mut applicability = app;
span_lint_and_sugg(
span_lint_and_then(
cx,
RC_BUFFER,
hir_ty.span,
"usage of `Arc<T>` when T is a buffer type",
"try",
format!(
"Arc<[{}]>",
snippet_with_applicability(cx, inner_span, "..", &mut applicability)
),
app,
|diag| {
let mut applicability = app;
diag.span_suggestion(
hir_ty.span,
"try",
format!(
"Arc<[{}]>",
snippet_with_applicability(cx, inner_span, "..", &mut applicability)
),
app,
);
},
);
return true;
}
14 changes: 5 additions & 9 deletions clippy_lints/src/types/rc_mutex.rs
Original file line number Diff line number Diff line change
@@ -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 rustc_hir::def_id::DefId;
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)
&& cx.tcx.is_diagnostic_item(sym::Mutex, id)
{
span_lint_and_help(
cx,
RC_MUTEX,
hir_ty.span,
"usage of `Rc<Mutex<_>>`",
None,
"consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead",
);
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
span_lint_and_then(cx, RC_MUTEX, hir_ty.span, "usage of `Rc<Mutex<_>>`", |diag| {
diag.help("consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead");
});
return true;
}

53 changes: 31 additions & 22 deletions clippy_lints/src/undocumented_unsafe_blocks.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::ops::ControlFlow;

use clippy_config::Conf;
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_lint_allowed;
use clippy_utils::source::walk_span_to_context;
use clippy_utils::visitors::{for_each_expr, Descend};
@@ -129,13 +129,15 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks {
block.span
};

span_lint_and_help(
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
span_lint_and_then(
cx,
UNDOCUMENTED_UNSAFE_BLOCKS,
span,
"unsafe block missing a safety comment",
None,
"consider adding a safety comment on the preceding line",
|diag| {
diag.help("consider adding a safety comment on the preceding line");
},
);
}

@@ -145,13 +147,14 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks {
&& let HasSafetyComment::Yes(pos) = stmt_has_safety_comment(cx, tail.span, tail.hir_id)
&& let Some(help_span) = expr_has_unnecessary_safety_comment(cx, tail, pos)
{
span_lint_and_help(
span_lint_and_then(
cx,
UNNECESSARY_SAFETY_COMMENT,
tail.span,
"expression has unnecessary safety comment",
Some(help_span),
"consider removing the safety comment",
|diag| {
diag.span_help(help_span, "consider removing the safety comment");
},
);
}
}
@@ -168,13 +171,14 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks {
&& let HasSafetyComment::Yes(pos) = stmt_has_safety_comment(cx, stmt.span, stmt.hir_id)
&& let Some(help_span) = expr_has_unnecessary_safety_comment(cx, expr, pos)
{
span_lint_and_help(
span_lint_and_then(
cx,
UNNECESSARY_SAFETY_COMMENT,
stmt.span,
"statement has unnecessary safety comment",
Some(help_span),
"consider removing the safety comment",
|diag| {
diag.span_help(help_span, "consider removing the safety comment");
},
);
}
}
@@ -210,13 +214,15 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks {
item.span
};

span_lint_and_help(
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
span_lint_and_then(
cx,
UNDOCUMENTED_UNSAFE_BLOCKS,
span,
"unsafe impl missing a safety comment",
None,
"consider adding a safety comment on the preceding line",
|diag| {
diag.help("consider adding a safety comment on the preceding line");
},
);
}
},
@@ -225,13 +231,14 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks {
if !is_lint_allowed(cx, UNNECESSARY_SAFETY_COMMENT, item.hir_id()) {
let (span, help_span) = mk_spans(pos);

span_lint_and_help(
span_lint_and_then(
cx,
UNNECESSARY_SAFETY_COMMENT,
span,
"impl has unnecessary safety comment",
Some(help_span),
"consider removing the safety comment",
|diag| {
diag.span_help(help_span, "consider removing the safety comment");
},
);
}
},
@@ -246,13 +253,14 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks {
) {
let (span, help_span) = mk_spans(pos);

span_lint_and_help(
span_lint_and_then(
cx,
UNNECESSARY_SAFETY_COMMENT,
span,
format!("{} has unnecessary safety comment", item.kind.descr()),
Some(help_span),
"consider removing the safety comment",
|diag| {
diag.span_help(help_span, "consider removing the safety comment");
},
);
}
}
@@ -263,13 +271,14 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks {
if !is_lint_allowed(cx, UNNECESSARY_SAFETY_COMMENT, item.hir_id()) {
let (span, help_span) = mk_spans(pos);

span_lint_and_help(
span_lint_and_then(
cx,
UNNECESSARY_SAFETY_COMMENT,
span,
format!("{} has unnecessary safety comment", item.kind.descr()),
Some(help_span),
"consider removing the safety comment",
|diag| {
diag.span_help(help_span, "consider removing the safety comment");
},
);
}
},
47 changes: 40 additions & 7 deletions tests/ui/suspicious_xor_used_as_pow.stderr
Original file line number Diff line number Diff line change
@@ -2,51 +2,84 @@ error: `^` is not the exponentiation operator
--> tests/ui/suspicious_xor_used_as_pow.rs:19:13
|
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`
= 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
--> tests/ui/suspicious_xor_used_as_pow.rs:22:13
|
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
--> tests/ui/suspicious_xor_used_as_pow.rs:24:13
|
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
--> tests/ui/suspicious_xor_used_as_pow.rs:26:13
|
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
--> tests/ui/suspicious_xor_used_as_pow.rs:28:13
|
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
--> tests/ui/suspicious_xor_used_as_pow.rs:30:13
|
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
--> tests/ui/suspicious_xor_used_as_pow.rs:13:9
|
LL | 1 ^ 2 // should warn even if inside macro
| ^^^^^ help: did you mean to write: `1.pow(2)`
| ^^^^^
...
LL | macro_test_inside!();
| -------------------- 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)
help: did you mean to write
|
LL | 1.pow(2) // should warn even if inside macro
| ~~~~~~~~

error: aborting due to 7 previous errors