Auto merge of #125764 - flip1995:clippy-subtree-update, r=Manishearth
Clippy subtree update r? `@Manishearth`
This commit is contained in:
commit
51347ba3c7
128 changed files with 1430 additions and 684 deletions
|
|
@ -1,8 +1,12 @@
|
|||
use std::iter::once;
|
||||
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::snippet;
|
||||
use clippy_utils::{get_expr_use_or_unification_node, is_res_lang_ctor, path_res, std_or_core};
|
||||
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::hir_id::HirId;
|
||||
use rustc_hir::LangItem::{OptionNone, OptionSome};
|
||||
use rustc_hir::{Expr, ExprKind, Node};
|
||||
use rustc_lint::LateContext;
|
||||
|
|
@ -25,7 +29,29 @@ impl IterType {
|
|||
}
|
||||
}
|
||||
|
||||
pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: &str, recv: &Expr<'_>) {
|
||||
fn is_arg_ty_unified_in_fn<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
fn_id: DefId,
|
||||
arg_id: HirId,
|
||||
args: impl IntoIterator<Item = &'tcx Expr<'tcx>>,
|
||||
) -> bool {
|
||||
let fn_sig = cx.tcx.fn_sig(fn_id).instantiate_identity();
|
||||
let arg_id_in_args = args.into_iter().position(|e| e.hir_id == arg_id).unwrap();
|
||||
let arg_ty_in_args = fn_sig.input(arg_id_in_args).skip_binder();
|
||||
|
||||
cx.tcx.predicates_of(fn_id).predicates.iter().any(|(clause, _)| {
|
||||
clause
|
||||
.as_projection_clause()
|
||||
.and_then(|p| p.map_bound(|p| p.term.ty()).transpose())
|
||||
.is_some_and(|ty| ty.skip_binder() == arg_ty_in_args)
|
||||
}) || fn_sig
|
||||
.inputs()
|
||||
.iter()
|
||||
.enumerate()
|
||||
.any(|(i, ty)| i != arg_id_in_args && ty.skip_binder().walk().any(|arg| arg.as_type() == Some(arg_ty_in_args)))
|
||||
}
|
||||
|
||||
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, method_name: &str, recv: &'tcx Expr<'tcx>) {
|
||||
let item = match recv.kind {
|
||||
ExprKind::Array([]) => None,
|
||||
ExprKind::Array([e]) => Some(e),
|
||||
|
|
@ -43,6 +69,25 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: &str, re
|
|||
let is_unified = match get_expr_use_or_unification_node(cx.tcx, expr) {
|
||||
Some((Node::Expr(parent), child_id)) => match parent.kind {
|
||||
ExprKind::If(e, _, _) | ExprKind::Match(e, _, _) if e.hir_id == child_id => false,
|
||||
ExprKind::Call(
|
||||
Expr {
|
||||
kind: ExprKind::Path(path),
|
||||
hir_id,
|
||||
..
|
||||
},
|
||||
args,
|
||||
) => cx
|
||||
.typeck_results()
|
||||
.qpath_res(path, *hir_id)
|
||||
.opt_def_id()
|
||||
.filter(|fn_id| cx.tcx.def_kind(fn_id).is_fn_like())
|
||||
.is_some_and(|fn_id| is_arg_ty_unified_in_fn(cx, fn_id, child_id, args)),
|
||||
ExprKind::MethodCall(_name, recv, args, _span) => is_arg_ty_unified_in_fn(
|
||||
cx,
|
||||
cx.typeck_results().type_dependent_def_id(parent.hir_id).unwrap(),
|
||||
child_id,
|
||||
once(recv).chain(args.iter()),
|
||||
),
|
||||
ExprKind::If(_, _, _)
|
||||
| ExprKind::Match(_, _, _)
|
||||
| ExprKind::Closure(_)
|
||||
|
|
|
|||
|
|
@ -257,7 +257,7 @@ declare_clippy_lint! {
|
|||
/// ### What it does
|
||||
/// Checks for `.unwrap()` or `.unwrap_err()` calls on `Result`s and `.unwrap()` call on `Option`s.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// ### Why restrict this?
|
||||
/// It is better to handle the `None` or `Err` case,
|
||||
/// or at least call `.expect(_)` with a more helpful message. Still, for a lot of
|
||||
/// quick-and-dirty code, `unwrap` is a good choice, which is why this lint is
|
||||
|
|
@ -333,7 +333,7 @@ declare_clippy_lint! {
|
|||
/// ### What it does
|
||||
/// Checks for `.expect()` or `.expect_err()` calls on `Result`s and `.expect()` call on `Option`s.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// ### Why restrict this?
|
||||
/// Usually it is better to handle the `None` or `Err` case.
|
||||
/// Still, for a lot of quick-and-dirty code, `expect` is a good choice, which is why
|
||||
/// this lint is `Allow` by default.
|
||||
|
|
@ -1029,8 +1029,8 @@ declare_clippy_lint! {
|
|||
/// (`Rc`, `Arc`, `rc::Weak`, or `sync::Weak`), and suggests calling Clone via unified
|
||||
/// function syntax instead (e.g., `Rc::clone(foo)`).
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// Calling '.clone()' on an Rc, Arc, or Weak
|
||||
/// ### Why restrict this?
|
||||
/// Calling `.clone()` on an `Rc`, `Arc`, or `Weak`
|
||||
/// can obscure the fact that only the pointer is being cloned, not the underlying
|
||||
/// data.
|
||||
///
|
||||
|
|
@ -1051,7 +1051,7 @@ declare_clippy_lint! {
|
|||
#[clippy::version = "pre 1.29.0"]
|
||||
pub CLONE_ON_REF_PTR,
|
||||
restriction,
|
||||
"using 'clone' on a ref-counted pointer"
|
||||
"using `clone` on a ref-counted pointer"
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
|
|
@ -1359,7 +1359,7 @@ declare_clippy_lint! {
|
|||
/// Checks for usage of `.get().unwrap()` (or
|
||||
/// `.get_mut().unwrap`) on a standard library type which implements `Index`
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// ### Why restrict this?
|
||||
/// Using the Index trait (`[]`) is more clear and more
|
||||
/// concise.
|
||||
///
|
||||
|
|
@ -1743,7 +1743,7 @@ declare_clippy_lint! {
|
|||
/// ### What it does
|
||||
/// Checks for `FileType::is_file()`.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// ### Why restrict this?
|
||||
/// When people testing a file type with `FileType::is_file`
|
||||
/// they are testing whether a path is something they can get bytes from. But
|
||||
/// `is_file` doesn't cover special file types in unix-like systems, and doesn't cover
|
||||
|
|
@ -2688,8 +2688,9 @@ declare_clippy_lint! {
|
|||
/// ### What it does
|
||||
/// Checks for instances of `map_err(|_| Some::Enum)`
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// This `map_err` throws away the original error rather than allowing the enum to contain and report the cause of the error
|
||||
/// ### Why restrict this?
|
||||
/// This `map_err` throws away the original error rather than allowing the enum to
|
||||
/// contain and report the cause of the error.
|
||||
///
|
||||
/// ### Example
|
||||
/// Before:
|
||||
|
|
@ -3145,7 +3146,7 @@ declare_clippy_lint! {
|
|||
/// ### What it does
|
||||
/// Checks for usage of File::read_to_end and File::read_to_string.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// ### Why restrict this?
|
||||
/// `fs::{read, read_to_string}` provide the same functionality when `buf` is empty with fewer imports and no intermediate values.
|
||||
/// See also: [fs::read docs](https://doc.rust-lang.org/std/fs/fn.read.html), [fs::read_to_string docs](https://doc.rust-lang.org/std/fs/fn.read_to_string.html)
|
||||
///
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ pub fn check_for_loop_iter(
|
|||
) -> bool {
|
||||
if let Some(grandparent) = get_parent_expr(cx, expr).and_then(|parent| get_parent_expr(cx, parent))
|
||||
&& let Some(ForLoop { pat, body, .. }) = ForLoop::hir(grandparent)
|
||||
&& let (clone_or_copy_needed, addr_of_exprs) = clone_or_copy_needed(cx, pat, body)
|
||||
&& let (clone_or_copy_needed, references_to_binding) = clone_or_copy_needed(cx, pat, body)
|
||||
&& !clone_or_copy_needed
|
||||
&& let Some(receiver_snippet) = snippet_opt(cx, receiver.span)
|
||||
{
|
||||
|
|
@ -123,14 +123,12 @@ pub fn check_for_loop_iter(
|
|||
Applicability::MachineApplicable
|
||||
};
|
||||
diag.span_suggestion(expr.span, "use", snippet, applicability);
|
||||
for addr_of_expr in addr_of_exprs {
|
||||
match addr_of_expr.kind {
|
||||
ExprKind::AddrOf(_, _, referent) => {
|
||||
let span = addr_of_expr.span.with_hi(referent.span.lo());
|
||||
diag.span_suggestion(span, "remove this `&`", "", applicability);
|
||||
},
|
||||
_ => unreachable!(),
|
||||
}
|
||||
if !references_to_binding.is_empty() {
|
||||
diag.multipart_suggestion(
|
||||
"remove any references to the binding",
|
||||
references_to_binding,
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ use rustc_lint::LateContext;
|
|||
use rustc_middle::hir::nested_filter;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::Span;
|
||||
|
||||
pub(super) fn derefs_to_slice<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
|
|
@ -96,15 +97,15 @@ pub(super) fn clone_or_copy_needed<'tcx>(
|
|||
cx: &LateContext<'tcx>,
|
||||
pat: &Pat<'tcx>,
|
||||
body: &'tcx Expr<'tcx>,
|
||||
) -> (bool, Vec<&'tcx Expr<'tcx>>) {
|
||||
) -> (bool, Vec<(Span, String)>) {
|
||||
let mut visitor = CloneOrCopyVisitor {
|
||||
cx,
|
||||
binding_hir_ids: pat_bindings(pat),
|
||||
clone_or_copy_needed: false,
|
||||
addr_of_exprs: Vec::new(),
|
||||
references_to_binding: Vec::new(),
|
||||
};
|
||||
visitor.visit_expr(body);
|
||||
(visitor.clone_or_copy_needed, visitor.addr_of_exprs)
|
||||
(visitor.clone_or_copy_needed, visitor.references_to_binding)
|
||||
}
|
||||
|
||||
/// Returns a vector of all `HirId`s bound by the pattern.
|
||||
|
|
@ -127,7 +128,7 @@ struct CloneOrCopyVisitor<'cx, 'tcx> {
|
|||
cx: &'cx LateContext<'tcx>,
|
||||
binding_hir_ids: Vec<HirId>,
|
||||
clone_or_copy_needed: bool,
|
||||
addr_of_exprs: Vec<&'tcx Expr<'tcx>>,
|
||||
references_to_binding: Vec<(Span, String)>,
|
||||
}
|
||||
|
||||
impl<'cx, 'tcx> Visitor<'tcx> for CloneOrCopyVisitor<'cx, 'tcx> {
|
||||
|
|
@ -142,8 +143,11 @@ impl<'cx, 'tcx> Visitor<'tcx> for CloneOrCopyVisitor<'cx, 'tcx> {
|
|||
if self.is_binding(expr) {
|
||||
if let Some(parent) = get_parent_expr(self.cx, expr) {
|
||||
match parent.kind {
|
||||
ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, _) => {
|
||||
self.addr_of_exprs.push(parent);
|
||||
ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, referent) => {
|
||||
if !parent.span.from_expansion() {
|
||||
self.references_to_binding
|
||||
.push((parent.span.until(referent.span), String::new()));
|
||||
}
|
||||
return;
|
||||
},
|
||||
ExprKind::MethodCall(.., args, _) => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue