Auto merge of #125764 - flip1995:clippy-subtree-update, r=Manishearth

Clippy subtree update

r? `@Manishearth`
This commit is contained in:
bors 2024-05-30 16:46:31 +00:00
commit 51347ba3c7
128 changed files with 1430 additions and 684 deletions

View file

@ -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(_)

View file

@ -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)
///

View file

@ -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,
);
}
},
);

View file

@ -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, _) => {