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 | 86 |
1 files changed, 45 insertions, 41 deletions
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index 83659dde17..4c860210a9 100644 --- a/crates/hir-ty/src/infer.rs +++ b/crates/hir-ty/src/infer.rs @@ -89,6 +89,7 @@ use crate::{ abi::Safety, infer::{InferCtxt, ObligationInspector, traits::ObligationCause}, }, + solver_errors::SolverDiagnostic, utils::TargetFeatureIsSafeInTarget, }; @@ -459,13 +460,13 @@ pub enum InferenceDiagnostic { #[type_visitable(ignore)] expr: ExprId, }, -} - -/// A mismatch between an expected and an inferred type. -#[derive(Clone, PartialEq, Eq, Debug, Hash, TypeVisitable, TypeFoldable)] -pub struct TypeMismatch { - pub expected: StoredTy, - pub actual: StoredTy, + TypeMismatch { + #[type_visitable(ignore)] + node: ExprOrPatId, + expected: StoredTy, + found: StoredTy, + }, + SolverDiagnostic(SolverDiagnostic), } /// Represents coercing a value to a different type of value. @@ -685,7 +686,6 @@ pub struct InferenceResult { pub(crate) type_of_type_placeholder: FxHashMap<TypeRefId, StoredTy>, pub(crate) type_of_opaque: FxHashMap<InternedOpaqueTyId, StoredTy>, - pub(crate) type_mismatches: Option<Box<FxHashMap<ExprOrPatId, TypeMismatch>>>, /// Whether there are any type-mismatching errors in the result. // FIXME: This isn't as useful as initially thought due to us falling back placeholders to // `TyKind::Error`. @@ -693,6 +693,8 @@ pub struct InferenceResult { pub(crate) has_errors: bool, /// During inference this field is empty and [`InferenceContext::diagnostics`] is filled instead. diagnostics: ThinVec<InferenceDiagnostic>, + // FIXME: Remove this, change it to be in `InferenceContext`: + nodes_with_type_mismatches: Option<Box<FxHashSet<ExprOrPatId>>>, /// Interned `Error` type to return references to. // FIXME: Remove this. @@ -986,12 +988,12 @@ impl InferenceResult { assoc_resolutions: Default::default(), tuple_field_access_types: Default::default(), diagnostics: Default::default(), + nodes_with_type_mismatches: Default::default(), type_of_expr: Default::default(), type_of_pat: Default::default(), type_of_binding: Default::default(), type_of_type_placeholder: Default::default(), type_of_opaque: Default::default(), - type_mismatches: Default::default(), skipped_ref_pats: Default::default(), has_errors: Default::default(), error_ty: error_ty.store(), @@ -1042,26 +1044,22 @@ impl InferenceResult { ExprOrPatId::PatId(id) => self.assoc_resolutions_for_pat(id), } } - pub fn type_mismatch_for_expr(&self, expr: ExprId) -> Option<&TypeMismatch> { - self.type_mismatches.as_deref()?.get(&expr.into()) + pub fn expr_or_pat_has_type_mismatch(&self, node: ExprOrPatId) -> bool { + self.nodes_with_type_mismatches.as_ref().is_some_and(|it| it.contains(&node)) } - pub fn type_mismatch_for_pat(&self, pat: PatId) -> Option<&TypeMismatch> { - self.type_mismatches.as_deref()?.get(&pat.into()) + pub fn expr_has_type_mismatch(&self, expr: ExprId) -> bool { + self.expr_or_pat_has_type_mismatch(expr.into()) } - pub fn type_mismatches(&self) -> impl Iterator<Item = (ExprOrPatId, &TypeMismatch)> { - self.type_mismatches - .as_deref() - .into_iter() - .flatten() - .map(|(expr_or_pat, mismatch)| (*expr_or_pat, mismatch)) - } - pub fn expr_type_mismatches(&self) -> impl Iterator<Item = (ExprId, &TypeMismatch)> { - self.type_mismatches.as_deref().into_iter().flatten().filter_map( - |(expr_or_pat, mismatch)| match *expr_or_pat { - ExprOrPatId::ExprId(expr) => Some((expr, mismatch)), - _ => None, - }, - ) + pub fn pat_has_type_mismatch(&self, pat: PatId) -> bool { + self.expr_or_pat_has_type_mismatch(pat.into()) + } + pub fn exprs_have_type_mismatches(&self) -> bool { + self.nodes_with_type_mismatches + .as_ref() + .is_some_and(|it| it.iter().any(|node| node.is_expr())) + } + pub fn has_type_mismatches(&self) -> bool { + self.nodes_with_type_mismatches.is_some() } pub fn placeholder_types<'db>(&self) -> impl Iterator<Item = (TypeRefId, Ty<'db>)> { self.type_of_type_placeholder.iter().map(|(&type_ref, ty)| (type_ref, ty.as_ref())) @@ -1408,7 +1406,6 @@ impl<'body, 'db> InferenceContext<'body, 'db> { type_of_type_placeholder, type_of_opaque, skipped_ref_pats, - type_mismatches, closures_data, has_errors, error_ty: _, @@ -1418,6 +1415,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> { tuple_field_access_types, coercion_casts: _, diagnostics: result_diagnostics, + nodes_with_type_mismatches, } = &mut result; let mut resolver = WriteBackCtxt::new(table, diagnostics, vars_emitted_type_must_be_known_for); @@ -1441,12 +1439,9 @@ impl<'body, 'db> InferenceContext<'body, 'db> { type_of_type_placeholder.shrink_to_fit(); type_of_opaque.shrink_to_fit(); - if let Some(type_mismatches) = type_mismatches { + if let Some(nodes_with_type_mismatches) = nodes_with_type_mismatches { *has_errors = true; - for mismatch in type_mismatches.values_mut() { - resolver.resolve_type_mismatch(mismatch); - } - type_mismatches.shrink_to_fit(); + nodes_with_type_mismatches.shrink_to_fit(); } for (_, subst) in method_resolutions.values_mut() { resolver.resolve_completely(subst); @@ -1938,6 +1933,21 @@ impl<'body, 'db> InferenceContext<'body, 'db> { if result.is_ty_var() { self.type_must_be_known_at_this_point(node, ty) } else { result } } + pub(crate) fn emit_type_mismatch( + &mut self, + node: ExprOrPatId, + expected: Ty<'db>, + found: Ty<'db>, + ) { + if self.result.nodes_with_type_mismatches.get_or_insert_default().insert(node) { + self.diagnostics.push(InferenceDiagnostic::TypeMismatch { + node, + expected: expected.store(), + found: found.store(), + }); + } + } + fn demand_eqtype( &mut self, id: ExprOrPatId, @@ -1950,10 +1960,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> { .eq(expected, actual) .map(|infer_ok| self.table.register_infer_ok(infer_ok)); if result.is_err() { - self.result - .type_mismatches - .get_or_insert_default() - .insert(id, TypeMismatch { expected: expected.store(), actual: actual.store() }); + self.emit_type_mismatch(id, expected, actual); } result.map_err(drop) } @@ -1983,10 +1990,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> { .sup(expected, actual) .map(|infer_ok| self.table.register_infer_ok(infer_ok)); if result.is_err() { - self.result - .type_mismatches - .get_or_insert_default() - .insert(id, TypeMismatch { expected: expected.store(), actual: actual.store() }); + self.emit_type_mismatch(id, expected, actual); } result.map_err(drop) } |