r? @ghost

changelog: none
This commit is contained in:
Philipp Krones 2024-12-15 15:55:37 +00:00 committed by GitHub
commit 1dddeab7c9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
113 changed files with 400 additions and 572 deletions

View file

@ -9,7 +9,11 @@ use rustc_span::sym;
pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute) {
if let AttrKind::Normal(normal_attr) = &attr.kind {
if let AttrArgs::Eq(_, AttrArgsEq::Ast(_)) = &normal_attr.item.args {
if let AttrArgs::Eq {
value: AttrArgsEq::Ast(_),
..
} = &normal_attr.item.args
{
// `#[should_panic = ".."]` found, good
return;
}

View file

@ -747,7 +747,6 @@ pub static LINTS: &[&crate::LintInfo] = &[
crate::unit_types::LET_UNIT_VALUE_INFO,
crate::unit_types::UNIT_ARG_INFO,
crate::unit_types::UNIT_CMP_INFO,
crate::unnamed_address::FN_ADDRESS_COMPARISONS_INFO,
crate::unnecessary_box_returns::UNNECESSARY_BOX_RETURNS_INFO,
crate::unnecessary_literal_bound::UNNECESSARY_LITERAL_BOUND_INFO,
crate::unnecessary_map_on_constructor::UNNECESSARY_MAP_ON_CONSTRUCTOR_INFO,

View file

@ -5,7 +5,7 @@ use clippy_utils::{contains_name, get_parent_expr, in_automatically_derived, is_
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability;
use rustc_hir::def::Res;
use rustc_hir::{Block, Expr, ExprKind, PatKind, QPath, Stmt, StmtKind};
use rustc_hir::{Block, Expr, ExprKind, PatKind, QPath, Stmt, StmtKind, StructTailExpr};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_middle::ty::print::with_forced_trimmed_paths;
@ -285,7 +285,7 @@ fn field_reassigned_by_stmt<'tcx>(this: &Stmt<'tcx>, binding_name: Symbol) -> Op
/// Returns whether `expr` is the update syntax base: `Foo { a: 1, .. base }`
fn is_update_syntax_base<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool {
if let Some(parent) = get_parent_expr(cx, expr)
&& let ExprKind::Struct(_, _, Some(base)) = parent.kind
&& let ExprKind::Struct(_, _, StructTailExpr::Base(base)) = parent.kind
{
base.hir_id == expr.hir_id
} else {

View file

@ -4,7 +4,7 @@ use clippy_utils::source::snippet_opt;
use rustc_ast::ast::{LitFloatType, LitIntType, LitKind};
use rustc_errors::Applicability;
use rustc_hir::intravisit::{Visitor, walk_expr, walk_stmt};
use rustc_hir::{Block, Body, ConstContext, Expr, ExprKind, FnRetTy, HirId, Lit, Stmt, StmtKind};
use rustc_hir::{Block, Body, ConstContext, Expr, ExprKind, FnRetTy, HirId, Lit, Stmt, StmtKind, StructTailExpr};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::{self, FloatTy, IntTy, PolyFnSig, Ty};
@ -198,7 +198,7 @@ impl<'tcx> Visitor<'tcx> for NumericFallbackVisitor<'_, 'tcx> {
}
// Visit base with no bound.
if let Some(base) = base {
if let StructTailExpr::Base(base) = base {
self.ty_bounds.push(ExplicitTyBound(false));
self.visit_expr(base);
self.ty_bounds.pop();

View file

@ -74,6 +74,8 @@ declare_with_version! { RENAMED(RENAMED_VERSION): &[(&str, &str)] = &[
#[clippy::version = "1.53.0"]
("clippy::filter_map", "clippy::manual_filter_map"),
#[clippy::version = ""]
("clippy::fn_address_comparisons", "unpredictable_function_pointer_comparisons"),
#[clippy::version = ""]
("clippy::identity_conversion", "clippy::useless_conversion"),
#[clippy::version = "pre 1.29.0"]
("clippy::if_let_redundant_pattern_matching", "clippy::redundant_pattern_matching"),

View file

@ -7,7 +7,7 @@ use clippy_utils::{
peel_middle_ty_refs,
};
use core::mem;
use rustc_ast::util::parser::{PREC_PREFIX, PREC_UNAMBIGUOUS};
use rustc_ast::util::parser::ExprPrecedence;
use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::Applicability;
use rustc_hir::def_id::DefId;
@ -814,12 +814,13 @@ impl TyCoercionStability {
| TyKind::Tup(_)
| TyKind::Path(_) => Self::Deref,
TyKind::OpaqueDef(..)
| TyKind::TraitAscription(..)
| TyKind::Infer
| TyKind::Typeof(..)
| TyKind::TraitObject(..)
| TyKind::InferDelegation(..)
| TyKind::AnonAdt(..)
| TyKind::Err(_) => Self::Reborrow,
TyKind::UnsafeBinder(..) => Self::None,
};
}
}
@ -963,7 +964,7 @@ fn report<'tcx>(
// expr_str (the suggestion) is never shown if is_final_ufcs is true, since it's
// `expr.kind == ExprKind::Call`. Therefore, this is, afaik, always unnecessary.
/*
expr_str = if !expr_is_macro_call && is_final_ufcs && expr.precedence() < PREC_PREFIX {
expr_str = if !expr_is_macro_call && is_final_ufcs && expr.precedence() < ExprPrecedence::Prefix {
Cow::Owned(format!("({expr_str})"))
} else {
expr_str
@ -999,13 +1000,16 @@ fn report<'tcx>(
data.first_expr.span,
state.msg,
|diag| {
let (precedence, calls_field) = match cx.tcx.parent_hir_node(data.first_expr.hir_id) {
let needs_paren = match cx.tcx.parent_hir_node(data.first_expr.hir_id) {
Node::Expr(e) => match e.kind {
ExprKind::Call(callee, _) if callee.hir_id != data.first_expr.hir_id => (0, false),
ExprKind::Call(..) => (PREC_UNAMBIGUOUS, matches!(expr.kind, ExprKind::Field(..))),
_ => (e.precedence(), false),
ExprKind::Call(callee, _) if callee.hir_id != data.first_expr.hir_id => false,
ExprKind::Call(..) => {
expr.precedence() < ExprPrecedence::Unambiguous
|| matches!(expr.kind, ExprKind::Field(..))
},
_ => expr.precedence() < e.precedence(),
},
_ => (0, false),
_ => false,
};
let is_in_tuple = matches!(
get_parent_expr(cx, data.first_expr),
@ -1015,11 +1019,7 @@ fn report<'tcx>(
})
);
let sugg = if !snip_is_macro
&& (calls_field || expr.precedence() < precedence)
&& !has_enclosing_paren(&snip)
&& !is_in_tuple
{
let sugg = if !snip_is_macro && needs_paren && !has_enclosing_paren(&snip) && !is_in_tuple {
format!("({snip})")
} else {
snip.into()
@ -1049,16 +1049,16 @@ fn report<'tcx>(
}
}
let (prefix, precedence) = match mutability {
let (prefix, needs_paren) = match mutability {
Some(mutability) if !ty.is_ref() => {
let prefix = match mutability {
Mutability::Not => "&",
Mutability::Mut => "&mut ",
};
(prefix, PREC_PREFIX)
(prefix, expr.precedence() < ExprPrecedence::Prefix)
},
None if !ty.is_ref() && data.adjusted_ty.is_ref() => ("&", 0),
_ => ("", 0),
None if !ty.is_ref() && data.adjusted_ty.is_ref() => ("&", false),
_ => ("", false),
};
span_lint_hir_and_then(
cx,
@ -1070,7 +1070,7 @@ fn report<'tcx>(
let mut app = Applicability::MachineApplicable;
let (snip, snip_is_macro) =
snippet_with_context(cx, expr.span, data.first_expr.span.ctxt(), "..", &mut app);
let sugg = if !snip_is_macro && expr.precedence() < precedence && !has_enclosing_paren(&snip) {
let sugg = if !snip_is_macro && needs_paren && !has_enclosing_paren(&snip) {
format!("{prefix}({snip})")
} else {
format!("{prefix}{snip}")
@ -1157,7 +1157,7 @@ impl<'tcx> Dereferencing<'tcx> {
},
Some(parent) if !parent.span.from_expansion() => {
// Double reference might be needed at this point.
if parent.precedence() == PREC_UNAMBIGUOUS {
if parent.precedence() == ExprPrecedence::Unambiguous {
// Parentheses would be needed here, don't lint.
*outer_pat = None;
} else {

View file

@ -12,7 +12,7 @@ pub fn check(cx: &LateContext<'_>, attrs: &[Attribute]) {
if !attr.span.from_expansion()
&& let AttrKind::Normal(ref normal) = attr.kind
&& normal.item.path == sym::doc
&& let AttrArgs::Eq(_, AttrArgsEq::Hir(ref meta)) = normal.item.args
&& let AttrArgs::Eq { value: AttrArgsEq::Hir(ref meta), .. } = normal.item.args
&& !attr.span.contains(meta.span)
// Since the `include_str` is already expanded at this point, we can only take the
// whole attribute snippet and then modify for our suggestion.

View file

@ -948,11 +948,11 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
);
refdefrange.start - range.start
} else {
let mut start = next_range.start;
if start > 0 && doc.as_bytes().get(start - 1) == Some(&b'\\') {
// backslashes aren't in the event stream...
start -= 1;
}
let mut start = next_range.start;
if start > 0 && doc.as_bytes().get(start - 1) == Some(&b'\\') {
// backslashes aren't in the event stream...
start -= 1;
}
start - range.start
}
} else {

View file

@ -63,7 +63,7 @@ impl_lint_pass!(DuplicateMod => [DUPLICATE_MOD]);
impl EarlyLintPass for DuplicateMod {
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
if let ItemKind::Mod(_, ModKind::Loaded(_, Inline::No, mod_spans)) = &item.kind
if let ItemKind::Mod(_, ModKind::Loaded(_, Inline::No, mod_spans, _)) = &item.kind
&& let FileName::Real(real) = cx.sess().source_map().span_to_filename(mod_spans.inner_span)
&& let Some(local_path) = real.into_local_path()
&& let Ok(absolute_path) = local_path.canonicalize()

View file

@ -163,7 +163,7 @@ impl Visitor<'_> for NestingVisitor<'_, '_> {
}
match &item.kind {
ItemKind::Trait(_) | ItemKind::Impl(_) | ItemKind::Mod(.., ModKind::Loaded(_, Inline::Yes, _)) => {
ItemKind::Trait(_) | ItemKind::Impl(_) | ItemKind::Mod(.., ModKind::Loaded(_, Inline::Yes, _, _)) => {
self.nest_level += 1;
if !self.check_indent(item.span, item.id) {

View file

@ -58,7 +58,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite {
// match call to write_fmt
&& let ExprKind::MethodCall(write_fun, write_recv, [write_arg], _) = *look_in_block(cx, &write_call.kind)
&& let ExprKind::Call(write_recv_path, []) = write_recv.kind
&& write_fun.ident.name.as_str() == "write_fmt"
&& write_fun.ident.name == sym::write_fmt
&& let Some(def_id) = path_def_id(cx, write_recv_path)
{
// match calls to std::io::stdout() / std::io::stderr ()

View file

@ -3,7 +3,7 @@ use clippy_utils::fulfill_or_allowed;
use clippy_utils::source::snippet;
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::Applicability;
use rustc_hir::{self as hir, ExprKind};
use rustc_hir::{self as hir, ExprKind, StructTailExpr};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
use rustc_span::symbol::Symbol;
@ -95,7 +95,7 @@ impl<'tcx> LateLintPass<'tcx> for InconsistentStructConstructor {
}
fields_snippet.push_str(&last_ident.to_string());
let base_snippet = if let Some(base) = base {
let base_snippet = if let StructTailExpr::Base(base) = base {
format!(", ..{}", snippet(cx, base.span, ".."))
} else {
String::new()

View file

@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::{Expr, ExprKind};
use rustc_hir::{Expr, ExprKind, StructTailExpr};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
use rustc_span::SyntaxContext;
@ -43,7 +43,7 @@ declare_lint_pass!(NumberedFields => [INIT_NUMBERED_FIELDS]);
impl<'tcx> LateLintPass<'tcx> for NumberedFields {
fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
if let ExprKind::Struct(path, fields @ [field, ..], None) = e.kind
if let ExprKind::Struct(path, fields @ [field, ..], StructTailExpr::None) = e.kind
// If the first character of any field is a digit it has to be a tuple.
&& field.ident.as_str().as_bytes().first().is_some_and(u8::is_ascii_digit)
// Type aliases can't be used as functions.

View file

@ -96,7 +96,7 @@ impl LateLintPass<'_> for LargeIncludeFile {
&& let AttrKind::Normal(ref normal) = attr.kind
&& let Some(doc) = attr.doc_str()
&& doc.as_str().len() as u64 > self.max_file_size
&& let AttrArgs::Eq(_, AttrArgsEq::Hir(ref meta)) = normal.item.args
&& let AttrArgs::Eq { value: AttrArgsEq::Hir(ref meta), .. } = normal.item.args
&& !attr.span.contains(meta.span)
// Since the `include_str` is already expanded at this point, we can only take the
// whole attribute snippet and then modify for our suggestion.

View file

@ -5,7 +5,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_from_proc_macro;
use clippy_utils::macros::macro_backtrace;
use clippy_utils::source::snippet;
use rustc_hir::{ArrayLen, Expr, ExprKind, Item, ItemKind, Node};
use rustc_hir::{Expr, ExprKind, Item, ItemKind, Node};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::{self, ConstKind};
@ -118,13 +118,13 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackArrays {
/// Only giving help messages if the expr does not contains macro expanded codes.
fn might_be_expanded<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> bool {
/// Check if the span of `ArrayLen` of a repeat expression is within the expr's span,
/// Check if the span of `ConstArg` of a repeat expression is within the expr's span,
/// if not, meaning this repeat expr is definitely from some proc-macro.
///
/// This is a fail-safe to a case where even the `is_from_proc_macro` is unable to determain the
/// correct result.
fn repeat_expr_might_be_expanded(expr: &Expr<'_>) -> bool {
let ExprKind::Repeat(_, ArrayLen::Body(len_ct)) = expr.kind else {
let ExprKind::Repeat(_, len_ct) = expr.kind else {
return false;
};
!expr.span.contains(len_ct.span())

View file

@ -366,7 +366,6 @@ mod uninhabited_references;
mod uninit_vec;
mod unit_return_expecting_ord;
mod unit_types;
mod unnamed_address;
mod unnecessary_box_returns;
mod unnecessary_literal_bound;
mod unnecessary_map_on_constructor;
@ -789,7 +788,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
store.register_early_pass(|| Box::new(option_env_unwrap::OptionEnvUnwrap));
store.register_late_pass(move |_| Box::new(wildcard_imports::WildcardImports::new(conf)));
store.register_late_pass(|_| Box::<redundant_pub_crate::RedundantPubCrate>::default());
store.register_late_pass(|_| Box::new(unnamed_address::UnnamedAddress));
store.register_late_pass(|_| Box::<dereference::Dereferencing<'_>>::default());
store.register_late_pass(|_| Box::new(option_if_let_else::OptionIfLetElse));
store.register_late_pass(|_| Box::new(future_not_send::FutureNotSend));

View file

@ -5,7 +5,7 @@ use clippy_utils::higher::ForLoop;
use clippy_utils::macros::root_macro_call_first_node;
use clippy_utils::source::snippet;
use rustc_errors::Applicability;
use rustc_hir::{Block, Destination, Expr, ExprKind, HirId, InlineAsmOperand, Pat, Stmt, StmtKind};
use rustc_hir::{Block, Destination, Expr, ExprKind, HirId, InlineAsmOperand, Pat, Stmt, StmtKind, StructTailExpr};
use rustc_lint::LateContext;
use rustc_span::{Span, sym};
use std::iter::once;
@ -156,7 +156,8 @@ fn never_loop_expr<'tcx>(
| ExprKind::Field(e, _)
| ExprKind::AddrOf(_, _, e)
| ExprKind::Repeat(e, _)
| ExprKind::DropTemps(e) => never_loop_expr(cx, e, local_labels, main_loop_id),
| ExprKind::DropTemps(e)
| ExprKind::UnsafeBinderCast(_, e, _) => never_loop_expr(cx, e, local_labels, main_loop_id),
ExprKind::Let(let_expr) => never_loop_expr(cx, let_expr.init, local_labels, main_loop_id),
ExprKind::Array(es) | ExprKind::Tup(es) => never_loop_expr_all(cx, es.iter(), local_labels, main_loop_id),
ExprKind::MethodCall(_, receiver, es, _) => {
@ -164,7 +165,7 @@ fn never_loop_expr<'tcx>(
},
ExprKind::Struct(_, fields, base) => {
let fields = never_loop_expr_all(cx, fields.iter().map(|f| f.expr), local_labels, main_loop_id);
if let Some(base) = base {
if let StructTailExpr::Base(base) = base {
combine_seq(fields, || never_loop_expr(cx, base, local_labels, main_loop_id))
} else {
fields

View file

@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::{indent_of, snippet, snippet_with_applicability};
use clippy_utils::visitors::contains_break_or_continue;
use rustc_ast::Mutability;
use rustc_ast::util::parser::PREC_PREFIX;
use rustc_ast::util::parser::ExprPrecedence;
use rustc_errors::Applicability;
use rustc_hir::{BorrowKind, Expr, ExprKind, Pat, PatKind, is_range_literal};
use rustc_lint::LateContext;
@ -84,7 +84,7 @@ pub(super) fn check<'tcx>(
if !prefix.is_empty()
&& (
// Precedence of internal expression is less than or equal to precedence of `&expr`.
arg_expression.precedence() <= PREC_PREFIX || is_range_literal(arg_expression)
arg_expression.precedence() <= ExprPrecedence::Prefix || is_range_literal(arg_expression)
)
{
arg_snip = format!("({arg_snip})").into();

View file

@ -5,9 +5,12 @@ use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::SpanRangeExt;
use clippy_utils::{is_from_proc_macro, path_to_local};
use rustc_errors::Applicability;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
use rustc_hir::{BinOpKind, Constness, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass, Lint, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::TyCtxt;
use rustc_session::impl_lint_pass;
declare_clippy_lint! {
@ -94,6 +97,42 @@ impl ManualFloatMethods {
}
}
fn is_not_const(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
match tcx.def_kind(def_id) {
DefKind::Mod
| DefKind::Struct
| DefKind::Union
| DefKind::Enum
| DefKind::Variant
| DefKind::Trait
| DefKind::TyAlias
| DefKind::ForeignTy
| DefKind::TraitAlias
| DefKind::AssocTy
| DefKind::Macro(..)
| DefKind::Field
| DefKind::LifetimeParam
| DefKind::ExternCrate
| DefKind::Use
| DefKind::ForeignMod
| DefKind::GlobalAsm
| DefKind::Impl { .. }
| DefKind::OpaqueTy
| DefKind::SyntheticCoroutineBody
| DefKind::TyParam => true,
DefKind::AnonConst
| DefKind::InlineConst
| DefKind::Const
| DefKind::ConstParam
| DefKind::Static { .. }
| DefKind::Ctor(..)
| DefKind::AssocConst => false,
DefKind::Fn | DefKind::AssocFn | DefKind::Closure => tcx.constness(def_id) == Constness::NotConst,
}
}
impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
if let ExprKind::Binary(kind, lhs, rhs) = expr.kind
@ -105,7 +144,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods {
&& exprs.iter_mut().partition_in_place(|i| path_to_local(i).is_some()) == 2
&& !in_external_macro(cx.sess(), expr.span)
&& (
matches!(cx.tcx.constness(cx.tcx.hir().enclosing_body_owner(expr.hir_id)), Constness::NotConst)
is_not_const(cx.tcx, cx.tcx.hir().enclosing_body_owner(expr.hir_id).into())
|| self.msrv.meets(msrvs::CONST_FLOAT_CLASSIFY)
)
&& let [first, second, const_1, const_2] = exprs

View file

@ -7,7 +7,7 @@ use clippy_utils::{
CaptureKind, can_move_expr_to_closure, is_else_clause, is_lint_allowed, is_res_lang_ctor, path_res,
path_to_local_id, peel_blocks, peel_hir_expr_refs, peel_hir_expr_while,
};
use rustc_ast::util::parser::PREC_UNAMBIGUOUS;
use rustc_ast::util::parser::ExprPrecedence;
use rustc_errors::Applicability;
use rustc_hir::LangItem::{OptionNone, OptionSome};
use rustc_hir::def::Res;
@ -117,7 +117,7 @@ where
// it's being passed by value.
let scrutinee = peel_hir_expr_refs(scrutinee).0;
let (scrutinee_str, _) = snippet_with_context(cx, scrutinee.span, expr_ctxt, "..", &mut app);
let scrutinee_str = if scrutinee.span.eq_ctxt(expr.span) && scrutinee.precedence() < PREC_UNAMBIGUOUS {
let scrutinee_str = if scrutinee.span.eq_ctxt(expr.span) && scrutinee.precedence() < ExprPrecedence::Unambiguous {
format!("({scrutinee_str})")
} else {
scrutinee_str.into()

View file

@ -148,7 +148,7 @@ pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>, name:
_ => {},
}
}
requires_copy |= !ty.is_copy_modulo_regions(cx.tcx, cx.typing_env());
requires_copy |= !cx.type_is_copy_modulo_regions(ty);
break;
}
},
@ -158,7 +158,7 @@ pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>, name:
}
if can_lint
&& (!requires_copy || arg_ty.is_copy_modulo_regions(cx.tcx, cx.typing_env()))
&& (!requires_copy || cx.type_is_copy_modulo_regions(arg_ty))
// This case could be handled, but a fair bit of care would need to be taken.
&& (!requires_deref || arg_ty.is_freeze(cx.tcx, cx.typing_env()))
{

View file

@ -3,13 +3,12 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::ty::is_copy;
use clippy_utils::usage::mutated_variables;
use clippy_utils::visitors::{Descend, for_each_expr_without_closures};
use clippy_utils::{MaybePath, is_res_lang_ctor, is_trait_method, path_res, path_to_local_id};
use clippy_utils::{is_res_lang_ctor, is_trait_method, path_res, path_to_local_id};
use core::ops::ControlFlow;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::LangItem::{OptionNone, OptionSome};
use rustc_lint::LateContext;
use rustc_middle::query::Key;
use rustc_middle::ty;
use rustc_span::sym;
@ -44,7 +43,6 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>, a
if name == "filter_map"
&& let hir::ExprKind::Call(expr, args) = body.value.kind
&& is_res_lang_ctor(cx, path_res(cx, expr), OptionSome)
&& arg_id.ty_def_id() == args[0].hir_id().ty_def_id()
&& let hir::ExprKind::Path(_) = args[0].kind
{
span_lint_and_sugg(

View file

@ -200,6 +200,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
cx.param_env,
ty,
traits::ObligationCause::dummy_with_span(span),
rustc_hir::Safety::Safe,
)
.is_ok()
{

View file

@ -1,5 +1,5 @@
use clippy_utils::diagnostics::span_lint;
use rustc_hir::{Expr, ExprKind};
use rustc_hir::{Expr, ExprKind, StructTailExpr};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::declare_lint_pass;
@ -51,7 +51,7 @@ declare_lint_pass!(NeedlessUpdate => [NEEDLESS_UPDATE]);
impl<'tcx> LateLintPass<'tcx> for NeedlessUpdate {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
if let ExprKind::Struct(_, fields, Some(base)) = expr.kind {
if let ExprKind::Struct(_, fields, StructTailExpr::Base(base)) = expr.kind {
let ty = cx.typeck_results().expr_ty(expr);
if let ty::Adt(def, _) = ty.kind() {
if fields.len() == def.non_enum_variant().fields.len()

View file

@ -2,7 +2,7 @@ use clippy_utils::consts::{self, Constant};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_context;
use clippy_utils::sugg::has_enclosing_paren;
use rustc_ast::util::parser::PREC_PREFIX;
use rustc_ast::util::parser::ExprPrecedence;
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
use rustc_lint::{LateContext, LateLintPass};
@ -58,7 +58,7 @@ fn check_mul(cx: &LateContext<'_>, span: Span, lit: &Expr<'_>, exp: &Expr<'_>) {
{
let mut applicability = Applicability::MachineApplicable;
let (snip, from_macro) = snippet_with_context(cx, exp.span, span.ctxt(), "..", &mut applicability);
let suggestion = if !from_macro && exp.precedence() < PREC_PREFIX && !has_enclosing_paren(&snip) {
let suggestion = if !from_macro && exp.precedence() < ExprPrecedence::Prefix && !has_enclosing_paren(&snip) {
format!("-({snip})")
} else {
format!("-{snip}")

View file

@ -8,7 +8,7 @@ use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::{
BinOpKind, BlockCheckMode, Expr, ExprKind, HirId, HirIdMap, ItemKind, LocalSource, Node, PatKind, Stmt, StmtKind,
UnsafeSource, is_range_literal,
StructTailExpr, UnsafeSource, is_range_literal,
};
use rustc_infer::infer::TyCtxtInferExt as _;
use rustc_lint::{LateContext, LateLintPass, LintContext};
@ -238,7 +238,10 @@ fn has_no_effect(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
ExprKind::Struct(_, fields, ref base) => {
!has_drop(cx, cx.typeck_results().expr_ty(expr))
&& fields.iter().all(|field| has_no_effect(cx, field.expr))
&& base.as_ref().is_none_or(|base| has_no_effect(cx, base))
&& match &base {
StructTailExpr::None | StructTailExpr::DefaultFields(_) => true,
StructTailExpr::Base(base) => has_no_effect(cx, base),
}
},
ExprKind::Call(callee, args) => {
if let ExprKind::Path(ref qpath) = callee.kind {
@ -342,6 +345,10 @@ fn reduce_expression<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<Vec
if has_drop(cx, cx.typeck_results().expr_ty(expr)) {
None
} else {
let base = match base {
StructTailExpr::Base(base) => Some(base),
StructTailExpr::None | StructTailExpr::DefaultFields(_) => None,
};
Some(fields.iter().map(|f| &f.expr).chain(base).map(Deref::deref).collect())
}
},

View file

@ -11,7 +11,7 @@ use rustc_hir::{
BodyId, Expr, ExprKind, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind, UnOp,
};
use rustc_lint::{LateContext, LateLintPass, Lint};
use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult, GlobalId};
use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult, GlobalId, ReportedErrorInfo};
use rustc_middle::ty::adjustment::Adjust;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_session::impl_lint_pass;
@ -302,7 +302,10 @@ impl<'tcx> NonCopyConst<'tcx> {
tcx.const_eval_global_id_for_typeck(typing_env, cid, span)
},
Ok(None) => Err(ErrorHandled::TooGeneric(span)),
Err(err) => Err(ErrorHandled::Reported(err.into(), span)),
Err(err) => Err(ErrorHandled::Reported(
ReportedErrorInfo::non_const_eval_error(err),
span,
)),
}
}
}

View file

@ -251,7 +251,7 @@ fn check_is_none_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Ex
{
let mut applicability = Applicability::MachineApplicable;
let receiver_str = snippet_with_applicability(cx, caller.span, "..", &mut applicability);
let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx, cx.typing_env())
let by_ref = !cx.type_is_copy_modulo_regions(caller_ty)
&& !matches!(caller.kind, ExprKind::Call(..) | ExprKind::MethodCall(..));
let sugg = if let Some(else_inner) = r#else {
if eq_expr_value(cx, caller, peel_blocks(else_inner)) {

View file

@ -2,7 +2,7 @@ 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};
use rustc_ast::util::parser::PREC_PREFIX;
use rustc_ast::util::parser::ExprPrecedence;
use rustc_errors::Applicability;
use rustc_hir::{BorrowKind, Expr, ExprKind, LangItem, Mutability};
use rustc_lint::{LateContext, LateLintPass, Lint};
@ -85,7 +85,8 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing {
let (expr_ty, expr_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(expr));
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.is_some_and(|parent| parent.precedence() > PREC_PREFIX);
let needs_parens_for_prefix =
parent_expr.is_some_and(|parent| parent.precedence() > ExprPrecedence::Prefix);
if expr_ty == indexed_ty {
if expr_ref_count > indexed_ref_count {

View file

@ -6,7 +6,7 @@ use clippy_utils::source::SpanRangeExt;
use clippy_utils::ty::implements_trait;
use rustc_ast::{LitIntType, LitKind, UintTy};
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, LangItem, QPath};
use rustc_hir::{Expr, ExprKind, LangItem, QPath, StructTailExpr};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
use std::fmt::{self, Display, Formatter};
@ -86,7 +86,8 @@ impl LateLintPass<'_> for SingleRangeInVecInit {
return;
};
let ExprKind::Struct(QPath::LangItem(lang_item, ..), [start, end], None) = inner_expr.kind else {
let ExprKind::Struct(QPath::LangItem(lang_item, ..), [start, end], StructTailExpr::None) = inner_expr.kind
else {
return;
};

View file

@ -1,7 +1,7 @@
use super::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::sugg::Sugg;
use rustc_ast::util::parser::AssocOp;
use rustc_ast::util::parser::ExprPrecedence;
use rustc_errors::Applicability;
use rustc_hir::{Expr, Node};
use rustc_hir_typeck::cast::check_cast;
@ -44,8 +44,7 @@ pub(super) fn check<'tcx>(
};
if let Node::Expr(parent) = cx.tcx.parent_hir_node(e.hir_id)
&& parent.precedence()
> i8::try_from(AssocOp::As.precedence()).expect("AssocOp always returns a precedence < 128")
&& parent.precedence() > ExprPrecedence::Cast
{
sugg = format!("({sugg})");
}

View file

@ -1,60 +0,0 @@
use clippy_utils::diagnostics::span_lint;
use rustc_hir::{BinOpKind, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::declare_lint_pass;
declare_clippy_lint! {
/// ### What it does
/// Checks for comparisons with an address of a function item.
///
/// ### Why is this bad?
/// Function item address is not guaranteed to be unique and could vary
/// between different code generation units. Furthermore different function items could have
/// the same address after being merged together.
///
/// ### Example
/// ```no_run
/// type F = fn();
/// fn a() {}
/// let f: F = a;
/// if f == a {
/// // ...
/// }
/// ```
#[clippy::version = "1.44.0"]
pub FN_ADDRESS_COMPARISONS,
correctness,
"comparison with an address of a function item"
}
declare_lint_pass!(UnnamedAddress => [FN_ADDRESS_COMPARISONS]);
impl LateLintPass<'_> for UnnamedAddress {
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
fn is_comparison(binop: BinOpKind) -> bool {
matches!(
binop,
BinOpKind::Eq | BinOpKind::Lt | BinOpKind::Le | BinOpKind::Ne | BinOpKind::Ge | BinOpKind::Gt
)
}
fn is_fn_def(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
matches!(cx.typeck_results().expr_ty(expr).kind(), ty::FnDef(..))
}
if let ExprKind::Binary(binop, left, right) = expr.kind
&& is_comparison(binop.node)
&& cx.typeck_results().expr_ty_adjusted(left).is_fn_ptr()
&& cx.typeck_results().expr_ty_adjusted(right).is_fn_ptr()
&& (is_fn_def(cx, left) || is_fn_def(cx, right))
{
span_lint(
cx,
FN_ADDRESS_COMPARISONS,
expr.span,
"comparing with a non-unique address of a function item",
);
}
}
}

View file

@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet;
use clippy_utils::ty::is_copy;
use clippy_utils::{get_parent_expr, path_to_local};
use rustc_hir::{BindingMode, Expr, ExprField, ExprKind, Node, PatKind, Path, QPath, UnOp};
use rustc_hir::{BindingMode, Expr, ExprField, ExprKind, Node, PatKind, Path, QPath, StructTailExpr, UnOp};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
@ -59,15 +59,17 @@ impl LateLintPass<'_> for UnnecessaryStruct {
let field_path = same_path_in_all_fields(cx, expr, fields);
let sugg = match (field_path, base) {
(Some(&path), None) => {
(Some(&path), StructTailExpr::None | StructTailExpr::DefaultFields(_)) => {
// all fields match, no base given
path.span
},
(Some(path), Some(base)) if base_is_suitable(cx, expr, base) && path_matches_base(path, base) => {
(Some(path), StructTailExpr::Base(base))
if base_is_suitable(cx, expr, base) && path_matches_base(path, base) =>
{
// all fields match, has base: ensure that the path of the base matches
base.span
},
(None, Some(base)) if fields.is_empty() && base_is_suitable(cx, expr, base) => {
(None, StructTailExpr::Base(base)) if fields.is_empty() && base_is_suitable(cx, expr, base) => {
// just the base, no explicit fields
base.span
},

View file

@ -234,7 +234,7 @@ fn transform_with_focus_on_idx(alternatives: &mut ThinVec<P<Pat>>, focus_idx: us
// In the case of only two patterns, replacement adds net characters.
| Ref(_, Mutability::Not)
// Dealt with elsewhere.
| Or(_) | Paren(_) | Deref(_) => false,
| Or(_) | Paren(_) | Deref(_) | Guard(..) => false,
// Transform `box x | ... | box y` into `box (x | y)`.
//
// The cases below until `Slice(...)` deal with *singleton* products.

View file

@ -14,7 +14,7 @@ use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::{self, AdtDef, EarlyBinder, GenericArg, GenericArgsRef, Ty, TypeVisitableExt};
use rustc_session::impl_lint_pass;
use rustc_span::{Span, Symbol, sym};
use rustc_span::{Span, sym};
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
declare_clippy_lint! {
@ -422,14 +422,7 @@ fn has_eligible_receiver(cx: &LateContext<'_>, recv: &Expr<'_>, expr: &Expr<'_>)
return true;
}
// FIXME: Add ControlFlow diagnostic item
let def_path = cx.get_def_path(recv_ty_defid);
if def_path
.iter()
.map(Symbol::as_str)
.zip(["core", "ops", "control_flow", "ControlFlow"])
.all(|(sym, s)| sym == s)
{
if cx.tcx.is_diagnostic_item(sym::ControlFlow, recv_ty_defid) {
return true;
}
}

View file

@ -3,8 +3,8 @@ use rustc_ast::LitIntType;
use rustc_ast::ast::{LitFloatType, LitKind};
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::{
self as hir, ArrayLen, BindingMode, CaptureBy, Closure, ClosureKind, ConstArg, ConstArgKind, CoroutineKind,
ExprKind, FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, TyKind,
self as hir, BindingMode, CaptureBy, Closure, ClosureKind, ConstArg, ConstArgKind, CoroutineKind, ExprKind,
FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, StructTailExpr, TyKind,
};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_session::declare_lint_pass;
@ -278,6 +278,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
chain!(self, "let ConstArgKind::Anon({anon_const}) = {const_arg}.kind");
self.body(field!(anon_const.body));
},
ConstArgKind::Infer(..) => chain!(self, "let ConstArgKind::Infer(..) = {const_arg}.kind"),
}
}
@ -597,7 +598,10 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
},
ExprKind::Struct(qpath, fields, base) => {
bind!(self, qpath, fields);
opt_bind!(self, base);
let base = OptionPat::new(match base {
StructTailExpr::Base(base) => Some(self.bind("base", base)),
StructTailExpr::None | StructTailExpr::DefaultFields(_) => None,
});
kind!("Struct({qpath}, {fields}, {base})");
self.qpath(qpath);
self.slice(fields, |field| {
@ -611,14 +615,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
bind!(self, value, length);
kind!("Repeat({value}, {length})");
self.expr(value);
match length.value {
ArrayLen::Infer(..) => chain!(self, "let ArrayLen::Infer(..) = length"),
ArrayLen::Body(const_arg) => {
bind!(self, const_arg);
chain!(self, "let ArrayLen::Body({const_arg}) = {length}");
self.const_arg(const_arg);
},
}
self.const_arg(length);
},
ExprKind::Err(_) => kind!("Err(_)"),
ExprKind::DropTemps(expr) => {
@ -626,6 +623,9 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
kind!("DropTemps({expr})");
self.expr(expr);
},
ExprKind::UnsafeBinderCast(..) => {
unimplemented!("unsafe binders are not implemented yet");
},
}
}

View file

@ -92,7 +92,7 @@ impl<'tcx> LateLintPass<'tcx> for InterningDefinedSymbol {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
if let ExprKind::Call(func, [arg]) = &expr.kind
&& let ty::FnDef(def_id, _) = cx.typeck_results().expr_ty(func).kind()
&& match_def_path(cx, *def_id, &paths::SYMBOL_INTERN)
&& cx.tcx.is_diagnostic_item(sym::SymbolIntern, *def_id)
&& let Some(Constant::Str(arg)) = ConstEvalCtxt::new(cx).eval_simple(arg)
&& let value = Symbol::intern(&arg).as_u32()
&& let Some(&def_id) = self.symbol_map.get(&value)

View file

@ -1,13 +1,13 @@
use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::paths;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::match_type;
use clippy_utils::{match_function_call, paths};
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
use rustc_span::Span;
use rustc_span::{Span, sym};
declare_clippy_lint! {
/// ### What it does
@ -34,7 +34,12 @@ fn check_slow_comparison<'tcx>(
op2: &'tcx Expr<'tcx>,
) -> Option<(Span, String)> {
if match_type(cx, cx.typeck_results().expr_ty(op1), &paths::SYMBOL)
&& let Some([symbol_name_expr]) = match_function_call(cx, op2, &paths::SYMBOL_INTERN)
&& let ExprKind::Call(fun, args) = op2.kind
&& let ExprKind::Path(ref qpath) = fun.kind
&& cx
.tcx
.is_diagnostic_item(sym::SymbolIntern, cx.qpath_res(qpath, fun.hir_id).opt_def_id()?)
&& let [symbol_name_expr] = args
&& let Some(Constant::Str(symbol_name)) = ConstEvalCtxt::new(cx).eval_simple(symbol_name_expr)
{
Some((op1.span, symbol_name))

View file

@ -5,7 +5,7 @@ use clippy_utils::visitors::for_each_expr_without_closures;
use rustc_ast::LitKind;
use rustc_data_structures::packed::Pu128;
use rustc_errors::Applicability;
use rustc_hir::{ArrayLen, ConstArgKind, ExprKind, Node};
use rustc_hir::{ConstArgKind, ExprKind, Node};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::Ty;
use rustc_session::declare_lint_pass;
@ -60,8 +60,7 @@ impl LateLintPass<'_> for ZeroRepeatSideEffects {
// doesn't seem as confusing as `[f(); 0]`. It would also have false positives when eg.
// the const item depends on `#[cfg]s` and has different values in different compilation
// sessions).
else if let ExprKind::Repeat(inner_expr, length) = expr.kind
&& let ArrayLen::Body(const_arg) = length
else if let ExprKind::Repeat(inner_expr, const_arg) = expr.kind
&& let ConstArgKind::Anon(anon_const) = const_arg.kind
&& let length_expr = hir_map.body(anon_const.body).value
&& !length_expr.span.from_expansion()

View file

@ -8,7 +8,7 @@ This crate is only guaranteed to build with this `nightly` toolchain:
<!-- begin autogenerated nightly -->
```
nightly-2024-11-28
nightly-2024-12-15
```
<!-- end autogenerated nightly -->

View file

@ -379,7 +379,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
(Mod(lu, lmk), Mod(ru, rmk)) => {
lu == ru
&& match (lmk, rmk) {
(ModKind::Loaded(litems, linline, _), ModKind::Loaded(ritems, rinline, _)) => {
(ModKind::Loaded(litems, linline, _, _), ModKind::Loaded(ritems, rinline, _, _)) => {
linline == rinline && over(litems, ritems, |l, r| eq_item(l, r, eq_item_kind))
},
(ModKind::Unloaded, ModKind::Unloaded) => true,
@ -872,8 +872,26 @@ pub fn eq_attr_args(l: &AttrArgs, r: &AttrArgs) -> bool {
match (l, r) {
(Empty, Empty) => true,
(Delimited(la), Delimited(ra)) => eq_delim_args(la, ra),
(Eq(_, AttrArgsEq::Ast(le)), Eq(_, AttrArgsEq::Ast(re))) => eq_expr(le, re),
(Eq(_, AttrArgsEq::Hir(ll)), Eq(_, AttrArgsEq::Hir(rl))) => ll.kind == rl.kind,
(
Eq {
value: AttrArgsEq::Ast(le),
..
},
Eq {
value: AttrArgsEq::Ast(re),
..
},
) => eq_expr(le, re),
(
Eq {
value: AttrArgsEq::Hir(ll),
..
},
Eq {
value: AttrArgsEq::Hir(rl),
..
},
) => ll.kind == rl.kind,
_ => false,
}
}

View file

@ -303,7 +303,8 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS
| ExprKind::AddrOf(..)
| ExprKind::Repeat(..)
| ExprKind::Block(Block { stmts: [], .. }, _)
| ExprKind::OffsetOf(..) => (),
| ExprKind::OffsetOf(..)
| ExprKind::UnsafeBinderCast(..) => (),
// Assignment might be to a local defined earlier, so don't eagerly evaluate.
// Blocks with multiple statements might be expensive, so don't eagerly evaluate.

View file

@ -8,7 +8,7 @@ use crate::ty::is_type_diagnostic_item;
use rustc_ast::ast;
use rustc_hir as hir;
use rustc_hir::{Arm, Block, Expr, ExprKind, HirId, LoopSource, MatchSource, Node, Pat, QPath};
use rustc_hir::{Arm, Block, Expr, ExprKind, HirId, LoopSource, MatchSource, Node, Pat, QPath, StructTailExpr};
use rustc_lint::LateContext;
use rustc_span::{Span, sym, symbol};
@ -236,7 +236,7 @@ impl<'a> Range<'a> {
limits: ast::RangeLimits::Closed,
})
},
ExprKind::Struct(path, fields, None) => match (path, fields) {
ExprKind::Struct(path, fields, StructTailExpr::None) => match (path, fields) {
(QPath::LangItem(hir::LangItem::RangeFull, ..), []) => Some(Range {
start: None,
end: None,

View file

@ -7,9 +7,9 @@ use rustc_data_structures::fx::FxHasher;
use rustc_hir::MatchSource::TryDesugar;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::{
ArrayLen, AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, ConstArg, ConstArgKind, Expr,
ExprField, ExprKind, FnRetTy, GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime,
LifetimeName, Pat, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitBoundModifiers, Ty,
AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, ConstArg, ConstArgKind, Expr, ExprField,
ExprKind, FnRetTy, GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime, LifetimeName,
Pat, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, StructTailExpr, TraitBoundModifiers, Ty,
TyKind,
};
use rustc_lexer::{TokenKind, tokenize};
@ -266,14 +266,6 @@ impl HirEqInterExpr<'_, '_, '_> {
})
}
pub fn eq_array_length(&mut self, left: ArrayLen<'_>, right: ArrayLen<'_>) -> bool {
match (left, right) {
(ArrayLen::Infer(..), ArrayLen::Infer(..)) => true,
(ArrayLen::Body(l_ct), ArrayLen::Body(r_ct)) => self.eq_const_arg(l_ct, r_ct),
(_, _) => false,
}
}
pub fn eq_body(&mut self, left: BodyId, right: BodyId) -> bool {
// swap out TypeckResults when hashing a body
let old_maybe_typeck_results = self.inner.maybe_typeck_results.replace((
@ -378,17 +370,26 @@ impl HirEqInterExpr<'_, '_, '_> {
&& self.eq_expr(l_receiver, r_receiver)
&& self.eq_exprs(l_args, r_args)
},
(&ExprKind::UnsafeBinderCast(lkind, le, None), &ExprKind::UnsafeBinderCast(rkind, re, None)) =>
lkind == rkind && self.eq_expr(le, re),
(&ExprKind::UnsafeBinderCast(lkind, le, Some(lt)), &ExprKind::UnsafeBinderCast(rkind, re, Some(rt))) =>
lkind == rkind && self.eq_expr(le, re) && self.eq_ty(lt, rt),
(&ExprKind::OffsetOf(l_container, l_fields), &ExprKind::OffsetOf(r_container, r_fields)) => {
self.eq_ty(l_container, r_container) && over(l_fields, r_fields, |l, r| l.name == r.name)
},
(ExprKind::Path(l), ExprKind::Path(r)) => self.eq_qpath(l, r),
(&ExprKind::Repeat(le, ll), &ExprKind::Repeat(re, rl)) => {
self.eq_expr(le, re) && self.eq_array_length(ll, rl)
self.eq_expr(le, re) && self.eq_const_arg(ll, rl)
},
(ExprKind::Ret(l), ExprKind::Ret(r)) => both(l.as_ref(), r.as_ref(), |l, r| self.eq_expr(l, r)),
(&ExprKind::Struct(l_path, lf, ref lo), &ExprKind::Struct(r_path, rf, ref ro)) => {
self.eq_qpath(l_path, r_path)
&& both(lo.as_ref(), ro.as_ref(), |l, r| self.eq_expr(l, r))
&& match (lo, ro) {
(StructTailExpr::Base(l),StructTailExpr::Base(r)) => self.eq_expr(l, r),
(StructTailExpr::None, StructTailExpr::None) |
(StructTailExpr::DefaultFields(_), StructTailExpr::DefaultFields(_)) => true,
_ => false,
}
&& over(lf, rf, |l, r| self.eq_expr_field(l, r))
},
(&ExprKind::Tup(l_tup), &ExprKind::Tup(r_tup)) => self.eq_exprs(l_tup, r_tup),
@ -427,6 +428,7 @@ impl HirEqInterExpr<'_, '_, '_> {
| &ExprKind::Type(..)
| &ExprKind::Unary(..)
| &ExprKind::Yield(..)
| &ExprKind::UnsafeBinderCast(..)
// --- Special cases that do not have a positive branch.
@ -469,10 +471,12 @@ impl HirEqInterExpr<'_, '_, '_> {
match (&left.kind, &right.kind) {
(ConstArgKind::Path(l_p), ConstArgKind::Path(r_p)) => self.eq_qpath(l_p, r_p),
(ConstArgKind::Anon(l_an), ConstArgKind::Anon(r_an)) => self.eq_body(l_an.body, r_an.body),
(ConstArgKind::Infer(..), ConstArgKind::Infer(..)) => true,
// Use explicit match for now since ConstArg is undergoing flux.
(ConstArgKind::Path(..), ConstArgKind::Anon(..)) | (ConstArgKind::Anon(..), ConstArgKind::Path(..)) => {
false
},
(ConstArgKind::Path(..), ConstArgKind::Anon(..))
| (ConstArgKind::Anon(..), ConstArgKind::Path(..))
| (ConstArgKind::Infer(..), _)
| (_, ConstArgKind::Infer(..)) => false,
}
}
@ -589,7 +593,7 @@ impl HirEqInterExpr<'_, '_, '_> {
pub fn eq_ty(&mut self, left: &Ty<'_>, right: &Ty<'_>) -> bool {
match (&left.kind, &right.kind) {
(&TyKind::Slice(l_vec), &TyKind::Slice(r_vec)) => self.eq_ty(l_vec, r_vec),
(&TyKind::Array(lt, ll), &TyKind::Array(rt, rl)) => self.eq_ty(lt, rt) && self.eq_array_length(ll, rl),
(&TyKind::Array(lt, ll), &TyKind::Array(rt, rl)) => self.eq_ty(lt, rt) && self.eq_const_arg(ll, rl),
(TyKind::Ptr(l_mut), TyKind::Ptr(r_mut)) => l_mut.mutbl == r_mut.mutbl && self.eq_ty(l_mut.ty, r_mut.ty),
(TyKind::Ref(_, l_rmut), TyKind::Ref(_, r_rmut)) => {
l_rmut.mutbl == r_rmut.mutbl && self.eq_ty(l_rmut.ty, r_rmut.ty)
@ -597,7 +601,6 @@ impl HirEqInterExpr<'_, '_, '_> {
(TyKind::Path(l), TyKind::Path(r)) => self.eq_qpath(l, r),
(&TyKind::Tup(l), &TyKind::Tup(r)) => over(l, r, |l, r| self.eq_ty(l, r)),
(&TyKind::Infer, &TyKind::Infer) => true,
(TyKind::AnonAdt(l_item_id), TyKind::AnonAdt(r_item_id)) => l_item_id == r_item_id,
_ => false,
}
}
@ -1008,7 +1011,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
},
ExprKind::Repeat(e, len) => {
self.hash_expr(e);
self.hash_array_length(len);
self.hash_const_arg(len);
},
ExprKind::Ret(ref e) => {
if let Some(e) = *e {
@ -1023,7 +1026,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
self.hash_expr(f.expr);
}
if let Some(e) = *expr {
if let StructTailExpr::Base(e) = *expr {
self.hash_expr(e);
}
},
@ -1034,6 +1037,13 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
std::mem::discriminant(&lop).hash(&mut self.s);
self.hash_expr(le);
},
ExprKind::UnsafeBinderCast(kind, expr, ty) => {
std::mem::discriminant(&kind).hash(&mut self.s);
self.hash_expr(expr);
if let Some(ty) = ty {
self.hash_ty(ty);
}
},
ExprKind::Err(_) => {},
}
}
@ -1201,7 +1211,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
},
&TyKind::Array(ty, len) => {
self.hash_ty(ty);
self.hash_array_length(len);
self.hash_const_arg(len);
},
TyKind::Pat(ty, pat) => {
self.hash_ty(ty);
@ -1243,19 +1253,15 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
TyKind::Typeof(anon_const) => {
self.hash_body(anon_const.body);
},
TyKind::UnsafeBinder(binder) => {
self.hash_ty(binder.inner_ty);
},
TyKind::Err(_)
| TyKind::Infer
| TyKind::Never
| TyKind::InferDelegation(..)
| TyKind::OpaqueDef(_)
| TyKind::AnonAdt(_) => {},
}
}
pub fn hash_array_length(&mut self, length: ArrayLen<'_>) {
match length {
ArrayLen::Infer(..) => {},
ArrayLen::Body(ct) => self.hash_const_arg(ct),
| TyKind::TraitAscription(_) => {},
}
}
@ -1270,6 +1276,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
match &const_arg.kind {
ConstArgKind::Path(path) => self.hash_qpath(path),
ConstArgKind::Anon(anon) => self.hash_body(anon.body),
ConstArgKind::Infer(..) => {},
}
}

View file

@ -103,7 +103,7 @@ use rustc_hir::definitions::{DefPath, DefPathData};
use rustc_hir::hir_id::{HirIdMap, HirIdSet};
use rustc_hir::intravisit::{FnKind, Visitor, walk_expr};
use rustc_hir::{
self as hir, Arm, ArrayLen, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstArgKind, ConstContext,
self as hir, Arm, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstArgKind, ConstContext,
Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem, ImplItemKind,
ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode, Param, Pat,
PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef, TraitRef,
@ -910,7 +910,7 @@ pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
_ => false,
},
ExprKind::Tup(items) | ExprKind::Array(items) => items.iter().all(|x| is_default_equivalent(cx, x)),
ExprKind::Repeat(x, ArrayLen::Body(len)) => {
ExprKind::Repeat(x, len) => {
if let ConstArgKind::Anon(anon_const) = len.kind
&& let ExprKind::Lit(const_lit) = cx.tcx.hir().body(anon_const.body).value.kind
&& let LitKind::Int(v, _) = const_lit.node
@ -940,7 +940,7 @@ fn is_default_equivalent_from(cx: &LateContext<'_>, from_func: &Expr<'_>, arg: &
..
}) => return sym.is_empty() && is_path_lang_item(cx, ty, LangItem::String),
ExprKind::Array([]) => return is_path_diagnostic_item(cx, ty, sym::Vec),
ExprKind::Repeat(_, ArrayLen::Body(len)) => {
ExprKind::Repeat(_, len) => {
if let ConstArgKind::Anon(anon_const) = len.kind
&& let ExprKind::Lit(const_lit) = cx.tcx.hir().body(anon_const.body).value.kind
&& let LitKind::Int(v, _) = const_lit.node
@ -1949,43 +1949,6 @@ pub fn in_automatically_derived(tcx: TyCtxt<'_>, id: HirId) -> bool {
})
}
/// Matches a function call with the given path and returns the arguments.
///
/// Usage:
///
/// ```rust,ignore
/// if let Some(args) = match_function_call(cx, cmp_max_call, &paths::CMP_MAX);
/// ```
/// This function is deprecated. Use [`match_function_call_with_def_id`].
pub fn match_function_call<'tcx>(
cx: &LateContext<'tcx>,
expr: &'tcx Expr<'_>,
path: &[&str],
) -> Option<&'tcx [Expr<'tcx>]> {
if let ExprKind::Call(fun, args) = expr.kind
&& let ExprKind::Path(ref qpath) = fun.kind
&& let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id()
&& match_def_path(cx, fun_def_id, path)
{
return Some(args);
};
None
}
pub fn match_function_call_with_def_id<'tcx>(
cx: &LateContext<'tcx>,
expr: &'tcx Expr<'_>,
fun_def_id: DefId,
) -> Option<&'tcx [Expr<'tcx>]> {
if let ExprKind::Call(fun, args) = expr.kind
&& let ExprKind::Path(ref qpath) = fun.kind
&& cx.qpath_res(qpath, fun.hir_id).opt_def_id() == Some(fun_def_id)
{
return Some(args);
};
None
}
/// Checks if the given `DefId` matches any of the paths. Returns the index of matching path, if
/// any.
///

View file

@ -2,7 +2,7 @@ use super::possible_origin::PossibleOriginVisitor;
use super::transitive_relation::TransitiveRelation;
use crate::ty::is_copy;
use rustc_data_structures::fx::FxHashMap;
use rustc_index::bit_set::{BitSet, HybridBitSet};
use rustc_index::bit_set::BitSet;
use rustc_lint::LateContext;
use rustc_middle::mir::visit::Visitor as _;
use rustc_middle::mir::{self, Mutability};
@ -21,14 +21,14 @@ struct PossibleBorrowerVisitor<'a, 'b, 'tcx> {
possible_borrower: TransitiveRelation,
body: &'b mir::Body<'tcx>,
cx: &'a LateContext<'tcx>,
possible_origin: FxHashMap<mir::Local, HybridBitSet<mir::Local>>,
possible_origin: FxHashMap<mir::Local, BitSet<mir::Local>>,
}
impl<'a, 'b, 'tcx> PossibleBorrowerVisitor<'a, 'b, 'tcx> {
fn new(
cx: &'a LateContext<'tcx>,
body: &'b mir::Body<'tcx>,
possible_origin: FxHashMap<mir::Local, HybridBitSet<mir::Local>>,
possible_origin: FxHashMap<mir::Local, BitSet<mir::Local>>,
) -> Self {
Self {
possible_borrower: TransitiveRelation::default(),
@ -119,7 +119,7 @@ impl<'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'_, '_, 'tcx> {
let mut mutable_variables: Vec<mir::Local> = mutable_borrowers
.iter()
.filter_map(|r| self.possible_origin.get(r))
.flat_map(HybridBitSet::iter)
.flat_map(BitSet::iter)
.collect();
if ContainsRegion.visit_ty(self.body.local_decls[*dest].ty).is_break() {
@ -171,7 +171,7 @@ fn rvalue_locals(rvalue: &mir::Rvalue<'_>, mut visit: impl FnMut(mir::Local)) {
#[allow(clippy::module_name_repetitions)]
pub struct PossibleBorrowerMap<'b, 'tcx> {
/// Mapping `Local -> its possible borrowers`
pub map: FxHashMap<mir::Local, HybridBitSet<mir::Local>>,
pub map: FxHashMap<mir::Local, BitSet<mir::Local>>,
maybe_live: ResultsCursor<'b, 'tcx, MaybeStorageLive<'tcx>>,
// Caches to avoid allocation of `BitSet` on every query
pub bitset: (BitSet<mir::Local>, BitSet<mir::Local>),

View file

@ -1,7 +1,7 @@
use super::transitive_relation::TransitiveRelation;
use crate::ty::is_copy;
use rustc_data_structures::fx::FxHashMap;
use rustc_index::bit_set::HybridBitSet;
use rustc_index::bit_set::BitSet;
use rustc_lint::LateContext;
use rustc_middle::mir;
@ -22,7 +22,7 @@ impl<'a, 'tcx> PossibleOriginVisitor<'a, 'tcx> {
}
}
pub fn into_map(self, cx: &LateContext<'tcx>) -> FxHashMap<mir::Local, HybridBitSet<mir::Local>> {
pub fn into_map(self, cx: &LateContext<'tcx>) -> FxHashMap<mir::Local, BitSet<mir::Local>> {
let mut map = FxHashMap::default();
for row in (1..self.body.local_decls.len()).map(mir::Local::from_usize) {
if is_copy(cx, self.body.local_decls[row].ty) {

View file

@ -1,5 +1,5 @@
use rustc_data_structures::fx::FxHashMap;
use rustc_index::bit_set::HybridBitSet;
use rustc_index::bit_set::BitSet;
use rustc_middle::mir;
#[derive(Default)]
@ -12,8 +12,8 @@ impl TransitiveRelation {
self.relations.entry(a).or_default().push(b);
}
pub fn reachable_from(&self, a: mir::Local, domain_size: usize) -> HybridBitSet<mir::Local> {
let mut seen = HybridBitSet::new_empty(domain_size);
pub fn reachable_from(&self, a: mir::Local, domain_size: usize) -> BitSet<mir::Local> {
let mut seen = BitSet::new_empty(domain_size);
let mut stack = vec![a];
while let Some(u) = stack.pop() {
if let Some(edges) = self.relations.get(&u) {

View file

@ -23,7 +23,6 @@ pub const LATE_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "LateLintPass"];
pub const LINT: [&str; 2] = ["rustc_lint_defs", "Lint"];
pub const SYMBOL: [&str; 3] = ["rustc_span", "symbol", "Symbol"];
pub const SYMBOL_AS_STR: [&str; 4] = ["rustc_span", "symbol", "Symbol", "as_str"];
pub const SYMBOL_INTERN: [&str; 4] = ["rustc_span", "symbol", "Symbol", "intern"];
pub const SYMBOL_TO_IDENT_STRING: [&str; 4] = ["rustc_span", "symbol", "Symbol", "to_ident_string"];
pub const SYM_MODULE: [&str; 3] = ["rustc_span", "symbol", "sym"];
pub const SYNTAX_CONTEXT: [&str; 3] = ["rustc_span", "hygiene", "SyntaxContext"];

View file

@ -151,7 +151,8 @@ impl<'a> Sugg<'a> {
| ExprKind::Become(..)
| ExprKind::Struct(..)
| ExprKind::Tup(..)
| ExprKind::Err(_) => Sugg::NonParen(get_snippet(expr.span)),
| ExprKind::Err(_)
| ExprKind::UnsafeBinderCast(..) => Sugg::NonParen(get_snippet(expr.span)),
ExprKind::DropTemps(inner) => Self::hir_from_snippet(inner, get_snippet),
ExprKind::Assign(lhs, rhs, _) => {
Sugg::BinOp(AssocOp::Assign, get_snippet(lhs.span), get_snippet(rhs.span))
@ -226,7 +227,8 @@ impl<'a> Sugg<'a> {
| ast::ExprKind::While(..)
| ast::ExprKind::Await(..)
| ast::ExprKind::Err(_)
| ast::ExprKind::Dummy => Sugg::NonParen(snippet(expr.span)),
| ast::ExprKind::Dummy
| ast::ExprKind::UnsafeBinderCast(..) => Sugg::NonParen(snippet(expr.span)),
ast::ExprKind::Range(ref lhs, ref rhs, RangeLimits::HalfOpen) => Sugg::BinOp(
AssocOp::DotDot,
lhs.as_ref().map_or("".into(), |lhs| snippet(lhs.span)),

View file

@ -38,7 +38,7 @@ pub use type_certainty::expr_type_is_certain;
/// Checks if the given type implements copy.
pub fn is_copy<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
ty.is_copy_modulo_regions(cx.tcx, cx.typing_env())
cx.type_is_copy_modulo_regions(ty)
}
/// This checks whether a given type is known to implement Debug.

View file

@ -7,7 +7,7 @@ use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::intravisit::{self, Visitor, walk_block, walk_expr};
use rustc_hir::{
AnonConst, Arm, Block, BlockCheckMode, Body, BodyId, Expr, ExprKind, HirId, ItemId, ItemKind, LetExpr, Pat, QPath,
Safety, Stmt, UnOp, UnsafeSource,
Safety, Stmt, StructTailExpr, UnOp, UnsafeSource,
};
use rustc_lint::LateContext;
use rustc_middle::hir::nested_filter;
@ -663,7 +663,7 @@ pub fn for_each_unconsumed_temporary<'tcx, B>(
for field in fields {
helper(typeck, true, field.expr, f)?;
}
if let Some(default) = default {
if let StructTailExpr::Base(default) = default {
helper(typeck, false, default, f)?;
}
},
@ -694,6 +694,7 @@ pub fn for_each_unconsumed_temporary<'tcx, B>(
| ExprKind::Continue(_)
| ExprKind::InlineAsm(_)
| ExprKind::OffsetOf(..)
| ExprKind::UnsafeBinderCast(..)
| ExprKind::Err(_) => (),
}
ControlFlow::Continue(())

View file

@ -1,6 +1,6 @@
[toolchain]
# begin autogenerated nightly
channel = "nightly-2024-11-28"
channel = "nightly-2024-12-15"
# end autogenerated nightly
components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
profile = "minimal"

View file

@ -236,7 +236,8 @@ pub fn main() {
let mut args: Vec<String> = orig_args.clone();
pass_sysroot_env_if_given(&mut args, sys_root_env);
return rustc_driver::RunCompiler::new(&args, &mut DefaultCallbacks).run();
rustc_driver::RunCompiler::new(&args, &mut DefaultCallbacks).run();
return Ok(());
}
if orig_args.iter().any(|a| a == "--version" || a == "-V") {
@ -296,12 +297,13 @@ pub fn main() {
args.extend(clippy_args);
rustc_driver::RunCompiler::new(&args, &mut ClippyCallbacks { clippy_args_var })
.set_using_internal_features(using_internal_features)
.run()
.run();
} else {
rustc_driver::RunCompiler::new(&args, &mut RustcCallbacks { clippy_args_var })
.set_using_internal_features(using_internal_features)
.run()
.run();
}
Ok(())
}))
}

View file

@ -20,7 +20,6 @@ LL | | fn clone_self(&self) -> Self {
LL | | Self {
LL | | a: true,
... |
LL | | }
LL | | }
| |_^
|
@ -32,7 +31,6 @@ LL | | fn default() -> Self {
LL | | Self {
LL | | a: true,
... |
LL | | }
LL | | }
| |_^

View file

@ -66,8 +66,7 @@ error: this block is too nested
LL | if true {
| _________________________^
LL | | if true {
LL | |
LL | | }
... |
LL | | }
| |_________________^
|

View file

@ -286,7 +286,6 @@ LL | | if unsafe { true } {
LL | | todo!();
LL | | } else {
... |
LL | | }
LL | | };
| |______^
|

View file

@ -294,7 +294,6 @@ LL | | if unsafe { true } {
LL | | todo!();
LL | | } else {
... |
LL | | }
LL | | };
| |______^
|

View file

@ -1,4 +1,3 @@
#![feature(async_closure)]
#![warn(clippy::async_yields_async)]
#![allow(clippy::redundant_async_block)]

View file

@ -1,4 +1,3 @@
#![feature(async_closure)]
#![warn(clippy::async_yields_async)]
#![allow(clippy::redundant_async_block)]

View file

@ -1,5 +1,5 @@
error: an async construct yields a type which is itself awaitable
--> tests/ui/async_yields_async.rs:38:9
--> tests/ui/async_yields_async.rs:37:9
|
LL | let _h = async {
| _____________________-
@ -20,7 +20,7 @@ LL + }.await
|
error: an async construct yields a type which is itself awaitable
--> tests/ui/async_yields_async.rs:43:9
--> tests/ui/async_yields_async.rs:42:9
|
LL | let _i = async {
| ____________________-
@ -33,7 +33,7 @@ LL | | };
| |_____- outer async construct
error: an async construct yields a type which is itself awaitable
--> tests/ui/async_yields_async.rs:49:9
--> tests/ui/async_yields_async.rs:48:9
|
LL | let _j = async || {
| ________________________-
@ -52,7 +52,7 @@ LL + }.await
|
error: an async construct yields a type which is itself awaitable
--> tests/ui/async_yields_async.rs:54:9
--> tests/ui/async_yields_async.rs:53:9
|
LL | let _k = async || {
| _______________________-
@ -65,7 +65,7 @@ LL | | };
| |_____- outer async construct
error: an async construct yields a type which is itself awaitable
--> tests/ui/async_yields_async.rs:56:23
--> tests/ui/async_yields_async.rs:55:23
|
LL | let _l = async || CustomFutureType;
| ^^^^^^^^^^^^^^^^
@ -75,12 +75,11 @@ LL | let _l = async || CustomFutureType;
| help: consider awaiting this value: `CustomFutureType.await`
error: an async construct yields a type which is itself awaitable
--> tests/ui/async_yields_async.rs:62:9
--> tests/ui/async_yields_async.rs:61:9
|
LL | let _m = async || {
| _______________________-
LL | | println!("I'm bored");
LL | | // Some more stuff
... |
LL | | CustomFutureType
| | ^^^^^^^^^^^^^^^^

View file

@ -2,7 +2,6 @@
#![allow(redundant_semicolons, clippy::no_effect)]
#![feature(stmt_expr_attributes)]
#![feature(async_closure)]
#[rustfmt::skip]
fn main() {

View file

@ -1,8 +1,7 @@
if let ExprKind::Repeat(value, length) = expr.kind
&& let ExprKind::Lit(ref lit) = value.kind
&& let LitKind::Int(1, LitIntType::Unsigned(UintTy::U8)) = lit.node
&& let ArrayLen::Body(const_arg) = length
&& let ConstArgKind::Anon(anon_const) = const_arg.kind
&& let ConstArgKind::Anon(anon_const) = length.kind
&& expr1 = &cx.tcx.hir().body(anon_const.body).value
&& let ExprKind::Lit(ref lit1) = expr1.kind
&& let LitKind::Int(5, LitIntType::Unsuffixed) = lit1.node

View file

@ -44,7 +44,6 @@ LL | | if {
LL | | if s == "43" {
LL | | return Some(43);
... |
LL | | }
LL | | });
| |______^
|

View file

@ -115,8 +115,7 @@ error: all if blocks contain the same code at the end
--> tests/ui/branches_sharing_code/shared_at_bottom.rs:183:5
|
LL | / x << 2
LL | |
LL | |
... |
LL | | };
| |_____^
|
@ -131,8 +130,7 @@ error: all if blocks contain the same code at the end
--> tests/ui/branches_sharing_code/shared_at_bottom.rs:192:5
|
LL | / x * 4
LL | |
LL | |
... |
LL | | }
| |_____^
|

View file

@ -43,9 +43,7 @@ LL | } else {
| ____________^
LL | | if y == "world" {
LL | | println!("world")
LL | | }
... |
LL | | }
LL | | }
| |_____^
|
@ -66,9 +64,7 @@ LL | } else {
| ____________^
LL | | if let Some(42) = Some(42) {
LL | | println!("world")
LL | | }
... |
LL | | }
LL | | }
| |_____^
|
@ -89,9 +85,7 @@ LL | } else {
| ____________^
LL | | if let Some(42) = Some(42) {
LL | | println!("world")
LL | | }
... |
LL | | }
LL | | }
| |_____^
|
@ -112,9 +106,7 @@ LL | } else {
| ____________^
LL | | if x == "hello" {
LL | | println!("world")
LL | | }
... |
LL | | }
LL | | }
| |_____^
|
@ -135,9 +127,7 @@ LL | } else {
| ____________^
LL | | if let Some(42) = Some(42) {
LL | | println!("world")
LL | | }
... |
LL | | }
LL | | }
| |_____^
|

View file

@ -6,7 +6,6 @@ LL | |
LL | |
LL | | type Item = u8;
... |
LL | | }
LL | | }
| |_^
|

View file

@ -2,11 +2,7 @@ error: this loop never actually loops
--> tests/ui/crashes/ice-360.rs:5:5
|
LL | / loop {
LL | |
LL | |
LL | |
... |
LL | |
LL | | }
| |_____^
|
@ -16,11 +12,7 @@ error: this loop could be written as a `while let` loop
--> tests/ui/crashes/ice-360.rs:5:5
|
LL | / loop {
LL | |
LL | |
LL | |
... |
LL | |
LL | | }
| |_____^ help: try: `while let Some(ele) = iter.next() { .. }`
|

View file

@ -2,8 +2,7 @@ error: this looks like you are trying to swap `a` and `b`
--> tests/ui/crate_level_checks/no_std_swap.rs:12:5
|
LL | / a = b;
LL | |
LL | |
... |
LL | | b = a;
| |_________^ help: try: `core::mem::swap(&mut a, &mut b)`
|

View file

@ -6,7 +6,6 @@ LL | | fn default() -> Self {
LL | | Self {
LL | | a: false,
... |
LL | | }
LL | | }
| |_^
|

View file

@ -99,8 +99,7 @@ LL | / /// for OldA
LL | | // struct OldA;
LL | |
LL | | /// Docs
LL | | /// for OldB
LL | | // struct OldB;
... |
LL | |
| |_^
...

View file

@ -103,8 +103,7 @@ error: empty lines after outer attribute
--> tests/ui/empty_line_after/outer_attribute.rs:64:1
|
LL | / #[allow(unused)]
LL | |
LL | | // This comment is isolated
... |
LL | |
| |_^
LL | pub fn isolated_comment() {}

View file

@ -16,8 +16,7 @@ LL | / if !m.contains_key(&k) {
LL | | if true {
LL | | m.insert(k, v);
LL | | } else {
LL | | m.insert(k, v2);
LL | | }
... |
LL | | }
| |_____^
|
@ -63,7 +62,6 @@ LL | | if true {
LL | | m.insert(k, v);
LL | | } else {
... |
LL | | }
LL | | }
| |_____^
|
@ -154,7 +152,6 @@ LL | | foo();
LL | | match 0 {
LL | | 0 if false => {
... |
LL | | }
LL | | }
| |_____^
|

View file

@ -13,7 +13,6 @@ error: all variants have the same prefix: `c`
LL | / enum Foo {
LL | |
LL | | cFoo,
LL | |
... |
LL | | cBaz,
LL | | }
@ -45,9 +44,7 @@ error: all variants have the same prefix: `Food`
LL | / enum Food {
LL | |
LL | | FoodGood,
LL | |
... |
LL | |
LL | | }
| |_^
|

View file

@ -29,7 +29,6 @@ LL | |
LL | | fn from(i: usize) -> Invalid {
LL | | if i != 42 {
... |
LL | | }
LL | | }
| |_^
|
@ -49,7 +48,6 @@ LL | |
LL | | fn from(s: Option<String>) -> Invalid {
LL | | let s = s.unwrap();
... |
LL | | }
LL | | }
| |_^
|
@ -76,7 +74,6 @@ LL | |
LL | | fn from(s: &'a mut <Box<u32> as ProjStrTrait>::ProjString) -> Invalid {
LL | | if s.parse::<u32>().ok().unwrap() != 42 {
... |
LL | | }
LL | | }
| |_^
|

View file

@ -1,23 +0,0 @@
use std::fmt::Debug;
use std::ptr;
use std::rc::Rc;
use std::sync::Arc;
fn a() {}
#[warn(clippy::fn_address_comparisons)]
fn main() {
type F = fn();
let f: F = a;
let g: F = f;
// These should fail:
let _ = f == a;
//~^ ERROR: comparing with a non-unique address of a function item
//~| NOTE: `-D clippy::fn-address-comparisons` implied by `-D warnings`
let _ = f != a;
//~^ ERROR: comparing with a non-unique address of a function item
// These should be fine:
let _ = f == g;
}

View file

@ -1,17 +0,0 @@
error: comparing with a non-unique address of a function item
--> tests/ui/fn_address_comparisons.rs:15:13
|
LL | let _ = f == a;
| ^^^^^^
|
= note: `-D clippy::fn-address-comparisons` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::fn_address_comparisons)]`
error: comparing with a non-unique address of a function item
--> tests/ui/fn_address_comparisons.rs:18:13
|
LL | let _ = f != a;
| ^^^^^^
error: aborting due to 2 previous errors

View file

@ -7,7 +7,6 @@ LL | | for _ in &[42] {
LL | | let foo: &Option<_> = &Some::<u8>(42);
LL | | if foo.is_some() {
... |
LL | | }
LL | | } else {
| |_____^
|
@ -20,7 +19,6 @@ LL | | for _ in &[42] {
LL | | let bar: &Option<_> = &Some::<u8>(42);
LL | | if bar.is_some() {
... |
LL | | }
LL | | }
| |_____^
= note: `-D clippy::if-same-then-else` implied by `-D warnings`

View file

@ -3,7 +3,6 @@
#![allow(clippy::never_loop)]
#![warn(clippy::infinite_loop)]
#![feature(async_closure)]
extern crate proc_macros;
use proc_macros::{external, with_span};

View file

@ -1,5 +1,5 @@
error: infinite loop detected
--> tests/ui/infinite_loops.rs:14:5
--> tests/ui/infinite_loops.rs:13:5
|
LL | / loop {
LL | |
@ -15,12 +15,11 @@ LL | fn no_break() -> ! {
| ++++
error: infinite loop detected
--> tests/ui/infinite_loops.rs:21:5
--> tests/ui/infinite_loops.rs:20:5
|
LL | / loop {
LL | |
LL | | loop {
LL | |
... |
LL | | do_something();
LL | | }
@ -32,14 +31,12 @@ LL | fn all_inf() -> ! {
| ++++
error: infinite loop detected
--> tests/ui/infinite_loops.rs:23:9
--> tests/ui/infinite_loops.rs:22:9
|
LL | / loop {
LL | |
LL | | loop {
LL | |
LL | | do_something();
LL | | }
... |
LL | | }
| |_________^
|
@ -49,7 +46,7 @@ LL | fn all_inf() -> ! {
| ++++
error: infinite loop detected
--> tests/ui/infinite_loops.rs:25:13
--> tests/ui/infinite_loops.rs:24:13
|
LL | / loop {
LL | |
@ -63,7 +60,7 @@ LL | fn all_inf() -> ! {
| ++++
error: infinite loop detected
--> tests/ui/infinite_loops.rs:39:5
--> tests/ui/infinite_loops.rs:38:5
|
LL | / loop {
LL | |
@ -74,13 +71,12 @@ LL | | }
= help: if this is not intended, try adding a `break` or `return` condition in the loop
error: infinite loop detected
--> tests/ui/infinite_loops.rs:52:5
--> tests/ui/infinite_loops.rs:51:5
|
LL | / loop {
LL | | fn inner_fn() -> ! {
LL | | std::process::exit(0);
LL | | }
LL | | do_something();
... |
LL | | }
| |_____^
|
@ -90,14 +86,13 @@ LL | fn no_break_never_ret_noise() -> ! {
| ++++
error: infinite loop detected
--> tests/ui/infinite_loops.rs:95:5
--> tests/ui/infinite_loops.rs:94:5
|
LL | / loop {
LL | |
LL | | loop {
LL | | if cond {
... |
LL | | }
LL | | }
| |_____^
|
@ -107,14 +102,13 @@ LL | fn break_inner_but_not_outer_1(cond: bool) -> ! {
| ++++
error: infinite loop detected
--> tests/ui/infinite_loops.rs:106:5
--> tests/ui/infinite_loops.rs:105:5
|
LL | / loop {
LL | |
LL | | 'inner: loop {
LL | | loop {
... |
LL | | }
LL | | }
| |_____^
|
@ -124,7 +118,7 @@ LL | fn break_inner_but_not_outer_2(cond: bool) -> ! {
| ++++
error: infinite loop detected
--> tests/ui/infinite_loops.rs:120:9
--> tests/ui/infinite_loops.rs:119:9
|
LL | / loop {
LL | |
@ -138,14 +132,13 @@ LL | fn break_outer_but_not_inner() -> ! {
| ++++
error: infinite loop detected
--> tests/ui/infinite_loops.rs:143:9
--> tests/ui/infinite_loops.rs:142:9
|
LL | / loop {
LL | |
LL | | 'inner: loop {
LL | | loop {
... |
LL | | }
LL | | }
| |_________^
|
@ -155,14 +148,13 @@ LL | fn break_wrong_loop(cond: bool) -> ! {
| ++++
error: infinite loop detected
--> tests/ui/infinite_loops.rs:183:5
--> tests/ui/infinite_loops.rs:182:5
|
LL | / loop {
LL | |
LL | | match opt {
LL | | Some(v) => {
... |
LL | | }
LL | | }
| |_____^
|
@ -172,7 +164,7 @@ LL | fn match_like() -> ! {
| ++++
error: infinite loop detected
--> tests/ui/infinite_loops.rs:224:5
--> tests/ui/infinite_loops.rs:223:5
|
LL | / loop {
LL | |
@ -186,7 +178,7 @@ LL | fn match_like() -> ! {
| ++++
error: infinite loop detected
--> tests/ui/infinite_loops.rs:229:5
--> tests/ui/infinite_loops.rs:228:5
|
LL | / loop {
LL | |
@ -203,7 +195,7 @@ LL | fn match_like() -> ! {
| ++++
error: infinite loop detected
--> tests/ui/infinite_loops.rs:334:9
--> tests/ui/infinite_loops.rs:333:9
|
LL | / loop {
LL | |
@ -217,7 +209,7 @@ LL | fn problematic_trait_method() -> ! {
| ++++
error: infinite loop detected
--> tests/ui/infinite_loops.rs:344:9
--> tests/ui/infinite_loops.rs:343:9
|
LL | / loop {
LL | |
@ -231,7 +223,7 @@ LL | fn could_be_problematic() -> ! {
| ++++
error: infinite loop detected
--> tests/ui/infinite_loops.rs:353:9
--> tests/ui/infinite_loops.rs:352:9
|
LL | / loop {
LL | |
@ -245,7 +237,7 @@ LL | let _loop_forever = || -> ! {
| ++++
error: infinite loop detected
--> tests/ui/infinite_loops.rs:367:8
--> tests/ui/infinite_loops.rs:366:8
|
LL | Ok(loop {
| ________^
@ -256,7 +248,7 @@ LL | | })
= help: if this is not intended, try adding a `break` or `return` condition in the loop
error: infinite loop detected
--> tests/ui/infinite_loops.rs:409:5
--> tests/ui/infinite_loops.rs:408:5
|
LL | / 'infinite: loop {
LL | |
@ -272,14 +264,13 @@ LL | fn continue_outer() -> ! {
| ++++
error: infinite loop detected
--> tests/ui/infinite_loops.rs:416:5
--> tests/ui/infinite_loops.rs:415:5
|
LL | / loop {
LL | |
LL | | 'inner: loop {
LL | | loop {
... |
LL | | }
LL | | }
| |_____^
|
@ -289,7 +280,7 @@ LL | fn continue_outer() -> ! {
| ++++
error: infinite loop detected
--> tests/ui/infinite_loops.rs:418:9
--> tests/ui/infinite_loops.rs:417:9
|
LL | / 'inner: loop {
LL | | loop {
@ -304,7 +295,7 @@ LL | fn continue_outer() -> ! {
| ++++
error: infinite loop detected
--> tests/ui/infinite_loops.rs:426:5
--> tests/ui/infinite_loops.rs:425:5
|
LL | / loop {
LL | |

View file

@ -6,7 +6,6 @@ LL | |
LL | | type IntoIter = std::slice::Iter<'a, u8>;
LL | | type Item = &'a u8;
... |
LL | | }
LL | | }
| |_^
|
@ -30,7 +29,6 @@ LL | |
LL | | type IntoIter = std::slice::IterMut<'a, u8>;
LL | | type Item = &'a mut u8;
... |
LL | | }
LL | | }
| |_^
|
@ -52,7 +50,6 @@ LL | |
LL | | type IntoIter = std::slice::Iter<'a, T>;
LL | | type Item = &'a T;
... |
LL | | }
LL | | }
| |_^
|
@ -74,7 +71,6 @@ LL | |
LL | | type IntoIter = std::slice::IterMut<'a, T>;
LL | | type Item = &'a mut T;
... |
LL | | }
LL | | }
| |_^
|
@ -96,7 +92,6 @@ LL | |
LL | | type IntoIter = std::slice::IterMut<'a, T>;
LL | | type Item = &'a mut T;
... |
LL | | }
LL | | }
| |_^
|
@ -117,8 +112,7 @@ LL | / impl<'a> IntoIterator for &'a Issue12037 {
LL | | type IntoIter = std::slice::Iter<'a, u8>;
LL | | type Item = &'a u8;
LL | | fn into_iter(self) -> Self::IntoIter {
LL | | todo!()
LL | | }
... |
LL | | }
| |_________^
...

View file

@ -6,7 +6,6 @@ LL | |
LL | |
LL | | if s == String::new() {
... |
LL | | }
LL | | None
| |________^ help: replace with an iterator: `strings.into_iter().find(|s| s == String::new())`
|
@ -22,7 +21,6 @@ LL | |
LL | |
LL | | if s == String::new() {
... |
LL | | }
LL | | None
| |________^ help: replace with an iterator: `arr.into_iter().map(|(s, _)| s).find(|s| s == String::new())`
|

View file

@ -4,8 +4,7 @@ error: manual implementation of `Iterator::find`
LL | / for &v in ARRAY {
LL | | if v == n {
LL | | return Some(v);
LL | | }
LL | | }
... |
LL | | None
| |________^ help: replace with an iterator: `ARRAY.iter().find(|&&v| v == n).copied()`
|
@ -18,8 +17,7 @@ error: manual implementation of `Iterator::find`
LL | / for (a, _) in arr {
LL | | if a % 2 == 0 {
LL | | return Some(a);
LL | | }
LL | | }
... |
LL | | None
| |________^ help: replace with an iterator: `arr.into_iter().map(|(a, _)| a).find(|&a| a % 2 == 0)`
@ -29,8 +27,7 @@ error: manual implementation of `Iterator::find`
LL | / for el in arr {
LL | | if el.name.len() == 10 {
LL | | return Some(el);
LL | | }
LL | | }
... |
LL | | None
| |________^ help: replace with an iterator: `arr.into_iter().find(|el| el.name.len() == 10)`
|
@ -42,8 +39,7 @@ error: manual implementation of `Iterator::find`
LL | / for Tuple(a, _) in arr {
LL | | if a >= 3 {
LL | | return Some(a);
LL | | }
LL | | }
... |
LL | | None
| |________^ help: replace with an iterator: `arr.into_iter().map(|Tuple(a, _)| a).find(|&a| a >= 3)`
@ -53,8 +49,7 @@ error: manual implementation of `Iterator::find`
LL | / for el in arr {
LL | | if el.should_keep() {
LL | | return Some(el);
LL | | }
LL | | }
... |
LL | | None
| |________^ help: replace with an iterator: `arr.into_iter().find(|el| el.should_keep())`
|
@ -66,8 +61,7 @@ error: manual implementation of `Iterator::find`
LL | / for el in arr {
LL | | if f(el) == 20 {
LL | | return Some(el);
LL | | }
LL | | }
... |
LL | | None
| |________^ help: replace with an iterator: `arr.into_iter().find(|&el| f(el) == 20)`
@ -77,8 +71,7 @@ error: manual implementation of `Iterator::find`
LL | / for &el in arr.values() {
LL | | if f(el) {
LL | | return Some(el);
LL | | }
LL | | }
... |
LL | | None
| |________^ help: replace with an iterator: `arr.values().find(|&&el| f(el)).copied()`
@ -88,8 +81,7 @@ error: manual implementation of `Iterator::find`
LL | / for el in arr {
LL | | if el.is_true {
LL | | return Some(el);
LL | | }
LL | | }
... |
LL | | None
| |________^ help: replace with an iterator: `arr.into_iter().find(|el| el.is_true)`
|
@ -101,8 +93,7 @@ error: manual implementation of `Iterator::find`
LL | / for (_, &x) in v {
LL | | if x > 10 {
LL | | return Some(x);
LL | | }
LL | | }
... |
LL | | None
| |________^ help: replace with an iterator: `v.into_iter().map(|(_, &x)| x).find(|&x| x > 10)`
@ -112,8 +103,7 @@ error: manual implementation of `Iterator::find`
LL | / for &(_, &x) in v {
LL | | if x > 10 {
LL | | return Some(x);
LL | | }
LL | | }
... |
LL | | None
| |________^ help: replace with an iterator: `v.iter().map(|&(_, &x)| x).find(|&x| x > 10)`
@ -123,8 +113,7 @@ error: manual implementation of `Iterator::find`
LL | / for x in arr {
LL | | if x >= 5 {
LL | | return Some(x);
LL | | }
LL | | }
... |
LL | | return None;
| |________________^ help: replace with an iterator: `arr.into_iter().find(|&x| x >= 5)`
@ -134,8 +123,7 @@ error: manual implementation of `Iterator::find`
LL | / for x in arr {
LL | | if x < 1 {
LL | | return Some(x);
LL | | }
LL | | }
... |
LL | | None
| |____________^ help: replace with an iterator: `arr.into_iter().find(|&x| x < 1)`

View file

@ -184,7 +184,6 @@ LL | |
LL | | Some(1),
LL | | Some(2),
... |
LL | | }
LL | | }
| |_____^
|

View file

@ -148,7 +148,6 @@ LL | |
LL | | v_some
LL | | } else {
... |
LL | | }
LL | | };
| |______^
|
@ -175,7 +174,6 @@ LL | |
LL | | v_some
LL | | } else {
... |
LL | | }
LL | | };
| |______^
|
@ -197,7 +195,6 @@ LL | |
LL | | v_some
LL | | } else {
... |
LL | | }
LL | | };
| |______^
|
@ -306,7 +303,6 @@ LL | |
LL | | v_some
LL | | } else {
... |
LL | | }
LL | | };
| |______^
|

View file

@ -36,7 +36,6 @@ LL | | Some(i) => i,
LL | | None => {
LL | | 42 + 42
... |
LL | | }
LL | | };
| |_____^
|
@ -130,7 +129,6 @@ LL | | Ok(i) => i,
LL | | Err(_) => {
LL | | 42 + 42
... |
LL | | }
LL | | };
| |_____^
|

View file

@ -77,9 +77,6 @@ error: called `map(..).flatten()` on `Option`
|
LL | .map(|_| {
| __________^
LL | | // we need some newlines
LL | | // so that the span is big enough
LL | | // for a split output of the diagnostic
... |
LL | | })
LL | | .flatten();

View file

@ -75,9 +75,6 @@ error: you seem to be trying to match on a boolean expression
--> tests/ui/match_bool.rs:36:5
|
LL | / match test && test {
LL | |
LL | |
LL | |
... |
LL | | _ => (),
LL | | };

View file

@ -68,8 +68,7 @@ LL | let _ans = match x {
| ____________________^
LL | | E::A(_) => {
LL | | true
LL | | }
LL | | E::B(_) => true,
... |
LL | | _ => false,
LL | | };
| |_________^ help: try: `matches!(x, E::A(_) | E::B(_))`

View file

@ -72,7 +72,6 @@ LL | | /// dox
LL | | pub fn documented() {}
LL | | pub fn undocumented1() {}
... |
LL | | }
LL | | }
| |_^

View file

@ -2,9 +2,7 @@ error: missing documentation for the crate
--> tests/ui/missing_doc_crate_missing.rs:1:1
|
LL | / #![warn(clippy::missing_docs_in_private_items)]
LL | |
LL | |
LL | |
... |
LL | | fn main() {}
| |____________^
|

View file

@ -6,7 +6,6 @@ LL | |
LL | | // unused field: hidden
LL | | fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
... |
LL | | }
LL | | }
| |_^
|
@ -28,7 +27,6 @@ LL | |
LL | | // unused fields: hidden, hidden2, hidden4
LL | | fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
... |
LL | | }
LL | | }
| |_^
|
@ -58,7 +56,6 @@ LL | |
LL | | fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
LL | | let mut f = formatter.debug_struct("MultiExprDebugImpl");
... |
LL | | }
LL | | }
| |_^
|

View file

@ -6,7 +6,6 @@ LL | |
LL | |
LL | | if *v == 10 {
... |
LL | | }
LL | | });
| |_______^
|

View file

@ -34,7 +34,6 @@ error: this `if` branch is empty
LL | / if {
LL | | if let true = true
LL | | && true
LL | | {
... |
LL | | } && true
LL | | {}

View file

@ -2,9 +2,6 @@ error: this loop never actually loops
--> tests/ui/never_loop.rs:12:5
|
LL | / loop {
LL | |
LL | |
LL | | // clippy::never_loop
... |
LL | | break;
LL | | }
@ -75,7 +72,6 @@ LL | |
LL | | // never loops
LL | | match x {
... |
LL | | }
LL | | }
| |_____^
|
@ -126,7 +122,6 @@ LL | |
LL | | 'b: {
LL | | break 'b 'c: {
... |
LL | | }
LL | | }
| |_____^

View file

@ -115,8 +115,7 @@ LL | let _ = if let Some(x) = arg {
| _____________^
LL | | x
LL | | } else {
LL | | // map_or_else must be suggested
LL | | side_effect()
... |
LL | | };
| |_____^ help: try: `arg.map_or_else(side_effect, |x| x)`

View file

@ -183,8 +183,7 @@ error: this block may be rewritten with the `?` operator
|
LL | / if a.is_none() {
LL | | return None;
LL | | // do lint here, the outer `try` is not relevant here
LL | | // https://github.com/rust-lang/rust-clippy/pull/11001#issuecomment-1610636867
... |
LL | | }
| |_____________^ help: replace it with: `a?;`

View file

@ -1,4 +1,3 @@
#![feature(async_closure)]
#![warn(clippy::redundant_closure_call)]
#![allow(clippy::redundant_async_block)]
#![allow(clippy::type_complexity)]

View file

@ -1,4 +1,3 @@
#![feature(async_closure)]
#![warn(clippy::redundant_closure_call)]
#![allow(clippy::redundant_async_block)]
#![allow(clippy::type_complexity)]

View file

@ -1,5 +1,5 @@
error: try not to call a closure in the expression where it is declared
--> tests/ui/redundant_closure_call_fixable.rs:16:13
--> tests/ui/redundant_closure_call_fixable.rs:15:13
|
LL | let a = (|| 42)();
| ^^^^^^^^^ help: try doing something like: `42`
@ -8,7 +8,7 @@ LL | let a = (|| 42)();
= help: to override `-D warnings` add `#[allow(clippy::redundant_closure_call)]`
error: try not to call a closure in the expression where it is declared
--> tests/ui/redundant_closure_call_fixable.rs:17:13
--> tests/ui/redundant_closure_call_fixable.rs:16:13
|
LL | let b = (async || {
| _____________^
@ -28,7 +28,7 @@ LL ~ };
|
error: try not to call a closure in the expression where it is declared
--> tests/ui/redundant_closure_call_fixable.rs:22:13
--> tests/ui/redundant_closure_call_fixable.rs:21:13
|
LL | let c = (|| {
| _____________^
@ -48,13 +48,13 @@ LL ~ };
|
error: try not to call a closure in the expression where it is declared
--> tests/ui/redundant_closure_call_fixable.rs:27:13
--> tests/ui/redundant_closure_call_fixable.rs:26:13
|
LL | let d = (async || something().await)();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `async { something().await }`
error: try not to call a closure in the expression where it is declared
--> tests/ui/redundant_closure_call_fixable.rs:36:13
--> tests/ui/redundant_closure_call_fixable.rs:35:13
|
LL | (|| m!())()
| ^^^^^^^^^^^ help: try doing something like: `m!()`
@ -65,7 +65,7 @@ LL | m2!();
= note: this error originates in the macro `m2` (in Nightly builds, run with -Z macro-backtrace for more info)
error: try not to call a closure in the expression where it is declared
--> tests/ui/redundant_closure_call_fixable.rs:31:13
--> tests/ui/redundant_closure_call_fixable.rs:30:13
|
LL | (|| 0)()
| ^^^^^^^^ help: try doing something like: `0`
@ -76,67 +76,67 @@ LL | m2!();
= note: this error originates in the macro `m` which comes from the expansion of the macro `m2` (in Nightly builds, run with -Z macro-backtrace for more info)
error: try not to call a closure in the expression where it is declared
--> tests/ui/redundant_closure_call_fixable.rs:44:16
--> tests/ui/redundant_closure_call_fixable.rs:43:16
|
LL | assert_eq!((|| || 43)()(), 42);
| ^^^^^^^^^^^^^^ help: try doing something like: `43`
error: try not to call a closure in the expression where it is declared
--> tests/ui/redundant_closure_call_fixable.rs:53:10
--> tests/ui/redundant_closure_call_fixable.rs:52:10
|
LL | dbg!((|| 42)());
| ^^^^^^^^^ help: try doing something like: `42`
error: try not to call a closure in the expression where it is declared
--> tests/ui/redundant_closure_call_fixable.rs:56:13
--> tests/ui/redundant_closure_call_fixable.rs:55:13
|
LL | let a = (|| || || 123)();
| ^^^^^^^^^^^^^^^^ help: try doing something like: `(|| || 123)`
error: try not to call a closure in the expression where it is declared
--> tests/ui/redundant_closure_call_fixable.rs:60:13
--> tests/ui/redundant_closure_call_fixable.rs:59:13
|
LL | let a = (|| || || || async || 1)()()()()();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `async { 1 }`
error: try not to call a closure in the expression where it is declared
--> tests/ui/redundant_closure_call_fixable.rs:69:13
--> tests/ui/redundant_closure_call_fixable.rs:68:13
|
LL | let a = (|| echo!(|| echo!(|| 1)))()()();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `1`
error: try not to call a closure in the expression where it is declared
--> tests/ui/redundant_closure_call_fixable.rs:71:13
--> tests/ui/redundant_closure_call_fixable.rs:70:13
|
LL | let a = (|| echo!((|| 123)))()();
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `123`
error: try not to call a closure in the expression where it is declared
--> tests/ui/redundant_closure_call_fixable.rs:84:11
--> tests/ui/redundant_closure_call_fixable.rs:83:11
|
LL | bar()((|| || 42)()(), 5);
| ^^^^^^^^^^^^^^ help: try doing something like: `42`
error: try not to call a closure in the expression where it is declared
--> tests/ui/redundant_closure_call_fixable.rs:85:9
--> tests/ui/redundant_closure_call_fixable.rs:84:9
|
LL | foo((|| || 42)()(), 5);
| ^^^^^^^^^^^^^^ help: try doing something like: `42`
error: try not to call a closure in the expression where it is declared
--> tests/ui/redundant_closure_call_fixable.rs:89:5
--> tests/ui/redundant_closure_call_fixable.rs:88:5
|
LL | (|| async {})().await;
| ^^^^^^^^^^^^^^^ help: try doing something like: `async {}`
error: try not to call a closure in the expression where it is declared
--> tests/ui/redundant_closure_call_fixable.rs:98:18
--> tests/ui/redundant_closure_call_fixable.rs:97:18
|
LL | spawn_on((|| async move {})());
| ^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `async move {}`
error: try not to call a closure in the expression where it is declared
--> tests/ui/redundant_closure_call_fixable.rs:103:28
--> tests/ui/redundant_closure_call_fixable.rs:102:28
|
LL | std::convert::identity((|| 13_i32 + 36_i32)()).leading_zeros();
| ^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `13_i32 + 36_i32`

Some files were not shown because too many files have changed in this diff Show more