Clean up after if chain removal

This commit is contained in:
Alex Macleod 2023-11-02 19:23:36 +00:00
parent 9681b4afe0
commit 13b4bb12ad
230 changed files with 1454 additions and 1847 deletions

View File

@ -14,7 +14,6 @@ cargo_metadata = "0.15.3"
clippy_config = { path = "../clippy_config" }
clippy_utils = { path = "../clippy_utils" }
declare_clippy_lint = { path = "../declare_clippy_lint" }
if_chain = "1.0"
itertools = "0.10.1"
quine-mc_cluskey = "0.2"
regex-syntax = "0.7"

View File

@ -5,7 +5,6 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sug
use clippy_utils::is_from_proc_macro;
use clippy_utils::macros::{is_panic, macro_backtrace};
use clippy_utils::source::{first_line_of_span, is_present_in_source, snippet_opt, without_block_comments};
use if_chain::if_chain;
use rustc_ast::token::{Token, TokenKind};
use rustc_ast::tokenstream::TokenTree;
use rustc_ast::{

View File

@ -4,7 +4,6 @@ use clippy_utils::ty::implements_trait;
use clippy_utils::visitors::{for_each_expr, Descend};
use clippy_utils::{get_parent_expr, higher};
use core::ops::ControlFlow;
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{BlockCheckMode, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};

View File

@ -2,7 +2,6 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
use clippy_utils::eq_expr_value;
use clippy_utils::source::snippet_opt;
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};

View File

@ -54,25 +54,25 @@ impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef {
&& !addrof_target.span.from_expansion()
&& let ExprKind::Unary(UnOp::Deref, deref_target) = addrof_target.kind
&& !deref_target.span.from_expansion()
&& !matches!(deref_target.kind, ExprKind::Unary(UnOp::Deref, ..) )
&& !matches!(deref_target.kind, ExprKind::Unary(UnOp::Deref, ..))
&& let ref_ty = cx.typeck_results().expr_ty(deref_target)
&& let ty::Ref(_, inner_ty, Mutability::Not) = ref_ty.kind()
&& !is_from_proc_macro(cx, e)
{
if let Some(parent_expr) = get_parent_expr(cx, e){
if matches!(parent_expr.kind, ExprKind::Unary(UnOp::Deref, ..)) &&
!is_lint_allowed(cx, DEREF_ADDROF, parent_expr.hir_id) {
if let Some(parent_expr) = get_parent_expr(cx, e) {
if matches!(parent_expr.kind, ExprKind::Unary(UnOp::Deref, ..))
&& !is_lint_allowed(cx, DEREF_ADDROF, parent_expr.hir_id)
{
return;
}
// modification to `&mut &*x` is different from `&mut x`
if matches!(deref_target.kind, ExprKind::Path(..)
| ExprKind::Field(..)
| ExprKind::Index(..)
| ExprKind::Unary(UnOp::Deref, ..))
&& matches!(parent_expr.kind, ExprKind::AddrOf(_, Mutability::Mut, _)) {
return;
if matches!(
deref_target.kind,
ExprKind::Path(..) | ExprKind::Field(..) | ExprKind::Index(..) | ExprKind::Unary(UnOp::Deref, ..)
) && matches!(parent_expr.kind, ExprKind::AddrOf(_, Mutability::Mut, _))
{
return;
}
}
@ -86,12 +86,12 @@ impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef {
e.span,
"if you would like to reborrow, try removing `&*`",
snippet_opt(cx, deref_target.span).unwrap(),
Applicability::MachineApplicable
Applicability::MachineApplicable,
);
// has deref trait -> give 2 help
// doesn't have deref trait -> give 1 help
if let Some(deref_trait_id) = cx.tcx.lang_items().deref_trait(){
if let Some(deref_trait_id) = cx.tcx.lang_items().deref_trait() {
if !implements_trait(cx, *inner_ty, deref_trait_id, &[]) {
return;
}
@ -100,16 +100,11 @@ impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef {
diag.span_suggestion(
e.span,
"if you would like to deref, try using `&**`",
format!(
"&**{}",
&snippet_opt(cx, deref_target.span).unwrap(),
),
Applicability::MaybeIncorrect
format!("&**{}", &snippet_opt(cx, deref_target.span).unwrap()),
Applicability::MaybeIncorrect,
);
}
},
);
}
}
}

View File

@ -2,7 +2,6 @@
use cargo_metadata::{DependencyKind, Metadata, Node, Package, PackageId};
use clippy_utils::diagnostics::span_lint;
use if_chain::if_chain;
use itertools::Itertools;
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_lint::LateContext;
@ -16,9 +15,13 @@ pub(super) fn check(cx: &LateContext<'_>, metadata: &Metadata) {
packages.sort_by(|a, b| a.name.cmp(&b.name));
if let Some(resolve) = &metadata.resolve
&& let Some(local_id) = packages
.iter()
.find_map(|p| if p.name == local_name.as_str() { Some(&p.id) } else { None })
&& let Some(local_id) = packages.iter().find_map(|p| {
if p.name == local_name.as_str() {
Some(&p.id)
} else {
None
}
})
{
for (name, group) in &packages.iter().group_by(|p| p.name.clone()) {
let group: Vec<&Package> = group.collect();

View File

@ -1,6 +1,5 @@
use cargo_metadata::Metadata;
use clippy_utils::diagnostics::span_lint;
use if_chain::if_chain;
use rustc_lint::LateContext;
use rustc_span::source_map::DUMMY_SP;

View File

@ -1,7 +1,6 @@
use clippy_utils::consts::{constant, Constant};
use clippy_utils::diagnostics::span_lint;
use clippy_utils::{method_chain_args, sext};
use if_chain::if_chain;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::LateContext;
use rustc_middle::ty::{self, Ty};

View File

@ -1,7 +1,6 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source;
use if_chain::if_chain;
use rustc_ast::Mutability;
use rustc_hir::{Expr, ExprKind, Node};
use rustc_lint::LateContext;

View File

@ -1,7 +1,6 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_context;
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::def_id::DefId;
use rustc_hir::{Expr, ExprKind};
@ -37,7 +36,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
{
let func = match rpk {
RawPartsKind::Immutable => "from_raw_parts",
RawPartsKind::Mutable => "from_raw_parts_mut"
RawPartsKind::Mutable => "from_raw_parts_mut",
};
let span = expr.span;
let mut applicability = Applicability::MachineApplicable;
@ -50,7 +49,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
&format!("casting the result of `{func}` to {cast_to}"),
"replace with",
format!("core::ptr::slice_{func}({ptr}, {len})"),
applicability
applicability,
);
}
}

View File

@ -1,6 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet_with_applicability;
use if_chain::if_chain;
use rustc_ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
@ -34,6 +33,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
applicability,
);
}
});
},
);
}
}

View File

@ -1,7 +1,6 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::sugg::Sugg;
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{Expr, Mutability};
use rustc_lint::LateContext;
@ -18,10 +17,18 @@ pub(super) fn check<'tcx>(
msrv: &Msrv,
) {
if msrv.meets(msrvs::POINTER_CAST_CONSTNESS)
&& let ty::RawPtr(TypeAndMut { mutbl: from_mutbl, ty: from_ty }) = cast_from.kind()
&& let ty::RawPtr(TypeAndMut { mutbl: to_mutbl, ty: to_ty }) = cast_to.kind()
&& matches!((from_mutbl, to_mutbl),
(Mutability::Not, Mutability::Mut) | (Mutability::Mut, Mutability::Not))
&& let ty::RawPtr(TypeAndMut {
mutbl: from_mutbl,
ty: from_ty,
}) = cast_from.kind()
&& let ty::RawPtr(TypeAndMut {
mutbl: to_mutbl,
ty: to_ty,
}) = cast_to.kind()
&& matches!(
(from_mutbl, to_mutbl),
(Mutability::Not, Mutability::Mut) | (Mutability::Mut, Mutability::Not)
)
&& from_ty == to_ty
{
let sugg = Sugg::hir(cx, cast_expr, "_");

View File

@ -3,7 +3,6 @@ use clippy_utils::numeric_literal::NumericLiteral;
use clippy_utils::source::snippet_opt;
use clippy_utils::visitors::{for_each_expr, Visitable};
use clippy_utils::{get_parent_expr, get_parent_node, is_hir_ty_cfg_dependant, is_ty_alias, path_to_local};
use if_chain::if_chain;
use rustc_ast::{LitFloatType, LitIntType, LitKind};
use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};
@ -52,7 +51,9 @@ pub(super) fn check<'tcx>(
cx,
UNNECESSARY_CAST,
expr.span,
&format!("casting raw pointers to the same type and constness is unnecessary (`{cast_from}` -> `{cast_to}`)"),
&format!(
"casting raw pointers to the same type and constness is unnecessary (`{cast_from}` -> `{cast_to}`)"
),
"try",
cast_str.clone(),
Applicability::MaybeIncorrect,
@ -87,8 +88,8 @@ pub(super) fn check<'tcx>(
if let ExprKind::Cast(_, cast_to) = expr.kind
&& let TyKind::Path(QPath::Resolved(_, path)) = &cast_to.kind
&& let Res::PrimTy(_) = path.res
{}
else {
{
} else {
return false;
}
@ -108,10 +109,13 @@ pub(super) fn check<'tcx>(
&& let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node)
&& let from_nbits = 128 - n.leading_zeros()
&& let to_nbits = fp_ty_mantissa_nbits(cast_to)
&& from_nbits != 0 && to_nbits != 0 && from_nbits <= to_nbits && num_lit.is_decimal()
&& from_nbits != 0
&& to_nbits != 0
&& from_nbits <= to_nbits
&& num_lit.is_decimal()
{
lint_unnecessary_cast(cx, expr, num_lit.integer, cast_from, cast_to);
return true
return true;
}
match lit.node {

View File

@ -4,7 +4,6 @@ use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{in_constant, is_integer_literal, SpanlessEq};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind, QPath, TyKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
@ -58,7 +57,6 @@ impl<'tcx> LateLintPass<'tcx> for CheckedConversions {
let result = if !in_constant(cx, item.hir_id)
&& !in_external_macro(cx.sess(), item.span)
&& let ExprKind::Binary(op, left, right) = &item.kind
{
match op.node {
BinOpKind::Ge | BinOpKind::Le => single_check(item),
@ -192,12 +190,11 @@ impl ConversionType {
/// Check for `expr <= (to_type::MAX as from_type)`
fn check_upper_bound<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<Conversion<'tcx>> {
if let ExprKind::Binary(ref op, left, right) = &expr.kind
&& let Some((candidate, check)) = normalize_le_ge(op, left, right)
&& let Some((from, to)) = get_types_from_cast(check, INTS, "max_value", "MAX")
{
Conversion::try_new(candidate, from, to)
} else {
&& let Some((candidate, check)) = normalize_le_ge(op, left, right)
&& let Some((from, to)) = get_types_from_cast(check, INTS, "max_value", "MAX")
{
Conversion::try_new(candidate, from, to)
} else {
None
}
}
@ -243,7 +240,6 @@ fn get_types_from_cast<'a>(
// to_type::max_value(), from_type
&& let TyKind::Path(ref from_type_path) = &from_type.kind
&& let Some(from_sym) = int_ty_to_sym(from_type_path)
{
Some((limit, from_sym))
} else {
@ -257,7 +253,6 @@ fn get_types_from_cast<'a>(
// `from_type::from`
&& let ExprKind::Path(ref path) = &from_func.kind
&& let Some(from_sym) = get_implementing_type(path, INTS, "from")
{
Some((limit, from_sym))
} else {

View File

@ -15,7 +15,6 @@
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
use clippy_utils::source::{snippet, snippet_block, snippet_block_with_applicability};
use clippy_utils::sugg::Sugg;
use if_chain::if_chain;
use rustc_ast::ast;
use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, EarlyLintPass};
@ -131,7 +130,11 @@ fn check_collapsible_maybe_if_let(cx: &EarlyContext<'_>, then_span: Span, else_:
// Prevent "elseif"
// Check that the "else" is followed by whitespace
let up_to_else = then_span.between(block.span);
let requires_space = if let Some(c) = snippet(cx, up_to_else, "..").chars().last() { !c.is_whitespace() } else { false };
let requires_space = if let Some(c) = snippet(cx, up_to_else, "..").chars().last() {
!c.is_whitespace()
} else {
false
};
let mut applicability = Applicability::MachineApplicable;
span_lint_and_sugg(
@ -160,21 +163,27 @@ fn check_collapsible_no_if_let(cx: &EarlyContext<'_>, expr: &ast::Expr, check: &
&& let ctxt = expr.span.ctxt()
&& inner.span.ctxt() == ctxt
{
span_lint_and_then(cx, COLLAPSIBLE_IF, expr.span, "this `if` statement can be collapsed", |diag| {
let mut app = Applicability::MachineApplicable;
let lhs = Sugg::ast(cx, check, "..", ctxt, &mut app);
let rhs = Sugg::ast(cx, check_inner, "..", ctxt, &mut app);
diag.span_suggestion(
expr.span,
"collapse nested if block",
format!(
"if {} {}",
lhs.and(&rhs),
snippet_block(cx, content.span, "..", Some(expr.span)),
),
app, // snippet
);
});
span_lint_and_then(
cx,
COLLAPSIBLE_IF,
expr.span,
"this `if` statement can be collapsed",
|diag| {
let mut app = Applicability::MachineApplicable;
let lhs = Sugg::ast(cx, check, "..", ctxt, &mut app);
let rhs = Sugg::ast(cx, check_inner, "..", ctxt, &mut app);
diag.span_suggestion(
expr.span,
"collapse nested if block",
format!(
"if {} {}",
lhs.and(&rhs),
snippet_block(cx, content.span, "..", Some(expr.span)),
),
app, // snippet
);
},
);
}
}

View File

@ -5,8 +5,6 @@ use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::sym;
use if_chain::if_chain;
declare_clippy_lint! {
/// ### What it does
/// Checks for types that implement `Copy` as well as
@ -39,9 +37,9 @@ declare_lint_pass!(CopyIterator => [COPY_ITERATOR]);
impl<'tcx> LateLintPass<'tcx> for CopyIterator {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
if let ItemKind::Impl(Impl {
of_trait: Some(ref trait_ref),
..
}) = item.kind
of_trait: Some(ref trait_ref),
..
}) = item.kind
&& let ty = cx.tcx.type_of(item.owner_id).instantiate_identity()
&& is_copy(cx, ty)
&& let Some(trait_id) = trait_ref.trait_def_id()

View File

@ -104,9 +104,19 @@ fn contains_unhygienic_crate_reference(tts: &TokenStream) -> Option<Span> {
}
fn is_crate_keyword(tt: &TokenTree) -> Option<Span> {
if let TokenTree::Token(Token { kind: TokenKind::Ident(symbol, _), span }, _) = tt
if let TokenTree::Token(
Token {
kind: TokenKind::Ident(symbol, _),
span,
},
_,
) = tt
&& symbol.as_str() == "crate"
{ Some(*span) } else { None }
{
Some(*span)
} else {
None
}
}
fn is_token(tt: &TokenTree, kind: &TokenKind) -> bool {

View File

@ -1,6 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet;
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
@ -46,7 +45,7 @@ impl LateLintPass<'_> for CreateDir {
"consider calling `std::fs::create_dir_all` instead",
format!("create_dir_all({})", snippet(cx, arg.span, "..")),
Applicability::MaybeIncorrect,
)
);
}
}
}

View File

@ -10,8 +10,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
#[cfg(feature = "internal")]
crate::utils::internal_lints::compiler_lint_functions::COMPILER_LINT_FUNCTIONS_INFO,
#[cfg(feature = "internal")]
crate::utils::internal_lints::if_chain_style::IF_CHAIN_STYLE_INFO,
#[cfg(feature = "internal")]
crate::utils::internal_lints::interning_defined_symbol::INTERNING_DEFINED_SYMBOL_INFO,
#[cfg(feature = "internal")]
crate::utils::internal_lints::interning_defined_symbol::UNNECESSARY_SYMBOL_STR_INFO,

View File

@ -2,7 +2,6 @@ use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_sugg};
use clippy_utils::source::snippet_with_context;
use clippy_utils::ty::{has_drop, is_copy};
use clippy_utils::{any_parent_is_automatically_derived, contains_name, get_parent_expr, is_from_proc_macro};
use if_chain::if_chain;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability;
use rustc_hir::def::Res;

View File

@ -79,7 +79,7 @@ impl LateLintPass<'_> for DefaultConstructedUnitStructs {
"remove this call to `default`",
String::new(),
Applicability::MachineApplicable,
)
);
};
}
}

View File

@ -1,7 +1,6 @@
use clippy_utils::diagnostics::span_lint_hir_and_then;
use clippy_utils::source::snippet_opt;
use clippy_utils::{get_parent_node, numeric_literal};
use if_chain::if_chain;
use rustc_ast::ast::{LitFloatType, LitIntType, LitKind};
use rustc_errors::Applicability;
use rustc_hir::intravisit::{walk_expr, walk_stmt, Visitor};
@ -83,38 +82,40 @@ impl<'a, 'tcx> NumericFallbackVisitor<'a, 'tcx> {
/// Check whether a passed literal has potential to cause fallback or not.
fn check_lit(&self, lit: &Lit, lit_ty: Ty<'tcx>, emit_hir_id: HirId) {
if !in_external_macro(self.cx.sess(), lit.span)
&& matches!(self.ty_bounds.last(), Some(ExplicitTyBound(false)))
&& matches!(lit.node,
LitKind::Int(_, LitIntType::Unsuffixed) | LitKind::Float(_, LitFloatType::Unsuffixed))
{
let (suffix, is_float) = match lit_ty.kind() {
ty::Int(IntTy::I32) => ("i32", false),
ty::Float(FloatTy::F64) => ("f64", true),
// Default numeric fallback never results in other types.
_ => return,
};
&& matches!(self.ty_bounds.last(), Some(ExplicitTyBound(false)))
&& matches!(
lit.node,
LitKind::Int(_, LitIntType::Unsuffixed) | LitKind::Float(_, LitFloatType::Unsuffixed)
)
{
let (suffix, is_float) = match lit_ty.kind() {
ty::Int(IntTy::I32) => ("i32", false),
ty::Float(FloatTy::F64) => ("f64", true),
// Default numeric fallback never results in other types.
_ => return,
};
let src = if let Some(src) = snippet_opt(self.cx, lit.span) {
src
} else {
match lit.node {
LitKind::Int(src, _) => format!("{src}"),
LitKind::Float(src, _) => format!("{src}"),
_ => return,
}
};
let sugg = numeric_literal::format(&src, Some(suffix), is_float);
span_lint_hir_and_then(
self.cx,
DEFAULT_NUMERIC_FALLBACK,
emit_hir_id,
lit.span,
"default numeric fallback might occur",
|diag| {
diag.span_suggestion(lit.span, "consider adding suffix", sugg, Applicability::MaybeIncorrect);
}
);
}
let src = if let Some(src) = snippet_opt(self.cx, lit.span) {
src
} else {
match lit.node {
LitKind::Int(src, _) => format!("{src}"),
LitKind::Float(src, _) => format!("{src}"),
_ => return,
}
};
let sugg = numeric_literal::format(&src, Some(suffix), is_float);
span_lint_hir_and_then(
self.cx,
DEFAULT_NUMERIC_FALLBACK,
emit_hir_id,
lit.span,
"default numeric fallback might occur",
|diag| {
diag.span_suggestion(lit.span, "consider adding suffix", sugg, Applicability::MaybeIncorrect);
},
);
}
}
}
@ -155,14 +156,13 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
// Push field type then visit each field expr.
for field in *fields {
let bound =
fields_def
.iter()
.find_map(|f_def| {
if f_def.ident(self.cx.tcx) == field.ident
{ Some(self.cx.tcx.type_of(f_def.did).instantiate_identity()) }
else { None }
});
let bound = fields_def.iter().find_map(|f_def| {
if f_def.ident(self.cx.tcx) == field.ident {
Some(self.cx.tcx.type_of(f_def.did).instantiate_identity())
} else {
None
}
});
self.ty_bounds.push(bound.into());
self.visit_expr(field.expr);
self.ty_bounds.pop();

View File

@ -154,55 +154,42 @@ fn check_enum<'tcx>(cx: &LateContext<'tcx>, item: &'tcx Item<'_>, func_expr: &Ex
&& let Some(variant_def) = adt_def.variants().iter().find(|v| v.def_id == variant_id)
&& variant_def.fields.is_empty()
&& !variant_def.is_field_list_non_exhaustive()
{
let enum_span = cx.tcx.def_span(adt_def.did());
let indent_enum = indent_of(cx, enum_span).unwrap_or(0);
let variant_span = cx.tcx.def_span(variant_def.def_id);
let indent_variant = indent_of(cx, variant_span).unwrap_or(0);
span_lint_and_then(
cx,
DERIVABLE_IMPLS,
item.span,
"this `impl` can be derived",
|diag| {
diag.span_suggestion_hidden(
item.span,
"remove the manual implementation...",
String::new(),
Applicability::MachineApplicable
);
diag.span_suggestion(
enum_span.shrink_to_lo(),
"...and instead derive it...",
format!(
"#[derive(Default)]\n{indent}",
indent = " ".repeat(indent_enum),
),
Applicability::MachineApplicable
);
diag.span_suggestion(
variant_span.shrink_to_lo(),
"...and mark the default variant",
format!(
"#[default]\n{indent}",
indent = " ".repeat(indent_variant),
),
Applicability::MachineApplicable
);
}
);
span_lint_and_then(cx, DERIVABLE_IMPLS, item.span, "this `impl` can be derived", |diag| {
diag.span_suggestion_hidden(
item.span,
"remove the manual implementation...",
String::new(),
Applicability::MachineApplicable,
);
diag.span_suggestion(
enum_span.shrink_to_lo(),
"...and instead derive it...",
format!("#[derive(Default)]\n{indent}", indent = " ".repeat(indent_enum),),
Applicability::MachineApplicable,
);
diag.span_suggestion(
variant_span.shrink_to_lo(),
"...and mark the default variant",
format!("#[default]\n{indent}", indent = " ".repeat(indent_variant),),
Applicability::MachineApplicable,
);
});
}
}
impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
if let ItemKind::Impl(Impl {
of_trait: Some(ref trait_ref),
items: [child],
self_ty,
..
}) = item.kind
of_trait: Some(ref trait_ref),
items: [child],
self_ty,
..
}) = item.kind
&& !cx.tcx.has_attr(item.owner_id, sym::automatically_derived)
&& !item.span.from_expansion()
&& let Some(def_id) = trait_ref.trait_def_id()
@ -215,7 +202,6 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
&& let attrs = cx.tcx.hir().attrs(item.hir_id())
&& !attrs.iter().any(|attr| attr.doc_str().is_some())
&& cx.tcx.hir().attrs(impl_item_hir).is_empty()
{
if adt_def.is_struct() {
check_struct(cx, item, self_ty, func_expr, adt_def, args, cx.tcx.typeck_body(*b));

View File

@ -1,7 +1,6 @@
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then};
use clippy_utils::ty::{implements_trait, implements_trait_with_env, is_copy};
use clippy_utils::{is_lint_allowed, match_def_path, paths};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::{walk_expr, walk_fn, walk_item, FnKind, Visitor};
@ -258,12 +257,9 @@ fn check_hash_peq<'tcx>(
|diag| {
if let Some(local_def_id) = impl_id.as_local() {
let hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_def_id);
diag.span_note(
cx.tcx.hir().span(hir_id),
"`PartialEq` implemented here"
);
diag.span_note(cx.tcx.hir().span(hir_id), "`PartialEq` implemented here");
}
}
},
);
}
});
@ -302,21 +298,12 @@ fn check_ord_partial_ord<'tcx>(
"you are deriving `Ord` but have implemented `PartialOrd` explicitly"
};
span_lint_and_then(
cx,
DERIVE_ORD_XOR_PARTIAL_ORD,
span,
mess,
|diag| {
if let Some(local_def_id) = impl_id.as_local() {
let hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_def_id);
diag.span_note(
cx.tcx.hir().span(hir_id),
"`PartialOrd` implemented here"
);
}
span_lint_and_then(cx, DERIVE_ORD_XOR_PARTIAL_ORD, span, mess, |diag| {
if let Some(local_def_id) = impl_id.as_local() {
let hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_def_id);
diag.span_note(cx.tcx.hir().span(hir_id), "`PartialOrd` implemented here");
}
);
});
}
});
}
@ -397,7 +384,9 @@ fn check_unsafe_derive_deserialize<'tcx>(
&& let Some(local_def_id) = def.did().as_local()
&& let adt_hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_def_id)
&& !is_lint_allowed(cx, UNSAFE_DERIVE_DESERIALIZE, adt_hir_id)
&& cx.tcx.inherent_impls(def.did())
&& cx
.tcx
.inherent_impls(def.did())
.iter()
.map(|imp_did| cx.tcx.hir().expect_item(imp_did.expect_local()))
.any(|imp| has_unsafe(cx, imp))
@ -408,7 +397,7 @@ fn check_unsafe_derive_deserialize<'tcx>(
item.span,
"you are deriving `serde::Deserialize` on a type that has methods using `unsafe`",
None,
"consider implementing `serde::Deserialize` manually. See https://serde.rs/impl-deserialize.html"
"consider implementing `serde::Deserialize` manually. See https://serde.rs/impl-deserialize.html",
);
}
}
@ -477,7 +466,7 @@ fn check_partial_eq_without_eq<'tcx>(cx: &LateContext<'tcx>, span: Span, trait_r
"consider deriving `Eq` as well",
"PartialEq, Eq".to_string(),
Applicability::MachineApplicable,
)
);
}
}

View File

@ -4,7 +4,6 @@ use clippy_utils::macros::{is_panic, root_macro_call_first_node};
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
use clippy_utils::{is_entrypoint_fn, method_chain_args, return_ty};
use if_chain::if_chain;
use pulldown_cmark::Event::{
Code, End, FootnoteReference, HardBreak, Html, Rule, SoftBreak, Start, TaskListMarker, Text,
};
@ -428,23 +427,21 @@ fn lint_for_missing_headers(
span,
"docs for function returning `Result` missing `# Errors` section",
);
} else {
if let Some(body_id) = body_id
&& let Some(future) = cx.tcx.lang_items().future_trait()
&& let typeck = cx.tcx.typeck_body(body_id)
&& let body = cx.tcx.hir().body(body_id)
&& let ret_ty = typeck.expr_ty(body.value)
&& implements_trait(cx, ret_ty, future, &[])
&& let ty::Coroutine(_, subs, _) = ret_ty.kind()
&& is_type_diagnostic_item(cx, subs.as_coroutine().return_ty(), sym::Result)
{
span_lint(
cx,
MISSING_ERRORS_DOC,
span,
"docs for function returning `Result` missing `# Errors` section",
);
}
} else if let Some(body_id) = body_id
&& let Some(future) = cx.tcx.lang_items().future_trait()
&& let typeck = cx.tcx.typeck_body(body_id)
&& let body = cx.tcx.hir().body(body_id)
&& let ret_ty = typeck.expr_ty(body.value)
&& implements_trait(cx, ret_ty, future, &[])
&& let ty::Coroutine(_, subs, _) = ret_ty.kind()
&& is_type_diagnostic_item(cx, subs.as_coroutine().return_ty(), sym::Result)
{
span_lint(
cx,
MISSING_ERRORS_DOC,
span,
"docs for function returning `Result` missing `# Errors` section",
);
}
}
}

View File

@ -1,6 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::peel_blocks;
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{Body, ExprKind, Impl, ImplItemKind, Item, ItemKind, Node};
use rustc_lint::{LateContext, LateLintPass};
@ -37,10 +36,10 @@ declare_lint_pass!(EmptyDrop => [EMPTY_DROP]);
impl LateLintPass<'_> for EmptyDrop {
fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
if let ItemKind::Impl(Impl {
of_trait: Some(ref trait_ref),
items: [child],
..
}) = item.kind
of_trait: Some(ref trait_ref),
items: [child],
..
}) = item.kind
&& trait_ref.trait_def_id() == cx.tcx.lang_items().drop_trait()
&& let impl_item_hir = child.id.hir_id()
&& let Some(Node::ImplItem(impl_item)) = cx.tcx.hir().find(impl_item_hir)
@ -48,7 +47,8 @@ impl LateLintPass<'_> for EmptyDrop {
&& let Body { value: func_expr, .. } = cx.tcx.hir().body(*b)
&& let func_expr = peel_blocks(func_expr)
&& let ExprKind::Block(block, _) = func_expr.kind
&& block.stmts.is_empty() && block.expr.is_none()
&& block.stmts.is_empty()
&& block.expr.is_none()
{
span_lint_and_sugg(
cx,
@ -57,7 +57,7 @@ impl LateLintPass<'_> for EmptyDrop {
"empty drop implementation",
"try removing this impl",
String::new(),
Applicability::MaybeIncorrect
Applicability::MaybeIncorrect,
);
}
}

View File

@ -1,6 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::indent_of;
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{Item, ItemKind};
use rustc_lint::{LateContext, LateLintPass};
@ -77,9 +76,7 @@ impl LateLintPass<'_> for ExhaustiveItems {
&& !attrs.iter().any(|a| a.has_name(sym::non_exhaustive))
{
let (lint, msg) = if let ItemKind::Struct(ref v, ..) = item.kind {
if v.fields().iter().any(|f| {
!cx.tcx.visibility(f.def_id).is_public()
}) {
if v.fields().iter().any(|f| !cx.tcx.visibility(f.def_id).is_public()) {
// skip structs with private fields
return;
}
@ -89,20 +86,15 @@ impl LateLintPass<'_> for ExhaustiveItems {
};
let suggestion_span = item.span.shrink_to_lo();
let indent = " ".repeat(indent_of(cx, item.span).unwrap_or(0));
span_lint_and_then(
cx,
lint,
item.span,
msg,
|diag| {
let sugg = format!("#[non_exhaustive]\n{indent}");
diag.span_suggestion(suggestion_span,
"try adding #[non_exhaustive]",
sugg,
Applicability::MaybeIncorrect);
}
);
span_lint_and_then(cx, lint, item.span, msg, |diag| {
let sugg = format!("#[non_exhaustive]\n{indent}");
diag.span_suggestion(
suggestion_span,
"try adding #[non_exhaustive]",
sugg,
Applicability::MaybeIncorrect,
);
});
}
}
}

View File

@ -1,6 +1,5 @@
use clippy_utils::diagnostics::span_lint;
use clippy_utils::is_entrypoint_fn;
use if_chain::if_chain;
use rustc_hir::{Expr, ExprKind, Item, ItemKind, Node};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};

View File

@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::macros::{find_format_args, format_args_inputs_span};
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{is_expn_of, path_def_id};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::def::Res;
use rustc_hir::{BindingAnnotation, Block, BlockCheckMode, Expr, ExprKind, Node, PatKind, QPath, Stmt, StmtKind};

View File

@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::macros::{is_panic, root_macro_call_first_node};
use clippy_utils::method_chain_args;
use clippy_utils::ty::is_type_diagnostic_item;
use if_chain::if_chain;
use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
@ -55,7 +54,9 @@ impl<'tcx> LateLintPass<'tcx> for FallibleImplFrom {
// check for `impl From<???> for ..`
if let hir::ItemKind::Impl(impl_) = &item.kind
&& let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id)
&& cx.tcx.is_diagnostic_item(sym::From, impl_trait_ref.skip_binder().def_id)
&& cx
.tcx
.is_diagnostic_item(sym::From, impl_trait_ref.skip_binder().def_id)
{
lint_impl_body(cx, item.span, impl_.items);
}
@ -97,8 +98,7 @@ fn lint_impl_body(cx: &LateContext<'_>, impl_span: Span, impl_items: &[hir::Impl
for impl_item in impl_items {
if impl_item.ident.name == sym::from
&& let ImplItemKind::Fn(_, body_id) =
cx.tcx.hir().impl_item(impl_item.id).kind
&& let ImplItemKind::Fn(_, body_id) = cx.tcx.hir().impl_item(impl_item.id).kind
{
// check the body for `begin_panic` or `unwrap`
let body = cx.tcx.hir().body(body_id);
@ -119,9 +119,11 @@ fn lint_impl_body(cx: &LateContext<'_>, impl_span: Span, impl_items: &[hir::Impl
move |diag| {
diag.help(
"`From` is intended for infallible conversions only. \
Use `TryFrom` if there's a possibility for the conversion to fail");
Use `TryFrom` if there's a possibility for the conversion to fail",
);
diag.span_note(fpu.result, "potential failure(s)");
});
},
);
}
}
}

View File

@ -1,6 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::numeric_literal;
use if_chain::if_chain;
use rustc_ast::ast::{self, LitFloatType, LitKind};
use rustc_errors::Applicability;
use rustc_hir as hir;
@ -79,7 +78,7 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral {
let type_suffix = match lit_float_ty {
LitFloatType::Suffixed(ast::FloatTy::F32) => Some("f32"),
LitFloatType::Suffixed(ast::FloatTy::F64) => Some("f64"),
LitFloatType::Unsuffixed => None
LitFloatType::Unsuffixed => None,
};
let (is_whole, is_inf, mut float_str) = match fty {
FloatTy::F32 => {
@ -90,7 +89,6 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral {
FloatTy::F64 => {
let value = sym_str.parse::<f64>().unwrap();
(value.fract() == 0.0, value.is_infinite(), formatter.format(value))
},
};

View File

@ -4,7 +4,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::{
eq_expr_value, get_parent_expr, higher, in_constant, is_no_std_crate, numeric_literal, peel_blocks, sugg,
};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment, UnOp};
use rustc_lint::{LateContext, LateLintPass};
@ -143,17 +142,14 @@ fn prepare_receiver_sugg<'a>(cx: &LateContext<'_>, mut expr: &'a Expr<'a>) -> Su
"{suggestion}{}{}",
// Check for float literals without numbers following the decimal
// separator such as `2.` and adds a trailing zero
if sym.as_str().ends_with('.') {
"0"
} else {
""
},
if sym.as_str().ends_with('.') { "0" } else { "" },
float_ty.name_str()
).into();
)
.into();
suggestion = match suggestion {
Sugg::MaybeParen(_) => Sugg::MaybeParen(op),
_ => Sugg::NonParen(op)
_ => Sugg::NonParen(op),
};
}
@ -357,31 +353,59 @@ fn detect_hypot(cx: &LateContext<'_>, receiver: &Expr<'_>) -> Option<String> {
) = receiver.kind
{
// check if expression of the form x * x + y * y
if let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, lmul_lhs, lmul_rhs) = add_lhs.kind
&& let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, rmul_lhs, rmul_rhs) = add_rhs.kind
if let ExprKind::Binary(
Spanned {
node: BinOpKind::Mul, ..
},
lmul_lhs,
lmul_rhs,
) = add_lhs.kind
&& let ExprKind::Binary(
Spanned {
node: BinOpKind::Mul, ..
},
rmul_lhs,
rmul_rhs,
) = add_rhs.kind
&& eq_expr_value(cx, lmul_lhs, lmul_rhs)
&& eq_expr_value(cx, rmul_lhs, rmul_rhs)
{
return Some(format!("{}.hypot({})", Sugg::hir(cx, lmul_lhs, "..").maybe_par(), Sugg::hir(cx, rmul_lhs, "..")));
return Some(format!(
"{}.hypot({})",
Sugg::hir(cx, lmul_lhs, "..").maybe_par(),
Sugg::hir(cx, rmul_lhs, "..")
));
}
// check if expression of the form x.powi(2) + y.powi(2)
if let ExprKind::MethodCall(
PathSegment { ident: lmethod_name, .. },
largs_0, [largs_1, ..],
_
) = &add_lhs.kind
PathSegment {
ident: lmethod_name, ..
},
largs_0,
[largs_1, ..],
_,
) = &add_lhs.kind
&& let ExprKind::MethodCall(
PathSegment { ident: rmethod_name, .. },
rargs_0, [rargs_1, ..],
_
PathSegment {
ident: rmethod_name, ..
},
rargs_0,
[rargs_1, ..],
_,
) = &add_rhs.kind
&& lmethod_name.as_str() == "powi" && rmethod_name.as_str() == "powi"
&& lmethod_name.as_str() == "powi"
&& rmethod_name.as_str() == "powi"
&& let Some(lvalue) = constant(cx, cx.typeck_results(), largs_1)
&& let Some(rvalue) = constant(cx, cx.typeck_results(), rargs_1)
&& Int(2) == lvalue && Int(2) == rvalue
&& Int(2) == lvalue
&& Int(2) == rvalue
{
return Some(format!("{}.hypot({})", Sugg::hir(cx, largs_0, "..").maybe_par(), Sugg::hir(cx, rargs_0, "..")));
return Some(format!(
"{}.hypot({})",
Sugg::hir(cx, largs_0, "..").maybe_par(),
Sugg::hir(cx, rargs_0, "..")
));
}
}
@ -405,7 +429,13 @@ fn check_hypot(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>) {
// TODO: Lint expressions of the form `x.exp() - y` where y > 1
// and suggest usage of `x.exp_m1() - (y - 1)` instead
fn check_expm1(cx: &LateContext<'_>, expr: &Expr<'_>) {
if let ExprKind::Binary(Spanned { node: BinOpKind::Sub, .. }, lhs, rhs) = expr.kind
if let ExprKind::Binary(
Spanned {
node: BinOpKind::Sub, ..
},
lhs,
rhs,
) = expr.kind
&& cx.typeck_results().expr_ty(lhs).is_floating_point()
&& let Some(value) = constant(cx, cx.typeck_results(), rhs)
&& (F32(1.0) == value || F64(1.0) == value)
@ -419,17 +449,20 @@ fn check_expm1(cx: &LateContext<'_>, expr: &Expr<'_>) {
expr.span,
"(e.pow(x) - 1) can be computed more accurately",
"consider using",
format!(
"{}.exp_m1()",
Sugg::hir(cx, self_arg, "..").maybe_par()
),
format!("{}.exp_m1()", Sugg::hir(cx, self_arg, "..").maybe_par()),
Applicability::MachineApplicable,
);
}
}
fn is_float_mul_expr<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(&'a Expr<'a>, &'a Expr<'a>)> {
if let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, lhs, rhs) = &expr.kind
if let ExprKind::Binary(
Spanned {
node: BinOpKind::Mul, ..
},
lhs,
rhs,
) = &expr.kind
&& cx.typeck_results().expr_ty(lhs).is_floating_point()
&& cx.typeck_results().expr_ty(rhs).is_floating_point()
{
@ -543,7 +576,11 @@ fn are_negated<'a>(cx: &LateContext<'_>, expr1: &'a Expr<'a>, expr2: &'a Expr<'a
}
fn check_custom_abs(cx: &LateContext<'_>, expr: &Expr<'_>) {
if let Some(higher::If { cond, then, r#else: Some(r#else) }) = higher::If::hir(expr)
if let Some(higher::If {
cond,
then,
r#else: Some(r#else),
}) = higher::If::hir(expr)
&& let if_body_expr = peel_blocks(then)
&& let else_body_expr = peel_blocks(r#else)
&& let Some((if_expr_positive, body)) = are_negated(cx, if_body_expr, else_body_expr)
@ -584,15 +621,27 @@ fn check_custom_abs(cx: &LateContext<'_>, expr: &Expr<'_>) {
}
fn are_same_base_logs(cx: &LateContext<'_>, expr_a: &Expr<'_>, expr_b: &Expr<'_>) -> bool {
if let ExprKind::MethodCall(PathSegment { ident: method_name_a, .. }, _, args_a, _) = expr_a.kind
&& let ExprKind::MethodCall(PathSegment { ident: method_name_b, .. }, _, args_b, _) = expr_b.kind
if let ExprKind::MethodCall(
PathSegment {
ident: method_name_a, ..
},
_,
args_a,
_,
) = expr_a.kind
&& let ExprKind::MethodCall(
PathSegment {
ident: method_name_b, ..
},
_,
args_b,
_,
) = expr_b.kind
{
return method_name_a.as_str() == method_name_b.as_str() &&
args_a.len() == args_b.len() &&
(
["ln", "log2", "log10"].contains(&method_name_a.as_str()) ||
method_name_a.as_str() == "log" && args_a.len() == 1 && eq_expr_value(cx, &args_a[0], &args_b[0])
);
return method_name_a.as_str() == method_name_b.as_str()
&& args_a.len() == args_b.len()
&& (["ln", "log2", "log10"].contains(&method_name_a.as_str())
|| method_name_a.as_str() == "log" && args_a.len() == 1 && eq_expr_value(cx, &args_a[0], &args_b[0]));
}
false
@ -601,12 +650,12 @@ fn are_same_base_logs(cx: &LateContext<'_>, expr_a: &Expr<'_>, expr_b: &Expr<'_>
fn check_log_division(cx: &LateContext<'_>, expr: &Expr<'_>) {
// check if expression of the form x.logN() / y.logN()
if let ExprKind::Binary(
Spanned {
node: BinOpKind::Div, ..
},
lhs,
rhs,
) = &expr.kind
Spanned {
node: BinOpKind::Div, ..
},
lhs,
rhs,
) = &expr.kind
&& are_same_base_logs(cx, lhs, rhs)
&& let ExprKind::MethodCall(_, largs_self, ..) = &lhs.kind
&& let ExprKind::MethodCall(_, rargs_self, ..) = &rhs.kind
@ -617,7 +666,11 @@ fn check_log_division(cx: &LateContext<'_>, expr: &Expr<'_>) {
expr.span,
"log base can be expressed more clearly",
"consider using",
format!("{}.log({})", Sugg::hir(cx, largs_self, "..").maybe_par(), Sugg::hir(cx, rargs_self, ".."),),
format!(
"{}.log({})",
Sugg::hir(cx, largs_self, "..").maybe_par(),
Sugg::hir(cx, rargs_self, ".."),
),
Applicability::MachineApplicable,
);
}
@ -625,12 +678,12 @@ fn check_log_division(cx: &LateContext<'_>, expr: &Expr<'_>) {
fn check_radians(cx: &LateContext<'_>, expr: &Expr<'_>) {
if let ExprKind::Binary(
Spanned {
node: BinOpKind::Div, ..
},
div_lhs,
div_rhs,
) = &expr.kind
Spanned {
node: BinOpKind::Div, ..
},
div_lhs,
div_rhs,
) = &expr.kind
&& let ExprKind::Binary(
Spanned {
node: BinOpKind::Mul, ..
@ -642,8 +695,8 @@ fn check_radians(cx: &LateContext<'_>, expr: &Expr<'_>) {
&& let Some(lvalue) = constant(cx, cx.typeck_results(), mul_rhs)
{
// TODO: also check for constant values near PI/180 or 180/PI
if (F32(f32_consts::PI) == rvalue || F64(f64_consts::PI) == rvalue) &&
(F32(180_f32) == lvalue || F64(180_f64) == lvalue)
if (F32(f32_consts::PI) == rvalue || F64(f64_consts::PI) == rvalue)
&& (F32(180_f32) == lvalue || F64(180_f64) == lvalue)
{
let mut proposal = format!("{}.to_degrees()", Sugg::hir(cx, mul_lhs, "..").maybe_par());
if let ExprKind::Lit(literal) = mul_lhs.kind
@ -665,9 +718,8 @@ fn check_radians(cx: &LateContext<'_>, expr: &Expr<'_>) {
proposal,
Applicability::MachineApplicable,
);
} else if
(F32(180_f32) == rvalue || F64(180_f64) == rvalue) &&
(F32(f32_consts::PI) == lvalue || F64(f64_consts::PI) == lvalue)
} else if (F32(180_f32) == rvalue || F64(180_f64) == rvalue)
&& (F32(f32_consts::PI) == lvalue || F64(f64_consts::PI) == lvalue)
{
let mut proposal = format!("{}.to_radians()", Sugg::hir(cx, mul_lhs, "..").maybe_par());
if let ExprKind::Lit(literal) = mul_lhs.kind

View File

@ -8,7 +8,6 @@ use clippy_utils::macros::{
};
use clippy_utils::source::snippet_opt;
use clippy_utils::ty::{implements_trait, is_type_lang_item};
use if_chain::if_chain;
use itertools::Itertools;
use rustc_ast::{
FormatArgPosition, FormatArgPositionKind, FormatArgsPiece, FormatArgumentKind, FormatCount, FormatOptions,
@ -422,9 +421,7 @@ fn check_to_string_in_format_args(cx: &LateContext<'_>, name: Symbol, value: &Ex
cx,
TO_STRING_IN_FORMAT_ARGS,
to_string_span.with_lo(receiver.span.hi()),
&format!(
"`to_string` applied to a type that implements `Display` in `{name}!` args"
),
&format!("`to_string` applied to a type that implements `Display` in `{name}!` args"),
"remove this",
String::new(),
Applicability::MachineApplicable,
@ -434,9 +431,7 @@ fn check_to_string_in_format_args(cx: &LateContext<'_>, name: Symbol, value: &Ex
cx,
TO_STRING_IN_FORMAT_ARGS,
value.span,
&format!(
"`to_string` applied to a type that implements `Display` in `{name}!` args"
),
&format!("`to_string` applied to a type that implements `Display` in `{name}!` args"),
"use this",
format!(
"{}{:*>n_needed_derefs$}{receiver_snippet}",

View File

@ -1,7 +1,6 @@
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
use clippy_utils::macros::{find_format_arg_expr, find_format_args, is_format_macro, root_macro_call_first_node};
use clippy_utils::{get_parent_as_impl, is_diag_trait_item, path_to_local, peel_ref_operators};
use if_chain::if_chain;
use rustc_ast::{FormatArgsPiece, FormatTrait};
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, Impl, ImplItem, ImplItemKind, QPath};
@ -243,20 +242,22 @@ fn check_print_in_format_impl(cx: &LateContext<'_>, expr: &Expr<'_>, impl_trait:
fn is_format_trait_impl(cx: &LateContext<'_>, impl_item: &ImplItem<'_>) -> Option<FormatTraitNames> {
if impl_item.ident.name == sym::fmt
&& let ImplItemKind::Fn(_, body_id) = impl_item.kind
&& let Some(Impl { of_trait: Some(trait_ref),..}) = get_parent_as_impl(cx.tcx, impl_item.hir_id())
&& let Some(Impl {
of_trait: Some(trait_ref),
..
}) = get_parent_as_impl(cx.tcx, impl_item.hir_id())
&& let Some(did) = trait_ref.trait_def_id()
&& let Some(name) = cx.tcx.get_diagnostic_name(did)
&& matches!(name, sym::Debug | sym::Display)
{
let body = cx.tcx.hir().body(body_id);
let formatter_name = body.params.get(1)
let formatter_name = body
.params
.get(1)
.and_then(|param| param.pat.simple_ident())
.map(|ident| ident.name);
Some(FormatTraitNames {
name,
formatter_name,
})
Some(FormatTraitNames { name, formatter_name })
} else {
None
}

View File

@ -1,7 +1,6 @@
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_note};
use clippy_utils::is_span_if;
use clippy_utils::source::snippet_opt;
use if_chain::if_chain;
use rustc_ast::ast::{BinOpKind, Block, Expr, ExprKind, StmtKind, UnOp};
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
@ -193,9 +192,7 @@ fn check_unop(cx: &EarlyContext<'_>, expr: &Expr) {
`{binop_str}{unop_str}` is a single operator"
),
None,
&format!(
"put a space between `{binop_str}` and `{unop_str}` and remove the space after `{unop_str}`"
),
&format!("put a space between `{binop_str}` and `{unop_str}` and remove the space after `{unop_str}`"),
);
}
}
@ -219,7 +216,6 @@ fn check_else(cx: &EarlyContext<'_>, expr: &Expr) {
&& let Some(else_snippet) = snippet_opt(cx, else_span)
&& let Some((pre_else, post_else)) = else_snippet.split_once("else")
&& let Some((_, post_else_post_eol)) = post_else.split_once('\n')
{
// Allow allman style braces `} \n else \n {`
if is_block(else_)
@ -234,7 +230,7 @@ fn check_else(cx: &EarlyContext<'_>, expr: &Expr) {
// Don't warn if the only thing inside post_else_post_eol is a comment block.
let trimmed_post_else_post_eol = post_else_post_eol.trim();
if trimmed_post_else_post_eol.starts_with("/*") && trimmed_post_else_post_eol.ends_with("*/") {
return
return;
}
let else_desc = if is_if(else_) { "if" } else { "{..}" };
@ -267,7 +263,8 @@ fn check_array(cx: &EarlyContext<'_>, expr: &Expr) {
if let ExprKind::Array(ref array) = expr.kind {
for element in array {
if let ExprKind::Binary(ref op, ref lhs, _) = element.kind
&& has_unary_equivalent(op.node) && lhs.span.eq_ctxt(op.span)
&& has_unary_equivalent(op.node)
&& lhs.span.eq_ctxt(op.span)
&& let space_span = lhs.span.between(op.span)
&& let Some(space_snippet) = snippet_opt(cx, space_span)
&& let lint_span = lhs.span.with_lo(lhs.span.hi())
@ -313,9 +310,7 @@ fn check_missing_else(cx: &EarlyContext<'_>, first: &Expr, second: &Expr) {
else_span,
&format!("this looks like {looks_like} but the `else` is missing"),
None,
&format!(
"to remove this lint, add the missing `else` or add a new line before {next_thing}",
),
&format!("to remove this lint, add the missing `else` or add a new line before {next_thing}",),
);
}
}

View File

@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::is_integer_literal;
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{def, Expr, ExprKind, LangItem, PrimTy, QPath, TyKind};
use rustc_lint::{LateContext, LateLintPass};
@ -61,25 +60,16 @@ impl<'tcx> LateLintPass<'tcx> for FromStrRadix10 {
// check if the second argument is a primitive `10`
&& is_integer_literal(radix, 10)
{
let expr = if let ExprKind::AddrOf(_, _, expr) = &src.kind {
let ty = cx.typeck_results().expr_ty(expr);
if is_ty_stringish(cx, ty) {
expr
} else {
&src
}
if is_ty_stringish(cx, ty) { expr } else { &src }
} else {
&src
};
let sugg = Sugg::hir_with_applicability(
cx,
expr,
"<string>",
&mut Applicability::MachineApplicable
).maybe_par();
let sugg =
Sugg::hir_with_applicability(cx, expr, "<string>", &mut Applicability::MachineApplicable).maybe_par();
span_lint_and_sugg(
cx,
@ -88,7 +78,7 @@ impl<'tcx> LateLintPass<'tcx> for FromStrRadix10 {
"this call to `from_str_radix` can be replaced with a call to `str::parse`",
"try",
format!("{sugg}.parse::<{}>()", prim_ty.name_str()),
Applicability::MaybeIncorrect
Applicability::MaybeIncorrect,
);
}
}

View File

@ -43,7 +43,7 @@ pub fn check_fn(cx: &LateContext<'_>, kind: FnKind<'_>, decl: &FnDecl<'_>, body:
// Body must be &(mut) <self_data>.name
// self_data is not necessarily self, to also lint sub-getters, etc…
let block_expr = if let ExprKind::Block(block,_) = body.value.kind
let block_expr = if let ExprKind::Block(block, _) = body.value.kind
&& block.stmts.is_empty()
&& let Some(block_expr) = block.expr
{

View File

@ -87,11 +87,12 @@ fn check_result_unit_err(cx: &LateContext<'_>, err_ty: Ty<'_>, fn_header_span: S
fn check_result_large_err<'tcx>(cx: &LateContext<'tcx>, err_ty: Ty<'tcx>, hir_ty_span: Span, large_err_threshold: u64) {
if let Adt(adt, subst) = err_ty.kind()
&& let Some(local_def_id) = err_ty.ty_adt_def().expect("already checked this is adt").did().as_local()
&& let Some(hir::Node::Item(item)) = cx
.tcx
.hir()
.find_by_def_id(local_def_id)
&& let Some(local_def_id) = err_ty
.ty_adt_def()
.expect("already checked this is adt")
.did()
.as_local()
&& let Some(hir::Node::Item(item)) = cx.tcx.hir().find_by_def_id(local_def_id)
&& let hir::ItemKind::Enum(ref def, _) = item.kind
{
let variants_size = AdtVariantInfo::new(cx, *adt, subst);
@ -114,17 +115,19 @@ fn check_result_large_err<'tcx>(cx: &LateContext<'tcx>, err_ty: Ty<'tcx>, hir_ty
let variant_def = &def.variants[variant.ind];
diag.span_label(
variant_def.span,
format!("the variant `{}` contains at least {} bytes", variant_def.ident, variant.size),
format!(
"the variant `{}` contains at least {} bytes",
variant_def.ident, variant.size
),
);
}
}
diag.help(format!("try reducing the size of `{err_ty}`, for example by boxing large elements or replacing it with `Box<{err_ty}>`"));
}
},
);
}
}
else {
} else {
let ty_size = approx_ty_size(cx, err_ty);
if ty_size >= large_err_threshold {
span_lint_and_then(

View File

@ -1,7 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{higher, SpanlessEq};
use if_chain::if_chain;
use rustc_errors::Diagnostic;
use rustc_hir::intravisit::{self as visit, Visitor};
use rustc_hir::{Expr, ExprKind};

View File

@ -13,8 +13,6 @@ use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span;
use rustc_span::symbol::sym;
use if_chain::if_chain;
use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
use clippy_utils::source::{snippet, snippet_opt};
use clippy_utils::ty::is_type_diagnostic_item;
@ -348,8 +346,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'a, 'b, 't
if self.cx.tcx.is_diagnostic_item(sym::HashMap, ty_did) {
if method.ident.name == sym::new {
self.suggestions
.insert(e.span, "HashMap::default()".to_string());
self.suggestions.insert(e.span, "HashMap::default()".to_string());
} else if method.ident.name == sym!(with_capacity) {
self.suggestions.insert(
e.span,
@ -361,8 +358,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'a, 'b, 't
}
} else if self.cx.tcx.is_diagnostic_item(sym::HashSet, ty_did) {
if method.ident.name == sym::new {
self.suggestions
.insert(e.span, "HashSet::default()".to_string());
self.suggestions.insert(e.span, "HashSet::default()".to_string());
} else if method.ident.name == sym!(with_capacity) {
self.suggestions.insert(
e.span,

View File

@ -2,7 +2,6 @@ use clippy_utils::consts::{constant, Constant};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::get_parent_expr;
use clippy_utils::source::snippet_with_context;
use if_chain::if_chain;
use rustc_ast::ast::{LitIntType, LitKind};
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Block, Expr, ExprKind, Stmt, StmtKind};
@ -47,10 +46,20 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingAdd {
&& let ExprKind::Block(block, None) = then.kind
&& let Block {
stmts:
[Stmt
{ kind: StmtKind::Expr(ex) | StmtKind::Semi(ex), .. }],
expr: None, ..} |
Block { stmts: [], expr: Some(ex), ..} = block
[
Stmt {
kind: StmtKind::Expr(ex) | StmtKind::Semi(ex),
..
},
],
expr: None,
..
}
| Block {
stmts: [],
expr: Some(ex),
..
} = block
&& let ExprKind::AssignOp(op1, target, value) = ex.kind
&& let ty = cx.typeck_results().expr_ty(target)
&& Some(c) == get_int_max(ty)
@ -73,7 +82,15 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingAdd {
} else {
format!("{code} = {code}.saturating_add(1);")
};
span_lint_and_sugg(cx, IMPLICIT_SATURATING_ADD, expr.span, "manual saturating add detected", "use instead", sugg, app);
span_lint_and_sugg(
cx,
IMPLICIT_SATURATING_ADD,
expr.span,
"manual saturating add detected",
"use instead",
sugg,
app,
);
}
}
}

View File

@ -1,6 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::{higher, is_integer_literal, peel_blocks_with_stmt, SpanlessEq};
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind, QPath};
@ -59,7 +58,6 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub {
// Extracting out the variable name
&& let ExprKind::Path(QPath::Resolved(_, ares_path)) = target.kind
{
// Handle symmetric conditions in the if statement
let (cond_var, cond_num_val) = if SpanlessEq::new(cx).eq_expr(cond_left, target) {
@ -102,7 +100,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub {
&& let None = cx.tcx.impl_trait_ref(impl_id) // An inherent impl
&& cx.tcx.type_of(impl_id).instantiate_identity().is_integral()
{
print_lint_and_sugg(cx, var_name, expr)
print_lint_and_sugg(cx, var_name, expr);
}
},
ExprKind::Call(func, []) => {
@ -113,7 +111,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub {
&& let None = cx.tcx.impl_trait_ref(impl_id) // An inherent impl
&& cx.tcx.type_of(impl_id).instantiate_identity().is_integral()
{
print_lint_and_sugg(cx, var_name, expr)
print_lint_and_sugg(cx, var_name, expr);
}
},
_ => (),
@ -131,9 +129,7 @@ fn subtracts_one<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<&'a Exp
ExprKind::Assign(target, value, _) => {
if let ExprKind::Binary(ref op1, left1, right1) = value.kind
&& BinOpKind::Sub == op1.node
&& SpanlessEq::new(cx).eq_expr(left1, target)
&& is_integer_literal(right1, 1)
{
Some(target)

View File

@ -1,6 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet;
use if_chain::if_chain;
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::Applicability;
use rustc_hir::{self as hir, ExprKind};
@ -94,14 +93,15 @@ impl<'tcx> LateLintPass<'tcx> for InconsistentStructConstructor {
fields_snippet.push_str(&last_ident.to_string());
let base_snippet = if let Some(base) = base {
format!(", ..{}", snippet(cx, base.span, ".."))
} else {
String::new()
};
format!(", ..{}", snippet(cx, base.span, ".."))
} else {
String::new()
};
let sugg = format!("{} {{ {fields_snippet}{base_snippet} }}",
let sugg = format!(
"{} {{ {fields_snippet}{base_snippet} }}",
snippet(cx, qpath.span(), ".."),
);
);
span_lint_and_sugg(
cx,
@ -111,7 +111,7 @@ impl<'tcx> LateLintPass<'tcx> for InconsistentStructConstructor {
"try",
sugg,
Applicability::MachineApplicable,
)
);
}
}
}

View File

@ -4,7 +4,6 @@ use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::higher::IfLet;
use clippy_utils::ty::is_copy;
use clippy_utils::{is_expn_of, is_lint_allowed, path_to_local};
use if_chain::if_chain;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_errors::Applicability;
use rustc_hir as hir;
@ -71,10 +70,9 @@ impl_lint_pass!(IndexRefutableSlice => [INDEX_REFUTABLE_SLICE]);
impl<'tcx> LateLintPass<'tcx> for IndexRefutableSlice {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
if (!expr.span.from_expansion() || is_expn_of(expr.span, "if_chain").is_some())
&& let Some(IfLet {let_pat, if_then, ..}) = IfLet::hir(cx, expr)
&& let Some(IfLet { let_pat, if_then, .. }) = IfLet::hir(cx, expr)
&& !is_lint_allowed(cx, INDEX_REFUTABLE_SLICE, expr.hir_id)
&& self.msrv.meets(msrvs::SLICE_PATTERNS)
&& let found_slices = find_slice_values(cx, let_pat)
&& !found_slices.is_empty()
&& let filtered_slices = filter_lintable_slices(cx, found_slices, self.max_suggested_slice, if_then)

View File

@ -90,22 +90,16 @@ impl LateLintPass<'_> for InstantSubtraction {
) = expr.kind
{
if is_instant_now_call(cx, lhs)
&& is_an_instant(cx, rhs)
&& let Some(sugg) = Sugg::hir_opt(cx, rhs)
{
print_manual_instant_elapsed_sugg(cx, expr, sugg)
} else {
if !expr.span.from_expansion()
&& self.msrv.meets(msrvs::TRY_FROM)
&& is_an_instant(cx, lhs)
&& is_a_duration(cx, rhs)
{
print_unchecked_duration_subtraction_sugg(cx, lhs, rhs, expr)
}
print_manual_instant_elapsed_sugg(cx, expr, sugg);
} else if !expr.span.from_expansion()
&& self.msrv.meets(msrvs::TRY_FROM)
&& is_an_instant(cx, lhs)
&& is_a_duration(cx, rhs)
{
print_unchecked_duration_subtraction_sugg(cx, lhs, rhs, expr);
}
}
}

View File

@ -1,5 +1,4 @@
use clippy_utils::diagnostics::span_lint_and_then;
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{Item, ItemKind};
use rustc_lint::{LateContext, LateLintPass};
@ -59,7 +58,6 @@ impl<'tcx> LateLintPass<'tcx> for LargeConstArrays {
&& let Ok(element_count) = element_count.try_to_target_usize(cx.tcx)
&& let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes())
&& self.maximum_allowed_size < u128::from(element_count) * u128::from(element_size)
{
let hi_pos = item.ident.span.lo() - BytePos::from_usize(1);
let sugg_span = Span::new(
@ -80,7 +78,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeConstArrays {
"static",
Applicability::MachineApplicable,
);
}
},
);
}
}

View File

@ -53,7 +53,7 @@ impl LateLintPass<'_> for LargeIncludeFile {
if let Some(macro_call) = root_macro_call_first_node(cx, expr)
&& !is_lint_allowed(cx, LARGE_INCLUDE_FILE, expr.hir_id)
&& (cx.tcx.is_diagnostic_item(sym::include_bytes_macro, macro_call.def_id)
|| cx.tcx.is_diagnostic_item(sym::include_str_macro, macro_call.def_id))
|| cx.tcx.is_diagnostic_item(sym::include_str_macro, macro_call.def_id))
&& let ExprKind::Lit(lit) = &expr.kind
{
let len = match &lit.node {

View File

@ -2,7 +2,6 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_the
use clippy_utils::source::snippet_with_context;
use clippy_utils::sugg::Sugg;
use clippy_utils::{get_item_name, get_parent_as_impl, is_lint_allowed, peel_ref_operators};
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::def::Res;
@ -144,10 +143,8 @@ impl<'tcx> LateLintPass<'tcx> for LenZero {
&& let Some(local_id) = ty_id.as_local()
&& let ty_hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_id)
&& !is_lint_allowed(cx, LEN_WITHOUT_IS_EMPTY, ty_hir_id)
&& let Some(output) = parse_len_output(
cx,
cx.tcx.fn_sig(item.owner_id).instantiate_identity().skip_binder()
)
&& let Some(output) =
parse_len_output(cx, cx.tcx.fn_sig(item.owner_id).instantiate_identity().skip_binder())
{
let (name, kind) = match cx.tcx.hir().find(ty_hir_id) {
Some(Node::ForeignItem(x)) => (x.ident.name, "extern type"),
@ -156,10 +153,10 @@ impl<'tcx> LateLintPass<'tcx> for LenZero {
ItemKind::Enum(..) => (x.ident.name, "enum"),
ItemKind::Union(..) => (x.ident.name, "union"),
_ => (x.ident.name, "type"),
}
},
_ => return,
};
check_for_is_empty(cx, sig.span, sig.decl.implicit_self, output, ty_id, name, kind)
check_for_is_empty(cx, sig.span, sig.decl.implicit_self, output, ty_id, name, kind);
}
}

View File

@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::path_to_local_id;
use clippy_utils::source::snippet;
use clippy_utils::visitors::is_local_used;
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::{BindingAnnotation, Mutability};
@ -65,7 +64,14 @@ impl<'tcx> LateLintPass<'tcx> for LetIfSeq {
&& let hir::StmtKind::Local(local) = stmt.kind
&& let hir::PatKind::Binding(mode, canonical_id, ident, None) = local.pat.kind
&& let hir::StmtKind::Expr(if_) = expr.kind
&& let hir::ExprKind::If(hir::Expr { kind: hir::ExprKind::DropTemps(cond), ..}, then, else_) = if_.kind
&& let hir::ExprKind::If(
hir::Expr {
kind: hir::ExprKind::DropTemps(cond),
..
},
then,
else_,
) = if_.kind
&& !is_local_used(cx, *cond, canonical_id)
&& let hir::ExprKind::Block(then, _) = then.kind
&& let Some(value) = check_assign(cx, canonical_id, then)
@ -73,11 +79,13 @@ impl<'tcx> LateLintPass<'tcx> for LetIfSeq {
{
let span = stmt.span.to(if_.span);
let has_interior_mutability = !cx.typeck_results().node_type(canonical_id).is_freeze(
cx.tcx,
cx.param_env,
);
if has_interior_mutability { return; }
let has_interior_mutability = !cx
.typeck_results()
.node_type(canonical_id)
.is_freeze(cx.tcx, cx.param_env);
if has_interior_mutability {
return;
}
let (default_multi_stmts, default) = if let Some(else_) = else_ {
if let hir::ExprKind::Block(else_, _) = else_.kind {
@ -114,21 +122,23 @@ impl<'tcx> LateLintPass<'tcx> for LetIfSeq {
value=snippet(cx, value.span, "<value>"),
default=snippet(cx, default.span, "<default>"),
);
span_lint_and_then(cx,
USELESS_LET_IF_SEQ,
span,
"`if _ { .. } else { .. }` is an expression",
|diag| {
diag.span_suggestion(
span,
"it is more idiomatic to write",
sug,
Applicability::HasPlaceholders,
);
if !mutability.is_empty() {
diag.note("you might not need `mut` at all");
}
});
span_lint_and_then(
cx,
USELESS_LET_IF_SEQ,
span,
"`if _ { .. } else { .. }` is an expression",
|diag| {
diag.span_suggestion(
span,
"it is more idiomatic to write",
sug,
Applicability::HasPlaceholders,
);
if !mutability.is_empty() {
diag.note("you might not need `mut` at all");
}
},
);
}
}
}
@ -145,7 +155,12 @@ fn check_assign<'tcx>(
&& let hir::ExprKind::Assign(var, value, _) = expr.kind
&& path_to_local_id(var, decl)
{
if block.stmts.iter().take(block.stmts.len()-1).any(|stmt| is_local_used(cx, stmt, decl)) {
if block
.stmts
.iter()
.take(block.stmts.len() - 1)
.any(|stmt| is_local_used(cx, stmt, decl))
{
None
} else {
Some(value)

View File

@ -44,8 +44,8 @@ impl LateLintPass<'_> for UnderscoreTyped {
local.span,
"variable declared with type underscore",
Some(ty.span.with_lo(local.pat.span.hi())),
"remove the explicit type `_` declaration"
)
"remove the explicit type `_` declaration",
);
};
}
}

View File

@ -521,7 +521,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|_| {
Box::new(utils::internal_lints::compiler_lint_functions::CompilerLintFunctions::new())
});
store.register_late_pass(|_| Box::new(utils::internal_lints::if_chain_style::IfChainStyle));
store.register_late_pass(|_| Box::new(utils::internal_lints::invalid_paths::InvalidPaths));
store.register_late_pass(|_| {
Box::<utils::internal_lints::interning_defined_symbol::InterningDefinedSymbol>::default()

View File

@ -313,7 +313,6 @@ fn explicit_self_type<'tcx>(cx: &LateContext<'tcx>, func: &FnDecl<'tcx>, ident:
if let Some(ident) = ident
&& ident.name == kw::SelfLower
&& !func.implicit_self.has_implicit_self()
&& let Some(self_ty) = func.inputs.first()
{
let mut visitor = RefVisitor::new(cx);

View File

@ -4,7 +4,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::numeric_literal::{NumericLiteral, Radix};
use clippy_utils::source::snippet_opt;
use if_chain::if_chain;
use rustc_ast::ast::{Expr, ExprKind, LitKind};
use rustc_ast::token;
use rustc_errors::Applicability;
@ -268,18 +267,17 @@ impl LiteralDigitGrouping {
}
let result = (|| {
let integral_group_size = Self::get_group_size(num_lit.integer.split('_'), num_lit.radix, true)?;
if let Some(fraction) = num_lit.fraction {
let fractional_group_size = Self::get_group_size(
fraction.rsplit('_'),
num_lit.radix,
self.lint_fraction_readability)?;
let fractional_group_size =
Self::get_group_size(fraction.rsplit('_'), num_lit.radix, self.lint_fraction_readability)?;
let consistent = Self::parts_consistent(integral_group_size,
fractional_group_size,
num_lit.integer.len(),
fraction.len());
let consistent = Self::parts_consistent(
integral_group_size,
fractional_group_size,
num_lit.integer.len(),
fraction.len(),
);
if !consistent {
return Err(WarningType::InconsistentDigitGrouping);
};
@ -288,18 +286,13 @@ impl LiteralDigitGrouping {
Ok(())
})();
if let Err(warning_type) = result {
let should_warn = match warning_type {
| WarningType::UnreadableLiteral
WarningType::UnreadableLiteral
| WarningType::InconsistentDigitGrouping
| WarningType::UnusualByteGroupings
| WarningType::LargeDigitGroups => {
!span.from_expansion()
}
WarningType::DecimalRepresentation | WarningType::MistypedLiteralSuffix => {
true
}
| WarningType::LargeDigitGroups => !span.from_expansion(),
WarningType::DecimalRepresentation | WarningType::MistypedLiteralSuffix => true,
};
if should_warn {
warning_type.display(num_lit.format(), cx, span);

View File

@ -2,7 +2,6 @@ use super::{make_iterator_snippet, IncrementVisitor, InitializeVisitor, EXPLICIT
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{get_enclosing_block, is_integer_const};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::intravisit::{walk_block, walk_expr};
use rustc_hir::{Expr, Pat};
@ -53,7 +52,7 @@ pub(super) fn check<'tcx>(
applicability,
);
return;
}
},
Some(ty::Int(int_ty)) => int_ty.name_str(),
Some(ty::Uint(uint_ty)) => uint_ty.name_str(),
_ => return,

View File

@ -4,7 +4,6 @@ use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::implements_trait;
use clippy_utils::{higher, is_res_lang_ctor, path_res, peel_blocks_with_stmt};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::def::Res;
use rustc_hir::lang_items::LangItem;
@ -23,7 +22,11 @@ pub(super) fn check<'tcx>(
let inner_expr = peel_blocks_with_stmt(body);
// Check for the specific case that the result is returned and optimize suggestion for that (more
// cases can be added later)
if let Some(higher::If { cond, then, r#else: None, }) = higher::If::hir(inner_expr)
if let Some(higher::If {
cond,
then,
r#else: None,
}) = higher::If::hir(inner_expr)
&& let Some(binding_id) = get_binding(pat)
&& let ExprKind::Block(block, _) = then.kind
&& let [stmt] = block.stmts
@ -51,7 +54,12 @@ pub(super) fn check<'tcx>(
);
}
let ty = cx.typeck_results().expr_ty(inner_ret);
if cx.tcx.lang_items().copy_trait().map_or(false, |id| implements_trait(cx, ty, id, &[])) {
if cx
.tcx
.lang_items()
.copy_trait()
.map_or(false, |id| implements_trait(cx, ty, id, &[]))
{
snippet.push_str(
&format!(
".find(|{}{}| {})",
@ -84,12 +92,7 @@ pub(super) fn check<'tcx>(
if applicability == Applicability::MaybeIncorrect {
diag.note("you may need to dereference some variables");
}
diag.span_suggestion(
lint_span,
"replace with an iterator",
snippet,
applicability,
);
diag.span_suggestion(lint_span, "replace with an iterator", snippet, applicability);
},
);
}

View File

@ -3,7 +3,6 @@ use super::MANUAL_FLATTEN;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::visitors::is_local_used;
use clippy_utils::{higher, path_to_local_id, peel_blocks_with_stmt};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::{Expr, Pat, PatKind};
@ -38,7 +37,8 @@ pub(super) fn check<'tcx>(
{
let if_let_type = if some_ctor { "Some" } else { "Ok" };
// Prepare the error message
let msg = format!("unnecessary `if let` since only the `{if_let_type}` variant of the iterator element is used");
let msg =
format!("unnecessary `if let` since only the `{if_let_type}` variant of the iterator element is used");
// Prepare the help message
let mut applicability = Applicability::MaybeIncorrect;
@ -46,39 +46,25 @@ pub(super) fn check<'tcx>(
let copied = match cx.typeck_results().expr_ty(let_expr).kind() {
ty::Ref(_, inner, _) => match inner.kind() {
ty::Ref(..) => ".copied()",
_ => ""
}
_ => ""
_ => "",
},
_ => "",
};
let sugg = format!("{arg_snippet}{copied}.flatten()");
// If suggestion is not a one-liner, it won't be shown inline within the error message. In that case,
// it will be shown in the extra `help` message at the end, which is why the first `help_msg` needs
// to refer to the correct relative position of the suggestion.
// If suggestion is not a one-liner, it won't be shown inline within the error message. In that
// case, it will be shown in the extra `help` message at the end, which is why the first
// `help_msg` needs to refer to the correct relative position of the suggestion.
let help_msg = if sugg.contains('\n') {
"remove the `if let` statement in the for loop and then..."
} else {
"...and remove the `if let` statement in the for loop"
};
span_lint_and_then(
cx,
MANUAL_FLATTEN,
span,
&msg,
|diag| {
diag.span_suggestion(
arg.span,
"try",
sugg,
applicability,
);
diag.span_help(
inner_expr.span,
help_msg,
);
}
);
span_lint_and_then(cx, MANUAL_FLATTEN, span, &msg, |diag| {
diag.span_suggestion(arg.span, "try", sugg, applicability);
diag.span_help(inner_expr.span, help_msg);
});
}
}

View File

@ -4,7 +4,6 @@ use clippy_utils::source::snippet;
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::is_copy;
use clippy_utils::{get_enclosing_block, higher, path_to_local, sugg};
use if_chain::if_chain;
use rustc_ast::ast;
use rustc_errors::Applicability;
use rustc_hir::intravisit::walk_block;
@ -69,8 +68,19 @@ pub(super) fn check<'tcx>(
// Source and destination must be different
&& path_to_local(base_left) != path_to_local(base_right)
{
Some((ty, IndexExpr { base: base_left, idx: start_left, idx_offset: offset_left },
IndexExpr { base: base_right, idx: start_right, idx_offset: offset_right }))
Some((
ty,
IndexExpr {
base: base_left,
idx: start_left,
idx_offset: offset_left,
},
IndexExpr {
base: base_right,
idx: start_right,
idx_offset: offset_right,
},
))
} else {
None
}
@ -127,9 +137,7 @@ fn build_manual_memcpy_suggestion<'tcx>(
}
} else {
match limits {
ast::RangeLimits::Closed => {
sugg + &sugg::ONE.into()
},
ast::RangeLimits::Closed => sugg + &sugg::ONE.into(),
ast::RangeLimits::HalfOpen => sugg,
}
}
@ -329,7 +337,11 @@ fn get_slice_like_element_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Opti
fn fetch_cloned_expr<'tcx>(expr: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> {
if let ExprKind::MethodCall(method, arg, [], _) = expr.kind
&& method.ident.name == sym::clone
{ arg } else { expr }
{
arg
} else {
expr
}
}
fn get_details_from_idx<'tcx>(

View File

@ -31,7 +31,12 @@ fn unpack_cond<'tcx>(cond: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> {
}
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, cond: &'tcx Expr<'_>, body: &'tcx Expr<'_>) {
if let ExprKind::Block(Block { stmts: [], expr: None, ..}, _) = body.kind
if let ExprKind::Block(
Block {
stmts: [], expr: None, ..
},
_,
) = body.kind
&& let ExprKind::MethodCall(method, callee, ..) = unpack_cond(cond).kind
&& [sym::load, sym::compare_exchange, sym::compare_exchange_weak].contains(&method.ident.name)
&& let ty::Adt(def, _args) = cx.typeck_results().expr_ty(callee).kind()
@ -47,8 +52,9 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, cond: &'tcx Expr<'_>, body: &'
"{ core::hint::spin_loop() }"
} else {
"{ std::hint::spin_loop() }"
}).into(),
Applicability::MachineApplicable
})
.into(),
Applicability::MachineApplicable,
);
}
}

View File

@ -1,7 +1,6 @@
use super::MUT_RANGE_BOUND;
use clippy_utils::diagnostics::span_lint_and_note;
use clippy_utils::{get_enclosing_block, higher, path_to_local};
use if_chain::if_chain;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{BindingAnnotation, Expr, ExprKind, HirId, Node, PatKind};
use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
@ -13,10 +12,10 @@ use rustc_span::source_map::Span;
pub(super) fn check(cx: &LateContext<'_>, arg: &Expr<'_>, body: &Expr<'_>) {
if let Some(higher::Range {
start: Some(start),
end: Some(end),
..
}) = higher::Range::hir(arg)
start: Some(start),
end: Some(end),
..
}) = higher::Range::hir(arg)
&& let (mut_id_start, mut_id_end) = (check_for_mutability(cx, start), check_for_mutability(cx, end))
&& (mut_id_start.is_some() || mut_id_end.is_some())
{

View File

@ -4,7 +4,6 @@ use clippy_utils::source::snippet;
use clippy_utils::ty::has_iter_method;
use clippy_utils::visitors::is_local_used;
use clippy_utils::{contains_name, higher, is_integer_const, sugg, SpanlessEq};
use if_chain::if_chain;
use rustc_ast::ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir::def::{DefKind, Res};

View File

@ -3,7 +3,6 @@ use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::path_to_local;
use clippy_utils::source::snippet_with_context;
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
use if_chain::if_chain;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};
@ -76,7 +75,7 @@ pub(super) fn check<'tcx>(
if let Res::Def(DefKind::Const, ..) = cx.qpath_res(path, init.hir_id) {
emit_lint(cx, vec, pushed_item, ctxt);
}
}
},
_ => {},
}
}
@ -182,8 +181,8 @@ fn get_vec_push<'tcx>(
// Check that the method being called is push() on a Vec
&& is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(self_expr), sym::Vec)
&& path.ident.name.as_str() == "push"
{
return Some((self_expr, pushed_item, semi_stmt.span.ctxt()))
}
{
return Some((self_expr, pushed_item, semi_stmt.span.ctxt()));
}
None
}

View File

@ -2,7 +2,6 @@ use super::SINGLE_ELEMENT_LOOP;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::{indent_of, snippet_with_applicability};
use clippy_utils::visitors::contains_break_or_continue;
use if_chain::if_chain;
use rustc_ast::util::parser::PREC_PREFIX;
use rustc_ast::Mutability;
use rustc_errors::Applicability;
@ -79,10 +78,12 @@ pub(super) fn check<'tcx>(
let indent = " ".repeat(indent_of(cx, block.stmts[0].span).unwrap_or(0));
// Reference iterator from `&(mut) []` or `[].iter(_mut)()`.
if !prefix.is_empty() && (
// Precedence of internal expression is less than or equal to precedence of `&expr`.
arg_expression.precedence().order() <= PREC_PREFIX || is_range_literal(arg_expression)
) {
if !prefix.is_empty()
&& (
// Precedence of internal expression is less than or equal to precedence of `&expr`.
arg_expression.precedence().order() <= PREC_PREFIX || is_range_literal(arg_expression)
)
{
arg_snip = format!("({arg_snip})").into();
}
@ -94,6 +95,6 @@ pub(super) fn check<'tcx>(
"try",
format!("{{\n{indent}let {pat_snip} = {prefix}{arg_snip};{block_str}}}"),
applicability,
)
);
}
}

View File

@ -1,6 +1,5 @@
use clippy_utils::ty::{has_iter_method, implements_trait};
use clippy_utils::{get_parent_expr, is_integer_const, path_to_local, path_to_local_id, sugg};
use if_chain::if_chain;
use rustc_ast::ast::{LitIntType, LitKind};
use rustc_errors::Applicability;
use rustc_hir::intravisit::{walk_expr, walk_local, walk_pat, walk_stmt, Visitor};
@ -156,7 +155,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> {
ty,
name: ident.name,
}
})
});
}
walk_local(self, l);

View File

@ -2,7 +2,6 @@ use super::WHILE_IMMUTABLE_CONDITION;
use clippy_utils::consts::constant;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::usage::mutated_variables;
use if_chain::if_chain;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefIdMap;
use rustc_hir::intravisit::{walk_expr, Visitor};

View File

@ -3,7 +3,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::visitors::is_res_used;
use clippy_utils::{get_enclosing_loop_or_multi_call_closure, higher, is_refutable, is_res_lang_ctor, is_trait_method};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::def::Res;
use rustc_hir::intravisit::{walk_expr, Visitor};
@ -15,7 +14,7 @@ use rustc_span::symbol::sym;
use rustc_span::Symbol;
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
let (scrutinee_expr, iter_expr_struct, iter_expr, some_pat, loop_expr) = if let Some(higher::WhileLet { if_then, let_pat, let_expr }) = higher::WhileLet::hir(expr)
if let Some(higher::WhileLet { if_then, let_pat, let_expr }) = higher::WhileLet::hir(expr)
// check for `Some(..)` pattern
&& let PatKind::TupleStruct(ref pat_path, some_pat, _) = let_pat.kind
&& is_res_lang_ctor(cx, cx.qpath_res(pat_path, let_pat.hir_id), LangItem::OptionSome)
@ -27,45 +26,41 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
// get the loop containing the match expression
&& !uses_iter(cx, &iter_expr_struct, if_then)
{
(let_expr, iter_expr_struct, iter_expr, some_pat, expr)
} else {
return;
};
let mut applicability = Applicability::MachineApplicable;
let loop_var = if let Some(some_pat) = some_pat.first() {
if is_refutable(cx, some_pat) {
// Refutable patterns don't work with for loops.
return;
}
snippet_with_applicability(cx, some_pat.span, "..", &mut applicability)
} else {
"_".into()
};
let mut applicability = Applicability::MachineApplicable;
let loop_var = if let Some(some_pat) = some_pat.first() {
if is_refutable(cx, some_pat) {
// Refutable patterns don't work with for loops.
return;
}
snippet_with_applicability(cx, some_pat.span, "..", &mut applicability)
} else {
"_".into()
};
// If the iterator is a field or the iterator is accessed after the loop is complete it needs to be
// borrowed mutably. TODO: If the struct can be partially moved from and the struct isn't used
// afterwards a mutable borrow of a field isn't necessary.
let by_ref = if cx.typeck_results().expr_ty(iter_expr).ref_mutability() == Some(Mutability::Mut)
|| !iter_expr_struct.can_move
|| !iter_expr_struct.fields.is_empty()
|| needs_mutable_borrow(cx, &iter_expr_struct, expr)
{
".by_ref()"
} else {
""
};
// If the iterator is a field or the iterator is accessed after the loop is complete it needs to be
// borrowed mutably. TODO: If the struct can be partially moved from and the struct isn't used
// afterwards a mutable borrow of a field isn't necessary.
let by_ref = if cx.typeck_results().expr_ty(iter_expr).ref_mutability() == Some(Mutability::Mut)
|| !iter_expr_struct.can_move
|| !iter_expr_struct.fields.is_empty()
|| needs_mutable_borrow(cx, &iter_expr_struct, loop_expr)
{
".by_ref()"
} else {
""
};
let iterator = snippet_with_applicability(cx, iter_expr.span, "_", &mut applicability);
span_lint_and_sugg(
cx,
WHILE_LET_ON_ITERATOR,
expr.span.with_hi(scrutinee_expr.span.hi()),
"this loop could be written as a `for` loop",
"try",
format!("for {loop_var} in {iterator}{by_ref}"),
applicability,
);
let iterator = snippet_with_applicability(cx, iter_expr.span, "_", &mut applicability);
span_lint_and_sugg(
cx,
WHILE_LET_ON_ITERATOR,
expr.span.with_hi(let_expr.span.hi()),
"this loop could be written as a `for` loop",
"try",
format!("for {loop_var} in {iterator}{by_ref}"),
applicability,
);
}
}
#[derive(Debug)]

View File

@ -1,7 +1,6 @@
use clippy_utils::diagnostics::span_lint_hir_and_then;
use clippy_utils::source::snippet;
use hir::def::{DefKind, Res};
use if_chain::if_chain;
use rustc_ast::ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::Applicability;
@ -108,10 +107,8 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
self.imports.push((def_path, span, hir_id));
}
}
} else {
if item.span.from_expansion() {
self.push_unique_macro_pat_ty(cx, item.span);
}
} else if item.span.from_expansion() {
self.push_unique_macro_pat_ty(cx, item.span);
}
}
fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &ast::Attribute) {

View File

@ -1,7 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::source::snippet;
use clippy_utils::{is_entrypoint_fn, is_no_std_crate};
use if_chain::if_chain;
use rustc_hir::{Expr, ExprKind, QPath};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};
@ -54,8 +53,8 @@ impl LateLintPass<'_> for MainRecursion {
func.span,
&format!("recursing into entrypoint `{}`", snippet(cx, func.span, "main")),
None,
"consider using another function for this recursion"
)
"consider using another function for this recursion",
);
}
}
}

View File

@ -1,6 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::{position_before_rarrow, snippet_block, snippet_opt};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::intravisit::FnKind;
use rustc_hir::{
@ -85,7 +84,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn {
header_span,
help,
format!("{header_snip}{ret_snip}"),
Applicability::MachineApplicable
Applicability::MachineApplicable,
);
let body_snip = snippet_block(cx, closure_body.value.span, "..", Some(block.span));
@ -93,7 +92,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn {
block.span,
"move the body of the async block to the enclosing function",
body_snip,
Applicability::MachineApplicable
Applicability::MachineApplicable,
);
}
},

View File

@ -98,16 +98,18 @@ fn get_one_size_of_ty<'tcx>(
fn get_size_of_ty<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<(&'tcx rustc_hir::Ty<'tcx>, Ty<'tcx>)> {
if let ExprKind::Call(count_func, _func_args) = expr.kind
&& let ExprKind::Path(ref count_func_qpath) = count_func.kind
&& let QPath::Resolved(_, count_func_path) = count_func_qpath
&& let Some(segment_zero) = count_func_path.segments.first()
&& let Some(args) = segment_zero.args
&& let Some(GenericArg::Type(real_ty)) = args.args.first()
&& let Some(def_id) = cx.qpath_res(count_func_qpath, count_func.hir_id).opt_def_id()
&& cx.tcx.is_diagnostic_item(sym::mem_size_of, def_id)
{
cx.typeck_results().node_args(count_func.hir_id).types().next().map(|resolved_ty| (*real_ty, resolved_ty))
cx.typeck_results()
.node_args(count_func.hir_id)
.types()
.next()
.map(|resolved_ty| (*real_ty, resolved_ty))
} else {
None
}

View File

@ -4,7 +4,6 @@ use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
use clippy_utils::source::snippet;
use clippy_utils::usage::mutated_variables;
use clippy_utils::{eq_expr_value, higher, match_def_path, paths};
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_hir::def::Res;
use rustc_hir::intravisit::{walk_expr, Visitor};
@ -97,25 +96,35 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip {
let strippings = find_stripping(cx, strip_kind, target_res, pattern, then);
if !strippings.is_empty() {
let kind_word = match strip_kind {
StripKind::Prefix => "prefix",
StripKind::Suffix => "suffix",
};
let test_span = expr.span.until(then.span);
span_lint_and_then(cx, MANUAL_STRIP, strippings[0], &format!("stripping a {kind_word} manually"), |diag| {
diag.span_note(test_span, format!("the {kind_word} was tested here"));
multispan_sugg(
diag,
&format!("try using the `strip_{kind_word}` method"),
vec![(test_span,
format!("if let Some(<stripped>) = {}.strip_{kind_word}({}) ",
snippet(cx, target_arg.span, ".."),
snippet(cx, pattern.span, "..")))]
.into_iter().chain(strippings.into_iter().map(|span| (span, "<stripped>".into()))),
);
});
span_lint_and_then(
cx,
MANUAL_STRIP,
strippings[0],
&format!("stripping a {kind_word} manually"),
|diag| {
diag.span_note(test_span, format!("the {kind_word} was tested here"));
multispan_sugg(
diag,
&format!("try using the `strip_{kind_word}` method"),
vec![(
test_span,
format!(
"if let Some(<stripped>) = {}.strip_{kind_word}({}) ",
snippet(cx, target_arg.span, ".."),
snippet(cx, pattern.span, "..")
),
)]
.into_iter()
.chain(strippings.into_iter().map(|span| (span, "<stripped>".into()))),
);
},
);
}
}
}
@ -210,7 +219,13 @@ fn find_stripping<'tcx>(
}
},
(StripKind::Suffix, None, Some(end)) => {
if let ExprKind::Binary(Spanned { node: BinOpKind::Sub, .. }, left, right) = end.kind
if let ExprKind::Binary(
Spanned {
node: BinOpKind::Sub, ..
},
left,
right,
) = end.kind
&& let Some(left_arg) = len_arg(self.cx, left)
&& let ExprKind::Path(left_path) = &left_arg.kind
&& self.cx.qpath_res(left_path, left_arg.hir_id) == self.target
@ -220,7 +235,7 @@ fn find_stripping<'tcx>(
return;
}
},
_ => {}
_ => {},
}
}

View File

@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::{snippet, snippet_with_applicability, snippet_with_context};
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{iter_input_pats, method_chain_args};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass};

View File

@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_context;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{higher, is_res_lang_ctor};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, LangItem, PatKind};
use rustc_lint::{LateContext, LateLintPass};

View File

@ -5,7 +5,6 @@ use clippy_utils::visitors::is_local_used;
use clippy_utils::{
is_res_lang_ctor, is_unit_expr, path_to_local, peel_blocks_with_stmt, peel_ref_operators, SpanlessEq,
};
use if_chain::if_chain;
use rustc_errors::MultiSpan;
use rustc_hir::LangItem::OptionNone;
use rustc_hir::{Arm, Expr, Guard, HirId, Let, Pat, PatKind};
@ -84,7 +83,11 @@ fn check_arm<'tcx>(
{
let msg = format!(
"this `{}` can be collapsed into the outer `{}`",
if matches!(inner, IfLetOrMatch::Match(..)) { "match" } else { "if let" },
if matches!(inner, IfLetOrMatch::Match(..)) {
"match"
} else {
"if let"
},
if outer_is_match { "match" } else { "if let" },
);
// collapsing patterns need an explicit field name in struct pattern matching
@ -94,18 +97,15 @@ fn check_arm<'tcx>(
} else {
String::new()
};
span_lint_and_then(
cx,
COLLAPSIBLE_MATCH,
inner_expr.span,
&msg,
|diag| {
let mut help_span = MultiSpan::from_spans(vec![binding_span, inner_then_pat.span]);
help_span.push_span_label(binding_span, "replace this binding");
help_span.push_span_label(inner_then_pat.span, format!("with this pattern{replace_msg}"));
diag.span_help(help_span, "the outer pattern can be modified to include the inner pattern");
},
);
span_lint_and_then(cx, COLLAPSIBLE_MATCH, inner_expr.span, &msg, |diag| {
let mut help_span = MultiSpan::from_spans(vec![binding_span, inner_then_pat.span]);
help_span.push_span_label(binding_span, "replace this binding");
help_span.push_span_label(inner_then_pat.span, format!("with this pattern{replace_msg}"));
diag.span_help(
help_span,
"the outer pattern can be modified to include the inner pattern",
);
});
}
}

View File

@ -11,14 +11,13 @@ pub(crate) fn check(cx: &LateContext<'_>, local: &Local<'_>) -> bool {
if !local.span.from_expansion()
&& let Some(expr) = local.init
&& let ExprKind::Match(target, arms, MatchSource::Normal) = expr.kind
&& arms.len() == 1 && arms[0].guard.is_none()
&& let PatKind::TupleStruct(
QPath::Resolved(None, variant_name), args, _) = arms[0].pat.kind
&& arms.len() == 1
&& arms[0].guard.is_none()
&& let PatKind::TupleStruct(QPath::Resolved(None, variant_name), args, _) = arms[0].pat.kind
&& args.len() == 1
&& let PatKind::Binding(binding, arg, ..) = strip_pat_refs(&args[0]).kind
&& let body = peel_blocks(arms[0].body)
&& path_to_local_id(body, arg)
{
let mut applicability = Applicability::MachineApplicable;
span_lint_and_sugg(

View File

@ -23,16 +23,18 @@ fn get_cond_expr<'tcx>(
) -> Option<SomeExpr<'tcx>> {
if let Some(block_expr) = peels_blocks_incl_unsafe_opt(expr)
&& let ExprKind::If(cond, then_expr, Some(else_expr)) = block_expr.kind
&& let PatKind::Binding(_,target, ..) = pat.kind
&& let PatKind::Binding(_, target, ..) = pat.kind
&& (is_some_expr(cx, target, ctxt, then_expr) && is_none_expr(cx, else_expr)
|| is_none_expr(cx, then_expr) && is_some_expr(cx, target, ctxt, else_expr)) // check that one expr resolves to `Some(x)`, the other to `None`
|| is_none_expr(cx, then_expr) && is_some_expr(cx, target, ctxt, else_expr))
// check that one expr resolves to `Some(x)`, the other to `None`
{
return Some(SomeExpr {
expr: peels_blocks_incl_unsafe(cond.peel_drop_temps()),
needs_unsafe_block: contains_unsafe_block(cx, expr),
needs_negated: is_none_expr(cx, then_expr) // if the `then_expr` resolves to `None`, need to negate the cond
})
};
expr: peels_blocks_incl_unsafe(cond.peel_drop_temps()),
needs_unsafe_block: contains_unsafe_block(cx, expr),
needs_negated: is_none_expr(cx, then_expr), /* if the `then_expr` resolves to `None`, need to negate the
* cond */
});
};
None
}

View File

@ -4,7 +4,6 @@ use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt};
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::usage::contains_return_break_continue_macro;
use clippy_utils::{is_res_lang_ctor, path_to_local_id, sugg};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::LangItem::{OptionNone, ResultErr};
@ -17,30 +16,27 @@ use super::MANUAL_UNWRAP_OR;
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, scrutinee: &'tcx Expr<'_>, arms: &'tcx [Arm<'_>]) {
let ty = cx.typeck_results().expr_ty(scrutinee);
if let Some(ty_name) = if is_type_diagnostic_item(cx, ty, sym::Option) {
Some("Option")
} else if is_type_diagnostic_item(cx, ty, sym::Result) {
Some("Result")
} else {
None
}
&& let Some(or_arm) = applicable_or_arm(cx, arms)
Some("Option")
} else if is_type_diagnostic_item(cx, ty, sym::Result) {
Some("Result")
} else {
None
} && let Some(or_arm) = applicable_or_arm(cx, arms)
&& let Some(or_body_snippet) = snippet_opt(cx, or_arm.body.span)
&& let Some(indent) = indent_of(cx, expr.span)
&& constant_simple(cx, cx.typeck_results(), or_arm.body).is_some()
{
let reindented_or_body =
reindent_multiline(or_body_snippet.into(), true, Some(indent));
let reindented_or_body = reindent_multiline(or_body_snippet.into(), true, Some(indent));
let mut app = Applicability::MachineApplicable;
let suggestion = sugg::Sugg::hir_with_context(cx, scrutinee, expr.span.ctxt(), "..", &mut app).maybe_par();
span_lint_and_sugg(
cx,
MANUAL_UNWRAP_OR, expr.span,
MANUAL_UNWRAP_OR,
expr.span,
&format!("this pattern reimplements `{ty_name}::unwrap_or`"),
"replace with",
format!(
"{suggestion}.unwrap_or({reindented_or_body})",
),
format!("{suggestion}.unwrap_or({reindented_or_body})",),
app,
);
}
@ -49,14 +45,13 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, scrutinee:
fn applicable_or_arm<'a>(cx: &LateContext<'_>, arms: &'a [Arm<'a>]) -> Option<&'a Arm<'a>> {
if arms.len() == 2
&& arms.iter().all(|arm| arm.guard.is_none())
&& let Some((idx, or_arm)) = arms.iter().enumerate().find(|(_, arm)| {
match arm.pat.kind {
PatKind::Path(ref qpath) => is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), OptionNone),
PatKind::TupleStruct(ref qpath, [pat], _) =>
matches!(pat.kind, PatKind::Wild)
&& is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), ResultErr),
_ => false,
}
&& let Some((idx, or_arm)) = arms.iter().enumerate().find(|(_, arm)| match arm.pat.kind {
PatKind::Path(ref qpath) => is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), OptionNone),
PatKind::TupleStruct(ref qpath, [pat], _) => {
matches!(pat.kind, PatKind::Wild)
&& is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), ResultErr)
},
_ => false,
})
&& let unwrap_arm = &arms[1 - idx]
&& let PatKind::TupleStruct(ref qpath, [unwrap_pat], _) = unwrap_arm.pat.kind

View File

@ -71,9 +71,10 @@ fn is_ref_some_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> Option<Mutability> {
&& let ExprKind::Call(e, [arg]) = peel_blocks(arm.body).kind
&& is_res_lang_ctor(cx, path_res(cx, e), LangItem::OptionSome)
&& let ExprKind::Path(QPath::Resolved(_, path2)) = arg.kind
&& path2.segments.len() == 1 && ident.name == path2.segments[0].ident.name
&& path2.segments.len() == 1
&& ident.name == path2.segments[0].ident.name
{
return Some(mutabl)
return Some(mutabl);
}
None
}

View File

@ -87,10 +87,7 @@ where
&& b0 != b1
&& (first_guard.is_none() || iter.len() == 0)
&& first_attrs.is_empty()
&& iter
.all(|arm| {
find_bool_lit(&arm.2.kind).map_or(false, |b| b == b0) && arm.3.is_none() && arm.0.is_empty()
})
&& iter.all(|arm| find_bool_lit(&arm.2.kind).map_or(false, |b| b == b0) && arm.3.is_none() && arm.0.is_empty())
{
if let Some(last_pat) = last_pat_opt {
if !is_wild(last_pat) {
@ -119,7 +116,10 @@ where
.join(" | ")
};
let pat_and_guard = if let Some(Guard::If(g)) = first_guard {
format!("{pat} if {}", snippet_with_applicability(cx, g.span, "..", &mut applicability))
format!(
"{pat} if {}",
snippet_with_applicability(cx, g.span, "..", &mut applicability)
)
} else {
pat
};
@ -135,7 +135,10 @@ where
cx,
MATCH_LIKE_MATCHES_MACRO,
expr.span,
&format!("{} expression looks like `matches!` macro", if is_if_let { "if let .. else" } else { "match" }),
&format!(
"{} expression looks like `matches!` macro",
if is_if_let { "if let .. else" } else { "match" }
),
"try",
format!(
"{}matches!({}, {pat_and_guard})",

View File

@ -1,7 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet;
use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, LangItem};
use rustc_lint::LateContext;
@ -12,7 +11,6 @@ use super::MATCH_ON_VEC_ITEMS;
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, scrutinee: &'tcx Expr<'_>) {
if let Some(idx_expr) = is_vec_indexing(cx, scrutinee)
&& let ExprKind::Index(vec, idx, _) = idx_expr.kind
{
// FIXME: could be improved to suggest surrounding every pattern with Some(_),
// but only when `or_patterns` are stabilized.
@ -22,12 +20,8 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, scrutinee: &'tcx Expr<'_>) {
scrutinee.span,
"indexing into a vector may panic",
"try",
format!(
"{}.get({})",
snippet(cx, vec.span, ".."),
snippet(cx, idx.span, "..")
),
Applicability::MaybeIncorrect
format!("{}.get({})", snippet(cx, vec.span, ".."), snippet(cx, idx.span, "..")),
Applicability::MaybeIncorrect,
);
}
}
@ -36,7 +30,6 @@ fn is_vec_indexing<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Opti
if let ExprKind::Index(array, index, _) = expr.kind
&& is_vector(cx, array)
&& !is_full_range(cx, index)
{
return Some(expr);
}

View File

@ -23,10 +23,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, scrutinee: &'tcx Expr<'_>, arm
if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty(scrutinee).kind()
&& let ty::Str = ty.kind()
{
let mut visitor = MatchExprVisitor {
cx,
case_method: None,
};
let mut visitor = MatchExprVisitor { cx, case_method: None };
visitor.visit_expr(scrutinee);
@ -87,9 +84,9 @@ fn verify_case<'a>(case_method: &'a CaseMethod, arms: &'a [Arm<'_>]) -> Option<(
for arm in arms {
if let PatKind::Lit(Expr {
kind: ExprKind::Lit(lit),
..
}) = arm.pat.kind
kind: ExprKind::Lit(lit),
..
}) = arm.pat.kind
&& let LitKind::Str(symbol, _) = lit.node
&& let input = symbol.as_str()
&& !case_check(input)

View File

@ -39,7 +39,8 @@ pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, ex: &Expr<'tcx>, arms: &[Arm<'
&& is_panic(cx, macro_call.def_id)
{
// `Err(_)` or `Err(_e)` arm with `panic!` found
span_lint_and_note(cx,
span_lint_and_note(
cx,
MATCH_WILD_ERR_ARM,
arm.pat.span,
&format!("`Err({ident_bind_name})` matches all errors"),

View File

@ -5,7 +5,6 @@ use clippy_utils::sugg::Sugg;
use clippy_utils::ty::{is_type_diagnostic_item, needs_ordered_drop};
use clippy_utils::visitors::{any_temporaries_need_ordered_drop, for_each_expr};
use clippy_utils::{higher, is_expn_of, is_trait_method};
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};

View File

@ -14,7 +14,6 @@ pub(crate) fn check(cx: &LateContext<'_>, pat: &Pat<'_>) {
&& (def.is_struct() || def.is_union())
&& fields.len() == def.non_enum_variant().fields.len()
&& !def.non_enum_variant().is_field_list_non_exhaustive()
{
span_lint_and_help(
cx,

View File

@ -93,14 +93,18 @@ fn report_single_pattern(
&& let (ty, ty_ref_count) = peel_mid_ty_refs(cx.typeck_results().expr_ty(ex))
&& let Some(spe_trait_id) = cx.tcx.lang_items().structural_peq_trait()
&& let Some(pe_trait_id) = cx.tcx.lang_items().eq_trait()
&& (ty.is_integral() || ty.is_char() || ty.is_str()
|| (implements_trait(cx, ty, spe_trait_id, &[])
&& implements_trait(cx, ty, pe_trait_id, &[ty.into()])))
&& (ty.is_integral()
|| ty.is_char()
|| ty.is_str()
|| (implements_trait(cx, ty, spe_trait_id, &[]) && implements_trait(cx, ty, pe_trait_id, &[ty.into()])))
{
// scrutinee derives PartialEq and the pattern is a constant.
let pat_ref_count = match pat.kind {
// string literals are already a reference.
PatKind::Lit(Expr { kind: ExprKind::Lit(lit), .. }) if lit.node.is_str() => pat_ref_count + 1,
PatKind::Lit(Expr {
kind: ExprKind::Lit(lit),
..
}) if lit.node.is_str() => pat_ref_count + 1,
_ => pat_ref_count,
};
// References are only implicitly added to the pattern, so no overflow here.

View File

@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{get_parent_expr, is_res_lang_ctor, path_res};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::LangItem::ResultErr;
use rustc_hir::{Expr, ExprKind, LangItem, MatchSource, QPath};
@ -104,7 +103,6 @@ fn poll_result_error_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<
if let ty::Adt(def, subst) = ty.kind()
&& cx.tcx.lang_items().get(LangItem::Poll) == Some(def.did())
&& let ready_ty = subst.type_at(0)
&& let ty::Adt(ready_def, ready_subst) = ready_ty.kind()
&& cx.tcx.is_diagnostic_item(sym::Result, ready_def.did())
{
@ -119,11 +117,9 @@ fn poll_option_result_error_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) ->
if let ty::Adt(def, subst) = ty.kind()
&& cx.tcx.lang_items().get(LangItem::Poll) == Some(def.did())
&& let ready_ty = subst.type_at(0)
&& let ty::Adt(ready_def, ready_subst) = ready_ty.kind()
&& cx.tcx.is_diagnostic_item(sym::Option, ready_def.did())
&& let some_ty = ready_subst.type_at(0)
&& let ty::Adt(some_def, some_subst) = some_ty.kind()
&& cx.tcx.is_diagnostic_item(sym::Result, some_def.did())
{

View File

@ -4,7 +4,6 @@ use clippy_utils::source::{snippet, snippet_with_applicability};
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::is_non_aggregate_primitive_type;
use clippy_utils::{is_default_equivalent, is_res_lang_ctor, path_res, peel_ref_operators};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::LangItem::OptionNone;
use rustc_hir::{Expr, ExprKind};
@ -163,8 +162,9 @@ fn check_replace_with_uninit(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'
),
applicability,
);
} else if cx.tcx.is_diagnostic_item(sym::mem_zeroed, repl_def_id) &&
!cx.typeck_results().expr_ty(src).is_primitive() {
} else if cx.tcx.is_diagnostic_item(sym::mem_zeroed, repl_def_id)
&& !cx.typeck_results().expr_ty(src).is_primitive()
{
span_lint_and_help(
cx,
MEM_REPLACE_WITH_UNINIT,

View File

@ -3,7 +3,6 @@ use clippy_utils::diagnostics::{multispan_sugg_with_applicability, span_lint_and
use clippy_utils::peel_blocks;
use clippy_utils::source::{snippet, snippet_with_context};
use clippy_utils::visitors::find_all_ret_expressions;
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
@ -81,16 +80,11 @@ pub(crate) trait BindInsteadOfMap {
let closure_args_snip = snippet(cx, closure_args_span, "..");
let option_snip = snippet(cx, recv.span, "..");
let note = format!("{option_snip}.{}({closure_args_snip} {some_inner_snip})", Self::GOOD_METHOD_NAME);
span_lint_and_sugg(
cx,
BIND_INSTEAD_OF_MAP,
expr.span,
&msg,
"try",
note,
app,
let note = format!(
"{option_snip}.{}({closure_args_snip} {some_inner_snip})",
Self::GOOD_METHOD_NAME
);
span_lint_and_sugg(cx, BIND_INSTEAD_OF_MAP, expr.span, &msg, "try", note, app);
true
} else {
false
@ -115,7 +109,11 @@ pub(crate) trait BindInsteadOfMap {
let (span, msg) = if can_sugg
&& let hir::ExprKind::MethodCall(segment, ..) = expr.kind
&& let Some(msg) = Self::lint_msg(cx)
{ (segment.ident.span, msg) } else { return false; };
{
(segment.ident.span, msg)
} else {
return false;
};
span_lint_and_then(cx, BIND_INSTEAD_OF_MAP, expr.span, &msg, |diag| {
multispan_sugg_with_applicability(
diag,
@ -136,7 +134,10 @@ pub(crate) trait BindInsteadOfMap {
if let Some(adt) = cx.typeck_results().expr_ty(recv).ty_adt_def()
&& let Some(vid) = cx.tcx.lang_items().get(Self::VARIANT_LANG_ITEM)
&& adt.did() == cx.tcx.parent(vid)
{} else { return false; }
{
} else {
return false;
}
match arg.kind {
hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, .. }) => {

View File

@ -3,7 +3,6 @@ use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::visitors::is_local_used;
use clippy_utils::{path_to_local_id, peel_blocks, peel_ref_operators, strip_pat_refs};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Closure, Expr, ExprKind, PatKind};
use rustc_lint::LateContext;
@ -24,9 +23,7 @@ pub(super) fn check<'tcx>(
&& let PatKind::Binding(_, arg_id, _, _) = strip_pat_refs(param.pat).kind
&& let ExprKind::Binary(ref op, l, r) = body.value.kind
&& op.node == BinOpKind::Eq
&& is_type_diagnostic_item(cx,
cx.typeck_results().expr_ty(filter_recv).peel_refs(),
sym::SliceIter)
&& is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(filter_recv).peel_refs(), sym::SliceIter)
&& let operand_is_arg = (|expr| {
let expr = peel_ref_operators(cx, peel_blocks(expr));
path_to_local_id(expr, arg_id)
@ -41,8 +38,7 @@ pub(super) fn check<'tcx>(
&& ty::Uint(UintTy::U8) == *cx.typeck_results().expr_ty(needle).peel_refs().kind()
&& !is_local_used(cx, needle, arg_id)
{
let haystack = if let ExprKind::MethodCall(path, receiver, [], _) =
filter_recv.kind {
let haystack = if let ExprKind::MethodCall(path, receiver, [], _) = filter_recv.kind {
let p = path.ident.name;
if p == sym::iter || p == sym::iter_mut {
receiver
@ -59,9 +55,11 @@ pub(super) fn check<'tcx>(
expr.span,
"you appear to be counting bytes the naive way",
"consider using the bytecount crate",
format!("bytecount::count({}, {})",
snippet_with_applicability(cx, haystack.span, "..", &mut applicability),
snippet_with_applicability(cx, needle.span, "..", &mut applicability)),
format!(
"bytecount::count({}, {})",
snippet_with_applicability(cx, haystack.span, "..", &mut applicability),
snippet_with_applicability(cx, needle.span, "..", &mut applicability)
),
applicability,
);
};

View File

@ -1,7 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::is_type_lang_item;
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::LateContext;
@ -27,8 +26,11 @@ pub(super) fn check<'tcx>(
expr.span,
"using long and hard to read `.bytes().count()`",
"consider calling `.len()` instead",
format!("{}.len()", snippet_with_applicability(cx, bytes_recv.span, "..", &mut applicability)),
applicability
format!(
"{}.len()",
snippet_with_applicability(cx, bytes_recv.span, "..", &mut applicability)
),
applicability,
);
};
}

View File

@ -1,7 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt};
use clippy_utils::ty::is_type_lang_item;
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, LangItem};
@ -30,7 +29,10 @@ pub(super) fn check<'tcx>(
if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
&& let Some(impl_id) = cx.tcx.impl_of_method(method_id)
&& cx.tcx.type_of(impl_id).instantiate_identity().is_str()
&& let ExprKind::Lit(Spanned { node: LitKind::Str(ext_literal, ..), ..}) = arg.kind
&& let ExprKind::Lit(Spanned {
node: LitKind::Str(ext_literal, ..),
..
}) = arg.kind
&& (2..=6).contains(&ext_literal.as_str().len())
&& let ext_str = ext_literal.as_str()
&& ext_str.starts_with('.')
@ -47,7 +49,6 @@ pub(super) fn check<'tcx>(
|diag| {
diag.help("consider using a case-insensitive comparison instead");
if let Some(mut recv_source) = snippet_opt(cx, recv.span) {
if !cx.typeck_results().expr_ty(recv).is_ref() {
recv_source = format!("&{recv_source}");
}
@ -57,9 +58,12 @@ pub(super) fn check<'tcx>(
"std::path::Path::new({})
.extension()
.map_or(false, |ext| ext.eq_ignore_ascii_case(\"{}\"))",
recv_source, ext_str.strip_prefix('.').unwrap()).into(),
recv_source,
ext_str.strip_prefix('.').unwrap()
)
.into(),
true,
Some(indent_of(cx, call_span).unwrap_or(0) + 4)
Some(indent_of(cx, call_span).unwrap_or(0) + 4),
);
diag.span_suggestion(
@ -69,7 +73,7 @@ pub(super) fn check<'tcx>(
Applicability::MaybeIncorrect,
);
}
}
},
);
}
}

View File

@ -1,7 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{method_chain_args, path_def_id};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::{LateContext, Lint};
@ -33,10 +32,12 @@ pub(super) fn check(
info.expr.span,
&format!("you should use the `{suggest}` method"),
"like this",
format!("{}{}.{suggest}({})",
if info.eq { "" } else { "!" },
snippet_with_applicability(cx, args[0].0.span, "..", &mut applicability),
snippet_with_applicability(cx, arg_char.span, "..", &mut applicability)),
format!(
"{}{}.{suggest}({})",
if info.eq { "" } else { "!" },
snippet_with_applicability(cx, args[0].0.span, "..", &mut applicability),
snippet_with_applicability(cx, arg_char.span, "..", &mut applicability)
),
applicability,
);

View File

@ -1,7 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::method_chain_args;
use clippy_utils::source::snippet_with_applicability;
use if_chain::if_chain;
use rustc_ast::ast;
use rustc_errors::Applicability;
use rustc_hir as hir;
@ -26,10 +25,12 @@ pub(super) fn check(
info.expr.span,
&format!("you should use the `{suggest}` method"),
"like this",
format!("{}{}.{suggest}('{}')",
if info.eq { "" } else { "!" },
snippet_with_applicability(cx, args[0].0.span, "..", &mut applicability),
c.escape_default()),
format!(
"{}{}.{suggest}('{}')",
if info.eq { "" } else { "!" },
snippet_with_applicability(cx, args[0].0.span, "..", &mut applicability),
c.escape_default()
),
applicability,
);

View File

@ -27,7 +27,6 @@ pub(super) fn check(
&& let Some(data_type) = get_data_type(cx, result_type)
// Tests if the T type in a `Result<T, E>` implements debug
&& has_debug_impl(cx, data_type)
{
span_lint_and_sugg(
cx,
@ -36,8 +35,8 @@ pub(super) fn check(
"called `.err().expect()` on a `Result` value",
"try",
"expect_err".to_string(),
Applicability::MachineApplicable
);
Applicability::MachineApplicable,
);
};
}

View File

@ -1,7 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, LangItem};
use rustc_lint::LateContext;

View File

@ -1,7 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::get_parent_expr;
use clippy_utils::ty::is_type_diagnostic_item;
use if_chain::if_chain;
use rustc_hir as hir;
use rustc_lint::LateContext;
use rustc_span::source_map::Span;

View File

@ -4,7 +4,6 @@ use clippy_utils::source::{indent_of, reindent_multiline, snippet};
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{higher, is_trait_method, path_to_local_id, peel_blocks, SpanlessEq};
use hir::{Body, HirId, MatchSource, Pat};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::def::Res;
@ -33,7 +32,7 @@ fn is_method(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_name: Symbol) ->
&& let hir::ExprKind::Path(path) = &receiver.kind
&& let Res::Local(ref local) = cx.qpath_res(path, receiver.hir_id)
{
return arg_id == *local
return arg_id == *local;
}
false
},
@ -324,7 +323,6 @@ pub(super) fn check(
&& let Some(check_result) =
offending_expr.check_map_call(cx, map_body, map_param_id, filter_param_id, is_filter_param_ref)
{
let span = filter_span.with_hi(expr.span.hi());
let (filter_name, lint) = if is_find {
@ -335,18 +333,23 @@ pub(super) fn check(
let msg = format!("`{filter_name}(..).map(..)` can be simplified as `{filter_name}_map(..)`");
let (sugg, note_and_span, applicability) = match check_result {
CheckResult::Method { map_arg, method, side_effect_expr_span } => {
CheckResult::Method {
map_arg,
method,
side_effect_expr_span,
} => {
let (to_opt, deref) = match method {
CalledMethod::ResultIsOk => (".ok()", String::new()),
CalledMethod::OptionIsSome => {
let derefs = cx.typeck_results()
let derefs = cx
.typeck_results()
.expr_adjustments(map_arg)
.iter()
.filter(|adj| matches!(adj.kind, Adjust::Deref(_)))
.count();
("", "*".repeat(derefs))
}
},
};
let sugg = format!(
@ -363,15 +366,24 @@ pub(super) fn check(
};
(sugg, note_and_span, applicability)
}
CheckResult::PatternMatching { variant_span, variant_ident } => {
},
CheckResult::PatternMatching {
variant_span,
variant_ident,
} => {
let pat = snippet(cx, variant_span, "<pattern>");
(format!("{filter_name}_map(|{map_param_ident}| match {map_param_ident} {{ \
(
format!(
"{filter_name}_map(|{map_param_ident}| match {map_param_ident} {{ \
{pat} => Some({variant_ident}), \
_ => None \
}})"), None, Applicability::MachineApplicable)
}
}})"
),
None,
Applicability::MachineApplicable,
)
},
};
span_lint_and_then(cx, lint, span, &msg, |diag| {
diag.span_suggestion(span, "try", sugg, applicability);

View File

@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_opt;
use clippy_utils::ty::implements_trait;
use clippy_utils::{is_path_diagnostic_item, sugg};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::LateContext;
@ -16,7 +15,6 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Exp
&& let ty = cx.typeck_results().expr_ty(expr)
&& let arg_ty = cx.typeck_results().expr_ty(&args[0])
&& let Some(iter_id) = cx.tcx.get_diagnostic_item(sym::Iterator)
&& implements_trait(cx, arg_ty, iter_id, &[])
{
// `expr` implements `FromIterator` trait
@ -44,7 +42,6 @@ fn extract_turbofish(cx: &LateContext<'_>, expr: &hir::Expr<'_>, ty: Ty<'_>) ->
if let Some(snippet) = snippet_opt(cx, call_site)
&& let snippet_split = snippet.split("::").collect::<Vec<_>>()
&& let Some((_, elements)) = snippet_split.split_last()
{
if let [type_specifier, _] = snippet_split.as_slice()
&& let Some(type_specifier) = strip_angle_brackets(type_specifier)
@ -55,9 +52,16 @@ fn extract_turbofish(cx: &LateContext<'_>, expr: &hir::Expr<'_>, ty: Ty<'_>) ->
// is there a type specifier? (i.e.: like `<u32>` in `collections::BTreeSet::<u32>::`)
if let Some(type_specifier) = snippet_split.iter().find(|e| strip_angle_brackets(e).is_some()) {
// remove the type specifier from the path elements
let without_ts = elements.iter().filter_map(|e| {
if e == type_specifier { None } else { Some((*e).to_string()) }
}).collect::<Vec<_>>();
let without_ts = elements
.iter()
.filter_map(|e| {
if e == type_specifier {
None
} else {
Some((*e).to_string())
}
})
.collect::<Vec<_>>();
// join and add the type specifier at the end (i.e.: `collections::BTreeSet<u32>`)
format!("{}{type_specifier}", without_ts.join("::"))
} else {

View File

@ -1,7 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::is_type_diagnostic_item;
use if_chain::if_chain;
use rustc_ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir as hir;
@ -20,7 +19,10 @@ pub(super) fn check<'tcx>(
if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
&& let Some(impl_id) = cx.tcx.impl_of_method(method_id)
&& let identity = cx.tcx.type_of(impl_id).instantiate_identity()
&& let hir::ExprKind::Lit(Spanned { node: LitKind::Int(0, _), .. }) = arg.kind
&& let hir::ExprKind::Lit(Spanned {
node: LitKind::Int(0, _),
..
}) = arg.kind
{
if identity.is_slice() {
let mut app = Applicability::MachineApplicable;
@ -34,18 +36,18 @@ pub(super) fn check<'tcx>(
format!("{slice_name}.first()"),
app,
);
} else if is_type_diagnostic_item(cx, identity, sym::VecDeque){
let mut app = Applicability::MachineApplicable;
let slice_name = snippet_with_applicability(cx, recv.span, "..", &mut app);
span_lint_and_sugg(
cx,
GET_FIRST,
expr.span,
&format!("accessing first element with `{slice_name}.get(0)`"),
"try",
format!("{slice_name}.front()"),
app,
);
} else if is_type_diagnostic_item(cx, identity, sym::VecDeque) {
let mut app = Applicability::MachineApplicable;
let slice_name = snippet_with_applicability(cx, recv.span, "..", &mut app);
span_lint_and_sugg(
cx,
GET_FIRST,
expr.span,
&format!("accessing first element with `{slice_name}.get(0)`"),
"try",
format!("{slice_name}.front()"),
app,
);
}
}
}

View File

@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_context;
use clippy_utils::ty::{implements_trait, peel_mid_ty_refs};
use clippy_utils::{is_diag_item_method, is_diag_trait_item};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::LateContext;

View File

@ -1,7 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::{is_type_lang_item, walk_ptrs_ty_depth};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::LateContext;
@ -18,7 +17,8 @@ pub fn check(
receiver: &hir::Expr<'_>,
args: &[hir::Expr<'_>],
) {
if args.is_empty() && method_name == sym::to_string
if args.is_empty()
&& method_name == sym::to_string
&& let Some(to_string_meth_did) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
&& cx.tcx.is_diagnostic_item(sym::to_string_method, to_string_meth_did)
&& let Some(args) = cx.typeck_results().node_args_opt(expr.hir_id)

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