Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/infer.rs')
-rw-r--r--crates/hir-ty/src/infer.rs72
1 files changed, 66 insertions, 6 deletions
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index 336de14282..22dcea8fcd 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -31,7 +31,7 @@ use hir_def::{
AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, HasModule,
ItemContainerId, Lookup, TraitId, TypeAliasId, VariantId,
};
-use hir_expand::name::name;
+use hir_expand::name::{name, Name};
use la_arena::ArenaMap;
use rustc_hash::FxHashMap;
use stdx::always;
@@ -164,12 +164,45 @@ pub(crate) type InferResult<T> = Result<InferOk<T>, TypeError>;
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum InferenceDiagnostic {
- NoSuchField { expr: ExprId },
- PrivateField { expr: ExprId, field: FieldId },
- PrivateAssocItem { id: ExprOrPatId, item: AssocItemId },
+ NoSuchField {
+ expr: ExprId,
+ },
+ PrivateField {
+ expr: ExprId,
+ field: FieldId,
+ },
+ PrivateAssocItem {
+ id: ExprOrPatId,
+ item: AssocItemId,
+ },
+ UnresolvedField {
+ expr: ExprId,
+ receiver: Ty,
+ name: Name,
+ method_with_same_name_exists: bool,
+ },
+ UnresolvedMethodCall {
+ expr: ExprId,
+ receiver: Ty,
+ name: Name,
+ /// Contains the type the field resolves to
+ field_with_same_name: Option<Ty>,
+ },
// FIXME: Make this proper
- BreakOutsideOfLoop { expr: ExprId, is_break: bool, bad_value_break: bool },
- MismatchedArgCount { call_expr: ExprId, expected: usize, found: usize },
+ 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 +538,33 @@ impl<'a> InferenceContext<'a> {
mismatch.expected = table.resolve_completely(mismatch.expected.clone());
mismatch.actual = table.resolve_completely(mismatch.actual.clone());
}
+ result.diagnostics.retain_mut(|diagnostic| {
+ if let InferenceDiagnostic::ExpectedFunction { found: ty, .. }
+ | InferenceDiagnostic::UnresolvedField { receiver: ty, .. }
+ | InferenceDiagnostic::UnresolvedMethodCall { receiver: ty, .. } = diagnostic
+ {
+ *ty = table.resolve_completely(ty.clone());
+ // FIXME: Remove this when we are on par with rustc in terms of inference
+ if ty.is_unknown() {
+ return false;
+ }
+
+ if let InferenceDiagnostic::UnresolvedMethodCall { field_with_same_name, .. } =
+ diagnostic
+ {
+ let clear = if let Some(ty) = field_with_same_name {
+ *ty = table.resolve_completely(ty.clone());
+ ty.is_unknown()
+ } else {
+ false
+ };
+ if clear {
+ *field_with_same_name = None;
+ }
+ }
+ }
+ true
+ });
for (_, subst) in result.method_resolutions.values_mut() {
*subst = table.resolve_completely(subst.clone());
}