|
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