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.rs458
1 files changed, 193 insertions, 265 deletions
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index 70868e4b95..d527a4ae29 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, Ty as _},
};
-use salsa::Update;
use span::Edition;
use stdx::never;
use thin_vec::ThinVec;
@@ -74,10 +72,10 @@ 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},
+ infer::{InferCtxt, ObligationInspector, traits::ObligationCause},
},
traits::FnTrait,
utils::TargetFeatureIsSafeInTarget,
@@ -95,12 +93,24 @@ 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 {
+ infer_query_with_inspect(db, def, None)
+}
+
+pub fn infer_query_with_inspect<'db>(
+ db: &'db dyn HirDatabase,
+ def: DefWithBodyId,
+ inspect: Option<ObligationInspector<'db>>,
+) -> InferenceResult {
let _p = tracing::info_span!("infer_query").entered();
let resolver = def.resolver(db);
let body = db.body(def);
let mut ctx = InferenceContext::new(db, def, &body, resolver);
+ if let Some(inspect) = inspect {
+ ctx.table.infer_ctxt.attach_obligation_inspector(inspect);
+ }
+
match def {
DefWithBodyId::FunctionId(f) => {
ctx.collect_fn(f);
@@ -110,23 +120,23 @@ fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> InferenceResult<'_>
DefWithBodyId::VariantId(v) => {
ctx.return_ty = match EnumSignature::variant_body_type(db, v.lookup(db).parent) {
hir_def::layout::IntegerType::Pointer(signed) => match signed {
- true => ctx.types.isize,
- false => ctx.types.usize,
+ true => ctx.types.types.isize,
+ false => ctx.types.types.usize,
},
hir_def::layout::IntegerType::Fixed(size, signed) => match signed {
true => match size {
- Integer::I8 => ctx.types.i8,
- Integer::I16 => ctx.types.i16,
- Integer::I32 => ctx.types.i32,
- Integer::I64 => ctx.types.i64,
- Integer::I128 => ctx.types.i128,
+ Integer::I8 => ctx.types.types.i8,
+ Integer::I16 => ctx.types.types.i16,
+ Integer::I32 => ctx.types.types.i32,
+ Integer::I64 => ctx.types.types.i64,
+ Integer::I128 => ctx.types.types.i128,
},
false => match size {
- Integer::I8 => ctx.types.u8,
- Integer::I16 => ctx.types.u16,
- Integer::I32 => ctx.types.u32,
- Integer::I64 => ctx.types.u64,
- Integer::I128 => ctx.types.u128,
+ Integer::I8 => ctx.types.types.u8,
+ Integer::I16 => ctx.types.types.u16,
+ Integer::I32 => ctx.types.types.u32,
+ Integer::I64 => ctx.types.types.u64,
+ Integer::I128 => ctx.types.types.u128,
},
},
};
@@ -162,7 +172,7 @@ fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> InferenceResult<'_>
ctx.resolve_all()
}
-fn infer_cycle_result(db: &dyn HirDatabase, _: 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 +206,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 +223,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 +259,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 +300,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 +346,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 +486,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 +542,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 +550,15 @@ pub struct InferenceResult<'db> {
}
#[salsa::tracked]
-impl<'db> InferenceResult<'db> {
+impl InferenceResult {
#[salsa::tracked(returns(ref), cycle_result = infer_cycle_result)]
- pub fn for_body(db: &'db dyn HirDatabase, def: DefWithBodyId) -> InferenceResult<'db> {
+ 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 +573,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 +583,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 +601,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 +622,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 +643,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 +667,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,135 +706,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)
- }
-}
-
-#[derive(Debug, Clone)]
-struct InternedStandardTypes<'db> {
- unit: Ty<'db>,
- never: Ty<'db>,
- char: Ty<'db>,
- bool: Ty<'db>,
- i8: Ty<'db>,
- i16: Ty<'db>,
- i32: Ty<'db>,
- i64: Ty<'db>,
- i128: Ty<'db>,
- isize: Ty<'db>,
- u8: Ty<'db>,
- u16: Ty<'db>,
- u32: Ty<'db>,
- u64: Ty<'db>,
- u128: Ty<'db>,
- usize: Ty<'db>,
- f16: Ty<'db>,
- f32: Ty<'db>,
- f64: Ty<'db>,
- f128: Ty<'db>,
- static_str_ref: Ty<'db>,
- error: Ty<'db>,
-
- re_static: Region<'db>,
- re_error: Region<'db>,
- re_erased: Region<'db>,
-
- empty_args: GenericArgs<'db>,
-}
-
-impl<'db> InternedStandardTypes<'db> {
- fn new(interner: DbInterner<'db>) -> Self {
- let str = Ty::new(interner, rustc_type_ir::TyKind::Str);
- let re_static = Region::new_static(interner);
- Self {
- unit: Ty::new_unit(interner),
- never: Ty::new(interner, TyKind::Never),
- char: Ty::new(interner, TyKind::Char),
- bool: Ty::new(interner, TyKind::Bool),
- i8: Ty::new_int(interner, rustc_type_ir::IntTy::I8),
- i16: Ty::new_int(interner, rustc_type_ir::IntTy::I16),
- i32: Ty::new_int(interner, rustc_type_ir::IntTy::I32),
- i64: Ty::new_int(interner, rustc_type_ir::IntTy::I64),
- i128: Ty::new_int(interner, rustc_type_ir::IntTy::I128),
- isize: Ty::new_int(interner, rustc_type_ir::IntTy::Isize),
- u8: Ty::new_uint(interner, rustc_type_ir::UintTy::U8),
- u16: Ty::new_uint(interner, rustc_type_ir::UintTy::U16),
- u32: Ty::new_uint(interner, rustc_type_ir::UintTy::U32),
- u64: Ty::new_uint(interner, rustc_type_ir::UintTy::U64),
- u128: Ty::new_uint(interner, rustc_type_ir::UintTy::U128),
- usize: Ty::new_uint(interner, rustc_type_ir::UintTy::Usize),
- f16: Ty::new_float(interner, rustc_type_ir::FloatTy::F16),
- f32: Ty::new_float(interner, rustc_type_ir::FloatTy::F32),
- f64: Ty::new_float(interner, rustc_type_ir::FloatTy::F64),
- f128: Ty::new_float(interner, rustc_type_ir::FloatTy::F128),
- static_str_ref: Ty::new_ref(interner, re_static, str, Mutability::Not),
- error: Ty::new_error(interner, ErrorGuaranteed),
-
- re_static,
- re_error: Region::error(interner),
- re_erased: Region::new_erased(interner),
-
- empty_args: GenericArgs::new_from_iter(interner, []),
- }
+ 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())
}
}
@@ -848,7 +767,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
@@ -865,7 +784,7 @@ pub(crate) struct InferenceContext<'body, 'db> {
resume_yield_tys: Option<(Ty<'db>, Ty<'db>)>,
diverges: Diverges,
breakables: Vec<BreakableContext<'db>>,
- types: InternedStandardTypes<'db>,
+ types: &'db crate::next_solver::DefaultAny<'db>,
/// Whether we are inside the pattern of a destructuring assignment.
inside_assignment: bool,
@@ -873,7 +792,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 +805,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)]
@@ -942,10 +861,10 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
) -> Self {
let trait_env = db.trait_environment_for_body(owner);
let table = unify::InferenceTable::new(db, trait_env, resolver.krate(), Some(owner));
- let types = InternedStandardTypes::new(table.interner());
+ let types = crate::next_solver::default_types(db);
InferenceContext {
- result: InferenceResult::new(types.error),
- return_ty: types.error, // set in collect_* calls
+ result: InferenceResult::new(types.types.error),
+ return_ty: types.types.error, // set in collect_* calls
types,
target_features: OnceCell::new(),
unstable_features: MethodResolutionUnstableFeatures::from_def_map(
@@ -1008,7 +927,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 +951,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 +985,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 +1009,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 +1020,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 +1044,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();
@@ -1174,7 +1096,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
data.type_ref,
&data.store,
InferenceTyDiagnosticSource::Signature,
- LifetimeElisionKind::Elided(self.types.re_static),
+ LifetimeElisionKind::Elided(self.types.regions.statik),
);
self.return_ty = return_ty;
@@ -1232,7 +1154,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
);
self.process_user_written_ty(return_ty)
}
- None => self.types.unit,
+ None => self.types.types.unit,
};
self.return_coercion = Some(CoerceMany::new(self.return_ty));
@@ -1262,10 +1184,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 +1200,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 +1213,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 +1226,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 +1239,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);
}
@@ -1429,7 +1351,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
}
fn err_ty(&self) -> Ty<'db> {
- self.types.error
+ self.types.types.error
}
pub(crate) fn make_body_lifetime(&mut self, lifetime_ref: LifetimeRefId) -> Region<'db> {
@@ -1486,7 +1408,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 +1475,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
}
@@ -1588,11 +1516,11 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
if let Err(_err) = result {
// FIXME: Emit diagnostic.
}
- result.unwrap_or(self.types.error)
+ result.unwrap_or(self.types.types.error)
}
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 +1528,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))
}
@@ -1820,7 +1748,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
result
} else {
// FIXME diagnostic
- (ctx.types.error, None)
+ (ctx.types.types.error, None)
}
}
}