mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-29 20:46:07 +03:00
Merge pull request #21167 from Veykril/push-xksxokxxwyqw
perf: Shrink `InferenceResult` by ~40 bytes
This commit is contained in:
@@ -905,6 +905,7 @@ dependencies = [
|
||||
"syntax",
|
||||
"test-fixture",
|
||||
"test-utils",
|
||||
"thin-vec",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"tracing-tree",
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
};
|
||||
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.
|
||||
///
|
||||
@@ -498,17 +498,23 @@ pub struct InferenceResult<'db> {
|
||||
/// unresolved or missing subpatterns or subpatterns of mismatched types.
|
||||
pub(crate) type_of_pat: ArenaMap<PatId, Ty<'db>>,
|
||||
pub(crate) type_of_binding: ArenaMap<BindingId, Ty<'db>>,
|
||||
pub(crate) type_of_type_placeholder: ArenaMap<TypeRefId, Ty<'db>>,
|
||||
pub(crate) type_of_type_placeholder: FxHashMap<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,25 +602,31 @@ pub fn assoc_resolutions_for_expr_or_pat(
|
||||
}
|
||||
}
|
||||
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()
|
||||
self.type_of_type_placeholder.iter().map(|(&type_ref, ty)| (type_ref, ty))
|
||||
}
|
||||
pub fn type_of_type_placeholder(&self, type_ref: TypeRefId) -> Option<Ty<'db>> {
|
||||
self.type_of_type_placeholder.get(type_ref).copied()
|
||||
self.type_of_type_placeholder.get(&type_ref).copied()
|
||||
}
|
||||
pub fn closure_info(&self, closure: InternedClosureId) -> &(Vec<CapturedItem<'db>>, FnTrait) {
|
||||
self.closure_info.get(&closure).unwrap()
|
||||
@@ -1063,13 +1076,14 @@ fn resolve_all(self) -> InferenceResult<'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 @@ fn demand_eqtype(
|
||||
) -> 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
|
||||
}
|
||||
|
||||
@@ -1514,7 +1514,7 @@ pub(crate) fn coerce_inner(
|
||||
|
||||
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 }
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
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 @@
|
||||
// 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 @@ fn push_ty_diagnostics(
|
||||
);
|
||||
}
|
||||
|
||||
pub(super) fn finish(self) -> Vec<InferenceDiagnostic<'db>> {
|
||||
pub(super) fn finish(self) -> ThinVec<InferenceDiagnostic<'db>> {
|
||||
self.0.into_inner()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,6 +71,7 @@ pub(crate) fn infer_expr(
|
||||
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 @@ pub(super) fn infer_expr_coerce(
|
||||
Err(_) => {
|
||||
self.result
|
||||
.type_mismatches
|
||||
.get_or_insert_default()
|
||||
.insert(expr.into(), TypeMismatch { expected: target, actual: ty });
|
||||
target
|
||||
}
|
||||
@@ -293,6 +295,7 @@ fn infer_expr_coerce_never(
|
||||
if !could_unify {
|
||||
self.result
|
||||
.type_mismatches
|
||||
.get_or_insert_default()
|
||||
.insert(expr.into(), TypeMismatch { expected: expected_ty, actual: ty });
|
||||
}
|
||||
}
|
||||
@@ -1188,6 +1191,7 @@ fn infer_async_block(
|
||||
Err(_) => {
|
||||
this.result
|
||||
.type_mismatches
|
||||
.get_or_insert_default()
|
||||
.insert(tgt_expr.into(), TypeMismatch { expected: target, actual: ty });
|
||||
target
|
||||
}
|
||||
@@ -1556,7 +1560,7 @@ fn infer_block(
|
||||
)
|
||||
.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 @@ pub(in super::super) fn check_call_arguments(
|
||||
// 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 });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -331,7 +331,7 @@ fn infer_pat(
|
||||
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 @@ fn infer_pat(
|
||||
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 @@ fn infer_pat(
|
||||
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)
|
||||
|
||||
@@ -481,7 +481,7 @@ fn unify_receivers(
|
||||
}
|
||||
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 },
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user