Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir-ty/src/infer.rs9
-rw-r--r--crates/hir-ty/src/infer/expr.rs8
-rw-r--r--crates/hir/src/diagnostics.rs7
-rw-r--r--crates/hir/src/lib.rs33
-rw-r--r--crates/ide-diagnostics/src/handlers/expected_function.rs38
-rw-r--r--crates/ide-diagnostics/src/lib.rs2
6 files changed, 83 insertions, 14 deletions
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index 336de14282..0c7529cffe 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -170,6 +170,7 @@ pub enum InferenceDiagnostic {
// FIXME: Make this proper
BreakOutsideOfLoop { expr: ExprId, is_break: bool, bad_value_break: bool },
MismatchedArgCount { call_expr: ExprId, expected: usize, found: usize },
+ ExpectedFunction { call_expr: ExprId, found: Ty },
}
/// A mismatch between an expected and an inferred type.
@@ -505,6 +506,14 @@ impl<'a> InferenceContext<'a> {
mismatch.expected = table.resolve_completely(mismatch.expected.clone());
mismatch.actual = table.resolve_completely(mismatch.actual.clone());
}
+ for diagnostic in &mut result.diagnostics {
+ match diagnostic {
+ InferenceDiagnostic::ExpectedFunction { found, .. } => {
+ *found = table.resolve_completely(found.clone())
+ }
+ _ => (),
+ }
+ }
for (_, subst) in result.method_resolutions.values_mut() {
*subst = table.resolve_completely(subst.clone());
}
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index e64b020c7f..9d75b67bc7 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/crates/hir-ty/src/infer/expr.rs
@@ -364,7 +364,13 @@ impl<'a> InferenceContext<'a> {
}
(params, ret_ty)
}
- None => (Vec::new(), self.err_ty()), // FIXME diagnostic
+ None => {
+ self.result.diagnostics.push(InferenceDiagnostic::ExpectedFunction {
+ call_expr: tgt_expr,
+ found: callee_ty.clone(),
+ });
+ (Vec::new(), self.err_ty())
+ }
};
let indices_to_skip = self.check_legacy_const_generics(derefed_callee, args);
self.register_obligations_for_call(&callee_ty);
diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs
index bb7468d466..3a6f26a4ea 100644
--- a/crates/hir/src/diagnostics.rs
+++ b/crates/hir/src/diagnostics.rs
@@ -31,6 +31,7 @@ macro_rules! diagnostics {
diagnostics![
BreakOutsideOfLoop,
+ ExpectedFunction,
InactiveCode,
IncorrectCase,
InvalidDeriveTarget,
@@ -131,6 +132,12 @@ pub struct PrivateAssocItem {
}
#[derive(Debug)]
+pub struct ExpectedFunction {
+ pub call: InFile<AstPtr<ast::Expr>>,
+ pub found: Type,
+}
+
+#[derive(Debug)]
pub struct PrivateField {
pub expr: InFile<AstPtr<ast::Expr>>,
pub field: Field,
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index bfc0d58cc7..08ccf38b65 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -84,9 +84,9 @@ use crate::db::{DefDatabase, HirDatabase};
pub use crate::{
attrs::{HasAttrs, Namespace},
diagnostics::{
- AnyDiagnostic, BreakOutsideOfLoop, InactiveCode, IncorrectCase, InvalidDeriveTarget,
- MacroError, MalformedDerive, MismatchedArgCount, MissingFields, MissingMatchArms,
- MissingUnsafe, NoSuchField, PrivateAssocItem, PrivateField,
+ AnyDiagnostic, BreakOutsideOfLoop, ExpectedFunction, InactiveCode, IncorrectCase,
+ InvalidDeriveTarget, MacroError, MalformedDerive, MismatchedArgCount, MissingFields,
+ MissingMatchArms, MissingUnsafe, NoSuchField, PrivateAssocItem, PrivateField,
ReplaceFilterMapNextWithFindMap, TypeMismatch, UnimplementedBuiltinMacro,
UnresolvedExternCrate, UnresolvedImport, UnresolvedMacroCall, UnresolvedModule,
UnresolvedProcMacro,
@@ -1377,8 +1377,8 @@ impl DefWithBody {
let source_map = Lazy::new(|| db.body_with_source_map(self.into()).1);
for d in &infer.diagnostics {
match d {
- hir_ty::InferenceDiagnostic::NoSuchField { expr } => {
- let field = source_map.field_syntax(*expr);
+ &hir_ty::InferenceDiagnostic::NoSuchField { expr } => {
+ let field = source_map.field_syntax(expr);
acc.push(NoSuchField { field }.into())
}
&hir_ty::InferenceDiagnostic::BreakOutsideOfLoop {
@@ -1391,15 +1391,10 @@ impl DefWithBody {
.expect("break outside of loop in synthetic syntax");
acc.push(BreakOutsideOfLoop { expr, is_break, bad_value_break }.into())
}
- hir_ty::InferenceDiagnostic::MismatchedArgCount { call_expr, expected, found } => {
- match source_map.expr_syntax(*call_expr) {
+ &hir_ty::InferenceDiagnostic::MismatchedArgCount { call_expr, expected, found } => {
+ match source_map.expr_syntax(call_expr) {
Ok(source_ptr) => acc.push(
- MismatchedArgCount {
- call_expr: source_ptr,
- expected: *expected,
- found: *found,
- }
- .into(),
+ MismatchedArgCount { call_expr: source_ptr, expected, found }.into(),
),
Err(SyntheticSyntax) => (),
}
@@ -1423,6 +1418,18 @@ impl DefWithBody {
let item = item.into();
acc.push(PrivateAssocItem { expr_or_pat, item }.into())
}
+ hir_ty::InferenceDiagnostic::ExpectedFunction { call_expr, found } => {
+ let call_expr =
+ source_map.expr_syntax(*call_expr).expect("unexpected synthetic");
+
+ acc.push(
+ ExpectedFunction {
+ call: call_expr,
+ found: Type::new(db, DefWithBodyId::from(self), found.clone()),
+ }
+ .into(),
+ )
+ }
}
}
for (pat_or_expr, mismatch) in infer.type_mismatches() {
diff --git a/crates/ide-diagnostics/src/handlers/expected_function.rs b/crates/ide-diagnostics/src/handlers/expected_function.rs
new file mode 100644
index 0000000000..23bc778da2
--- /dev/null
+++ b/crates/ide-diagnostics/src/handlers/expected_function.rs
@@ -0,0 +1,38 @@
+use hir::HirDisplay;
+
+use crate::{Diagnostic, DiagnosticsContext};
+
+// Diagnostic: expected-function
+//
+// This diagnostic is triggered if a call is made on something that is not callable.
+pub(crate) fn expected_function(
+ ctx: &DiagnosticsContext<'_>,
+ d: &hir::ExpectedFunction,
+) -> Diagnostic {
+ Diagnostic::new(
+ "expected-function",
+ format!("expected function, found {}", d.found.display(ctx.sema.db)),
+ ctx.sema.diagnostics_display_range(d.call.clone().map(|it| it.into())).range,
+ )
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::tests::check_diagnostics;
+
+ #[test]
+ fn smoke_test() {
+ check_diagnostics(
+ r#"
+fn foo() {
+ let x = 3;
+ x();
+ // ^^^ error: expected function, found i32
+ ""();
+ // ^^^^ error: expected function, found &str
+ foo();
+}
+"#,
+ );
+ }
+}
diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs
index 64ba08ac88..b878119fee 100644
--- a/crates/ide-diagnostics/src/lib.rs
+++ b/crates/ide-diagnostics/src/lib.rs
@@ -27,6 +27,7 @@
mod handlers {
pub(crate) mod break_outside_of_loop;
+ pub(crate) mod expected_function;
pub(crate) mod inactive_code;
pub(crate) mod incorrect_case;
pub(crate) mod invalid_derive_target;
@@ -248,6 +249,7 @@ pub fn diagnostics(
#[rustfmt::skip]
let d = match diag {
AnyDiagnostic::BreakOutsideOfLoop(d) => handlers::break_outside_of_loop::break_outside_of_loop(&ctx, &d),
+ AnyDiagnostic::ExpectedFunction(d) => handlers::expected_function::expected_function(&ctx, &d),
AnyDiagnostic::IncorrectCase(d) => handlers::incorrect_case::incorrect_case(&ctx, &d),
AnyDiagnostic::MacroError(d) => handlers::macro_error::macro_error(&ctx, &d),
AnyDiagnostic::MalformedDerive(d) => handlers::malformed_derive::malformed_derive(&ctx, &d),