Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--Cargo.lock1
-rw-r--r--crates/hir-ty/Cargo.toml1
-rw-r--r--crates/hir-ty/src/infer.rs53
-rw-r--r--crates/hir-ty/src/infer/coerce.rs2
-rw-r--r--crates/hir-ty/src/infer/diagnostics.rs5
-rw-r--r--crates/hir-ty/src/infer/expr.rs7
-rw-r--r--crates/hir-ty/src/infer/pat.rs8
-rw-r--r--crates/hir-ty/src/method_resolution/confirm.rs2
8 files changed, 54 insertions, 25 deletions
diff --git a/Cargo.lock b/Cargo.lock
index e21776cdab..7e1bd6320d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -905,6 +905,7 @@ dependencies = [
"syntax",
"test-fixture",
"test-utils",
+ "thin-vec",
"tracing",
"tracing-subscriber",
"tracing-tree",
diff --git a/crates/hir-ty/Cargo.toml b/crates/hir-ty/Cargo.toml
index 8adf95bd04..c60ecef58e 100644
--- a/crates/hir-ty/Cargo.toml
+++ b/crates/hir-ty/Cargo.toml
@@ -53,6 +53,7 @@ hir-expand.workspace = true
base-db.workspace = true
syntax.workspace = true
span.workspace = true
+thin-vec = "0.2.14"
[dev-dependencies]
expect-test = "1.5.1"
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index 15eb355128..616b9fd448 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -56,6 +56,7 @@ use rustc_type_ir::{
};
use span::Edition;
use stdx::never;
+use thin_vec::ThinVec;
use triomphe::Arc;
use crate::{
@@ -489,8 +490,7 @@ pub struct InferenceResult<'db> {
/// [`InferenceContext`] and store the tuples substitution there. This map is the reverse of
/// that which allows us to resolve a [`TupleFieldId`]s type.
tuple_field_access_types: FxHashMap<TupleId, Tys<'db>>,
- /// During inference this field is empty and [`InferenceContext::diagnostics`] is filled instead.
- diagnostics: Vec<InferenceDiagnostic<'db>>,
+
pub(crate) type_of_expr: ArenaMap<ExprId, Ty<'db>>,
/// For each pattern record the type it resolves to.
///
@@ -500,15 +500,21 @@ pub struct InferenceResult<'db> {
pub(crate) type_of_binding: ArenaMap<BindingId, Ty<'db>>,
pub(crate) type_of_type_placeholder: ArenaMap<TypeRefId, Ty<'db>>,
pub(crate) type_of_opaque: FxHashMap<InternedOpaqueTyId, Ty<'db>>,
- pub(crate) type_mismatches: FxHashMap<ExprOrPatId, TypeMismatch<'db>>,
+
+ pub(crate) type_mismatches: Option<Box<FxHashMap<ExprOrPatId, TypeMismatch<'db>>>>,
/// 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`.
// Which will then mark this field.
pub(crate) has_errors: bool,
+ /// During inference this field is empty and [`InferenceContext::diagnostics`] is filled instead.
+ diagnostics: ThinVec<InferenceDiagnostic<'db>>,
+
/// Interned `Error` type to return references to.
// FIXME: Remove this.
error_ty: Ty<'db>,
+
+ pub(crate) expr_adjustments: FxHashMap<ExprId, Box<[Adjustment<'db>]>>,
/// Stores the types which were implicitly dereferenced in pattern binding modes.
pub(crate) pat_adjustments: FxHashMap<PatId, Vec<Ty<'db>>>,
/// Stores the binding mode (`ref` in `let ref x = 2`) of bindings.
@@ -525,10 +531,11 @@ pub struct InferenceResult<'db> {
/// ```
/// the first `rest` has implicit `ref` binding mode, but the second `rest` binding mode is `move`.
pub(crate) binding_modes: ArenaMap<PatId, BindingMode>,
- pub(crate) expr_adjustments: FxHashMap<ExprId, Box<[Adjustment<'db>]>>,
+
pub(crate) closure_info: FxHashMap<InternedClosureId, (Vec<CapturedItem<'db>>, FnTrait)>,
// FIXME: remove this field
pub mutated_bindings_in_closure: FxHashSet<BindingId>,
+
pub(crate) coercion_casts: FxHashSet<ExprId>,
}
@@ -595,19 +602,25 @@ impl<'db> InferenceResult<'db> {
}
}
pub fn type_mismatch_for_expr(&self, expr: ExprId) -> Option<&TypeMismatch<'db>> {
- self.type_mismatches.get(&expr.into())
+ self.type_mismatches.as_deref()?.get(&expr.into())
}
pub fn type_mismatch_for_pat(&self, pat: PatId) -> Option<&TypeMismatch<'db>> {
- self.type_mismatches.get(&pat.into())
+ self.type_mismatches.as_deref()?.get(&pat.into())
}
pub fn type_mismatches(&self) -> impl Iterator<Item = (ExprOrPatId, &TypeMismatch<'db>)> {
- self.type_mismatches.iter().map(|(expr_or_pat, mismatch)| (*expr_or_pat, mismatch))
+ 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<'db>)> {
- self.type_mismatches.iter().filter_map(|(expr_or_pat, mismatch)| match *expr_or_pat {
- ExprOrPatId::ExprId(expr) => Some((expr, mismatch)),
- _ => None,
- })
+ 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 placeholder_types(&self) -> impl Iterator<Item = (TypeRefId, &Ty<'db>)> {
self.type_of_type_placeholder.iter()
@@ -1063,13 +1076,14 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
type_of_type_placeholder.shrink_to_fit();
type_of_opaque.shrink_to_fit();
- *has_errors |= !type_mismatches.is_empty();
-
- for mismatch in (*type_mismatches).values_mut() {
- mismatch.expected = table.resolve_completely(mismatch.expected);
- mismatch.actual = table.resolve_completely(mismatch.actual);
+ if let Some(type_mismatches) = type_mismatches {
+ *has_errors = true;
+ for mismatch in type_mismatches.values_mut() {
+ mismatch.expected = table.resolve_completely(mismatch.expected);
+ mismatch.actual = table.resolve_completely(mismatch.actual);
+ }
+ type_mismatches.shrink_to_fit();
}
- type_mismatches.shrink_to_fit();
diagnostics.retain_mut(|diagnostic| {
use InferenceDiagnostic::*;
match diagnostic {
@@ -1520,7 +1534,10 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
) -> Result<(), ()> {
let result = self.demand_eqtype_fixme_no_diag(expected, actual);
if result.is_err() {
- self.result.type_mismatches.insert(id, TypeMismatch { expected, actual });
+ self.result
+ .type_mismatches
+ .get_or_insert_default()
+ .insert(id, TypeMismatch { expected, actual });
}
result
}
diff --git a/crates/hir-ty/src/infer/coerce.rs b/crates/hir-ty/src/infer/coerce.rs
index 4acf964bbc..add8fc9bfc 100644
--- a/crates/hir-ty/src/infer/coerce.rs
+++ b/crates/hir-ty/src/infer/coerce.rs
@@ -1514,7 +1514,7 @@ impl<'db, 'exprs> CoerceMany<'db, 'exprs> {
self.final_ty = Some(icx.types.error);
- icx.result.type_mismatches.insert(
+ icx.result.type_mismatches.get_or_insert_default().insert(
expression.into(),
if label_expression_as_expected {
TypeMismatch { expected: found, actual: expected }
diff --git a/crates/hir-ty/src/infer/diagnostics.rs b/crates/hir-ty/src/infer/diagnostics.rs
index 844eb02ab0..0eb7a2f474 100644
--- a/crates/hir-ty/src/infer/diagnostics.rs
+++ b/crates/hir-ty/src/infer/diagnostics.rs
@@ -11,6 +11,7 @@ use hir_def::expr_store::ExpressionStore;
use hir_def::expr_store::path::Path;
use hir_def::{hir::ExprOrPatId, resolver::Resolver};
use la_arena::{Idx, RawIdx};
+use thin_vec::ThinVec;
use crate::{
InferenceDiagnostic, InferenceTyDiagnosticSource, TyLoweringDiagnostic,
@@ -24,7 +25,7 @@ use crate::{
// to our resolver and so we cannot have mutable reference, but we really want to have
// ability to dispatch diagnostics during this work otherwise the code becomes a complete mess.
#[derive(Debug, Default, Clone)]
-pub(super) struct Diagnostics<'db>(RefCell<Vec<InferenceDiagnostic<'db>>>);
+pub(super) struct Diagnostics<'db>(RefCell<ThinVec<InferenceDiagnostic<'db>>>);
impl<'db> Diagnostics<'db> {
pub(super) fn push(&self, diagnostic: InferenceDiagnostic<'db>) {
@@ -41,7 +42,7 @@ impl<'db> Diagnostics<'db> {
);
}
- pub(super) fn finish(self) -> Vec<InferenceDiagnostic<'db>> {
+ pub(super) fn finish(self) -> ThinVec<InferenceDiagnostic<'db>> {
self.0.into_inner()
}
}
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index 7487660a76..d3d6d1ed61 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/crates/hir-ty/src/infer/expr.rs
@@ -71,6 +71,7 @@ impl<'db> InferenceContext<'_, 'db> {
if !could_unify {
self.result
.type_mismatches
+ .get_or_insert_default()
.insert(tgt_expr.into(), TypeMismatch { expected: expected_ty, actual: ty });
}
}
@@ -100,6 +101,7 @@ impl<'db> InferenceContext<'_, 'db> {
Err(_) => {
self.result
.type_mismatches
+ .get_or_insert_default()
.insert(expr.into(), TypeMismatch { expected: target, actual: ty });
target
}
@@ -293,6 +295,7 @@ impl<'db> InferenceContext<'_, 'db> {
if !could_unify {
self.result
.type_mismatches
+ .get_or_insert_default()
.insert(expr.into(), TypeMismatch { expected: expected_ty, actual: ty });
}
}
@@ -1188,6 +1191,7 @@ impl<'db> InferenceContext<'_, 'db> {
Err(_) => {
this.result
.type_mismatches
+ .get_or_insert_default()
.insert(tgt_expr.into(), TypeMismatch { expected: target, actual: ty });
target
}
@@ -1556,7 +1560,7 @@ impl<'db> InferenceContext<'_, 'db> {
)
.is_err()
{
- this.result.type_mismatches.insert(
+ this.result.type_mismatches.get_or_insert_default().insert(
expr.into(),
TypeMismatch { expected: t, actual: this.types.unit },
);
@@ -2130,6 +2134,7 @@ impl<'db> InferenceContext<'_, 'db> {
// Don't report type mismatches if there is a mismatch in args count.
self.result
.type_mismatches
+ .get_or_insert_default()
.insert((*arg).into(), TypeMismatch { expected, actual: found });
}
}
diff --git a/crates/hir-ty/src/infer/pat.rs b/crates/hir-ty/src/infer/pat.rs
index ece2bdc4fd..a02e280ac6 100644
--- a/crates/hir-ty/src/infer/pat.rs
+++ b/crates/hir-ty/src/infer/pat.rs
@@ -331,7 +331,7 @@ impl<'db> InferenceContext<'_, 'db> {
return self.pat_ty_after_adjustment(pat);
}
Err(_) => {
- self.result.type_mismatches.insert(
+ self.result.type_mismatches.get_or_insert_default().insert(
pat.into(),
TypeMismatch { expected, actual: ty_inserted_vars },
);
@@ -415,6 +415,7 @@ impl<'db> InferenceContext<'_, 'db> {
Err(_) => {
self.result
.type_mismatches
+ .get_or_insert_default()
.insert(pat.into(), TypeMismatch { expected, actual: lhs_ty });
// `rhs_ty` is returned so no further type mismatches are
// reported because of this mismatch.
@@ -431,7 +432,10 @@ impl<'db> InferenceContext<'_, 'db> {
let ty = self.insert_type_vars_shallow(ty);
// FIXME: This never check is odd, but required with out we do inference right now
if !expected.is_never() && !self.unify(ty, expected) {
- self.result.type_mismatches.insert(pat.into(), TypeMismatch { expected, actual: ty });
+ self.result
+ .type_mismatches
+ .get_or_insert_default()
+ .insert(pat.into(), TypeMismatch { expected, actual: ty });
}
self.write_pat_ty(pat, ty);
self.pat_ty_after_adjustment(pat)
diff --git a/crates/hir-ty/src/method_resolution/confirm.rs b/crates/hir-ty/src/method_resolution/confirm.rs
index 9e8791edde..9017c2f877 100644
--- a/crates/hir-ty/src/method_resolution/confirm.rs
+++ b/crates/hir-ty/src/method_resolution/confirm.rs
@@ -481,7 +481,7 @@ impl<'a, 'b, 'db> ConfirmContext<'a, 'b, 'db> {
}
Err(_) => {
if self.ctx.unstable_features.arbitrary_self_types {
- self.ctx.result.type_mismatches.insert(
+ self.ctx.result.type_mismatches.get_or_insert_default().insert(
self.expr.into(),
TypeMismatch { expected: method_self_ty, actual: self_ty },
);