From 371c5aec1c4ad18f37e96b4bf85c49563fc4a01d Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 17 Jul 2020 10:57:49 +0200 Subject: call_info works with closures --- crates/ra_hir/src/code_model.rs | 33 +++++++++++++++++++-------------- crates/ra_hir_ty/src/lib.rs | 11 +---------- crates/ra_ide/src/call_info.rs | 20 +++++++++++++++++++- crates/ra_ide/src/inlay_hints.rs | 4 +++- 4 files changed, 42 insertions(+), 26 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 0f6953158..859bdfb3b 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -1233,9 +1233,13 @@ impl Type { } pub fn as_callable(&self, db: &dyn HirDatabase) -> Option { - let (id, substs) = self.ty.value.as_callable()?; - let sig = db.callable_item_signature(id).subst(substs); - Some(Callable { ty: self.clone(), sig, id, is_bound_method: false }) + let def = match self.ty.value { + Ty::Apply(ApplicationTy { ctor: TypeCtor::FnDef(def), parameters: _ }) => Some(def), + _ => None, + }; + + let sig = self.ty.value.callable_sig(db)?; + Some(Callable { ty: self.clone(), sig, def, is_bound_method: false }) } pub fn is_closure(&self) -> bool { @@ -1525,7 +1529,7 @@ impl HirDisplay for Type { pub struct Callable { ty: Type, sig: FnSig, - id: CallableDefId, + def: Option, pub(crate) is_bound_method: bool, } @@ -1533,19 +1537,21 @@ pub enum CallableKind { Function(Function), TupleStruct(Struct), TupleEnumVariant(EnumVariant), + Closure, } impl Callable { pub fn kind(&self) -> CallableKind { - match self.id { - CallableDefId::FunctionId(it) => CallableKind::Function(it.into()), - CallableDefId::StructId(it) => CallableKind::TupleStruct(it.into()), - CallableDefId::EnumVariantId(it) => CallableKind::TupleEnumVariant(it.into()), + match self.def { + Some(CallableDefId::FunctionId(it)) => CallableKind::Function(it.into()), + Some(CallableDefId::StructId(it)) => CallableKind::TupleStruct(it.into()), + Some(CallableDefId::EnumVariantId(it)) => CallableKind::TupleEnumVariant(it.into()), + None => CallableKind::Closure, } } pub fn receiver_param(&self, db: &dyn HirDatabase) -> Option { - let func = match self.id { - CallableDefId::FunctionId(it) if self.is_bound_method => it, + let func = match self.def { + Some(CallableDefId::FunctionId(it)) if self.is_bound_method => it, _ => return None, }; let src = func.lookup(db.upcast()).source(db.upcast()); @@ -1565,8 +1571,8 @@ impl Callable { .iter() .skip(if self.is_bound_method { 1 } else { 0 }) .map(|ty| self.ty.derived(ty.clone())); - let patterns = match self.id { - CallableDefId::FunctionId(func) => { + let patterns = match self.def { + Some(CallableDefId::FunctionId(func)) => { let src = func.lookup(db.upcast()).source(db.upcast()); src.value.param_list().map(|param_list| { param_list @@ -1577,8 +1583,7 @@ impl Callable { .chain(param_list.params().map(|it| it.pat().map(Either::Right))) }) } - CallableDefId::StructId(_) => None, - CallableDefId::EnumVariantId(_) => None, + _ => None, }; patterns.into_iter().flatten().chain(iter::repeat(None)).zip(types).collect() } diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs index 1f6626c46..7698cb0d4 100644 --- a/crates/ra_hir_ty/src/lib.rs +++ b/crates/ra_hir_ty/src/lib.rs @@ -767,15 +767,6 @@ impl Ty { } } - pub fn as_callable(&self) -> Option<(CallableDefId, &Substs)> { - match self { - Ty::Apply(ApplicationTy { ctor: TypeCtor::FnDef(callable_def), parameters }) => { - Some((*callable_def, parameters)) - } - _ => None, - } - } - pub fn is_never(&self) -> bool { matches!(self, Ty::Apply(ApplicationTy { ctor: TypeCtor::Never, .. })) } @@ -807,7 +798,7 @@ impl Ty { } } - pub(crate) fn callable_sig(&self, db: &dyn HirDatabase) -> Option { + pub fn callable_sig(&self, db: &dyn HirDatabase) -> Option { match self { Ty::Apply(a_ty) => match a_ty.ctor { TypeCtor::FnPtr { is_varargs, .. } => { diff --git a/crates/ra_ide/src/call_info.rs b/crates/ra_ide/src/call_info.rs index 35a8a0dc5..53d56a0a4 100644 --- a/crates/ra_ide/src/call_info.rs +++ b/crates/ra_ide/src/call_info.rs @@ -70,6 +70,7 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option (), } res.signature.push('('); @@ -93,7 +94,7 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option { + hir::CallableKind::Function(_) | hir::CallableKind::Closure => { let ret_type = callable.return_type(); if !ret_type.is_unit() { format_to!(res.signature, " -> {}", ret_type.display(db)); @@ -702,4 +703,21 @@ id! { "#]], ); } + + #[test] + fn call_info_for_lambdas() { + check( + r#" +struct S; +fn foo(s: S) -> i32 { 92 } +fn main() { + (|s| foo(s))(<|>) +} + "#, + expect![[r#" + (S) -> i32 + () + "#]], + ) + } } diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs index cec3b04e8..43a5e29b5 100644 --- a/crates/ra_ide/src/inlay_hints.rs +++ b/crates/ra_ide/src/inlay_hints.rs @@ -262,7 +262,9 @@ fn should_show_param_name_hint( let param_name = param_name.trim_start_matches('_'); let fn_name = match callable.kind() { hir::CallableKind::Function(it) => Some(it.name(sema.db).to_string()), - hir::CallableKind::TupleStruct(_) | hir::CallableKind::TupleEnumVariant(_) => None, + hir::CallableKind::TupleStruct(_) + | hir::CallableKind::TupleEnumVariant(_) + | hir::CallableKind::Closure => None, }; if param_name.is_empty() || Some(param_name) == fn_name.as_ref().map(|s| s.trim_start_matches('_')) -- cgit v1.2.3