Merge remote-tracking branch 'upstream/master' into rustup
This commit is contained in:
commit
95dc7be92f
358 changed files with 3171 additions and 2172 deletions
|
|
@ -1,6 +1,6 @@
|
|||
use clippy_config::msrvs::{self, Msrv};
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::is_trait_method;
|
||||
use clippy_utils::msrvs::{self, Msrv};
|
||||
use clippy_utils::ty::{get_iterator_item_ty, is_copy};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::Expr;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use super::ERR_EXPECT;
|
||||
use clippy_config::msrvs::{self, Msrv};
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::msrvs::{self, Msrv};
|
||||
use clippy_utils::ty::{has_debug_impl, is_type_diagnostic_item};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lint::LateContext;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use clippy_config::msrvs::{self, Msrv};
|
||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
|
||||
use clippy_utils::is_trait_method;
|
||||
use clippy_utils::msrvs::{self, Msrv};
|
||||
use clippy_utils::source::snippet;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::snippet_with_applicability;
|
||||
use clippy_utils::ty::is_type_diagnostic_item;
|
||||
use if_chain::if_chain;
|
||||
use rustc_ast::LitKind;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::sym;
|
||||
|
||||
use super::GET_FIRST;
|
||||
|
||||
|
|
@ -18,20 +20,34 @@ pub(super) fn check<'tcx>(
|
|||
if_chain! {
|
||||
if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
|
||||
if let Some(impl_id) = cx.tcx.impl_of_method(method_id);
|
||||
if cx.tcx.type_of(impl_id).instantiate_identity().is_slice();
|
||||
let identity = cx.tcx.type_of(impl_id).instantiate_identity();
|
||||
if let hir::ExprKind::Lit(Spanned { node: LitKind::Int(0, _), .. }) = arg.kind;
|
||||
then {
|
||||
let mut app = Applicability::MachineApplicable;
|
||||
let slice_name = snippet_with_applicability(cx, recv.span, "..", &mut app);
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
GET_FIRST,
|
||||
expr.span,
|
||||
&format!("accessing first element with `{slice_name}.get(0)`"),
|
||||
"try",
|
||||
format!("{slice_name}.first()"),
|
||||
app,
|
||||
);
|
||||
if identity.is_slice() {
|
||||
let mut app = Applicability::MachineApplicable;
|
||||
let slice_name = snippet_with_applicability(cx, recv.span, "..", &mut app);
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
GET_FIRST,
|
||||
expr.span,
|
||||
&format!("accessing first element with `{slice_name}.get(0)`"),
|
||||
"try",
|
||||
format!("{slice_name}.first()"),
|
||||
app,
|
||||
);
|
||||
} else if is_type_diagnostic_item(cx, identity, sym::VecDeque){
|
||||
let mut app = Applicability::MachineApplicable;
|
||||
let slice_name = snippet_with_applicability(cx, recv.span, "..", &mut app);
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
GET_FIRST,
|
||||
expr.span,
|
||||
&format!("accessing first element with `{slice_name}.get(0)`"),
|
||||
"try",
|
||||
format!("{slice_name}.front()"),
|
||||
app,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
//! Lint for `c.is_digit(10)`
|
||||
|
||||
use super::IS_DIGIT_ASCII_RADIX;
|
||||
use clippy_config::msrvs::{self, Msrv};
|
||||
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::source::snippet_with_applicability;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::Expr;
|
||||
|
|
|
|||
|
|
@ -3,9 +3,8 @@
|
|||
use super::ITER_KV_MAP;
|
||||
use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_sugg, span_lint_and_then};
|
||||
use clippy_utils::source::{snippet, snippet_with_applicability};
|
||||
use clippy_utils::sugg;
|
||||
use clippy_utils::ty::is_type_diagnostic_item;
|
||||
use clippy_utils::visitors::is_local_used;
|
||||
use clippy_utils::{pat_is_wild, sugg};
|
||||
use rustc_hir::{BindingAnnotation, Body, BorrowKind, ByRef, Expr, ExprKind, Mutability, Pat, PatKind};
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
use rustc_middle::ty;
|
||||
|
|
@ -84,13 +83,3 @@ pub(super) fn check<'tcx>(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the pattern is a `PatWild`, or is an ident prefixed with `_`
|
||||
/// that is not locally used.
|
||||
fn pat_is_wild<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx PatKind<'_>, body: &'tcx Expr<'_>) -> bool {
|
||||
match *pat {
|
||||
PatKind::Wild => true,
|
||||
PatKind::Binding(_, id, ident, None) if ident.as_str().starts_with('_') => !is_local_used(cx, body, id),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use clippy_config::msrvs::{self, Msrv};
|
||||
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;
|
||||
|
|
@ -21,7 +21,7 @@ pub(super) fn check<'tcx>(
|
|||
msrv: &Msrv,
|
||||
) {
|
||||
if !in_external_macro(cx.sess(), fold_span)
|
||||
&& msrv.meets(ITERATOR_TRY_FOLD)
|
||||
&& msrv.meets(msrvs::ITERATOR_TRY_FOLD)
|
||||
&& let init_ty = cx.typeck_results().expr_ty(init)
|
||||
&& let Some(try_trait) = cx.tcx.lang_items().try_trait()
|
||||
&& implements_trait(cx, init_ty, try_trait, &[])
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use clippy_config::msrvs::{self, Msrv};
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::msrvs::{self, Msrv};
|
||||
use clippy_utils::source::snippet_with_applicability;
|
||||
use clippy_utils::ty::{is_copy, is_type_diagnostic_item};
|
||||
use clippy_utils::{is_diag_trait_item, peel_blocks};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use clippy_config::msrvs::{self, Msrv};
|
||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
|
||||
use clippy_utils::msrvs::{self, Msrv};
|
||||
use clippy_utils::source::snippet;
|
||||
use clippy_utils::ty::is_type_diagnostic_item;
|
||||
use clippy_utils::usage::mutated_variables;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -207,11 +207,10 @@ fn is_is_empty_sig(cx: &LateContext<'_>, call_id: HirId) -> bool {
|
|||
|
||||
/// Checks if `<iter_ty as Iterator>::Item` is the same as `<collect_ty as IntoIter>::Item`
|
||||
fn iterates_same_ty<'tcx>(cx: &LateContext<'tcx>, iter_ty: Ty<'tcx>, collect_ty: Ty<'tcx>) -> bool {
|
||||
let item = Symbol::intern("Item");
|
||||
if let Some(iter_trait) = cx.tcx.get_diagnostic_item(sym::Iterator)
|
||||
&& let Some(into_iter_trait) = cx.tcx.get_diagnostic_item(sym::IntoIterator)
|
||||
&& let Some(iter_item_ty) = make_normalized_projection(cx.tcx, cx.param_env, iter_trait, item, [iter_ty])
|
||||
&& let Some(into_iter_item_proj) = make_projection(cx.tcx, into_iter_trait, item, [collect_ty])
|
||||
&& let Some(iter_item_ty) = make_normalized_projection(cx.tcx, cx.param_env, iter_trait, sym::Item, [iter_ty])
|
||||
&& let Some(into_iter_item_proj) = make_projection(cx.tcx, into_iter_trait, sym::Item, [collect_ty])
|
||||
&& let Ok(into_iter_item_ty) = cx.tcx.try_normalize_erasing_regions(
|
||||
cx.param_env,
|
||||
Ty::new_projection(cx.tcx,into_iter_item_proj.def_id, into_iter_item_proj.args)
|
||||
|
|
@ -233,9 +232,12 @@ fn is_contains_sig(cx: &LateContext<'_>, call_id: HirId, iter_expr: &Expr<'_>) -
|
|||
&& let [_, search_ty] = *sig.skip_binder().inputs()
|
||||
&& let ty::Ref(_, search_ty, Mutability::Not) = *cx.tcx.erase_late_bound_regions(sig.rebind(search_ty)).kind()
|
||||
&& let Some(iter_trait) = cx.tcx.get_diagnostic_item(sym::Iterator)
|
||||
&& let Some(iter_item) = cx.tcx
|
||||
.associated_items(iter_trait)
|
||||
.find_by_name_and_kind(cx.tcx, Ident::with_dummy_span(Symbol::intern("Item")), AssocKind::Type, iter_trait)
|
||||
&& let Some(iter_item) = cx.tcx.associated_items(iter_trait).find_by_name_and_kind(
|
||||
cx.tcx,
|
||||
Ident::with_dummy_span(sym::Item),
|
||||
AssocKind::Type,
|
||||
iter_trait,
|
||||
)
|
||||
&& let args = cx.tcx.mk_args(&[GenericArg::from(typeck.expr_ty_adjusted(iter_expr))])
|
||||
&& let proj_ty = Ty::new_projection(cx.tcx,iter_item.def_id, args)
|
||||
&& let Ok(item_ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, proj_ty)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use clippy_config::msrvs::{self, Msrv};
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::msrvs::{self, Msrv};
|
||||
use clippy_utils::source::snippet;
|
||||
use clippy_utils::ty::is_type_diagnostic_item;
|
||||
use clippy_utils::{match_def_path, path_to_local_id, paths, peel_blocks};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use clippy_config::msrvs::{self, Msrv};
|
||||
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, is_type_diagnostic_item};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
use super::PATH_ENDS_WITH_EXT;
|
||||
use clippy_config::msrvs::{self, Msrv};
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::msrvs;
|
||||
use clippy_utils::msrvs::Msrv;
|
||||
use clippy_utils::source::snippet;
|
||||
use clippy_utils::ty::is_type_diagnostic_item;
|
||||
use rustc_ast::{LitKind, StrStyle};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use clippy_config::msrvs::{self, Msrv};
|
||||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
|
||||
use clippy_utils::msrvs::{self, Msrv};
|
||||
use clippy_utils::source::snippet_with_context;
|
||||
use clippy_utils::usage::local_used_after_expr;
|
||||
use clippy_utils::visitors::{for_each_expr_with_closures, Descend};
|
||||
|
|
@ -115,7 +115,7 @@ fn check_manual_split_once(
|
|||
|
||||
/// checks for
|
||||
///
|
||||
/// ```
|
||||
/// ```no_run
|
||||
/// let mut iter = "a.b.c".splitn(2, '.');
|
||||
/// let a = iter.next();
|
||||
/// let b = iter.next();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use clippy_config::msrvs::{self, Msrv};
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::msrvs::{Msrv, MATCHES_MACRO};
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use clippy_utils::{is_from_proc_macro, is_trait_method, path_to_local};
|
||||
use itertools::Itertools;
|
||||
|
|
@ -19,7 +19,7 @@ pub(super) fn check<'tcx>(
|
|||
body: &Expr<'_>,
|
||||
msrv: &Msrv,
|
||||
) {
|
||||
if msrv.meets(MATCHES_MACRO)
|
||||
if msrv.meets(msrvs::MATCHES_MACRO)
|
||||
&& is_trait_method(cx, expr, sym::Iterator)
|
||||
&& let PatKind::Binding(_, arg, _, _) = param.pat.kind
|
||||
&& let ExprKind::Lit(lit_kind) = recv.kind
|
||||
|
|
|
|||
119
clippy_lints/src/methods/unnecessary_fallible_conversions.rs
Normal file
119
clippy_lints/src/methods/unnecessary_fallible_conversions.rs
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::get_parent_expr;
|
||||
use clippy_utils::ty::implements_trait;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Expr, ExprKind};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty;
|
||||
use rustc_span::{sym, Span};
|
||||
|
||||
use super::UNNECESSARY_FALLIBLE_CONVERSIONS;
|
||||
|
||||
/// What function is being called and whether that call is written as a method call or a function
|
||||
/// call
|
||||
#[derive(Copy, Clone)]
|
||||
#[expect(clippy::enum_variant_names)]
|
||||
enum FunctionKind {
|
||||
/// `T::try_from(U)`
|
||||
TryFromFunction,
|
||||
/// `t.try_into()`
|
||||
TryIntoMethod,
|
||||
/// `U::try_into(t)`
|
||||
TryIntoFunction,
|
||||
}
|
||||
|
||||
fn check<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
expr: &Expr<'_>,
|
||||
node_args: ty::GenericArgsRef<'tcx>,
|
||||
kind: FunctionKind,
|
||||
primary_span: Span,
|
||||
) {
|
||||
if let &[self_ty, other_ty] = node_args.as_slice()
|
||||
// useless_conversion already warns `T::try_from(T)`, so ignore it here
|
||||
&& self_ty != other_ty
|
||||
&& let Some(self_ty) = self_ty.as_type()
|
||||
&& let Some(from_into_trait) = cx.tcx.get_diagnostic_item(match kind {
|
||||
FunctionKind::TryFromFunction => sym::From,
|
||||
FunctionKind::TryIntoMethod | FunctionKind::TryIntoFunction => sym::Into,
|
||||
})
|
||||
// If `T: TryFrom<U>` and `T: From<U>` both exist, then that means that the `TryFrom`
|
||||
// _must_ be from the blanket impl and cannot have been manually implemented
|
||||
// (else there would be conflicting impls, even with #![feature(spec)]), so we don't even need to check
|
||||
// what `<T as TryFrom<U>>::Error` is: it's always `Infallible`
|
||||
&& implements_trait(cx, self_ty, from_into_trait, &[other_ty])
|
||||
{
|
||||
let parent_unwrap_call = get_parent_expr(cx, expr)
|
||||
.and_then(|parent| {
|
||||
if let ExprKind::MethodCall(path, .., span) = parent.kind
|
||||
&& let sym::unwrap | sym::expect = path.ident.name
|
||||
{
|
||||
Some(span)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
let (sugg, span, applicability) = match kind {
|
||||
FunctionKind::TryIntoMethod if let Some(unwrap_span) = parent_unwrap_call => {
|
||||
// Extend the span to include the unwrap/expect call:
|
||||
// `foo.try_into().expect("..")`
|
||||
// ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
//
|
||||
// `try_into().unwrap()` specifically can be trivially replaced with just `into()`,
|
||||
// so that can be machine-applicable
|
||||
|
||||
("into()", primary_span.with_hi(unwrap_span.hi()), Applicability::MachineApplicable)
|
||||
}
|
||||
FunctionKind::TryFromFunction => ("From::from", primary_span, Applicability::Unspecified),
|
||||
FunctionKind::TryIntoFunction => ("Into::into", primary_span, Applicability::Unspecified),
|
||||
FunctionKind::TryIntoMethod => ("into", primary_span, Applicability::Unspecified),
|
||||
};
|
||||
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
UNNECESSARY_FALLIBLE_CONVERSIONS,
|
||||
span,
|
||||
"use of a fallible conversion when an infallible one could be used",
|
||||
"use",
|
||||
sugg.into(),
|
||||
applicability
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks method call exprs:
|
||||
/// - `0i32.try_into()`
|
||||
pub(super) fn check_method(cx: &LateContext<'_>, expr: &Expr<'_>) {
|
||||
if let ExprKind::MethodCall(path, ..) = expr.kind {
|
||||
check(
|
||||
cx,
|
||||
expr,
|
||||
cx.typeck_results().node_args(expr.hir_id),
|
||||
FunctionKind::TryIntoMethod,
|
||||
path.ident.span,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks function call exprs:
|
||||
/// - `<i64 as TryFrom<_>>::try_from(0i32)`
|
||||
/// - `<_ as TryInto<i64>>::try_into(0i32)`
|
||||
pub(super) fn check_function(cx: &LateContext<'_>, expr: &Expr<'_>, callee: &Expr<'_>) {
|
||||
if let ExprKind::Path(ref qpath) = callee.kind
|
||||
&& let Some(item_def_id) = cx.qpath_res(qpath, callee.hir_id).opt_def_id()
|
||||
&& let Some(trait_def_id) = cx.tcx.trait_of_item(item_def_id)
|
||||
{
|
||||
check(
|
||||
cx,
|
||||
expr,
|
||||
cx.typeck_results().node_args(callee.hir_id),
|
||||
match cx.tcx.get_diagnostic_name(trait_def_id) {
|
||||
Some(sym::TryFrom) => FunctionKind::TryFromFunction,
|
||||
Some(sym::TryInto) => FunctionKind::TryIntoFunction,
|
||||
_ => return,
|
||||
},
|
||||
callee.span,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -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, GenericArgKind};
|
||||
use rustc_middle::ty;
|
||||
use rustc_middle::ty::GenericArgKind;
|
||||
use rustc_span::sym;
|
||||
use rustc_span::symbol::Ident;
|
||||
use std::iter;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use super::implicit_clone::is_clone_like;
|
||||
use super::unnecessary_iter_cloned::{self, is_into_iter};
|
||||
use clippy_config::msrvs::{self, Msrv};
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::msrvs::{self, Msrv};
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use clippy_utils::ty::{get_iterator_item_ty, implements_trait, is_copy, peel_mid_ty_refs};
|
||||
use clippy_utils::visitors::find_all_ret_expressions;
|
||||
|
|
|
|||
32
clippy_lints/src/methods/waker_clone_wake.rs
Normal file
32
clippy_lints/src/methods/waker_clone_wake.rs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::snippet_with_applicability;
|
||||
use clippy_utils::{is_trait_method, match_def_path, paths};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Expr, ExprKind};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_span::sym;
|
||||
|
||||
use super::WAKER_CLONE_WAKE;
|
||||
|
||||
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &'tcx Expr<'_>) {
|
||||
let ty = cx.typeck_results().expr_ty(recv);
|
||||
|
||||
if let Some(did) = ty.ty_adt_def()
|
||||
&& match_def_path(cx, did.did(), &paths::WAKER)
|
||||
&& let ExprKind::MethodCall(_, waker_ref, &[], _) = recv.kind
|
||||
&& is_trait_method(cx, recv, sym::Clone)
|
||||
{
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
let snippet = snippet_with_applicability(cx, waker_ref.span.source_callsite(), "..", &mut applicability);
|
||||
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
WAKER_CLONE_WAKE,
|
||||
expr.span,
|
||||
"cloning a `Waker` only to wake it",
|
||||
"replace with",
|
||||
format!("{snippet}.wake_by_ref()"),
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue