Skip to content
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
10 changes: 6 additions & 4 deletions clippy_lints/src/as_conversions.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_from_proc_macro;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
@@ -52,13 +52,15 @@ impl<'tcx> LateLintPass<'tcx> for AsConversions {
&& !in_external_macro(cx.sess(), expr.span)
&& !is_from_proc_macro(cx, expr)
{
span_lint_and_help(
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
span_lint_and_then(
cx,
AS_CONVERSIONS,
expr.span,
"using a potentially dangerous silent `as` conversion",
None,
"consider using a safe wrapper for this conversion",
|diag| {
diag.help("consider using a safe wrapper for this conversion");
},
);
}
}
47 changes: 18 additions & 29 deletions clippy_lints/src/assertions_on_result_states.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::macros::{find_assert_args, root_macro_call_first_node, PanicExpn};
use clippy_utils::source::snippet_with_context;
use clippy_utils::ty::{has_debug_impl, is_copy, is_type_diagnostic_item};
@@ -68,39 +68,28 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnResultStates {
return;
}
}
let semicolon = if is_expr_final_block_expr(cx.tcx, e) { ";" } else { "" };
let mut app = Applicability::MachineApplicable;
match method_segment.ident.as_str() {
let (message, replacement) = match method_segment.ident.as_str() {
"is_ok" if type_suitable_to_unwrap(cx, args.type_at(1)) => {
span_lint_and_sugg(
cx,
ASSERTIONS_ON_RESULT_STATES,
macro_call.span,
"called `assert!` with `Result::is_ok`",
"replace with",
format!(
"{}.unwrap(){semicolon}",
snippet_with_context(cx, recv.span, condition.span.ctxt(), "..", &mut app).0
),
app,
);
("called `assert!` with `Result::is_ok`", "unwrap")
},
"is_err" if type_suitable_to_unwrap(cx, args.type_at(0)) => {
span_lint_and_sugg(
cx,
ASSERTIONS_ON_RESULT_STATES,
macro_call.span,
"called `assert!` with `Result::is_err`",
"replace with",
format!(
"{}.unwrap_err(){semicolon}",
snippet_with_context(cx, recv.span, condition.span.ctxt(), "..", &mut app).0
),
app,
);
("called `assert!` with `Result::is_err`", "unwrap_err")
},
_ => (),
_ => return,
};
span_lint_and_then(cx, ASSERTIONS_ON_RESULT_STATES, macro_call.span, message, |diag| {
let semicolon = if is_expr_final_block_expr(cx.tcx, e) { ";" } else { "" };
let mut app = Applicability::MachineApplicable;
diag.span_suggestion(
macro_call.span,
"replace with",
format!(
"{}.{replacement}(){semicolon}",
snippet_with_context(cx, recv.span, condition.span.ctxt(), "..", &mut app).0
),
app,
);
});
}
}
}
20 changes: 10 additions & 10 deletions clippy_lints/src/attrs/allow_attributes.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::ALLOW_ATTRIBUTES;
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_ast::{AttrStyle, Attribute};
use rustc_errors::Applicability;
@@ -13,14 +13,14 @@ pub fn check<'cx>(cx: &LateContext<'cx>, attr: &'cx Attribute) {
&& let Some(ident) = attr.ident()
&& !is_from_proc_macro(cx, attr)
{
span_lint_and_sugg(
cx,
ALLOW_ATTRIBUTES,
ident.span,
"#[allow] attribute found",
"replace it with",
"expect".into(),
Applicability::MachineApplicable,
);
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
span_lint_and_then(cx, ALLOW_ATTRIBUTES, ident.span, "#[allow] attribute found", |diag| {
diag.span_suggestion(
ident.span,
"replace it with",
"expect",
Applicability::MachineApplicable,
);
});
}
}
10 changes: 6 additions & 4 deletions clippy_lints/src/attrs/allow_attributes_without_reason.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::{Attribute, ALLOW_ATTRIBUTES_WITHOUT_REASON};
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_from_proc_macro;
use rustc_ast::{MetaItemKind, NestedMetaItem};
use rustc_lint::{LateContext, LintContext};
@@ -21,12 +21,14 @@ pub(super) fn check<'cx>(cx: &LateContext<'cx>, name: Symbol, items: &[NestedMet
return;
}

span_lint_and_help(
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
span_lint_and_then(
cx,
ALLOW_ATTRIBUTES_WITHOUT_REASON,
attr.span,
format!("`{}` attribute without specifying a reason", name.as_str()),
None,
"try adding a reason at the end with `, reason = \"..\"`",
|diag| {
diag.help("try adding a reason at the end with `, reason = \"..\"`");
},
);
}
37 changes: 20 additions & 17 deletions clippy_lints/src/casts/fn_to_numeric_cast_any.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet_with_applicability;
use rustc_errors::Applicability;
use rustc_errors::{Applicability, SuggestionStyle};
use rustc_hir::Expr;
use rustc_lint::LateContext;
use rustc_middle::ty::{self, Ty};
@@ -14,21 +14,24 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
_ => { /* continue to checks */ },
}

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

span_lint_and_sugg(
cx,
FN_TO_NUMERIC_CAST_ANY,
expr.span,
format!("casting function pointer `{from_snippet}` to `{cast_to}`"),
"did you mean to invoke the function?",
format!("{from_snippet}() as {cast_to}"),
applicability,
);
},
_ => {},
span_lint_and_then(
cx,
FN_TO_NUMERIC_CAST_ANY,
expr.span,
format!("casting function pointer `{from_snippet}` to `{cast_to}`"),
|diag| {
diag.span_suggestion_with_style(
expr.span,
"did you mean to invoke the function?",
format!("{from_snippet}() as {cast_to}"),
applicability,
SuggestionStyle::ShowAlways,
);
},
);
}
}
24 changes: 17 additions & 7 deletions clippy_lints/src/create_dir.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet;
use rustc_errors::Applicability;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet_with_applicability;
use rustc_errors::{Applicability, SuggestionStyle};
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
@@ -39,14 +39,24 @@ impl LateLintPass<'_> for CreateDir {
&& let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id()
&& cx.tcx.is_diagnostic_item(sym::fs_create_dir, def_id)
{
span_lint_and_sugg(
span_lint_and_then(
cx,
CREATE_DIR,
expr.span,
"calling `std::fs::create_dir` where there may be a better way",
"consider calling `std::fs::create_dir_all` instead",
format!("create_dir_all({})", snippet(cx, arg.span, "..")),
Applicability::MaybeIncorrect,
|diag| {
let mut app = Applicability::MaybeIncorrect;
diag.span_suggestion_with_style(
expr.span,
"consider calling `std::fs::create_dir_all` instead",
format!(
"create_dir_all({})",
snippet_with_applicability(cx, arg.span, "..", &mut app)
),
app,
SuggestionStyle::ShowAlways,
);
},
);
}
}
108 changes: 57 additions & 51 deletions clippy_lints/src/dbg_macro.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use clippy_config::Conf;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_in_test;
use clippy_utils::macros::{macro_backtrace, MacroCall};
use clippy_utils::source::snippet_with_applicability;
@@ -65,61 +65,67 @@ impl LateLintPass<'_> for DbgMacro {
// allows `dbg!` in test code if allow-dbg-in-test is set to true in clippy.toml
!(self.allow_dbg_in_tests && is_in_test(cx.tcx, expr.hir_id))
{
let mut applicability = Applicability::MachineApplicable;

let (sugg_span, suggestion) = match expr.peel_drop_temps().kind {
// dbg!()
ExprKind::Block(..) => {
// If the `dbg!` macro is a "free" statement and not contained within other expressions,
// remove the whole statement.
if let Node::Stmt(_) = cx.tcx.parent_hir_node(expr.hir_id)
&& let Some(semi_span) = cx.sess().source_map().mac_call_stmt_semi_span(macro_call.span)
{
(macro_call.span.to(semi_span), String::new())
} else {
(macro_call.span, String::from("()"))
}
},
// dbg!(1)
ExprKind::Match(val, ..) => (
macro_call.span,
snippet_with_applicability(cx, val.span.source_callsite(), "..", &mut applicability).to_string(),
),
// dbg!(2, 3)
ExprKind::Tup(
[
Expr {
kind: ExprKind::Match(first, ..),
..
},
..,
Expr {
kind: ExprKind::Match(last, ..),
..
},
],
) => {
let snippet = snippet_with_applicability(
cx,
first.span.source_callsite().to(last.span.source_callsite()),
"..",
&mut applicability,
);
(macro_call.span, format!("({snippet})"))
},
_ => return,
};

self.prev_ctxt = cur_syntax_ctxt;

span_lint_and_sugg(
span_lint_and_then(
cx,
DBG_MACRO,
sugg_span,
macro_call.span,
"the `dbg!` macro is intended as a debugging tool",
"remove the invocation before committing it to a version control system",
suggestion,
applicability,
|diag| {
let mut applicability = Applicability::MachineApplicable;

let (sugg_span, suggestion) = match expr.peel_drop_temps().kind {
// dbg!()
ExprKind::Block(..) => {
// If the `dbg!` macro is a "free" statement and not contained within other expressions,
// remove the whole statement.
if let Node::Stmt(_) = cx.tcx.parent_hir_node(expr.hir_id)
&& let Some(semi_span) = cx.sess().source_map().mac_call_stmt_semi_span(macro_call.span)
{
(macro_call.span.to(semi_span), String::new())
} else {
(macro_call.span, String::from("()"))
}
},
// dbg!(1)
ExprKind::Match(val, ..) => (
macro_call.span,
snippet_with_applicability(cx, val.span.source_callsite(), "..", &mut applicability)
.to_string(),
),
// dbg!(2, 3)
ExprKind::Tup(
[
Expr {
kind: ExprKind::Match(first, ..),
..
},
..,
Expr {
kind: ExprKind::Match(last, ..),
..
},
],
) => {
let snippet = snippet_with_applicability(
cx,
first.span.source_callsite().to(last.span.source_callsite()),
"..",
&mut applicability,
);
(macro_call.span, format!("({snippet})"))
},
_ => unreachable!(),
};

diag.span_suggestion(
sugg_span,
"remove the invocation before committing it to a version control system",
suggestion,
applicability,
);
},
);
}
}
23 changes: 11 additions & 12 deletions clippy_lints/src/default_numeric_fallback.rs
Original file line number Diff line number Diff line change
@@ -92,27 +92,26 @@ impl<'a, 'tcx> NumericFallbackVisitor<'a, 'tcx> {
let (suffix, is_float) = match lit_ty.kind() {
ty::Int(IntTy::I32) => ("i32", false),
ty::Float(FloatTy::F64) => ("f64", true),
// Default numeric fallback never results in other types.
_ => return,
};

let src = if let Some(src) = snippet_opt(self.cx, lit.span) {
src
} else {
match lit.node {
LitKind::Int(src, _) => format!("{src}"),
LitKind::Float(src, _) => format!("{src}"),
_ => return,
}
};
let sugg = numeric_literal::format(&src, Some(suffix), is_float);
span_lint_hir_and_then(
self.cx,
DEFAULT_NUMERIC_FALLBACK,
emit_hir_id,
lit.span,
"default numeric fallback might occur",
|diag| {
let src = if let Some(src) = snippet_opt(self.cx, lit.span) {
src
} else {
match lit.node {
LitKind::Int(src, _) => format!("{src}"),
LitKind::Float(src, _) => format!("{src}"),
_ => unreachable!("Default numeric fallback never results in other types"),
}
};

let sugg = numeric_literal::format(&src, Some(suffix), is_float);
diag.span_suggestion(lit.span, "consider adding suffix", sugg, Applicability::MaybeIncorrect);
},
);
16 changes: 9 additions & 7 deletions clippy_lints/src/default_union_representation.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::{HirId, Item, ItemKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::layout::LayoutOf;
@@ -56,16 +56,18 @@ impl<'tcx> LateLintPass<'tcx> for DefaultUnionRepresentation {
&& is_union_with_two_non_zst_fields(cx, item)
&& !has_c_repr_attr(cx, item.hir_id())
{
span_lint_and_help(
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
span_lint_and_then(
cx,
DEFAULT_UNION_REPRESENTATION,
item.span,
"this union has the default representation",
None,
format!(
"consider annotating `{}` with `#[repr(C)]` to explicitly specify memory layout",
cx.tcx.def_path_str(item.owner_id)
),
|diag| {
diag.help(format!(
"consider annotating `{}` with `#[repr(C)]` to explicitly specify memory layout",
cx.tcx.def_path_str(item.owner_id)
));
},
);
}
}
10 changes: 6 additions & 4 deletions clippy_lints/src/else_if_without_else.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Lint on if expressions with an else if, but without a final else branch.
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::diagnostics::span_lint_and_then;
use rustc_ast::ast::{Expr, ExprKind};
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
@@ -54,13 +54,15 @@ impl EarlyLintPass for ElseIfWithoutElse {
&& let ExprKind::If(_, _, None) = els.kind
&& !in_external_macro(cx.sess(), item.span)
{
span_lint_and_help(
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
span_lint_and_then(
cx,
ELSE_IF_WITHOUT_ELSE,
els.span,
"`if` expression with an `else if`, but without a final `else`",
None,
"add an `else` block here",
|diag| {
diag.help("add an `else` block here");
},
);
}
}
19 changes: 9 additions & 10 deletions clippy_lints/src/empty_drop.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::peel_blocks;
use rustc_errors::Applicability;
use rustc_hir::{Body, ExprKind, Impl, ImplItemKind, Item, ItemKind, Node};
@@ -50,15 +50,14 @@ impl LateLintPass<'_> for EmptyDrop {
&& block.stmts.is_empty()
&& block.expr.is_none()
{
span_lint_and_sugg(
cx,
EMPTY_DROP,
item.span,
"empty drop implementation",
"try removing this impl",
String::new(),
Applicability::MaybeIncorrect,
);
span_lint_and_then(cx, EMPTY_DROP, item.span, "empty drop implementation", |diag| {
diag.span_suggestion_hidden(
item.span,
"try removing this impl",
String::new(),
Applicability::MaybeIncorrect,
);
});
}
}
}
89 changes: 40 additions & 49 deletions clippy_lints/src/endian_bytes.rs
Original file line number Diff line number Diff line change
@@ -7,7 +7,6 @@ use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::Ty;
use rustc_session::declare_lint_pass;
use rustc_span::Symbol;
use std::borrow::Cow;

declare_clippy_lint! {
/// ### What it does
@@ -141,52 +140,6 @@ fn maybe_lint_endian_bytes(cx: &LateContext<'_>, expr: &Expr<'_>, prefix: Prefix
_ => return,
};

let mut help = None;

'build_help: {
// all lints disallowed, don't give help here
if [&[lint], other_lints.as_slice()]
.concat()
.iter()
.all(|lint| !lint.allowed(cx, expr))
{
break 'build_help;
}

// ne_bytes and all other lints allowed
if lint.as_name(prefix) == ne && other_lints.iter().all(|lint| lint.allowed(cx, expr)) {
help = Some(Cow::Borrowed("specify the desired endianness explicitly"));
break 'build_help;
}

// le_bytes where ne_bytes allowed but be_bytes is not, or le_bytes where ne_bytes allowed but
// le_bytes is not
if (lint.as_name(prefix) == le || lint.as_name(prefix) == be) && LintKind::Host.allowed(cx, expr) {
help = Some(Cow::Borrowed("use the native endianness instead"));
break 'build_help;
}

let allowed_lints = other_lints.iter().filter(|lint| lint.allowed(cx, expr));
let len = allowed_lints.clone().count();

let mut help_str = "use ".to_owned();

for (i, lint) in allowed_lints.enumerate() {
let only_one = len == 1;
if !only_one {
help_str.push_str("either of ");
}

help_str.push_str(&format!("`{ty}::{}` ", lint.as_name(prefix)));

if i != len && !only_one {
help_str.push_str("or ");
}
}

help = Some(Cow::Owned(help_str + "instead"));
}

span_lint_and_then(
cx,
lint.as_lint(),
@@ -198,9 +151,47 @@ fn maybe_lint_endian_bytes(cx: &LateContext<'_>, expr: &Expr<'_>, prefix: Prefix
if prefix == Prefix::To { " method" } else { "" },
),
move |diag| {
if let Some(help) = help {
diag.help(help);
// all lints disallowed, don't give help here
if [&[lint], other_lints.as_slice()]
.concat()
.iter()
.all(|lint| !lint.allowed(cx, expr))
{
return;
}

// ne_bytes and all other lints allowed
if lint.as_name(prefix) == ne && other_lints.iter().all(|lint| lint.allowed(cx, expr)) {
diag.help("specify the desired endianness explicitly");
return;
}

// le_bytes where ne_bytes allowed but be_bytes is not, or le_bytes where ne_bytes allowed but
// le_bytes is not
if (lint.as_name(prefix) == le || lint.as_name(prefix) == be) && LintKind::Host.allowed(cx, expr) {
diag.help("use the native endianness instead");
return;
}

let allowed_lints = other_lints.iter().filter(|lint| lint.allowed(cx, expr));
let len = allowed_lints.clone().count();

let mut help_str = "use ".to_owned();

for (i, lint) in allowed_lints.enumerate() {
let only_one = len == 1;
if !only_one {
help_str.push_str("either of ");
}

help_str.push_str(&format!("`{ty}::{}` ", lint.as_name(prefix)));

if i != len && !only_one {
help_str.push_str("or ");
}
}
help_str.push_str("instead");
diag.help(help_str);
},
);
}
6 changes: 3 additions & 3 deletions clippy_lints/src/exhaustive_items.rs
Original file line number Diff line number Diff line change
@@ -88,11 +88,11 @@ impl LateLintPass<'_> for ExhaustiveItems {
&& !attrs.iter().any(|a| a.has_name(sym::non_exhaustive))
&& fields.iter().all(|f| cx.tcx.visibility(f.def_id).is_public())
{
let suggestion_span = item.span.shrink_to_lo();
let indent = " ".repeat(indent_of(cx, item.span).unwrap_or(0));
span_lint_and_then(cx, lint, item.span, msg, |diag| {
let suggestion_span = item.span.shrink_to_lo();
let indent = " ".repeat(indent_of(cx, item.span).unwrap_or(0));
let sugg = format!("#[non_exhaustive]\n{indent}");
diag.span_suggestion(
diag.span_suggestion_verbose(
suggestion_span,
"try adding #[non_exhaustive]",
sugg,
10 changes: 6 additions & 4 deletions clippy_lints/src/field_scoped_visibility_modifiers.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::{Item, ItemKind, VisibilityKind};
use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::declare_lint_pass;
@@ -62,13 +62,15 @@ impl EarlyLintPass for FieldScopedVisibilityModifiers {
// pub(self) is equivalent to not using pub at all, so we ignore it
continue;
}
span_lint_and_help(
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
span_lint_and_then(
cx,
FIELD_SCOPED_VISIBILITY_MODIFIERS,
field.vis.span,
"scoped visibility modifier on a field",
None,
"consider making the field private and adding a scoped visibility method for it",
|diag| {
diag.help("consider making the field private and adding a scoped visibility method for it");
},
);
}
}
10 changes: 6 additions & 4 deletions clippy_lints/src/format_push_string.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::ty::is_type_lang_item;
use clippy_utils::{higher, match_def_path, paths};
use rustc_hir::{BinOpKind, Expr, ExprKind, LangItem, MatchSource};
@@ -81,13 +81,15 @@ impl<'tcx> LateLintPass<'tcx> for FormatPushString {
_ => return,
};
if is_format(cx, arg) {
span_lint_and_help(
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
span_lint_and_then(
cx,
FORMAT_PUSH_STRING,
expr.span,
"`format!(..)` appended to existing `String`",
None,
"consider using `write!` to avoid the extra allocation",
|diag| {
diag.help("consider using `write!` to avoid the extra allocation");
},
);
}
}
41 changes: 24 additions & 17 deletions clippy_lints/src/if_then_some_else_none.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::eager_or_lazy::switch_to_eager_eval;
use clippy_utils::source::snippet_with_context;
use clippy_utils::sugg::Sugg;
@@ -81,32 +81,39 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone {
&& self.msrv.meets(msrvs::BOOL_THEN)
&& !contains_return(then_block.stmts)
{
let mut app = Applicability::Unspecified;
let cond_snip = Sugg::hir_with_context(cx, cond, expr.span.ctxt(), "[condition]", &mut app)
.maybe_par()
.to_string();
let arg_snip = snippet_with_context(cx, then_arg.span, ctxt, "[body]", &mut app).0;
let mut method_body = if then_block.stmts.is_empty() {
arg_snip.into_owned()
} else {
format!("{{ /* snippet */ {arg_snip} }}")
};
let method_name = if switch_to_eager_eval(cx, expr) && self.msrv.meets(msrvs::BOOL_THEN_SOME) {
"then_some"
} else {
method_body.insert_str(0, "|| ");
"then"
};

let help =
format!("consider using `bool::{method_name}` like: `{cond_snip}.{method_name}({method_body})`",);
span_lint_and_help(
span_lint_and_then(
cx,
IF_THEN_SOME_ELSE_NONE,
expr.span,
format!("this could be simplified with `bool::{method_name}`"),
None,
help,
|diag| {
let mut app = Applicability::Unspecified;
let cond_snip = Sugg::hir_with_context(cx, cond, expr.span.ctxt(), "[condition]", &mut app)
.maybe_par()
.to_string();
let arg_snip = snippet_with_context(cx, then_arg.span, ctxt, "[body]", &mut app).0;
let method_body = if let Some(first_stmt) = then_block.stmts.first() {
let (block_snippet, _) =
snippet_with_context(cx, first_stmt.span.until(then_arg.span), ctxt, "..", &mut app);
let closure = if method_name == "then" { "|| " } else { "" };
format!("{closure} {{ {block_snippet}; {arg_snip} }}")
} else {
arg_snip.into_owned()
};

diag.span_suggestion(
expr.span,
"try",
format!("{cond_snip}.{method_name}({method_body})"),
app,
);
},
);
}
}
21 changes: 14 additions & 7 deletions clippy_lints/src/implicit_return.rs
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ use clippy_utils::source::{snippet_with_applicability, snippet_with_context, wal
use clippy_utils::visitors::for_each_expr_without_closures;
use clippy_utils::{get_async_fn_body, is_async_fn, is_from_proc_macro};
use core::ops::ControlFlow;
use rustc_errors::Applicability;
use rustc_errors::{Applicability, SuggestionStyle};
use rustc_hir::intravisit::FnKind;
use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, FnRetTy, HirId};
use rustc_lint::{LateContext, LateLintPass, LintContext};
@@ -45,35 +45,42 @@ declare_clippy_lint! {
declare_lint_pass!(ImplicitReturn => [IMPLICIT_RETURN]);

fn lint_return(cx: &LateContext<'_>, emission_place: HirId, span: Span) {
let mut app = Applicability::MachineApplicable;
let snip = snippet_with_applicability(cx, span, "..", &mut app);
span_lint_hir_and_then(
cx,
IMPLICIT_RETURN,
emission_place,
span,
"missing `return` statement",
|diag| {
diag.span_suggestion(span, "add `return` as shown", format!("return {snip}"), app);
let mut app = Applicability::MachineApplicable;
let snip = snippet_with_applicability(cx, span, "..", &mut app);
diag.span_suggestion_with_style(
span,
"add `return` as shown",
format!("return {snip}"),
app,
SuggestionStyle::ShowAlways,
);
},
);
}

fn lint_break(cx: &LateContext<'_>, emission_place: HirId, break_span: Span, expr_span: Span) {
let mut app = Applicability::MachineApplicable;
let snip = snippet_with_context(cx, expr_span, break_span.ctxt(), "..", &mut app).0;
span_lint_hir_and_then(
cx,
IMPLICIT_RETURN,
emission_place,
break_span,
"missing `return` statement",
|diag| {
diag.span_suggestion(
let mut app = Applicability::MachineApplicable;
let snip = snippet_with_context(cx, expr_span, break_span.ctxt(), "..", &mut app).0;
diag.span_suggestion_with_style(
break_span,
"change `break` to `return` as shown",
format!("return {snip}"),
app,
SuggestionStyle::ShowAlways,
);
},
);
77 changes: 28 additions & 49 deletions clippy_lints/src/literal_representation.rs
Original file line number Diff line number Diff line change
@@ -2,13 +2,13 @@
//! floating-point literal expressions.
use clippy_config::Conf;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::numeric_literal::{NumericLiteral, Radix};
use clippy_utils::source::snippet_opt;
use rustc_ast::ast::{Expr, ExprKind, LitKind};
use rustc_ast::token;
use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
use rustc_lint::{EarlyContext, EarlyLintPass, Lint, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::impl_lint_pass;
use rustc_span::Span;
@@ -159,63 +159,39 @@ enum WarningType {
}

impl WarningType {
fn display(&self, suggested_format: String, cx: &EarlyContext<'_>, span: Span) {
fn lint_and_text(&self) -> (&'static Lint, &'static str, &'static str) {
match self {
Self::MistypedLiteralSuffix => span_lint_and_sugg(
cx,
Self::MistypedLiteralSuffix => (
MISTYPED_LITERAL_SUFFIXES,
span,
"mistyped literal suffix",
"did you mean to write",
suggested_format,
Applicability::MaybeIncorrect,
),
Self::UnreadableLiteral => span_lint_and_sugg(
cx,
UNREADABLE_LITERAL,
span,
"long literal lacking separators",
"consider",
suggested_format,
Applicability::MachineApplicable,
),
Self::LargeDigitGroups => span_lint_and_sugg(
cx,
LARGE_DIGIT_GROUPS,
span,
"digit groups should be smaller",
"consider",
suggested_format,
Applicability::MachineApplicable,
),
Self::InconsistentDigitGrouping => span_lint_and_sugg(
cx,
Self::UnreadableLiteral => (UNREADABLE_LITERAL, "long literal lacking separators", "consider"),
Self::LargeDigitGroups => (LARGE_DIGIT_GROUPS, "digit groups should be smaller", "consider"),
Self::InconsistentDigitGrouping => (
INCONSISTENT_DIGIT_GROUPING,
span,
"digits grouped inconsistently by underscores",
"consider",
suggested_format,
Applicability::MachineApplicable,
),
Self::DecimalRepresentation => span_lint_and_sugg(
cx,
Self::DecimalRepresentation => (
DECIMAL_LITERAL_REPRESENTATION,
span,
"integer literal has a better hexadecimal representation",
"consider",
suggested_format,
Applicability::MachineApplicable,
),
Self::UnusualByteGroupings => span_lint_and_sugg(
cx,
Self::UnusualByteGroupings => (
UNUSUAL_BYTE_GROUPINGS,
span,
"digits of hex, binary or octal literal not in groups of equal size",
"consider",
suggested_format,
Applicability::MachineApplicable,
),
};
}
}

fn display(&self, num_lit: &NumericLiteral<'_>, cx: &EarlyContext<'_>, span: Span) {
let (lint, message, try_msg) = self.lint_and_text();
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
span_lint_and_then(cx, lint, span, message, |diag| {
diag.span_suggestion(span, try_msg, num_lit.format(), Applicability::MaybeIncorrect);
});
}
}

@@ -293,7 +269,7 @@ impl LiteralDigitGrouping {
WarningType::DecimalRepresentation | WarningType::MistypedLiteralSuffix => true,
};
if should_warn {
warning_type.display(num_lit.format(), cx, span);
warning_type.display(&num_lit, cx, span);
}
}
}
@@ -346,11 +322,14 @@ impl LiteralDigitGrouping {
}
}
*part = main_part;
let mut sugg = num_lit.format();
sugg.push('_');
sugg.push(missing_char);
sugg.push_str(last_group);
WarningType::MistypedLiteralSuffix.display(sugg, cx, span);
let (lint, message, try_msg) = WarningType::MistypedLiteralSuffix.lint_and_text();
span_lint_and_then(cx, lint, span, message, |diag| {
let mut sugg = num_lit.format();
sugg.push('_');
sugg.push(missing_char);
sugg.push_str(last_group);
diag.span_suggestion(span, try_msg, sugg, Applicability::MaybeIncorrect);
});
false
} else {
true
@@ -471,7 +450,7 @@ impl DecimalLiteralRepresentation {
let hex = format!("{val:#X}");
let num_lit = NumericLiteral::new(&hex, num_lit.suffix, false);
let _: Result<(), ()> = Self::do_lint(num_lit.integer).map_err(|warning_type| {
warning_type.display(num_lit.format(), cx, span);
warning_type.display(&num_lit, cx, span);
});
}
}
23 changes: 13 additions & 10 deletions clippy_lints/src/methods/clone_on_ref_ptr.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_context;
use rustc_errors::Applicability;
use rustc_hir as hir;
@@ -29,19 +29,22 @@ pub(super) fn check(
sym::RcWeak | sym::ArcWeak => "Weak",
_ => return,
};

// Sometimes unnecessary ::<_> after Rc/Arc/Weak
let mut app = Applicability::Unspecified;
let snippet = snippet_with_context(cx, receiver.span, expr.span.ctxt(), "..", &mut app).0;

span_lint_and_sugg(
span_lint_and_then(
cx,
CLONE_ON_REF_PTR,
expr.span,
"using `.clone()` on a ref-counted pointer",
"try",
format!("{caller_type}::<{}>::clone(&{snippet})", subst.type_at(0)),
app,
|diag| {
// Sometimes unnecessary ::<_> after Rc/Arc/Weak
let mut app = Applicability::Unspecified;
let snippet = snippet_with_context(cx, receiver.span, expr.span.ctxt(), "..", &mut app).0;
diag.span_suggestion(
expr.span,
"try",
format!("{caller_type}::<{}>::clone(&{snippet})", subst.type_at(0)),
app,
);
},
);
}
}
9 changes: 6 additions & 3 deletions clippy_lints/src/methods/filetype_is_file.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::get_parent_expr;
use clippy_utils::ty::is_type_diagnostic_item;
use rustc_hir as hir;
@@ -33,6 +33,9 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr
span = expr.span;
}
let lint_msg = format!("`{lint_unary}FileType::is_file()` only {verb} regular files");
let help_msg = format!("use `{help_unary}FileType::is_dir()` instead");
span_lint_and_help(cx, FILETYPE_IS_FILE, span, lint_msg, None, help_msg);

#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
span_lint_and_then(cx, FILETYPE_IS_FILE, span, lint_msg, |diag| {
diag.help(format!("use `{help_unary}FileType::is_dir()` instead"));
});
}
44 changes: 26 additions & 18 deletions clippy_lints/src/methods/get_unwrap.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::utils::derefs_to_slice;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::get_parent_expr;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::is_type_diagnostic_item;
@@ -19,9 +19,7 @@ pub(super) fn check<'tcx>(
) {
// Note: we don't want to lint `get_mut().unwrap` for `HashMap` or `BTreeMap`,
// because they do not implement `IndexMut`
let mut applicability = Applicability::MachineApplicable;
let expr_ty = cx.typeck_results().expr_ty(recv);
let get_args_str = snippet_with_applicability(cx, get_arg.span, "..", &mut applicability);
let caller_type = if derefs_to_slice(cx, recv, expr_ty).is_some() {
"slice"
} else if is_type_diagnostic_item(cx, expr_ty, sym::Vec) {
@@ -58,24 +56,34 @@ pub(super) fn check<'tcx>(
};

let mut_str = if is_mut { "_mut" } else { "" };
let borrow_str = if !needs_ref {
""
} else if is_mut {
"&mut "
} else {
"&"
};

span_lint_and_sugg(
span_lint_and_then(
cx,
GET_UNWRAP,
span,
format!("called `.get{mut_str}().unwrap()` on a {caller_type}. Using `[]` is more clear and more concise"),
"try",
format!(
"{borrow_str}{}[{get_args_str}]",
snippet_with_applicability(cx, recv.span, "..", &mut applicability)
),
applicability,
format!("called `.get{mut_str}().unwrap()` on a {caller_type}"),
|diag| {
let mut applicability = Applicability::MachineApplicable;
let get_args_str = snippet_with_applicability(cx, get_arg.span, "..", &mut applicability);

let borrow_str = if !needs_ref {
""
} else if is_mut {
"&mut "
} else {
"&"
};

diag.span_suggestion_with_style(
span,
"using `[]` is clearer and more concise",
format!(
"{borrow_str}{}[{get_args_str}]",
snippet_with_applicability(cx, recv.span, "..", &mut applicability)
),
applicability,
rustc_errors::SuggestionStyle::ShowAlways,
);
},
);
}
53 changes: 25 additions & 28 deletions clippy_lints/src/redundant_slicing.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_context;
use clippy_utils::ty::is_type_lang_item;
use clippy_utils::{get_parent_expr, peel_middle_ty_refs};
@@ -86,9 +86,8 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing {
let (indexed_ty, indexed_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(indexed));
let parent_expr = get_parent_expr(cx, expr);
let needs_parens_for_prefix = parent_expr.map_or(false, |parent| parent.precedence().order() > PREC_PREFIX);
let mut app = Applicability::MachineApplicable;

let ((lint, msg), help, sugg) = if expr_ty == indexed_ty {
if expr_ty == indexed_ty {
if expr_ref_count > indexed_ref_count {
// Indexing takes self by reference and can't return a reference to that
// reference as it's a local variable. The only way this could happen is if
@@ -99,7 +98,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing {
}
let deref_count = indexed_ref_count - expr_ref_count;

let (lint, reborrow_str, help_str) = if mutability == Mutability::Mut {
let ((lint, msg), reborrow_str, help_msg) = if mutability == Mutability::Mut {
// The slice was used to reborrow the mutable reference.
(DEREF_BY_SLICING_LINT, "&mut *", "reborrow the original value instead")
} else if matches!(
@@ -125,38 +124,36 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing {
(REDUNDANT_SLICING_LINT, "", "use the original value instead")
};

let snip = snippet_with_context(cx, indexed.span, ctxt, "..", &mut app).0;
let sugg = if (deref_count != 0 || !reborrow_str.is_empty()) && needs_parens_for_prefix {
format!("({reborrow_str}{}{snip})", "*".repeat(deref_count))
} else {
format!("{reborrow_str}{}{snip}", "*".repeat(deref_count))
};

(lint, help_str, sugg)
span_lint_and_then(cx, lint, expr.span, msg, |diag| {
let mut app = Applicability::MachineApplicable;
let snip = snippet_with_context(cx, indexed.span, ctxt, "..", &mut app).0;
let sugg = if (deref_count != 0 || !reborrow_str.is_empty()) && needs_parens_for_prefix {
format!("({reborrow_str}{}{snip})", "*".repeat(deref_count))
} else {
format!("{reborrow_str}{}{snip}", "*".repeat(deref_count))
};
diag.span_suggestion(expr.span, help_msg, sugg, app);
});
} else if let Some(target_id) = cx.tcx.lang_items().deref_target() {
if let Ok(deref_ty) = cx.tcx.try_normalize_erasing_regions(
cx.param_env,
Ty::new_projection_from_args(cx.tcx, target_id, cx.tcx.mk_args(&[GenericArg::from(indexed_ty)])),
) {
if deref_ty == expr_ty {
let snip = snippet_with_context(cx, indexed.span, ctxt, "..", &mut app).0;
let sugg = if needs_parens_for_prefix {
format!("(&{}{}*{snip})", mutability.prefix_str(), "*".repeat(indexed_ref_count))
} else {
format!("&{}{}*{snip}", mutability.prefix_str(), "*".repeat(indexed_ref_count))
};
(DEREF_BY_SLICING_LINT, "dereference the original value instead", sugg)
} else {
return;
let (lint, msg) = DEREF_BY_SLICING_LINT;
span_lint_and_then(cx, lint, expr.span, msg, |diag| {
let mut app = Applicability::MachineApplicable;
let snip = snippet_with_context(cx, indexed.span, ctxt, "..", &mut app).0;
let sugg = if needs_parens_for_prefix {
format!("(&{}{}*{snip})", mutability.prefix_str(), "*".repeat(indexed_ref_count))
} else {
format!("&{}{}*{snip}", mutability.prefix_str(), "*".repeat(indexed_ref_count))
};
diag.span_suggestion(expr.span, "dereference the original value instead", sugg, app);
});
}
} else {
return;
}
} else {
return;
};

span_lint_and_sugg(cx, lint, expr.span, msg, help, sugg, app);
}
}
}
}
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;
}
134 changes: 104 additions & 30 deletions tests/ui-toml/unwrap_used/unwrap_used.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
error: called `.get().unwrap()` on a slice
--> tests/ui-toml/unwrap_used/unwrap_used.rs:38:17
|
LL | let _ = boxed_slice.get(1).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&boxed_slice[1]`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::get-unwrap` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::get_unwrap)]`
help: using `[]` is clearer and more concise
|
LL | let _ = &boxed_slice[1];
| ~~~~~~~~~~~~~~~

error: used `unwrap()` on an `Option` value
--> tests/ui-toml/unwrap_used/unwrap_used.rs:38:17
@@ -18,11 +22,16 @@ LL | let _ = boxed_slice.get(1).unwrap();
= note: `-D clippy::unwrap-used` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::unwrap_used)]`

error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
error: called `.get().unwrap()` on a slice
--> tests/ui-toml/unwrap_used/unwrap_used.rs:39:17
|
LL | let _ = some_slice.get(0).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_slice[0]`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: using `[]` is clearer and more concise
|
LL | let _ = &some_slice[0];
| ~~~~~~~~~~~~~~

error: used `unwrap()` on an `Option` value
--> tests/ui-toml/unwrap_used/unwrap_used.rs:39:17
@@ -33,11 +42,16 @@ LL | let _ = some_slice.get(0).unwrap();
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message

error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise
error: called `.get().unwrap()` on a Vec
--> tests/ui-toml/unwrap_used/unwrap_used.rs:40:17
|
LL | let _ = some_vec.get(0).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_vec[0]`
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
help: using `[]` is clearer and more concise
|
LL | let _ = &some_vec[0];
| ~~~~~~~~~~~~

error: used `unwrap()` on an `Option` value
--> tests/ui-toml/unwrap_used/unwrap_used.rs:40:17
@@ -48,11 +62,16 @@ LL | let _ = some_vec.get(0).unwrap();
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message

error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more concise
error: called `.get().unwrap()` on a VecDeque
--> tests/ui-toml/unwrap_used/unwrap_used.rs:41:17
|
LL | let _ = some_vecdeque.get(0).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_vecdeque[0]`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: using `[]` is clearer and more concise
|
LL | let _ = &some_vecdeque[0];
| ~~~~~~~~~~~~~~~~~

error: used `unwrap()` on an `Option` value
--> tests/ui-toml/unwrap_used/unwrap_used.rs:41:17
@@ -63,11 +82,16 @@ LL | let _ = some_vecdeque.get(0).unwrap();
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message

error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more concise
error: called `.get().unwrap()` on a HashMap
--> tests/ui-toml/unwrap_used/unwrap_used.rs:42:17
|
LL | let _ = some_hashmap.get(&1).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_hashmap[&1]`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: using `[]` is clearer and more concise
|
LL | let _ = &some_hashmap[&1];
| ~~~~~~~~~~~~~~~~~

error: used `unwrap()` on an `Option` value
--> tests/ui-toml/unwrap_used/unwrap_used.rs:42:17
@@ -78,11 +102,16 @@ LL | let _ = some_hashmap.get(&1).unwrap();
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message

error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more concise
error: called `.get().unwrap()` on a BTreeMap
--> tests/ui-toml/unwrap_used/unwrap_used.rs:43:17
|
LL | let _ = some_btreemap.get(&1).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_btreemap[&1]`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: using `[]` is clearer and more concise
|
LL | let _ = &some_btreemap[&1];
| ~~~~~~~~~~~~~~~~~~

error: used `unwrap()` on an `Option` value
--> tests/ui-toml/unwrap_used/unwrap_used.rs:43:17
@@ -93,11 +122,16 @@ LL | let _ = some_btreemap.get(&1).unwrap();
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message

error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
error: called `.get().unwrap()` on a slice
--> tests/ui-toml/unwrap_used/unwrap_used.rs:47:21
|
LL | let _: u8 = *boxed_slice.get(1).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `boxed_slice[1]`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: using `[]` is clearer and more concise
|
LL | let _: u8 = boxed_slice[1];
| ~~~~~~~~~~~~~~

error: used `unwrap()` on an `Option` value
--> tests/ui-toml/unwrap_used/unwrap_used.rs:47:22
@@ -108,11 +142,16 @@ LL | let _: u8 = *boxed_slice.get(1).unwrap();
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message

error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise
error: called `.get_mut().unwrap()` on a slice
--> tests/ui-toml/unwrap_used/unwrap_used.rs:52:9
|
LL | *boxed_slice.get_mut(0).unwrap() = 1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `boxed_slice[0]`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: using `[]` is clearer and more concise
|
LL | boxed_slice[0] = 1;
| ~~~~~~~~~~~~~~

error: used `unwrap()` on an `Option` value
--> tests/ui-toml/unwrap_used/unwrap_used.rs:52:10
@@ -123,11 +162,16 @@ LL | *boxed_slice.get_mut(0).unwrap() = 1;
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message

error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise
error: called `.get_mut().unwrap()` on a slice
--> tests/ui-toml/unwrap_used/unwrap_used.rs:53:9
|
LL | *some_slice.get_mut(0).unwrap() = 1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_slice[0]`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: using `[]` is clearer and more concise
|
LL | some_slice[0] = 1;
| ~~~~~~~~~~~~~

error: used `unwrap()` on an `Option` value
--> tests/ui-toml/unwrap_used/unwrap_used.rs:53:10
@@ -138,11 +182,16 @@ LL | *some_slice.get_mut(0).unwrap() = 1;
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message

error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise
error: called `.get_mut().unwrap()` on a Vec
--> tests/ui-toml/unwrap_used/unwrap_used.rs:54:9
|
LL | *some_vec.get_mut(0).unwrap() = 1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_vec[0]`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: using `[]` is clearer and more concise
|
LL | some_vec[0] = 1;
| ~~~~~~~~~~~

error: used `unwrap()` on an `Option` value
--> tests/ui-toml/unwrap_used/unwrap_used.rs:54:10
@@ -153,11 +202,16 @@ LL | *some_vec.get_mut(0).unwrap() = 1;
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message

error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and more concise
error: called `.get_mut().unwrap()` on a VecDeque
--> tests/ui-toml/unwrap_used/unwrap_used.rs:55:9
|
LL | *some_vecdeque.get_mut(0).unwrap() = 1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_vecdeque[0]`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: using `[]` is clearer and more concise
|
LL | some_vecdeque[0] = 1;
| ~~~~~~~~~~~~~~~~

error: used `unwrap()` on an `Option` value
--> tests/ui-toml/unwrap_used/unwrap_used.rs:55:10
@@ -168,11 +222,16 @@ LL | *some_vecdeque.get_mut(0).unwrap() = 1;
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message

error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise
error: called `.get().unwrap()` on a Vec
--> tests/ui-toml/unwrap_used/unwrap_used.rs:67:17
|
LL | let _ = some_vec.get(0..1).unwrap().to_vec();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_vec[0..1]`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: using `[]` is clearer and more concise
|
LL | let _ = some_vec[0..1].to_vec();
| ~~~~~~~~~~~~~~

error: used `unwrap()` on an `Option` value
--> tests/ui-toml/unwrap_used/unwrap_used.rs:67:17
@@ -183,11 +242,16 @@ LL | let _ = some_vec.get(0..1).unwrap().to_vec();
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message

error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise
error: called `.get_mut().unwrap()` on a Vec
--> tests/ui-toml/unwrap_used/unwrap_used.rs:68:17
|
LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_vec[0..1]`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: using `[]` is clearer and more concise
|
LL | let _ = some_vec[0..1].to_vec();
| ~~~~~~~~~~~~~~

error: used `unwrap()` on an `Option` value
--> tests/ui-toml/unwrap_used/unwrap_used.rs:68:17
@@ -198,17 +262,27 @@ LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec();
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message

error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
error: called `.get().unwrap()` on a slice
--> tests/ui-toml/unwrap_used/unwrap_used.rs:75:13
|
LL | let _ = boxed_slice.get(1).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&boxed_slice[1]`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: using `[]` is clearer and more concise
|
LL | let _ = &boxed_slice[1];
| ~~~~~~~~~~~~~~~

error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
error: called `.get().unwrap()` on a slice
--> tests/ui-toml/unwrap_used/unwrap_used.rs:93:17
|
LL | let _ = Box::new([0]).get(1).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&Box::new([0])[1]`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: using `[]` is clearer and more concise
|
LL | let _ = &Box::new([0])[1];
| ~~~~~~~~~~~~~~~~~

error: aborting due to 28 previous errors

13 changes: 11 additions & 2 deletions tests/ui/create_dir.stderr
Original file line number Diff line number Diff line change
@@ -2,16 +2,25 @@ error: calling `std::fs::create_dir` where there may be a better way
--> tests/ui/create_dir.rs:10:5
|
LL | std::fs::create_dir("foo");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `std::fs::create_dir_all` instead: `create_dir_all("foo")`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::create-dir` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::create_dir)]`
help: consider calling `std::fs::create_dir_all` instead
|
LL | create_dir_all("foo");
| ~~~~~~~~~~~~~~~~~~~~~

error: calling `std::fs::create_dir` where there may be a better way
--> tests/ui/create_dir.rs:11:5
|
LL | std::fs::create_dir("bar").unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `std::fs::create_dir_all` instead: `create_dir_all("bar")`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: consider calling `std::fs::create_dir_all` instead
|
LL | create_dir_all("bar").unwrap();
| ~~~~~~~~~~~~~~~~~~~~~

error: aborting due to 2 previous errors

4 changes: 2 additions & 2 deletions tests/ui/dbg_macro/dbg_macro.stderr
Original file line number Diff line number Diff line change
@@ -81,7 +81,7 @@ error: the `dbg!` macro is intended as a debugging tool
--> tests/ui/dbg_macro/dbg_macro.rs:48:5
|
LL | dbg!();
| ^^^^^^^
| ^^^^^^
|
help: remove the invocation before committing it to a version control system
|
@@ -136,7 +136,7 @@ error: the `dbg!` macro is intended as a debugging tool
--> tests/ui/dbg_macro/dbg_macro.rs:43:13
|
LL | dbg!();
| ^^^^^^^
| ^^^^^^
...
LL | expand_to_dbg!();
| ---------------- in this macro invocation
2 changes: 1 addition & 1 deletion tests/ui/dbg_macro/dbg_macro_unfixable.stderr
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ error: the `dbg!` macro is intended as a debugging tool
--> tests/ui/dbg_macro/auxiliary/submodule.rs:2:5
|
LL | dbg!();
| ^^^^^^^
| ^^^^^^
|
= note: `-D clippy::dbg-macro` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::dbg_macro)]`
7 changes: 5 additions & 2 deletions tests/ui/empty_drop.stderr
Original file line number Diff line number Diff line change
@@ -4,10 +4,11 @@ error: empty drop implementation
LL | / impl Drop for Foo {
LL | | fn drop(&mut self) {}
LL | | }
| |_^ help: try removing this impl
| |_^
|
= note: `-D clippy::empty-drop` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::empty_drop)]`
= help: try removing this impl

error: empty drop implementation
--> tests/ui/empty_drop.rs:23:1
@@ -17,7 +18,9 @@ LL | | fn drop(&mut self) {
LL | | {}
LL | | }
LL | | }
| |_^ help: try removing this impl
| |_^
|
= help: try removing this impl

error: aborting due to 2 previous errors

118 changes: 101 additions & 17 deletions tests/ui/fn_to_numeric_cast_any.stderr
Original file line number Diff line number Diff line change
@@ -2,106 +2,190 @@ error: casting function pointer `foo` to `i8`
--> tests/ui/fn_to_numeric_cast_any.rs:23:13
|
LL | let _ = foo as i8;
| ^^^^^^^^^ help: did you mean to invoke the function?: `foo() as i8`
| ^^^^^^^^^
|
= note: `-D clippy::fn-to-numeric-cast-any` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::fn_to_numeric_cast_any)]`
help: did you mean to invoke the function?
|
LL | let _ = foo() as i8;
| ~~~~~~~~~~~

error: casting function pointer `foo` to `i16`
--> tests/ui/fn_to_numeric_cast_any.rs:26:13
|
LL | let _ = foo as i16;
| ^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as i16`
| ^^^^^^^^^^
|
help: did you mean to invoke the function?
|
LL | let _ = foo() as i16;
| ~~~~~~~~~~~~

error: casting function pointer `foo` to `i32`
--> tests/ui/fn_to_numeric_cast_any.rs:28:13
|
LL | let _ = foo as i32;
| ^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as i32`
| ^^^^^^^^^^
|
help: did you mean to invoke the function?
|
LL | let _ = foo() as i32;
| ~~~~~~~~~~~~

error: casting function pointer `foo` to `i64`
--> tests/ui/fn_to_numeric_cast_any.rs:30:13
|
LL | let _ = foo as i64;
| ^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as i64`
| ^^^^^^^^^^
|
help: did you mean to invoke the function?
|
LL | let _ = foo() as i64;
| ~~~~~~~~~~~~

error: casting function pointer `foo` to `i128`
--> tests/ui/fn_to_numeric_cast_any.rs:32:13
|
LL | let _ = foo as i128;
| ^^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as i128`
| ^^^^^^^^^^^
|
help: did you mean to invoke the function?
|
LL | let _ = foo() as i128;
| ~~~~~~~~~~~~~

error: casting function pointer `foo` to `isize`
--> tests/ui/fn_to_numeric_cast_any.rs:34:13
|
LL | let _ = foo as isize;
| ^^^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as isize`
| ^^^^^^^^^^^^
|
help: did you mean to invoke the function?
|
LL | let _ = foo() as isize;
| ~~~~~~~~~~~~~~

error: casting function pointer `foo` to `u8`
--> tests/ui/fn_to_numeric_cast_any.rs:37:13
|
LL | let _ = foo as u8;
| ^^^^^^^^^ help: did you mean to invoke the function?: `foo() as u8`
| ^^^^^^^^^
|
help: did you mean to invoke the function?
|
LL | let _ = foo() as u8;
| ~~~~~~~~~~~

error: casting function pointer `foo` to `u16`
--> tests/ui/fn_to_numeric_cast_any.rs:39:13
|
LL | let _ = foo as u16;
| ^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as u16`
| ^^^^^^^^^^
|
help: did you mean to invoke the function?
|
LL | let _ = foo() as u16;
| ~~~~~~~~~~~~

error: casting function pointer `foo` to `u32`
--> tests/ui/fn_to_numeric_cast_any.rs:41:13
|
LL | let _ = foo as u32;
| ^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as u32`
| ^^^^^^^^^^
|
help: did you mean to invoke the function?
|
LL | let _ = foo() as u32;
| ~~~~~~~~~~~~

error: casting function pointer `foo` to `u64`
--> tests/ui/fn_to_numeric_cast_any.rs:43:13
|
LL | let _ = foo as u64;
| ^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as u64`
| ^^^^^^^^^^
|
help: did you mean to invoke the function?
|
LL | let _ = foo() as u64;
| ~~~~~~~~~~~~

error: casting function pointer `foo` to `u128`
--> tests/ui/fn_to_numeric_cast_any.rs:45:13
|
LL | let _ = foo as u128;
| ^^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as u128`
| ^^^^^^^^^^^
|
help: did you mean to invoke the function?
|
LL | let _ = foo() as u128;
| ~~~~~~~~~~~~~

error: casting function pointer `foo` to `usize`
--> tests/ui/fn_to_numeric_cast_any.rs:47:13
|
LL | let _ = foo as usize;
| ^^^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as usize`
| ^^^^^^^^^^^^
|
help: did you mean to invoke the function?
|
LL | let _ = foo() as usize;
| ~~~~~~~~~~~~~~

error: casting function pointer `Struct::static_method` to `usize`
--> tests/ui/fn_to_numeric_cast_any.rs:52:13
|
LL | let _ = Struct::static_method as usize;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean to invoke the function?: `Struct::static_method() as usize`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: did you mean to invoke the function?
|
LL | let _ = Struct::static_method() as usize;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

error: casting function pointer `f` to `usize`
--> tests/ui/fn_to_numeric_cast_any.rs:57:5
|
LL | f as usize
| ^^^^^^^^^^ help: did you mean to invoke the function?: `f() as usize`
| ^^^^^^^^^^
|
help: did you mean to invoke the function?
|
LL | f() as usize
|

error: casting function pointer `T::static_method` to `usize`
--> tests/ui/fn_to_numeric_cast_any.rs:62:5
|
LL | T::static_method as usize
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean to invoke the function?: `T::static_method() as usize`
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: did you mean to invoke the function?
|
LL | T::static_method() as usize
|

error: casting function pointer `(clos as fn(u32) -> u32)` to `usize`
--> tests/ui/fn_to_numeric_cast_any.rs:69:13
|
LL | let _ = (clos as fn(u32) -> u32) as usize;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean to invoke the function?: `(clos as fn(u32) -> u32)() as usize`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: did you mean to invoke the function?
|
LL | let _ = (clos as fn(u32) -> u32)() as usize;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

error: casting function pointer `foo` to `*const ()`
--> tests/ui/fn_to_numeric_cast_any.rs:74:13
|
LL | let _ = foo as *const ();
| ^^^^^^^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as *const ()`
| ^^^^^^^^^^^^^^^^
|
help: did you mean to invoke the function?
|
LL | let _ = foo() as *const ();
| ~~~~~~~~~~~~~~~~~~

error: aborting due to 17 previous errors

152 changes: 118 additions & 34 deletions tests/ui/get_unwrap.stderr
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
error: called `.get().unwrap()` on a slice
--> tests/ui/get_unwrap.rs:37:17
|
LL | let _ = boxed_slice.get(1).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&boxed_slice[1]`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the lint level is defined here
--> tests/ui/get_unwrap.rs:9:9
|
LL | #![deny(clippy::get_unwrap)]
| ^^^^^^^^^^^^^^^^^^
help: using `[]` is clearer and more concise
|
LL | let _ = &boxed_slice[1];
| ~~~~~~~~~~~~~~~

error: used `unwrap()` on an `Option` value
--> tests/ui/get_unwrap.rs:37:17
@@ -21,11 +25,16 @@ LL | let _ = boxed_slice.get(1).unwrap();
= note: `-D clippy::unwrap-used` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::unwrap_used)]`

error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
error: called `.get().unwrap()` on a slice
--> tests/ui/get_unwrap.rs:38:17
|
LL | let _ = some_slice.get(0).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_slice[0]`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: using `[]` is clearer and more concise
|
LL | let _ = &some_slice[0];
| ~~~~~~~~~~~~~~

error: used `unwrap()` on an `Option` value
--> tests/ui/get_unwrap.rs:38:17
@@ -36,11 +45,16 @@ LL | let _ = some_slice.get(0).unwrap();
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message

error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise
error: called `.get().unwrap()` on a Vec
--> tests/ui/get_unwrap.rs:39:17
|
LL | let _ = some_vec.get(0).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_vec[0]`
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
help: using `[]` is clearer and more concise
|
LL | let _ = &some_vec[0];
| ~~~~~~~~~~~~

error: used `unwrap()` on an `Option` value
--> tests/ui/get_unwrap.rs:39:17
@@ -51,11 +65,16 @@ LL | let _ = some_vec.get(0).unwrap();
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message

error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more concise
error: called `.get().unwrap()` on a VecDeque
--> tests/ui/get_unwrap.rs:40:17
|
LL | let _ = some_vecdeque.get(0).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_vecdeque[0]`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: using `[]` is clearer and more concise
|
LL | let _ = &some_vecdeque[0];
| ~~~~~~~~~~~~~~~~~

error: used `unwrap()` on an `Option` value
--> tests/ui/get_unwrap.rs:40:17
@@ -66,11 +85,16 @@ LL | let _ = some_vecdeque.get(0).unwrap();
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message

error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more concise
error: called `.get().unwrap()` on a HashMap
--> tests/ui/get_unwrap.rs:41:17
|
LL | let _ = some_hashmap.get(&1).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_hashmap[&1]`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: using `[]` is clearer and more concise
|
LL | let _ = &some_hashmap[&1];
| ~~~~~~~~~~~~~~~~~

error: used `unwrap()` on an `Option` value
--> tests/ui/get_unwrap.rs:41:17
@@ -81,11 +105,16 @@ LL | let _ = some_hashmap.get(&1).unwrap();
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message

error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more concise
error: called `.get().unwrap()` on a BTreeMap
--> tests/ui/get_unwrap.rs:42:17
|
LL | let _ = some_btreemap.get(&1).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_btreemap[&1]`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: using `[]` is clearer and more concise
|
LL | let _ = &some_btreemap[&1];
| ~~~~~~~~~~~~~~~~~~

error: used `unwrap()` on an `Option` value
--> tests/ui/get_unwrap.rs:42:17
@@ -96,11 +125,16 @@ LL | let _ = some_btreemap.get(&1).unwrap();
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message

error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
error: called `.get().unwrap()` on a slice
--> tests/ui/get_unwrap.rs:46:21
|
LL | let _: u8 = *boxed_slice.get(1).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `boxed_slice[1]`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: using `[]` is clearer and more concise
|
LL | let _: u8 = boxed_slice[1];
| ~~~~~~~~~~~~~~

error: used `unwrap()` on an `Option` value
--> tests/ui/get_unwrap.rs:46:22
@@ -111,11 +145,16 @@ LL | let _: u8 = *boxed_slice.get(1).unwrap();
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message

error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise
error: called `.get_mut().unwrap()` on a slice
--> tests/ui/get_unwrap.rs:51:9
|
LL | *boxed_slice.get_mut(0).unwrap() = 1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `boxed_slice[0]`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: using `[]` is clearer and more concise
|
LL | boxed_slice[0] = 1;
| ~~~~~~~~~~~~~~

error: used `unwrap()` on an `Option` value
--> tests/ui/get_unwrap.rs:51:10
@@ -126,11 +165,16 @@ LL | *boxed_slice.get_mut(0).unwrap() = 1;
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message

error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise
error: called `.get_mut().unwrap()` on a slice
--> tests/ui/get_unwrap.rs:52:9
|
LL | *some_slice.get_mut(0).unwrap() = 1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_slice[0]`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: using `[]` is clearer and more concise
|
LL | some_slice[0] = 1;
| ~~~~~~~~~~~~~

error: used `unwrap()` on an `Option` value
--> tests/ui/get_unwrap.rs:52:10
@@ -141,11 +185,16 @@ LL | *some_slice.get_mut(0).unwrap() = 1;
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message

error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise
error: called `.get_mut().unwrap()` on a Vec
--> tests/ui/get_unwrap.rs:53:9
|
LL | *some_vec.get_mut(0).unwrap() = 1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_vec[0]`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: using `[]` is clearer and more concise
|
LL | some_vec[0] = 1;
| ~~~~~~~~~~~

error: used `unwrap()` on an `Option` value
--> tests/ui/get_unwrap.rs:53:10
@@ -156,11 +205,16 @@ LL | *some_vec.get_mut(0).unwrap() = 1;
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message

error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and more concise
error: called `.get_mut().unwrap()` on a VecDeque
--> tests/ui/get_unwrap.rs:54:9
|
LL | *some_vecdeque.get_mut(0).unwrap() = 1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_vecdeque[0]`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: using `[]` is clearer and more concise
|
LL | some_vecdeque[0] = 1;
| ~~~~~~~~~~~~~~~~

error: used `unwrap()` on an `Option` value
--> tests/ui/get_unwrap.rs:54:10
@@ -171,11 +225,16 @@ LL | *some_vecdeque.get_mut(0).unwrap() = 1;
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message

error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise
error: called `.get().unwrap()` on a Vec
--> tests/ui/get_unwrap.rs:66:17
|
LL | let _ = some_vec.get(0..1).unwrap().to_vec();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_vec[0..1]`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: using `[]` is clearer and more concise
|
LL | let _ = some_vec[0..1].to_vec();
| ~~~~~~~~~~~~~~

error: used `unwrap()` on an `Option` value
--> tests/ui/get_unwrap.rs:66:17
@@ -186,11 +245,16 @@ LL | let _ = some_vec.get(0..1).unwrap().to_vec();
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message

error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise
error: called `.get_mut().unwrap()` on a Vec
--> tests/ui/get_unwrap.rs:67:17
|
LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_vec[0..1]`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: using `[]` is clearer and more concise
|
LL | let _ = some_vec[0..1].to_vec();
| ~~~~~~~~~~~~~~

error: used `unwrap()` on an `Option` value
--> tests/ui/get_unwrap.rs:67:17
@@ -201,29 +265,49 @@ LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec();
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message

error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
error: called `.get().unwrap()` on a slice
--> tests/ui/get_unwrap.rs:77:24
|
LL | let _x: &i32 = f.get(1 + 2).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^ help: try: `&f[1 + 2]`
| ^^^^^^^^^^^^^^^^^^^^^
|
help: using `[]` is clearer and more concise
|
LL | let _x: &i32 = &f[1 + 2];
| ~~~~~~~~~

error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
error: called `.get().unwrap()` on a slice
--> tests/ui/get_unwrap.rs:80:18
|
LL | let _x = f.get(1 + 2).unwrap().to_string();
| ^^^^^^^^^^^^^^^^^^^^^ help: try: `f[1 + 2]`
| ^^^^^^^^^^^^^^^^^^^^^
|
help: using `[]` is clearer and more concise
|
LL | let _x = f[1 + 2].to_string();
| ~~~~~~~~

error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
error: called `.get().unwrap()` on a slice
--> tests/ui/get_unwrap.rs:83:18
|
LL | let _x = f.get(1 + 2).unwrap().abs();
| ^^^^^^^^^^^^^^^^^^^^^ help: try: `f[1 + 2]`
| ^^^^^^^^^^^^^^^^^^^^^
|
help: using `[]` is clearer and more concise
|
LL | let _x = f[1 + 2].abs();
| ~~~~~~~~

error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise
error: called `.get_mut().unwrap()` on a slice
--> tests/ui/get_unwrap.rs:100:33
|
LL | let b = rest.get_mut(linidx(j, k) - linidx(i, k) - 1).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut rest[linidx(j, k) - linidx(i, k) - 1]`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: using `[]` is clearer and more concise
|
LL | let b = &mut rest[linidx(j, k) - linidx(i, k) - 1];
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

error: aborting due to 30 previous errors

119 changes: 119 additions & 0 deletions tests/ui/if_then_some_else_none.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
#![warn(clippy::if_then_some_else_none)]
#![allow(clippy::redundant_pattern_matching, clippy::unnecessary_lazy_evaluations)]

fn main() {
// Should issue an error.
let _ = foo().then(|| { println!("true!"); "foo" });

// Should issue an error when macros are used.
let _ = matches!(true, true).then(|| { println!("true!"); matches!(true, false) });

// Should issue an error. Binary expression `o < 32` should be parenthesized.
let x = Some(5);
let _ = x.and_then(|o| (o < 32).then_some(o));
//~^ ERROR: this could be simplified with `bool::then_some`

// Should issue an error. Unary expression `!x` should be parenthesized.
let x = true;
let _ = (!x).then_some(0);
//~^ ERROR: this could be simplified with `bool::then_some`

// Should not issue an error since the `else` block has a statement besides `None`.
let _ = if foo() {
println!("true!");
Some("foo")
} else {
eprintln!("false...");
None
};

// Should not issue an error since there are more than 2 blocks in the if-else chain.
let _ = if foo() {
println!("foo true!");
Some("foo")
} else if bar() {
println!("bar true!");
Some("bar")
} else {
None
};

let _ = if foo() {
println!("foo true!");
Some("foo")
} else {
bar().then(|| {
println!("bar true!");
"bar"
})
};

// Should not issue an error since the `then` block has `None`, not `Some`.
let _ = if foo() { None } else { Some("foo is false") };

// Should not issue an error since the `else` block doesn't use `None` directly.
let _ = if foo() { Some("foo is true") } else { into_none() };

// Should not issue an error since the `then` block doesn't use `Some` directly.
let _ = if foo() { into_some("foo") } else { None };
}

#[clippy::msrv = "1.49"]
fn _msrv_1_49() {
// `bool::then` was stabilized in 1.50. Do not lint this
let _ = if foo() {
println!("true!");
Some(149)
} else {
None
};
}

#[clippy::msrv = "1.50"]
fn _msrv_1_50() {
let _ = foo().then(|| { println!("true!"); 150 });
}

fn foo() -> bool {
unimplemented!()
}

fn bar() -> bool {
unimplemented!()
}

fn into_some<T>(v: T) -> Option<T> {
Some(v)
}

fn into_none<T>() -> Option<T> {
None
}

// Should not warn
fn f(b: bool, v: Option<()>) -> Option<()> {
if b {
v?; // This is a potential early return, is not equivalent with `bool::then`

Some(())
} else {
None
}
}

fn issue11394(b: bool, v: Result<(), ()>) -> Result<(), ()> {
let x = if b {
#[allow(clippy::let_unit_value)]
let _ = v?;
Some(())
} else {
None
};

Ok(())
}

const fn issue12103(x: u32) -> Option<u32> {
// Should not issue an error in `const` context
if x > 42 { Some(150) } else { None }
}
2 changes: 1 addition & 1 deletion tests/ui/if_then_some_else_none.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#![warn(clippy::if_then_some_else_none)]
#![allow(clippy::redundant_pattern_matching)]
#![allow(clippy::redundant_pattern_matching, clippy::unnecessary_lazy_evaluations)]

fn main() {
// Should issue an error.
19 changes: 5 additions & 14 deletions tests/ui/if_then_some_else_none.stderr
Original file line number Diff line number Diff line change
@@ -9,9 +9,8 @@ LL | | Some("foo")
LL | | } else {
LL | | None
LL | | };
| |_____^
| |_____^ help: try: `foo().then(|| { println!("true!"); "foo" })`
|
= help: consider using `bool::then` like: `foo().then(|| { /* snippet */ "foo" })`
= note: `-D clippy::if-then-some-else-none` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::if_then_some_else_none)]`

@@ -26,25 +25,19 @@ LL | | Some(matches!(true, false))
LL | | } else {
LL | | None
LL | | };
| |_____^
|
= help: consider using `bool::then` like: `matches!(true, true).then(|| { /* snippet */ matches!(true, false) })`
| |_____^ help: try: `matches!(true, true).then(|| { println!("true!"); matches!(true, false) })`

error: this could be simplified with `bool::then_some`
--> tests/ui/if_then_some_else_none.rs:25:28
|
LL | let _ = x.and_then(|o| if o < 32 { Some(o) } else { None });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider using `bool::then_some` like: `(o < 32).then_some(o)`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(o < 32).then_some(o)`

error: this could be simplified with `bool::then_some`
--> tests/ui/if_then_some_else_none.rs:30:13
|
LL | let _ = if !x { Some(0) } else { None };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider using `bool::then_some` like: `(!x).then_some(0)`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(!x).then_some(0)`

error: this could be simplified with `bool::then`
--> tests/ui/if_then_some_else_none.rs:86:13
@@ -57,9 +50,7 @@ LL | | Some(150)
LL | | } else {
LL | | None
LL | | };
| |_____^
|
= help: consider using `bool::then` like: `foo().then(|| { /* snippet */ 150 })`
| |_____^ help: try: `foo().then(|| { println!("true!"); 150 })`

error: aborting due to 5 previous errors

104 changes: 89 additions & 15 deletions tests/ui/implicit_return.stderr
Original file line number Diff line number Diff line change
@@ -2,88 +2,157 @@ error: missing `return` statement
--> tests/ui/implicit_return.rs:15:5
|
LL | true
| ^^^^ help: add `return` as shown: `return true`
| ^^^^
|
= note: `-D clippy::implicit-return` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::implicit_return)]`
help: add `return` as shown
|
LL | return true
|

error: missing `return` statement
--> tests/ui/implicit_return.rs:19:15
|
LL | if true { true } else { false }
| ^^^^ help: add `return` as shown: `return true`
| ^^^^
|
help: add `return` as shown
|
LL | if true { return true } else { false }
| ~~~~~~~~~~~

error: missing `return` statement
--> tests/ui/implicit_return.rs:19:29
|
LL | if true { true } else { false }
| ^^^^^ help: add `return` as shown: `return false`
| ^^^^^
|
help: add `return` as shown
|
LL | if true { true } else { return false }
| ~~~~~~~~~~~~

error: missing `return` statement
--> tests/ui/implicit_return.rs:25:17
|
LL | true => false,
| ^^^^^ help: add `return` as shown: `return false`
| ^^^^^
|
help: add `return` as shown
|
LL | true => return false,
| ~~~~~~~~~~~~

error: missing `return` statement
--> tests/ui/implicit_return.rs:26:20
|
LL | false => { true },
| ^^^^ help: add `return` as shown: `return true`
| ^^^^
|
help: add `return` as shown
|
LL | false => { return true },
| ~~~~~~~~~~~

error: missing `return` statement
--> tests/ui/implicit_return.rs:39:9
|
LL | break true;
| ^^^^^^^^^^ help: change `break` to `return` as shown: `return true`
| ^^^^^^^^^^
|
help: change `break` to `return` as shown
|
LL | return true;
| ~~~~~~~~~~~

error: missing `return` statement
--> tests/ui/implicit_return.rs:46:13
|
LL | break true;
| ^^^^^^^^^^ help: change `break` to `return` as shown: `return true`
| ^^^^^^^^^^
|
help: change `break` to `return` as shown
|
LL | return true;
| ~~~~~~~~~~~

error: missing `return` statement
--> tests/ui/implicit_return.rs:54:13
|
LL | break true;
| ^^^^^^^^^^ help: change `break` to `return` as shown: `return true`
| ^^^^^^^^^^
|
help: change `break` to `return` as shown
|
LL | return true;
| ~~~~~~~~~~~

error: missing `return` statement
--> tests/ui/implicit_return.rs:72:18
|
LL | let _ = || { true };
| ^^^^ help: add `return` as shown: `return true`
| ^^^^
|
help: add `return` as shown
|
LL | let _ = || { return true };
| ~~~~~~~~~~~

error: missing `return` statement
--> tests/ui/implicit_return.rs:73:16
|
LL | let _ = || true;
| ^^^^ help: add `return` as shown: `return true`
| ^^^^
|
help: add `return` as shown
|
LL | let _ = || return true;
| ~~~~~~~~~~~

error: missing `return` statement
--> tests/ui/implicit_return.rs:81:5
|
LL | format!("test {}", "test")
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `return` as shown: `return format!("test {}", "test")`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: add `return` as shown
|
LL | return format!("test {}", "test")
|

error: missing `return` statement
--> tests/ui/implicit_return.rs:90:5
|
LL | m!(true, false)
| ^^^^^^^^^^^^^^^ help: add `return` as shown: `return m!(true, false)`
| ^^^^^^^^^^^^^^^
|
help: add `return` as shown
|
LL | return m!(true, false)
|

error: missing `return` statement
--> tests/ui/implicit_return.rs:96:13
|
LL | break true;
| ^^^^^^^^^^ help: change `break` to `return` as shown: `return true`
| ^^^^^^^^^^
|
help: change `break` to `return` as shown
|
LL | return true;
| ~~~~~~~~~~~

error: missing `return` statement
--> tests/ui/implicit_return.rs:101:17
|
LL | break 'outer false;
| ^^^^^^^^^^^^^^^^^^ help: change `break` to `return` as shown: `return false`
| ^^^^^^^^^^^^^^^^^^
|
help: change `break` to `return` as shown
|
LL | return false;
| ~~~~~~~~~~~~

error: missing `return` statement
--> tests/ui/implicit_return.rs:116:5
@@ -104,7 +173,12 @@ error: missing `return` statement
--> tests/ui/implicit_return.rs:130:5
|
LL | true
| ^^^^ help: add `return` as shown: `return true`
| ^^^^
|
help: add `return` as shown
|
LL | return true
|

error: aborting due to 16 previous errors