Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit bf37fe2

Browse files
committed
Auto merge of rust-lang#12316 - jonas-schievink:closure-param-hints, r=jonas-schievink
feat: Show parameter inlay hints for closure invocations Fixes rust-lang/rust-analyzer#12268
2 parents eba26af + 52ff863 commit bf37fe2

File tree

3 files changed

+77
-22
lines changed

3 files changed

+77
-22
lines changed

crates/hir/src/lib.rs

Lines changed: 54 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,9 @@ use hir_ty::{
6262
subst_prefix,
6363
traits::FnTrait,
6464
AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast,
65-
DebruijnIndex, GenericArgData, InEnvironment, Interner, ParamKind, QuantifiedWhereClause,
66-
Scalar, Solution, Substitution, TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt,
67-
TyKind, TyVariableKind, WhereClause,
65+
ClosureId, DebruijnIndex, GenericArgData, InEnvironment, Interner, ParamKind,
66+
QuantifiedWhereClause, Scalar, Solution, Substitution, TraitEnvironment, TraitRefExt, Ty,
67+
TyBuilder, TyDefId, TyExt, TyKind, TyVariableKind, WhereClause,
6868
};
6969
use itertools::Itertools;
7070
use nameres::diagnostics::DefDiagnosticKind;
@@ -2819,10 +2819,14 @@ impl Type {
28192819
}
28202820

28212821
pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> {
2822-
let def = self.ty.callable_def(db);
2822+
let callee = match self.ty.kind(Interner) {
2823+
TyKind::Closure(id, _) => Callee::Closure(*id),
2824+
TyKind::Function(_) => Callee::FnPtr,
2825+
_ => Callee::Def(self.ty.callable_def(db)?),
2826+
};
28232827

28242828
let sig = self.ty.callable_sig(db)?;
2825-
Some(Callable { ty: self.clone(), sig, def, is_bound_method: false })
2829+
Some(Callable { ty: self.clone(), sig, callee, is_bound_method: false })
28262830
}
28272831

28282832
pub fn is_closure(&self) -> bool {
@@ -3265,34 +3269,43 @@ impl Type {
32653269
}
32663270
}
32673271

3268-
// FIXME: closures
32693272
#[derive(Debug)]
32703273
pub struct Callable {
32713274
ty: Type,
32723275
sig: CallableSig,
3273-
def: Option<CallableDefId>,
3276+
callee: Callee,
32743277
pub(crate) is_bound_method: bool,
32753278
}
32763279

3280+
#[derive(Debug)]
3281+
enum Callee {
3282+
Def(CallableDefId),
3283+
Closure(ClosureId),
3284+
FnPtr,
3285+
}
3286+
32773287
pub enum CallableKind {
32783288
Function(Function),
32793289
TupleStruct(Struct),
32803290
TupleEnumVariant(Variant),
32813291
Closure,
3292+
FnPtr,
32823293
}
32833294

32843295
impl Callable {
32853296
pub fn kind(&self) -> CallableKind {
3286-
match self.def {
3287-
Some(CallableDefId::FunctionId(it)) => CallableKind::Function(it.into()),
3288-
Some(CallableDefId::StructId(it)) => CallableKind::TupleStruct(it.into()),
3289-
Some(CallableDefId::EnumVariantId(it)) => CallableKind::TupleEnumVariant(it.into()),
3290-
None => CallableKind::Closure,
3297+
use Callee::*;
3298+
match self.callee {
3299+
Def(CallableDefId::FunctionId(it)) => CallableKind::Function(it.into()),
3300+
Def(CallableDefId::StructId(it)) => CallableKind::TupleStruct(it.into()),
3301+
Def(CallableDefId::EnumVariantId(it)) => CallableKind::TupleEnumVariant(it.into()),
3302+
Closure(_) => CallableKind::Closure,
3303+
FnPtr => CallableKind::FnPtr,
32913304
}
32923305
}
32933306
pub fn receiver_param(&self, db: &dyn HirDatabase) -> Option<ast::SelfParam> {
3294-
let func = match self.def {
3295-
Some(CallableDefId::FunctionId(it)) if self.is_bound_method => it,
3307+
let func = match self.callee {
3308+
Callee::Def(CallableDefId::FunctionId(it)) if self.is_bound_method => it,
32963309
_ => return None,
32973310
};
32983311
let src = func.lookup(db.upcast()).source(db.upcast());
@@ -3312,18 +3325,30 @@ impl Callable {
33123325
.iter()
33133326
.skip(if self.is_bound_method { 1 } else { 0 })
33143327
.map(|ty| self.ty.derived(ty.clone()));
3315-
let patterns = match self.def {
3316-
Some(CallableDefId::FunctionId(func)) => {
3328+
let map_param = |it: ast::Param| it.pat().map(Either::Right);
3329+
let patterns = match self.callee {
3330+
Callee::Def(CallableDefId::FunctionId(func)) => {
33173331
let src = func.lookup(db.upcast()).source(db.upcast());
33183332
src.value.param_list().map(|param_list| {
33193333
param_list
33203334
.self_param()
33213335
.map(|it| Some(Either::Left(it)))
33223336
.filter(|_| !self.is_bound_method)
33233337
.into_iter()
3324-
.chain(param_list.params().map(|it| it.pat().map(Either::Right)))
3338+
.chain(param_list.params().map(map_param))
33253339
})
33263340
}
3341+
Callee::Closure(closure_id) => match closure_source(db, closure_id) {
3342+
Some(src) => src.param_list().map(|param_list| {
3343+
param_list
3344+
.self_param()
3345+
.map(|it| Some(Either::Left(it)))
3346+
.filter(|_| !self.is_bound_method)
3347+
.into_iter()
3348+
.chain(param_list.params().map(map_param))
3349+
}),
3350+
None => None,
3351+
},
33273352
_ => None,
33283353
};
33293354
patterns.into_iter().flatten().chain(iter::repeat(None)).zip(types).collect()
@@ -3333,6 +3358,18 @@ impl Callable {
33333358
}
33343359
}
33353360

3361+
fn closure_source(db: &dyn HirDatabase, closure: ClosureId) -> Option<ast::ClosureExpr> {
3362+
let (owner, expr_id) = db.lookup_intern_closure(closure.into());
3363+
let (_, source_map) = db.body_with_source_map(owner);
3364+
let ast = source_map.expr_syntax(expr_id).ok()?;
3365+
let root = ast.file_syntax(db.upcast());
3366+
let expr = ast.value.to_node(&root);
3367+
match expr {
3368+
ast::Expr::ClosureExpr(it) => Some(it),
3369+
_ => None,
3370+
}
3371+
}
3372+
33363373
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
33373374
pub enum BindingMode {
33383375
Move,

crates/ide/src/inlay_hints.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1169,6 +1169,23 @@ fn main() {
11691169
);
11701170
}
11711171

1172+
#[test]
1173+
fn param_hints_on_closure() {
1174+
check_params(
1175+
r#"
1176+
fn main() {
1177+
let clo = |a: u8, b: u8| a + b;
1178+
clo(
1179+
1,
1180+
//^ a
1181+
2,
1182+
//^ b
1183+
);
1184+
}
1185+
"#,
1186+
);
1187+
}
1188+
11721189
#[test]
11731190
fn param_name_similar_to_fn_name_still_hints() {
11741191
check_params(
@@ -2000,7 +2017,8 @@ fn main() {
20002017
20012018
;
20022019
2003-
let _: i32 = multiply(1, 2);
2020+
let _: i32 = multiply(1, 2);
2021+
//^ a ^ b
20042022
let multiply_ref = &multiply;
20052023
//^^^^^^^^^^^^ &|i32, i32| -> i32
20062024

crates/ide/src/signature_help.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ fn signature_help_for_call(
149149
variant.name(db)
150150
);
151151
}
152-
hir::CallableKind::Closure => (),
152+
hir::CallableKind::Closure | hir::CallableKind::FnPtr => (),
153153
}
154154

155155
res.signature.push('(');
@@ -189,7 +189,7 @@ fn signature_help_for_call(
189189
hir::CallableKind::Function(func) if callable.return_type().contains_unknown() => {
190190
render(func.ret_type(db))
191191
}
192-
hir::CallableKind::Function(_) | hir::CallableKind::Closure => {
192+
hir::CallableKind::Function(_) | hir::CallableKind::Closure | hir::CallableKind::FnPtr => {
193193
render(callable.return_type())
194194
}
195195
hir::CallableKind::TupleStruct(_) | hir::CallableKind::TupleEnumVariant(_) => {}
@@ -914,8 +914,8 @@ fn main() {
914914
}
915915
"#,
916916
expect![[r#"
917-
(S) -> i32
918-
^
917+
(s: S) -> i32
918+
^^^^
919919
"#]],
920920
)
921921
}

0 commit comments

Comments
 (0)