Merge remote-tracking branch 'upstream/master' into rustup
This commit is contained in:
commit
415fdb2d1a
522 changed files with 5251 additions and 2556 deletions
|
|
@ -1,7 +1,8 @@
|
|||
use super::{contains_return, BIND_INSTEAD_OF_MAP};
|
||||
use clippy_utils::diagnostics::{multispan_sugg_with_applicability, span_lint_and_sugg, span_lint_and_then};
|
||||
use clippy_utils::peel_blocks;
|
||||
use clippy_utils::source::{snippet, snippet_with_context};
|
||||
use clippy_utils::{peel_blocks, visitors::find_all_ret_expressions};
|
||||
use clippy_utils::visitors::find_all_ret_expressions;
|
||||
use if_chain::if_chain;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
|
|
@ -87,7 +88,7 @@ pub(crate) trait BindInsteadOfMap {
|
|||
BIND_INSTEAD_OF_MAP,
|
||||
expr.span,
|
||||
&msg,
|
||||
"try this",
|
||||
"try",
|
||||
note,
|
||||
app,
|
||||
);
|
||||
|
|
@ -124,7 +125,7 @@ pub(crate) trait BindInsteadOfMap {
|
|||
span_lint_and_then(cx, BIND_INSTEAD_OF_MAP, expr.span, &msg, |diag| {
|
||||
multispan_sugg_with_applicability(
|
||||
diag,
|
||||
"try this",
|
||||
"try",
|
||||
Applicability::MachineApplicable,
|
||||
std::iter::once((span, Self::GOOD_METHOD_NAME.into())).chain(
|
||||
suggs
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use clippy_utils::source::{indent_of, reindent_multiline};
|
||||
use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt};
|
||||
use clippy_utils::ty::is_type_lang_item;
|
||||
use if_chain::if_chain;
|
||||
use rustc_ast::ast::LitKind;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Expr, ExprKind, LangItem};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_span::{source_map::Spanned, Span};
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::Span;
|
||||
|
||||
use super::CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@ use clippy_utils::{method_chain_args, path_def_id};
|
|||
use if_chain::if_chain;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_lint::Lint;
|
||||
use rustc_lint::{LateContext, Lint};
|
||||
use rustc_middle::ty;
|
||||
|
||||
/// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints.
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@ use if_chain::if_chain;
|
|||
use rustc_ast::ast;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_lint::Lint;
|
||||
use rustc_lint::{LateContext, Lint};
|
||||
|
||||
/// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints with `unwrap()`.
|
||||
pub(super) fn check(
|
||||
|
|
|
|||
|
|
@ -5,7 +5,9 @@ use clippy_utils::ty::is_copy;
|
|||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{BindingAnnotation, ByRef, Expr, ExprKind, MatchSource, Node, PatKind, QPath};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty::{self, adjustment::Adjust, print::with_forced_trimmed_paths};
|
||||
use rustc_middle::ty::adjustment::Adjust;
|
||||
use rustc_middle::ty::print::with_forced_trimmed_paths;
|
||||
use rustc_middle::ty::{self};
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
|
||||
use super::CLONE_ON_COPY;
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ pub(super) fn check(
|
|||
CLONE_ON_REF_PTR,
|
||||
expr.span,
|
||||
"using `.clone()` on a ref-counted pointer",
|
||||
"try this",
|
||||
"try",
|
||||
format!("{caller_type}::<{}>::clone(&{snippet})", subst.type_at(0)),
|
||||
app,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -8,8 +8,7 @@ use rustc_hir as hir;
|
|||
use rustc_lint::LateContext;
|
||||
use std::collections::VecDeque;
|
||||
|
||||
use super::method_call;
|
||||
use super::COLLAPSIBLE_STR_REPLACE;
|
||||
use super::{method_call, COLLAPSIBLE_STR_REPLACE};
|
||||
|
||||
pub(super) fn check<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
|
|
|
|||
|
|
@ -4,17 +4,12 @@ use clippy_utils::is_range_full;
|
|||
use clippy_utils::source::snippet;
|
||||
use clippy_utils::ty::is_type_lang_item;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::Expr;
|
||||
use rustc_hir::ExprKind;
|
||||
use rustc_hir::LangItem;
|
||||
use rustc_hir::Path;
|
||||
use rustc_hir::QPath;
|
||||
use rustc_hir::{Expr, ExprKind, LangItem, Path, QPath};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::query::Key;
|
||||
use rustc_middle::ty;
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_span::sym;
|
||||
use rustc_span::Symbol;
|
||||
use rustc_span::{sym, Symbol};
|
||||
|
||||
/// Checks if both types match the given diagnostic item, e.g.:
|
||||
///
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
use super::ERR_EXPECT;
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::msrvs::{self, Msrv};
|
||||
use clippy_utils::ty::has_debug_impl;
|
||||
use clippy_utils::ty::is_type_diagnostic_item;
|
||||
use clippy_utils::ty::{has_debug_impl, is_type_diagnostic_item};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty;
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ pub(super) fn check<'tcx>(
|
|||
EXPECT_FUN_CALL,
|
||||
span_replace_word,
|
||||
&format!("use of `{name}` followed by a function call"),
|
||||
"try this",
|
||||
"try",
|
||||
format!("unwrap_or_else({closure_args} panic!({sugg}))"),
|
||||
applicability,
|
||||
);
|
||||
|
|
@ -162,7 +162,7 @@ pub(super) fn check<'tcx>(
|
|||
EXPECT_FUN_CALL,
|
||||
span_replace_word,
|
||||
&format!("use of `{name}` followed by a function call"),
|
||||
"try this",
|
||||
"try",
|
||||
format!("unwrap_or_else({closure_args} {{ panic!(\"{{}}\", {arg_root_snippet}) }})"),
|
||||
applicability,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg:
|
|||
EXTEND_WITH_DRAIN,
|
||||
expr.span,
|
||||
"use of `extend` instead of `append` for adding the full range of a second vector",
|
||||
"try this",
|
||||
"try",
|
||||
format!(
|
||||
"{}.append({}{})",
|
||||
snippet_with_applicability(cx, recv.span, "..", &mut applicability),
|
||||
|
|
|
|||
|
|
@ -13,9 +13,7 @@ use rustc_span::source_map::Span;
|
|||
use rustc_span::symbol::{sym, Symbol};
|
||||
use std::borrow::Cow;
|
||||
|
||||
use super::MANUAL_FILTER_MAP;
|
||||
use super::MANUAL_FIND_MAP;
|
||||
use super::OPTION_FILTER_MAP;
|
||||
use super::{MANUAL_FILTER_MAP, MANUAL_FIND_MAP, OPTION_FILTER_MAP};
|
||||
|
||||
fn is_method(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_name: Symbol) -> bool {
|
||||
match &expr.kind {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@ use clippy_utils::{is_expr_identity_function, is_trait_method};
|
|||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_span::{source_map::Span, sym};
|
||||
use rustc_span::source_map::Span;
|
||||
use rustc_span::sym;
|
||||
|
||||
use super::FILTER_MAP_IDENTITY;
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ pub(super) fn check<'tcx>(
|
|||
FILTER_MAP_NEXT,
|
||||
expr.span,
|
||||
msg,
|
||||
"try this",
|
||||
"try",
|
||||
format!("{iter_snippet}.find_map({filter_snippet})"),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
|
||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
|
||||
use clippy_utils::source::snippet;
|
||||
use clippy_utils::ty::implements_trait;
|
||||
use rustc_ast::{BindingAnnotation, Mutability};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
use rustc_lint::LateContext;
|
||||
|
|
@ -8,6 +9,21 @@ use rustc_span::sym;
|
|||
|
||||
use super::FILTER_NEXT;
|
||||
|
||||
fn path_to_local(expr: &hir::Expr<'_>) -> Option<hir::HirId> {
|
||||
match expr.kind {
|
||||
hir::ExprKind::Field(f, _) => path_to_local(f),
|
||||
hir::ExprKind::Index(recv, _) => path_to_local(recv),
|
||||
hir::ExprKind::Path(hir::QPath::Resolved(
|
||||
_,
|
||||
hir::Path {
|
||||
res: rustc_hir::def::Res::Local(local),
|
||||
..
|
||||
},
|
||||
)) => Some(*local),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// lint use of `filter().next()` for `Iterators`
|
||||
pub(super) fn check<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
|
|
@ -26,15 +42,30 @@ pub(super) fn check<'tcx>(
|
|||
if filter_snippet.lines().count() <= 1 {
|
||||
let iter_snippet = snippet(cx, recv.span, "..");
|
||||
// add note if not multi-line
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
FILTER_NEXT,
|
||||
expr.span,
|
||||
msg,
|
||||
"try this",
|
||||
format!("{iter_snippet}.find({filter_snippet})"),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
span_lint_and_then(cx, FILTER_NEXT, expr.span, msg, |diag| {
|
||||
let (applicability, pat) = if let Some(id) = path_to_local(recv)
|
||||
&& let Some(hir::Node::Pat(pat)) = cx.tcx.hir().find(id)
|
||||
&& let hir::PatKind::Binding(BindingAnnotation(_, Mutability::Not), _, ident, _) = pat.kind
|
||||
{
|
||||
(Applicability::Unspecified, Some((pat.span, ident)))
|
||||
} else {
|
||||
(Applicability::MachineApplicable, None)
|
||||
};
|
||||
|
||||
diag.span_suggestion(
|
||||
expr.span,
|
||||
"try",
|
||||
format!("{iter_snippet}.find({filter_snippet})"),
|
||||
applicability,
|
||||
);
|
||||
|
||||
if let Some((pat_span, ident)) = pat {
|
||||
diag.span_help(
|
||||
pat_span,
|
||||
format!("you will also need to make `{ident}` mutable, because `find` takes `&mut self`"),
|
||||
);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
span_lint(cx, FILTER_NEXT, expr.span, msg);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@ use clippy_utils::{is_expr_identity_function, is_trait_method};
|
|||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_span::{source_map::Span, sym};
|
||||
use rustc_span::source_map::Span;
|
||||
use rustc_span::sym;
|
||||
|
||||
use super::FLAT_MAP_IDENTITY;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ use rustc_errors::Applicability;
|
|||
use rustc_hir as hir;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty;
|
||||
use rustc_span::{source_map::Span, sym};
|
||||
use rustc_span::source_map::Span;
|
||||
use rustc_span::sym;
|
||||
|
||||
use super::FLAT_MAP_OPTION;
|
||||
use clippy_utils::ty::is_type_diagnostic_item;
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ pub(super) fn check<'tcx>(
|
|||
GET_UNWRAP,
|
||||
span,
|
||||
&format!("called `.get{mut_str}().unwrap()` on a {caller_type}. Using `[]` is more clear and more concise"),
|
||||
"try this",
|
||||
"try",
|
||||
format!(
|
||||
"{borrow_str}{}[{get_args_str}]",
|
||||
snippet_with_applicability(cx, recv.span, "..", &mut applicability)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use rustc_errors::Applicability;
|
|||
use rustc_hir as hir;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::symbol::{Symbol, sym};
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
|
||||
use super::INEFFICIENT_TO_STRING;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@ use clippy_utils::diagnostics::span_lint_and_help;
|
|||
use clippy_utils::is_trait_method;
|
||||
use rustc_hir as hir;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_span::{source_map::Span, sym};
|
||||
use rustc_span::source_map::Span;
|
||||
use rustc_span::sym;
|
||||
|
||||
use super::INSPECT_FOR_EACH;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
//! Lint for `c.is_digit(10)`
|
||||
|
||||
use super::IS_DIGIT_ASCII_RADIX;
|
||||
use clippy_utils::consts::{constant_full_int, FullInt};
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::msrvs::{self, Msrv};
|
||||
use clippy_utils::{
|
||||
consts::constant_full_int, consts::FullInt, diagnostics::span_lint_and_sugg, source::snippet_with_applicability,
|
||||
};
|
||||
use clippy_utils::source::snippet_with_applicability;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::Expr;
|
||||
use rustc_lint::LateContext;
|
||||
|
|
|
|||
|
|
@ -9,8 +9,7 @@ use clippy_utils::visitors::is_local_used;
|
|||
use rustc_hir::{BindingAnnotation, Body, BorrowKind, ByRef, Expr, ExprKind, Mutability, Pat, PatKind};
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
use rustc_middle::ty;
|
||||
use rustc_span::sym;
|
||||
use rustc_span::Span;
|
||||
use rustc_span::{sym, Span};
|
||||
|
||||
/// lint use of:
|
||||
/// - `hashmap.iter().map(|(_, v)| v)`
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ pub(super) fn check<'tcx>(
|
|||
if let Some(mut snip) = snippet_opt(cx, method_span) {
|
||||
snip.push_str(trailing_clone);
|
||||
let replace_span = expr.span.with_lo(cloned_recv.span.hi());
|
||||
diag.span_suggestion(replace_span, "try this", snip, Applicability::MachineApplicable);
|
||||
diag.span_suggestion(replace_span, "try", snip, Applicability::MachineApplicable);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::is_trait_method;
|
||||
use clippy_utils::path_to_local;
|
||||
use clippy_utils::source::snippet;
|
||||
use clippy_utils::{is_trait_method, path_to_local};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::{BindingAnnotation, Node, PatKind};
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, span
|
|||
ITER_WITH_DRAIN,
|
||||
span.with_hi(expr.span.hi()),
|
||||
&format!("`drain(..)` used on a `{ty_name}`"),
|
||||
"try this",
|
||||
"try",
|
||||
"into_iter()".to_string(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -21,13 +21,13 @@ pub fn check(
|
|||
return;
|
||||
}
|
||||
|
||||
let Some(mm) = is_min_or_max(cx, unwrap_arg) else { return };
|
||||
let Some(mm) = is_min_or_max(cx, unwrap_arg) else {
|
||||
return;
|
||||
};
|
||||
|
||||
if ty.is_signed() {
|
||||
use self::{
|
||||
MinMax::{Max, Min},
|
||||
Sign::{Neg, Pos},
|
||||
};
|
||||
use self::MinMax::{Max, Min};
|
||||
use self::Sign::{Neg, Pos};
|
||||
|
||||
let Some(sign) = lit_sign(arith_rhs) else {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ pub(super) fn check(
|
|||
MANUAL_STR_REPEAT,
|
||||
collect_expr.span,
|
||||
"manual implementation of `str::repeat` using iterators",
|
||||
"try this",
|
||||
"try",
|
||||
format!("{val_str}.repeat({count_snip})"),
|
||||
app
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,15 +1,11 @@
|
|||
use clippy_utils::{
|
||||
diagnostics::span_lint_and_sugg,
|
||||
is_from_proc_macro,
|
||||
msrvs::{Msrv, ITERATOR_TRY_FOLD},
|
||||
source::snippet_opt,
|
||||
ty::implements_trait,
|
||||
};
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::is_from_proc_macro;
|
||||
use clippy_utils::msrvs::{Msrv, ITERATOR_TRY_FOLD};
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use clippy_utils::ty::implements_trait;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{
|
||||
def::{DefKind, Res},
|
||||
Expr, ExprKind,
|
||||
};
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::{Expr, ExprKind};
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_span::Span;
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, iter: &hir::Expr
|
|||
MAP_COLLECT_RESULT_UNIT,
|
||||
expr.span,
|
||||
"`.map().collect()` can be replaced with `.try_for_each()`",
|
||||
"try this",
|
||||
"try",
|
||||
format!(
|
||||
"{}.try_for_each({})",
|
||||
snippet(cx, iter.span, ".."),
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ use rustc_errors::Applicability;
|
|||
use rustc_hir::Expr;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty;
|
||||
use rustc_span::{symbol::sym, Span};
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::Span;
|
||||
|
||||
use super::MAP_FLATTEN;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ use clippy_utils::{is_expr_identity_function, is_trait_method};
|
|||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_span::{source_map::Span, sym};
|
||||
use rustc_span::source_map::Span;
|
||||
use rustc_span::sym;
|
||||
|
||||
use super::MAP_IDENTITY;
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@ use rustc_span::symbol::sym;
|
|||
use super::MAP_UNWRAP_OR;
|
||||
|
||||
/// lint use of `map().unwrap_or_else()` for `Option`s and `Result`s
|
||||
/// Return true if lint triggered
|
||||
///
|
||||
/// Returns true if the lint was emitted
|
||||
pub(super) fn check<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
expr: &'tcx hir::Expr<'_>,
|
||||
|
|
@ -63,7 +64,7 @@ pub(super) fn check<'tcx>(
|
|||
MAP_UNWRAP_OR,
|
||||
expr.span,
|
||||
msg,
|
||||
"try this",
|
||||
"try",
|
||||
format!("{var_snippet}.map_or_else({unwrap_snippet}, {map_snippet})"),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ mod or_fun_call;
|
|||
mod or_then_unwrap;
|
||||
mod path_buf_push_overwrite;
|
||||
mod range_zip_with_len;
|
||||
mod read_line_without_trim;
|
||||
mod repeat_once;
|
||||
mod search_is_some;
|
||||
mod seek_from_current;
|
||||
|
|
@ -88,6 +89,7 @@ mod suspicious_command_arg_space;
|
|||
mod suspicious_map;
|
||||
mod suspicious_splitn;
|
||||
mod suspicious_to_owned;
|
||||
mod type_id_on_box;
|
||||
mod uninit_assumed_init;
|
||||
mod unit_hash;
|
||||
mod unnecessary_filter_map;
|
||||
|
|
@ -2925,6 +2927,37 @@ declare_clippy_lint! {
|
|||
"use of sort() when sort_unstable() is equivalent"
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Looks for calls to `<Box<dyn Any> as Any>::type_id`.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// This most certainly does not do what the user expects and is very easy to miss.
|
||||
/// Calling `type_id` on a `Box<dyn Any>` calls `type_id` on the `Box<..>` itself,
|
||||
/// so this will return the `TypeId` of the `Box<dyn Any>` type (not the type id
|
||||
/// of the value referenced by the box!).
|
||||
///
|
||||
/// ### Example
|
||||
/// ```rust,ignore
|
||||
/// use std::any::{Any, TypeId};
|
||||
///
|
||||
/// let any_box: Box<dyn Any> = Box::new(42_i32);
|
||||
/// assert_eq!(any_box.type_id(), TypeId::of::<i32>()); // ⚠️ this fails!
|
||||
/// ```
|
||||
/// Use instead:
|
||||
/// ```rust
|
||||
/// use std::any::{Any, TypeId};
|
||||
///
|
||||
/// let any_box: Box<dyn Any> = Box::new(42_i32);
|
||||
/// assert_eq!((*any_box).type_id(), TypeId::of::<i32>());
|
||||
/// // ^ dereference first, to call `type_id` on `dyn Any`
|
||||
/// ```
|
||||
#[clippy::version = "1.72.0"]
|
||||
pub TYPE_ID_ON_BOX,
|
||||
suspicious,
|
||||
"calling `.type_id()` on `Box<dyn Any>`"
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Detects `().hash(_)`.
|
||||
|
|
@ -3316,6 +3349,35 @@ declare_clippy_lint! {
|
|||
"checks for usage of `Iterator::fold` with a type that implements `Try`"
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// Looks for calls to [`Stdin::read_line`] to read a line from the standard input
|
||||
/// into a string, then later attempting to parse this string into a type without first trimming it, which will
|
||||
/// always fail because the string has a trailing newline in it.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// The `.parse()` call will always fail.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```rust,ignore
|
||||
/// let mut input = String::new();
|
||||
/// std::io::stdin().read_line(&mut input).expect("Failed to read a line");
|
||||
/// let num: i32 = input.parse().expect("Not a number!");
|
||||
/// assert_eq!(num, 42); // we never even get here!
|
||||
/// ```
|
||||
/// Use instead:
|
||||
/// ```rust,ignore
|
||||
/// let mut input = String::new();
|
||||
/// std::io::stdin().read_line(&mut input).expect("Failed to read a line");
|
||||
/// let num: i32 = input.trim_end().parse().expect("Not a number!");
|
||||
/// // ^^^^^^^^^^^ remove the trailing newline
|
||||
/// assert_eq!(num, 42);
|
||||
/// ```
|
||||
#[clippy::version = "1.72.0"]
|
||||
pub READ_LINE_WITHOUT_TRIM,
|
||||
correctness,
|
||||
"calling `Stdin::read_line`, then trying to parse it without first trimming"
|
||||
}
|
||||
|
||||
pub struct Methods {
|
||||
avoid_breaking_exported_api: bool,
|
||||
msrv: Msrv,
|
||||
|
|
@ -3389,6 +3451,7 @@ impl_lint_pass!(Methods => [
|
|||
STRING_EXTEND_CHARS,
|
||||
ITER_CLONED_COLLECT,
|
||||
ITER_WITH_DRAIN,
|
||||
TYPE_ID_ON_BOX,
|
||||
USELESS_ASREF,
|
||||
UNNECESSARY_FOLD,
|
||||
UNNECESSARY_FILTER_MAP,
|
||||
|
|
@ -3435,6 +3498,7 @@ impl_lint_pass!(Methods => [
|
|||
REPEAT_ONCE,
|
||||
STABLE_SORT_PRIMITIVE,
|
||||
UNIT_HASH,
|
||||
READ_LINE_WITHOUT_TRIM,
|
||||
UNNECESSARY_SORT_BY,
|
||||
VEC_RESIZE_TO_ZERO,
|
||||
VERBOSE_FILE_READS,
|
||||
|
|
@ -3846,6 +3910,9 @@ impl Methods {
|
|||
("read_to_string", [_]) => {
|
||||
verbose_file_reads::check(cx, expr, recv, verbose_file_reads::READ_TO_STRING_MSG);
|
||||
},
|
||||
("read_line", [arg]) => {
|
||||
read_line_without_trim::check(cx, expr, recv, arg);
|
||||
}
|
||||
("repeat", [arg]) => {
|
||||
repeat_once::check(cx, expr, recv, arg);
|
||||
},
|
||||
|
|
@ -3914,6 +3981,9 @@ impl Methods {
|
|||
("to_os_string" | "to_path_buf" | "to_vec", []) => {
|
||||
implicit_clone::check(cx, name, expr, recv);
|
||||
},
|
||||
("type_id", []) => {
|
||||
type_id_on_box::check(cx, recv, expr.span);
|
||||
}
|
||||
("unwrap", []) => {
|
||||
match method_call(recv) {
|
||||
Some(("get", recv, [get_arg], _, _)) => {
|
||||
|
|
@ -3949,7 +4019,7 @@ impl Methods {
|
|||
}
|
||||
unnecessary_literal_unwrap::check(cx, expr, recv, name, args);
|
||||
},
|
||||
("unwrap_or_default", []) => {
|
||||
("unwrap_or_default" | "unwrap_unchecked" | "unwrap_err_unchecked", []) => {
|
||||
unnecessary_literal_unwrap::check(cx, expr, recv, name, args);
|
||||
}
|
||||
("unwrap_or_else", [u_arg]) => {
|
||||
|
|
@ -4134,7 +4204,7 @@ impl SelfKind {
|
|||
};
|
||||
|
||||
let Some(trait_def_id) = cx.tcx.get_diagnostic_item(trait_sym) else {
|
||||
return false
|
||||
return false;
|
||||
};
|
||||
implements_trait(cx, ty, trait_def_id, &[parent_ty.into()])
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::{expr_custom_deref_adjustment, ty::is_type_diagnostic_item};
|
||||
use clippy_utils::expr_custom_deref_adjustment;
|
||||
use clippy_utils::ty::is_type_diagnostic_item;
|
||||
use if_chain::if_chain;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Expr, Mutability};
|
||||
|
|
|
|||
|
|
@ -4,10 +4,9 @@ use clippy_utils::source::{snippet, snippet_with_applicability};
|
|||
use clippy_utils::sugg::Sugg;
|
||||
use clippy_utils::ty::{is_type_diagnostic_item, make_normalized_projection, make_projection};
|
||||
use clippy_utils::{
|
||||
can_move_expr_to_closure, get_enclosing_block, get_parent_node, is_trait_method, path_to_local, path_to_local_id,
|
||||
CaptureKind,
|
||||
can_move_expr_to_closure, fn_def_id, get_enclosing_block, get_parent_node, higher, is_trait_method, path_to_local,
|
||||
path_to_local_id, CaptureKind,
|
||||
};
|
||||
use clippy_utils::{fn_def_id, higher};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::{Applicability, MultiSpan};
|
||||
use rustc_hir::intravisit::{walk_block, walk_expr, Visitor};
|
||||
|
|
|
|||
|
|
@ -17,7 +17,9 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, name
|
|||
|
||||
if is_type_diagnostic_item(cx, outer_ty, sym::Option) && outer_ty == typeck.expr_ty(recv) {
|
||||
if name == "as_deref_mut" && recv.is_syntactic_place_expr() {
|
||||
let Res::Local(binding_id) = path_res(cx, recv) else { return };
|
||||
let Res::Local(binding_id) = path_res(cx, recv) else {
|
||||
return;
|
||||
};
|
||||
|
||||
if local_used_after_expr(cx, binding_id, recv) {
|
||||
return;
|
||||
|
|
@ -29,7 +31,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, name
|
|||
NEEDLESS_OPTION_AS_DEREF,
|
||||
expr.span,
|
||||
"derefed type is same as origin",
|
||||
"try this",
|
||||
"try",
|
||||
snippet_opt(cx, recv.span).unwrap(),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use super::OBFUSCATED_IF_ELSE;
|
||||
use clippy_utils::{diagnostics::span_lint_and_sugg, source::snippet_with_applicability};
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::snippet_with_applicability;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
use rustc_lint::LateContext;
|
||||
|
|
|
|||
|
|
@ -8,8 +8,7 @@ use rustc_hir::LangItem::{OptionNone, OptionSome};
|
|||
use rustc_lint::LateContext;
|
||||
use rustc_span::symbol::sym;
|
||||
|
||||
use super::OPTION_MAP_OR_NONE;
|
||||
use super::RESULT_MAP_OR_INTO_OPTION;
|
||||
use super::{OPTION_MAP_OR_NONE, RESULT_MAP_OR_INTO_OPTION};
|
||||
|
||||
// The expression inside a closure may or may not have surrounding braces
|
||||
// which causes problems when generating a suggestion.
|
||||
|
|
|
|||
|
|
@ -1,17 +1,12 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::msrvs::{self, Msrv};
|
||||
use clippy_utils::source::snippet_with_applicability;
|
||||
use clippy_utils::ty::is_copy;
|
||||
use clippy_utils::ty::is_type_diagnostic_item;
|
||||
use clippy_utils::ty::{is_copy, is_type_diagnostic_item};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_hir::intravisit::{walk_path, Visitor};
|
||||
use rustc_hir::ExprKind;
|
||||
use rustc_hir::Node;
|
||||
use rustc_hir::PatKind;
|
||||
use rustc_hir::QPath;
|
||||
use rustc_hir::{self, HirId, Path};
|
||||
use rustc_hir::{self, ExprKind, HirId, Node, PatKind, Path, QPath};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::hir::nested_filter;
|
||||
use rustc_span::source_map::Span;
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ pub(super) fn check<'tcx>(
|
|||
OR_FUN_CALL,
|
||||
method_span.with_hi(span.hi()),
|
||||
&format!("use of `{name}` followed by a call to `{path}`"),
|
||||
"try this",
|
||||
"try",
|
||||
format!("{sugg}()"),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
|
|
@ -139,7 +139,7 @@ pub(super) fn check<'tcx>(
|
|||
OR_FUN_CALL,
|
||||
span_replace_word,
|
||||
&format!("use of `{name}` followed by a function call"),
|
||||
"try this",
|
||||
"try",
|
||||
format!("{name}_{suffix}({sugg})"),
|
||||
app,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::snippet_with_applicability;
|
||||
use clippy_utils::ty::is_type_diagnostic_item;
|
||||
use clippy_utils::{diagnostics::span_lint_and_sugg, is_res_lang_ctor, path_res};
|
||||
use clippy_utils::{is_res_lang_ctor, path_res};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{lang_items::LangItem, Expr, ExprKind};
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{Expr, ExprKind};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_span::{sym, Span};
|
||||
|
||||
|
|
@ -50,7 +52,7 @@ pub(super) fn check<'tcx>(
|
|||
OR_THEN_UNWRAP,
|
||||
unwrap_expr.span.with_lo(or_span.lo()),
|
||||
title,
|
||||
"try this",
|
||||
"try",
|
||||
suggestion,
|
||||
applicability,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
use clippy_utils::diagnostics::span_lint;
|
||||
use clippy_utils::source::snippet;
|
||||
use clippy_utils::{higher, SpanlessEq};
|
||||
use clippy_utils::{is_integer_const, is_trait_method};
|
||||
use clippy_utils::{higher, is_integer_const, is_trait_method, SpanlessEq};
|
||||
use if_chain::if_chain;
|
||||
use rustc_hir::{Expr, ExprKind, QPath};
|
||||
use rustc_lint::LateContext;
|
||||
|
|
|
|||
74
clippy_lints/src/methods/read_line_without_trim.rs
Normal file
74
clippy_lints/src/methods/read_line_without_trim.rs
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
use std::ops::ControlFlow;
|
||||
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
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, match_def_path};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_hir::{Expr, ExprKind, QPath};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::sym;
|
||||
|
||||
use super::READ_LINE_WITHOUT_TRIM;
|
||||
|
||||
/// Will a `.parse::<ty>()` call fail if the input has a trailing newline?
|
||||
fn parse_fails_on_trailing_newline(ty: Ty<'_>) -> bool {
|
||||
// only allow a very limited set of types for now, for which we 100% know parsing will fail
|
||||
matches!(ty.kind(), ty::Float(_) | ty::Bool | ty::Int(_) | ty::Uint(_))
|
||||
}
|
||||
|
||||
pub fn check(cx: &LateContext<'_>, call: &Expr<'_>, recv: &Expr<'_>, arg: &Expr<'_>) {
|
||||
if let Some(recv_adt) = cx.typeck_results().expr_ty(recv).ty_adt_def()
|
||||
&& match_def_path(cx, recv_adt.did(), &["std", "io", "stdio", "Stdin"])
|
||||
&& let ExprKind::Path(QPath::Resolved(_, path)) = arg.peel_borrows().kind
|
||||
&& let Res::Local(local_id) = path.res
|
||||
{
|
||||
// We've checked that `call` is a call to `Stdin::read_line()` with the right receiver,
|
||||
// now let's check if the first use of the string passed to `::read_line()` is
|
||||
// parsed into a type that will always fail if it has a trailing newline.
|
||||
for_each_local_use_after_expr(cx, local_id, call.hir_id, |expr| {
|
||||
if let Some(parent) = get_parent_expr(cx, expr)
|
||||
&& let ExprKind::MethodCall(segment, .., span) = parent.kind
|
||||
&& 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()
|
||||
&& let Some(ok_ty) = substs[0].as_type()
|
||||
&& parse_fails_on_trailing_newline(ok_ty)
|
||||
{
|
||||
let local_snippet = snippet(cx, expr.span, "<expr>");
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
READ_LINE_WITHOUT_TRIM,
|
||||
span,
|
||||
"calling `.parse()` without trimming the trailing newline character",
|
||||
|diag| {
|
||||
diag.span_note(call.span, "call to `.read_line()` here, \
|
||||
which leaves a trailing newline character in the buffer, \
|
||||
which in turn will cause `.parse()` to fail");
|
||||
|
||||
diag.span_suggestion(
|
||||
expr.span,
|
||||
"try",
|
||||
format!("{local_snippet}.trim_end()"),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// only consider the first use to prevent this scenario:
|
||||
// ```
|
||||
// let mut s = String::new();
|
||||
// std::io::stdin().read_line(&mut s);
|
||||
// s.pop();
|
||||
// let _x: i32 = s.parse().unwrap();
|
||||
// ```
|
||||
// this is actually fine, because the pop call removes the trailing newline.
|
||||
ControlFlow::<(), ()>::Break(())
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -3,10 +3,10 @@ use rustc_errors::Applicability;
|
|||
use rustc_hir::{Expr, ExprKind};
|
||||
use rustc_lint::LateContext;
|
||||
|
||||
use clippy_utils::{
|
||||
diagnostics::span_lint_and_sugg, get_trait_def_id, match_def_path, paths, source::snippet_with_applicability,
|
||||
ty::implements_trait,
|
||||
};
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::snippet_with_applicability;
|
||||
use clippy_utils::ty::implements_trait;
|
||||
use clippy_utils::{get_trait_def_id, match_def_path, paths};
|
||||
|
||||
use super::SEEK_FROM_CURRENT;
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ fn lint_needless(cx: &LateContext<'_>, method_name: &str, expr: &Expr<'_>, self_
|
|||
NEEDLESS_SPLITN,
|
||||
expr.span,
|
||||
&format!("unnecessary use of `{r}splitn`"),
|
||||
"try this",
|
||||
"try",
|
||||
format!(
|
||||
"{}.{r}split({})",
|
||||
snippet_with_context(cx, self_arg.span, expr.span.ctxt(), "..", &mut app).0,
|
||||
|
|
@ -110,7 +110,7 @@ fn check_manual_split_once(
|
|||
IterUsageKind::Nth(_) => return,
|
||||
};
|
||||
|
||||
span_lint_and_sugg(cx, MANUAL_SPLIT_ONCE, usage.span, msg, "try this", sugg, app);
|
||||
span_lint_and_sugg(cx, MANUAL_SPLIT_ONCE, usage.span, msg, "try", sugg, app);
|
||||
}
|
||||
|
||||
/// checks for
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr
|
|||
STRING_EXTEND_CHARS,
|
||||
expr.span,
|
||||
"calling `.extend(_.chars())`",
|
||||
"try this",
|
||||
"try",
|
||||
format!(
|
||||
"{}.push_str({ref_str}{})",
|
||||
snippet_with_applicability(cx, recv.span, "..", &mut applicability),
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::paths;
|
||||
use clippy_utils::ty::match_type;
|
||||
use rustc_ast as ast;
|
||||
use rustc_errors::{Applicability, Diagnostic};
|
||||
use rustc_hir as hir;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_span::Span;
|
||||
use {rustc_ast as ast, rustc_hir as hir};
|
||||
|
||||
use super::SUSPICIOUS_COMMAND_ARG_SPACE;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@ use if_chain::if_chain;
|
|||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty::{self, print::with_forced_trimmed_paths};
|
||||
use rustc_middle::ty::print::with_forced_trimmed_paths;
|
||||
use rustc_middle::ty::{self};
|
||||
use rustc_span::sym;
|
||||
|
||||
use super::SUSPICIOUS_TO_OWNED;
|
||||
|
|
|
|||
62
clippy_lints/src/methods/type_id_on_box.rs
Normal file
62
clippy_lints/src/methods/type_id_on_box.rs
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
use crate::methods::TYPE_ID_ON_BOX;
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::source::snippet;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::Expr;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty::adjustment::{Adjust, Adjustment};
|
||||
use rustc_middle::ty::{self, ExistentialPredicate, Ty};
|
||||
use rustc_span::{sym, Span};
|
||||
|
||||
fn is_dyn_any(cx: &LateContext<'_>, ty: Ty<'_>) -> bool {
|
||||
if let ty::Dynamic(preds, ..) = ty.kind() {
|
||||
preds.iter().any(|p| match p.skip_binder() {
|
||||
ExistentialPredicate::Trait(tr) => cx.tcx.is_diagnostic_item(sym::Any, tr.def_id),
|
||||
_ => false,
|
||||
})
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn check(cx: &LateContext<'_>, receiver: &Expr<'_>, call_span: Span) {
|
||||
let recv_adjusts = cx.typeck_results().expr_adjustments(receiver);
|
||||
|
||||
if let Some(Adjustment { target: recv_ty, .. }) = recv_adjusts.last()
|
||||
&& let ty::Ref(_, ty, _) = recv_ty.kind()
|
||||
&& let ty::Adt(adt, substs) = ty.kind()
|
||||
&& adt.is_box()
|
||||
&& is_dyn_any(cx, substs.type_at(0))
|
||||
{
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
TYPE_ID_ON_BOX,
|
||||
call_span,
|
||||
"calling `.type_id()` on a `Box<dyn Any>`",
|
||||
|diag| {
|
||||
let derefs = recv_adjusts
|
||||
.iter()
|
||||
.filter(|adj| matches!(adj.kind, Adjust::Deref(None)))
|
||||
.count();
|
||||
|
||||
let mut sugg = "*".repeat(derefs + 1);
|
||||
sugg += &snippet(cx, receiver.span, "<expr>");
|
||||
|
||||
diag.note(
|
||||
"this returns the type id of the literal type `Box<dyn Any>` instead of the \
|
||||
type id of the boxed value, which is most likely not what you want"
|
||||
)
|
||||
.note(
|
||||
"if this is intentional, use `TypeId::of::<Box<dyn Any>>()` instead, \
|
||||
which makes it more clear"
|
||||
)
|
||||
.span_suggestion(
|
||||
receiver.span,
|
||||
"consider dereferencing first",
|
||||
format!("({sugg})"),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
use clippy_utils::diagnostics::span_lint;
|
||||
use clippy_utils::{is_path_diagnostic_item, ty::is_uninit_value_valid_for_ty};
|
||||
use clippy_utils::is_path_diagnostic_item;
|
||||
use clippy_utils::ty::is_uninit_value_valid_for_ty;
|
||||
use if_chain::if_chain;
|
||||
use rustc_hir as hir;
|
||||
use rustc_lint::LateContext;
|
||||
|
|
|
|||
|
|
@ -11,8 +11,7 @@ use rustc_lint::LateContext;
|
|||
use rustc_middle::ty;
|
||||
use rustc_span::sym;
|
||||
|
||||
use super::UNNECESSARY_FILTER_MAP;
|
||||
use super::UNNECESSARY_FIND_MAP;
|
||||
use super::{UNNECESSARY_FILTER_MAP, UNNECESSARY_FIND_MAP};
|
||||
|
||||
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>, arg: &'tcx hir::Expr<'tcx>, name: &str) {
|
||||
if !is_trait_method(cx, expr, sym::Iterator) {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@ use rustc_hir as hir;
|
|||
use rustc_hir::PatKind;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty;
|
||||
use rustc_span::{source_map::Span, sym};
|
||||
use rustc_span::source_map::Span;
|
||||
use rustc_span::sym;
|
||||
|
||||
use super::UNNECESSARY_FOLD;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@ use clippy_utils::source::snippet_opt;
|
|||
use clippy_utils::ty::{get_iterator_item_ty, implements_trait};
|
||||
use clippy_utils::{fn_def_id, get_parent_expr};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{def_id::DefId, Expr, ExprKind};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::{Expr, ExprKind};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_span::{sym, Symbol};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use clippy_utils::{diagnostics::span_lint_and_sugg, ty::is_type_lang_item};
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::ty::is_type_lang_item;
|
||||
use rustc_ast::ast::LitKind;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Expr, ExprKind, LangItem};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use clippy_utils::{diagnostics::span_lint_and_then, is_res_lang_ctor, last_path_segment, path_res, MaybePath};
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::{is_res_lang_ctor, last_path_segment, path_res, MaybePath};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
use rustc_lint::LateContext;
|
||||
|
|
@ -29,6 +30,11 @@ pub(super) fn check(
|
|||
args: &[hir::Expr<'_>],
|
||||
) {
|
||||
let init = clippy_utils::expr_or_init(cx, recv);
|
||||
if init.span.from_expansion() {
|
||||
// don't lint if the receiver or binding initializer comes from a macro
|
||||
// (e.g. `let x = option_env!(..); x.unwrap()`)
|
||||
return;
|
||||
}
|
||||
|
||||
let (constructor, call_args, ty) = if let hir::ExprKind::Call(call, call_args) = init.kind {
|
||||
let Some(qpath) = call.qpath_opt() else { return };
|
||||
|
|
@ -62,6 +68,22 @@ pub(super) fn check(
|
|||
(expr.span.with_hi(args[0].span.lo()), "panic!(".to_string()),
|
||||
(expr.span.with_lo(args[0].span.hi()), ")".to_string()),
|
||||
]),
|
||||
("Some" | "Ok", "unwrap_unchecked", _) | ("Err", "unwrap_err_unchecked", _) => {
|
||||
let mut suggs = vec![
|
||||
(recv.span.with_hi(call_args[0].span.lo()), String::new()),
|
||||
(expr.span.with_lo(call_args[0].span.hi()), String::new()),
|
||||
];
|
||||
// try to also remove the unsafe block if present
|
||||
if let hir::Node::Block(block) = cx.tcx.hir().get_parent(expr.hir_id)
|
||||
&& let hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::UserProvided) = block.rules
|
||||
{
|
||||
suggs.extend([
|
||||
(block.span.shrink_to_lo().to(expr.span.shrink_to_lo()), String::new()),
|
||||
(expr.span.shrink_to_hi().to(block.span.shrink_to_hi()), String::new())
|
||||
]);
|
||||
}
|
||||
Some(suggs)
|
||||
},
|
||||
(_, _, Some(_)) => None,
|
||||
("Ok", "unwrap_err", None) | ("Err", "unwrap", None) => Some(vec![
|
||||
(
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ use if_chain::if_chain;
|
|||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Closure, Expr, ExprKind, Mutability, Param, Pat, PatKind, Path, PathSegment, QPath};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty::{self, subst::GenericArgKind};
|
||||
use rustc_middle::ty::subst::GenericArgKind;
|
||||
use rustc_middle::ty::{self};
|
||||
use rustc_span::sym;
|
||||
use rustc_span::symbol::Ident;
|
||||
use std::iter;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@ use clippy_utils::ty::{get_iterator_item_ty, implements_trait, is_copy, peel_mid
|
|||
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, return_ty};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{def_id::DefId, BorrowKind, Expr, ExprKind, ItemKind, Node};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::{BorrowKind, Expr, ExprKind, ItemKind, Node};
|
||||
use rustc_hir_typeck::{FnCtxt, Inherited};
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_lint::LateContext;
|
||||
|
|
@ -16,7 +17,8 @@ use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref};
|
|||
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef};
|
||||
use rustc_middle::ty::{self, ClauseKind, EarlyBinder, ParamTy, ProjectionPredicate, TraitPredicate, Ty};
|
||||
use rustc_span::{sym, Symbol};
|
||||
use rustc_trait_selection::traits::{query::evaluate_obligation::InferCtxtExt as _, Obligation, ObligationCause};
|
||||
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
|
||||
use rustc_trait_selection::traits::{Obligation, ObligationCause};
|
||||
|
||||
use super::UNNECESSARY_TO_OWNED;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
//! Lint for `some_result_or_option.unwrap_or_else(Default::default)`
|
||||
|
||||
use super::UNWRAP_OR_ELSE_DEFAULT;
|
||||
use clippy_utils::{
|
||||
diagnostics::span_lint_and_sugg, is_default_equivalent_call, source::snippet_with_applicability,
|
||||
ty::is_type_diagnostic_item,
|
||||
};
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::is_default_equivalent_call;
|
||||
use clippy_utils::source::snippet_with_applicability;
|
||||
use clippy_utils::ty::is_type_diagnostic_item;
|
||||
use rustc_ast::ast::LitKind;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, call_name: &str,
|
|||
USELESS_ASREF,
|
||||
expr.span,
|
||||
&format!("this call to `{call_name}` does nothing"),
|
||||
"try this",
|
||||
"try",
|
||||
snippet_with_applicability(cx, recvr.span, "..", &mut applicability).to_string(),
|
||||
applicability,
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue