Skip to content

Commit f312411

Browse files
committed
add a helper for extracting fn def id and node args together
1 parent e97881c commit f312411

File tree

3 files changed

+19
-12
lines changed

3 files changed

+19
-12
lines changed

clippy_lints/src/unconditional_recursion.rs

+2-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use clippy_utils::diagnostics::span_lint_and_then;
2-
use clippy_utils::{expr_or_init, fn_def_id, get_trait_def_id, path_def_id};
2+
use clippy_utils::{expr_or_init, fn_def_id_with_node_args, get_trait_def_id, path_def_id};
33
use itertools::Itertools;
44
use rustc_ast::BinOpKind;
55
use rustc_data_structures::fx::FxHashMap;
@@ -401,20 +401,14 @@ fn check_from(cx: &LateContext<'_>, method_span: Span, method_def_id: LocalDefId
401401
else {
402402
return;
403403
};
404-
let typeck = cx.typeck_results();
405404

406405
// Check if we are calling `Into::into` where the node args match with our `From::from` signature:
407406
// From::from signature: fn(S1) -> S2
408407
// <S1 as Into<S2>>::into(s1), node_args=[S1, S2]
409408
// If they do match, then it must mean that it is the blanket impl,
410409
// which calls back into our `From::from` again (`Into` is not specializable).
411410
// rustc's unconditional_recursion already catches calling `From::from` directly
412-
if let Some(fn_def_id) = fn_def_id(cx, expr)
413-
&& let node_args = match expr.kind {
414-
ExprKind::MethodCall(..) => typeck.node_args(expr.hir_id),
415-
ExprKind::Call(callee, _) => typeck.node_args(callee.hir_id),
416-
_ => return,
417-
}
411+
if let Some((fn_def_id, node_args)) = fn_def_id_with_node_args(cx, expr)
418412
&& let Some((s1, s2)) = node_args.iter().filter_map(ty::GenericArg::as_type).collect_tuple()
419413
&& let Some(trait_def_id) = cx.tcx.trait_of_item(fn_def_id)
420414
&& cx.tcx.is_diagnostic_item(sym::Into, trait_def_id)

clippy_utils/src/lib.rs

+16-3
Original file line numberDiff line numberDiff line change
@@ -2249,8 +2249,21 @@ pub fn fn_has_unsatisfiable_preds(cx: &LateContext<'_>, did: DefId) -> bool {
22492249

22502250
/// Returns the `DefId` of the callee if the given expression is a function or method call.
22512251
pub fn fn_def_id(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<DefId> {
2252+
fn_def_id_with_node_args(cx, expr).map(|(did, _)| did)
2253+
}
2254+
2255+
/// Returns the `DefId` of the callee if the given expression is a function or method call,
2256+
/// as well as its node args.
2257+
pub fn fn_def_id_with_node_args<'tcx>(
2258+
cx: &LateContext<'tcx>,
2259+
expr: &Expr<'_>,
2260+
) -> Option<(DefId, rustc_ty::GenericArgsRef<'tcx>)> {
2261+
let typeck = cx.typeck_results();
22522262
match &expr.kind {
2253-
ExprKind::MethodCall(..) => cx.typeck_results().type_dependent_def_id(expr.hir_id),
2263+
ExprKind::MethodCall(..) => Some((
2264+
typeck.type_dependent_def_id(expr.hir_id)?,
2265+
typeck.node_args(expr.hir_id),
2266+
)),
22542267
ExprKind::Call(
22552268
Expr {
22562269
kind: ExprKind::Path(qpath),
@@ -2262,9 +2275,9 @@ pub fn fn_def_id(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<DefId> {
22622275
// Only return Fn-like DefIds, not the DefIds of statics/consts/etc that contain or
22632276
// deref to fn pointers, dyn Fn, impl Fn - #8850
22642277
if let Res::Def(DefKind::Fn | DefKind::Ctor(..) | DefKind::AssocFn, id) =
2265-
cx.typeck_results().qpath_res(qpath, *path_hir_id)
2278+
typeck.qpath_res(qpath, *path_hir_id)
22662279
{
2267-
Some(id)
2280+
Some((id, typeck.node_args(*path_hir_id)))
22682281
} else {
22692282
None
22702283
}

tests/ui/unconditional_recursion.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ impl<'a> From<BadFromTy1<'a>> for BadIntoTy1<'static> {
363363
}
364364
}
365365

366-
// From::from -> From::from
366+
// Using UFCS syntax
367367
struct BadFromTy2<'a>(&'a ());
368368
struct BadIntoTy2<'b>(&'b ());
369369
impl<'a> From<BadFromTy2<'a>> for BadIntoTy2<'static> {

0 commit comments

Comments
 (0)