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.rs337
1 files changed, 161 insertions, 176 deletions
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index d6682c0cf2..bd5fffc4cc 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -28,7 +28,7 @@ mod path;
mod place_op;
pub(crate) mod unify;
-use std::{cell::OnceCell, convert::identity, iter, ops::Index};
+use std::{cell::OnceCell, convert::identity, iter};
use base_db::Crate;
use either::Either;
@@ -47,14 +47,12 @@ use hir_expand::{mod_path::ModPath, name::Name};
use indexmap::IndexSet;
use intern::sym;
use la_arena::ArenaMap;
-use macros::{TypeFoldable, TypeVisitable};
use rustc_ast_ir::Mutability;
use rustc_hash::{FxHashMap, FxHashSet};
use rustc_type_ir::{
AliasTyKind, TypeFoldable,
- inherent::{AdtDef, IntoKind, Region as _, SliceLike, Ty as _},
+ inherent::{AdtDef, IntoKind, Region as _, Ty as _},
};
-use salsa::Update;
use span::Edition;
use stdx::never;
use thin_vec::ThinVec;
@@ -74,8 +72,8 @@ use crate::{
method_resolution::{CandidateId, MethodResolutionUnstableFeatures},
mir::MirSpan,
next_solver::{
- AliasTy, Const, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs, Region, Ty, TyKind,
- Tys,
+ AliasTy, Const, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs, Region,
+ StoredGenericArgs, StoredTy, StoredTys, Ty, TyKind, Tys,
abi::Safety,
infer::{InferCtxt, traits::ObligationCause},
},
@@ -95,7 +93,7 @@ use cast::{CastCheck, CastError};
pub(crate) use closure::analysis::{CaptureKind, CapturedItem, CapturedItemWithoutTy};
/// The entry point of type inference.
-fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> InferenceResult<'_> {
+fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> InferenceResult {
let _p = tracing::info_span!("infer_query").entered();
let resolver = def.resolver(db);
let body = db.body(def);
@@ -162,7 +160,7 @@ fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> InferenceResult<'_>
ctx.resolve_all()
}
-fn infer_cycle_result(db: &dyn HirDatabase, _: salsa::Id, _: DefWithBodyId) -> InferenceResult<'_> {
+fn infer_cycle_result(db: &dyn HirDatabase, _: salsa::Id, _: DefWithBodyId) -> InferenceResult {
InferenceResult {
has_errors: true,
..InferenceResult::new(Ty::new_error(DbInterner::new_no_crate(db), ErrorGuaranteed))
@@ -196,8 +194,8 @@ pub enum InferenceTyDiagnosticSource {
Signature,
}
-#[derive(Debug, PartialEq, Eq, Clone, Update)]
-pub enum InferenceDiagnostic<'db> {
+#[derive(Debug, PartialEq, Eq, Clone)]
+pub enum InferenceDiagnostic {
NoSuchField {
field: ExprOrPatId,
private: Option<LocalFieldId>,
@@ -213,16 +211,16 @@ pub enum InferenceDiagnostic<'db> {
},
UnresolvedField {
expr: ExprId,
- receiver: Ty<'db>,
+ receiver: StoredTy,
name: Name,
method_with_same_name_exists: bool,
},
UnresolvedMethodCall {
expr: ExprId,
- receiver: Ty<'db>,
+ receiver: StoredTy,
name: Name,
/// Contains the type the field resolves to
- field_with_same_name: Option<Ty<'db>>,
+ field_with_same_name: Option<StoredTy>,
assoc_func_with_same_name: Option<FunctionId>,
},
UnresolvedAssocItem {
@@ -249,21 +247,21 @@ pub enum InferenceDiagnostic<'db> {
},
ExpectedFunction {
call_expr: ExprId,
- found: Ty<'db>,
+ found: StoredTy,
},
TypedHole {
expr: ExprId,
- expected: Ty<'db>,
+ expected: StoredTy,
},
CastToUnsized {
expr: ExprId,
- cast_ty: Ty<'db>,
+ cast_ty: StoredTy,
},
InvalidCast {
expr: ExprId,
error: CastError,
- expr_ty: Ty<'db>,
- cast_ty: Ty<'db>,
+ expr_ty: StoredTy,
+ cast_ty: StoredTy,
},
TyDiagnostic {
source: InferenceTyDiagnosticSource,
@@ -290,10 +288,10 @@ pub enum InferenceDiagnostic<'db> {
}
/// A mismatch between an expected and an inferred type.
-#[derive(Clone, PartialEq, Eq, Debug, Hash, Update)]
-pub struct TypeMismatch<'db> {
- pub expected: Ty<'db>,
- pub actual: Ty<'db>,
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
+pub struct TypeMismatch {
+ pub expected: StoredTy,
+ pub actual: StoredTy,
}
/// Represents coercing a value to a different type of value.
@@ -336,20 +334,23 @@ pub struct TypeMismatch<'db> {
/// At some point, of course, `Box` should move out of the compiler, in which
/// case this is analogous to transforming a struct. E.g., Box<[i32; 4]> ->
/// Box<[i32]> is an `Adjust::Unsize` with the target `Box<[i32]>`.
-#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeVisitable, TypeFoldable, Update)]
-pub struct Adjustment<'db> {
- #[type_visitable(ignore)]
- #[type_foldable(identity)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+pub struct Adjustment {
pub kind: Adjust,
- pub target: Ty<'db>,
+ pub target: StoredTy,
}
-impl<'db> Adjustment<'db> {
- pub fn borrow(interner: DbInterner<'db>, m: Mutability, ty: Ty<'db>, lt: Region<'db>) -> Self {
+impl Adjustment {
+ pub fn borrow<'db>(
+ interner: DbInterner<'db>,
+ m: Mutability,
+ ty: Ty<'db>,
+ lt: Region<'db>,
+ ) -> Self {
let ty = Ty::new_ref(interner, lt, ty, m);
Adjustment {
kind: Adjust::Borrow(AutoBorrow::Ref(AutoBorrowMutability::new(m, AllowTwoPhase::No))),
- target: ty,
+ target: ty.store(),
}
}
}
@@ -473,56 +474,47 @@ pub enum PointerCast {
/// When you add a field that stores types (including `Substitution` and the like), don't forget
/// `resolve_completely()`'ing them in `InferenceContext::resolve_all()`. Inference variables must
/// not appear in the final inference result.
-#[derive(Clone, PartialEq, Eq, Debug, Update)]
-pub struct InferenceResult<'db> {
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct InferenceResult {
/// For each method call expr, records the function it resolves to.
- #[update(unsafe(with(crate::utils::unsafe_update_eq /* expr id is technically update */)))]
- method_resolutions: FxHashMap<ExprId, (FunctionId, GenericArgs<'db>)>,
+ method_resolutions: FxHashMap<ExprId, (FunctionId, StoredGenericArgs)>,
/// For each field access expr, records the field it resolves to.
field_resolutions: FxHashMap<ExprId, Either<FieldId, TupleFieldId>>,
/// For each struct literal or pattern, records the variant it resolves to.
variant_resolutions: FxHashMap<ExprOrPatId, VariantId>,
/// For each associated item record what it resolves to
- assoc_resolutions: FxHashMap<ExprOrPatId, (CandidateId, GenericArgs<'db>)>,
+ assoc_resolutions: FxHashMap<ExprOrPatId, (CandidateId, StoredGenericArgs)>,
/// Whenever a tuple field expression access a tuple field, we allocate a tuple id in
/// [`InferenceContext`] and store the tuples substitution there. This map is the reverse of
/// that which allows us to resolve a [`TupleFieldId`]s type.
- #[update(unsafe(with(crate::utils::unsafe_update_eq /* thinvec is technically update */)))]
- tuple_field_access_types: ThinVec<Tys<'db>>,
+ tuple_field_access_types: ThinVec<StoredTys>,
- #[update(unsafe(with(crate::utils::unsafe_update_eq /* expr id is technically update */)))]
- pub(crate) type_of_expr: ArenaMap<ExprId, Ty<'db>>,
+ pub(crate) type_of_expr: ArenaMap<ExprId, StoredTy>,
/// For each pattern record the type it resolves to.
///
/// **Note**: When a pattern type is resolved it may still contain
/// unresolved or missing subpatterns or subpatterns of mismatched types.
- #[update(unsafe(with(crate::utils::unsafe_update_eq /* pat id is technically update */)))]
- pub(crate) type_of_pat: ArenaMap<PatId, Ty<'db>>,
- #[update(unsafe(with(crate::utils::unsafe_update_eq /* binding id is technically update */)))]
- pub(crate) type_of_binding: ArenaMap<BindingId, Ty<'db>>,
- #[update(unsafe(with(crate::utils::unsafe_update_eq /* type ref id is technically update */)))]
- pub(crate) type_of_type_placeholder: FxHashMap<TypeRefId, Ty<'db>>,
- pub(crate) type_of_opaque: FxHashMap<InternedOpaqueTyId, Ty<'db>>,
-
- pub(crate) type_mismatches: Option<Box<FxHashMap<ExprOrPatId, TypeMismatch<'db>>>>,
+ pub(crate) type_of_pat: ArenaMap<PatId, StoredTy>,
+ pub(crate) type_of_binding: ArenaMap<BindingId, StoredTy>,
+ 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`.
// Which will then mark this field.
pub(crate) has_errors: bool,
/// During inference this field is empty and [`InferenceContext::diagnostics`] is filled instead.
- #[update(unsafe(with(crate::utils::unsafe_update_eq /* thinvec is technically update */)))]
- diagnostics: ThinVec<InferenceDiagnostic<'db>>,
+ diagnostics: ThinVec<InferenceDiagnostic>,
/// Interned `Error` type to return references to.
// FIXME: Remove this.
- error_ty: Ty<'db>,
+ error_ty: StoredTy,
- #[update(unsafe(with(crate::utils::unsafe_update_eq /* expr id is technically update */)))]
- pub(crate) expr_adjustments: FxHashMap<ExprId, Box<[Adjustment<'db>]>>,
+ pub(crate) expr_adjustments: FxHashMap<ExprId, Box<[Adjustment]>>,
/// Stores the types which were implicitly dereferenced in pattern binding modes.
- #[update(unsafe(with(crate::utils::unsafe_update_eq /* pat id is technically update */)))]
- pub(crate) pat_adjustments: FxHashMap<PatId, Vec<Ty<'db>>>,
+ pub(crate) pat_adjustments: FxHashMap<PatId, Vec<StoredTy>>,
/// Stores the binding mode (`ref` in `let ref x = 2`) of bindings.
///
/// This one is tied to the `PatId` instead of `BindingId`, because in some rare cases, a binding in an
@@ -538,7 +530,7 @@ 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) closure_info: FxHashMap<InternedClosureId, (Vec<CapturedItem<'db>>, FnTrait)>,
+ pub(crate) closure_info: FxHashMap<InternedClosureId, (Vec<CapturedItem>, FnTrait)>,
// FIXME: remove this field
pub mutated_bindings_in_closure: FxHashSet<BindingId>,
@@ -546,15 +538,15 @@ pub struct InferenceResult<'db> {
}
#[salsa::tracked]
-impl<'db> InferenceResult<'db> {
- #[salsa::tracked(returns(ref), cycle_result = infer_cycle_result, unsafe(non_update_types))]
- pub fn for_body(db: &'db dyn HirDatabase, def: DefWithBodyId) -> InferenceResult<'db> {
+impl InferenceResult {
+ #[salsa::tracked(returns(ref), cycle_result = infer_cycle_result)]
+ pub fn for_body(db: &dyn HirDatabase, def: DefWithBodyId) -> InferenceResult {
infer_query(db, def)
}
}
-impl<'db> InferenceResult<'db> {
- fn new(error_ty: Ty<'db>) -> Self {
+impl InferenceResult {
+ fn new(error_ty: Ty<'_>) -> Self {
Self {
method_resolutions: Default::default(),
field_resolutions: Default::default(),
@@ -569,7 +561,7 @@ impl<'db> InferenceResult<'db> {
type_of_opaque: Default::default(),
type_mismatches: Default::default(),
has_errors: Default::default(),
- error_ty,
+ error_ty: error_ty.store(),
pat_adjustments: Default::default(),
binding_modes: Default::default(),
expr_adjustments: Default::default(),
@@ -579,8 +571,8 @@ impl<'db> InferenceResult<'db> {
}
}
- pub fn method_resolution(&self, expr: ExprId) -> Option<(FunctionId, GenericArgs<'db>)> {
- self.method_resolutions.get(&expr).copied()
+ pub fn method_resolution<'db>(&self, expr: ExprId) -> Option<(FunctionId, GenericArgs<'db>)> {
+ self.method_resolutions.get(&expr).map(|(func, args)| (*func, args.as_ref()))
}
pub fn field_resolution(&self, expr: ExprId) -> Option<Either<FieldId, TupleFieldId>> {
self.field_resolutions.get(&expr).copied()
@@ -597,16 +589,19 @@ impl<'db> InferenceResult<'db> {
ExprOrPatId::PatId(id) => self.variant_resolution_for_pat(id),
}
}
- pub fn assoc_resolutions_for_expr(
+ pub fn assoc_resolutions_for_expr<'db>(
&self,
id: ExprId,
) -> Option<(CandidateId, GenericArgs<'db>)> {
- self.assoc_resolutions.get(&id.into()).copied()
+ self.assoc_resolutions.get(&id.into()).map(|(assoc, args)| (*assoc, args.as_ref()))
}
- pub fn assoc_resolutions_for_pat(&self, id: PatId) -> Option<(CandidateId, GenericArgs<'db>)> {
- self.assoc_resolutions.get(&id.into()).copied()
+ pub fn assoc_resolutions_for_pat<'db>(
+ &self,
+ id: PatId,
+ ) -> Option<(CandidateId, GenericArgs<'db>)> {
+ self.assoc_resolutions.get(&id.into()).map(|(assoc, args)| (*assoc, args.as_ref()))
}
- pub fn assoc_resolutions_for_expr_or_pat(
+ pub fn assoc_resolutions_for_expr_or_pat<'db>(
&self,
id: ExprOrPatId,
) -> Option<(CandidateId, GenericArgs<'db>)> {
@@ -615,20 +610,20 @@ impl<'db> InferenceResult<'db> {
ExprOrPatId::PatId(id) => self.assoc_resolutions_for_pat(id),
}
}
- pub fn type_mismatch_for_expr(&self, expr: ExprId) -> Option<&TypeMismatch<'db>> {
+ pub fn type_mismatch_for_expr(&self, expr: ExprId) -> Option<&TypeMismatch> {
self.type_mismatches.as_deref()?.get(&expr.into())
}
- pub fn type_mismatch_for_pat(&self, pat: PatId) -> Option<&TypeMismatch<'db>> {
+ pub fn type_mismatch_for_pat(&self, pat: PatId) -> Option<&TypeMismatch> {
self.type_mismatches.as_deref()?.get(&pat.into())
}
- pub fn type_mismatches(&self) -> impl Iterator<Item = (ExprOrPatId, &TypeMismatch<'db>)> {
+ 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<'db>)> {
+ 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)),
@@ -636,22 +631,22 @@ impl<'db> InferenceResult<'db> {
},
)
}
- pub fn placeholder_types(&self) -> impl Iterator<Item = (TypeRefId, &Ty<'db>)> {
- self.type_of_type_placeholder.iter().map(|(&type_ref, ty)| (type_ref, ty))
+ 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()))
}
- pub fn type_of_type_placeholder(&self, type_ref: TypeRefId) -> Option<Ty<'db>> {
- self.type_of_type_placeholder.get(&type_ref).copied()
+ pub fn type_of_type_placeholder<'db>(&self, type_ref: TypeRefId) -> Option<Ty<'db>> {
+ self.type_of_type_placeholder.get(&type_ref).map(|ty| ty.as_ref())
}
- pub fn closure_info(&self, closure: InternedClosureId) -> &(Vec<CapturedItem<'db>>, FnTrait) {
+ pub fn closure_info(&self, closure: InternedClosureId) -> &(Vec<CapturedItem>, FnTrait) {
self.closure_info.get(&closure).unwrap()
}
- pub fn type_of_expr_or_pat(&self, id: ExprOrPatId) -> Option<Ty<'db>> {
+ pub fn type_of_expr_or_pat<'db>(&self, id: ExprOrPatId) -> Option<Ty<'db>> {
match id {
- ExprOrPatId::ExprId(id) => self.type_of_expr.get(id).copied(),
- ExprOrPatId::PatId(id) => self.type_of_pat.get(id).copied(),
+ ExprOrPatId::ExprId(id) => self.type_of_expr.get(id).map(|it| it.as_ref()),
+ ExprOrPatId::PatId(id) => self.type_of_pat.get(id).map(|it| it.as_ref()),
}
}
- pub fn type_of_expr_with_adjust(&self, id: ExprId) -> Option<Ty<'db>> {
+ pub fn type_of_expr_with_adjust<'db>(&self, id: ExprId) -> Option<Ty<'db>> {
match self.expr_adjustments.get(&id).and_then(|adjustments| {
adjustments.iter().rfind(|adj| {
// https://github.com/rust-lang/rust/blob/67819923ac8ea353aaa775303f4c3aacbf41d010/compiler/rustc_mir_build/src/thir/cx/expr.rs#L140
@@ -660,37 +655,37 @@ impl<'db> InferenceResult<'db> {
Adjustment {
kind: Adjust::NeverToAny,
target,
- } if target.is_never()
+ } if target.as_ref().is_never()
)
})
}) {
- Some(adjustment) => Some(adjustment.target),
- None => self.type_of_expr.get(id).copied(),
+ Some(adjustment) => Some(adjustment.target.as_ref()),
+ None => self.type_of_expr.get(id).map(|it| it.as_ref()),
}
}
- pub fn type_of_pat_with_adjust(&self, id: PatId) -> Option<Ty<'db>> {
+ pub fn type_of_pat_with_adjust<'db>(&self, id: PatId) -> Option<Ty<'db>> {
match self.pat_adjustments.get(&id).and_then(|adjustments| adjustments.last()) {
- Some(adjusted) => Some(*adjusted),
- None => self.type_of_pat.get(id).copied(),
+ Some(adjusted) => Some(adjusted.as_ref()),
+ None => self.type_of_pat.get(id).map(|it| it.as_ref()),
}
}
pub fn is_erroneous(&self) -> bool {
self.has_errors && self.type_of_expr.iter().count() == 0
}
- pub fn diagnostics(&self) -> &[InferenceDiagnostic<'db>] {
+ pub fn diagnostics(&self) -> &[InferenceDiagnostic] {
&self.diagnostics
}
- pub fn tuple_field_access_type(&self, id: TupleId) -> Tys<'db> {
- self.tuple_field_access_types[id.0 as usize]
+ pub fn tuple_field_access_type<'db>(&self, id: TupleId) -> Tys<'db> {
+ self.tuple_field_access_types[id.0 as usize].as_ref()
}
- pub fn pat_adjustment(&self, id: PatId) -> Option<&[Ty<'db>]> {
+ pub fn pat_adjustment(&self, id: PatId) -> Option<&[StoredTy]> {
self.pat_adjustments.get(&id).map(|it| &**it)
}
- pub fn expr_adjustment(&self, id: ExprId) -> Option<&[Adjustment<'db>]> {
+ pub fn expr_adjustment(&self, id: ExprId) -> Option<&[Adjustment]> {
self.expr_adjustments.get(&id).map(|it| &**it)
}
@@ -699,66 +694,47 @@ impl<'db> InferenceResult<'db> {
}
// This method is consumed by external tools to run rust-analyzer as a library. Don't remove, please.
- pub fn expression_types(&self) -> impl Iterator<Item = (ExprId, Ty<'db>)> {
- self.type_of_expr.iter().map(|(k, v)| (k, *v))
+ pub fn expression_types<'db>(&self) -> impl Iterator<Item = (ExprId, Ty<'db>)> {
+ self.type_of_expr.iter().map(|(k, v)| (k, v.as_ref()))
}
// This method is consumed by external tools to run rust-analyzer as a library. Don't remove, please.
- pub fn pattern_types(&self) -> impl Iterator<Item = (PatId, Ty<'db>)> {
- self.type_of_pat.iter().map(|(k, v)| (k, *v))
+ pub fn pattern_types<'db>(&self) -> impl Iterator<Item = (PatId, Ty<'db>)> {
+ self.type_of_pat.iter().map(|(k, v)| (k, v.as_ref()))
}
// This method is consumed by external tools to run rust-analyzer as a library. Don't remove, please.
- pub fn binding_types(&self) -> impl Iterator<Item = (BindingId, Ty<'db>)> {
- self.type_of_binding.iter().map(|(k, v)| (k, *v))
+ pub fn binding_types<'db>(&self) -> impl Iterator<Item = (BindingId, Ty<'db>)> {
+ self.type_of_binding.iter().map(|(k, v)| (k, v.as_ref()))
}
// This method is consumed by external tools to run rust-analyzer as a library. Don't remove, please.
- pub fn return_position_impl_trait_types(
- &self,
+ pub fn return_position_impl_trait_types<'db>(
+ &'db self,
db: &'db dyn HirDatabase,
- ) -> impl Iterator<Item = (ImplTraitIdx<'db>, Ty<'db>)> {
- self.type_of_opaque.iter().filter_map(move |(&id, &ty)| {
+ ) -> impl Iterator<Item = (ImplTraitIdx, Ty<'db>)> {
+ self.type_of_opaque.iter().filter_map(move |(&id, ty)| {
let ImplTraitId::ReturnTypeImplTrait(_, rpit_idx) = id.loc(db) else {
return None;
};
- Some((rpit_idx, ty))
+ Some((rpit_idx, ty.as_ref()))
})
}
-}
-impl<'db> Index<ExprId> for InferenceResult<'db> {
- type Output = Ty<'db>;
-
- fn index(&self, expr: ExprId) -> &Ty<'db> {
- self.type_of_expr.get(expr).unwrap_or(&self.error_ty)
+ pub fn expr_ty<'db>(&self, id: ExprId) -> Ty<'db> {
+ self.type_of_expr.get(id).map_or(self.error_ty.as_ref(), |it| it.as_ref())
}
-}
-
-impl<'db> Index<PatId> for InferenceResult<'db> {
- type Output = Ty<'db>;
- fn index(&self, pat: PatId) -> &Ty<'db> {
- self.type_of_pat.get(pat).unwrap_or(&self.error_ty)
+ pub fn pat_ty<'db>(&self, id: PatId) -> Ty<'db> {
+ self.type_of_pat.get(id).map_or(self.error_ty.as_ref(), |it| it.as_ref())
}
-}
-
-impl<'db> Index<ExprOrPatId> for InferenceResult<'db> {
- type Output = Ty<'db>;
- fn index(&self, id: ExprOrPatId) -> &Ty<'db> {
- match id {
- ExprOrPatId::ExprId(id) => &self[id],
- ExprOrPatId::PatId(id) => &self[id],
- }
+ pub fn expr_or_pat_ty<'db>(&self, id: ExprOrPatId) -> Ty<'db> {
+ self.type_of_expr_or_pat(id).unwrap_or(self.error_ty.as_ref())
}
-}
-impl<'db> Index<BindingId> for InferenceResult<'db> {
- type Output = Ty<'db>;
-
- fn index(&self, b: BindingId) -> &Ty<'db> {
- self.type_of_binding.get(b).unwrap_or(&self.error_ty)
+ pub fn binding_ty<'db>(&self, id: BindingId) -> Ty<'db> {
+ self.type_of_binding.get(id).map_or(self.error_ty.as_ref(), |it| it.as_ref())
}
}
@@ -826,7 +802,7 @@ impl<'db> InternedStandardTypes<'db> {
re_error: Region::error(interner),
re_erased: Region::new_erased(interner),
- empty_args: GenericArgs::new_from_iter(interner, []),
+ empty_args: GenericArgs::empty(interner),
}
}
}
@@ -848,7 +824,7 @@ pub(crate) struct InferenceContext<'body, 'db> {
pub(crate) lang_items: &'db LangItems,
/// The traits in scope, disregarding block modules. This is used for caching purposes.
traits_in_scope: FxHashSet<TraitId>,
- pub(crate) result: InferenceResult<'db>,
+ pub(crate) result: InferenceResult,
tuple_field_accesses_rev:
IndexSet<Tys<'db>, std::hash::BuildHasherDefault<rustc_hash::FxHasher>>,
/// The return type of the function being inferred, the closure or async block if we're
@@ -873,7 +849,7 @@ pub(crate) struct InferenceContext<'body, 'db> {
deferred_cast_checks: Vec<CastCheck<'db>>,
// fields related to closure capture
- current_captures: Vec<CapturedItemWithoutTy<'db>>,
+ current_captures: Vec<CapturedItemWithoutTy>,
/// A stack that has an entry for each projection in the current capture.
///
/// For example, in `a.b.c`, we capture the spans of `a`, `a.b`, and `a.b.c`.
@@ -886,7 +862,7 @@ pub(crate) struct InferenceContext<'body, 'db> {
closure_dependencies: FxHashMap<InternedClosureId, Vec<InternedClosureId>>,
deferred_closures: FxHashMap<InternedClosureId, Vec<(Ty<'db>, Ty<'db>, Vec<Ty<'db>>, ExprId)>>,
- diagnostics: Diagnostics<'db>,
+ diagnostics: Diagnostics,
}
#[derive(Clone, Debug)]
@@ -1008,7 +984,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
/// Clones `self` and calls `resolve_all()` on it.
// FIXME: Remove this.
- pub(crate) fn fixme_resolve_all_clone(&self) -> InferenceResult<'db> {
+ pub(crate) fn fixme_resolve_all_clone(&self) -> InferenceResult {
let mut ctx = self.clone();
ctx.type_inference_fallback();
@@ -1032,7 +1008,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
// `InferenceResult` in the middle of inference. See the fixme comment in `consteval::eval_to_const`. If you
// used this function for another workaround, mention it here. If you really need this function and believe that
// there is no problem in it being `pub(crate)`, remove this comment.
- fn resolve_all(self) -> InferenceResult<'db> {
+ fn resolve_all(self) -> InferenceResult {
let InferenceContext {
mut table, mut result, tuple_field_accesses_rev, diagnostics, ..
} = self;
@@ -1066,23 +1042,23 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
} = &mut result;
for ty in type_of_expr.values_mut() {
- *ty = table.resolve_completely(*ty);
- *has_errors = *has_errors || ty.references_non_lt_error();
+ *ty = table.resolve_completely(ty.as_ref()).store();
+ *has_errors = *has_errors || ty.as_ref().references_non_lt_error();
}
type_of_expr.shrink_to_fit();
for ty in type_of_pat.values_mut() {
- *ty = table.resolve_completely(*ty);
- *has_errors = *has_errors || ty.references_non_lt_error();
+ *ty = table.resolve_completely(ty.as_ref()).store();
+ *has_errors = *has_errors || ty.as_ref().references_non_lt_error();
}
type_of_pat.shrink_to_fit();
for ty in type_of_binding.values_mut() {
- *ty = table.resolve_completely(*ty);
- *has_errors = *has_errors || ty.references_non_lt_error();
+ *ty = table.resolve_completely(ty.as_ref()).store();
+ *has_errors = *has_errors || ty.as_ref().references_non_lt_error();
}
type_of_binding.shrink_to_fit();
for ty in type_of_type_placeholder.values_mut() {
- *ty = table.resolve_completely(*ty);
- *has_errors = *has_errors || ty.references_non_lt_error();
+ *ty = table.resolve_completely(ty.as_ref()).store();
+ *has_errors = *has_errors || ty.as_ref().references_non_lt_error();
}
type_of_type_placeholder.shrink_to_fit();
type_of_opaque.shrink_to_fit();
@@ -1090,8 +1066,8 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
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);
+ mismatch.expected = table.resolve_completely(mismatch.expected.as_ref()).store();
+ mismatch.actual = table.resolve_completely(mismatch.actual.as_ref()).store();
}
type_mismatches.shrink_to_fit();
}
@@ -1101,23 +1077,23 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
ExpectedFunction { found: ty, .. }
| UnresolvedField { receiver: ty, .. }
| UnresolvedMethodCall { receiver: ty, .. } => {
- *ty = table.resolve_completely(*ty);
+ *ty = table.resolve_completely(ty.as_ref()).store();
// FIXME: Remove this when we are on par with rustc in terms of inference
- if ty.references_non_lt_error() {
+ if ty.as_ref().references_non_lt_error() {
return false;
}
if let UnresolvedMethodCall { field_with_same_name, .. } = diagnostic
&& let Some(ty) = field_with_same_name
{
- *ty = table.resolve_completely(*ty);
- if ty.references_non_lt_error() {
+ *ty = table.resolve_completely(ty.as_ref()).store();
+ if ty.as_ref().references_non_lt_error() {
*field_with_same_name = None;
}
}
}
TypedHole { expected: ty, .. } => {
- *ty = table.resolve_completely(*ty);
+ *ty = table.resolve_completely(ty.as_ref()).store();
}
_ => (),
}
@@ -1125,30 +1101,33 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
});
diagnostics.shrink_to_fit();
for (_, subst) in method_resolutions.values_mut() {
- *subst = table.resolve_completely(*subst);
- *has_errors = *has_errors || subst.types().any(|ty| ty.references_non_lt_error());
+ *subst = table.resolve_completely(subst.as_ref()).store();
+ *has_errors =
+ *has_errors || subst.as_ref().types().any(|ty| ty.references_non_lt_error());
}
method_resolutions.shrink_to_fit();
for (_, subst) in assoc_resolutions.values_mut() {
- *subst = table.resolve_completely(*subst);
- *has_errors = *has_errors || subst.types().any(|ty| ty.references_non_lt_error());
+ *subst = table.resolve_completely(subst.as_ref()).store();
+ *has_errors =
+ *has_errors || subst.as_ref().types().any(|ty| ty.references_non_lt_error());
}
assoc_resolutions.shrink_to_fit();
for adjustment in expr_adjustments.values_mut().flatten() {
- adjustment.target = table.resolve_completely(adjustment.target);
- *has_errors = *has_errors || adjustment.target.references_non_lt_error();
+ adjustment.target = table.resolve_completely(adjustment.target.as_ref()).store();
+ *has_errors = *has_errors || adjustment.target.as_ref().references_non_lt_error();
}
expr_adjustments.shrink_to_fit();
for adjustment in pat_adjustments.values_mut().flatten() {
- *adjustment = table.resolve_completely(*adjustment);
- *has_errors = *has_errors || adjustment.references_non_lt_error();
+ *adjustment = table.resolve_completely(adjustment.as_ref()).store();
+ *has_errors = *has_errors || adjustment.as_ref().references_non_lt_error();
}
pat_adjustments.shrink_to_fit();
result.tuple_field_access_types = tuple_field_accesses_rev
.into_iter()
- .map(|subst| table.resolve_completely(subst))
+ .map(|subst| table.resolve_completely(subst).store())
.inspect(|subst| {
- *has_errors = *has_errors || subst.iter().any(|ty| ty.references_non_lt_error());
+ *has_errors =
+ *has_errors || subst.as_ref().iter().any(|ty| ty.references_non_lt_error());
})
.collect();
result.tuple_field_access_types.shrink_to_fit();
@@ -1262,10 +1241,10 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
}
fn write_expr_ty(&mut self, expr: ExprId, ty: Ty<'db>) {
- self.result.type_of_expr.insert(expr, ty);
+ self.result.type_of_expr.insert(expr, ty.store());
}
- pub(crate) fn write_expr_adj(&mut self, expr: ExprId, adjustments: Box<[Adjustment<'db>]>) {
+ pub(crate) fn write_expr_adj(&mut self, expr: ExprId, adjustments: Box<[Adjustment]>) {
if adjustments.is_empty() {
return;
}
@@ -1278,7 +1257,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
) => {
// NeverToAny coercion can target any type, so instead of adding a new
// adjustment on top we can change the target.
- *target = *new_target;
+ *target = new_target.clone();
}
_ => {
*entry.get_mut() = adjustments;
@@ -1291,7 +1270,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
}
}
- fn write_pat_adj(&mut self, pat: PatId, adjustments: Box<[Ty<'db>]>) {
+ fn write_pat_adj(&mut self, pat: PatId, adjustments: Box<[StoredTy]>) {
if adjustments.is_empty() {
return;
}
@@ -1304,7 +1283,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
func: FunctionId,
subst: GenericArgs<'db>,
) {
- self.result.method_resolutions.insert(expr, (func, subst));
+ self.result.method_resolutions.insert(expr, (func, subst.store()));
}
fn write_variant_resolution(&mut self, id: ExprOrPatId, variant: VariantId) {
@@ -1317,22 +1296,22 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
item: CandidateId,
subs: GenericArgs<'db>,
) {
- self.result.assoc_resolutions.insert(id, (item, subs));
+ self.result.assoc_resolutions.insert(id, (item, subs.store()));
}
fn write_pat_ty(&mut self, pat: PatId, ty: Ty<'db>) {
- self.result.type_of_pat.insert(pat, ty);
+ self.result.type_of_pat.insert(pat, ty.store());
}
fn write_type_placeholder_ty(&mut self, type_ref: TypeRefId, ty: Ty<'db>) {
- self.result.type_of_type_placeholder.insert(type_ref, ty);
+ self.result.type_of_type_placeholder.insert(type_ref, ty.store());
}
fn write_binding_ty(&mut self, id: BindingId, ty: Ty<'db>) {
- self.result.type_of_binding.insert(id, ty);
+ self.result.type_of_binding.insert(id, ty.store());
}
- pub(crate) fn push_diagnostic(&self, diagnostic: InferenceDiagnostic<'db>) {
+ pub(crate) fn push_diagnostic(&self, diagnostic: InferenceDiagnostic) {
self.diagnostics.push(diagnostic);
}
@@ -1486,7 +1465,13 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
match ty.kind() {
TyKind::Adt(adt_def, substs) => match adt_def.def_id().0 {
AdtId::StructId(struct_id) => {
- match self.db.field_types(struct_id.into()).values().next_back().copied() {
+ match self
+ .db
+ .field_types(struct_id.into())
+ .values()
+ .next_back()
+ .map(|it| it.get())
+ {
Some(field) => {
ty = field.instantiate(self.interner(), substs);
}
@@ -1547,7 +1532,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
self.result
.type_mismatches
.get_or_insert_default()
- .insert(id, TypeMismatch { expected, actual });
+ .insert(id, TypeMismatch { expected: expected.store(), actual: actual.store() });
}
result
}
@@ -1592,7 +1577,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
}
fn expr_ty(&self, expr: ExprId) -> Ty<'db> {
- self.result[expr]
+ self.result.expr_ty(expr)
}
fn expr_ty_after_adjustments(&self, e: ExprId) -> Ty<'db> {
@@ -1600,7 +1585,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
if let Some(it) = self.result.expr_adjustments.get(&e)
&& let Some(it) = it.last()
{
- ty = Some(it.target);
+ ty = Some(it.target.as_ref());
}
ty.unwrap_or_else(|| self.expr_ty(e))
}