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.rs63
1 files changed, 55 insertions, 8 deletions
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index a663a568b9..22dcea8fcd 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -164,14 +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 },
- UnresolvedField { expr: ExprId, receiver: Ty, name: Name, method_with_same_name_exists: bool },
+ 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 },
- ExpectedFunction { call_expr: ExprId, found: Ty },
+ 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.
@@ -509,12 +540,28 @@ impl<'a> InferenceContext<'a> {
}
result.diagnostics.retain_mut(|diagnostic| {
if let InferenceDiagnostic::ExpectedFunction { found: ty, .. }
- | InferenceDiagnostic::UnresolvedField { receiver: ty, .. } = diagnostic
+ | 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
});