Auto merge of #9046 - xFrednet:rust-97660-expection-something-something, r=Jarcho

Fix `#[expect]` for most clippy lints

This PR fixes most `#[expect]` - lint interactions listed in rust-lang/rust#97660. [My comment in the issue](https://github.com/rust-lang/rust/issues/97660#issuecomment-1147269504) shows the current progress (Once this is merged). I plan to work on `duplicate_mod` and `multiple_inherent_impl` and leave the rest for later. I feel like stabilizing the feature is more important than fixing the last few nits, which currently also don't work with `#[allow]`.

---

changelog: none

r? `@Jarcho`

cc: rust-lang/rust#97660
This commit is contained in:
bors
2022-06-28 18:28:38 +00:00
34 changed files with 467 additions and 234 deletions

View File

@@ -78,10 +78,17 @@ declare_clippy_lint! {
/// Checks for `extern crate` and `use` items annotated with /// Checks for `extern crate` and `use` items annotated with
/// lint attributes. /// lint attributes.
/// ///
/// This lint permits `#[allow(unused_imports)]`, `#[allow(deprecated)]`, /// This lint permits lint attributes for lints emitted on the items themself.
/// `#[allow(unreachable_pub)]`, `#[allow(clippy::wildcard_imports)]` and /// For `use` items these lints are:
/// `#[allow(clippy::enum_glob_use)]` on `use` items and `#[allow(unused_imports)]` on /// * deprecated
/// `extern crate` items with a `#[macro_use]` attribute. /// * unreachable_pub
/// * unused_imports
/// * clippy::enum_glob_use
/// * clippy::macro_use_imports
/// * clippy::wildcard_imports
///
/// For `extern crate` items these lints are:
/// * `unused_imports` on items with `#[macro_use]`
/// ///
/// ### Why is this bad? /// ### Why is this bad?
/// Lint attributes have no effect on crate imports. Most /// Lint attributes have no effect on crate imports. Most
@@ -347,7 +354,10 @@ impl<'tcx> LateLintPass<'tcx> for Attributes {
|| extract_clippy_lint(lint).map_or(false, |s| { || extract_clippy_lint(lint).map_or(false, |s| {
matches!( matches!(
s.as_str(), s.as_str(),
"wildcard_imports" | "enum_glob_use" | "redundant_pub_crate", "wildcard_imports"
| "enum_glob_use"
| "redundant_pub_crate"
| "macro_use_imports",
) )
}) })
{ {

View File

@@ -1,4 +1,4 @@
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
use clippy_utils::source::snippet_opt; use clippy_utils::source::snippet_opt;
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
use clippy_utils::{eq_expr_value, get_trait_def_id, paths}; use clippy_utils::{eq_expr_value, get_trait_def_id, paths};
@@ -394,9 +394,10 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
continue 'simplified; continue 'simplified;
} }
if stats.terminals[i] != 0 && simplified_stats.terminals[i] == 0 { if stats.terminals[i] != 0 && simplified_stats.terminals[i] == 0 {
span_lint_and_then( span_lint_hir_and_then(
self.cx, self.cx,
LOGIC_BUG, LOGIC_BUG,
e.hir_id,
e.span, e.span,
"this boolean expression contains a logic bug", "this boolean expression contains a logic bug",
|diag| { |diag| {
@@ -429,9 +430,10 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
} }
} }
let nonminimal_bool_lint = |suggestions: Vec<_>| { let nonminimal_bool_lint = |suggestions: Vec<_>| {
span_lint_and_then( span_lint_hir_and_then(
self.cx, self.cx,
NONMINIMAL_BOOL, NONMINIMAL_BOOL,
e.hir_id,
e.span, e.span,
"this boolean expression can be simplified", "this boolean expression can be simplified",
|diag| { |diag| {

View File

@@ -1,4 +1,4 @@
use clippy_utils::diagnostics::span_lint; use clippy_utils::diagnostics::span_lint_hir;
use clippy_utils::ty::contains_ty; use clippy_utils::ty::contains_ty;
use rustc_hir::intravisit; use rustc_hir::intravisit;
use rustc_hir::{self, AssocItemKind, Body, FnDecl, HirId, HirIdSet, Impl, ItemKind, Node}; use rustc_hir::{self, AssocItemKind, Body, FnDecl, HirId, HirIdSet, Impl, ItemKind, Node};
@@ -118,9 +118,10 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal {
}); });
for node in v.set { for node in v.set {
span_lint( span_lint_hir(
cx, cx,
BOXED_LOCAL, BOXED_LOCAL,
node,
cx.tcx.hir().span(node), cx.tcx.hir().span(node),
"local variable doesn't need to be boxed here", "local variable doesn't need to be boxed here",
); );

View File

@@ -1,5 +1,5 @@
use clippy_utils::{ use clippy_utils::{
diagnostics::span_lint_and_sugg, diagnostics::span_lint_hir_and_then,
get_async_fn_body, is_async_fn, get_async_fn_body, is_async_fn,
source::{snippet_with_applicability, snippet_with_context, walk_span_to_context}, source::{snippet_with_applicability, snippet_with_context, walk_span_to_context},
visitors::expr_visitor_no_bodies, visitors::expr_visitor_no_bodies,
@@ -43,31 +43,38 @@ declare_clippy_lint! {
declare_lint_pass!(ImplicitReturn => [IMPLICIT_RETURN]); declare_lint_pass!(ImplicitReturn => [IMPLICIT_RETURN]);
fn lint_return(cx: &LateContext<'_>, span: Span) { fn lint_return(cx: &LateContext<'_>, emission_place: HirId, span: Span) {
let mut app = Applicability::MachineApplicable; let mut app = Applicability::MachineApplicable;
let snip = snippet_with_applicability(cx, span, "..", &mut app); let snip = snippet_with_applicability(cx, span, "..", &mut app);
span_lint_and_sugg( span_lint_hir_and_then(
cx, cx,
IMPLICIT_RETURN, IMPLICIT_RETURN,
emission_place,
span, span,
"missing `return` statement", "missing `return` statement",
"add `return` as shown", |diag| {
format!("return {}", snip), diag.span_suggestion(span, "add `return` as shown", format!("return {}", snip), app);
app, },
); );
} }
fn lint_break(cx: &LateContext<'_>, break_span: Span, expr_span: Span) { fn lint_break(cx: &LateContext<'_>, emission_place: HirId, break_span: Span, expr_span: Span) {
let mut app = Applicability::MachineApplicable; let mut app = Applicability::MachineApplicable;
let snip = snippet_with_context(cx, expr_span, break_span.ctxt(), "..", &mut app).0; let snip = snippet_with_context(cx, expr_span, break_span.ctxt(), "..", &mut app).0;
span_lint_and_sugg( span_lint_hir_and_then(
cx, cx,
IMPLICIT_RETURN, IMPLICIT_RETURN,
emission_place,
break_span, break_span,
"missing `return` statement", "missing `return` statement",
"change `break` to `return` as shown", |diag| {
format!("return {}", snip), diag.span_suggestion(
app, break_span,
"change `break` to `return` as shown",
format!("return {}", snip),
app,
);
},
); );
} }
@@ -152,7 +159,7 @@ fn lint_implicit_returns(
// At this point sub_expr can be `None` in async functions which either diverge, or return // At this point sub_expr can be `None` in async functions which either diverge, or return
// the unit type. // the unit type.
if let Some(sub_expr) = sub_expr { if let Some(sub_expr) = sub_expr {
lint_break(cx, e.span, sub_expr.span); lint_break(cx, e.hir_id, e.span, sub_expr.span);
} }
} else { } else {
// the break expression is from a macro call, add a return to the loop // the break expression is from a macro call, add a return to the loop
@@ -166,10 +173,10 @@ fn lint_implicit_returns(
if add_return { if add_return {
#[expect(clippy::option_if_let_else)] #[expect(clippy::option_if_let_else)]
if let Some(span) = call_site_span { if let Some(span) = call_site_span {
lint_return(cx, span); lint_return(cx, expr.hir_id, span);
LintLocation::Parent LintLocation::Parent
} else { } else {
lint_return(cx, expr.span); lint_return(cx, expr.hir_id, expr.span);
LintLocation::Inner LintLocation::Inner
} }
} else { } else {
@@ -198,10 +205,10 @@ fn lint_implicit_returns(
{ {
#[expect(clippy::option_if_let_else)] #[expect(clippy::option_if_let_else)]
if let Some(span) = call_site_span { if let Some(span) = call_site_span {
lint_return(cx, span); lint_return(cx, expr.hir_id, span);
LintLocation::Parent LintLocation::Parent
} else { } else {
lint_return(cx, expr.span); lint_return(cx, expr.hir_id, expr.span);
LintLocation::Inner LintLocation::Inner
} }
}, },

View File

@@ -1,4 +1,4 @@
use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::diagnostics::span_lint_hir_and_then;
use clippy_utils::source::snippet; use clippy_utils::source::snippet;
use hir::def::{DefKind, Res}; use hir::def::{DefKind, Res};
use if_chain::if_chain; use if_chain::if_chain;
@@ -51,8 +51,9 @@ impl MacroRefData {
#[derive(Default)] #[derive(Default)]
#[expect(clippy::module_name_repetitions)] #[expect(clippy::module_name_repetitions)]
pub struct MacroUseImports { pub struct MacroUseImports {
/// the actual import path used and the span of the attribute above it. /// the actual import path used and the span of the attribute above it. The value is
imports: Vec<(String, Span)>, /// the location, where the lint should be emitted.
imports: Vec<(String, Span, hir::HirId)>,
/// the span of the macro reference, kept to ensure only one reference is used per macro call. /// the span of the macro reference, kept to ensure only one reference is used per macro call.
collected: FxHashSet<Span>, collected: FxHashSet<Span>,
mac_refs: Vec<MacroRefData>, mac_refs: Vec<MacroRefData>,
@@ -91,7 +92,8 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
if_chain! { if_chain! {
if cx.sess().opts.edition >= Edition::Edition2018; if cx.sess().opts.edition >= Edition::Edition2018;
if let hir::ItemKind::Use(path, _kind) = &item.kind; if let hir::ItemKind::Use(path, _kind) = &item.kind;
let attrs = cx.tcx.hir().attrs(item.hir_id()); let hir_id = item.hir_id();
let attrs = cx.tcx.hir().attrs(hir_id);
if let Some(mac_attr) = attrs.iter().find(|attr| attr.has_name(sym::macro_use)); if let Some(mac_attr) = attrs.iter().find(|attr| attr.has_name(sym::macro_use));
if let Res::Def(DefKind::Mod, id) = path.res; if let Res::Def(DefKind::Mod, id) = path.res;
if !id.is_local(); if !id.is_local();
@@ -100,7 +102,7 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
if let Res::Def(DefKind::Macro(_mac_type), mac_id) = kid.res { if let Res::Def(DefKind::Macro(_mac_type), mac_id) = kid.res {
let span = mac_attr.span; let span = mac_attr.span;
let def_path = cx.tcx.def_path_str(mac_id); let def_path = cx.tcx.def_path_str(mac_id);
self.imports.push((def_path, span)); self.imports.push((def_path, span, hir_id));
} }
} }
} else { } else {
@@ -138,7 +140,7 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
fn check_crate_post(&mut self, cx: &LateContext<'_>) { fn check_crate_post(&mut self, cx: &LateContext<'_>) {
let mut used = FxHashMap::default(); let mut used = FxHashMap::default();
let mut check_dup = vec![]; let mut check_dup = vec![];
for (import, span) in &self.imports { for (import, span, hir_id) in &self.imports {
let found_idx = self.mac_refs.iter().position(|mac| import.ends_with(&mac.name)); let found_idx = self.mac_refs.iter().position(|mac| import.ends_with(&mac.name));
if let Some(idx) = found_idx { if let Some(idx) = found_idx {
@@ -151,7 +153,7 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
[] | [_] => return, [] | [_] => return,
[root, item] => { [root, item] => {
if !check_dup.contains(&(*item).to_string()) { if !check_dup.contains(&(*item).to_string()) {
used.entry(((*root).to_string(), span)) used.entry(((*root).to_string(), span, hir_id))
.or_insert_with(Vec::new) .or_insert_with(Vec::new)
.push((*item).to_string()); .push((*item).to_string());
check_dup.push((*item).to_string()); check_dup.push((*item).to_string());
@@ -169,13 +171,13 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
} }
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
used.entry(((*root).to_string(), span)) used.entry(((*root).to_string(), span, hir_id))
.or_insert_with(Vec::new) .or_insert_with(Vec::new)
.push(filtered.join("::")); .push(filtered.join("::"));
check_dup.extend(filtered); check_dup.extend(filtered);
} else { } else {
let rest = rest.to_vec(); let rest = rest.to_vec();
used.entry(((*root).to_string(), span)) used.entry(((*root).to_string(), span, hir_id))
.or_insert_with(Vec::new) .or_insert_with(Vec::new)
.push(rest.join("::")); .push(rest.join("::"));
check_dup.extend(rest.iter().map(ToString::to_string)); check_dup.extend(rest.iter().map(ToString::to_string));
@@ -186,27 +188,33 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
} }
let mut suggestions = vec![]; let mut suggestions = vec![];
for ((root, span), path) in used { for ((root, span, hir_id), path) in used {
if path.len() == 1 { if path.len() == 1 {
suggestions.push((span, format!("{}::{}", root, path[0]))); suggestions.push((span, format!("{}::{}", root, path[0]), hir_id));
} else { } else {
suggestions.push((span, format!("{}::{{{}}}", root, path.join(", ")))); suggestions.push((span, format!("{}::{{{}}}", root, path.join(", ")), hir_id));
} }
} }
// If mac_refs is not empty we have encountered an import we could not handle // If mac_refs is not empty we have encountered an import we could not handle
// such as `std::prelude::v1::foo` or some other macro that expands to an import. // such as `std::prelude::v1::foo` or some other macro that expands to an import.
if self.mac_refs.is_empty() { if self.mac_refs.is_empty() {
for (span, import) in suggestions { for (span, import, hir_id) in suggestions {
let help = format!("use {};", import); let help = format!("use {};", import);
span_lint_and_sugg( span_lint_hir_and_then(
cx, cx,
MACRO_USE_IMPORTS, MACRO_USE_IMPORTS,
*hir_id,
*span, *span,
"`macro_use` attributes are no longer needed in the Rust 2018 edition", "`macro_use` attributes are no longer needed in the Rust 2018 edition",
"remove the attribute and import the macro directly, try", |diag| {
help, diag.span_suggestion(
Applicability::MaybeIncorrect, *span,
"remove the attribute and import the macro directly, try",
help,
Applicability::MaybeIncorrect,
);
},
); );
} }
} }

View File

@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
use clippy_utils::source::snippet_opt; use clippy_utils::source::snippet_opt;
use clippy_utils::{is_doc_hidden, is_lint_allowed, meets_msrv, msrvs}; use clippy_utils::{is_doc_hidden, meets_msrv, msrvs};
use rustc_ast::ast::{self, VisibilityKind}; use rustc_ast::ast::{self, VisibilityKind};
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability; use rustc_errors::Applicability;
@@ -190,12 +190,13 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustiveEnum {
!self !self
.constructed_enum_variants .constructed_enum_variants
.contains(&(enum_id.to_def_id(), variant_id.to_def_id())) .contains(&(enum_id.to_def_id(), variant_id.to_def_id()))
&& !is_lint_allowed(cx, MANUAL_NON_EXHAUSTIVE, cx.tcx.hir().local_def_id_to_hir_id(enum_id))
}) })
{ {
span_lint_and_then( let hir_id = cx.tcx.hir().local_def_id_to_hir_id(enum_id);
span_lint_hir_and_then(
cx, cx,
MANUAL_NON_EXHAUSTIVE, MANUAL_NON_EXHAUSTIVE,
hir_id,
enum_span, enum_span,
"this seems like a manual implementation of the non-exhaustive pattern", "this seems like a manual implementation of the non-exhaustive pattern",
|diag| { |diag| {

View File

@@ -1,6 +1,6 @@
//! Checks for usage of `&Vec[_]` and `&String`. //! Checks for usage of `&Vec[_]` and `&String`.
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then}; use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then, span_lint_hir_and_then};
use clippy_utils::source::snippet_opt; use clippy_utils::source::snippet_opt;
use clippy_utils::ty::expr_sig; use clippy_utils::ty::expr_sig;
use clippy_utils::visitors::contains_unsafe_block; use clippy_utils::visitors::contains_unsafe_block;
@@ -166,15 +166,14 @@ impl<'tcx> LateLintPass<'tcx> for Ptr {
) )
.filter(|arg| arg.mutability() == Mutability::Not) .filter(|arg| arg.mutability() == Mutability::Not)
{ {
span_lint_and_sugg( span_lint_hir_and_then(cx, PTR_ARG, arg.emission_id, arg.span, &arg.build_msg(), |diag| {
cx, diag.span_suggestion(
PTR_ARG, arg.span,
arg.span, "change this to",
&arg.build_msg(), format!("{}{}", arg.ref_prefix, arg.deref_ty.display(cx)),
"change this to", Applicability::Unspecified,
format!("{}{}", arg.ref_prefix, arg.deref_ty.display(cx)), );
Applicability::Unspecified, });
);
} }
} }
} }
@@ -221,7 +220,7 @@ impl<'tcx> LateLintPass<'tcx> for Ptr {
let results = check_ptr_arg_usage(cx, body, &lint_args); let results = check_ptr_arg_usage(cx, body, &lint_args);
for (result, args) in results.iter().zip(lint_args.iter()).filter(|(r, _)| !r.skip) { for (result, args) in results.iter().zip(lint_args.iter()).filter(|(r, _)| !r.skip) {
span_lint_and_then(cx, PTR_ARG, args.span, &args.build_msg(), |diag| { span_lint_hir_and_then(cx, PTR_ARG, args.emission_id, args.span, &args.build_msg(), |diag| {
diag.multipart_suggestion( diag.multipart_suggestion(
"change this to", "change this to",
iter::once((args.span, format!("{}{}", args.ref_prefix, args.deref_ty.display(cx)))) iter::once((args.span, format!("{}{}", args.ref_prefix, args.deref_ty.display(cx))))
@@ -315,6 +314,7 @@ struct PtrArgReplacement {
struct PtrArg<'tcx> { struct PtrArg<'tcx> {
idx: usize, idx: usize,
emission_id: hir::HirId,
span: Span, span: Span,
ty_did: DefId, ty_did: DefId,
ty_name: Symbol, ty_name: Symbol,
@@ -419,10 +419,8 @@ fn check_fn_args<'cx, 'tcx: 'cx>(
if let [.., name] = path.segments; if let [.., name] = path.segments;
if cx.tcx.item_name(adt.did()) == name.ident.name; if cx.tcx.item_name(adt.did()) == name.ident.name;
if !is_lint_allowed(cx, PTR_ARG, hir_ty.hir_id);
if params.get(i).map_or(true, |p| !is_lint_allowed(cx, PTR_ARG, p.hir_id));
then { then {
let emission_id = params.get(i).map_or(hir_ty.hir_id, |param| param.hir_id);
let (method_renames, deref_ty) = match cx.tcx.get_diagnostic_name(adt.did()) { let (method_renames, deref_ty) = match cx.tcx.get_diagnostic_name(adt.did()) {
Some(sym::Vec) => ( Some(sym::Vec) => (
[("clone", ".to_owned()")].as_slice(), [("clone", ".to_owned()")].as_slice(),
@@ -455,14 +453,20 @@ fn check_fn_args<'cx, 'tcx: 'cx>(
}) })
.and_then(|arg| snippet_opt(cx, arg.span)) .and_then(|arg| snippet_opt(cx, arg.span))
.unwrap_or_else(|| substs.type_at(1).to_string()); .unwrap_or_else(|| substs.type_at(1).to_string());
span_lint_and_sugg( span_lint_hir_and_then(
cx, cx,
PTR_ARG, PTR_ARG,
emission_id,
hir_ty.span, hir_ty.span,
"using a reference to `Cow` is not recommended", "using a reference to `Cow` is not recommended",
"change this to", |diag| {
format!("&{}{}", mutability.prefix_str(), ty_name), diag.span_suggestion(
Applicability::Unspecified, hir_ty.span,
"change this to",
format!("&{}{}", mutability.prefix_str(), ty_name),
Applicability::Unspecified,
);
}
); );
return None; return None;
}, },
@@ -470,6 +474,7 @@ fn check_fn_args<'cx, 'tcx: 'cx>(
}; };
return Some(PtrArg { return Some(PtrArg {
idx: i, idx: i,
emission_id,
span: hir_ty.span, span: hir_ty.span,
ty_did: adt.did(), ty_did: adt.did(),
ty_name: name.ident.name, ty_name: name.ident.name,

View File

@@ -1,4 +1,4 @@
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::diagnostics::span_lint_hir_and_then;
use clippy_utils::source::{snippet_opt, snippet_with_context}; use clippy_utils::source::{snippet_opt, snippet_with_context};
use clippy_utils::{fn_def_id, path_to_local_id}; use clippy_utils::{fn_def_id, path_to_local_id};
use if_chain::if_chain; use if_chain::if_chain;
@@ -94,9 +94,10 @@ impl<'tcx> LateLintPass<'tcx> for Return {
if !in_external_macro(cx.sess(), retexpr.span); if !in_external_macro(cx.sess(), retexpr.span);
if !local.span.from_expansion(); if !local.span.from_expansion();
then { then {
span_lint_and_then( span_lint_hir_and_then(
cx, cx,
LET_AND_RETURN, LET_AND_RETURN,
retexpr.hir_id,
retexpr.span, retexpr.span,
"returning the result of a `let` binding from a block", "returning the result of a `let` binding from a block",
|err| { |err| {
@@ -185,6 +186,7 @@ fn check_final_expr<'tcx>(
if !borrows { if !borrows {
emit_return_lint( emit_return_lint(
cx, cx,
inner.map_or(expr.hir_id, |inner| inner.hir_id),
span.expect("`else return` is not possible"), span.expect("`else return` is not possible"),
inner.as_ref().map(|i| i.span), inner.as_ref().map(|i| i.span),
replacement, replacement,
@@ -220,50 +222,81 @@ fn check_final_expr<'tcx>(
} }
} }
fn emit_return_lint(cx: &LateContext<'_>, ret_span: Span, inner_span: Option<Span>, replacement: RetReplacement) { fn emit_return_lint(
cx: &LateContext<'_>,
emission_place: HirId,
ret_span: Span,
inner_span: Option<Span>,
replacement: RetReplacement,
) {
if ret_span.from_expansion() { if ret_span.from_expansion() {
return; return;
} }
match inner_span { match inner_span {
Some(inner_span) => { Some(inner_span) => {
let mut applicability = Applicability::MachineApplicable; let mut applicability = Applicability::MachineApplicable;
span_lint_and_then(cx, NEEDLESS_RETURN, ret_span, "unneeded `return` statement", |diag| { span_lint_hir_and_then(
let (snippet, _) = snippet_with_context(cx, inner_span, ret_span.ctxt(), "..", &mut applicability); cx,
diag.span_suggestion(ret_span, "remove `return`", snippet, applicability); NEEDLESS_RETURN,
}); emission_place,
ret_span,
"unneeded `return` statement",
|diag| {
let (snippet, _) = snippet_with_context(cx, inner_span, ret_span.ctxt(), "..", &mut applicability);
diag.span_suggestion(ret_span, "remove `return`", snippet, applicability);
},
);
}, },
None => match replacement { None => match replacement {
RetReplacement::Empty => { RetReplacement::Empty => {
span_lint_and_sugg( span_lint_hir_and_then(
cx, cx,
NEEDLESS_RETURN, NEEDLESS_RETURN,
emission_place,
ret_span, ret_span,
"unneeded `return` statement", "unneeded `return` statement",
"remove `return`", |diag| {
String::new(), diag.span_suggestion(
Applicability::MachineApplicable, ret_span,
"remove `return`",
String::new(),
Applicability::MachineApplicable,
);
},
); );
}, },
RetReplacement::Block => { RetReplacement::Block => {
span_lint_and_sugg( span_lint_hir_and_then(
cx, cx,
NEEDLESS_RETURN, NEEDLESS_RETURN,
emission_place,
ret_span, ret_span,
"unneeded `return` statement", "unneeded `return` statement",
"replace `return` with an empty block", |diag| {
"{}".to_string(), diag.span_suggestion(
Applicability::MachineApplicable, ret_span,
"replace `return` with an empty block",
"{}".to_string(),
Applicability::MachineApplicable,
);
},
); );
}, },
RetReplacement::Unit => { RetReplacement::Unit => {
span_lint_and_sugg( span_lint_hir_and_then(
cx, cx,
NEEDLESS_RETURN, NEEDLESS_RETURN,
emission_place,
ret_span, ret_span,
"unneeded `return` statement", "unneeded `return` statement",
"replace `return` with a unit value", |diag| {
"()".to_string(), diag.span_suggestion(
Applicability::MachineApplicable, ret_span,
"replace `return` with a unit value",
"()".to_string(),
Applicability::MachineApplicable,
);
},
); );
}, },
}, },

View File

@@ -1,4 +1,4 @@
use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::diagnostics::span_lint_hir_and_then;
use clippy_utils::higher; use clippy_utils::higher;
use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{path_to_local, usage::is_potentially_mutated}; use clippy_utils::{path_to_local, usage::is_potentially_mutated};
@@ -251,9 +251,10 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> {
unwrappable.kind.error_variant_pattern() unwrappable.kind.error_variant_pattern()
}; };
span_lint_and_then( span_lint_hir_and_then(
self.cx, self.cx,
UNNECESSARY_UNWRAP, UNNECESSARY_UNWRAP,
expr.hir_id,
expr.span, expr.span,
&format!( &format!(
"called `{}` on `{}` after checking its variant with `{}`", "called `{}` on `{}` after checking its variant with `{}`",
@@ -283,9 +284,10 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> {
}, },
); );
} else { } else {
span_lint_and_then( span_lint_hir_and_then(
self.cx, self.cx,
PANICKING_UNWRAP, PANICKING_UNWRAP,
expr.hir_id,
expr.span, expr.span,
&format!("this call to `{}()` will always panic", &format!("this call to `{}()` will always panic",
method_name.ident.name), method_name.ident.name),

View File

@@ -1539,9 +1539,13 @@ pub fn is_try<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'tcx>) -> Option<&'tc
None None
} }
/// Returns `true` if the lint is allowed in the current context /// Returns `true` if the lint is allowed in the current context. This is useful for
/// skipping long running code when it's unnecessary
/// ///
/// Useful for skipping long running code when it's unnecessary /// This function should check the lint level for the same node, that the lint will
/// be emitted at. If the information is buffered to be emitted at a later point, please
/// make sure to use `span_lint_hir` functions to emit the lint. This ensures that
/// expectations at the checked nodes will be fulfilled.
pub fn is_lint_allowed(cx: &LateContext<'_>, lint: &'static Lint, id: HirId) -> bool { pub fn is_lint_allowed(cx: &LateContext<'_>, lint: &'static Lint, id: HirId) -> bool {
cx.tcx.lint_level_at_node(lint, id).0 == Level::Allow cx.tcx.lint_level_at_node(lint, id).0 == Level::Allow
} }

View File

@@ -1,4 +1,5 @@
#![feature(box_syntax)] #![feature(box_syntax)]
#![feature(lint_reasons)]
#![allow( #![allow(
clippy::borrowed_box, clippy::borrowed_box,
clippy::needless_pass_by_value, clippy::needless_pass_by_value,
@@ -202,3 +203,7 @@ mod issue4804 {
fn foo(x: Box<u32>) {} fn foo(x: Box<u32>) {}
} }
} }
fn check_expect(#[expect(clippy::boxed_local)] x: Box<A>) {
x.foo();
}

View File

@@ -1,5 +1,5 @@
error: local variable doesn't need to be boxed here error: local variable doesn't need to be boxed here
--> $DIR/escape_analysis.rs:40:13 --> $DIR/boxed_local.rs:41:13
| |
LL | fn warn_arg(x: Box<A>) { LL | fn warn_arg(x: Box<A>) {
| ^ | ^
@@ -7,19 +7,19 @@ LL | fn warn_arg(x: Box<A>) {
= note: `-D clippy::boxed-local` implied by `-D warnings` = note: `-D clippy::boxed-local` implied by `-D warnings`
error: local variable doesn't need to be boxed here error: local variable doesn't need to be boxed here
--> $DIR/escape_analysis.rs:131:12 --> $DIR/boxed_local.rs:132:12
| |
LL | pub fn new(_needs_name: Box<PeekableSeekable<&()>>) -> () {} LL | pub fn new(_needs_name: Box<PeekableSeekable<&()>>) -> () {}
| ^^^^^^^^^^^ | ^^^^^^^^^^^
error: local variable doesn't need to be boxed here error: local variable doesn't need to be boxed here
--> $DIR/escape_analysis.rs:195:44 --> $DIR/boxed_local.rs:196:44
| |
LL | fn default_impl_x(self: Box<Self>, x: Box<u32>) -> u32 { LL | fn default_impl_x(self: Box<Self>, x: Box<u32>) -> u32 {
| ^ | ^
error: local variable doesn't need to be boxed here error: local variable doesn't need to be boxed here
--> $DIR/escape_analysis.rs:202:16 --> $DIR/boxed_local.rs:203:16
| |
LL | fn foo(x: Box<u32>) {} LL | fn foo(x: Box<u32>) {}
| ^ | ^

View File

@@ -1,3 +1,4 @@
#![feature(lint_reasons)]
#![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)]
#![allow(clippy::if_same_then_else, clippy::branches_sharing_code)] #![allow(clippy::if_same_then_else, clippy::branches_sharing_code)]
@@ -84,3 +85,18 @@ fn main() {
assert!(x.is_ok(), "{:?}", x.unwrap_err()); // ok, it's a common test pattern assert!(x.is_ok(), "{:?}", x.unwrap_err()); // ok, it's a common test pattern
} }
fn check_expect() {
let x = Some(());
if x.is_some() {
#[expect(clippy::unnecessary_unwrap)]
x.unwrap(); // unnecessary
#[expect(clippy::unnecessary_unwrap)]
x.expect("an error message"); // unnecessary
} else {
#[expect(clippy::panicking_unwrap)]
x.unwrap(); // will panic
#[expect(clippy::panicking_unwrap)]
x.expect("an error message"); // will panic
}
}

View File

@@ -1,5 +1,5 @@
error: called `unwrap` on `x` after checking its variant with `is_some` error: called `unwrap` on `x` after checking its variant with `is_some`
--> $DIR/simple_conditionals.rs:39:9 --> $DIR/simple_conditionals.rs:40:9
| |
LL | if x.is_some() { LL | if x.is_some() {
| -------------- help: try: `if let Some(..) = x` | -------------- help: try: `if let Some(..) = x`
@@ -7,13 +7,13 @@ LL | x.unwrap(); // unnecessary
| ^^^^^^^^^^ | ^^^^^^^^^^
| |
note: the lint level is defined here note: the lint level is defined here
--> $DIR/simple_conditionals.rs:1:35 --> $DIR/simple_conditionals.rs:2:35
| |
LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
error: called `expect` on `x` after checking its variant with `is_some` error: called `expect` on `x` after checking its variant with `is_some`
--> $DIR/simple_conditionals.rs:40:9 --> $DIR/simple_conditionals.rs:41:9
| |
LL | if x.is_some() { LL | if x.is_some() {
| -------------- help: try: `if let Some(..) = x` | -------------- help: try: `if let Some(..) = x`
@@ -22,7 +22,7 @@ LL | x.expect("an error message"); // unnecessary
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: this call to `unwrap()` will always panic error: this call to `unwrap()` will always panic
--> $DIR/simple_conditionals.rs:42:9 --> $DIR/simple_conditionals.rs:43:9
| |
LL | if x.is_some() { LL | if x.is_some() {
| ----------- because of this check | ----------- because of this check
@@ -31,13 +31,13 @@ LL | x.unwrap(); // will panic
| ^^^^^^^^^^ | ^^^^^^^^^^
| |
note: the lint level is defined here note: the lint level is defined here
--> $DIR/simple_conditionals.rs:1:9 --> $DIR/simple_conditionals.rs:2:9
| |
LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)]
| ^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^
error: this call to `expect()` will always panic error: this call to `expect()` will always panic
--> $DIR/simple_conditionals.rs:43:9 --> $DIR/simple_conditionals.rs:44:9
| |
LL | if x.is_some() { LL | if x.is_some() {
| ----------- because of this check | ----------- because of this check
@@ -46,7 +46,7 @@ LL | x.expect("an error message"); // will panic
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: this call to `unwrap()` will always panic error: this call to `unwrap()` will always panic
--> $DIR/simple_conditionals.rs:46:9 --> $DIR/simple_conditionals.rs:47:9
| |
LL | if x.is_none() { LL | if x.is_none() {
| ----------- because of this check | ----------- because of this check
@@ -54,7 +54,7 @@ LL | x.unwrap(); // will panic
| ^^^^^^^^^^ | ^^^^^^^^^^
error: called `unwrap` on `x` after checking its variant with `is_none` error: called `unwrap` on `x` after checking its variant with `is_none`
--> $DIR/simple_conditionals.rs:48:9 --> $DIR/simple_conditionals.rs:49:9
| |
LL | if x.is_none() { LL | if x.is_none() {
| -------------- help: try: `if let Some(..) = x` | -------------- help: try: `if let Some(..) = x`
@@ -63,7 +63,7 @@ LL | x.unwrap(); // unnecessary
| ^^^^^^^^^^ | ^^^^^^^^^^
error: called `unwrap` on `x` after checking its variant with `is_some` error: called `unwrap` on `x` after checking its variant with `is_some`
--> $DIR/simple_conditionals.rs:7:13 --> $DIR/simple_conditionals.rs:8:13
| |
LL | if $a.is_some() { LL | if $a.is_some() {
| --------------- help: try: `if let Some(..) = x` | --------------- help: try: `if let Some(..) = x`
@@ -76,7 +76,7 @@ LL | m!(x);
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
error: called `unwrap` on `x` after checking its variant with `is_ok` error: called `unwrap` on `x` after checking its variant with `is_ok`
--> $DIR/simple_conditionals.rs:56:9 --> $DIR/simple_conditionals.rs:57:9
| |
LL | if x.is_ok() { LL | if x.is_ok() {
| ------------ help: try: `if let Ok(..) = x` | ------------ help: try: `if let Ok(..) = x`
@@ -84,7 +84,7 @@ LL | x.unwrap(); // unnecessary
| ^^^^^^^^^^ | ^^^^^^^^^^
error: called `expect` on `x` after checking its variant with `is_ok` error: called `expect` on `x` after checking its variant with `is_ok`
--> $DIR/simple_conditionals.rs:57:9 --> $DIR/simple_conditionals.rs:58:9
| |
LL | if x.is_ok() { LL | if x.is_ok() {
| ------------ help: try: `if let Ok(..) = x` | ------------ help: try: `if let Ok(..) = x`
@@ -93,7 +93,7 @@ LL | x.expect("an error message"); // unnecessary
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: this call to `unwrap_err()` will always panic error: this call to `unwrap_err()` will always panic
--> $DIR/simple_conditionals.rs:58:9 --> $DIR/simple_conditionals.rs:59:9
| |
LL | if x.is_ok() { LL | if x.is_ok() {
| --------- because of this check | --------- because of this check
@@ -102,7 +102,7 @@ LL | x.unwrap_err(); // will panic
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
error: this call to `unwrap()` will always panic error: this call to `unwrap()` will always panic
--> $DIR/simple_conditionals.rs:60:9 --> $DIR/simple_conditionals.rs:61:9
| |
LL | if x.is_ok() { LL | if x.is_ok() {
| --------- because of this check | --------- because of this check
@@ -111,7 +111,7 @@ LL | x.unwrap(); // will panic
| ^^^^^^^^^^ | ^^^^^^^^^^
error: this call to `expect()` will always panic error: this call to `expect()` will always panic
--> $DIR/simple_conditionals.rs:61:9 --> $DIR/simple_conditionals.rs:62:9
| |
LL | if x.is_ok() { LL | if x.is_ok() {
| --------- because of this check | --------- because of this check
@@ -120,7 +120,7 @@ LL | x.expect("an error message"); // will panic
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: called `unwrap_err` on `x` after checking its variant with `is_ok` error: called `unwrap_err` on `x` after checking its variant with `is_ok`
--> $DIR/simple_conditionals.rs:62:9 --> $DIR/simple_conditionals.rs:63:9
| |
LL | if x.is_ok() { LL | if x.is_ok() {
| ------------ help: try: `if let Err(..) = x` | ------------ help: try: `if let Err(..) = x`
@@ -129,7 +129,7 @@ LL | x.unwrap_err(); // unnecessary
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
error: this call to `unwrap()` will always panic error: this call to `unwrap()` will always panic
--> $DIR/simple_conditionals.rs:65:9 --> $DIR/simple_conditionals.rs:66:9
| |
LL | if x.is_err() { LL | if x.is_err() {
| ---------- because of this check | ---------- because of this check
@@ -137,7 +137,7 @@ LL | x.unwrap(); // will panic
| ^^^^^^^^^^ | ^^^^^^^^^^
error: called `unwrap_err` on `x` after checking its variant with `is_err` error: called `unwrap_err` on `x` after checking its variant with `is_err`
--> $DIR/simple_conditionals.rs:66:9 --> $DIR/simple_conditionals.rs:67:9
| |
LL | if x.is_err() { LL | if x.is_err() {
| ------------- help: try: `if let Err(..) = x` | ------------- help: try: `if let Err(..) = x`
@@ -146,7 +146,7 @@ LL | x.unwrap_err(); // unnecessary
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
error: called `unwrap` on `x` after checking its variant with `is_err` error: called `unwrap` on `x` after checking its variant with `is_err`
--> $DIR/simple_conditionals.rs:68:9 --> $DIR/simple_conditionals.rs:69:9
| |
LL | if x.is_err() { LL | if x.is_err() {
| ------------- help: try: `if let Ok(..) = x` | ------------- help: try: `if let Ok(..) = x`
@@ -155,7 +155,7 @@ LL | x.unwrap(); // unnecessary
| ^^^^^^^^^^ | ^^^^^^^^^^
error: this call to `unwrap_err()` will always panic error: this call to `unwrap_err()` will always panic
--> $DIR/simple_conditionals.rs:69:9 --> $DIR/simple_conditionals.rs:70:9
| |
LL | if x.is_err() { LL | if x.is_err() {
| ---------- because of this check | ---------- because of this check

View File

@@ -1,5 +1,5 @@
// run-rustfix // run-rustfix
#![feature(lint_reasons)]
#![warn(clippy::implicit_return)] #![warn(clippy::implicit_return)]
#![allow(clippy::needless_return, clippy::needless_bool, unused, clippy::never_loop)] #![allow(clippy::needless_return, clippy::needless_bool, unused, clippy::never_loop)]
@@ -128,3 +128,13 @@ async fn foo() -> bool {
} }
fn main() {} fn main() {}
fn check_expect() -> bool {
if true {
// no error!
return true;
}
#[expect(clippy::implicit_return)]
true
}

View File

@@ -1,5 +1,5 @@
// run-rustfix // run-rustfix
#![feature(lint_reasons)]
#![warn(clippy::implicit_return)] #![warn(clippy::implicit_return)]
#![allow(clippy::needless_return, clippy::needless_bool, unused, clippy::never_loop)] #![allow(clippy::needless_return, clippy::needless_bool, unused, clippy::never_loop)]
@@ -128,3 +128,13 @@ async fn foo() -> bool {
} }
fn main() {} fn main() {}
fn check_expect() -> bool {
if true {
// no error!
return true;
}
#[expect(clippy::implicit_return)]
true
}

View File

@@ -1,3 +1,4 @@
#![feature(lint_reasons)]
#![allow(unused, clippy::diverging_sub_expression)] #![allow(unused, clippy::diverging_sub_expression)]
#![warn(clippy::logic_bug)] #![warn(clippy::logic_bug)]
@@ -24,3 +25,10 @@ fn equality_stuff() {
let _ = a > b && a <= b; let _ = a > b && a <= b;
let _ = a > b && a == b; let _ = a > b && a == b;
} }
fn check_expect() {
let a: i32 = unimplemented!();
let b: i32 = unimplemented!();
#[expect(clippy::logic_bug)]
let _ = a < b && a >= b;
}

View File

@@ -1,60 +1,60 @@
error: this boolean expression contains a logic bug error: this boolean expression contains a logic bug
--> $DIR/logic_bug.rs:10:13 --> $DIR/logic_bug.rs:11:13
| |
LL | let _ = a && b || a; LL | let _ = a && b || a;
| ^^^^^^^^^^^ help: it would look like the following: `a` | ^^^^^^^^^^^ help: it would look like the following: `a`
| |
= note: `-D clippy::logic-bug` implied by `-D warnings` = note: `-D clippy::logic-bug` implied by `-D warnings`
help: this expression can be optimized out by applying boolean operations to the outer expression help: this expression can be optimized out by applying boolean operations to the outer expression
--> $DIR/logic_bug.rs:10:18 --> $DIR/logic_bug.rs:11:18
| |
LL | let _ = a && b || a; LL | let _ = a && b || a;
| ^ | ^
error: this boolean expression contains a logic bug error: this boolean expression contains a logic bug
--> $DIR/logic_bug.rs:12:13 --> $DIR/logic_bug.rs:13:13
| |
LL | let _ = false && a; LL | let _ = false && a;
| ^^^^^^^^^^ help: it would look like the following: `false` | ^^^^^^^^^^ help: it would look like the following: `false`
| |
help: this expression can be optimized out by applying boolean operations to the outer expression help: this expression can be optimized out by applying boolean operations to the outer expression
--> $DIR/logic_bug.rs:12:22 --> $DIR/logic_bug.rs:13:22
| |
LL | let _ = false && a; LL | let _ = false && a;
| ^ | ^
error: this boolean expression contains a logic bug error: this boolean expression contains a logic bug
--> $DIR/logic_bug.rs:22:13 --> $DIR/logic_bug.rs:23:13
| |
LL | let _ = a == b && a != b; LL | let _ = a == b && a != b;
| ^^^^^^^^^^^^^^^^ help: it would look like the following: `false` | ^^^^^^^^^^^^^^^^ help: it would look like the following: `false`
| |
help: this expression can be optimized out by applying boolean operations to the outer expression help: this expression can be optimized out by applying boolean operations to the outer expression
--> $DIR/logic_bug.rs:22:13 --> $DIR/logic_bug.rs:23:13
| |
LL | let _ = a == b && a != b; LL | let _ = a == b && a != b;
| ^^^^^^ | ^^^^^^
error: this boolean expression contains a logic bug error: this boolean expression contains a logic bug
--> $DIR/logic_bug.rs:23:13 --> $DIR/logic_bug.rs:24:13
| |
LL | let _ = a < b && a >= b; LL | let _ = a < b && a >= b;
| ^^^^^^^^^^^^^^^ help: it would look like the following: `false` | ^^^^^^^^^^^^^^^ help: it would look like the following: `false`
| |
help: this expression can be optimized out by applying boolean operations to the outer expression help: this expression can be optimized out by applying boolean operations to the outer expression
--> $DIR/logic_bug.rs:23:13 --> $DIR/logic_bug.rs:24:13
| |
LL | let _ = a < b && a >= b; LL | let _ = a < b && a >= b;
| ^^^^^ | ^^^^^
error: this boolean expression contains a logic bug error: this boolean expression contains a logic bug
--> $DIR/logic_bug.rs:24:13 --> $DIR/logic_bug.rs:25:13
| |
LL | let _ = a > b && a <= b; LL | let _ = a > b && a <= b;
| ^^^^^^^^^^^^^^^ help: it would look like the following: `false` | ^^^^^^^^^^^^^^^ help: it would look like the following: `false`
| |
help: this expression can be optimized out by applying boolean operations to the outer expression help: this expression can be optimized out by applying boolean operations to the outer expression
--> $DIR/logic_bug.rs:24:13 --> $DIR/logic_bug.rs:25:13
| |
LL | let _ = a > b && a <= b; LL | let _ = a > b && a <= b;
| ^^^^^ | ^^^^^

View File

@@ -4,6 +4,7 @@
// run-rustfix // run-rustfix
// ignore-32bit // ignore-32bit
#![feature(lint_reasons)]
#![allow(unused_imports, unreachable_code, unused_variables, dead_code, unused_attributes)] #![allow(unused_imports, unreachable_code, unused_variables, dead_code, unused_attributes)]
#![allow(clippy::single_component_path_imports)] #![allow(clippy::single_component_path_imports)]
#![warn(clippy::macro_use_imports)] #![warn(clippy::macro_use_imports)]

View File

@@ -4,6 +4,7 @@
// run-rustfix // run-rustfix
// ignore-32bit // ignore-32bit
#![feature(lint_reasons)]
#![allow(unused_imports, unreachable_code, unused_variables, dead_code, unused_attributes)] #![allow(unused_imports, unreachable_code, unused_variables, dead_code, unused_attributes)]
#![allow(clippy::single_component_path_imports)] #![allow(clippy::single_component_path_imports)]
#![warn(clippy::macro_use_imports)] #![warn(clippy::macro_use_imports)]

View File

@@ -1,28 +1,28 @@
error: `macro_use` attributes are no longer needed in the Rust 2018 edition error: `macro_use` attributes are no longer needed in the Rust 2018 edition
--> $DIR/macro_use_imports.rs:18:5 --> $DIR/macro_use_imports.rs:23:5
| |
LL | #[macro_use] LL | #[macro_use]
| ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{pub_macro, function_macro, ty_macro, inner_mod_macro, pub_in_private_macro};` | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{inner::foofoo, inner::try_err};`
| |
= note: `-D clippy::macro-use-imports` implied by `-D warnings` = note: `-D clippy::macro-use-imports` implied by `-D warnings`
error: `macro_use` attributes are no longer needed in the Rust 2018 edition error: `macro_use` attributes are no longer needed in the Rust 2018 edition
--> $DIR/macro_use_imports.rs:20:5 --> $DIR/macro_use_imports.rs:21:5
| |
LL | #[macro_use] LL | #[macro_use]
| ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mini_mac::ClippyMiniMacroTest;` | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mini_mac::ClippyMiniMacroTest;`
error: `macro_use` attributes are no longer needed in the Rust 2018 edition error: `macro_use` attributes are no longer needed in the Rust 2018 edition
--> $DIR/macro_use_imports.rs:22:5 --> $DIR/macro_use_imports.rs:25:5
|
LL | #[macro_use]
| ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{inner::foofoo, inner::try_err};`
error: `macro_use` attributes are no longer needed in the Rust 2018 edition
--> $DIR/macro_use_imports.rs:24:5
| |
LL | #[macro_use] LL | #[macro_use]
| ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner::nested::string_add;` | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner::nested::string_add;`
error: `macro_use` attributes are no longer needed in the Rust 2018 edition
--> $DIR/macro_use_imports.rs:19:5
|
LL | #[macro_use]
| ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{pub_macro, function_macro, ty_macro, inner_mod_macro, pub_in_private_macro};`
error: aborting due to 4 previous errors error: aborting due to 4 previous errors

View File

@@ -0,0 +1,51 @@
// aux-build:macro_rules.rs
// aux-build:macro_use_helper.rs
// aux-build:proc_macro_derive.rs
// ignore-32bit
#![feature(lint_reasons)]
#![allow(unused_imports, unreachable_code, unused_variables, dead_code, unused_attributes)]
#![allow(clippy::single_component_path_imports)]
#![warn(clippy::macro_use_imports)]
#[macro_use]
extern crate macro_use_helper as mac;
#[macro_use]
extern crate proc_macro_derive as mini_mac;
mod a {
#[expect(clippy::macro_use_imports)]
#[macro_use]
use mac;
#[expect(clippy::macro_use_imports)]
#[macro_use]
use mini_mac;
#[expect(clippy::macro_use_imports)]
#[macro_use]
use mac::inner;
#[expect(clippy::macro_use_imports)]
#[macro_use]
use mac::inner::nested;
#[derive(ClippyMiniMacroTest)]
struct Test;
fn test() {
pub_macro!();
inner_mod_macro!();
pub_in_private_macro!(_var);
function_macro!();
let v: ty_macro!() = Vec::default();
inner::try_err!();
inner::foofoo!();
nested::string_add!();
}
}
// issue #7015, ICE due to calling `module_children` with local `DefId`
#[macro_use]
use a as b;
fn main() {}

View File

@@ -1,3 +1,4 @@
#![feature(lint_reasons)]
#![warn(clippy::manual_non_exhaustive)] #![warn(clippy::manual_non_exhaustive)]
#![allow(unused)] #![allow(unused)]
@@ -75,4 +76,12 @@ fn foo(x: &mut UsedHidden) {
} }
} }
#[expect(clippy::manual_non_exhaustive)]
enum ExpectLint {
A,
B,
#[doc(hidden)]
_C,
}
fn main() {} fn main() {}

View File

@@ -1,5 +1,5 @@
error: this seems like a manual implementation of the non-exhaustive pattern error: this seems like a manual implementation of the non-exhaustive pattern
--> $DIR/manual_non_exhaustive_enum.rs:4:1 --> $DIR/manual_non_exhaustive_enum.rs:5:1
| |
LL | enum E { LL | enum E {
| ^----- | ^-----
@@ -15,13 +15,13 @@ LL | | }
| |
= note: `-D clippy::manual-non-exhaustive` implied by `-D warnings` = note: `-D clippy::manual-non-exhaustive` implied by `-D warnings`
help: remove this variant help: remove this variant
--> $DIR/manual_non_exhaustive_enum.rs:8:5 --> $DIR/manual_non_exhaustive_enum.rs:9:5
| |
LL | _C, LL | _C,
| ^^ | ^^
error: this seems like a manual implementation of the non-exhaustive pattern error: this seems like a manual implementation of the non-exhaustive pattern
--> $DIR/manual_non_exhaustive_enum.rs:13:1 --> $DIR/manual_non_exhaustive_enum.rs:14:1
| |
LL | / enum Ep { LL | / enum Ep {
LL | | A, LL | | A,
@@ -32,7 +32,7 @@ LL | | }
| |_^ | |_^
| |
help: remove this variant help: remove this variant
--> $DIR/manual_non_exhaustive_enum.rs:17:5 --> $DIR/manual_non_exhaustive_enum.rs:18:5
| |
LL | _C, LL | _C,
| ^^ | ^^

View File

@@ -1,5 +1,6 @@
// run-rustfix // run-rustfix
#![feature(lint_reasons)]
#![feature(let_else)] #![feature(let_else)]
#![allow(unused)] #![allow(unused)]
#![allow( #![allow(
@@ -227,4 +228,13 @@ fn needless_return_macro() -> String {
format!("Hello {}", "world!") format!("Hello {}", "world!")
} }
fn check_expect() -> bool {
if true {
// no error!
return true;
}
#[expect(clippy::needless_return)]
return true;
}
fn main() {} fn main() {}

View File

@@ -1,5 +1,6 @@
// run-rustfix // run-rustfix
#![feature(lint_reasons)]
#![feature(let_else)] #![feature(let_else)]
#![allow(unused)] #![allow(unused)]
#![allow( #![allow(
@@ -227,4 +228,13 @@ fn needless_return_macro() -> String {
return format!("Hello {}", "world!"); return format!("Hello {}", "world!");
} }
fn check_expect() -> bool {
if true {
// no error!
return true;
}
#[expect(clippy::needless_return)]
return true;
}
fn main() {} fn main() {}

View File

@@ -1,5 +1,5 @@
error: unneeded `return` statement error: unneeded `return` statement
--> $DIR/needless_return.rs:26:5 --> $DIR/needless_return.rs:27:5
| |
LL | return true; LL | return true;
| ^^^^^^^^^^^^ help: remove `return`: `true` | ^^^^^^^^^^^^ help: remove `return`: `true`
@@ -7,217 +7,217 @@ LL | return true;
= note: `-D clippy::needless-return` implied by `-D warnings` = note: `-D clippy::needless-return` implied by `-D warnings`
error: unneeded `return` statement error: unneeded `return` statement
--> $DIR/needless_return.rs:30:5 --> $DIR/needless_return.rs:31:5
| |
LL | return true; LL | return true;
| ^^^^^^^^^^^^ help: remove `return`: `true` | ^^^^^^^^^^^^ help: remove `return`: `true`
error: unneeded `return` statement error: unneeded `return` statement
--> $DIR/needless_return.rs:35:9 --> $DIR/needless_return.rs:36:9
| |
LL | return true; LL | return true;
| ^^^^^^^^^^^^ help: remove `return`: `true` | ^^^^^^^^^^^^ help: remove `return`: `true`
error: unneeded `return` statement error: unneeded `return` statement
--> $DIR/needless_return.rs:37:9 --> $DIR/needless_return.rs:38:9
| |
LL | return false; LL | return false;
| ^^^^^^^^^^^^^ help: remove `return`: `false` | ^^^^^^^^^^^^^ help: remove `return`: `false`
error: unneeded `return` statement error: unneeded `return` statement
--> $DIR/needless_return.rs:43:17 --> $DIR/needless_return.rs:44:17
| |
LL | true => return false, LL | true => return false,
| ^^^^^^^^^^^^ help: remove `return`: `false` | ^^^^^^^^^^^^ help: remove `return`: `false`
error: unneeded `return` statement error: unneeded `return` statement
--> $DIR/needless_return.rs:45:13 --> $DIR/needless_return.rs:46:13
| |
LL | return true; LL | return true;
| ^^^^^^^^^^^^ help: remove `return`: `true` | ^^^^^^^^^^^^ help: remove `return`: `true`
error: unneeded `return` statement error: unneeded `return` statement
--> $DIR/needless_return.rs:52:9 --> $DIR/needless_return.rs:53:9
| |
LL | return true; LL | return true;
| ^^^^^^^^^^^^ help: remove `return`: `true` | ^^^^^^^^^^^^ help: remove `return`: `true`
error: unneeded `return` statement error: unneeded `return` statement
--> $DIR/needless_return.rs:54:16 --> $DIR/needless_return.rs:55:16
| |
LL | let _ = || return true; LL | let _ = || return true;
| ^^^^^^^^^^^ help: remove `return`: `true` | ^^^^^^^^^^^ help: remove `return`: `true`
error: unneeded `return` statement error: unneeded `return` statement
--> $DIR/needless_return.rs:58:5 --> $DIR/needless_return.rs:59:5
| |
LL | return the_answer!(); LL | return the_answer!();
| ^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `the_answer!()` | ^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `the_answer!()`
error: unneeded `return` statement error: unneeded `return` statement
--> $DIR/needless_return.rs:62:5 --> $DIR/needless_return.rs:63:5
| |
LL | return; LL | return;
| ^^^^^^^ help: remove `return` | ^^^^^^^ help: remove `return`
error: unneeded `return` statement error: unneeded `return` statement
--> $DIR/needless_return.rs:67:9 --> $DIR/needless_return.rs:68:9
| |
LL | return; LL | return;
| ^^^^^^^ help: remove `return` | ^^^^^^^ help: remove `return`
error: unneeded `return` statement error: unneeded `return` statement
--> $DIR/needless_return.rs:69:9 --> $DIR/needless_return.rs:70:9
| |
LL | return; LL | return;
| ^^^^^^^ help: remove `return` | ^^^^^^^ help: remove `return`
error: unneeded `return` statement error: unneeded `return` statement
--> $DIR/needless_return.rs:76:14 --> $DIR/needless_return.rs:77:14
| |
LL | _ => return, LL | _ => return,
| ^^^^^^ help: replace `return` with a unit value: `()` | ^^^^^^ help: replace `return` with a unit value: `()`
error: unneeded `return` statement error: unneeded `return` statement
--> $DIR/needless_return.rs:85:13 --> $DIR/needless_return.rs:86:13
| |
LL | return; LL | return;
| ^^^^^^^ help: remove `return` | ^^^^^^^ help: remove `return`
error: unneeded `return` statement error: unneeded `return` statement
--> $DIR/needless_return.rs:87:14 --> $DIR/needless_return.rs:88:14
| |
LL | _ => return, LL | _ => return,
| ^^^^^^ help: replace `return` with a unit value: `()` | ^^^^^^ help: replace `return` with a unit value: `()`
error: unneeded `return` statement error: unneeded `return` statement
--> $DIR/needless_return.rs:100:9 --> $DIR/needless_return.rs:101:9
| |
LL | return String::from("test"); LL | return String::from("test");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::from("test")` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::from("test")`
error: unneeded `return` statement error: unneeded `return` statement
--> $DIR/needless_return.rs:102:9 --> $DIR/needless_return.rs:103:9
| |
LL | return String::new(); LL | return String::new();
| ^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::new()` | ^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::new()`
error: unneeded `return` statement error: unneeded `return` statement
--> $DIR/needless_return.rs:124:32 --> $DIR/needless_return.rs:125:32
| |
LL | bar.unwrap_or_else(|_| return) LL | bar.unwrap_or_else(|_| return)
| ^^^^^^ help: replace `return` with an empty block: `{}` | ^^^^^^ help: replace `return` with an empty block: `{}`
error: unneeded `return` statement error: unneeded `return` statement
--> $DIR/needless_return.rs:129:13 --> $DIR/needless_return.rs:130:13
| |
LL | return; LL | return;
| ^^^^^^^ help: remove `return` | ^^^^^^^ help: remove `return`
error: unneeded `return` statement error: unneeded `return` statement
--> $DIR/needless_return.rs:131:20 --> $DIR/needless_return.rs:132:20
| |
LL | let _ = || return; LL | let _ = || return;
| ^^^^^^ help: replace `return` with an empty block: `{}` | ^^^^^^ help: replace `return` with an empty block: `{}`
error: unneeded `return` statement error: unneeded `return` statement
--> $DIR/needless_return.rs:137:32 --> $DIR/needless_return.rs:138:32
| |
LL | res.unwrap_or_else(|_| return Foo) LL | res.unwrap_or_else(|_| return Foo)
| ^^^^^^^^^^ help: remove `return`: `Foo` | ^^^^^^^^^^ help: remove `return`: `Foo`
error: unneeded `return` statement error: unneeded `return` statement
--> $DIR/needless_return.rs:146:5 --> $DIR/needless_return.rs:147:5
| |
LL | return true; LL | return true;
| ^^^^^^^^^^^^ help: remove `return`: `true` | ^^^^^^^^^^^^ help: remove `return`: `true`
error: unneeded `return` statement error: unneeded `return` statement
--> $DIR/needless_return.rs:150:5 --> $DIR/needless_return.rs:151:5
| |
LL | return true; LL | return true;
| ^^^^^^^^^^^^ help: remove `return`: `true` | ^^^^^^^^^^^^ help: remove `return`: `true`
error: unneeded `return` statement error: unneeded `return` statement
--> $DIR/needless_return.rs:155:9 --> $DIR/needless_return.rs:156:9
| |
LL | return true; LL | return true;
| ^^^^^^^^^^^^ help: remove `return`: `true` | ^^^^^^^^^^^^ help: remove `return`: `true`
error: unneeded `return` statement error: unneeded `return` statement
--> $DIR/needless_return.rs:157:9 --> $DIR/needless_return.rs:158:9
| |
LL | return false; LL | return false;
| ^^^^^^^^^^^^^ help: remove `return`: `false` | ^^^^^^^^^^^^^ help: remove `return`: `false`
error: unneeded `return` statement error: unneeded `return` statement
--> $DIR/needless_return.rs:163:17 --> $DIR/needless_return.rs:164:17
| |
LL | true => return false, LL | true => return false,
| ^^^^^^^^^^^^ help: remove `return`: `false` | ^^^^^^^^^^^^ help: remove `return`: `false`
error: unneeded `return` statement error: unneeded `return` statement
--> $DIR/needless_return.rs:165:13 --> $DIR/needless_return.rs:166:13
| |
LL | return true; LL | return true;
| ^^^^^^^^^^^^ help: remove `return`: `true` | ^^^^^^^^^^^^ help: remove `return`: `true`
error: unneeded `return` statement error: unneeded `return` statement
--> $DIR/needless_return.rs:172:9 --> $DIR/needless_return.rs:173:9
| |
LL | return true; LL | return true;
| ^^^^^^^^^^^^ help: remove `return`: `true` | ^^^^^^^^^^^^ help: remove `return`: `true`
error: unneeded `return` statement error: unneeded `return` statement
--> $DIR/needless_return.rs:174:16 --> $DIR/needless_return.rs:175:16
| |
LL | let _ = || return true; LL | let _ = || return true;
| ^^^^^^^^^^^ help: remove `return`: `true` | ^^^^^^^^^^^ help: remove `return`: `true`
error: unneeded `return` statement error: unneeded `return` statement
--> $DIR/needless_return.rs:178:5 --> $DIR/needless_return.rs:179:5
| |
LL | return the_answer!(); LL | return the_answer!();
| ^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `the_answer!()` | ^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `the_answer!()`
error: unneeded `return` statement error: unneeded `return` statement
--> $DIR/needless_return.rs:182:5 --> $DIR/needless_return.rs:183:5
| |
LL | return; LL | return;
| ^^^^^^^ help: remove `return` | ^^^^^^^ help: remove `return`
error: unneeded `return` statement error: unneeded `return` statement
--> $DIR/needless_return.rs:187:9 --> $DIR/needless_return.rs:188:9
| |
LL | return; LL | return;
| ^^^^^^^ help: remove `return` | ^^^^^^^ help: remove `return`
error: unneeded `return` statement error: unneeded `return` statement
--> $DIR/needless_return.rs:189:9 --> $DIR/needless_return.rs:190:9
| |
LL | return; LL | return;
| ^^^^^^^ help: remove `return` | ^^^^^^^ help: remove `return`
error: unneeded `return` statement error: unneeded `return` statement
--> $DIR/needless_return.rs:196:14 --> $DIR/needless_return.rs:197:14
| |
LL | _ => return, LL | _ => return,
| ^^^^^^ help: replace `return` with a unit value: `()` | ^^^^^^ help: replace `return` with a unit value: `()`
error: unneeded `return` statement error: unneeded `return` statement
--> $DIR/needless_return.rs:209:9 --> $DIR/needless_return.rs:210:9
| |
LL | return String::from("test"); LL | return String::from("test");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::from("test")` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::from("test")`
error: unneeded `return` statement error: unneeded `return` statement
--> $DIR/needless_return.rs:211:9 --> $DIR/needless_return.rs:212:9
| |
LL | return String::new(); LL | return String::new();
| ^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::new()` | ^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::new()`
error: unneeded `return` statement error: unneeded `return` statement
--> $DIR/needless_return.rs:227:5 --> $DIR/needless_return.rs:228:5
| |
LL | return format!("Hello {}", "world!"); LL | return format!("Hello {}", "world!");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `format!("Hello {}", "world!")` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `format!("Hello {}", "world!")`

View File

@@ -1,3 +1,4 @@
#![feature(lint_reasons)]
#![allow(unused, clippy::diverging_sub_expression)] #![allow(unused, clippy::diverging_sub_expression)]
#![warn(clippy::nonminimal_bool)] #![warn(clippy::nonminimal_bool)]
@@ -50,3 +51,9 @@ fn issue4548() {
if i != j && f(i, j) != 0 || i == j && f(i, j) != 1 {} if i != j && f(i, j) != 0 || i == j && f(i, j) != 1 {}
} }
fn check_expect() {
let a: bool = unimplemented!();
#[expect(clippy::nonminimal_bool)]
let _ = !!a;
}

View File

@@ -1,5 +1,5 @@
error: this boolean expression can be simplified error: this boolean expression can be simplified
--> $DIR/nonminimal_bool.rs:10:13 --> $DIR/nonminimal_bool.rs:11:13
| |
LL | let _ = !true; LL | let _ = !true;
| ^^^^^ help: try: `false` | ^^^^^ help: try: `false`
@@ -7,43 +7,43 @@ LL | let _ = !true;
= note: `-D clippy::nonminimal-bool` implied by `-D warnings` = note: `-D clippy::nonminimal-bool` implied by `-D warnings`
error: this boolean expression can be simplified error: this boolean expression can be simplified
--> $DIR/nonminimal_bool.rs:11:13 --> $DIR/nonminimal_bool.rs:12:13
| |
LL | let _ = !false; LL | let _ = !false;
| ^^^^^^ help: try: `true` | ^^^^^^ help: try: `true`
error: this boolean expression can be simplified error: this boolean expression can be simplified
--> $DIR/nonminimal_bool.rs:12:13 --> $DIR/nonminimal_bool.rs:13:13
| |
LL | let _ = !!a; LL | let _ = !!a;
| ^^^ help: try: `a` | ^^^ help: try: `a`
error: this boolean expression can be simplified error: this boolean expression can be simplified
--> $DIR/nonminimal_bool.rs:13:13 --> $DIR/nonminimal_bool.rs:14:13
| |
LL | let _ = false || a; LL | let _ = false || a;
| ^^^^^^^^^^ help: try: `a` | ^^^^^^^^^^ help: try: `a`
error: this boolean expression can be simplified error: this boolean expression can be simplified
--> $DIR/nonminimal_bool.rs:17:13 --> $DIR/nonminimal_bool.rs:18:13
| |
LL | let _ = !(!a && b); LL | let _ = !(!a && b);
| ^^^^^^^^^^ help: try: `a || !b` | ^^^^^^^^^^ help: try: `a || !b`
error: this boolean expression can be simplified error: this boolean expression can be simplified
--> $DIR/nonminimal_bool.rs:18:13 --> $DIR/nonminimal_bool.rs:19:13
| |
LL | let _ = !(!a || b); LL | let _ = !(!a || b);
| ^^^^^^^^^^ help: try: `a && !b` | ^^^^^^^^^^ help: try: `a && !b`
error: this boolean expression can be simplified error: this boolean expression can be simplified
--> $DIR/nonminimal_bool.rs:19:13 --> $DIR/nonminimal_bool.rs:20:13
| |
LL | let _ = !a && !(b && c); LL | let _ = !a && !(b && c);
| ^^^^^^^^^^^^^^^ help: try: `!(a || b && c)` | ^^^^^^^^^^^^^^^ help: try: `!(a || b && c)`
error: this boolean expression can be simplified error: this boolean expression can be simplified
--> $DIR/nonminimal_bool.rs:27:13 --> $DIR/nonminimal_bool.rs:28:13
| |
LL | let _ = a == b && c == 5 && a == b; LL | let _ = a == b && c == 5 && a == b;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -56,7 +56,7 @@ LL | let _ = a == b && c == 5;
| ~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~
error: this boolean expression can be simplified error: this boolean expression can be simplified
--> $DIR/nonminimal_bool.rs:28:13 --> $DIR/nonminimal_bool.rs:29:13
| |
LL | let _ = a == b || c == 5 || a == b; LL | let _ = a == b || c == 5 || a == b;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -69,7 +69,7 @@ LL | let _ = a == b || c == 5;
| ~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~
error: this boolean expression can be simplified error: this boolean expression can be simplified
--> $DIR/nonminimal_bool.rs:29:13 --> $DIR/nonminimal_bool.rs:30:13
| |
LL | let _ = a == b && c == 5 && b == a; LL | let _ = a == b && c == 5 && b == a;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -82,7 +82,7 @@ LL | let _ = a == b && c == 5;
| ~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~
error: this boolean expression can be simplified error: this boolean expression can be simplified
--> $DIR/nonminimal_bool.rs:30:13 --> $DIR/nonminimal_bool.rs:31:13
| |
LL | let _ = a != b || !(a != b || c == d); LL | let _ = a != b || !(a != b || c == d);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -95,7 +95,7 @@ LL | let _ = a != b || c != d;
| ~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~
error: this boolean expression can be simplified error: this boolean expression can be simplified
--> $DIR/nonminimal_bool.rs:31:13 --> $DIR/nonminimal_bool.rs:32:13
| |
LL | let _ = a != b && !(a != b && c == d); LL | let _ = a != b && !(a != b && c == d);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@@ -1,3 +1,4 @@
#![feature(lint_reasons)]
#![allow(unused, clippy::many_single_char_names, clippy::redundant_clone)] #![allow(unused, clippy::many_single_char_names, clippy::redundant_clone)]
#![warn(clippy::ptr_arg)] #![warn(clippy::ptr_arg)]
@@ -109,9 +110,12 @@ mod issue_5644 {
#[allow(clippy::ptr_arg)] _s: &String, #[allow(clippy::ptr_arg)] _s: &String,
#[allow(clippy::ptr_arg)] _p: &PathBuf, #[allow(clippy::ptr_arg)] _p: &PathBuf,
#[allow(clippy::ptr_arg)] _c: &Cow<[i32]>, #[allow(clippy::ptr_arg)] _c: &Cow<[i32]>,
#[expect(clippy::ptr_arg)] _expect: &Cow<[i32]>,
) { ) {
} }
fn some_allowed(#[allow(clippy::ptr_arg)] _v: &Vec<u32>, _s: &String) {}
struct S; struct S;
impl S { impl S {
fn allowed( fn allowed(
@@ -119,6 +123,7 @@ mod issue_5644 {
#[allow(clippy::ptr_arg)] _s: &String, #[allow(clippy::ptr_arg)] _s: &String,
#[allow(clippy::ptr_arg)] _p: &PathBuf, #[allow(clippy::ptr_arg)] _p: &PathBuf,
#[allow(clippy::ptr_arg)] _c: &Cow<[i32]>, #[allow(clippy::ptr_arg)] _c: &Cow<[i32]>,
#[expect(clippy::ptr_arg)] _expect: &Cow<[i32]>,
) { ) {
} }
} }
@@ -129,6 +134,7 @@ mod issue_5644 {
#[allow(clippy::ptr_arg)] _s: &String, #[allow(clippy::ptr_arg)] _s: &String,
#[allow(clippy::ptr_arg)] _p: &PathBuf, #[allow(clippy::ptr_arg)] _p: &PathBuf,
#[allow(clippy::ptr_arg)] _c: &Cow<[i32]>, #[allow(clippy::ptr_arg)] _c: &Cow<[i32]>,
#[expect(clippy::ptr_arg)] _expect: &Cow<[i32]>,
) { ) {
} }
} }

View File

@@ -1,5 +1,5 @@
error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do
--> $DIR/ptr_arg.rs:7:14 --> $DIR/ptr_arg.rs:8:14
| |
LL | fn do_vec(x: &Vec<i64>) { LL | fn do_vec(x: &Vec<i64>) {
| ^^^^^^^^^ help: change this to: `&[i64]` | ^^^^^^^^^ help: change this to: `&[i64]`
@@ -7,43 +7,43 @@ LL | fn do_vec(x: &Vec<i64>) {
= note: `-D clippy::ptr-arg` implied by `-D warnings` = note: `-D clippy::ptr-arg` implied by `-D warnings`
error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do
--> $DIR/ptr_arg.rs:11:18 --> $DIR/ptr_arg.rs:12:18
| |
LL | fn do_vec_mut(x: &mut Vec<i64>) { LL | fn do_vec_mut(x: &mut Vec<i64>) {
| ^^^^^^^^^^^^^ help: change this to: `&mut [i64]` | ^^^^^^^^^^^^^ help: change this to: `&mut [i64]`
error: writing `&String` instead of `&str` involves a new object where a slice will do error: writing `&String` instead of `&str` involves a new object where a slice will do
--> $DIR/ptr_arg.rs:15:14 --> $DIR/ptr_arg.rs:16:14
| |
LL | fn do_str(x: &String) { LL | fn do_str(x: &String) {
| ^^^^^^^ help: change this to: `&str` | ^^^^^^^ help: change this to: `&str`
error: writing `&mut String` instead of `&mut str` involves a new object where a slice will do error: writing `&mut String` instead of `&mut str` involves a new object where a slice will do
--> $DIR/ptr_arg.rs:19:18 --> $DIR/ptr_arg.rs:20:18
| |
LL | fn do_str_mut(x: &mut String) { LL | fn do_str_mut(x: &mut String) {
| ^^^^^^^^^^^ help: change this to: `&mut str` | ^^^^^^^^^^^ help: change this to: `&mut str`
error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do
--> $DIR/ptr_arg.rs:23:15 --> $DIR/ptr_arg.rs:24:15
| |
LL | fn do_path(x: &PathBuf) { LL | fn do_path(x: &PathBuf) {
| ^^^^^^^^ help: change this to: `&Path` | ^^^^^^^^ help: change this to: `&Path`
error: writing `&mut PathBuf` instead of `&mut Path` involves a new object where a slice will do error: writing `&mut PathBuf` instead of `&mut Path` involves a new object where a slice will do
--> $DIR/ptr_arg.rs:27:19 --> $DIR/ptr_arg.rs:28:19
| |
LL | fn do_path_mut(x: &mut PathBuf) { LL | fn do_path_mut(x: &mut PathBuf) {
| ^^^^^^^^^^^^ help: change this to: `&mut Path` | ^^^^^^^^^^^^ help: change this to: `&mut Path`
error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do
--> $DIR/ptr_arg.rs:35:18 --> $DIR/ptr_arg.rs:36:18
| |
LL | fn do_vec(x: &Vec<i64>); LL | fn do_vec(x: &Vec<i64>);
| ^^^^^^^^^ help: change this to: `&[i64]` | ^^^^^^^^^ help: change this to: `&[i64]`
error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do
--> $DIR/ptr_arg.rs:48:14 --> $DIR/ptr_arg.rs:49:14
| |
LL | fn cloned(x: &Vec<u8>) -> Vec<u8> { LL | fn cloned(x: &Vec<u8>) -> Vec<u8> {
| ^^^^^^^^ | ^^^^^^^^
@@ -59,7 +59,7 @@ LL | let i = (e).clone();
... ...
error: writing `&String` instead of `&str` involves a new object where a slice will do error: writing `&String` instead of `&str` involves a new object where a slice will do
--> $DIR/ptr_arg.rs:57:18 --> $DIR/ptr_arg.rs:58:18
| |
LL | fn str_cloned(x: &String) -> String { LL | fn str_cloned(x: &String) -> String {
| ^^^^^^^ | ^^^^^^^
@@ -75,7 +75,7 @@ LL ~ x.to_owned()
| |
error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do
--> $DIR/ptr_arg.rs:65:19 --> $DIR/ptr_arg.rs:66:19
| |
LL | fn path_cloned(x: &PathBuf) -> PathBuf { LL | fn path_cloned(x: &PathBuf) -> PathBuf {
| ^^^^^^^^ | ^^^^^^^^
@@ -91,7 +91,7 @@ LL ~ x.to_path_buf()
| |
error: writing `&String` instead of `&str` involves a new object where a slice will do error: writing `&String` instead of `&str` involves a new object where a slice will do
--> $DIR/ptr_arg.rs:73:44 --> $DIR/ptr_arg.rs:74:44
| |
LL | fn false_positive_capacity(x: &Vec<u8>, y: &String) { LL | fn false_positive_capacity(x: &Vec<u8>, y: &String) {
| ^^^^^^^ | ^^^^^^^
@@ -105,13 +105,19 @@ LL ~ let c = y;
| |
error: using a reference to `Cow` is not recommended error: using a reference to `Cow` is not recommended
--> $DIR/ptr_arg.rs:87:25 --> $DIR/ptr_arg.rs:88:25
| |
LL | fn test_cow_with_ref(c: &Cow<[i32]>) {} LL | fn test_cow_with_ref(c: &Cow<[i32]>) {}
| ^^^^^^^^^^^ help: change this to: `&[i32]` | ^^^^^^^^^^^ help: change this to: `&[i32]`
error: writing `&String` instead of `&str` involves a new object where a slice will do
--> $DIR/ptr_arg.rs:117:66
|
LL | fn some_allowed(#[allow(clippy::ptr_arg)] _v: &Vec<u32>, _s: &String) {}
| ^^^^^^^ help: change this to: `&str`
error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do
--> $DIR/ptr_arg.rs:140:21 --> $DIR/ptr_arg.rs:146:21
| |
LL | fn foo_vec(vec: &Vec<u8>) { LL | fn foo_vec(vec: &Vec<u8>) {
| ^^^^^^^^ | ^^^^^^^^
@@ -124,7 +130,7 @@ LL ~ let _ = vec.to_owned().clone();
| |
error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do
--> $DIR/ptr_arg.rs:145:23 --> $DIR/ptr_arg.rs:151:23
| |
LL | fn foo_path(path: &PathBuf) { LL | fn foo_path(path: &PathBuf) {
| ^^^^^^^^ | ^^^^^^^^
@@ -137,7 +143,7 @@ LL ~ let _ = path.to_path_buf().clone();
| |
error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do
--> $DIR/ptr_arg.rs:150:21 --> $DIR/ptr_arg.rs:156:21
| |
LL | fn foo_str(str: &PathBuf) { LL | fn foo_str(str: &PathBuf) {
| ^^^^^^^^ | ^^^^^^^^
@@ -150,10 +156,10 @@ LL ~ let _ = str.to_path_buf().clone();
| |
error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do
--> $DIR/ptr_arg.rs:156:29 --> $DIR/ptr_arg.rs:162:29
| |
LL | fn mut_vec_slice_methods(v: &mut Vec<u32>) { LL | fn mut_vec_slice_methods(v: &mut Vec<u32>) {
| ^^^^^^^^^^^^^ help: change this to: `&mut [u32]` | ^^^^^^^^^^^^^ help: change this to: `&mut [u32]`
error: aborting due to 16 previous errors error: aborting due to 17 previous errors

View File

@@ -1,6 +1,7 @@
// run-rustfix // run-rustfix
// rustfix-only-machine-applicable // rustfix-only-machine-applicable
#![feature(lint_reasons)]
#![allow(clippy::implicit_clone, clippy::drop_non_drop)] #![allow(clippy::implicit_clone, clippy::drop_non_drop)]
use std::ffi::OsString; use std::ffi::OsString;
use std::path::Path; use std::path::Path;
@@ -29,6 +30,10 @@ fn main() {
#[allow(clippy::redundant_clone)] #[allow(clippy::redundant_clone)]
let _s = String::new().to_string(); let _s = String::new().to_string();
// Check that lint level works
#[expect(clippy::redundant_clone)]
let _s = String::new().to_string();
let tup = (String::from("foo"),); let tup = (String::from("foo"),);
let _t = tup.0; let _t = tup.0;

View File

@@ -1,6 +1,7 @@
// run-rustfix // run-rustfix
// rustfix-only-machine-applicable // rustfix-only-machine-applicable
#![feature(lint_reasons)]
#![allow(clippy::implicit_clone, clippy::drop_non_drop)] #![allow(clippy::implicit_clone, clippy::drop_non_drop)]
use std::ffi::OsString; use std::ffi::OsString;
use std::path::Path; use std::path::Path;
@@ -29,6 +30,10 @@ fn main() {
#[allow(clippy::redundant_clone)] #[allow(clippy::redundant_clone)]
let _s = String::new().to_string(); let _s = String::new().to_string();
// Check that lint level works
#[expect(clippy::redundant_clone)]
let _s = String::new().to_string();
let tup = (String::from("foo"),); let tup = (String::from("foo"),);
let _t = tup.0.clone(); let _t = tup.0.clone();

View File

@@ -1,180 +1,180 @@
error: redundant clone error: redundant clone
--> $DIR/redundant_clone.rs:9:42 --> $DIR/redundant_clone.rs:10:42
| |
LL | let _s = ["lorem", "ipsum"].join(" ").to_string(); LL | let _s = ["lorem", "ipsum"].join(" ").to_string();
| ^^^^^^^^^^^^ help: remove this | ^^^^^^^^^^^^ help: remove this
| |
= note: `-D clippy::redundant-clone` implied by `-D warnings` = note: `-D clippy::redundant-clone` implied by `-D warnings`
note: this value is dropped without further use note: this value is dropped without further use
--> $DIR/redundant_clone.rs:9:14 --> $DIR/redundant_clone.rs:10:14
| |
LL | let _s = ["lorem", "ipsum"].join(" ").to_string(); LL | let _s = ["lorem", "ipsum"].join(" ").to_string();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: redundant clone error: redundant clone
--> $DIR/redundant_clone.rs:12:15 --> $DIR/redundant_clone.rs:13:15
| |
LL | let _s = s.clone(); LL | let _s = s.clone();
| ^^^^^^^^ help: remove this | ^^^^^^^^ help: remove this
| |
note: this value is dropped without further use note: this value is dropped without further use
--> $DIR/redundant_clone.rs:12:14 --> $DIR/redundant_clone.rs:13:14
| |
LL | let _s = s.clone(); LL | let _s = s.clone();
| ^ | ^
error: redundant clone error: redundant clone
--> $DIR/redundant_clone.rs:15:15 --> $DIR/redundant_clone.rs:16:15
| |
LL | let _s = s.to_string(); LL | let _s = s.to_string();
| ^^^^^^^^^^^^ help: remove this | ^^^^^^^^^^^^ help: remove this
| |
note: this value is dropped without further use note: this value is dropped without further use
--> $DIR/redundant_clone.rs:15:14 --> $DIR/redundant_clone.rs:16:14
| |
LL | let _s = s.to_string(); LL | let _s = s.to_string();
| ^ | ^
error: redundant clone error: redundant clone
--> $DIR/redundant_clone.rs:18:15 --> $DIR/redundant_clone.rs:19:15
| |
LL | let _s = s.to_owned(); LL | let _s = s.to_owned();
| ^^^^^^^^^^^ help: remove this | ^^^^^^^^^^^ help: remove this
| |
note: this value is dropped without further use note: this value is dropped without further use
--> $DIR/redundant_clone.rs:18:14 --> $DIR/redundant_clone.rs:19:14
| |
LL | let _s = s.to_owned(); LL | let _s = s.to_owned();
| ^ | ^
error: redundant clone error: redundant clone
--> $DIR/redundant_clone.rs:20:42 --> $DIR/redundant_clone.rs:21:42
| |
LL | let _s = Path::new("/a/b/").join("c").to_owned(); LL | let _s = Path::new("/a/b/").join("c").to_owned();
| ^^^^^^^^^^^ help: remove this | ^^^^^^^^^^^ help: remove this
| |
note: this value is dropped without further use note: this value is dropped without further use
--> $DIR/redundant_clone.rs:20:14 --> $DIR/redundant_clone.rs:21:14
| |
LL | let _s = Path::new("/a/b/").join("c").to_owned(); LL | let _s = Path::new("/a/b/").join("c").to_owned();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: redundant clone error: redundant clone
--> $DIR/redundant_clone.rs:22:42 --> $DIR/redundant_clone.rs:23:42
| |
LL | let _s = Path::new("/a/b/").join("c").to_path_buf(); LL | let _s = Path::new("/a/b/").join("c").to_path_buf();
| ^^^^^^^^^^^^^^ help: remove this | ^^^^^^^^^^^^^^ help: remove this
| |
note: this value is dropped without further use note: this value is dropped without further use
--> $DIR/redundant_clone.rs:22:14 --> $DIR/redundant_clone.rs:23:14
| |
LL | let _s = Path::new("/a/b/").join("c").to_path_buf(); LL | let _s = Path::new("/a/b/").join("c").to_path_buf();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: redundant clone error: redundant clone
--> $DIR/redundant_clone.rs:24:29 --> $DIR/redundant_clone.rs:25:29
| |
LL | let _s = OsString::new().to_owned(); LL | let _s = OsString::new().to_owned();
| ^^^^^^^^^^^ help: remove this | ^^^^^^^^^^^ help: remove this
| |
note: this value is dropped without further use note: this value is dropped without further use
--> $DIR/redundant_clone.rs:24:14 --> $DIR/redundant_clone.rs:25:14
| |
LL | let _s = OsString::new().to_owned(); LL | let _s = OsString::new().to_owned();
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
error: redundant clone error: redundant clone
--> $DIR/redundant_clone.rs:26:29 --> $DIR/redundant_clone.rs:27:29
| |
LL | let _s = OsString::new().to_os_string(); LL | let _s = OsString::new().to_os_string();
| ^^^^^^^^^^^^^^^ help: remove this | ^^^^^^^^^^^^^^^ help: remove this
| |
note: this value is dropped without further use note: this value is dropped without further use
--> $DIR/redundant_clone.rs:26:14 --> $DIR/redundant_clone.rs:27:14
| |
LL | let _s = OsString::new().to_os_string(); LL | let _s = OsString::new().to_os_string();
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
error: redundant clone error: redundant clone
--> $DIR/redundant_clone.rs:33:19 --> $DIR/redundant_clone.rs:38:19
| |
LL | let _t = tup.0.clone(); LL | let _t = tup.0.clone();
| ^^^^^^^^ help: remove this | ^^^^^^^^ help: remove this
| |
note: this value is dropped without further use note: this value is dropped without further use
--> $DIR/redundant_clone.rs:33:14 --> $DIR/redundant_clone.rs:38:14
| |
LL | let _t = tup.0.clone(); LL | let _t = tup.0.clone();
| ^^^^^ | ^^^^^
error: redundant clone error: redundant clone
--> $DIR/redundant_clone.rs:65:25 --> $DIR/redundant_clone.rs:70:25
| |
LL | if b { (a.clone(), a.clone()) } else { (Alpha, a) } LL | if b { (a.clone(), a.clone()) } else { (Alpha, a) }
| ^^^^^^^^ help: remove this | ^^^^^^^^ help: remove this
| |
note: this value is dropped without further use note: this value is dropped without further use
--> $DIR/redundant_clone.rs:65:24 --> $DIR/redundant_clone.rs:70:24
| |
LL | if b { (a.clone(), a.clone()) } else { (Alpha, a) } LL | if b { (a.clone(), a.clone()) } else { (Alpha, a) }
| ^ | ^
error: redundant clone error: redundant clone
--> $DIR/redundant_clone.rs:122:15 --> $DIR/redundant_clone.rs:127:15
| |
LL | let _s = s.clone(); LL | let _s = s.clone();
| ^^^^^^^^ help: remove this | ^^^^^^^^ help: remove this
| |
note: this value is dropped without further use note: this value is dropped without further use
--> $DIR/redundant_clone.rs:122:14 --> $DIR/redundant_clone.rs:127:14
| |
LL | let _s = s.clone(); LL | let _s = s.clone();
| ^ | ^
error: redundant clone error: redundant clone
--> $DIR/redundant_clone.rs:123:15 --> $DIR/redundant_clone.rs:128:15
| |
LL | let _t = t.clone(); LL | let _t = t.clone();
| ^^^^^^^^ help: remove this | ^^^^^^^^ help: remove this
| |
note: this value is dropped without further use note: this value is dropped without further use
--> $DIR/redundant_clone.rs:123:14 --> $DIR/redundant_clone.rs:128:14
| |
LL | let _t = t.clone(); LL | let _t = t.clone();
| ^ | ^
error: redundant clone error: redundant clone
--> $DIR/redundant_clone.rs:133:19 --> $DIR/redundant_clone.rs:138:19
| |
LL | let _f = f.clone(); LL | let _f = f.clone();
| ^^^^^^^^ help: remove this | ^^^^^^^^ help: remove this
| |
note: this value is dropped without further use note: this value is dropped without further use
--> $DIR/redundant_clone.rs:133:18 --> $DIR/redundant_clone.rs:138:18
| |
LL | let _f = f.clone(); LL | let _f = f.clone();
| ^ | ^
error: redundant clone error: redundant clone
--> $DIR/redundant_clone.rs:145:14 --> $DIR/redundant_clone.rs:150:14
| |
LL | let y = x.clone().join("matthias"); LL | let y = x.clone().join("matthias");
| ^^^^^^^^ help: remove this | ^^^^^^^^ help: remove this
| |
note: cloned value is neither consumed nor mutated note: cloned value is neither consumed nor mutated
--> $DIR/redundant_clone.rs:145:13 --> $DIR/redundant_clone.rs:150:13
| |
LL | let y = x.clone().join("matthias"); LL | let y = x.clone().join("matthias");
| ^^^^^^^^^ | ^^^^^^^^^
error: redundant clone error: redundant clone
--> $DIR/redundant_clone.rs:199:11 --> $DIR/redundant_clone.rs:204:11
| |
LL | foo(&x.clone(), move || { LL | foo(&x.clone(), move || {
| ^^^^^^^^ help: remove this | ^^^^^^^^ help: remove this
| |
note: this value is dropped without further use note: this value is dropped without further use
--> $DIR/redundant_clone.rs:199:10 --> $DIR/redundant_clone.rs:204:10
| |
LL | foo(&x.clone(), move || { LL | foo(&x.clone(), move || {
| ^ | ^