Skip to content

Commit 9b5ac1d

Browse files
bors[bot]matklad
andauthored
Merge #5417
5417: Mismatched arg count works for lambdas r=jonas-schievink a=matklad Co-authored-by: Aleksey Kladov <[email protected]>
2 parents 6ae6c14 + 393b711 commit 9b5ac1d

File tree

5 files changed

+86
-35
lines changed

5 files changed

+86
-35
lines changed

crates/ra_hir/src/code_model.rs

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1233,9 +1233,13 @@ impl Type {
12331233
}
12341234

12351235
pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> {
1236-
let (id, substs) = self.ty.value.as_callable()?;
1237-
let sig = db.callable_item_signature(id).subst(substs);
1238-
Some(Callable { ty: self.clone(), sig, id, is_bound_method: false })
1236+
let def = match self.ty.value {
1237+
Ty::Apply(ApplicationTy { ctor: TypeCtor::FnDef(def), parameters: _ }) => Some(def),
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 })
12391243
}
12401244

12411245
pub fn is_closure(&self) -> bool {
@@ -1525,27 +1529,29 @@ impl HirDisplay for Type {
15251529
pub struct Callable {
15261530
ty: Type,
15271531
sig: FnSig,
1528-
id: CallableDefId,
1532+
def: Option<CallableDefId>,
15291533
pub(crate) is_bound_method: bool,
15301534
}
15311535

15321536
pub enum CallableKind {
15331537
Function(Function),
15341538
TupleStruct(Struct),
15351539
TupleEnumVariant(EnumVariant),
1540+
Closure,
15361541
}
15371542

15381543
impl Callable {
15391544
pub fn kind(&self) -> CallableKind {
1540-
match self.id {
1541-
CallableDefId::FunctionId(it) => CallableKind::Function(it.into()),
1542-
CallableDefId::StructId(it) => CallableKind::TupleStruct(it.into()),
1543-
CallableDefId::EnumVariantId(it) => CallableKind::TupleEnumVariant(it.into()),
1545+
match self.def {
1546+
Some(CallableDefId::FunctionId(it)) => CallableKind::Function(it.into()),
1547+
Some(CallableDefId::StructId(it)) => CallableKind::TupleStruct(it.into()),
1548+
Some(CallableDefId::EnumVariantId(it)) => CallableKind::TupleEnumVariant(it.into()),
1549+
None => CallableKind::Closure,
15441550
}
15451551
}
15461552
pub fn receiver_param(&self, db: &dyn HirDatabase) -> Option<ast::SelfParam> {
1547-
let func = match self.id {
1548-
CallableDefId::FunctionId(it) if self.is_bound_method => it,
1553+
let func = match self.def {
1554+
Some(CallableDefId::FunctionId(it)) if self.is_bound_method => it,
15491555
_ => return None,
15501556
};
15511557
let src = func.lookup(db.upcast()).source(db.upcast());
@@ -1565,8 +1571,8 @@ impl Callable {
15651571
.iter()
15661572
.skip(if self.is_bound_method { 1 } else { 0 })
15671573
.map(|ty| self.ty.derived(ty.clone()));
1568-
let patterns = match self.id {
1569-
CallableDefId::FunctionId(func) => {
1574+
let patterns = match self.def {
1575+
Some(CallableDefId::FunctionId(func)) => {
15701576
let src = func.lookup(db.upcast()).source(db.upcast());
15711577
src.value.param_list().map(|param_list| {
15721578
param_list
@@ -1577,8 +1583,7 @@ impl Callable {
15771583
.chain(param_list.params().map(|it| it.pat().map(Either::Right)))
15781584
})
15791585
}
1580-
CallableDefId::StructId(_) => None,
1581-
CallableDefId::EnumVariantId(_) => None,
1586+
_ => None,
15821587
};
15831588
patterns.into_iter().flatten().chain(iter::repeat(None)).zip(types).collect()
15841589
}

crates/ra_hir_ty/src/diagnostics/expr.rs

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -158,28 +158,32 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
158158
}
159159

160160
let is_method_call = matches!(expr, Expr::MethodCall { .. });
161-
let (callee, args) = match expr {
161+
let (sig, args) = match expr {
162162
Expr::Call { callee, args } => {
163163
let callee = &self.infer.type_of_expr[*callee];
164-
let (callable, _) = callee.as_callable()?;
165-
166-
(callable, args.clone())
164+
let sig = callee.callable_sig(db)?;
165+
(sig, args.clone())
167166
}
168167
Expr::MethodCall { receiver, args, .. } => {
169-
let callee = self.infer.method_resolution(call_id)?;
170168
let mut args = args.clone();
171169
args.insert(0, *receiver);
172-
(callee.into(), args)
170+
171+
// FIXME: note that we erase information about substs here. This
172+
// is not right, but, luckily, doesn't matter as we care only
173+
// about the number of params
174+
let callee = self.infer.method_resolution(call_id)?;
175+
let sig = db.callable_item_signature(callee.into()).value;
176+
177+
(sig, args)
173178
}
174179
_ => return None,
175180
};
176181

177-
let sig = db.callable_item_signature(callee);
178-
if sig.value.is_varargs {
182+
if sig.is_varargs {
179183
return None;
180184
}
181185

182-
let params = sig.value.params();
186+
let params = sig.params();
183187

184188
let mut param_count = params.len();
185189
let mut arg_count = args.len();
@@ -542,4 +546,20 @@ fn f() {
542546
"#,
543547
)
544548
}
549+
550+
#[test]
551+
fn arg_count_lambda() {
552+
check_diagnostics(
553+
r#"
554+
fn main() {
555+
let f = |()| ();
556+
f();
557+
//^^^ Expected 1 argument, found 0
558+
f(());
559+
f((), ());
560+
//^^^^^^^^^ Expected 1 argument, found 2
561+
}
562+
"#,
563+
)
564+
}
545565
}

crates/ra_hir_ty/src/lib.rs

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -767,15 +767,6 @@ impl Ty {
767767
}
768768
}
769769

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-
779770
pub fn is_never(&self) -> bool {
780771
matches!(self, Ty::Apply(ApplicationTy { ctor: TypeCtor::Never, .. }))
781772
}
@@ -807,7 +798,7 @@ impl Ty {
807798
}
808799
}
809800

810-
fn callable_sig(&self, db: &dyn HirDatabase) -> Option<FnSig> {
801+
pub fn callable_sig(&self, db: &dyn HirDatabase) -> Option<FnSig> {
811802
match self {
812803
Ty::Apply(a_ty) => match a_ty.ctor {
813804
TypeCtor::FnPtr { is_varargs, .. } => {

crates/ra_ide/src/call_info.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
7070
variant.name(db)
7171
);
7272
}
73+
hir::CallableKind::Closure => (),
7374
}
7475

7576
res.signature.push('(');
@@ -93,7 +94,7 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
9394
res.signature.push(')');
9495

9596
match callable.kind() {
96-
hir::CallableKind::Function(_) => {
97+
hir::CallableKind::Function(_) | hir::CallableKind::Closure => {
9798
let ret_type = callable.return_type();
9899
if !ret_type.is_unit() {
99100
format_to!(res.signature, " -> {}", ret_type.display(db));
@@ -702,4 +703,36 @@ id! {
702703
"#]],
703704
);
704705
}
706+
707+
#[test]
708+
fn call_info_for_lambdas() {
709+
check(
710+
r#"
711+
struct S;
712+
fn foo(s: S) -> i32 { 92 }
713+
fn main() {
714+
(|s| foo(s))(<|>)
715+
}
716+
"#,
717+
expect![[r#"
718+
(S) -> i32
719+
(<S>)
720+
"#]],
721+
)
722+
}
723+
724+
#[test]
725+
fn call_info_for_fn_ptr() {
726+
check(
727+
r#"
728+
fn main(f: fn(i32, f64) -> char) {
729+
f(0, <|>)
730+
}
731+
"#,
732+
expect![[r#"
733+
(i32, f64) -> char
734+
(i32, <f64>)
735+
"#]],
736+
)
737+
}
705738
}

crates/ra_ide/src/inlay_hints.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,9 @@ fn should_show_param_name_hint(
262262
let param_name = param_name.trim_start_matches('_');
263263
let fn_name = match callable.kind() {
264264
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,
266268
};
267269
if param_name.is_empty()
268270
|| Some(param_name) == fn_name.as_ref().map(|s| s.trim_start_matches('_'))

0 commit comments

Comments
 (0)