Skip to content

Commit 83148cb

Browse files
committed
Do not always consider parameters of closures as type-certain
`Node::Param(…)` can represent function parameters as well as closure parameters. In the second case, a type is not always given. When no type is given, consider it uncertain.
1 parent 08f5eba commit 83148cb

File tree

1 file changed

+18
-3
lines changed
  • clippy_utils/src/ty/type_certainty

1 file changed

+18
-3
lines changed

clippy_utils/src/ty/type_certainty/mod.rs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use rustc_ast::{LitFloatType, LitIntType, LitKind};
1616
use rustc_hir::def::{DefKind, Res};
1717
use rustc_hir::def_id::DefId;
1818
use rustc_hir::intravisit::{InferKind, Visitor, VisitorExt, walk_qpath, walk_ty};
19-
use rustc_hir::{self as hir, AmbigArg, Expr, ExprKind, GenericArgs, HirId, Node, PathSegment, QPath, TyKind};
19+
use rustc_hir::{self as hir, AmbigArg, Expr, ExprKind, GenericArgs, HirId, Node, Param, PathSegment, QPath, TyKind};
2020
use rustc_lint::LateContext;
2121
use rustc_middle::ty::{self, AdtDef, GenericArgKind, Ty};
2222
use rustc_span::Span;
@@ -215,6 +215,20 @@ fn qpath_certainty(cx: &LateContext<'_>, qpath: &QPath<'_>, resolves_to_type: bo
215215
certainty
216216
}
217217

218+
/// Tries to tell whether `param` resolves to something certain, e.g., a non-wildcard type if
219+
/// present. The certainty `DefId` is cleared before returning.
220+
fn param_certainty(cx: &LateContext<'_>, param: &Param<'_>) -> Certainty {
221+
let owner_did = cx.tcx.hir_enclosing_body_owner(param.hir_id);
222+
let Some(fn_decl) = cx.tcx.hir_fn_decl_by_hir_id(cx.tcx.local_def_id_to_hir_id(owner_did)) else {
223+
return Certainty::Uncertain;
224+
};
225+
let inputs = fn_decl.inputs;
226+
let body_params = cx.tcx.hir_body_owned_by(owner_did).params;
227+
std::iter::zip(body_params, inputs)
228+
.find(|(p, _)| p.hir_id == param.hir_id)
229+
.map_or(Certainty::Uncertain, |(_, ty)| type_certainty(cx, ty).clear_def_id())
230+
}
231+
218232
fn path_segment_certainty(
219233
cx: &LateContext<'_>,
220234
parent_certainty: Certainty,
@@ -267,8 +281,9 @@ fn path_segment_certainty(
267281

268282
// `get_parent` because `hir_id` refers to a `Pat`, and we're interested in the node containing the `Pat`.
269283
Res::Local(hir_id) => match cx.tcx.parent_hir_node(hir_id) {
270-
// An argument's type is always certain.
271-
Node::Param(..) => Certainty::Certain(None),
284+
// A parameter's type is not always certain, as it may come from an untyped closure definition,
285+
// or from a wildcard in a typed closure definition.
286+
Node::Param(param) => param_certainty(cx, param),
272287
// A local's type is certain if its type annotation is certain or it has an initializer whose
273288
// type is certain.
274289
Node::LetStmt(local) => {

0 commit comments

Comments
 (0)