Skip to content

Commit 4b3d7f6

Browse files
committed
Render closure fn trait kind in siganture help
1 parent 7045044 commit 4b3d7f6

File tree

3 files changed

+79
-27
lines changed

3 files changed

+79
-27
lines changed

src/tools/rust-analyzer/crates/hir-ty/src/traits.rs

+11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! Trait solving using Chalk.
22
3+
use core::fmt;
34
use std::env::var;
45

56
use chalk_ir::{fold::TypeFoldable, DebruijnIndex, GoalData};
@@ -209,6 +210,16 @@ pub enum FnTrait {
209210
Fn,
210211
}
211212

213+
impl fmt::Display for FnTrait {
214+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
215+
match self {
216+
FnTrait::FnOnce => write!(f, "FnOnce"),
217+
FnTrait::FnMut => write!(f, "FnMut"),
218+
FnTrait::Fn => write!(f, "Fn"),
219+
}
220+
}
221+
}
222+
212223
impl FnTrait {
213224
const fn lang_item(self) -> LangItem {
214225
match self {

src/tools/rust-analyzer/crates/hir/src/lib.rs

+32-22
Original file line numberDiff line numberDiff line change
@@ -2199,7 +2199,7 @@ impl Param {
21992199
pub fn as_local(&self, db: &dyn HirDatabase) -> Option<Local> {
22002200
let parent = match self.func {
22012201
Callee::Def(CallableDefId::FunctionId(it)) => DefWithBodyId::FunctionId(it),
2202-
Callee::Closure(closure) => db.lookup_intern_closure(closure.into()).0,
2202+
Callee::Closure(closure, _) => db.lookup_intern_closure(closure.into()).0,
22032203
_ => return None,
22042204
};
22052205
let body = db.body(parent);
@@ -2237,7 +2237,7 @@ impl Param {
22372237
}
22382238
.map(|value| InFile { file_id, value })
22392239
}
2240-
Callee::Closure(closure) => {
2240+
Callee::Closure(closure, _) => {
22412241
let InternedClosure(owner, expr_id) = db.lookup_intern_closure(closure.into());
22422242
let (_, source_map) = db.body_with_source_map(owner);
22432243
let ast @ InFile { file_id, value } = source_map.expr_syntax(expr_id).ok()?;
@@ -4316,16 +4316,23 @@ impl Type {
43164316
}
43174317

43184318
pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> {
4319-
let mut the_ty = &self.ty;
43204319
let callee = match self.ty.kind(Interner) {
4321-
TyKind::Ref(_, _, ty) if ty.as_closure().is_some() => {
4322-
the_ty = ty;
4323-
Callee::Closure(ty.as_closure().unwrap())
4324-
}
4325-
TyKind::Closure(id, _) => Callee::Closure(*id),
4320+
TyKind::Closure(id, subst) => Callee::Closure(*id, subst.clone()),
43264321
TyKind::Function(_) => Callee::FnPtr,
43274322
TyKind::FnDef(..) => Callee::Def(self.ty.callable_def(db)?),
4328-
_ => {
4323+
kind => {
4324+
// This branch shouldn't be necessary?
4325+
if let TyKind::Ref(_, _, ty) = kind {
4326+
if let TyKind::Closure(closure, subst) = ty.kind(Interner) {
4327+
let sig = ty.callable_sig(db)?;
4328+
return Some(Callable {
4329+
ty: self.clone(),
4330+
sig,
4331+
callee: Callee::Closure(*closure, subst.clone()),
4332+
is_bound_method: false,
4333+
});
4334+
}
4335+
}
43294336
let sig = hir_ty::callable_sig_from_fnonce(&self.ty, self.env.clone(), db)?;
43304337
return Some(Callable {
43314338
ty: self.clone(),
@@ -4336,7 +4343,7 @@ impl Type {
43364343
}
43374344
};
43384345

4339-
let sig = the_ty.callable_sig(db)?;
4346+
let sig = self.ty.callable_sig(db)?;
43404347
Some(Callable { ty: self.clone(), sig, callee, is_bound_method: false })
43414348
}
43424349

@@ -4953,13 +4960,13 @@ pub struct Callable {
49534960
sig: CallableSig,
49544961
callee: Callee,
49554962
/// Whether this is a method that was called with method call syntax.
4956-
pub(crate) is_bound_method: bool,
4963+
is_bound_method: bool,
49574964
}
49584965

4959-
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
4966+
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
49604967
enum Callee {
49614968
Def(CallableDefId),
4962-
Closure(ClosureId),
4969+
Closure(ClosureId, Substitution),
49634970
FnPtr,
49644971
Other,
49654972
}
@@ -4968,22 +4975,25 @@ pub enum CallableKind {
49684975
Function(Function),
49694976
TupleStruct(Struct),
49704977
TupleEnumVariant(Variant),
4971-
Closure,
4978+
Closure(Closure),
49724979
FnPtr,
49734980
/// Some other type that implements `FnOnce`.
49744981
Other,
49754982
}
49764983

49774984
impl Callable {
49784985
pub fn kind(&self) -> CallableKind {
4979-
use Callee::*;
49804986
match self.callee {
4981-
Def(CallableDefId::FunctionId(it)) => CallableKind::Function(it.into()),
4982-
Def(CallableDefId::StructId(it)) => CallableKind::TupleStruct(it.into()),
4983-
Def(CallableDefId::EnumVariantId(it)) => CallableKind::TupleEnumVariant(it.into()),
4984-
Closure(_) => CallableKind::Closure,
4985-
FnPtr => CallableKind::FnPtr,
4986-
Other => CallableKind::Other,
4987+
Callee::Def(CallableDefId::FunctionId(it)) => CallableKind::Function(it.into()),
4988+
Callee::Def(CallableDefId::StructId(it)) => CallableKind::TupleStruct(it.into()),
4989+
Callee::Def(CallableDefId::EnumVariantId(it)) => {
4990+
CallableKind::TupleEnumVariant(it.into())
4991+
}
4992+
Callee::Closure(id, ref subst) => {
4993+
CallableKind::Closure(Closure { id, subst: subst.clone() })
4994+
}
4995+
Callee::FnPtr => CallableKind::FnPtr,
4996+
Callee::Other => CallableKind::Other,
49874997
}
49884998
}
49894999
pub fn receiver_param(&self, db: &dyn HirDatabase) -> Option<(SelfParam, Type)> {
@@ -5004,7 +5014,7 @@ impl Callable {
50045014
.enumerate()
50055015
.skip(if self.is_bound_method { 1 } else { 0 })
50065016
.map(|(idx, ty)| (idx, self.ty.derived(ty.clone())))
5007-
.map(|(idx, ty)| Param { func: self.callee, idx, ty })
5017+
.map(|(idx, ty)| Param { func: self.callee.clone(), idx, ty })
50085018
.collect()
50095019
}
50105020
pub fn return_type(&self) -> Type {

src/tools/rust-analyzer/crates/ide/src/signature_help.rs

+36-5
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,10 @@ fn signature_help_for_call(
201201
variant.name(db).display(db)
202202
);
203203
}
204-
hir::CallableKind::Closure | hir::CallableKind::FnPtr | hir::CallableKind::Other => (),
204+
hir::CallableKind::Closure(closure) => {
205+
format_to!(res.signature, "impl {}", closure.fn_trait(db));
206+
}
207+
hir::CallableKind::FnPtr | hir::CallableKind::Other => (),
205208
}
206209

207210
res.signature.push('(');
@@ -245,7 +248,7 @@ fn signature_help_for_call(
245248
render(func.ret_type(db))
246249
}
247250
hir::CallableKind::Function(_)
248-
| hir::CallableKind::Closure
251+
| hir::CallableKind::Closure(_)
249252
| hir::CallableKind::FnPtr
250253
| hir::CallableKind::Other => render(callable.return_type()),
251254
hir::CallableKind::TupleStruct(_) | hir::CallableKind::TupleEnumVariant(_) => {}
@@ -1348,15 +1351,43 @@ fn test() { S.foo($0); }
13481351
r#"
13491352
struct S;
13501353
fn foo(s: S) -> i32 { 92 }
1354+
fn main() {
1355+
let _move = S;
1356+
(|s| {{_move}; foo(s)})($0)
1357+
}
1358+
"#,
1359+
expect![[r#"
1360+
impl FnOnce(s: S) -> i32
1361+
^^^^
1362+
"#]],
1363+
);
1364+
check(
1365+
r#"
1366+
struct S;
1367+
fn foo(s: S) -> i32 { 92 }
13511368
fn main() {
13521369
(|s| foo(s))($0)
13531370
}
13541371
"#,
13551372
expect![[r#"
1356-
(s: S) -> i32
1357-
^^^^
1373+
impl Fn(s: S) -> i32
1374+
^^^^
13581375
"#]],
1359-
)
1376+
);
1377+
check(
1378+
r#"
1379+
struct S;
1380+
fn foo(s: S) -> i32 { 92 }
1381+
fn main() {
1382+
let mut mutate = 0;
1383+
(|s| { mutate = 1; foo(s) })($0)
1384+
}
1385+
"#,
1386+
expect![[r#"
1387+
impl FnMut(s: S) -> i32
1388+
^^^^
1389+
"#]],
1390+
);
13601391
}
13611392

13621393
#[test]

0 commit comments

Comments
 (0)