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.rs | 72 |
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()); } |