Merge commit '03a5b6b976' into clippy-subtree-update
This commit is contained in:
parent
6d589103e9
commit
dd5113daab
109 changed files with 1822 additions and 585 deletions
|
|
@ -3,14 +3,13 @@ use clippy_utils::diagnostics::span_lint_and_then;
|
|||
use clippy_utils::mir::{PossibleBorrowerMap, enclosing_mir};
|
||||
use clippy_utils::msrvs::{self, Msrv};
|
||||
use clippy_utils::sugg::Sugg;
|
||||
use clippy_utils::{is_diag_trait_item, is_in_test, last_path_segment, local_is_initialized, path_to_local};
|
||||
use clippy_utils::{is_diag_trait_item, is_in_test, last_path_segment, local_is_initialized, path_to_local, sym};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{self as hir, Expr, ExprKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::ty::{self, Instance, Mutability};
|
||||
use rustc_session::impl_lint_pass;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::{Span, SyntaxContext};
|
||||
|
||||
declare_clippy_lint! {
|
||||
|
|
@ -86,9 +85,9 @@ impl<'tcx> LateLintPass<'tcx> for AssigningClones {
|
|||
&& ctxt.is_root()
|
||||
&& let which_trait = match fn_name {
|
||||
sym::clone if is_diag_trait_item(cx, fn_id, sym::Clone) => CloneTrait::Clone,
|
||||
_ if fn_name.as_str() == "to_owned"
|
||||
&& is_diag_trait_item(cx, fn_id, sym::ToOwned)
|
||||
&& self.msrv.meets(cx, msrvs::CLONE_INTO) =>
|
||||
sym::to_owned
|
||||
if is_diag_trait_item(cx, fn_id, sym::ToOwned)
|
||||
&& self.msrv.meets(cx, msrvs::CLONE_INTO) =>
|
||||
{
|
||||
CloneTrait::ToOwned
|
||||
},
|
||||
|
|
@ -112,7 +111,7 @@ impl<'tcx> LateLintPass<'tcx> for AssigningClones {
|
|||
&& resolved_assoc_items.in_definition_order().any(|assoc|
|
||||
match which_trait {
|
||||
CloneTrait::Clone => assoc.name() == sym::clone_from,
|
||||
CloneTrait::ToOwned => assoc.name().as_str() == "clone_into",
|
||||
CloneTrait::ToOwned => assoc.name() == sym::clone_into,
|
||||
}
|
||||
)
|
||||
&& !clone_source_borrows_from_dest(cx, lhs, rhs.span)
|
||||
|
|
|
|||
|
|
@ -1,17 +1,15 @@
|
|||
use super::BLANKET_CLIPPY_RESTRICTION_LINTS;
|
||||
use super::utils::extract_clippy_lint;
|
||||
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
|
||||
use clippy_utils::sym;
|
||||
use rustc_ast::MetaItemInner;
|
||||
use rustc_lint::{EarlyContext, Level, LintContext};
|
||||
use rustc_span::DUMMY_SP;
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_span::{DUMMY_SP, sym};
|
||||
|
||||
pub(super) fn check(cx: &EarlyContext<'_>, name: Symbol, items: &[MetaItemInner]) {
|
||||
for lint in items {
|
||||
if let Some(lint_name) = extract_clippy_lint(lint)
|
||||
&& lint_name.as_str() == "restriction"
|
||||
&& name != sym::allow
|
||||
{
|
||||
if name != sym::allow && extract_clippy_lint(lint) == Some(sym::restriction) {
|
||||
span_lint_and_help(
|
||||
cx,
|
||||
BLANKET_CLIPPY_RESTRICTION_LINTS,
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ fn check_deprecated_cfg_recursively(cx: &EarlyContext<'_>, attr: &rustc_ast::Met
|
|||
}
|
||||
|
||||
fn check_cargo_clippy_attr(cx: &EarlyContext<'_>, item: &rustc_ast::MetaItem) {
|
||||
if item.has_name(sym::feature) && item.value_str().is_some_and(|v| v.as_str() == "cargo-clippy") {
|
||||
if item.has_name(sym::feature) && item.value_str() == Some(sym::cargo_clippy) {
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
DEPRECATED_CLIPPY_CFG_ATTR,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use super::DEPRECATED_SEMVER;
|
||||
use clippy_utils::diagnostics::span_lint;
|
||||
use clippy_utils::sym;
|
||||
use rustc_ast::{LitKind, MetaItemLit};
|
||||
use rustc_lint::EarlyContext;
|
||||
use rustc_span::Span;
|
||||
|
|
@ -7,7 +8,7 @@ use semver::Version;
|
|||
|
||||
pub(super) fn check(cx: &EarlyContext<'_>, span: Span, lit: &MetaItemLit) {
|
||||
if let LitKind::Str(is, _) = lit.kind
|
||||
&& (is.as_str() == "TBD" || Version::parse(is.as_str()).is_ok())
|
||||
&& (is == sym::TBD || Version::parse(is.as_str()).is_ok())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::msrvs::{self, Msrv};
|
||||
use clippy_utils::sugg::Sugg;
|
||||
use clippy_utils::sym;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Expr, ExprKind};
|
||||
use rustc_lint::LateContext;
|
||||
|
|
@ -19,7 +20,7 @@ pub(super) fn check(
|
|||
if let ty::Int(from) = cast_from.kind()
|
||||
&& let ty::Uint(to) = cast_to.kind()
|
||||
&& let ExprKind::MethodCall(method_path, receiver, [], _) = cast_expr.kind
|
||||
&& method_path.ident.name.as_str() == "abs"
|
||||
&& method_path.ident.name == sym::abs
|
||||
&& msrv.meets(cx, msrvs::UNSIGNED_ABS)
|
||||
{
|
||||
let span = if from.bit_width() == to.bit_width() {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
|
||||
use clippy_utils::expr_or_init;
|
||||
use clippy_utils::source::snippet;
|
||||
use clippy_utils::sugg::Sugg;
|
||||
use clippy_utils::ty::{get_discriminant_value, is_isize_or_usize};
|
||||
use clippy_utils::{expr_or_init, sym};
|
||||
use rustc_abi::IntegerType;
|
||||
use rustc_errors::{Applicability, Diag};
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
|
|
@ -73,7 +73,7 @@ fn apply_reductions(cx: &LateContext<'_>, nbits: u64, expr: &Expr<'_>, signed: b
|
|||
nbits
|
||||
},
|
||||
ExprKind::MethodCall(method, _value, [], _) => {
|
||||
if method.ident.name.as_str() == "signum" {
|
||||
if method.ident.name == sym::signum {
|
||||
0 // do not lint if cast comes from a `signum` function
|
||||
} else {
|
||||
nbits
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
use clippy_utils::diagnostics::span_lint;
|
||||
use clippy_utils::ty::is_c_void;
|
||||
use clippy_utils::{get_parent_expr, is_hir_ty_cfg_dependant};
|
||||
use clippy_utils::{get_parent_expr, is_hir_ty_cfg_dependant, sym};
|
||||
use rustc_hir::{Expr, ExprKind, GenericArg};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty::layout::LayoutOf;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::sym;
|
||||
|
||||
use super::CAST_PTR_ALIGNMENT;
|
||||
|
||||
|
|
@ -20,7 +19,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
|
|||
);
|
||||
lint_cast_ptr_alignment(cx, expr, cast_from, cast_to);
|
||||
} else if let ExprKind::MethodCall(method_path, self_arg, [], _) = &expr.kind
|
||||
&& method_path.ident.name.as_str() == "cast"
|
||||
&& method_path.ident.name == sym::cast
|
||||
&& let Some(generic_args) = method_path.args
|
||||
&& let [GenericArg::Type(cast_to)] = generic_args.args
|
||||
// There probably is no obvious reason to do this, just to be consistent with `as` cases.
|
||||
|
|
|
|||
|
|
@ -8,7 +8,9 @@ use rustc_errors::Applicability;
|
|||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::{Expr, ExprKind, Lit, Node, Path, QPath, TyKind, UnOp};
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
use rustc_middle::ty::adjustment::Adjust;
|
||||
use rustc_middle::ty::{self, FloatTy, InferTy, Ty};
|
||||
use rustc_span::{Symbol, sym};
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
use super::UNNECESSARY_CAST;
|
||||
|
|
@ -142,6 +144,33 @@ pub(super) fn check<'tcx>(
|
|||
}
|
||||
|
||||
if cast_from.kind() == cast_to.kind() && !expr.span.in_external_macro(cx.sess().source_map()) {
|
||||
enum MaybeParenOrBlock {
|
||||
Paren,
|
||||
Block,
|
||||
Nothing,
|
||||
}
|
||||
|
||||
fn is_borrow_expr(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
||||
matches!(expr.kind, ExprKind::AddrOf(..))
|
||||
|| cx
|
||||
.typeck_results()
|
||||
.expr_adjustments(expr)
|
||||
.first()
|
||||
.is_some_and(|adj| matches!(adj.kind, Adjust::Borrow(_)))
|
||||
}
|
||||
|
||||
fn is_in_allowed_macro(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
||||
const ALLOWED_MACROS: &[Symbol] = &[
|
||||
sym::format_args_macro,
|
||||
sym::assert_eq_macro,
|
||||
sym::debug_assert_eq_macro,
|
||||
sym::assert_ne_macro,
|
||||
sym::debug_assert_ne_macro,
|
||||
];
|
||||
matches!(expr.span.ctxt().outer_expn_data().macro_def_id, Some(def_id) if
|
||||
cx.tcx.get_diagnostic_name(def_id).is_some_and(|sym| ALLOWED_MACROS.contains(&sym)))
|
||||
}
|
||||
|
||||
if let Some(id) = path_to_local(cast_expr)
|
||||
&& !cx.tcx.hir_span(id).eq_ctxt(cast_expr.span)
|
||||
{
|
||||
|
|
@ -150,15 +179,15 @@ pub(super) fn check<'tcx>(
|
|||
return false;
|
||||
}
|
||||
|
||||
// If the whole cast expression is a unary expression (`(*x as T)`) or an addressof
|
||||
// expression (`(&x as T)`), then not surrounding the suggestion into a block risks us
|
||||
// changing the precedence of operators if the cast expression is followed by an operation
|
||||
// with higher precedence than the unary operator (`(*x as T).foo()` would become
|
||||
// `*x.foo()`, which changes what the `*` applies on).
|
||||
// The same is true if the expression encompassing the cast expression is a unary
|
||||
// expression or an addressof expression.
|
||||
let needs_block = matches!(cast_expr.kind, ExprKind::Unary(..) | ExprKind::AddrOf(..))
|
||||
|| get_parent_expr(cx, expr).is_some_and(|e| matches!(e.kind, ExprKind::Unary(..) | ExprKind::AddrOf(..)));
|
||||
// Changing `&(x as i32)` to `&x` would change the meaning of the code because the previous creates
|
||||
// a reference to the temporary while the latter creates a reference to the original value.
|
||||
let surrounding = match cx.tcx.parent_hir_node(expr.hir_id) {
|
||||
Node::Expr(parent) if is_borrow_expr(cx, parent) && !is_in_allowed_macro(cx, parent) => {
|
||||
MaybeParenOrBlock::Block
|
||||
},
|
||||
Node::Expr(parent) if cast_expr.precedence() < parent.precedence() => MaybeParenOrBlock::Paren,
|
||||
_ => MaybeParenOrBlock::Nothing,
|
||||
};
|
||||
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
|
|
@ -166,10 +195,10 @@ pub(super) fn check<'tcx>(
|
|||
expr.span,
|
||||
format!("casting to the same type is unnecessary (`{cast_from}` -> `{cast_to}`)"),
|
||||
"try",
|
||||
if needs_block {
|
||||
format!("{{ {cast_str} }}")
|
||||
} else {
|
||||
cast_str
|
||||
match surrounding {
|
||||
MaybeParenOrBlock::Paren => format!("({cast_str})"),
|
||||
MaybeParenOrBlock::Block => format!("{{ {cast_str} }}"),
|
||||
MaybeParenOrBlock::Nothing => cast_str,
|
||||
},
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ use rustc_ast::tokenstream::{TokenStream, TokenTree};
|
|||
use rustc_errors::Applicability;
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass};
|
||||
use rustc_session::declare_lint_pass;
|
||||
use rustc_span::Span;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::{Span, kw};
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
|
|
@ -105,12 +105,11 @@ 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, _),
|
||||
kind: TokenKind::Ident(kw::Crate, _),
|
||||
span,
|
||||
},
|
||||
_,
|
||||
) = tt
|
||||
&& symbol.as_str() == "crate"
|
||||
{
|
||||
Some(*span)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -68,6 +68,38 @@ fn is_structural_partial_eq<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, other: T
|
|||
}
|
||||
}
|
||||
|
||||
/// Check if the pattern has any type mismatch that would prevent it from being used in an equality
|
||||
/// check. This can happen if the expr has a reference type and the corresponding pattern is a
|
||||
/// literal.
|
||||
fn contains_type_mismatch(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
|
||||
let mut result = false;
|
||||
pat.walk(|p| {
|
||||
if result {
|
||||
return false;
|
||||
}
|
||||
|
||||
if p.span.in_external_macro(cx.sess().source_map()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
let adjust_pat = match p.kind {
|
||||
PatKind::Or([p, ..]) => p,
|
||||
_ => p,
|
||||
};
|
||||
|
||||
if let Some(adjustments) = cx.typeck_results().pat_adjustments().get(adjust_pat.hir_id)
|
||||
&& adjustments.first().is_some_and(|first| first.source.is_ref())
|
||||
{
|
||||
result = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
});
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for PatternEquality {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
|
||||
if let ExprKind::Let(let_expr) = expr.kind
|
||||
|
|
@ -78,7 +110,7 @@ impl<'tcx> LateLintPass<'tcx> for PatternEquality {
|
|||
let pat_ty = cx.typeck_results().pat_ty(let_expr.pat);
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
|
||||
if is_structural_partial_eq(cx, exp_ty, pat_ty) {
|
||||
if is_structural_partial_eq(cx, exp_ty, pat_ty) && !contains_type_mismatch(cx, let_expr.pat) {
|
||||
let pat_str = match let_expr.pat.kind {
|
||||
PatKind::Struct(..) => format!(
|
||||
"({})",
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::{
|
||||
eq_expr_value, get_parent_expr, higher, is_in_const_context, is_inherent_method_call, is_no_std_crate,
|
||||
numeric_literal, peel_blocks, sugg,
|
||||
numeric_literal, peel_blocks, sugg, sym,
|
||||
};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment, UnOp};
|
||||
|
|
@ -435,7 +435,7 @@ fn check_expm1(cx: &LateContext<'_>, expr: &Expr<'_>) {
|
|||
rhs,
|
||||
) = expr.kind
|
||||
&& let ExprKind::MethodCall(path, self_arg, [], _) = &lhs.kind
|
||||
&& path.ident.name.as_str() == "exp"
|
||||
&& path.ident.name == sym::exp
|
||||
&& cx.typeck_results().expr_ty(lhs).is_floating_point()
|
||||
&& let Some(value) = ConstEvalCtxt::new(cx).eval(rhs)
|
||||
&& (F32(1.0) == value || F64(1.0) == value)
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_help;
|
||||
use clippy_utils::path_def_id;
|
||||
use clippy_utils::ty::is_c_void;
|
||||
use clippy_utils::{path_def_id, sym};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::{Expr, ExprKind, QPath};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty;
|
||||
use rustc_session::declare_lint_pass;
|
||||
use rustc_span::sym;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
|
|
@ -41,7 +40,7 @@ impl LateLintPass<'_> for FromRawWithVoidPtr {
|
|||
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
|
||||
if let ExprKind::Call(box_from_raw, [arg]) = expr.kind
|
||||
&& let ExprKind::Path(QPath::TypeRelative(ty, seg)) = box_from_raw.kind
|
||||
&& seg.ident.name.as_str() == "from_raw"
|
||||
&& seg.ident.name == sym::from_raw
|
||||
&& let Some(type_str) = path_def_id(cx, ty).and_then(|id| def_id_matches_type(cx, id))
|
||||
&& let arg_kind = cx.typeck_results().expr_ty(arg).kind()
|
||||
&& let ty::RawPtr(ty, _) = arg_kind
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::sugg::Sugg;
|
||||
use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
|
||||
use clippy_utils::{is_in_const_context, is_integer_literal};
|
||||
use clippy_utils::{is_in_const_context, is_integer_literal, sym};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Expr, ExprKind, LangItem, PrimTy, QPath, TyKind, def};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_session::declare_lint_pass;
|
||||
use rustc_span::symbol::sym;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
|
|
@ -53,7 +52,7 @@ impl<'tcx> LateLintPass<'tcx> for FromStrRadix10 {
|
|||
|
||||
// check if the second part of the path indeed calls the associated
|
||||
// function `from_str_radix`
|
||||
&& pathseg.ident.name.as_str() == "from_str_radix"
|
||||
&& pathseg.ident.name == sym::from_str_radix
|
||||
|
||||
// check if the first part of the path is some integer primitive
|
||||
&& let TyKind::Path(ty_qpath) = &ty.kind
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@ use rustc_middle::hir::nested_filter;
|
|||
use rustc_middle::ty::{Ty, TypeckResults};
|
||||
use rustc_session::declare_lint_pass;
|
||||
use rustc_span::Span;
|
||||
use rustc_span::symbol::sym;
|
||||
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::source::{IntoSpan, SpanRangeExt, snippet};
|
||||
use clippy_utils::sym;
|
||||
use clippy_utils::ty::is_type_diagnostic_item;
|
||||
|
||||
declare_clippy_lint! {
|
||||
|
|
@ -326,6 +326,7 @@ impl<'tcx> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'_, '_, 'tcx> {
|
|||
fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
|
||||
if let ExprKind::Call(fun, args) = e.kind
|
||||
&& let ExprKind::Path(QPath::TypeRelative(ty, method)) = fun.kind
|
||||
&& matches!(method.ident.name, sym::new | sym::with_capacity)
|
||||
&& let TyKind::Path(QPath::Resolved(None, ty_path)) = ty.kind
|
||||
&& let Some(ty_did) = ty_path.res.opt_def_id()
|
||||
{
|
||||
|
|
@ -333,10 +334,11 @@ impl<'tcx> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'_, '_, 'tcx> {
|
|||
return;
|
||||
}
|
||||
|
||||
if self.cx.tcx.is_diagnostic_item(sym::HashMap, ty_did) {
|
||||
if method.ident.name == sym::new {
|
||||
match (self.cx.tcx.get_diagnostic_name(ty_did), method.ident.name) {
|
||||
(Some(sym::HashMap), sym::new) => {
|
||||
self.suggestions.insert(e.span, "HashMap::default()".to_string());
|
||||
} else if method.ident.name.as_str() == "with_capacity" {
|
||||
},
|
||||
(Some(sym::HashMap), sym::with_capacity) => {
|
||||
self.suggestions.insert(
|
||||
e.span,
|
||||
format!(
|
||||
|
|
@ -344,11 +346,11 @@ impl<'tcx> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'_, '_, 'tcx> {
|
|||
snippet(self.cx, args[0].span, "capacity"),
|
||||
),
|
||||
);
|
||||
}
|
||||
} else if self.cx.tcx.is_diagnostic_item(sym::HashSet, ty_did) {
|
||||
if method.ident.name == sym::new {
|
||||
},
|
||||
(Some(sym::HashSet), sym::new) => {
|
||||
self.suggestions.insert(e.span, "HashSet::default()".to_string());
|
||||
} else if method.ident.name.as_str() == "with_capacity" {
|
||||
},
|
||||
(Some(sym::HashSet), sym::with_capacity) => {
|
||||
self.suggestions.insert(
|
||||
e.span,
|
||||
format!(
|
||||
|
|
@ -356,7 +358,8 @@ impl<'tcx> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'_, '_, 'tcx> {
|
|||
snippet(self.cx, args[0].span, "capacity"),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
use clippy_utils::diagnostics::span_lint;
|
||||
use clippy_utils::higher;
|
||||
use clippy_utils::ty::{get_type_diagnostic_name, implements_trait};
|
||||
use clippy_utils::{higher, sym};
|
||||
use rustc_hir::{BorrowKind, Closure, Expr, ExprKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::declare_lint_pass;
|
||||
use rustc_span::symbol::sym;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
|
|
@ -156,7 +155,7 @@ fn is_infinite(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
|
|||
.and(cap);
|
||||
}
|
||||
}
|
||||
if method.ident.name.as_str() == "flat_map"
|
||||
if method.ident.name == sym::flat_map
|
||||
&& args.len() == 1
|
||||
&& let ExprKind::Closure(&Closure { body, .. }) = args[0].kind
|
||||
{
|
||||
|
|
@ -224,7 +223,7 @@ fn complete_infinite_iter(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
|
|||
return MaybeInfinite.and(is_infinite(cx, receiver));
|
||||
}
|
||||
}
|
||||
if method.ident.name.as_str() == "last" && args.is_empty() {
|
||||
if method.ident.name == sym::last && args.is_empty() {
|
||||
let not_double_ended = cx
|
||||
.tcx
|
||||
.get_diagnostic_item(sym::DoubleEndedIterator)
|
||||
|
|
@ -232,7 +231,7 @@ fn complete_infinite_iter(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
|
|||
if not_double_ended {
|
||||
return is_infinite(cx, receiver);
|
||||
}
|
||||
} else if method.ident.name.as_str() == "collect" {
|
||||
} else if method.ident.name == sym::collect {
|
||||
let ty = cx.typeck_results().expr_ty(expr);
|
||||
if matches!(
|
||||
get_type_diagnostic_name(cx, ty),
|
||||
|
|
|
|||
|
|
@ -1,14 +1,13 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::get_parent_as_impl;
|
||||
use clippy_utils::source::snippet;
|
||||
use clippy_utils::ty::{deref_chain, get_adt_inherent_method, implements_trait, make_normalized_projection};
|
||||
use clippy_utils::{get_parent_as_impl, sym};
|
||||
use rustc_ast::Mutability;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{FnRetTy, ImplItemKind, ImplicitSelfKind, ItemKind, TyKind};
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_session::declare_lint_pass;
|
||||
use rustc_span::sym;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
|
|
@ -141,7 +140,7 @@ impl LateLintPass<'_> for IterWithoutIntoIter {
|
|||
ty.peel_refs().is_slice() || get_adt_inherent_method(cx, ty, expected_method_name).is_some()
|
||||
})
|
||||
&& let Some(iter_assoc_span) = imp.items.iter().find_map(|item| {
|
||||
if item.ident.name.as_str() == "IntoIter" {
|
||||
if item.ident.name == sym::IntoIter {
|
||||
Some(cx.tcx.hir_impl_item(item.id).expect_type().span)
|
||||
} else {
|
||||
None
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_the
|
|||
use clippy_utils::source::{SpanRangeExt, snippet_with_context};
|
||||
use clippy_utils::sugg::{Sugg, has_enclosing_paren};
|
||||
use clippy_utils::ty::implements_trait;
|
||||
use clippy_utils::{fulfill_or_allowed, get_item_name, get_parent_as_impl, is_trait_method, peel_ref_operators, sym};
|
||||
use clippy_utils::{
|
||||
fulfill_or_allowed, get_parent_as_impl, is_trait_method, parent_item_name, peel_ref_operators, sym,
|
||||
};
|
||||
use rustc_ast::ast::LitKind;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::def::Res;
|
||||
|
|
@ -533,9 +535,7 @@ fn check_cmp(cx: &LateContext<'_>, span: Span, method: &Expr<'_>, lit: &Expr<'_>
|
|||
|
||||
if let (&ExprKind::MethodCall(method_path, receiver, [], _), ExprKind::Lit(lit)) = (&method.kind, &lit.kind) {
|
||||
// check if we are in an is_empty() method
|
||||
if let Some(name) = get_item_name(cx, method)
|
||||
&& name.as_str() == "is_empty"
|
||||
{
|
||||
if parent_item_name(cx, method) == Some(sym::is_empty) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -729,6 +729,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
|
|||
store.register_early_pass(|| Box::new(misc_early::MiscEarlyLints));
|
||||
store.register_late_pass(|_| Box::new(redundant_closure_call::RedundantClosureCall));
|
||||
store.register_early_pass(|| Box::new(unused_unit::UnusedUnit));
|
||||
store.register_late_pass(|_| Box::new(unused_unit::UnusedUnit));
|
||||
store.register_late_pass(|_| Box::new(returns::Return));
|
||||
store.register_late_pass(move |tcx| Box::new(collapsible_if::CollapsibleIf::new(tcx, conf)));
|
||||
store.register_late_pass(|_| Box::new(items_after_statements::ItemsAfterStatements));
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
|
|||
use clippy_utils::msrvs::Msrv;
|
||||
use clippy_utils::source::snippet_with_context;
|
||||
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
|
||||
use clippy_utils::{msrvs, path_to_local, std_or_core};
|
||||
use clippy_utils::{msrvs, path_to_local, std_or_core, sym};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
|
|
@ -11,7 +11,6 @@ use rustc_hir::intravisit::{Visitor, walk_expr};
|
|||
use rustc_hir::{BindingMode, Block, Expr, ExprKind, HirId, Mutability, Node, Pat, PatKind, Stmt, StmtKind};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_span::SyntaxContext;
|
||||
use rustc_span::symbol::sym;
|
||||
|
||||
/// Detects for loop pushing the same item into a Vec
|
||||
pub(super) fn check<'tcx>(
|
||||
|
|
@ -187,8 +186,8 @@ fn get_vec_push<'tcx>(
|
|||
// Extract method being called and figure out the parameters for the method call
|
||||
&& let ExprKind::MethodCall(path, self_expr, [pushed_item], _) = &semi_stmt.kind
|
||||
// Check that the method being called is push() on a Vec
|
||||
&& path.ident.name == sym::push
|
||||
&& 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()));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use clippy_config::Conf;
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::msrvs::{self, Msrv};
|
||||
use clippy_utils::source::snippet_with_applicability;
|
||||
use clippy_utils::source::snippet_with_context;
|
||||
use clippy_utils::sugg::{Sugg, has_enclosing_paren};
|
||||
use clippy_utils::{SpanlessEq, sym};
|
||||
use rustc_ast::{BinOpKind, LitIntType, LitKind, UnOp};
|
||||
|
|
@ -199,9 +199,9 @@ fn build_suggestion(
|
|||
} else {
|
||||
format!("{dividend_sugg_str}{type_suffix}")
|
||||
};
|
||||
let divisor_snippet = snippet_with_applicability(cx, rhs.span.source_callsite(), "..", applicability);
|
||||
let divisor_snippet = snippet_with_context(cx, rhs.span, expr.span.ctxt(), "..", applicability);
|
||||
|
||||
let sugg = format!("{suggestion_before_div_ceil}.div_ceil({divisor_snippet})");
|
||||
let sugg = format!("{suggestion_before_div_ceil}.div_ceil({})", divisor_snippet.0);
|
||||
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
|
|
|
|||
|
|
@ -3,12 +3,11 @@ use clippy_utils::diagnostics::span_lint_hir_and_then;
|
|||
use clippy_utils::msrvs::{self, Msrv};
|
||||
use clippy_utils::source::SpanRangeExt;
|
||||
use clippy_utils::visitors::{is_local_used, local_used_once};
|
||||
use clippy_utils::{is_trait_method, path_to_local_id};
|
||||
use clippy_utils::{is_trait_method, path_to_local_id, sym};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{BindingMode, ExprKind, LetStmt, Node, PatKind, StmtKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::impl_lint_pass;
|
||||
use rustc_span::sym;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
|
|
@ -66,7 +65,7 @@ impl LateLintPass<'_> for ManualHashOne {
|
|||
&& let Some(init) = local.init
|
||||
&& !init.span.from_expansion()
|
||||
&& let ExprKind::MethodCall(seg, build_hasher, [], _) = init.kind
|
||||
&& seg.ident.name.as_str() == "build_hasher"
|
||||
&& seg.ident.name == sym::build_hasher
|
||||
|
||||
&& let Node::Stmt(local_stmt) = cx.tcx.parent_hir_node(local.hir_id)
|
||||
&& let Node::Block(block) = cx.tcx.parent_hir_node(local_stmt.hir_id)
|
||||
|
|
@ -94,7 +93,7 @@ impl LateLintPass<'_> for ManualHashOne {
|
|||
&& let Node::Expr(finish_expr) = cx.tcx.parent_hir_node(path_expr.hir_id)
|
||||
&& !finish_expr.span.from_expansion()
|
||||
&& let ExprKind::MethodCall(seg, _, [], _) = finish_expr.kind
|
||||
&& seg.ident.name.as_str() == "finish"
|
||||
&& seg.ident.name == sym::finish
|
||||
|
||||
&& self.msrv.meets(cx, msrvs::BUILD_HASHER_HASH_ONE)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
|
|||
use clippy_utils::macros::matching_root_macro_call;
|
||||
use clippy_utils::msrvs::{self, Msrv};
|
||||
use clippy_utils::sugg::Sugg;
|
||||
use clippy_utils::{higher, is_in_const_context, path_to_local, peel_ref_operators};
|
||||
use clippy_utils::{higher, is_in_const_context, path_to_local, peel_ref_operators, sym};
|
||||
use rustc_ast::LitKind::{Byte, Char};
|
||||
use rustc_ast::ast::RangeLimits;
|
||||
use rustc_errors::Applicability;
|
||||
|
|
@ -11,7 +11,7 @@ use rustc_hir::{Expr, ExprKind, Lit, Node, Param, PatExpr, PatExprKind, PatKind,
|
|||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_session::impl_lint_pass;
|
||||
use rustc_span::{Span, sym};
|
||||
use rustc_span::Span;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
|
|
@ -103,7 +103,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualIsAsciiCheck {
|
|||
check_is_ascii(cx, macro_call.span, recv, &range, None);
|
||||
}
|
||||
} else if let ExprKind::MethodCall(path, receiver, [arg], ..) = expr.kind
|
||||
&& path.ident.name.as_str() == "contains"
|
||||
&& path.ident.name == sym::contains
|
||||
&& let Some(higher::Range {
|
||||
start: Some(start),
|
||||
end: Some(end),
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
use clippy_config::Conf;
|
||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
|
||||
use clippy_utils::msrvs::Msrv;
|
||||
use clippy_utils::{is_none_arm, msrvs, peel_hir_expr_refs};
|
||||
use clippy_utils::{is_none_arm, msrvs, peel_hir_expr_refs, sym};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::{Arm, Expr, ExprKind, LangItem, Pat, PatKind, QPath, is_range_literal};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty;
|
||||
use rustc_session::impl_lint_pass;
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
use rustc_span::{Span, Symbol};
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
|
|
@ -76,7 +76,7 @@ impl LateLintPass<'_> for ManualOptionAsSlice {
|
|||
}
|
||||
},
|
||||
ExprKind::MethodCall(seg, callee, [], _) => {
|
||||
if seg.ident.name.as_str() == "unwrap_or_default" {
|
||||
if seg.ident.name == sym::unwrap_or_default {
|
||||
check_map(cx, callee, span, self.msrv);
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::ty::{has_non_owning_mutable_access, implements_trait};
|
||||
use clippy_utils::{is_mutable, is_trait_method, path_to_local};
|
||||
use clippy_utils::{is_mutable, is_trait_method, path_to_local, sym};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Expr, Node, PatKind};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty::Instance;
|
||||
use rustc_span::{Span, sym};
|
||||
use rustc_span::Span;
|
||||
|
||||
use super::DOUBLE_ENDED_ITERATOR_LAST;
|
||||
|
||||
|
|
@ -24,7 +24,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &'_ Expr<'_>, self_expr: &'_ Exp
|
|||
&& let Ok(Some(fn_def)) = Instance::try_resolve(cx.tcx, cx.typing_env(), id, args)
|
||||
// find the provided definition of Iterator::last
|
||||
&& let Some(item) = cx.tcx.get_diagnostic_item(sym::Iterator)
|
||||
&& let Some(last_def) = cx.tcx.provided_trait_methods(item).find(|m| m.name().as_str() == "last")
|
||||
&& let Some(last_def) = cx.tcx.provided_trait_methods(item).find(|m| m.name() == sym::last)
|
||||
// if the resolved method is the same as the provided definition
|
||||
&& fn_def.def_id() == last_def.def_id
|
||||
&& let self_ty = cx.typeck_results().expr_ty(self_expr)
|
||||
|
|
|
|||
|
|
@ -233,12 +233,12 @@ impl<'tcx> OffendingFilterExpr<'tcx> {
|
|||
// the latter only calls `effect` once
|
||||
let side_effect_expr_span = receiver.can_have_side_effects().then_some(receiver.span);
|
||||
|
||||
if cx.tcx.is_diagnostic_item(sym::Option, recv_ty.did()) && path.ident.name.as_str() == "is_some" {
|
||||
if cx.tcx.is_diagnostic_item(sym::Option, recv_ty.did()) && path.ident.name == sym::is_some {
|
||||
Some(Self::IsSome {
|
||||
receiver,
|
||||
side_effect_expr_span,
|
||||
})
|
||||
} else if cx.tcx.is_diagnostic_item(sym::Result, recv_ty.did()) && path.ident.name.as_str() == "is_ok" {
|
||||
} else if cx.tcx.is_diagnostic_item(sym::Result, recv_ty.did()) && path.ident.name == sym::is_ok {
|
||||
Some(Self::IsOk {
|
||||
receiver,
|
||||
side_effect_expr_span,
|
||||
|
|
|
|||
|
|
@ -4370,11 +4370,10 @@ declare_clippy_lint! {
|
|||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
///
|
||||
/// Detect functions that end with `Option::and_then` or `Result::and_then`, and suggest using a question mark (`?`) instead.
|
||||
/// Detect functions that end with `Option::and_then` or `Result::and_then`, and suggest using
|
||||
/// the `?` operator instead.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
///
|
||||
/// The `and_then` method is used to chain a computation that returns an `Option` or a `Result`.
|
||||
/// This can be replaced with the `?` operator, which is more concise and idiomatic.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use super::utils::get_last_chain_binding_hir_id;
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::paths::CHAR_IS_ASCII;
|
||||
use clippy_utils::source::SpanRangeExt;
|
||||
use clippy_utils::{match_def_path, path_to_local_id, peel_blocks};
|
||||
use clippy_utils::{match_def_path, path_to_local_id, peel_blocks, sym};
|
||||
|
||||
fn peels_expr_ref<'a, 'tcx>(mut expr: &'a Expr<'tcx>) -> &'a Expr<'tcx> {
|
||||
while let ExprKind::AddrOf(_, _, e) = expr.kind {
|
||||
|
|
@ -32,7 +32,7 @@ fn handle_expr(
|
|||
// If we have `!is_ascii`, then only `.any()` should warn. And if the condition is
|
||||
// `is_ascii`, then only `.all()` should warn.
|
||||
if revert != is_all
|
||||
&& method.ident.name.as_str() == "is_ascii"
|
||||
&& method.ident.name == sym::is_ascii
|
||||
&& path_to_local_id(receiver, first_param)
|
||||
&& let char_arg_ty = cx.typeck_results().expr_ty_adjusted(receiver).peel_refs()
|
||||
&& *char_arg_ty.kind() == ty::Char
|
||||
|
|
@ -102,7 +102,7 @@ pub(super) fn check(cx: &LateContext<'_>, call_expr: &Expr<'_>, recv: &Expr<'_>,
|
|||
&& let body = cx.tcx.hir_body(body)
|
||||
&& let Some(first_param) = body.params.first()
|
||||
&& let ExprKind::MethodCall(method, mut recv, [], _) = recv.kind
|
||||
&& method.ident.name.as_str() == "chars"
|
||||
&& method.ident.name == sym::chars
|
||||
&& let str_ty = cx.typeck_results().expr_ty_adjusted(recv).peel_refs()
|
||||
&& *str_ty.kind() == ty::Str
|
||||
{
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use clippy_utils::ty::{
|
|||
};
|
||||
use clippy_utils::{
|
||||
CaptureKind, can_move_expr_to_closure, fn_def_id, get_enclosing_block, higher, is_trait_method, path_to_local,
|
||||
path_to_local_id,
|
||||
path_to_local_id, sym,
|
||||
};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::{Applicability, MultiSpan};
|
||||
|
|
@ -20,8 +20,8 @@ use rustc_hir::{
|
|||
use rustc_lint::LateContext;
|
||||
use rustc_middle::hir::nested_filter;
|
||||
use rustc_middle::ty::{self, AssocTag, ClauseKind, EarlyBinder, GenericArg, GenericArgKind, Ty};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::{Span, sym};
|
||||
|
||||
const NEEDLESS_COLLECT_MSG: &str = "avoid using `collect()` when not needed";
|
||||
|
||||
|
|
@ -339,7 +339,7 @@ impl<'tcx> Visitor<'tcx> for IterFunctionVisitor<'_, 'tcx> {
|
|||
// Check function calls on our collection
|
||||
if let ExprKind::MethodCall(method_name, recv, args, _) = &expr.kind {
|
||||
if args.is_empty()
|
||||
&& method_name.ident.name.as_str() == "collect"
|
||||
&& method_name.ident.name == sym::collect
|
||||
&& is_trait_method(self.cx, expr, sym::Iterator)
|
||||
{
|
||||
self.current_mutably_captured_ids = get_captured_ids(self.cx, self.cx.typeck_results().expr_ty(recv));
|
||||
|
|
|
|||
|
|
@ -1,17 +1,16 @@
|
|||
use std::ops::ControlFlow;
|
||||
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::get_parent_expr;
|
||||
use clippy_utils::source::snippet;
|
||||
use clippy_utils::ty::is_type_diagnostic_item;
|
||||
use clippy_utils::visitors::for_each_local_use_after_expr;
|
||||
use clippy_utils::{get_parent_expr, sym};
|
||||
use rustc_ast::LitKind;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_hir::{BinOpKind, Expr, ExprKind, QPath};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::sym;
|
||||
|
||||
use super::READ_LINE_WITHOUT_TRIM;
|
||||
|
||||
|
|
@ -44,7 +43,7 @@ pub fn check(cx: &LateContext<'_>, call: &Expr<'_>, recv: &Expr<'_>, arg: &Expr<
|
|||
if let Some(parent) = get_parent_expr(cx, expr) {
|
||||
let data = if let ExprKind::MethodCall(segment, recv, args, span) = parent.kind {
|
||||
if args.is_empty()
|
||||
&& segment.ident.name.as_str() == "parse"
|
||||
&& segment.ident.name == sym::parse
|
||||
&& let parse_result_ty = cx.typeck_results().expr_ty(parent)
|
||||
&& is_type_diagnostic_item(cx, parse_result_ty, sym::Result)
|
||||
&& let ty::Adt(_, substs) = parse_result_ty.kind()
|
||||
|
|
@ -58,7 +57,7 @@ pub fn check(cx: &LateContext<'_>, call: &Expr<'_>, recv: &Expr<'_>, arg: &Expr<
|
|||
"calling `.parse()` on a string without trimming the trailing newline character",
|
||||
"checking",
|
||||
))
|
||||
} else if segment.ident.name.as_str() == "ends_with"
|
||||
} else if segment.ident.name == sym::ends_with
|
||||
&& recv.span == expr.span
|
||||
&& let [arg] = args
|
||||
&& expr_is_string_literal_without_trailing_newline(arg)
|
||||
|
|
|
|||
|
|
@ -55,7 +55,6 @@ pub(super) fn check<'tcx>(
|
|||
None => &body_snip,
|
||||
};
|
||||
|
||||
let msg = "use the question mark operator instead of an `and_then` call";
|
||||
let sugg = format!(
|
||||
"let {} = {}?;\n{}",
|
||||
arg_snip,
|
||||
|
|
@ -63,5 +62,13 @@ pub(super) fn check<'tcx>(
|
|||
reindent_multiline(inner, false, indent_of(cx, expr.span))
|
||||
);
|
||||
|
||||
span_lint_and_sugg(cx, RETURN_AND_THEN, expr.span, msg, "try", sugg, applicability);
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
RETURN_AND_THEN,
|
||||
expr.span,
|
||||
"use the `?` operator instead of an `and_then` call",
|
||||
"try",
|
||||
sugg,
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::snippet_with_context;
|
||||
use clippy_utils::sym;
|
||||
use clippy_utils::visitors::is_const_evaluatable;
|
||||
use rustc_ast::ast::LitKind;
|
||||
use rustc_errors::Applicability;
|
||||
|
|
@ -19,7 +20,7 @@ pub(super) fn check<'a>(cx: &LateContext<'a>, expr: &'_ Expr<'_>, split_recv: &'
|
|||
&& !is_const_evaluatable(cx, trim_recv)
|
||||
&& let ExprKind::Lit(split_lit) = split_arg.kind
|
||||
&& (matches!(split_lit.node, LitKind::Char('\n'))
|
||||
|| matches!(split_lit.node, LitKind::Str(sym, _) if (sym.as_str() == "\n" || sym.as_str() == "\r\n")))
|
||||
|| matches!(split_lit.node, LitKind::Str(sym::LF | sym::CRLF, _)))
|
||||
{
|
||||
let mut app = Applicability::MaybeIncorrect;
|
||||
span_lint_and_sugg(
|
||||
|
|
|
|||
|
|
@ -3,13 +3,12 @@ use clippy_utils::diagnostics::span_lint;
|
|||
use clippy_utils::ty::is_copy;
|
||||
use clippy_utils::usage::mutated_variables;
|
||||
use clippy_utils::visitors::{Descend, for_each_expr_without_closures};
|
||||
use clippy_utils::{is_res_lang_ctor, is_trait_method, path_res, path_to_local_id};
|
||||
use clippy_utils::{is_res_lang_ctor, is_trait_method, path_res, path_to_local_id, sym};
|
||||
use core::ops::ControlFlow;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::LangItem::{OptionNone, OptionSome};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty;
|
||||
use rustc_span::sym;
|
||||
|
||||
use super::{UNNECESSARY_FILTER_MAP, UNNECESSARY_FIND_MAP};
|
||||
|
||||
|
|
@ -95,7 +94,7 @@ fn check_expression<'tcx>(cx: &LateContext<'tcx>, arg_id: hir::HirId, expr: &'tc
|
|||
(true, true)
|
||||
},
|
||||
hir::ExprKind::MethodCall(segment, recv, [arg], _) => {
|
||||
if segment.ident.name.as_str() == "then_some"
|
||||
if segment.ident.name == sym::then_some
|
||||
&& cx.typeck_results().expr_ty(recv).is_bool()
|
||||
&& path_to_local_id(arg, arg_id)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use clippy_utils::ty::{get_iterator_item_ty, implements_trait, is_copy, is_type_
|
|||
use clippy_utils::visitors::find_all_ret_expressions;
|
||||
use clippy_utils::{
|
||||
fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, is_expr_temporary_value, peel_middle_ty_refs,
|
||||
return_ty,
|
||||
return_ty, sym,
|
||||
};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
|
|
@ -20,7 +20,7 @@ use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref};
|
|||
use rustc_middle::ty::{
|
||||
self, ClauseKind, GenericArg, GenericArgKind, GenericArgsRef, ParamTy, ProjectionPredicate, TraitPredicate, Ty,
|
||||
};
|
||||
use rustc_span::{Symbol, sym};
|
||||
use rustc_span::Symbol;
|
||||
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
|
||||
use rustc_trait_selection::traits::{Obligation, ObligationCause};
|
||||
|
||||
|
|
@ -312,8 +312,7 @@ fn check_string_from_utf8<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>,
|
|||
/// call of a `to_owned`-like function is unnecessary.
|
||||
fn check_split_call_arg(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symbol, receiver: &Expr<'_>) -> bool {
|
||||
if let Some(parent) = get_parent_expr(cx, expr)
|
||||
&& let Some((fn_name, argument_expr)) = get_fn_name_and_arg(cx, parent)
|
||||
&& fn_name.as_str() == "split"
|
||||
&& let Some((sym::split, argument_expr)) = get_fn_name_and_arg(cx, parent)
|
||||
&& let Some(receiver_snippet) = receiver.span.get_source_text(cx)
|
||||
&& let Some(arg_snippet) = argument_expr.span.get_source_text(cx)
|
||||
{
|
||||
|
|
@ -614,8 +613,7 @@ fn has_lifetime(ty: Ty<'_>) -> bool {
|
|||
|
||||
/// Returns true if the named method is `Iterator::cloned` or `Iterator::copied`.
|
||||
fn is_cloned_or_copied(cx: &LateContext<'_>, method_name: Symbol, method_def_id: DefId) -> bool {
|
||||
(method_name.as_str() == "cloned" || method_name.as_str() == "copied")
|
||||
&& is_diag_trait_item(cx, method_def_id, sym::Iterator)
|
||||
matches!(method_name, sym::cloned | sym::copied) && is_diag_trait_item(cx, method_def_id, sym::Iterator)
|
||||
}
|
||||
|
||||
/// Returns true if the named method can be used to convert the receiver to its "owned"
|
||||
|
|
@ -628,7 +626,7 @@ fn is_to_owned_like<'a>(cx: &LateContext<'a>, call_expr: &Expr<'a>, method_name:
|
|||
|
||||
/// Returns true if the named method is `Cow::into_owned`.
|
||||
fn is_cow_into_owned(cx: &LateContext<'_>, method_name: Symbol, method_def_id: DefId) -> bool {
|
||||
method_name.as_str() == "into_owned" && is_diag_item_method(cx, method_def_id, sym::Cow)
|
||||
method_name == sym::into_owned && is_diag_item_method(cx, method_def_id, sym::Cow)
|
||||
}
|
||||
|
||||
/// Returns true if the named method is `ToString::to_string` and it's called on a type that
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::span_lint;
|
||||
use clippy_utils::is_trait_method;
|
||||
use clippy_utils::{is_trait_method, sym};
|
||||
use rustc_hir::{Expr, ExprKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::declare_lint_pass;
|
||||
use rustc_span::sym;
|
||||
use std::cmp::Ordering::{Equal, Greater, Less};
|
||||
|
||||
declare_clippy_lint! {
|
||||
|
|
@ -79,12 +78,10 @@ fn min_max<'a, 'tcx>(cx: &LateContext<'tcx>, expr: &'a Expr<'a>) -> Option<(MinM
|
|||
},
|
||||
ExprKind::MethodCall(path, receiver, args @ [_], _) => {
|
||||
if cx.typeck_results().expr_ty(receiver).is_floating_point() || is_trait_method(cx, expr, sym::Ord) {
|
||||
if path.ident.name.as_str() == "max" {
|
||||
fetch_const(cx, Some(receiver), args, MinMax::Max)
|
||||
} else if path.ident.name.as_str() == "min" {
|
||||
fetch_const(cx, Some(receiver), args, MinMax::Min)
|
||||
} else {
|
||||
None
|
||||
match path.ident.name {
|
||||
sym::max => fetch_const(cx, Some(receiver), args, MinMax::Max),
|
||||
sym::min => fetch_const(cx, Some(receiver), args, MinMax::Min),
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
None
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
use std::ops::ControlFlow;
|
||||
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::is_path_lang_item;
|
||||
use clippy_utils::ty::is_type_diagnostic_item;
|
||||
use clippy_utils::visitors::{Visitable, for_each_expr};
|
||||
use clippy_utils::{is_path_lang_item, sym};
|
||||
use rustc_ast::LitKind;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
|
|
@ -13,7 +13,7 @@ use rustc_hir::{
|
|||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty::{Ty, TypeckResults};
|
||||
use rustc_session::declare_lint_pass;
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
use rustc_span::{Span, Symbol};
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
|
|
@ -116,7 +116,7 @@ fn should_lint<'tcx>(
|
|||
|
||||
if path.ident.name == sym::debug_struct && is_type_diagnostic_item(cx, recv_ty, sym::Formatter) {
|
||||
has_debug_struct = true;
|
||||
} else if path.ident.name.as_str() == "finish_non_exhaustive"
|
||||
} else if path.ident.name == sym::finish_non_exhaustive
|
||||
&& is_type_diagnostic_item(cx, recv_ty, sym::DebugStruct)
|
||||
{
|
||||
has_finish_non_exhaustive = true;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
|
||||
use clippy_utils::macros::root_macro_call_first_node;
|
||||
use clippy_utils::{get_parent_expr, path_to_local, path_to_local_id};
|
||||
use clippy_utils::{get_parent_expr, path_to_local, path_to_local_id, sym};
|
||||
use rustc_hir::intravisit::{Visitor, walk_expr};
|
||||
use rustc_hir::{BinOpKind, Block, Expr, ExprKind, HirId, LetStmt, Node, Stmt, StmtKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
|
|
@ -136,7 +136,7 @@ impl<'tcx> DivergenceVisitor<'_, 'tcx> {
|
|||
|
||||
fn report_diverging_sub_expr(&mut self, e: &Expr<'_>) {
|
||||
if let Some(macro_call) = root_macro_call_first_node(self.cx, e)
|
||||
&& self.cx.tcx.item_name(macro_call.def_id).as_str() == "todo"
|
||||
&& self.cx.tcx.is_diagnostic_item(sym::todo_macro, macro_call.def_id)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,12 +3,12 @@ use rustc_hir::intravisit::{Visitor, walk_expr};
|
|||
use rustc_hir::{Block, BlockCheckMode, Closure, Expr, ExprKind, Stmt, StmtKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::declare_lint_pass;
|
||||
use rustc_span::{Span, sym};
|
||||
use rustc_span::Span;
|
||||
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::is_trait_method;
|
||||
use clippy_utils::source::snippet_with_applicability;
|
||||
use clippy_utils::ty::has_iter_method;
|
||||
use clippy_utils::{is_trait_method, sym};
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
|
|
@ -64,7 +64,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessForEach {
|
|||
iter_recv.kind,
|
||||
ExprKind::Array(..) | ExprKind::Call(..) | ExprKind::Path(..)
|
||||
)
|
||||
&& method_name.ident.name.as_str() == "for_each"
|
||||
&& method_name.ident.name == sym::for_each
|
||||
&& is_trait_method(cx, expr, sym::Iterator)
|
||||
// Checks the type of the `iter` method receiver is NOT a user defined type.
|
||||
&& has_iter_method(cx, cx.typeck_results().expr_ty(iter_recv)).is_some()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::diagnostics::span_lint_hir_and_then;
|
||||
use clippy_utils::path_res;
|
||||
use clippy_utils::source::snippet;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::{Block, Body, Expr, ExprKind, LangItem, MatchSource, QPath};
|
||||
|
|
@ -9,52 +8,38 @@ use rustc_session::declare_lint_pass;
|
|||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Suggests alternatives for useless applications of `?` in terminating expressions
|
||||
/// Suggests replacing `Ok(x?)` or `Some(x?)` with `x` in return positions where the `?` operator
|
||||
/// is not needed to convert the type of `x`.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// There's no reason to use `?` to short-circuit when execution of the body will end there anyway.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```no_run
|
||||
/// struct TO {
|
||||
/// magic: Option<usize>,
|
||||
/// # use std::num::ParseIntError;
|
||||
/// fn f(s: &str) -> Option<usize> {
|
||||
/// Some(s.find('x')?)
|
||||
/// }
|
||||
///
|
||||
/// fn f(to: TO) -> Option<usize> {
|
||||
/// Some(to.magic?)
|
||||
/// fn g(s: &str) -> Result<usize, ParseIntError> {
|
||||
/// Ok(s.parse()?)
|
||||
/// }
|
||||
///
|
||||
/// struct TR {
|
||||
/// magic: Result<usize, bool>,
|
||||
/// }
|
||||
///
|
||||
/// fn g(tr: Result<TR, bool>) -> Result<usize, bool> {
|
||||
/// tr.and_then(|t| Ok(t.magic?))
|
||||
/// }
|
||||
///
|
||||
/// ```
|
||||
/// Use instead:
|
||||
/// ```no_run
|
||||
/// struct TO {
|
||||
/// magic: Option<usize>,
|
||||
/// # use std::num::ParseIntError;
|
||||
/// fn f(s: &str) -> Option<usize> {
|
||||
/// s.find('x')
|
||||
/// }
|
||||
///
|
||||
/// fn f(to: TO) -> Option<usize> {
|
||||
/// to.magic
|
||||
/// }
|
||||
///
|
||||
/// struct TR {
|
||||
/// magic: Result<usize, bool>,
|
||||
/// }
|
||||
///
|
||||
/// fn g(tr: Result<TR, bool>) -> Result<usize, bool> {
|
||||
/// tr.and_then(|t| t.magic)
|
||||
/// fn g(s: &str) -> Result<usize, ParseIntError> {
|
||||
/// s.parse()
|
||||
/// }
|
||||
/// ```
|
||||
#[clippy::version = "1.51.0"]
|
||||
pub NEEDLESS_QUESTION_MARK,
|
||||
complexity,
|
||||
"Suggest `value.inner_option` instead of `Some(value.inner_option?)`. The same goes for `Result<T, E>`."
|
||||
"using `Ok(x?)` or `Some(x?)` where `x` would be equivalent"
|
||||
}
|
||||
|
||||
declare_lint_pass!(NeedlessQuestionMark => [NEEDLESS_QUESTION_MARK]);
|
||||
|
|
@ -111,10 +96,10 @@ fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
|
|||
if let ExprKind::Call(path, [arg]) = expr.kind
|
||||
&& let Res::Def(DefKind::Ctor(..), ctor_id) = path_res(cx, path)
|
||||
&& let Some(variant_id) = cx.tcx.opt_parent(ctor_id)
|
||||
&& let sugg_remove = if cx.tcx.lang_items().option_some_variant() == Some(variant_id) {
|
||||
"Some()"
|
||||
&& let variant = if cx.tcx.lang_items().option_some_variant() == Some(variant_id) {
|
||||
"Some"
|
||||
} else if cx.tcx.lang_items().result_ok_variant() == Some(variant_id) {
|
||||
"Ok()"
|
||||
"Ok"
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
|
@ -126,14 +111,25 @@ fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
|
|||
&& let inner_ty = cx.typeck_results().expr_ty(inner_expr)
|
||||
&& expr_ty == inner_ty
|
||||
{
|
||||
span_lint_and_sugg(
|
||||
span_lint_hir_and_then(
|
||||
cx,
|
||||
NEEDLESS_QUESTION_MARK,
|
||||
expr.hir_id,
|
||||
expr.span,
|
||||
"question mark operator is useless here",
|
||||
format!("try removing question mark and `{sugg_remove}`"),
|
||||
format!("{}", snippet(cx, inner_expr.span, r#""...""#)),
|
||||
Applicability::MachineApplicable,
|
||||
format!("enclosing `{variant}` and `?` operator are unneeded"),
|
||||
|diag| {
|
||||
diag.multipart_suggestion(
|
||||
format!("remove the enclosing `{variant}` and `?` operator"),
|
||||
vec![
|
||||
(expr.span.until(inner_expr.span), String::new()),
|
||||
(
|
||||
inner_expr.span.shrink_to_hi().to(expr.span.shrink_to_hi()),
|
||||
String::new(),
|
||||
),
|
||||
],
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::{SpanRangeExt, snippet_with_applicability};
|
||||
use clippy_utils::sym;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Expr, ExprKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::declare_lint_pass;
|
||||
use rustc_span::sym;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
|
|
@ -43,12 +43,12 @@ impl<'tcx> LateLintPass<'tcx> for NonOctalUnixPermissions {
|
|||
match &expr.kind {
|
||||
ExprKind::MethodCall(path, func, [param], _) => {
|
||||
if let Some(adt) = cx.typeck_results().expr_ty(func).peel_refs().ty_adt_def()
|
||||
&& ((path.ident.name.as_str() == "mode"
|
||||
&& ((path.ident.name == sym::mode
|
||||
&& matches!(
|
||||
cx.tcx.get_diagnostic_name(adt.did()),
|
||||
Some(sym::FsOpenOptions | sym::DirBuilder)
|
||||
))
|
||||
|| (path.ident.name.as_str() == "set_mode"
|
||||
|| (path.ident.name == sym::set_mode
|
||||
&& cx.tcx.is_diagnostic_item(sym::FsPermissions, adt.did())))
|
||||
&& let ExprKind::Lit(_) = param.kind
|
||||
&& param.span.eq_ctxt(expr.span)
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::snippet;
|
||||
use clippy_utils::sym;
|
||||
use rustc_ast::ast::BinOpKind;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Expr, ExprKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_session::declare_lint_pass;
|
||||
use rustc_span::symbol::sym;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
|
|
@ -72,7 +72,7 @@ fn check_non_zero_conversion(cx: &LateContext<'_>, expr: &Expr<'_>, applicabilit
|
|||
&& let ExprKind::Path(qpath) = &func.kind
|
||||
&& let Some(def_id) = cx.qpath_res(qpath, func.hir_id).opt_def_id()
|
||||
&& let ExprKind::MethodCall(rcv_path, receiver, [], _) = &arg.kind
|
||||
&& rcv_path.ident.name.as_str() == "get"
|
||||
&& rcv_path.ident.name == sym::get
|
||||
{
|
||||
let fn_name = cx.tcx.item_name(def_id);
|
||||
let target_ty = cx.typeck_results().expr_ty(expr);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::get_item_name;
|
||||
use clippy_utils::sugg::Sugg;
|
||||
use clippy_utils::{parent_item_name, sym};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
|
||||
use rustc_lint::LateContext;
|
||||
|
|
@ -34,7 +34,7 @@ pub(crate) fn check<'tcx>(
|
|||
return;
|
||||
}
|
||||
|
||||
if let Some(name) = get_item_name(cx, expr) {
|
||||
if let Some(name) = parent_item_name(cx, expr) {
|
||||
let name = name.as_str();
|
||||
if name == "eq" || name == "ne" || name == "is_nan" || name.starts_with("eq_") || name.ends_with("_eq") {
|
||||
return;
|
||||
|
|
@ -106,7 +106,7 @@ fn is_signum(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
|||
}
|
||||
|
||||
if let ExprKind::MethodCall(method_name, self_arg, [], _) = expr.kind
|
||||
&& method_name.ident.name.as_str() == "signum"
|
||||
&& method_name.ident.name == sym::signum
|
||||
// Check that the receiver of the signum() is a float (expressions[0] is the receiver of
|
||||
// the method call)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::sym;
|
||||
use clippy_utils::ty::is_type_diagnostic_item;
|
||||
use rustc_ast::ast::LitKind;
|
||||
use rustc_hir::{Expr, ExprKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::declare_lint_pass;
|
||||
use rustc_span::sym;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
|
|
@ -33,7 +33,7 @@ impl<'tcx> LateLintPass<'tcx> for PermissionsSetReadonlyFalse {
|
|||
if let ExprKind::MethodCall(path, receiver, [arg], _) = &expr.kind
|
||||
&& let ExprKind::Lit(lit) = &arg.kind
|
||||
&& LitKind::Bool(false) == lit.node
|
||||
&& path.ident.name.as_str() == "set_readonly"
|
||||
&& path.ident.name == sym::set_readonly
|
||||
&& is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(receiver), sym::FsPermissions)
|
||||
{
|
||||
span_lint_and_then(
|
||||
|
|
|
|||
|
|
@ -743,9 +743,9 @@ fn check_ptr_eq<'tcx>(
|
|||
}
|
||||
|
||||
// Remove one level of usize conversion if any
|
||||
let (left, right) = match (expr_as_cast_to_usize(cx, left), expr_as_cast_to_usize(cx, right)) {
|
||||
(Some(lhs), Some(rhs)) => (lhs, rhs),
|
||||
_ => (left, right),
|
||||
let (left, right, usize_peeled) = match (expr_as_cast_to_usize(cx, left), expr_as_cast_to_usize(cx, right)) {
|
||||
(Some(lhs), Some(rhs)) => (lhs, rhs, true),
|
||||
_ => (left, right, false),
|
||||
};
|
||||
|
||||
// This lint concerns raw pointers
|
||||
|
|
@ -754,7 +754,12 @@ fn check_ptr_eq<'tcx>(
|
|||
return;
|
||||
}
|
||||
|
||||
let (left_var, right_var) = (peel_raw_casts(cx, left, left_ty), peel_raw_casts(cx, right, right_ty));
|
||||
let ((left_var, left_casts_peeled), (right_var, right_casts_peeled)) =
|
||||
(peel_raw_casts(cx, left, left_ty), peel_raw_casts(cx, right, right_ty));
|
||||
|
||||
if !(usize_peeled || left_casts_peeled || right_casts_peeled) {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut app = Applicability::MachineApplicable;
|
||||
let left_snip = Sugg::hir_with_context(cx, left_var, expr.span.ctxt(), "_", &mut app);
|
||||
|
|
@ -787,8 +792,9 @@ fn expr_as_cast_to_usize<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>
|
|||
}
|
||||
}
|
||||
|
||||
// Peel raw casts if the remaining expression can be coerced to it
|
||||
fn peel_raw_casts<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, expr_ty: Ty<'tcx>) -> &'tcx Expr<'tcx> {
|
||||
// Peel raw casts if the remaining expression can be coerced to it, and whether casts have been
|
||||
// peeled or not.
|
||||
fn peel_raw_casts<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, expr_ty: Ty<'tcx>) -> (&'tcx Expr<'tcx>, bool) {
|
||||
if !expr.span.from_expansion()
|
||||
&& let ExprKind::Cast(inner, _) = expr.kind
|
||||
&& let ty::RawPtr(target_ty, _) = expr_ty.kind()
|
||||
|
|
@ -796,8 +802,8 @@ fn peel_raw_casts<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, expr_ty:
|
|||
&& let ty::RawPtr(inner_target_ty, _) | ty::Ref(_, inner_target_ty, _) = inner_ty.kind()
|
||||
&& target_ty == inner_target_ty
|
||||
{
|
||||
peel_raw_casts(cx, inner, inner_ty)
|
||||
(peel_raw_casts(cx, inner, inner_ty).0, true)
|
||||
} else {
|
||||
expr
|
||||
(expr, false)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
|
||||
use clippy_utils::source::SpanRangeExt;
|
||||
use clippy_utils::sym;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Expr, ExprKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::declare_lint_pass;
|
||||
use rustc_span::sym;
|
||||
use std::fmt;
|
||||
|
||||
declare_clippy_lint! {
|
||||
|
|
@ -97,7 +97,7 @@ fn expr_as_ptr_offset_call<'tcx>(
|
|||
if path_segment.ident.name == sym::offset {
|
||||
return Some((arg_0, arg_1, Method::Offset));
|
||||
}
|
||||
if path_segment.ident.name.as_str() == "wrapping_offset" {
|
||||
if path_segment.ident.name == sym::wrapping_offset {
|
||||
return Some((arg_0, arg_1, Method::WrappingOffset));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
|
|||
use clippy_utils::{
|
||||
eq_expr_value, higher, is_else_clause, is_in_const_context, is_lint_allowed, is_path_lang_item, is_res_lang_ctor,
|
||||
pat_and_expr_can_be_question_mark, path_res, path_to_local, path_to_local_id, peel_blocks, peel_blocks_with_stmt,
|
||||
span_contains_cfg, span_contains_comment,
|
||||
span_contains_cfg, span_contains_comment, sym,
|
||||
};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::LangItem::{self, OptionNone, OptionSome, ResultErr, ResultOk};
|
||||
|
|
@ -22,15 +22,14 @@ use rustc_hir::{
|
|||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_session::impl_lint_pass;
|
||||
use rustc_span::sym;
|
||||
use rustc_span::symbol::Symbol;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Checks for expressions that could be replaced by the question mark operator.
|
||||
/// Checks for expressions that could be replaced by the `?` operator.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// Question mark usage is more idiomatic.
|
||||
/// Using the `?` operator is shorter and more idiomatic.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```ignore
|
||||
|
|
@ -47,7 +46,7 @@ declare_clippy_lint! {
|
|||
#[clippy::version = "pre 1.29.0"]
|
||||
pub QUESTION_MARK,
|
||||
style,
|
||||
"checks for expressions that could be replaced by the question mark operator"
|
||||
"checks for expressions that could be replaced by the `?` operator"
|
||||
}
|
||||
|
||||
pub struct QuestionMark {
|
||||
|
|
@ -207,8 +206,8 @@ fn is_early_return(smbl: Symbol, cx: &LateContext<'_>, if_block: &IfBlockType<'_
|
|||
is_type_diagnostic_item(cx, caller_ty, smbl)
|
||||
&& expr_return_none_or_err(smbl, cx, if_then, caller, None)
|
||||
&& match smbl {
|
||||
sym::Option => call_sym.as_str() == "is_none",
|
||||
sym::Result => call_sym.as_str() == "is_err",
|
||||
sym::Option => call_sym == sym::is_none,
|
||||
sym::Result => call_sym == sym::is_err,
|
||||
_ => false,
|
||||
}
|
||||
},
|
||||
|
|
@ -280,7 +279,7 @@ fn expr_return_none_or_err(
|
|||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// If it matches, it will suggest to use the question mark operator instead
|
||||
/// If it matches, it will suggest to use the `?` operator instead
|
||||
fn check_is_none_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
|
||||
if let Some(higher::If { cond, then, r#else }) = higher::If::hir(expr)
|
||||
&& !is_else_clause(cx.tcx, expr)
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@ use rustc_session::declare_lint_pass;
|
|||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Checks for expressions that use the question mark operator and rejects them.
|
||||
/// Checks for expressions that use the `?` operator and rejects them.
|
||||
///
|
||||
/// ### Why restrict this?
|
||||
/// Sometimes code wants to avoid the question mark operator because for instance a local
|
||||
/// Sometimes code wants to avoid the `?` operator because for instance a local
|
||||
/// block requires a macro to re-throw errors to attach additional information to the
|
||||
/// error.
|
||||
///
|
||||
|
|
@ -27,7 +27,7 @@ declare_clippy_lint! {
|
|||
#[clippy::version = "1.69.0"]
|
||||
pub QUESTION_MARK_USED,
|
||||
restriction,
|
||||
"complains if the question mark operator is used"
|
||||
"checks if the `?` operator is used"
|
||||
}
|
||||
|
||||
declare_lint_pass!(QuestionMarkUsed => [QUESTION_MARK_USED]);
|
||||
|
|
@ -40,15 +40,9 @@ impl<'tcx> LateLintPass<'tcx> for QuestionMarkUsed {
|
|||
}
|
||||
|
||||
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
QUESTION_MARK_USED,
|
||||
expr.span,
|
||||
"question mark operator was used",
|
||||
|diag| {
|
||||
diag.help("consider using a custom macro or match expression");
|
||||
},
|
||||
);
|
||||
span_lint_and_then(cx, QUESTION_MARK_USED, expr.span, "the `?` operator was used", |diag| {
|
||||
diag.help("consider using a custom macro or match expression");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,14 +3,13 @@ use clippy_utils::macros::matching_root_macro_call;
|
|||
use clippy_utils::sugg::Sugg;
|
||||
use clippy_utils::{
|
||||
SpanlessEq, get_enclosing_block, is_integer_literal, is_path_diagnostic_item, path_to_local, path_to_local_id,
|
||||
span_contains_comment,
|
||||
span_contains_comment, sym,
|
||||
};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::intravisit::{Visitor, walk_block, walk_expr, walk_stmt};
|
||||
use rustc_hir::{BindingMode, Block, Expr, ExprKind, HirId, PatKind, Stmt, StmtKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::declare_lint_pass;
|
||||
use rustc_span::symbol::sym;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
|
|
@ -248,7 +247,7 @@ impl<'tcx> VectorInitializationVisitor<'_, 'tcx> {
|
|||
if self.initialization_found
|
||||
&& let ExprKind::MethodCall(path, self_arg, [extend_arg], _) = expr.kind
|
||||
&& path_to_local_id(self_arg, self.vec_alloc.local_id)
|
||||
&& path.ident.name.as_str() == "extend"
|
||||
&& path.ident.name == sym::extend
|
||||
&& self.is_repeat_take(extend_arg)
|
||||
{
|
||||
self.slow_expression = Some(InitializationType::Extend(expr));
|
||||
|
|
@ -260,7 +259,7 @@ impl<'tcx> VectorInitializationVisitor<'_, 'tcx> {
|
|||
if self.initialization_found
|
||||
&& let ExprKind::MethodCall(path, self_arg, [len_arg, fill_arg], _) = expr.kind
|
||||
&& path_to_local_id(self_arg, self.vec_alloc.local_id)
|
||||
&& path.ident.name.as_str() == "resize"
|
||||
&& path.ident.name == sym::resize
|
||||
// Check that is filled with 0
|
||||
&& is_integer_literal(fill_arg, 0)
|
||||
{
|
||||
|
|
@ -282,7 +281,7 @@ impl<'tcx> VectorInitializationVisitor<'_, 'tcx> {
|
|||
/// Returns `true` if give expression is `repeat(0).take(...)`
|
||||
fn is_repeat_take(&mut self, expr: &'tcx Expr<'tcx>) -> bool {
|
||||
if let ExprKind::MethodCall(take_path, recv, [len_arg], _) = expr.kind
|
||||
&& take_path.ident.name.as_str() == "take"
|
||||
&& take_path.ident.name == sym::take
|
||||
// Check that take is applied to `repeat(0)`
|
||||
&& self.is_repeat_zero(recv)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -286,7 +286,7 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes {
|
|||
|
||||
if !e.span.in_external_macro(cx.sess().source_map())
|
||||
&& let ExprKind::MethodCall(path, receiver, ..) = &e.kind
|
||||
&& path.ident.name.as_str() == "as_bytes"
|
||||
&& path.ident.name == sym::as_bytes
|
||||
&& let ExprKind::Lit(lit) = &receiver.kind
|
||||
&& let LitKind::Str(lit_content, _) = &lit.node
|
||||
{
|
||||
|
|
@ -332,7 +332,7 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes {
|
|||
}
|
||||
|
||||
if let ExprKind::MethodCall(path, recv, [], _) = &e.kind
|
||||
&& path.ident.name.as_str() == "into_bytes"
|
||||
&& path.ident.name == sym::into_bytes
|
||||
&& let ExprKind::MethodCall(path, recv, [], _) = &recv.kind
|
||||
&& matches!(path.ident.name.as_str(), "to_owned" | "to_string")
|
||||
&& let ExprKind::Lit(lit) = &recv.kind
|
||||
|
|
@ -556,7 +556,7 @@ impl<'tcx> LateLintPass<'tcx> for TrimSplitWhitespace {
|
|||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
|
||||
let tyckres = cx.typeck_results();
|
||||
if let ExprKind::MethodCall(path, split_recv, [], split_ws_span) = expr.kind
|
||||
&& path.ident.name.as_str() == "split_whitespace"
|
||||
&& path.ident.name == sym::split_whitespace
|
||||
&& let Some(split_ws_def_id) = tyckres.type_dependent_def_id(expr.hir_id)
|
||||
&& cx.tcx.is_diagnostic_item(sym::str_split_whitespace, split_ws_def_id)
|
||||
&& let ExprKind::MethodCall(path, _trim_recv, [], trim_span) = split_recv.kind
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::match_def_path;
|
||||
use clippy_utils::source::snippet_with_applicability;
|
||||
use clippy_utils::{match_def_path, sym};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
|
|
@ -38,11 +38,11 @@ declare_lint_pass!(ToDigitIsSome => [TO_DIGIT_IS_SOME]);
|
|||
impl<'tcx> LateLintPass<'tcx> for ToDigitIsSome {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
|
||||
if let hir::ExprKind::MethodCall(is_some_path, to_digit_expr, [], _) = &expr.kind
|
||||
&& is_some_path.ident.name.as_str() == "is_some"
|
||||
&& is_some_path.ident.name == sym::is_some
|
||||
{
|
||||
let match_result = match &to_digit_expr.kind {
|
||||
hir::ExprKind::MethodCall(to_digits_path, char_arg, [radix_arg], _) => {
|
||||
if to_digits_path.ident.name.as_str() == "to_digit"
|
||||
if to_digits_path.ident.name == sym::to_digit
|
||||
&& let char_arg_ty = cx.typeck_results().expr_ty_adjusted(char_arg)
|
||||
&& *char_arg_ty.kind() == ty::Char
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::ty::is_normalizable;
|
||||
use clippy_utils::{eq_expr_value, path_to_local};
|
||||
use clippy_utils::{eq_expr_value, path_to_local, sym};
|
||||
use rustc_abi::WrappingRange;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Expr, ExprKind, Node};
|
||||
|
|
@ -43,7 +43,7 @@ fn binops_with_local(cx: &LateContext<'_>, local_expr: &Expr<'_>, expr: &Expr<'_
|
|||
binops_with_local(cx, local_expr, lhs) || binops_with_local(cx, local_expr, rhs)
|
||||
},
|
||||
ExprKind::MethodCall(path, receiver, [arg], _)
|
||||
if path.ident.name.as_str() == "contains"
|
||||
if path.ident.name == sym::contains
|
||||
// ... `contains` called on some kind of range
|
||||
&& let Some(receiver_adt) = cx.typeck_results().expr_ty(receiver).peel_refs().ty_adt_def()
|
||||
&& let lang_items = cx.tcx.lang_items()
|
||||
|
|
@ -81,7 +81,7 @@ pub(super) fn check<'tcx>(
|
|||
if let Some(then_some_call) = peel_parent_unsafe_blocks(cx, expr)
|
||||
&& let ExprKind::MethodCall(path, receiver, [arg], _) = then_some_call.kind
|
||||
&& cx.typeck_results().expr_ty(receiver).is_bool()
|
||||
&& path.ident.name.as_str() == "then_some"
|
||||
&& path.ident.name == sym::then_some
|
||||
&& is_local_with_projections(transmutable)
|
||||
&& binops_with_local(cx, transmutable, receiver)
|
||||
&& is_normalizable(cx, cx.param_env, from_ty)
|
||||
|
|
|
|||
|
|
@ -19,61 +19,58 @@ pub(super) fn check<'tcx>(
|
|||
def_id: DefId,
|
||||
box_size_threshold: u64,
|
||||
) -> bool {
|
||||
if cx.tcx.is_diagnostic_item(sym::Vec, def_id) {
|
||||
if let Some(last) = last_path_segment(qpath).args
|
||||
// Get the _ part of Vec<_>
|
||||
&& let Some(GenericArg::Type(ty)) = last.args.first()
|
||||
// extract allocator from the Vec for later
|
||||
&& let vec_alloc_ty = last.args.get(1)
|
||||
// ty is now _ at this point
|
||||
&& let TyKind::Path(ref ty_qpath) = ty.kind
|
||||
&& let res = cx.qpath_res(ty_qpath, ty.hir_id)
|
||||
&& let Some(def_id) = res.opt_def_id()
|
||||
&& Some(def_id) == cx.tcx.lang_items().owned_box()
|
||||
// At this point, we know ty is Box<T>, now get T
|
||||
&& let Some(last) = last_path_segment(ty_qpath).args
|
||||
&& let Some(GenericArg::Type(boxed_ty)) = last.args.first()
|
||||
// extract allocator from the Box for later
|
||||
&& let boxed_alloc_ty = last.args.get(1)
|
||||
// we don't expect to encounter `_` here so ignore `GenericArg::Infer` is okay
|
||||
&& let ty_ty = lower_ty(cx.tcx, boxed_ty.as_unambig_ty())
|
||||
&& !ty_ty.has_escaping_bound_vars()
|
||||
&& ty_ty.is_sized(cx.tcx, cx.typing_env())
|
||||
&& let Ok(ty_ty_size) = cx.layout_of(ty_ty).map(|l| l.size.bytes())
|
||||
&& ty_ty_size < box_size_threshold
|
||||
// https://github.com/rust-lang/rust-clippy/issues/7114
|
||||
&& match (vec_alloc_ty, boxed_alloc_ty) {
|
||||
(None, None) => true,
|
||||
// this is in the event that we have something like
|
||||
// Vec<_, Global>, in which case is equivalent to
|
||||
// Vec<_>
|
||||
(None, Some(GenericArg::Type(inner))) | (Some(GenericArg::Type(inner)), None) => {
|
||||
if let TyKind::Path(path) = inner.kind
|
||||
&& let Some(did) = cx.qpath_res(&path, inner.hir_id).opt_def_id() {
|
||||
cx.tcx.lang_items().get(LangItem::GlobalAlloc) == Some(did)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
},
|
||||
(Some(GenericArg::Type(l)), Some(GenericArg::Type(r))) =>
|
||||
// we don't expect to encounter `_` here so ignore `GenericArg::Infer` is okay
|
||||
lower_ty(cx.tcx, l.as_unambig_ty()) == lower_ty(cx.tcx, r.as_unambig_ty()),
|
||||
_ => false
|
||||
}
|
||||
{
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
VEC_BOX,
|
||||
hir_ty.span,
|
||||
"`Vec<T>` is already on the heap, the boxing is unnecessary",
|
||||
"try",
|
||||
format!("Vec<{}>", snippet(cx, boxed_ty.span, "..")),
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
if cx.tcx.is_diagnostic_item(sym::Vec, def_id)
|
||||
&& let Some(last) = last_path_segment(qpath).args
|
||||
// Get the _ part of Vec<_>
|
||||
&& let Some(GenericArg::Type(ty)) = last.args.first()
|
||||
// extract allocator from the Vec for later
|
||||
&& let vec_alloc_ty = last.args.get(1)
|
||||
// ty is now _ at this point
|
||||
&& let TyKind::Path(ref ty_qpath) = ty.kind
|
||||
&& let res = cx.qpath_res(ty_qpath, ty.hir_id)
|
||||
&& let Some(def_id) = res.opt_def_id()
|
||||
&& Some(def_id) == cx.tcx.lang_items().owned_box()
|
||||
// At this point, we know ty is Box<T>, now get T
|
||||
&& let Some(last) = last_path_segment(ty_qpath).args
|
||||
&& let Some(GenericArg::Type(boxed_ty)) = last.args.first()
|
||||
// extract allocator from the Box for later
|
||||
&& let boxed_alloc_ty = last.args.get(1)
|
||||
// we don't expect to encounter `_` here so ignore `GenericArg::Infer` is okay
|
||||
&& let ty_ty = lower_ty(cx.tcx, boxed_ty.as_unambig_ty())
|
||||
&& !ty_ty.has_escaping_bound_vars()
|
||||
&& ty_ty.is_sized(cx.tcx, cx.typing_env())
|
||||
&& let Ok(ty_ty_size) = cx.layout_of(ty_ty).map(|l| l.size.bytes())
|
||||
&& ty_ty_size < box_size_threshold
|
||||
// https://github.com/rust-lang/rust-clippy/issues/7114
|
||||
&& match (vec_alloc_ty, boxed_alloc_ty) {
|
||||
(None, None) => true,
|
||||
// this is in the event that we have something like
|
||||
// Vec<_, Global>, in which case is equivalent to
|
||||
// Vec<_>
|
||||
(None, Some(GenericArg::Type(inner))) | (Some(GenericArg::Type(inner)), None) => {
|
||||
if let TyKind::Path(path) = inner.kind
|
||||
&& let Some(did) = cx.qpath_res(&path, inner.hir_id).opt_def_id() {
|
||||
cx.tcx.lang_items().get(LangItem::GlobalAlloc) == Some(did)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
},
|
||||
(Some(GenericArg::Type(l)), Some(GenericArg::Type(r))) =>
|
||||
// we don't expect to encounter `_` here so ignore `GenericArg::Infer` is okay
|
||||
lower_ty(cx.tcx, l.as_unambig_ty()) == lower_ty(cx.tcx, r.as_unambig_ty()),
|
||||
_ => false
|
||||
}
|
||||
{
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
VEC_BOX,
|
||||
hir_ty.span,
|
||||
"`Vec<T>` is already on the heap, the boxing is unnecessary",
|
||||
"try",
|
||||
format!("Vec<{}>", snippet(cx, boxed_ty.span, "..")),
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
|
||||
use clippy_utils::higher::{VecInitKind, get_vec_init_kind};
|
||||
use clippy_utils::ty::{is_type_diagnostic_item, is_uninit_value_valid_for_ty};
|
||||
use clippy_utils::{SpanlessEq, is_integer_literal, is_lint_allowed, path_to_local_id, peel_hir_expr_while};
|
||||
use clippy_utils::{SpanlessEq, is_integer_literal, is_lint_allowed, path_to_local_id, peel_hir_expr_while, sym};
|
||||
use rustc_hir::{Block, Expr, ExprKind, HirId, PatKind, PathSegment, Stmt, StmtKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty;
|
||||
use rustc_session::declare_lint_pass;
|
||||
use rustc_span::{Span, sym};
|
||||
use rustc_span::Span;
|
||||
|
||||
// TODO: add `ReadBuf` (RFC 2930) in "How to fix" once it is available in std
|
||||
declare_clippy_lint! {
|
||||
|
|
@ -187,7 +187,7 @@ fn extract_init_or_reserve_target<'tcx>(cx: &LateContext<'tcx>, stmt: &'tcx Stmt
|
|||
|
||||
fn is_reserve(cx: &LateContext<'_>, path: &PathSegment<'_>, self_expr: &Expr<'_>) -> bool {
|
||||
is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(self_expr).peel_refs(), sym::Vec)
|
||||
&& path.ident.name.as_str() == "reserve"
|
||||
&& path.ident.name == sym::reserve
|
||||
}
|
||||
|
||||
/// Returns self if the expression is `Vec::set_len()`
|
||||
|
|
@ -209,7 +209,7 @@ fn extract_set_len_self<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Opt
|
|||
ExprKind::MethodCall(path, self_expr, [arg], _) => {
|
||||
let self_type = cx.typeck_results().expr_ty(self_expr).peel_refs();
|
||||
if is_type_diagnostic_item(cx, self_type, sym::Vec)
|
||||
&& path.ident.name.as_str() == "set_len"
|
||||
&& path.ident.name == sym::set_len
|
||||
&& !is_integer_literal(arg, 0)
|
||||
{
|
||||
Some((self_expr, expr.span))
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use clippy_config::Conf;
|
||||
use clippy_utils::diagnostics::span_lint_and_help;
|
||||
use clippy_utils::macros::root_macro_call_first_node;
|
||||
use clippy_utils::sym;
|
||||
use clippy_utils::visitors::is_local_used;
|
||||
use rustc_hir::{Body, Impl, ImplItem, ImplItemKind, ItemKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
|
|
@ -61,12 +62,10 @@ impl<'tcx> LateLintPass<'tcx> for UnusedSelf {
|
|||
let assoc_item = cx.tcx.associated_item(impl_item.owner_id);
|
||||
let contains_todo = |cx, body: &'_ Body<'_>| -> bool {
|
||||
clippy_utils::visitors::for_each_expr_without_closures(body.value, |e| {
|
||||
if let Some(macro_call) = root_macro_call_first_node(cx, e) {
|
||||
if cx.tcx.item_name(macro_call.def_id).as_str() == "todo" {
|
||||
ControlFlow::Break(())
|
||||
} else {
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
if let Some(macro_call) = root_macro_call_first_node(cx, e)
|
||||
&& cx.tcx.is_diagnostic_item(sym::todo_macro, macro_call.def_id)
|
||||
{
|
||||
ControlFlow::Break(())
|
||||
} else {
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,18 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::{SpanRangeExt, position_before_rarrow};
|
||||
use rustc_ast::visit::FnKind;
|
||||
use rustc_ast::{ClosureBinder, ast};
|
||||
use clippy_utils::{is_never_expr, is_unit_expr};
|
||||
use rustc_ast::{Block, StmtKind};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass};
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::intravisit::FnKind;
|
||||
use rustc_hir::{
|
||||
AssocItemConstraintKind, Body, Expr, ExprKind, FnDecl, FnRetTy, GenericArgsParentheses, Node, PolyTraitRef, Term,
|
||||
Ty, TyKind,
|
||||
};
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
|
||||
use rustc_session::declare_lint_pass;
|
||||
use rustc_span::{BytePos, Span};
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::{BytePos, Span, sym};
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
|
|
@ -34,27 +41,89 @@ declare_clippy_lint! {
|
|||
|
||||
declare_lint_pass!(UnusedUnit => [UNUSED_UNIT]);
|
||||
|
||||
impl EarlyLintPass for UnusedUnit {
|
||||
fn check_fn(&mut self, cx: &EarlyContext<'_>, kind: FnKind<'_>, span: Span, _: ast::NodeId) {
|
||||
if let ast::FnRetTy::Ty(ref ty) = kind.decl().output
|
||||
&& let ast::TyKind::Tup(ref vals) = ty.kind
|
||||
&& vals.is_empty()
|
||||
&& !ty.span.from_expansion()
|
||||
&& get_def(span) == get_def(ty.span)
|
||||
impl<'tcx> LateLintPass<'tcx> for UnusedUnit {
|
||||
fn check_fn(
|
||||
&mut self,
|
||||
cx: &LateContext<'tcx>,
|
||||
kind: FnKind<'tcx>,
|
||||
decl: &'tcx FnDecl<'tcx>,
|
||||
body: &'tcx Body<'tcx>,
|
||||
span: Span,
|
||||
def_id: LocalDefId,
|
||||
) {
|
||||
if let FnRetTy::Return(hir_ty) = decl.output
|
||||
&& is_unit_ty(hir_ty)
|
||||
&& !hir_ty.span.from_expansion()
|
||||
&& get_def(span) == get_def(hir_ty.span)
|
||||
{
|
||||
// implicit types in closure signatures are forbidden when `for<...>` is present
|
||||
if let FnKind::Closure(&ClosureBinder::For { .. }, ..) = kind {
|
||||
if let FnKind::Closure = kind
|
||||
&& let Node::Expr(expr) = cx.tcx.hir_node_by_def_id(def_id)
|
||||
&& let ExprKind::Closure(closure) = expr.kind
|
||||
&& !closure.bound_generic_params.is_empty()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lint_unneeded_unit_return(cx, ty, span);
|
||||
// unit never type fallback is no longer supported since Rust 2024. For more information,
|
||||
// see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
|
||||
if cx.tcx.sess.edition() >= Edition::Edition2024
|
||||
&& let ExprKind::Block(block, _) = body.value.kind
|
||||
&& let Some(expr) = block.expr
|
||||
&& is_never_expr(cx, expr).is_some()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lint_unneeded_unit_return(cx, hir_ty.span, span);
|
||||
}
|
||||
}
|
||||
|
||||
fn check_block(&mut self, cx: &EarlyContext<'_>, block: &ast::Block) {
|
||||
if let Some(stmt) = block.stmts.last()
|
||||
&& let ast::StmtKind::Expr(ref expr) = stmt.kind
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
|
||||
if let ExprKind::Ret(Some(expr)) | ExprKind::Break(_, Some(expr)) = expr.kind
|
||||
&& is_unit_expr(expr)
|
||||
&& !expr.span.from_expansion()
|
||||
{
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
UNUSED_UNIT,
|
||||
expr.span,
|
||||
"unneeded `()`",
|
||||
"remove the `()`",
|
||||
String::new(),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn check_poly_trait_ref(&mut self, cx: &LateContext<'tcx>, poly: &'tcx PolyTraitRef<'tcx>) {
|
||||
let segments = &poly.trait_ref.path.segments;
|
||||
|
||||
if segments.len() == 1
|
||||
&& ["Fn", "FnMut", "FnOnce"].contains(&segments[0].ident.name.as_str())
|
||||
&& let Some(args) = segments[0].args
|
||||
&& args.parenthesized == GenericArgsParentheses::ParenSugar
|
||||
&& let constraints = &args.constraints
|
||||
&& constraints.len() == 1
|
||||
&& constraints[0].ident.name == sym::Output
|
||||
&& let AssocItemConstraintKind::Equality { term: Term::Ty(hir_ty) } = constraints[0].kind
|
||||
&& args.span_ext.hi() != poly.span.hi()
|
||||
&& !hir_ty.span.from_expansion()
|
||||
&& is_unit_ty(hir_ty)
|
||||
{
|
||||
lint_unneeded_unit_return(cx, hir_ty.span, poly.span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl EarlyLintPass for UnusedUnit {
|
||||
/// Check for unit expressions in blocks. This is left in the early pass because some macros
|
||||
/// expand its inputs as-is, making it invisible to the late pass. See #4076.
|
||||
fn check_block(&mut self, cx: &EarlyContext<'_>, block: &Block) {
|
||||
if let Some(stmt) = block.stmts.last()
|
||||
&& let StmtKind::Expr(expr) = &stmt.kind
|
||||
&& let rustc_ast::ExprKind::Tup(inner) = &expr.kind
|
||||
&& inner.is_empty()
|
||||
&& let ctxt = block.span.ctxt()
|
||||
&& stmt.span.ctxt() == ctxt
|
||||
&& expr.span.ctxt() == ctxt
|
||||
|
|
@ -72,39 +141,10 @@ impl EarlyLintPass for UnusedUnit {
|
|||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
|
||||
match e.kind {
|
||||
ast::ExprKind::Ret(Some(ref expr)) | ast::ExprKind::Break(_, Some(ref expr)) => {
|
||||
if is_unit_expr(expr) && !expr.span.from_expansion() {
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
UNUSED_UNIT,
|
||||
expr.span,
|
||||
"unneeded `()`",
|
||||
"remove the `()`",
|
||||
String::new(),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn check_poly_trait_ref(&mut self, cx: &EarlyContext<'_>, poly: &ast::PolyTraitRef) {
|
||||
let segments = &poly.trait_ref.path.segments;
|
||||
|
||||
if segments.len() == 1
|
||||
&& ["Fn", "FnMut", "FnOnce"].contains(&segments[0].ident.name.as_str())
|
||||
&& let Some(args) = &segments[0].args
|
||||
&& let ast::GenericArgs::Parenthesized(generic_args) = &**args
|
||||
&& let ast::FnRetTy::Ty(ty) = &generic_args.output
|
||||
&& ty.kind.is_unit()
|
||||
{
|
||||
lint_unneeded_unit_return(cx, ty, generic_args.span);
|
||||
}
|
||||
}
|
||||
fn is_unit_ty(ty: &Ty<'_>) -> bool {
|
||||
matches!(ty.kind, TyKind::Tup([]))
|
||||
}
|
||||
|
||||
// get the def site
|
||||
|
|
@ -117,24 +157,15 @@ fn get_def(span: Span) -> Option<Span> {
|
|||
}
|
||||
}
|
||||
|
||||
// is this expr a `()` unit?
|
||||
fn is_unit_expr(expr: &ast::Expr) -> bool {
|
||||
if let ast::ExprKind::Tup(ref vals) = expr.kind {
|
||||
vals.is_empty()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn lint_unneeded_unit_return(cx: &EarlyContext<'_>, ty: &ast::Ty, span: Span) {
|
||||
fn lint_unneeded_unit_return(cx: &LateContext<'_>, ty_span: Span, span: Span) {
|
||||
let (ret_span, appl) =
|
||||
span.with_hi(ty.span.hi())
|
||||
span.with_hi(ty_span.hi())
|
||||
.get_source_text(cx)
|
||||
.map_or((ty.span, Applicability::MaybeIncorrect), |src| {
|
||||
position_before_rarrow(&src).map_or((ty.span, Applicability::MaybeIncorrect), |rpos| {
|
||||
.map_or((ty_span, Applicability::MaybeIncorrect), |src| {
|
||||
position_before_rarrow(&src).map_or((ty_span, Applicability::MaybeIncorrect), |rpos| {
|
||||
(
|
||||
#[expect(clippy::cast_possible_truncation)]
|
||||
ty.span.with_lo(BytePos(span.lo().0 + rpos as u32)),
|
||||
ty_span.with_lo(BytePos(span.lo().0 + rpos as u32)),
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@ fn is_option_as_mut_use(tcx: TyCtxt<'_>, expr_id: HirId) -> bool {
|
|||
if let Node::Expr(mutating_expr) = tcx.parent_hir_node(expr_id)
|
||||
&& let ExprKind::MethodCall(path, _, [], _) = mutating_expr.kind
|
||||
{
|
||||
path.ident.name.as_str() == "as_mut"
|
||||
path.ident.name == sym::as_mut
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
|
@ -278,7 +278,7 @@ fn consume_option_as_ref<'tcx>(expr: &'tcx Expr<'tcx>) -> (&'tcx Expr<'tcx>, Opt
|
|||
if let ExprKind::MethodCall(path, recv, [], _) = expr.kind {
|
||||
if path.ident.name == sym::as_ref {
|
||||
(recv, Some(AsRefKind::AsRef))
|
||||
} else if path.ident.name.as_str() == "as_mut" {
|
||||
} else if path.ident.name == sym::as_mut {
|
||||
(recv, Some(AsRefKind::AsMut))
|
||||
} else {
|
||||
(expr, None)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use clippy_config::Conf;
|
||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
|
||||
use clippy_utils::is_in_test;
|
||||
use clippy_utils::macros::{FormatArgsStorage, MacroCall, format_arg_removal_span, root_macro_call_first_node};
|
||||
use clippy_utils::source::{SpanRangeExt, expand_past_previous_comma};
|
||||
use clippy_utils::{is_in_test, sym};
|
||||
use rustc_ast::token::LitKind;
|
||||
use rustc_ast::{
|
||||
FormatArgPosition, FormatArgPositionKind, FormatArgs, FormatArgsPiece, FormatOptions, FormatPlaceholder,
|
||||
|
|
@ -12,7 +12,7 @@ use rustc_errors::Applicability;
|
|||
use rustc_hir::{Expr, Impl, Item, ItemKind};
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_session::impl_lint_pass;
|
||||
use rustc_span::{BytePos, Span, sym};
|
||||
use rustc_span::{BytePos, Span};
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
|
|
@ -359,7 +359,7 @@ fn is_debug_impl(cx: &LateContext<'_>, item: &Item<'_>) -> bool {
|
|||
}
|
||||
|
||||
fn check_newline(cx: &LateContext<'_>, format_args: &FormatArgs, macro_call: &MacroCall, name: &str) {
|
||||
let Some(FormatArgsPiece::Literal(last)) = format_args.template.last() else {
|
||||
let Some(&FormatArgsPiece::Literal(last)) = format_args.template.last() else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
@ -401,7 +401,7 @@ fn check_newline(cx: &LateContext<'_>, format_args: &FormatArgs, macro_call: &Ma
|
|||
return;
|
||||
};
|
||||
|
||||
if format_args.template.len() == 1 && last.as_str() == "\n" {
|
||||
if format_args.template.len() == 1 && last == sym::LF {
|
||||
// print!("\n"), write!(f, "\n")
|
||||
|
||||
diag.multipart_suggestion(
|
||||
|
|
@ -427,9 +427,7 @@ fn check_newline(cx: &LateContext<'_>, format_args: &FormatArgs, macro_call: &Ma
|
|||
}
|
||||
|
||||
fn check_empty_string(cx: &LateContext<'_>, format_args: &FormatArgs, macro_call: &MacroCall, name: &str) {
|
||||
if let [FormatArgsPiece::Literal(literal)] = &format_args.template[..]
|
||||
&& literal.as_str() == "\n"
|
||||
{
|
||||
if let [FormatArgsPiece::Literal(sym::LF)] = &format_args.template[..] {
|
||||
let mut span = format_args.span;
|
||||
|
||||
let lint = if name == "writeln" {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use clippy_utils::{fn_def_id, get_enclosing_block, path_to_local_id};
|
|||
use rustc_ast::Mutability;
|
||||
use rustc_ast::visit::visit_opt;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::intravisit::{Visitor, walk_block, walk_expr, walk_local};
|
||||
use rustc_hir::{Expr, ExprKind, HirId, LetStmt, Node, PatKind, Stmt, StmtKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
|
|
@ -68,6 +69,7 @@ impl<'tcx> LateLintPass<'tcx> for ZombieProcesses {
|
|||
let mut vis = WaitFinder {
|
||||
cx,
|
||||
local_id,
|
||||
body_id: cx.tcx.hir_enclosing_body_owner(expr.hir_id),
|
||||
state: VisitorState::WalkUpToLocal,
|
||||
early_return: None,
|
||||
missing_wait_branch: None,
|
||||
|
|
@ -129,6 +131,7 @@ struct MaybeWait(Span);
|
|||
struct WaitFinder<'a, 'tcx> {
|
||||
cx: &'a LateContext<'tcx>,
|
||||
local_id: HirId,
|
||||
body_id: LocalDefId,
|
||||
state: VisitorState,
|
||||
early_return: Option<Span>,
|
||||
// When joining two if branches where one of them doesn't call `wait()`, stores its span for more targeted help
|
||||
|
|
@ -186,7 +189,7 @@ impl<'tcx> Visitor<'tcx> for WaitFinder<'_, 'tcx> {
|
|||
}
|
||||
} else {
|
||||
match ex.kind {
|
||||
ExprKind::Ret(e) => {
|
||||
ExprKind::Ret(e) if self.cx.tcx.hir_enclosing_body_owner(ex.hir_id) == self.body_id => {
|
||||
visit_opt!(self, visit_expr, e);
|
||||
if self.early_return.is_none() {
|
||||
self.early_return = Some(ex.span);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#![allow(
|
||||
clippy::missing_docs_in_private_items,
|
||||
clippy::must_use_candidate,
|
||||
clippy::symbol_as_str,
|
||||
rustc::diagnostic_outside_of_impl,
|
||||
rustc::untranslatable_diagnostic
|
||||
)]
|
||||
|
|
@ -31,12 +32,12 @@ extern crate rustc_span;
|
|||
|
||||
mod almost_standard_lint_formulation;
|
||||
mod collapsible_calls;
|
||||
mod interning_literals;
|
||||
mod invalid_paths;
|
||||
mod lint_without_lint_pass;
|
||||
mod msrv_attr_impl;
|
||||
mod outer_expn_data_pass;
|
||||
mod produce_ice;
|
||||
mod symbols;
|
||||
mod unnecessary_def_path;
|
||||
mod unsorted_clippy_utils_paths;
|
||||
|
||||
|
|
@ -45,7 +46,6 @@ use rustc_lint::{Lint, LintStore};
|
|||
static LINTS: &[&Lint] = &[
|
||||
almost_standard_lint_formulation::ALMOST_STANDARD_LINT_FORMULATION,
|
||||
collapsible_calls::COLLAPSIBLE_SPAN_LINT_CALLS,
|
||||
interning_literals::INTERNING_LITERALS,
|
||||
invalid_paths::INVALID_PATHS,
|
||||
lint_without_lint_pass::DEFAULT_LINT,
|
||||
lint_without_lint_pass::INVALID_CLIPPY_VERSION_ATTRIBUTE,
|
||||
|
|
@ -54,6 +54,8 @@ static LINTS: &[&Lint] = &[
|
|||
msrv_attr_impl::MISSING_MSRV_ATTR_IMPL,
|
||||
outer_expn_data_pass::OUTER_EXPN_EXPN_DATA,
|
||||
produce_ice::PRODUCE_ICE,
|
||||
symbols::INTERNING_LITERALS,
|
||||
symbols::SYMBOL_AS_STR,
|
||||
unnecessary_def_path::UNNECESSARY_DEF_PATH,
|
||||
unsorted_clippy_utils_paths::UNSORTED_CLIPPY_UTILS_PATHS,
|
||||
];
|
||||
|
|
@ -65,7 +67,7 @@ pub fn register_lints(store: &mut LintStore) {
|
|||
store.register_early_pass(|| Box::new(produce_ice::ProduceIce));
|
||||
store.register_late_pass(|_| Box::new(collapsible_calls::CollapsibleCalls));
|
||||
store.register_late_pass(|_| Box::new(invalid_paths::InvalidPaths));
|
||||
store.register_late_pass(|_| Box::<interning_literals::InterningDefinedSymbol>::default());
|
||||
store.register_late_pass(|_| Box::<symbols::Symbols>::default());
|
||||
store.register_late_pass(|_| Box::<lint_without_lint_pass::LintWithoutLintPass>::default());
|
||||
store.register_late_pass(|_| Box::<unnecessary_def_path::UnnecessaryDefPath>::default());
|
||||
store.register_late_pass(|_| Box::new(outer_expn_data_pass::OuterExpnDataPass));
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::ty::match_type;
|
||||
use clippy_utils::{def_path_def_ids, paths};
|
||||
use clippy_utils::{def_path_def_ids, match_def_path, paths};
|
||||
use rustc_ast::LitKind;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
|
|
@ -11,8 +11,8 @@ use rustc_lint_defs::declare_tool_lint;
|
|||
use rustc_middle::mir::ConstValue;
|
||||
use rustc_middle::ty;
|
||||
use rustc_session::impl_lint_pass;
|
||||
use rustc_span::sym;
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_span::{Span, sym};
|
||||
|
||||
declare_tool_lint! {
|
||||
/// ### What it does
|
||||
|
|
@ -36,15 +36,37 @@ declare_tool_lint! {
|
|||
report_in_external_macro: true
|
||||
}
|
||||
|
||||
declare_tool_lint! {
|
||||
/// ### What it does
|
||||
/// Checks for calls to `Symbol::as_str`
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// It's faster and easier to use the symbol constant. If one doesn't exist it can be added to `clippy_utils/src/sym.rs`
|
||||
///
|
||||
/// ### Example
|
||||
/// ```rust,ignore
|
||||
/// symbol.as_str() == "foo"
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```rust,ignore
|
||||
/// symbol == sym::foo
|
||||
/// ```
|
||||
pub clippy::SYMBOL_AS_STR,
|
||||
Warn,
|
||||
"calls to `Symbol::as_str`",
|
||||
report_in_external_macro: true
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct InterningDefinedSymbol {
|
||||
pub struct Symbols {
|
||||
// Maps the symbol to the import path
|
||||
symbol_map: FxHashMap<u32, (&'static str, Symbol)>,
|
||||
}
|
||||
|
||||
impl_lint_pass!(InterningDefinedSymbol => [INTERNING_LITERALS]);
|
||||
impl_lint_pass!(Symbols => [INTERNING_LITERALS, SYMBOL_AS_STR]);
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for InterningDefinedSymbol {
|
||||
impl<'tcx> LateLintPass<'tcx> for Symbols {
|
||||
fn check_crate(&mut self, cx: &LateContext<'_>) {
|
||||
let modules = [
|
||||
("kw", &paths::KW_MODULE[..]),
|
||||
|
|
@ -77,7 +99,8 @@ impl<'tcx> LateLintPass<'tcx> for InterningDefinedSymbol {
|
|||
if let ExprKind::Call(func, [arg]) = &expr.kind
|
||||
&& let ty::FnDef(def_id, _) = cx.typeck_results().expr_ty(func).kind()
|
||||
&& cx.tcx.is_diagnostic_item(sym::SymbolIntern, *def_id)
|
||||
&& let Some(Constant::Str(arg)) = ConstEvalCtxt::new(cx).eval_simple(arg)
|
||||
&& let ExprKind::Lit(lit) = arg.kind
|
||||
&& let LitKind::Str(name, _) = lit.node
|
||||
{
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
|
|
@ -85,18 +108,62 @@ impl<'tcx> LateLintPass<'tcx> for InterningDefinedSymbol {
|
|||
expr.span,
|
||||
"interning a string literal",
|
||||
|diag| {
|
||||
let value = Symbol::intern(&arg).as_u32();
|
||||
let (message, path) = if let Some((prefix, name)) = self.symbol_map.get(&value) {
|
||||
("use the preinterned symbol", format!("{prefix}::{name}"))
|
||||
} else {
|
||||
(
|
||||
"add the symbol to `clippy_utils/src/sym.rs` and use it",
|
||||
format!("sym::{}", arg.replace(|ch: char| !ch.is_alphanumeric(), "_")),
|
||||
)
|
||||
};
|
||||
let (message, path) = suggestion(&mut self.symbol_map, name);
|
||||
diag.span_suggestion_verbose(expr.span, message, path, Applicability::MaybeIncorrect);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
if let ExprKind::Binary(_, lhs, rhs) = expr.kind {
|
||||
check_binary(cx, lhs, rhs, &mut self.symbol_map);
|
||||
check_binary(cx, rhs, lhs, &mut self.symbol_map);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_binary(
|
||||
cx: &LateContext<'_>,
|
||||
lhs: &Expr<'_>,
|
||||
rhs: &Expr<'_>,
|
||||
symbols: &mut FxHashMap<u32, (&'static str, Symbol)>,
|
||||
) {
|
||||
if let Some(removal_span) = as_str_span(cx, lhs)
|
||||
&& let ExprKind::Lit(lit) = rhs.kind
|
||||
&& let LitKind::Str(name, _) = lit.node
|
||||
{
|
||||
span_lint_and_then(cx, SYMBOL_AS_STR, lhs.span, "converting a Symbol to a string", |diag| {
|
||||
let (message, path) = suggestion(symbols, name);
|
||||
diag.multipart_suggestion_verbose(
|
||||
message,
|
||||
vec![(removal_span, String::new()), (rhs.span, path)],
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn suggestion(symbols: &mut FxHashMap<u32, (&'static str, Symbol)>, name: Symbol) -> (&'static str, String) {
|
||||
if let Some((prefix, name)) = symbols.get(&name.as_u32()) {
|
||||
("use the preinterned symbol", format!("{prefix}::{name}"))
|
||||
} else {
|
||||
(
|
||||
"add the symbol to `clippy_utils/src/sym.rs` and use it",
|
||||
format!("sym::{}", name.as_str().replace(|ch: char| !ch.is_alphanumeric(), "_")),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// ```ignore
|
||||
/// symbol.as_str()
|
||||
/// // ^^^^^^^^
|
||||
/// ```
|
||||
fn as_str_span(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<Span> {
|
||||
if let ExprKind::MethodCall(_, recv, [], _) = expr.kind
|
||||
&& let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
|
||||
&& match_def_path(cx, method_def_id, &paths::SYMBOL_AS_STR)
|
||||
{
|
||||
Some(recv.span.shrink_to_hi().to(expr.span.shrink_to_hi()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ This crate is only guaranteed to build with this `nightly` toolchain:
|
|||
|
||||
<!-- begin autogenerated nightly -->
|
||||
```
|
||||
nightly-2025-04-22
|
||||
nightly-2025-05-01
|
||||
```
|
||||
<!-- end autogenerated nightly -->
|
||||
|
||||
|
|
|
|||
|
|
@ -3,14 +3,14 @@
|
|||
#![deny(clippy::missing_docs_in_private_items)]
|
||||
|
||||
use crate::consts::{ConstEvalCtxt, Constant};
|
||||
use crate::is_expn_of;
|
||||
use crate::ty::is_type_diagnostic_item;
|
||||
use crate::{is_expn_of, sym};
|
||||
|
||||
use rustc_ast::ast;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::{Arm, Block, Expr, ExprKind, HirId, LoopSource, MatchSource, Node, Pat, QPath, StructTailExpr};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_span::{Span, sym, symbol};
|
||||
use rustc_span::{Span, symbol};
|
||||
|
||||
/// The essential nodes of a desugared for loop as well as the entire span:
|
||||
/// `for pat in arg { body }` becomes `(pat, arg, body)`. Returns `(pat, arg, body, span)`.
|
||||
|
|
@ -474,7 +474,7 @@ pub fn get_vec_init_kind<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -
|
|||
return Some(VecInitKind::New);
|
||||
} else if name.ident.name == symbol::kw::Default {
|
||||
return Some(VecInitKind::Default);
|
||||
} else if name.ident.name.as_str() == "with_capacity" {
|
||||
} else if name.ident.name == sym::with_capacity {
|
||||
let arg = args.first()?;
|
||||
return match ConstEvalCtxt::new(cx).eval_simple(arg) {
|
||||
Some(Constant::Int(num)) => Some(VecInitKind::WithConstCapacity(num)),
|
||||
|
|
|
|||
|
|
@ -1118,8 +1118,8 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
|||
self.hash_const_arg(e);
|
||||
},
|
||||
TyPatKind::Or(variants) => {
|
||||
for variant in variants.iter() {
|
||||
self.hash_ty_pat(variant)
|
||||
for variant in variants {
|
||||
self.hash_ty_pat(variant);
|
||||
}
|
||||
},
|
||||
TyPatKind::Err(_) => {},
|
||||
|
|
|
|||
|
|
@ -1412,7 +1412,7 @@ pub fn is_in_panic_handler(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
|
|||
}
|
||||
|
||||
/// Gets the name of the item the expression is in, if available.
|
||||
pub fn get_item_name(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<Symbol> {
|
||||
pub fn parent_item_name(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<Symbol> {
|
||||
let parent_id = cx.tcx.hir_get_parent_item(expr.hir_id).def_id;
|
||||
match cx.tcx.hir_node_by_def_id(parent_id) {
|
||||
Node::Item(item) => item.kind.ident().map(|ident| ident.name),
|
||||
|
|
@ -2088,7 +2088,7 @@ pub fn match_libc_symbol(cx: &LateContext<'_>, did: DefId, name: &str) -> bool {
|
|||
let path = cx.get_def_path(did);
|
||||
// libc is meant to be used as a flat list of names, but they're all actually defined in different
|
||||
// modules based on the target platform. Ignore everything but crate name and the item name.
|
||||
path.first().is_some_and(|s| s.as_str() == "libc") && path.last().is_some_and(|s| s.as_str() == name)
|
||||
path.first().is_some_and(|s| *s == sym::libc) && path.last().is_some_and(|s| s.as_str() == name)
|
||||
}
|
||||
|
||||
/// Returns the list of condition expressions and the list of blocks in a
|
||||
|
|
@ -3101,7 +3101,7 @@ pub fn span_find_starting_semi(sm: &SourceMap, span: Span) -> Span {
|
|||
sm.span_take_while(span, |&ch| ch == ' ' || ch == ';')
|
||||
}
|
||||
|
||||
/// Returns whether the given let pattern and else body can be turned into a question mark
|
||||
/// Returns whether the given let pattern and else body can be turned into the `?` operator
|
||||
///
|
||||
/// For this example:
|
||||
/// ```ignore
|
||||
|
|
@ -3124,8 +3124,7 @@ pub fn span_find_starting_semi(sm: &SourceMap, span: Span) -> Span {
|
|||
/// ```
|
||||
///
|
||||
/// We output `Some(a)` in the first instance, and `Some(FooBar { a, b })` in the second, because
|
||||
/// the question mark operator is applicable here. Callers have to check whether we are in a
|
||||
/// constant or not.
|
||||
/// the `?` operator is applicable here. Callers have to check whether we are in a constant or not.
|
||||
pub fn pat_and_expr_can_be_question_mark<'a, 'hir>(
|
||||
cx: &LateContext<'_>,
|
||||
pat: &'a Pat<'hir>,
|
||||
|
|
|
|||
|
|
@ -30,33 +30,75 @@ macro_rules! generate {
|
|||
}
|
||||
|
||||
generate! {
|
||||
abs,
|
||||
as_bytes,
|
||||
as_deref_mut,
|
||||
as_deref,
|
||||
as_mut,
|
||||
Binary,
|
||||
build_hasher,
|
||||
cargo_clippy: "cargo-clippy",
|
||||
Cargo_toml: "Cargo.toml",
|
||||
cast,
|
||||
chars,
|
||||
CLIPPY_ARGS,
|
||||
CLIPPY_CONF_DIR,
|
||||
clone_into,
|
||||
cloned,
|
||||
collect,
|
||||
contains,
|
||||
copied,
|
||||
CRLF: "\r\n",
|
||||
Current,
|
||||
ends_with,
|
||||
exp,
|
||||
extend,
|
||||
finish_non_exhaustive,
|
||||
finish,
|
||||
flat_map,
|
||||
for_each,
|
||||
from_raw,
|
||||
from_str_radix,
|
||||
get,
|
||||
insert,
|
||||
int_roundings,
|
||||
into_bytes,
|
||||
into_owned,
|
||||
IntoIter,
|
||||
is_ascii,
|
||||
is_empty,
|
||||
is_err,
|
||||
is_none,
|
||||
is_ok,
|
||||
is_some,
|
||||
last,
|
||||
LF: "\n",
|
||||
LowerExp,
|
||||
LowerHex,
|
||||
max,
|
||||
min,
|
||||
mode,
|
||||
msrv,
|
||||
Octal,
|
||||
or_default,
|
||||
parse,
|
||||
push,
|
||||
regex,
|
||||
reserve,
|
||||
resize,
|
||||
restriction,
|
||||
rustfmt_skip,
|
||||
set_len,
|
||||
set_mode,
|
||||
set_readonly,
|
||||
signum,
|
||||
split_whitespace,
|
||||
split,
|
||||
Start,
|
||||
take,
|
||||
TBD,
|
||||
then_some,
|
||||
to_digit,
|
||||
to_owned,
|
||||
unused_extern_crates,
|
||||
unwrap_err,
|
||||
|
|
@ -66,4 +108,6 @@ generate! {
|
|||
V4,
|
||||
V6,
|
||||
Weak,
|
||||
with_capacity,
|
||||
wrapping_offset,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[toolchain]
|
||||
# begin autogenerated nightly
|
||||
channel = "nightly-2025-04-22"
|
||||
channel = "nightly-2025-05-01"
|
||||
# end autogenerated nightly
|
||||
components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
|
||||
profile = "minimal"
|
||||
|
|
|
|||
21
tests/ui-internal/symbol_as_str.fixed
Normal file
21
tests/ui-internal/symbol_as_str.fixed
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#![feature(rustc_private)]
|
||||
|
||||
extern crate rustc_span;
|
||||
|
||||
use clippy_utils::sym;
|
||||
use rustc_span::{Symbol, kw};
|
||||
|
||||
fn f(s: Symbol) {
|
||||
s == sym::f32;
|
||||
//~^ symbol_as_str
|
||||
s == sym::proc_dash_macro;
|
||||
//~^ symbol_as_str
|
||||
s == kw::SelfLower;
|
||||
//~^ symbol_as_str
|
||||
s == sym::msrv;
|
||||
//~^ symbol_as_str
|
||||
s == sym::Cargo_toml;
|
||||
//~^ symbol_as_str
|
||||
sym::get == s;
|
||||
//~^ symbol_as_str
|
||||
}
|
||||
21
tests/ui-internal/symbol_as_str.rs
Normal file
21
tests/ui-internal/symbol_as_str.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#![feature(rustc_private)]
|
||||
|
||||
extern crate rustc_span;
|
||||
|
||||
use clippy_utils::sym;
|
||||
use rustc_span::{Symbol, kw};
|
||||
|
||||
fn f(s: Symbol) {
|
||||
s.as_str() == "f32";
|
||||
//~^ symbol_as_str
|
||||
s.as_str() == "proc-macro";
|
||||
//~^ symbol_as_str
|
||||
s.as_str() == "self";
|
||||
//~^ symbol_as_str
|
||||
s.as_str() == "msrv";
|
||||
//~^ symbol_as_str
|
||||
s.as_str() == "Cargo.toml";
|
||||
//~^ symbol_as_str
|
||||
"get" == s.as_str();
|
||||
//~^ symbol_as_str
|
||||
}
|
||||
76
tests/ui-internal/symbol_as_str.stderr
Normal file
76
tests/ui-internal/symbol_as_str.stderr
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
error: converting a Symbol to a string
|
||||
--> tests/ui-internal/symbol_as_str.rs:9:5
|
||||
|
|
||||
LL | s.as_str() == "f32";
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::symbol-as-str` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::symbol_as_str)]`
|
||||
help: use the preinterned symbol
|
||||
|
|
||||
LL - s.as_str() == "f32";
|
||||
LL + s == sym::f32;
|
||||
|
|
||||
|
||||
error: converting a Symbol to a string
|
||||
--> tests/ui-internal/symbol_as_str.rs:11:5
|
||||
|
|
||||
LL | s.as_str() == "proc-macro";
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
help: use the preinterned symbol
|
||||
|
|
||||
LL - s.as_str() == "proc-macro";
|
||||
LL + s == sym::proc_dash_macro;
|
||||
|
|
||||
|
||||
error: converting a Symbol to a string
|
||||
--> tests/ui-internal/symbol_as_str.rs:13:5
|
||||
|
|
||||
LL | s.as_str() == "self";
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
help: use the preinterned symbol
|
||||
|
|
||||
LL - s.as_str() == "self";
|
||||
LL + s == kw::SelfLower;
|
||||
|
|
||||
|
||||
error: converting a Symbol to a string
|
||||
--> tests/ui-internal/symbol_as_str.rs:15:5
|
||||
|
|
||||
LL | s.as_str() == "msrv";
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
help: use the preinterned symbol
|
||||
|
|
||||
LL - s.as_str() == "msrv";
|
||||
LL + s == sym::msrv;
|
||||
|
|
||||
|
||||
error: converting a Symbol to a string
|
||||
--> tests/ui-internal/symbol_as_str.rs:17:5
|
||||
|
|
||||
LL | s.as_str() == "Cargo.toml";
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
help: use the preinterned symbol
|
||||
|
|
||||
LL - s.as_str() == "Cargo.toml";
|
||||
LL + s == sym::Cargo_toml;
|
||||
|
|
||||
|
||||
error: converting a Symbol to a string
|
||||
--> tests/ui-internal/symbol_as_str.rs:19:14
|
||||
|
|
||||
LL | "get" == s.as_str();
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
help: use the preinterned symbol
|
||||
|
|
||||
LL - "get" == s.as_str();
|
||||
LL + sym::get == s;
|
||||
|
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
15
tests/ui-internal/symbol_as_str_unfixable.rs
Normal file
15
tests/ui-internal/symbol_as_str_unfixable.rs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
//@no-rustfix: paths that don't exist yet
|
||||
#![feature(rustc_private)]
|
||||
|
||||
extern crate rustc_span;
|
||||
|
||||
use rustc_span::Symbol;
|
||||
|
||||
fn f(s: Symbol) {
|
||||
s.as_str() == "xyz123";
|
||||
//~^ symbol_as_str
|
||||
s.as_str() == "with-dash";
|
||||
//~^ symbol_as_str
|
||||
s.as_str() == "with.dot";
|
||||
//~^ symbol_as_str
|
||||
}
|
||||
40
tests/ui-internal/symbol_as_str_unfixable.stderr
Normal file
40
tests/ui-internal/symbol_as_str_unfixable.stderr
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
error: converting a Symbol to a string
|
||||
--> tests/ui-internal/symbol_as_str_unfixable.rs:9:5
|
||||
|
|
||||
LL | s.as_str() == "xyz123";
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::symbol-as-str` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::symbol_as_str)]`
|
||||
help: add the symbol to `clippy_utils/src/sym.rs` and use it
|
||||
|
|
||||
LL - s.as_str() == "xyz123";
|
||||
LL + s == sym::xyz123;
|
||||
|
|
||||
|
||||
error: converting a Symbol to a string
|
||||
--> tests/ui-internal/symbol_as_str_unfixable.rs:11:5
|
||||
|
|
||||
LL | s.as_str() == "with-dash";
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
help: add the symbol to `clippy_utils/src/sym.rs` and use it
|
||||
|
|
||||
LL - s.as_str() == "with-dash";
|
||||
LL + s == sym::with_dash;
|
||||
|
|
||||
|
||||
error: converting a Symbol to a string
|
||||
--> tests/ui-internal/symbol_as_str_unfixable.rs:13:5
|
||||
|
|
||||
LL | s.as_str() == "with.dot";
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
help: add the symbol to `clippy_utils/src/sym.rs` and use it
|
||||
|
|
||||
LL - s.as_str() == "with.dot";
|
||||
LL + s == sym::with_dot;
|
||||
|
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
@ -4,7 +4,6 @@
|
|||
#![allow(
|
||||
unused,
|
||||
unnecessary_transmutes,
|
||||
clippy::let_and_return,
|
||||
clippy::needless_if,
|
||||
clippy::missing_transmute_annotations
|
||||
)]
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
#![allow(
|
||||
unused,
|
||||
unnecessary_transmutes,
|
||||
clippy::let_and_return,
|
||||
clippy::needless_if,
|
||||
clippy::missing_transmute_annotations
|
||||
)]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error: in an `if` condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let`
|
||||
--> tests/ui/blocks_in_conditions.rs:31:5
|
||||
--> tests/ui/blocks_in_conditions.rs:30:5
|
||||
|
|
||||
LL | / if {
|
||||
LL | |
|
||||
|
|
@ -20,13 +20,13 @@ LL ~ }; if res {
|
|||
|
|
||||
|
||||
error: omit braces around single expression condition
|
||||
--> tests/ui/blocks_in_conditions.rs:43:8
|
||||
--> tests/ui/blocks_in_conditions.rs:42:8
|
||||
|
|
||||
LL | if { true } { 6 } else { 10 }
|
||||
| ^^^^^^^^ help: try: `true`
|
||||
|
||||
error: this boolean expression can be simplified
|
||||
--> tests/ui/blocks_in_conditions.rs:49:8
|
||||
--> tests/ui/blocks_in_conditions.rs:48:8
|
||||
|
|
||||
LL | if true && x == 3 { 6 } else { 10 }
|
||||
| ^^^^^^^^^^^^^^ help: try: `x == 3`
|
||||
|
|
|
|||
|
|
@ -103,3 +103,39 @@ fn main() {
|
|||
|
||||
external!({ if let 2 = $a {} });
|
||||
}
|
||||
|
||||
mod issue8710 {
|
||||
fn str_ref(cs: &[char]) {
|
||||
if matches!(cs.iter().next(), Some('i')) {
|
||||
//~^ equatable_if_let
|
||||
} else {
|
||||
todo!();
|
||||
}
|
||||
}
|
||||
|
||||
fn i32_ref(cs: &[i32]) {
|
||||
if matches!(cs.iter().next(), Some(1)) {
|
||||
//~^ equatable_if_let
|
||||
} else {
|
||||
todo!();
|
||||
}
|
||||
}
|
||||
|
||||
fn enum_ref() {
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
enum MyEnum {
|
||||
A(i32),
|
||||
B,
|
||||
}
|
||||
|
||||
fn get_enum() -> Option<&'static MyEnum> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
if matches!(get_enum(), Some(MyEnum::B)) {
|
||||
//~^ equatable_if_let
|
||||
} else {
|
||||
todo!();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,3 +103,39 @@ fn main() {
|
|||
|
||||
external!({ if let 2 = $a {} });
|
||||
}
|
||||
|
||||
mod issue8710 {
|
||||
fn str_ref(cs: &[char]) {
|
||||
if let Some('i') = cs.iter().next() {
|
||||
//~^ equatable_if_let
|
||||
} else {
|
||||
todo!();
|
||||
}
|
||||
}
|
||||
|
||||
fn i32_ref(cs: &[i32]) {
|
||||
if let Some(1) = cs.iter().next() {
|
||||
//~^ equatable_if_let
|
||||
} else {
|
||||
todo!();
|
||||
}
|
||||
}
|
||||
|
||||
fn enum_ref() {
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
enum MyEnum {
|
||||
A(i32),
|
||||
B,
|
||||
}
|
||||
|
||||
fn get_enum() -> Option<&'static MyEnum> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
if let Some(MyEnum::B) = get_enum() {
|
||||
//~^ equatable_if_let
|
||||
} else {
|
||||
todo!();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,5 +85,23 @@ error: this pattern matching can be expressed using equality
|
|||
LL | if let inline!("abc") = "abc" {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"abc" == inline!("abc")`
|
||||
|
||||
error: aborting due to 14 previous errors
|
||||
error: this pattern matching can be expressed using `matches!`
|
||||
--> tests/ui/equatable_if_let.rs:109:12
|
||||
|
|
||||
LL | if let Some('i') = cs.iter().next() {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(cs.iter().next(), Some('i'))`
|
||||
|
||||
error: this pattern matching can be expressed using `matches!`
|
||||
--> tests/ui/equatable_if_let.rs:117:12
|
||||
|
|
||||
LL | if let Some(1) = cs.iter().next() {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(cs.iter().next(), Some(1))`
|
||||
|
||||
error: this pattern matching can be expressed using `matches!`
|
||||
--> tests/ui/equatable_if_let.rs:135:12
|
||||
|
|
||||
LL | if let Some(MyEnum::B) = get_enum() {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(get_enum(), Some(MyEnum::B))`
|
||||
|
||||
error: aborting due to 17 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,21 @@
|
|||
#![warn(clippy::manual_div_ceil)]
|
||||
|
||||
macro_rules! y {
|
||||
() => {
|
||||
let x = 33u32;
|
||||
let _ = x.div_ceil(8);
|
||||
//~^ manual_div_ceil
|
||||
let _ = x.div_ceil(8);
|
||||
//~^ manual_div_ceil
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! eight {
|
||||
() => {
|
||||
8
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = 7_u32;
|
||||
let y = 4_u32;
|
||||
|
|
@ -32,6 +48,13 @@ fn main() {
|
|||
let _ = (z as i32 + (y_i - 1)) / y_i;
|
||||
let _ = (7_u32 as i32 + (y_i - 1)) / y_i;
|
||||
let _ = (7_u32 as i32 + (4 - 1)) / 4;
|
||||
|
||||
// Test lint with macro
|
||||
y!();
|
||||
|
||||
// Also test if RHS should be result of macro expansion
|
||||
let _ = 33u32.div_ceil(eight!());
|
||||
//~^ manual_div_ceil
|
||||
}
|
||||
|
||||
fn issue_13843() {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,21 @@
|
|||
#![warn(clippy::manual_div_ceil)]
|
||||
|
||||
macro_rules! y {
|
||||
() => {
|
||||
let x = 33u32;
|
||||
let _ = (x + 7) / 8;
|
||||
//~^ manual_div_ceil
|
||||
let _ = (7 + x) / 8;
|
||||
//~^ manual_div_ceil
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! eight {
|
||||
() => {
|
||||
8
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = 7_u32;
|
||||
let y = 4_u32;
|
||||
|
|
@ -32,6 +48,13 @@ fn main() {
|
|||
let _ = (z as i32 + (y_i - 1)) / y_i;
|
||||
let _ = (7_u32 as i32 + (y_i - 1)) / y_i;
|
||||
let _ = (7_u32 as i32 + (4 - 1)) / 4;
|
||||
|
||||
// Test lint with macro
|
||||
y!();
|
||||
|
||||
// Also test if RHS should be result of macro expansion
|
||||
let _ = (33u32 + 7) / eight!();
|
||||
//~^ manual_div_ceil
|
||||
}
|
||||
|
||||
fn issue_13843() {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error: manually reimplementing `div_ceil`
|
||||
--> tests/ui/manual_div_ceil.rs:9:13
|
||||
--> tests/ui/manual_div_ceil.rs:25:13
|
||||
|
|
||||
LL | let _ = (x + (y - 1)) / y;
|
||||
| ^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(y)`
|
||||
|
|
@ -8,94 +8,122 @@ LL | let _ = (x + (y - 1)) / y;
|
|||
= help: to override `-D warnings` add `#[allow(clippy::manual_div_ceil)]`
|
||||
|
||||
error: manually reimplementing `div_ceil`
|
||||
--> tests/ui/manual_div_ceil.rs:11:13
|
||||
--> tests/ui/manual_div_ceil.rs:27:13
|
||||
|
|
||||
LL | let _ = ((y - 1) + x) / y;
|
||||
| ^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(y)`
|
||||
|
||||
error: manually reimplementing `div_ceil`
|
||||
--> tests/ui/manual_div_ceil.rs:13:13
|
||||
--> tests/ui/manual_div_ceil.rs:29:13
|
||||
|
|
||||
LL | let _ = (x + y - 1) / y;
|
||||
| ^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(y)`
|
||||
|
||||
error: manually reimplementing `div_ceil`
|
||||
--> tests/ui/manual_div_ceil.rs:16:13
|
||||
--> tests/ui/manual_div_ceil.rs:32:13
|
||||
|
|
||||
LL | let _ = (7_u32 + (4 - 1)) / 4;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `7_u32.div_ceil(4)`
|
||||
|
||||
error: manually reimplementing `div_ceil`
|
||||
--> tests/ui/manual_div_ceil.rs:18:13
|
||||
--> tests/ui/manual_div_ceil.rs:34:13
|
||||
|
|
||||
LL | let _ = (7_i32 as u32 + (4 - 1)) / 4;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `(7_i32 as u32).div_ceil(4)`
|
||||
|
||||
error: manually reimplementing `div_ceil`
|
||||
--> tests/ui/manual_div_ceil.rs:39:13
|
||||
--> tests/ui/manual_div_ceil.rs:6:17
|
||||
|
|
||||
LL | let _ = (x + 7) / 8;
|
||||
| ^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(8)`
|
||||
...
|
||||
LL | y!();
|
||||
| ---- in this macro invocation
|
||||
|
|
||||
= note: this error originates in the macro `y` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: manually reimplementing `div_ceil`
|
||||
--> tests/ui/manual_div_ceil.rs:8:17
|
||||
|
|
||||
LL | let _ = (7 + x) / 8;
|
||||
| ^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(8)`
|
||||
...
|
||||
LL | y!();
|
||||
| ---- in this macro invocation
|
||||
|
|
||||
= note: this error originates in the macro `y` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: manually reimplementing `div_ceil`
|
||||
--> tests/ui/manual_div_ceil.rs:56:13
|
||||
|
|
||||
LL | let _ = (33u32 + 7) / eight!();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `33u32.div_ceil(eight!())`
|
||||
|
||||
error: manually reimplementing `div_ceil`
|
||||
--> tests/ui/manual_div_ceil.rs:62:13
|
||||
|
|
||||
LL | let _ = (2048 + x - 1) / x;
|
||||
| ^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048_usize.div_ceil(x)`
|
||||
|
||||
error: manually reimplementing `div_ceil`
|
||||
--> tests/ui/manual_div_ceil.rs:43:13
|
||||
--> tests/ui/manual_div_ceil.rs:66:13
|
||||
|
|
||||
LL | let _ = (2048usize + x - 1) / x;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048usize.div_ceil(x)`
|
||||
|
||||
error: manually reimplementing `div_ceil`
|
||||
--> tests/ui/manual_div_ceil.rs:47:13
|
||||
--> tests/ui/manual_div_ceil.rs:70:13
|
||||
|
|
||||
LL | let _ = (2048_usize + x - 1) / x;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048_usize.div_ceil(x)`
|
||||
|
||||
error: manually reimplementing `div_ceil`
|
||||
--> tests/ui/manual_div_ceil.rs:51:13
|
||||
--> tests/ui/manual_div_ceil.rs:74:13
|
||||
|
|
||||
LL | let _ = (x + 4 - 1) / 4;
|
||||
| ^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(4)`
|
||||
|
||||
error: manually reimplementing `div_ceil`
|
||||
--> tests/ui/manual_div_ceil.rs:54:18
|
||||
--> tests/ui/manual_div_ceil.rs:77:18
|
||||
|
|
||||
LL | let _: u32 = (2048 + 6 - 1) / 6;
|
||||
| ^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048_u32.div_ceil(6)`
|
||||
|
||||
error: manually reimplementing `div_ceil`
|
||||
--> tests/ui/manual_div_ceil.rs:56:20
|
||||
--> tests/ui/manual_div_ceil.rs:79:20
|
||||
|
|
||||
LL | let _: usize = (2048 + 6 - 1) / 6;
|
||||
| ^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048_usize.div_ceil(6)`
|
||||
|
||||
error: manually reimplementing `div_ceil`
|
||||
--> tests/ui/manual_div_ceil.rs:58:18
|
||||
--> tests/ui/manual_div_ceil.rs:81:18
|
||||
|
|
||||
LL | let _: u32 = (0x2048 + 0x6 - 1) / 0x6;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `0x2048_u32.div_ceil(0x6)`
|
||||
|
||||
error: manually reimplementing `div_ceil`
|
||||
--> tests/ui/manual_div_ceil.rs:61:13
|
||||
--> tests/ui/manual_div_ceil.rs:84:13
|
||||
|
|
||||
LL | let _ = (2048 + 6u32 - 1) / 6u32;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048_u32.div_ceil(6u32)`
|
||||
|
||||
error: manually reimplementing `div_ceil`
|
||||
--> tests/ui/manual_div_ceil.rs:64:13
|
||||
--> tests/ui/manual_div_ceil.rs:87:13
|
||||
|
|
||||
LL | let _ = (1_000_000 + 6u32 - 1) / 6u32;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `1_000_000_u32.div_ceil(6u32)`
|
||||
|
||||
error: manually reimplementing `div_ceil`
|
||||
--> tests/ui/manual_div_ceil.rs:70:13
|
||||
--> tests/ui/manual_div_ceil.rs:93:13
|
||||
|
|
||||
LL | let _ = (x + 7) / 8;
|
||||
| ^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(8)`
|
||||
|
||||
error: manually reimplementing `div_ceil`
|
||||
--> tests/ui/manual_div_ceil.rs:72:13
|
||||
--> tests/ui/manual_div_ceil.rs:95:13
|
||||
|
|
||||
LL | let _ = (7 + x) / 8;
|
||||
| ^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(8)`
|
||||
|
||||
error: aborting due to 16 previous errors
|
||||
error: aborting due to 19 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -46,9 +46,7 @@ fn main() {
|
|||
if let true = true
|
||||
&& true
|
||||
{}
|
||||
if true
|
||||
&& let true = true
|
||||
{}
|
||||
if true && let true = true {}
|
||||
// Can lint nested `if let`s
|
||||
({
|
||||
//~^ needless_if
|
||||
|
|
|
|||
|
|
@ -46,9 +46,7 @@ fn main() {
|
|||
if let true = true
|
||||
&& true
|
||||
{}
|
||||
if true
|
||||
&& let true = true
|
||||
{}
|
||||
if true && let true = true {}
|
||||
// Can lint nested `if let`s
|
||||
if {
|
||||
//~^ needless_if
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ LL + });
|
|||
|
|
||||
|
||||
error: this `if` branch is empty
|
||||
--> tests/ui/needless_if.rs:53:5
|
||||
--> tests/ui/needless_if.rs:51:5
|
||||
|
|
||||
LL | / if {
|
||||
LL | |
|
||||
|
|
@ -57,19 +57,19 @@ LL + } && true);
|
|||
|
|
||||
|
||||
error: this `if` branch is empty
|
||||
--> tests/ui/needless_if.rs:98:5
|
||||
--> tests/ui/needless_if.rs:96:5
|
||||
|
|
||||
LL | if { maybe_side_effect() } {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can remove it: `({ maybe_side_effect() });`
|
||||
|
||||
error: this `if` branch is empty
|
||||
--> tests/ui/needless_if.rs:101:5
|
||||
--> tests/ui/needless_if.rs:99:5
|
||||
|
|
||||
LL | if { maybe_side_effect() } && true {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can remove it: `({ maybe_side_effect() } && true);`
|
||||
|
||||
error: this `if` branch is empty
|
||||
--> tests/ui/needless_if.rs:106:5
|
||||
--> tests/ui/needless_if.rs:104:5
|
||||
|
|
||||
LL | if true {}
|
||||
| ^^^^^^^^^^ help: you can remove it: `true;`
|
||||
|
|
|
|||
|
|
@ -246,9 +246,7 @@ fn does_not_lint() {
|
|||
}
|
||||
|
||||
let x;
|
||||
if true
|
||||
&& let Some(n) = Some("let chains too")
|
||||
{
|
||||
if true && let Some(n) = Some("let chains too") {
|
||||
x = 1;
|
||||
} else {
|
||||
x = 2;
|
||||
|
|
|
|||
|
|
@ -246,9 +246,7 @@ fn does_not_lint() {
|
|||
}
|
||||
|
||||
let x;
|
||||
if true
|
||||
&& let Some(n) = Some("let chains too")
|
||||
{
|
||||
if true && let Some(n) = Some("let chains too") {
|
||||
x = 1;
|
||||
} else {
|
||||
x = 2;
|
||||
|
|
|
|||
|
|
@ -276,7 +276,7 @@ LL ~ };
|
|||
|
|
||||
|
||||
error: unneeded late initialization
|
||||
--> tests/ui/needless_late_init.rs:302:5
|
||||
--> tests/ui/needless_late_init.rs:300:5
|
||||
|
|
||||
LL | let r;
|
||||
| ^^^^^^ created here
|
||||
|
|
|
|||
|
|
@ -1,100 +1,188 @@
|
|||
error: question mark operator is useless here
|
||||
error: enclosing `Some` and `?` operator are unneeded
|
||||
--> tests/ui/needless_question_mark.rs:20:12
|
||||
|
|
||||
LL | return Some(to.magic?);
|
||||
| ^^^^^^^^^^^^^^^ help: try removing question mark and `Some()`: `to.magic`
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::needless-question-mark` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::needless_question_mark)]`
|
||||
help: remove the enclosing `Some` and `?` operator
|
||||
|
|
||||
LL - return Some(to.magic?);
|
||||
LL + return to.magic;
|
||||
|
|
||||
|
||||
error: question mark operator is useless here
|
||||
error: enclosing `Some` and `?` operator are unneeded
|
||||
--> tests/ui/needless_question_mark.rs:29:12
|
||||
|
|
||||
LL | return Some(to.magic?)
|
||||
| ^^^^^^^^^^^^^^^ help: try removing question mark and `Some()`: `to.magic`
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: remove the enclosing `Some` and `?` operator
|
||||
|
|
||||
LL - return Some(to.magic?)
|
||||
LL + return to.magic
|
||||
|
|
||||
|
||||
error: question mark operator is useless here
|
||||
error: enclosing `Some` and `?` operator are unneeded
|
||||
--> tests/ui/needless_question_mark.rs:35:5
|
||||
|
|
||||
LL | Some(to.magic?)
|
||||
| ^^^^^^^^^^^^^^^ help: try removing question mark and `Some()`: `to.magic`
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: remove the enclosing `Some` and `?` operator
|
||||
|
|
||||
LL - Some(to.magic?)
|
||||
LL + to.magic
|
||||
|
|
||||
|
||||
error: question mark operator is useless here
|
||||
error: enclosing `Some` and `?` operator are unneeded
|
||||
--> tests/ui/needless_question_mark.rs:41:21
|
||||
|
|
||||
LL | to.and_then(|t| Some(t.magic?))
|
||||
| ^^^^^^^^^^^^^^ help: try removing question mark and `Some()`: `t.magic`
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
help: remove the enclosing `Some` and `?` operator
|
||||
|
|
||||
LL - to.and_then(|t| Some(t.magic?))
|
||||
LL + to.and_then(|t| t.magic)
|
||||
|
|
||||
|
||||
error: question mark operator is useless here
|
||||
error: enclosing `Some` and `?` operator are unneeded
|
||||
--> tests/ui/needless_question_mark.rs:51:9
|
||||
|
|
||||
LL | Some(t.magic?)
|
||||
| ^^^^^^^^^^^^^^ help: try removing question mark and `Some()`: `t.magic`
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
help: remove the enclosing `Some` and `?` operator
|
||||
|
|
||||
LL - Some(t.magic?)
|
||||
LL + t.magic
|
||||
|
|
||||
|
||||
error: question mark operator is useless here
|
||||
error: enclosing `Ok` and `?` operator are unneeded
|
||||
--> tests/ui/needless_question_mark.rs:57:12
|
||||
|
|
||||
LL | return Ok(tr.magic?);
|
||||
| ^^^^^^^^^^^^^ help: try removing question mark and `Ok()`: `tr.magic`
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
help: remove the enclosing `Ok` and `?` operator
|
||||
|
|
||||
LL - return Ok(tr.magic?);
|
||||
LL + return tr.magic;
|
||||
|
|
||||
|
||||
error: question mark operator is useless here
|
||||
error: enclosing `Ok` and `?` operator are unneeded
|
||||
--> tests/ui/needless_question_mark.rs:65:12
|
||||
|
|
||||
LL | return Ok(tr.magic?)
|
||||
| ^^^^^^^^^^^^^ help: try removing question mark and `Ok()`: `tr.magic`
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
help: remove the enclosing `Ok` and `?` operator
|
||||
|
|
||||
LL - return Ok(tr.magic?)
|
||||
LL + return tr.magic
|
||||
|
|
||||
|
||||
error: question mark operator is useless here
|
||||
error: enclosing `Ok` and `?` operator are unneeded
|
||||
--> tests/ui/needless_question_mark.rs:70:5
|
||||
|
|
||||
LL | Ok(tr.magic?)
|
||||
| ^^^^^^^^^^^^^ help: try removing question mark and `Ok()`: `tr.magic`
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
help: remove the enclosing `Ok` and `?` operator
|
||||
|
|
||||
LL - Ok(tr.magic?)
|
||||
LL + tr.magic
|
||||
|
|
||||
|
||||
error: question mark operator is useless here
|
||||
error: enclosing `Ok` and `?` operator are unneeded
|
||||
--> tests/ui/needless_question_mark.rs:75:21
|
||||
|
|
||||
LL | tr.and_then(|t| Ok(t.magic?))
|
||||
| ^^^^^^^^^^^^ help: try removing question mark and `Ok()`: `t.magic`
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
help: remove the enclosing `Ok` and `?` operator
|
||||
|
|
||||
LL - tr.and_then(|t| Ok(t.magic?))
|
||||
LL + tr.and_then(|t| t.magic)
|
||||
|
|
||||
|
||||
error: question mark operator is useless here
|
||||
error: enclosing `Ok` and `?` operator are unneeded
|
||||
--> tests/ui/needless_question_mark.rs:84:9
|
||||
|
|
||||
LL | Ok(t.magic?)
|
||||
| ^^^^^^^^^^^^ help: try removing question mark and `Ok()`: `t.magic`
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
help: remove the enclosing `Ok` and `?` operator
|
||||
|
|
||||
LL - Ok(t.magic?)
|
||||
LL + t.magic
|
||||
|
|
||||
|
||||
error: question mark operator is useless here
|
||||
error: enclosing `Ok` and `?` operator are unneeded
|
||||
--> tests/ui/needless_question_mark.rs:92:16
|
||||
|
|
||||
LL | return Ok(t.magic?);
|
||||
| ^^^^^^^^^^^^ help: try removing question mark and `Ok()`: `t.magic`
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
help: remove the enclosing `Ok` and `?` operator
|
||||
|
|
||||
LL - return Ok(t.magic?);
|
||||
LL + return t.magic;
|
||||
|
|
||||
|
||||
error: question mark operator is useless here
|
||||
error: enclosing `Some` and `?` operator are unneeded
|
||||
--> tests/ui/needless_question_mark.rs:128:27
|
||||
|
|
||||
LL | || -> Option<_> { Some(Some($expr)?) }()
|
||||
| ^^^^^^^^^^^^^^^^^^ help: try removing question mark and `Some()`: `Some($expr)`
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
...
|
||||
LL | let _x = some_and_qmark_in_macro!(x?);
|
||||
| ---------------------------- in this macro invocation
|
||||
|
|
||||
= note: this error originates in the macro `some_and_qmark_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: remove the enclosing `Some` and `?` operator
|
||||
|
|
||||
LL - || -> Option<_> { Some(Some($expr)?) }()
|
||||
LL + || -> Option<_> { Some($expr) }()
|
||||
|
|
||||
|
||||
error: question mark operator is useless here
|
||||
error: enclosing `Some` and `?` operator are unneeded
|
||||
--> tests/ui/needless_question_mark.rs:140:5
|
||||
|
|
||||
LL | Some(to.magic?)
|
||||
| ^^^^^^^^^^^^^^^ help: try removing question mark and `Some()`: `to.magic`
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: remove the enclosing `Some` and `?` operator
|
||||
|
|
||||
LL - Some(to.magic?)
|
||||
LL + to.magic
|
||||
|
|
||||
|
||||
error: question mark operator is useless here
|
||||
error: enclosing `Ok` and `?` operator are unneeded
|
||||
--> tests/ui/needless_question_mark.rs:149:5
|
||||
|
|
||||
LL | Ok(s.magic?)
|
||||
| ^^^^^^^^^^^^ help: try removing question mark and `Ok()`: `s.magic`
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
help: remove the enclosing `Ok` and `?` operator
|
||||
|
|
||||
LL - Ok(s.magic?)
|
||||
LL + s.magic
|
||||
|
|
||||
|
||||
error: question mark operator is useless here
|
||||
error: enclosing `Some` and `?` operator are unneeded
|
||||
--> tests/ui/needless_question_mark.rs:154:7
|
||||
|
|
||||
LL | { Some(a?) }
|
||||
| ^^^^^^^^ help: try removing question mark and `Some()`: `a`
|
||||
| ^^^^^^^^
|
||||
|
|
||||
help: remove the enclosing `Some` and `?` operator
|
||||
|
|
||||
LL - { Some(a?) }
|
||||
LL + { a }
|
||||
|
|
||||
|
||||
error: aborting due to 15 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -23,23 +23,25 @@ fn main() {
|
|||
//~^ ptr_eq
|
||||
let _ = std::ptr::eq(a, b);
|
||||
//~^ ptr_eq
|
||||
let _ = std::ptr::eq(a.as_ptr(), b as *const _);
|
||||
//~^ ptr_eq
|
||||
let _ = std::ptr::eq(a.as_ptr(), b.as_ptr());
|
||||
//~^ ptr_eq
|
||||
|
||||
// Do not lint: the rhs conversion is needed
|
||||
let _ = a.as_ptr() == b as *const _;
|
||||
|
||||
// Do not lint: we have two raw pointers already
|
||||
let _ = a.as_ptr() == b.as_ptr();
|
||||
|
||||
// Do not lint
|
||||
|
||||
let _ = mac!(a, b);
|
||||
let _ = another_mac!(a, b);
|
||||
|
||||
let a = &mut [1, 2, 3];
|
||||
let b = &mut [1, 2, 3];
|
||||
|
||||
let _ = std::ptr::eq(a.as_mut_ptr(), b as *mut [i32] as *mut _);
|
||||
//~^ ptr_eq
|
||||
let _ = std::ptr::eq(a.as_mut_ptr(), b.as_mut_ptr());
|
||||
//~^ ptr_eq
|
||||
// Do not lint: the rhs conversion is needed
|
||||
let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _;
|
||||
|
||||
// Do not lint: we have two raw pointers already
|
||||
let _ = a.as_mut_ptr() == b.as_mut_ptr();
|
||||
|
||||
let _ = a == b;
|
||||
let _ = core::ptr::eq(a, b);
|
||||
|
|
@ -51,8 +53,12 @@ fn main() {
|
|||
let _ = !std::ptr::eq(x, y);
|
||||
//~^ ptr_eq
|
||||
|
||||
#[allow(clippy::eq_op)]
|
||||
let _issue14337 = std::ptr::eq(main as *const (), main as *const ());
|
||||
#[expect(clippy::eq_op)]
|
||||
// Do not lint: casts are needed to not change type
|
||||
let _issue14337 = main as *const () == main as *const ();
|
||||
|
||||
// Do not peel the content of macros
|
||||
let _ = std::ptr::eq(mac!(cast a), mac!(cast b));
|
||||
//~^ ptr_eq
|
||||
|
||||
// Do not peel the content of macros
|
||||
|
|
|
|||
|
|
@ -23,23 +23,25 @@ fn main() {
|
|||
//~^ ptr_eq
|
||||
let _ = a as *const _ == b as *const _;
|
||||
//~^ ptr_eq
|
||||
|
||||
// Do not lint: the rhs conversion is needed
|
||||
let _ = a.as_ptr() == b as *const _;
|
||||
//~^ ptr_eq
|
||||
|
||||
// Do not lint: we have two raw pointers already
|
||||
let _ = a.as_ptr() == b.as_ptr();
|
||||
//~^ ptr_eq
|
||||
|
||||
// Do not lint
|
||||
|
||||
let _ = mac!(a, b);
|
||||
let _ = another_mac!(a, b);
|
||||
|
||||
let a = &mut [1, 2, 3];
|
||||
let b = &mut [1, 2, 3];
|
||||
|
||||
// Do not lint: the rhs conversion is needed
|
||||
let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _;
|
||||
//~^ ptr_eq
|
||||
|
||||
// Do not lint: we have two raw pointers already
|
||||
let _ = a.as_mut_ptr() == b.as_mut_ptr();
|
||||
//~^ ptr_eq
|
||||
|
||||
let _ = a == b;
|
||||
let _ = core::ptr::eq(a, b);
|
||||
|
|
@ -51,8 +53,12 @@ fn main() {
|
|||
let _ = x as *const u32 != y as *mut u32 as *const u32;
|
||||
//~^ ptr_eq
|
||||
|
||||
#[allow(clippy::eq_op)]
|
||||
#[expect(clippy::eq_op)]
|
||||
// Do not lint: casts are needed to not change type
|
||||
let _issue14337 = main as *const () == main as *const ();
|
||||
|
||||
// Do not peel the content of macros
|
||||
let _ = mac!(cast a) as *const _ == mac!(cast b) as *const _;
|
||||
//~^ ptr_eq
|
||||
|
||||
// Do not peel the content of macros
|
||||
|
|
|
|||
|
|
@ -14,52 +14,28 @@ LL | let _ = a as *const _ == b as *const _;
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a, b)`
|
||||
|
||||
error: use `std::ptr::eq` when comparing raw pointers
|
||||
--> tests/ui/ptr_eq.rs:26:13
|
||||
|
|
||||
LL | let _ = a.as_ptr() == b as *const _;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a.as_ptr(), b as *const _)`
|
||||
|
||||
error: use `std::ptr::eq` when comparing raw pointers
|
||||
--> tests/ui/ptr_eq.rs:28:13
|
||||
|
|
||||
LL | let _ = a.as_ptr() == b.as_ptr();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a.as_ptr(), b.as_ptr())`
|
||||
|
||||
error: use `std::ptr::eq` when comparing raw pointers
|
||||
--> tests/ui/ptr_eq.rs:39:13
|
||||
|
|
||||
LL | let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a.as_mut_ptr(), b as *mut [i32] as *mut _)`
|
||||
|
||||
error: use `std::ptr::eq` when comparing raw pointers
|
||||
--> tests/ui/ptr_eq.rs:41:13
|
||||
|
|
||||
LL | let _ = a.as_mut_ptr() == b.as_mut_ptr();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a.as_mut_ptr(), b.as_mut_ptr())`
|
||||
|
||||
error: use `std::ptr::eq` when comparing raw pointers
|
||||
--> tests/ui/ptr_eq.rs:48:13
|
||||
--> tests/ui/ptr_eq.rs:50:13
|
||||
|
|
||||
LL | let _ = x as *const u32 == y as *mut u32 as *const u32;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(x, y)`
|
||||
|
||||
error: use `std::ptr::eq` when comparing raw pointers
|
||||
--> tests/ui/ptr_eq.rs:51:13
|
||||
--> tests/ui/ptr_eq.rs:53:13
|
||||
|
|
||||
LL | let _ = x as *const u32 != y as *mut u32 as *const u32;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `!std::ptr::eq(x, y)`
|
||||
|
||||
error: use `std::ptr::eq` when comparing raw pointers
|
||||
--> tests/ui/ptr_eq.rs:55:23
|
||||
|
|
||||
LL | let _issue14337 = main as *const () == main as *const ();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(main as *const (), main as *const ())`
|
||||
|
||||
error: use `std::ptr::eq` when comparing raw pointers
|
||||
--> tests/ui/ptr_eq.rs:59:13
|
||||
--> tests/ui/ptr_eq.rs:61:13
|
||||
|
|
||||
LL | let _ = mac!(cast a) as *const _ == mac!(cast b) as *const _;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(mac!(cast a), mac!(cast b))`
|
||||
|
||||
error: aborting due to 10 previous errors
|
||||
error: use `std::ptr::eq` when comparing raw pointers
|
||||
--> tests/ui/ptr_eq.rs:65:13
|
||||
|
|
||||
LL | let _ = mac!(cast a) as *const _ == mac!(cast b) as *const _;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(mac!(cast a), mac!(cast b))`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -32,23 +32,25 @@ fn main() {
|
|||
//~^ ptr_eq
|
||||
let _ = core::ptr::eq(a, b);
|
||||
//~^ ptr_eq
|
||||
let _ = core::ptr::eq(a.as_ptr(), b as *const _);
|
||||
//~^ ptr_eq
|
||||
let _ = core::ptr::eq(a.as_ptr(), b.as_ptr());
|
||||
//~^ ptr_eq
|
||||
|
||||
// Do not lint: the rhs conversion is needed
|
||||
let _ = a.as_ptr() == b as *const _;
|
||||
|
||||
// Do not lint: we have two raw pointers already
|
||||
let _ = a.as_ptr() == b.as_ptr();
|
||||
|
||||
// Do not lint
|
||||
|
||||
let _ = mac!(a, b);
|
||||
let _ = another_mac!(a, b);
|
||||
|
||||
let a = &mut [1, 2, 3];
|
||||
let b = &mut [1, 2, 3];
|
||||
|
||||
let _ = core::ptr::eq(a.as_mut_ptr(), b as *mut [i32] as *mut _);
|
||||
//~^ ptr_eq
|
||||
let _ = core::ptr::eq(a.as_mut_ptr(), b.as_mut_ptr());
|
||||
//~^ ptr_eq
|
||||
// Do not lint: the rhs conversion is needed
|
||||
let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _;
|
||||
|
||||
// Do not lint: we have two raw pointers already
|
||||
let _ = a.as_mut_ptr() == b.as_mut_ptr();
|
||||
|
||||
let _ = a == b;
|
||||
let _ = core::ptr::eq(a, b);
|
||||
|
|
|
|||
|
|
@ -32,23 +32,25 @@ fn main() {
|
|||
//~^ ptr_eq
|
||||
let _ = a as *const _ == b as *const _;
|
||||
//~^ ptr_eq
|
||||
|
||||
// Do not lint: the rhs conversion is needed
|
||||
let _ = a.as_ptr() == b as *const _;
|
||||
//~^ ptr_eq
|
||||
|
||||
// Do not lint: we have two raw pointers already
|
||||
let _ = a.as_ptr() == b.as_ptr();
|
||||
//~^ ptr_eq
|
||||
|
||||
// Do not lint
|
||||
|
||||
let _ = mac!(a, b);
|
||||
let _ = another_mac!(a, b);
|
||||
|
||||
let a = &mut [1, 2, 3];
|
||||
let b = &mut [1, 2, 3];
|
||||
|
||||
// Do not lint: the rhs conversion is needed
|
||||
let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _;
|
||||
//~^ ptr_eq
|
||||
|
||||
// Do not lint: we have two raw pointers already
|
||||
let _ = a.as_mut_ptr() == b.as_mut_ptr();
|
||||
//~^ ptr_eq
|
||||
|
||||
let _ = a == b;
|
||||
let _ = core::ptr::eq(a, b);
|
||||
|
|
|
|||
|
|
@ -13,29 +13,5 @@ error: use `core::ptr::eq` when comparing raw pointers
|
|||
LL | let _ = a as *const _ == b as *const _;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::eq(a, b)`
|
||||
|
||||
error: use `core::ptr::eq` when comparing raw pointers
|
||||
--> tests/ui/ptr_eq_no_std.rs:35:13
|
||||
|
|
||||
LL | let _ = a.as_ptr() == b as *const _;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::eq(a.as_ptr(), b as *const _)`
|
||||
|
||||
error: use `core::ptr::eq` when comparing raw pointers
|
||||
--> tests/ui/ptr_eq_no_std.rs:37:13
|
||||
|
|
||||
LL | let _ = a.as_ptr() == b.as_ptr();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::eq(a.as_ptr(), b.as_ptr())`
|
||||
|
||||
error: use `core::ptr::eq` when comparing raw pointers
|
||||
--> tests/ui/ptr_eq_no_std.rs:48:13
|
||||
|
|
||||
LL | let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::eq(a.as_mut_ptr(), b as *mut [i32] as *mut _)`
|
||||
|
||||
error: use `core::ptr::eq` when comparing raw pointers
|
||||
--> tests/ui/ptr_eq_no_std.rs:50:13
|
||||
|
|
||||
LL | let _ = a.as_mut_ptr() == b.as_mut_ptr();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::eq(a.as_mut_ptr(), b.as_mut_ptr())`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -301,6 +301,11 @@ fn pattern() -> Result<(), PatternedError> {
|
|||
res
|
||||
}
|
||||
|
||||
fn expect_expr(a: Option<usize>) -> Option<usize> {
|
||||
#[expect(clippy::needless_question_mark)]
|
||||
Some(a?)
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
||||
// `?` is not the same as `return None;` if inside of a try block
|
||||
|
|
|
|||
|
|
@ -371,6 +371,11 @@ fn pattern() -> Result<(), PatternedError> {
|
|||
res
|
||||
}
|
||||
|
||||
fn expect_expr(a: Option<usize>) -> Option<usize> {
|
||||
#[expect(clippy::needless_question_mark)]
|
||||
Some(a?)
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
||||
// `?` is not the same as `return None;` if inside of a try block
|
||||
|
|
|
|||
|
|
@ -198,7 +198,7 @@ LL | | }
|
|||
| |_____^ help: replace it with: `func_returning_result()?;`
|
||||
|
||||
error: this block may be rewritten with the `?` operator
|
||||
--> tests/ui/question_mark.rs:390:13
|
||||
--> tests/ui/question_mark.rs:395:13
|
||||
|
|
||||
LL | / if a.is_none() {
|
||||
LL | |
|
||||
|
|
@ -208,7 +208,7 @@ LL | | }
|
|||
| |_____________^ help: replace it with: `a?;`
|
||||
|
||||
error: this `let...else` may be rewritten with the `?` operator
|
||||
--> tests/ui/question_mark.rs:451:5
|
||||
--> tests/ui/question_mark.rs:456:5
|
||||
|
|
||||
LL | / let Some(v) = bar.foo.owned.clone() else {
|
||||
LL | | return None;
|
||||
|
|
@ -216,7 +216,7 @@ LL | | };
|
|||
| |______^ help: replace it with: `let v = bar.foo.owned.clone()?;`
|
||||
|
||||
error: this `let...else` may be rewritten with the `?` operator
|
||||
--> tests/ui/question_mark.rs:466:5
|
||||
--> tests/ui/question_mark.rs:471:5
|
||||
|
|
||||
LL | / let Some(ref x) = foo.opt_x else {
|
||||
LL | | return None;
|
||||
|
|
@ -224,7 +224,7 @@ LL | | };
|
|||
| |______^ help: replace it with: `let x = foo.opt_x.as_ref()?;`
|
||||
|
||||
error: this `let...else` may be rewritten with the `?` operator
|
||||
--> tests/ui/question_mark.rs:476:5
|
||||
--> tests/ui/question_mark.rs:481:5
|
||||
|
|
||||
LL | / let Some(ref mut x) = foo.opt_x else {
|
||||
LL | | return None;
|
||||
|
|
@ -232,7 +232,7 @@ LL | | };
|
|||
| |______^ help: replace it with: `let x = foo.opt_x.as_mut()?;`
|
||||
|
||||
error: this `let...else` may be rewritten with the `?` operator
|
||||
--> tests/ui/question_mark.rs:487:5
|
||||
--> tests/ui/question_mark.rs:492:5
|
||||
|
|
||||
LL | / let Some(ref x @ ref y) = foo.opt_x else {
|
||||
LL | | return None;
|
||||
|
|
@ -240,7 +240,7 @@ LL | | };
|
|||
| |______^ help: replace it with: `let x @ y = foo.opt_x.as_ref()?;`
|
||||
|
||||
error: this `let...else` may be rewritten with the `?` operator
|
||||
--> tests/ui/question_mark.rs:491:5
|
||||
--> tests/ui/question_mark.rs:496:5
|
||||
|
|
||||
LL | / let Some(ref x @ WrapperStructWithString(_)) = bar else {
|
||||
LL | | return None;
|
||||
|
|
@ -248,7 +248,7 @@ LL | | };
|
|||
| |______^ help: replace it with: `let x @ &WrapperStructWithString(_) = bar.as_ref()?;`
|
||||
|
||||
error: this `let...else` may be rewritten with the `?` operator
|
||||
--> tests/ui/question_mark.rs:495:5
|
||||
--> tests/ui/question_mark.rs:500:5
|
||||
|
|
||||
LL | / let Some(ref mut x @ WrapperStructWithString(_)) = bar else {
|
||||
LL | | return None;
|
||||
|
|
@ -256,7 +256,7 @@ LL | | };
|
|||
| |______^ help: replace it with: `let x @ &mut WrapperStructWithString(_) = bar.as_mut()?;`
|
||||
|
||||
error: this block may be rewritten with the `?` operator
|
||||
--> tests/ui/question_mark.rs:517:5
|
||||
--> tests/ui/question_mark.rs:522:5
|
||||
|
|
||||
LL | / if arg.is_none() {
|
||||
LL | |
|
||||
|
|
@ -265,7 +265,7 @@ LL | | }
|
|||
| |_____^ help: replace it with: `arg?;`
|
||||
|
||||
error: this `match` expression can be replaced with `?`
|
||||
--> tests/ui/question_mark.rs:521:15
|
||||
--> tests/ui/question_mark.rs:526:15
|
||||
|
|
||||
LL | let val = match arg {
|
||||
| _______________^
|
||||
|
|
@ -276,7 +276,7 @@ LL | | };
|
|||
| |_____^ help: try instead: `arg?`
|
||||
|
||||
error: this `let...else` may be rewritten with the `?` operator
|
||||
--> tests/ui/question_mark.rs:531:5
|
||||
--> tests/ui/question_mark.rs:536:5
|
||||
|
|
||||
LL | / let Some(a) = *a else {
|
||||
LL | | return None;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
error: question mark operator was used
|
||||
error: the `?` operator was used
|
||||
--> tests/ui/question_mark_used.rs:11:5
|
||||
|
|
||||
LL | other_function()?;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
error: use the question mark operator instead of an `and_then` call
|
||||
error: use the `?` operator instead of an `and_then` call
|
||||
--> tests/ui/return_and_then.rs:5:9
|
||||
|
|
||||
LL | / opt.and_then(|n| {
|
||||
|
|
@ -20,7 +20,7 @@ LL + ret += n;
|
|||
LL + if n > 1 { Some(ret) } else { None }
|
||||
|
|
||||
|
||||
error: use the question mark operator instead of an `and_then` call
|
||||
error: use the `?` operator instead of an `and_then` call
|
||||
--> tests/ui/return_and_then.rs:14:9
|
||||
|
|
||||
LL | opt.and_then(|n| test_opt_block(Some(n)))
|
||||
|
|
@ -32,7 +32,7 @@ LL ~ let n = opt?;
|
|||
LL + test_opt_block(Some(n))
|
||||
|
|
||||
|
||||
error: use the question mark operator instead of an `and_then` call
|
||||
error: use the `?` operator instead of an `and_then` call
|
||||
--> tests/ui/return_and_then.rs:19:9
|
||||
|
|
||||
LL | gen_option(1).and_then(|n| test_opt_block(Some(n)))
|
||||
|
|
@ -44,7 +44,7 @@ LL ~ let n = gen_option(1)?;
|
|||
LL + test_opt_block(Some(n))
|
||||
|
|
||||
|
||||
error: use the question mark operator instead of an `and_then` call
|
||||
error: use the `?` operator instead of an `and_then` call
|
||||
--> tests/ui/return_and_then.rs:24:9
|
||||
|
|
||||
LL | opt.and_then(|n| if n > 1 { Ok(n + 1) } else { Err(n) })
|
||||
|
|
@ -56,7 +56,7 @@ LL ~ let n = opt?;
|
|||
LL + if n > 1 { Ok(n + 1) } else { Err(n) }
|
||||
|
|
||||
|
||||
error: use the question mark operator instead of an `and_then` call
|
||||
error: use the `?` operator instead of an `and_then` call
|
||||
--> tests/ui/return_and_then.rs:29:9
|
||||
|
|
||||
LL | opt.and_then(|n| test_res_block(Ok(n)))
|
||||
|
|
@ -68,7 +68,7 @@ LL ~ let n = opt?;
|
|||
LL + test_res_block(Ok(n))
|
||||
|
|
||||
|
||||
error: use the question mark operator instead of an `and_then` call
|
||||
error: use the `?` operator instead of an `and_then` call
|
||||
--> tests/ui/return_and_then.rs:35:9
|
||||
|
|
||||
LL | Some("").and_then(|x| if x.len() > 2 { Some(3) } else { None })
|
||||
|
|
@ -80,7 +80,7 @@ LL ~ let x = Some("")?;
|
|||
LL + if x.len() > 2 { Some(3) } else { None }
|
||||
|
|
||||
|
||||
error: use the question mark operator instead of an `and_then` call
|
||||
error: use the `?` operator instead of an `and_then` call
|
||||
--> tests/ui/return_and_then.rs:41:9
|
||||
|
|
||||
LL | / Some(match (vec![1, 2, 3], vec![1, 2, 4]) {
|
||||
|
|
|
|||
|
|
@ -266,7 +266,21 @@ mod fixable {
|
|||
// Issue #11968: The suggestion for this lint removes the parentheses and leave the code as
|
||||
// `*x.pow(2)` which tries to dereference the return value rather than `x`.
|
||||
fn issue_11968(x: &usize) -> usize {
|
||||
{ *x }.pow(2)
|
||||
(*x).pow(2)
|
||||
//~^ unnecessary_cast
|
||||
}
|
||||
|
||||
#[allow(clippy::cast_lossless)]
|
||||
fn issue_14640() {
|
||||
let x = 5usize;
|
||||
let vec: Vec<u64> = vec![1, 2, 3, 4, 5];
|
||||
assert_eq!(vec.len(), x);
|
||||
//~^ unnecessary_cast
|
||||
|
||||
let _ = (5i32 as i64).abs();
|
||||
//~^ unnecessary_cast
|
||||
|
||||
let _ = 5i32 as i64;
|
||||
//~^ unnecessary_cast
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -269,4 +269,18 @@ mod fixable {
|
|||
(*x as usize).pow(2)
|
||||
//~^ unnecessary_cast
|
||||
}
|
||||
|
||||
#[allow(clippy::cast_lossless)]
|
||||
fn issue_14640() {
|
||||
let x = 5usize;
|
||||
let vec: Vec<u64> = vec![1, 2, 3, 4, 5];
|
||||
assert_eq!(vec.len(), x as usize);
|
||||
//~^ unnecessary_cast
|
||||
|
||||
let _ = (5i32 as i64 as i64).abs();
|
||||
//~^ unnecessary_cast
|
||||
|
||||
let _ = 5i32 as i64 as i64;
|
||||
//~^ unnecessary_cast
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -245,7 +245,25 @@ error: casting to the same type is unnecessary (`usize` -> `usize`)
|
|||
--> tests/ui/unnecessary_cast.rs:269:9
|
||||
|
|
||||
LL | (*x as usize).pow(2)
|
||||
| ^^^^^^^^^^^^^ help: try: `{ *x }`
|
||||
| ^^^^^^^^^^^^^ help: try: `(*x)`
|
||||
|
||||
error: aborting due to 41 previous errors
|
||||
error: casting to the same type is unnecessary (`usize` -> `usize`)
|
||||
--> tests/ui/unnecessary_cast.rs:277:31
|
||||
|
|
||||
LL | assert_eq!(vec.len(), x as usize);
|
||||
| ^^^^^^^^^^ help: try: `x`
|
||||
|
||||
error: casting to the same type is unnecessary (`i64` -> `i64`)
|
||||
--> tests/ui/unnecessary_cast.rs:280:17
|
||||
|
|
||||
LL | let _ = (5i32 as i64 as i64).abs();
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: try: `(5i32 as i64)`
|
||||
|
||||
error: casting to the same type is unnecessary (`i64` -> `i64`)
|
||||
--> tests/ui/unnecessary_cast.rs:283:17
|
||||
|
|
||||
LL | let _ = 5i32 as i64 as i64;
|
||||
| ^^^^^^^^^^^^^^^^^^ help: try: `5i32 as i64`
|
||||
|
||||
error: aborting due to 44 previous errors
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue