|
1 | 1 | use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then, span_lint_hir_and_then}; |
2 | 2 | use clippy_utils::source::SpanRangeExt; |
3 | | -use clippy_utils::ty::expr_sig; |
4 | 3 | use clippy_utils::visitors::contains_unsafe_block; |
5 | 4 | use clippy_utils::{get_expr_use_or_unification_node, is_lint_allowed, path_def_id, path_to_local}; |
6 | 5 | use hir::LifetimeName; |
7 | 6 | use rustc_errors::{Applicability, MultiSpan}; |
8 | | -use rustc_hir::def_id::DefId; |
9 | 7 | use rustc_hir::hir_id::{HirId, HirIdMap}; |
10 | 8 | use rustc_hir::intravisit::{walk_expr, Visitor}; |
11 | 9 | use rustc_hir::{ |
@@ -323,7 +321,6 @@ struct PtrArg<'tcx> { |
323 | 321 | idx: usize, |
324 | 322 | emission_id: HirId, |
325 | 323 | span: Span, |
326 | | - ty_did: DefId, |
327 | 324 | ty_name: Symbol, |
328 | 325 | method_renames: &'static [(&'static str, &'static str)], |
329 | 326 | ref_prefix: RefPrefix, |
@@ -411,7 +408,6 @@ impl<'tcx> DerefTy<'tcx> { |
411 | 408 | } |
412 | 409 | } |
413 | 410 |
|
414 | | -#[expect(clippy::too_many_lines)] |
415 | 411 | fn check_fn_args<'cx, 'tcx: 'cx>( |
416 | 412 | cx: &'cx LateContext<'tcx>, |
417 | 413 | fn_sig: ty::FnSig<'tcx>, |
@@ -514,7 +510,6 @@ fn check_fn_args<'cx, 'tcx: 'cx>( |
514 | 510 | idx: i, |
515 | 511 | emission_id, |
516 | 512 | span: hir_ty.span, |
517 | | - ty_did: adt.did(), |
518 | 513 | ty_name: name.ident.name, |
519 | 514 | method_renames, |
520 | 515 | ref_prefix: RefPrefix { lt: *lt, mutability }, |
@@ -610,65 +605,50 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &Body<'tcx>, args: &[ |
610 | 605 | set_skip_flag(); |
611 | 606 | } |
612 | 607 | }, |
613 | | - Some((Node::Expr(e), child_id)) => match e.kind { |
614 | | - ExprKind::Call(f, expr_args) => { |
615 | | - let i = expr_args.iter().position(|arg| arg.hir_id == child_id).unwrap_or(0); |
616 | | - if expr_sig(self.cx, f).and_then(|sig| sig.input(i)).map_or(true, |ty| { |
617 | | - match *ty.skip_binder().peel_refs().kind() { |
618 | | - ty::Dynamic(preds, _, _) => !matches_preds(self.cx, args.deref_ty.ty(self.cx), preds), |
619 | | - ty::Param(_) => true, |
620 | | - ty::Adt(def, _) => def.did() == args.ty_did, |
621 | | - _ => false, |
622 | | - } |
623 | | - }) { |
624 | | - // Passed to a function taking the non-dereferenced type. |
625 | | - set_skip_flag(); |
626 | | - } |
627 | | - }, |
628 | | - ExprKind::MethodCall(name, self_arg, expr_args, _) => { |
629 | | - let i = iter::once(self_arg) |
630 | | - .chain(expr_args.iter()) |
631 | | - .position(|arg| arg.hir_id == child_id) |
632 | | - .unwrap_or(0); |
633 | | - if i == 0 { |
634 | | - // Check if the method can be renamed. |
635 | | - let name = name.ident.as_str(); |
636 | | - if let Some((_, replacement)) = args.method_renames.iter().find(|&&(x, _)| x == name) { |
637 | | - result.replacements.push(PtrArgReplacement { |
638 | | - expr_span: e.span, |
639 | | - self_span: self_arg.span, |
640 | | - replacement, |
641 | | - }); |
642 | | - return; |
643 | | - } |
| 608 | + Some((Node::Expr(use_expr), child_id)) => { |
| 609 | + if let ExprKind::Index(e, ..) = use_expr.kind |
| 610 | + && e.hir_id == child_id |
| 611 | + { |
| 612 | + // Indexing works with both owned and its dereferenced type |
| 613 | + return; |
| 614 | + } |
| 615 | + |
| 616 | + if let ExprKind::MethodCall(name, receiver, ..) = use_expr.kind |
| 617 | + && receiver.hir_id == child_id |
| 618 | + { |
| 619 | + let name = name.ident.as_str(); |
| 620 | + |
| 621 | + // Check if the method can be renamed. |
| 622 | + if let Some((_, replacement)) = args.method_renames.iter().find(|&&(x, _)| x == name) { |
| 623 | + result.replacements.push(PtrArgReplacement { |
| 624 | + expr_span: use_expr.span, |
| 625 | + self_span: receiver.span, |
| 626 | + replacement, |
| 627 | + }); |
| 628 | + return; |
644 | 629 | } |
645 | 630 |
|
646 | | - let Some(id) = self.cx.typeck_results().type_dependent_def_id(e.hir_id) else { |
647 | | - set_skip_flag(); |
| 631 | + // Some methods exist on both `[T]` and `Vec<T>`, such as `len`, where the receiver type |
| 632 | + // doesn't coerce to a slice and our adjusted type check below isn't enough, |
| 633 | + // but it would still be valid to call with a slice |
| 634 | + if is_allowed_vec_method(self.cx, use_expr) { |
648 | 635 | return; |
649 | | - }; |
650 | | - |
651 | | - match *self.cx.tcx.fn_sig(id).instantiate_identity().skip_binder().inputs()[i] |
652 | | - .peel_refs() |
653 | | - .kind() |
654 | | - { |
655 | | - ty::Dynamic(preds, _, _) if !matches_preds(self.cx, args.deref_ty.ty(self.cx), preds) => { |
656 | | - set_skip_flag(); |
657 | | - }, |
658 | | - ty::Param(_) => { |
659 | | - set_skip_flag(); |
660 | | - }, |
661 | | - // If the types match check for methods which exist on both types. e.g. `Vec::len` and |
662 | | - // `slice::len` |
663 | | - ty::Adt(def, _) if def.did() == args.ty_did && !is_allowed_vec_method(self.cx, e) => { |
664 | | - set_skip_flag(); |
665 | | - }, |
666 | | - _ => (), |
667 | 636 | } |
668 | | - }, |
669 | | - // Indexing is fine for currently supported types. |
670 | | - ExprKind::Index(e, _, _) if e.hir_id == child_id => (), |
671 | | - _ => set_skip_flag(), |
| 637 | + } |
| 638 | + |
| 639 | + let deref_ty = args.deref_ty.ty(self.cx); |
| 640 | + let adjusted_ty = self.cx.typeck_results().expr_ty_adjusted(e).peel_refs(); |
| 641 | + if adjusted_ty == deref_ty { |
| 642 | + return; |
| 643 | + } |
| 644 | + |
| 645 | + if let ty::Dynamic(preds, ..) = adjusted_ty.kind() |
| 646 | + && matches_preds(self.cx, deref_ty, preds) |
| 647 | + { |
| 648 | + return; |
| 649 | + } |
| 650 | + |
| 651 | + set_skip_flag(); |
672 | 652 | }, |
673 | 653 | _ => set_skip_flag(), |
674 | 654 | } |
|
0 commit comments