aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/code_model.rs33
-rw-r--r--crates/ra_hir_ty/src/lib.rs11
-rw-r--r--crates/ra_ide/src/call_info.rs20
-rw-r--r--crates/ra_ide/src/inlay_hints.rs4
4 files changed, 42 insertions, 26 deletions
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 {
1233 } 1233 }
1234 1234
1235 pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> { 1235 pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> {
1236 let (id, substs) = self.ty.value.as_callable()?; 1236 let def = match self.ty.value {
1237 let sig = db.callable_item_signature(id).subst(substs); 1237 Ty::Apply(ApplicationTy { ctor: TypeCtor::FnDef(def), parameters: _ }) => Some(def),
1238 Some(Callable { ty: self.clone(), sig, id, is_bound_method: false }) 1238 _ => None,
1239 };
1240
1241 let sig = self.ty.value.callable_sig(db)?;
1242 Some(Callable { ty: self.clone(), sig, def, is_bound_method: false })
1239 } 1243 }
1240 1244
1241 pub fn is_closure(&self) -> bool { 1245 pub fn is_closure(&self) -> bool {
@@ -1525,7 +1529,7 @@ impl HirDisplay for Type {
1525pub struct Callable { 1529pub struct Callable {
1526 ty: Type, 1530 ty: Type,
1527 sig: FnSig, 1531 sig: FnSig,
1528 id: CallableDefId, 1532 def: Option<CallableDefId>,
1529 pub(crate) is_bound_method: bool, 1533 pub(crate) is_bound_method: bool,
1530} 1534}
1531 1535
@@ -1533,19 +1537,21 @@ pub enum CallableKind {
1533 Function(Function), 1537 Function(Function),
1534 TupleStruct(Struct), 1538 TupleStruct(Struct),
1535 TupleEnumVariant(EnumVariant), 1539 TupleEnumVariant(EnumVariant),
1540 Closure,
1536} 1541}
1537 1542
1538impl Callable { 1543impl Callable {
1539 pub fn kind(&self) -> CallableKind { 1544 pub fn kind(&self) -> CallableKind {
1540 match self.id { 1545 match self.def {
1541 CallableDefId::FunctionId(it) => CallableKind::Function(it.into()), 1546 Some(CallableDefId::FunctionId(it)) => CallableKind::Function(it.into()),
1542 CallableDefId::StructId(it) => CallableKind::TupleStruct(it.into()), 1547 Some(CallableDefId::StructId(it)) => CallableKind::TupleStruct(it.into()),
1543 CallableDefId::EnumVariantId(it) => CallableKind::TupleEnumVariant(it.into()), 1548 Some(CallableDefId::EnumVariantId(it)) => CallableKind::TupleEnumVariant(it.into()),
1549 None => CallableKind::Closure,
1544 } 1550 }
1545 } 1551 }
1546 pub fn receiver_param(&self, db: &dyn HirDatabase) -> Option<ast::SelfParam> { 1552 pub fn receiver_param(&self, db: &dyn HirDatabase) -> Option<ast::SelfParam> {
1547 let func = match self.id { 1553 let func = match self.def {
1548 CallableDefId::FunctionId(it) if self.is_bound_method => it, 1554 Some(CallableDefId::FunctionId(it)) if self.is_bound_method => it,
1549 _ => return None, 1555 _ => return None,
1550 }; 1556 };
1551 let src = func.lookup(db.upcast()).source(db.upcast()); 1557 let src = func.lookup(db.upcast()).source(db.upcast());
@@ -1565,8 +1571,8 @@ impl Callable {
1565 .iter() 1571 .iter()
1566 .skip(if self.is_bound_method { 1 } else { 0 }) 1572 .skip(if self.is_bound_method { 1 } else { 0 })
1567 .map(|ty| self.ty.derived(ty.clone())); 1573 .map(|ty| self.ty.derived(ty.clone()));
1568 let patterns = match self.id { 1574 let patterns = match self.def {
1569 CallableDefId::FunctionId(func) => { 1575 Some(CallableDefId::FunctionId(func)) => {
1570 let src = func.lookup(db.upcast()).source(db.upcast()); 1576 let src = func.lookup(db.upcast()).source(db.upcast());
1571 src.value.param_list().map(|param_list| { 1577 src.value.param_list().map(|param_list| {
1572 param_list 1578 param_list
@@ -1577,8 +1583,7 @@ impl Callable {
1577 .chain(param_list.params().map(|it| it.pat().map(Either::Right))) 1583 .chain(param_list.params().map(|it| it.pat().map(Either::Right)))
1578 }) 1584 })
1579 } 1585 }
1580 CallableDefId::StructId(_) => None, 1586 _ => None,
1581 CallableDefId::EnumVariantId(_) => None,
1582 }; 1587 };
1583 patterns.into_iter().flatten().chain(iter::repeat(None)).zip(types).collect() 1588 patterns.into_iter().flatten().chain(iter::repeat(None)).zip(types).collect()
1584 } 1589 }
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 {
767 } 767 }
768 } 768 }
769 769
770 pub fn as_callable(&self) -> Option<(CallableDefId, &Substs)> {
771 match self {
772 Ty::Apply(ApplicationTy { ctor: TypeCtor::FnDef(callable_def), parameters }) => {
773 Some((*callable_def, parameters))
774 }
775 _ => None,
776 }
777 }
778
779 pub fn is_never(&self) -> bool { 770 pub fn is_never(&self) -> bool {
780 matches!(self, Ty::Apply(ApplicationTy { ctor: TypeCtor::Never, .. })) 771 matches!(self, Ty::Apply(ApplicationTy { ctor: TypeCtor::Never, .. }))
781 } 772 }
@@ -807,7 +798,7 @@ impl Ty {
807 } 798 }
808 } 799 }
809 800
810 pub(crate) fn callable_sig(&self, db: &dyn HirDatabase) -> Option<FnSig> { 801 pub fn callable_sig(&self, db: &dyn HirDatabase) -> Option<FnSig> {
811 match self { 802 match self {
812 Ty::Apply(a_ty) => match a_ty.ctor { 803 Ty::Apply(a_ty) => match a_ty.ctor {
813 TypeCtor::FnPtr { is_varargs, .. } => { 804 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<Cal
70 variant.name(db) 70 variant.name(db)
71 ); 71 );
72 } 72 }
73 hir::CallableKind::Closure => (),
73 } 74 }
74 75
75 res.signature.push('('); 76 res.signature.push('(');
@@ -93,7 +94,7 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
93 res.signature.push(')'); 94 res.signature.push(')');
94 95
95 match callable.kind() { 96 match callable.kind() {
96 hir::CallableKind::Function(_) => { 97 hir::CallableKind::Function(_) | hir::CallableKind::Closure => {
97 let ret_type = callable.return_type(); 98 let ret_type = callable.return_type();
98 if !ret_type.is_unit() { 99 if !ret_type.is_unit() {
99 format_to!(res.signature, " -> {}", ret_type.display(db)); 100 format_to!(res.signature, " -> {}", ret_type.display(db));
@@ -702,4 +703,21 @@ id! {
702 "#]], 703 "#]],
703 ); 704 );
704 } 705 }
706
707 #[test]
708 fn call_info_for_lambdas() {
709 check(
710 r#"
711struct S;
712fn foo(s: S) -> i32 { 92 }
713fn main() {
714 (|s| foo(s))(<|>)
715}
716 "#,
717 expect![[r#"
718 (S) -> i32
719 (<S>)
720 "#]],
721 )
722 }
705} 723}
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(
262 let param_name = param_name.trim_start_matches('_'); 262 let param_name = param_name.trim_start_matches('_');
263 let fn_name = match callable.kind() { 263 let fn_name = match callable.kind() {
264 hir::CallableKind::Function(it) => Some(it.name(sema.db).to_string()), 264 hir::CallableKind::Function(it) => Some(it.name(sema.db).to_string()),
265 hir::CallableKind::TupleStruct(_) | hir::CallableKind::TupleEnumVariant(_) => None, 265 hir::CallableKind::TupleStruct(_)
266 | hir::CallableKind::TupleEnumVariant(_)
267 | hir::CallableKind::Closure => None,
266 }; 268 };
267 if param_name.is_empty() 269 if param_name.is_empty()
268 || Some(param_name) == fn_name.as_ref().map(|s| s.trim_start_matches('_')) 270 || Some(param_name) == fn_name.as_ref().map(|s| s.trim_start_matches('_'))