Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/db.rs')
-rw-r--r--crates/hir-ty/src/db.rs251
1 files changed, 216 insertions, 35 deletions
diff --git a/crates/hir-ty/src/db.rs b/crates/hir-ty/src/db.rs
index 5dba53a761..352f717454 100644
--- a/crates/hir-ty/src/db.rs
+++ b/crates/hir-ty/src/db.rs
@@ -1,32 +1,39 @@
//! The home of `HirDatabase`, which is the Salsa database containing all the
//! type inference-related queries.
+use arrayvec::ArrayVec;
use base_db::{Crate, target::TargetLoadError};
use either::Either;
use hir_def::{
- AdtId, BuiltinDeriveImplId, CallableDefId, ConstId, ConstParamId, DefWithBodyId, EnumVariantId,
- ExpressionStoreOwnerId, FunctionId, GenericDefId, ImplId, LifetimeParamId, LocalFieldId,
- StaticId, TraitId, TypeAliasId, VariantId,
+ AdtId, BuiltinDeriveImplId, CallableDefId, ConstId, ConstParamId, EnumVariantId,
+ ExpressionStoreOwnerId, FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId,
+ LocalFieldId, ModuleId, StaticId, TraitId, TypeAliasId, VariantId,
builtin_derive::BuiltinDeriveImplMethod,
db::DefDatabase,
expr_store::ExpressionStore,
- hir::{ClosureKind, ExprId},
+ hir::{ClosureKind, ExprId, generics::LocalTypeOrConstParamId},
layout::TargetDataLayout,
+ resolver::{HasResolver, Resolver},
+ signatures::{ConstSignature, StaticSignature},
};
use la_arena::ArenaMap;
use salsa::plumbing::AsId;
+use span::Edition;
+use stdx::impl_from;
use triomphe::Arc;
use crate::{
- ImplTraitId, TyDefId, ValueTyDefId,
+ GenericDefaultsRef, GenericPredicates, ImplTraitId, InferBodyId, TyDefId, TyLoweringResult,
+ ValueTyDefId,
consteval::ConstEvalError,
dyn_compatibility::DynCompatibilityViolation,
layout::{Layout, LayoutError},
- lower::{Diagnostics, GenericDefaults},
+ lower::{GenericDefaults, TypeAliasBounds},
mir::{BorrowckResult, MirBody, MirLowerError},
next_solver::{
- Allocation, EarlyBinder, GenericArgs, ParamEnv, PolyFnSig, StoredEarlyBinder,
- StoredGenericArgs, StoredTy, TraitRef, Ty, VariancesOf,
+ Allocation, Clause, EarlyBinder, GenericArgs, ParamEnv, PolyFnSig, StoredClauses,
+ StoredEarlyBinder, StoredGenericArgs, StoredPolyFnSig, StoredTraitRef, StoredTy, TraitRef,
+ Ty, VariancesOf,
},
traits::{ParamEnvAndCrate, StoredParamEnvAndCrate},
};
@@ -38,7 +45,7 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
// FXME: Collapse `mir_body_for_closure` into `mir_body`
// and `monomorphized_mir_body_for_closure` into `monomorphized_mir_body`
#[salsa::transparent]
- fn mir_body(&self, def: DefWithBodyId) -> Result<&MirBody, MirLowerError> {
+ fn mir_body(&self, def: InferBodyId) -> Result<&MirBody, MirLowerError> {
crate::mir::mir_body_query(self, def).as_ref().map_err(|err| err.clone())
}
@@ -50,7 +57,7 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
#[salsa::transparent]
fn monomorphized_mir_body(
&self,
- def: DefWithBodyId,
+ def: InferBodyId,
subst: StoredGenericArgs,
env: StoredParamEnvAndCrate,
) -> Result<&MirBody, MirLowerError> {
@@ -72,7 +79,7 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
}
#[salsa::transparent]
- fn borrowck(&self, def: DefWithBodyId) -> Result<&[BorrowckResult], MirLowerError> {
+ fn borrowck(&self, def: InferBodyId) -> Result<&[BorrowckResult], MirLowerError> {
crate::mir::borrowck_query(self, def).as_ref().map(|it| &**it).map_err(|err| err.clone())
}
@@ -85,6 +92,15 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
trait_env: Option<ParamEnvAndCrate<'db>>,
) -> Result<Allocation<'db>, ConstEvalError>;
+ #[salsa::invoke(crate::consteval::anon_const_eval)]
+ #[salsa::transparent]
+ fn anon_const_eval<'db>(
+ &'db self,
+ def: AnonConstId,
+ subst: GenericArgs<'db>,
+ trait_env: Option<ParamEnvAndCrate<'db>>,
+ ) -> Result<Allocation<'db>, ConstEvalError>;
+
#[salsa::invoke(crate::consteval::const_eval_static)]
#[salsa::transparent]
fn const_eval_static<'db>(&'db self, def: StaticId) -> Result<Allocation<'db>, ConstEvalError>;
@@ -135,10 +151,10 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
#[salsa::invoke(crate::lower::type_for_type_alias_with_diagnostics)]
#[salsa::transparent]
- fn type_for_type_alias_with_diagnostics<'db>(
- &'db self,
+ fn type_for_type_alias_with_diagnostics(
+ &self,
def: TypeAliasId,
- ) -> (EarlyBinder<'db, Ty<'db>>, Diagnostics);
+ ) -> &TyLoweringResult<StoredEarlyBinder<StoredTy>>;
/// Returns the type of the value of the given constant, or `None` if the `ValueTyDefId` is
/// a `StructId` or `EnumVariantId` with a record constructor.
@@ -146,43 +162,71 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
#[salsa::transparent]
fn value_ty<'db>(&'db self, def: ValueTyDefId) -> Option<EarlyBinder<'db, Ty<'db>>>;
+ #[salsa::invoke(crate::lower::type_for_const)]
+ #[salsa::transparent]
+ fn type_for_const<'db>(&'db self, def: ConstId) -> EarlyBinder<'db, Ty<'db>>;
+
+ #[salsa::invoke(crate::lower::type_for_const_with_diagnostics)]
+ #[salsa::transparent]
+ fn type_for_const_with_diagnostics(
+ &self,
+ def: ConstId,
+ ) -> &TyLoweringResult<StoredEarlyBinder<StoredTy>>;
+
+ #[salsa::invoke(crate::lower::type_for_static)]
+ #[salsa::transparent]
+ fn type_for_static<'db>(&'db self, def: StaticId) -> EarlyBinder<'db, Ty<'db>>;
+
+ #[salsa::invoke(crate::lower::type_for_static_with_diagnostics)]
+ #[salsa::transparent]
+ fn type_for_static_with_diagnostics(
+ &self,
+ def: StaticId,
+ ) -> &TyLoweringResult<StoredEarlyBinder<StoredTy>>;
+
#[salsa::invoke(crate::lower::impl_self_ty_with_diagnostics)]
#[salsa::transparent]
- fn impl_self_ty_with_diagnostics<'db>(
- &'db self,
+ fn impl_self_ty_with_diagnostics(
+ &self,
def: ImplId,
- ) -> (EarlyBinder<'db, Ty<'db>>, Diagnostics);
+ ) -> &TyLoweringResult<StoredEarlyBinder<StoredTy>>;
#[salsa::invoke(crate::lower::impl_self_ty_query)]
#[salsa::transparent]
fn impl_self_ty<'db>(&'db self, def: ImplId) -> EarlyBinder<'db, Ty<'db>>;
- #[salsa::invoke(crate::lower::const_param_ty_with_diagnostics)]
+ #[salsa::invoke(crate::lower::const_param_types_with_diagnostics)]
#[salsa::transparent]
- fn const_param_ty_with_diagnostics<'db>(&'db self, def: ConstParamId)
- -> (Ty<'db>, Diagnostics);
+ fn const_param_types_with_diagnostics(
+ &self,
+ def: GenericDefId,
+ ) -> &TyLoweringResult<ArenaMap<LocalTypeOrConstParamId, StoredTy>>;
- #[salsa::invoke(crate::lower::const_param_ty_query)]
+ #[salsa::invoke(crate::lower::const_param_types)]
+ #[salsa::transparent]
+ fn const_param_types(&self, def: GenericDefId) -> &ArenaMap<LocalTypeOrConstParamId, StoredTy>;
+
+ #[salsa::invoke(crate::lower::const_param_ty)]
#[salsa::transparent]
fn const_param_ty<'db>(&'db self, def: ConstParamId) -> Ty<'db>;
#[salsa::invoke(crate::lower::impl_trait_with_diagnostics)]
#[salsa::transparent]
- fn impl_trait_with_diagnostics<'db>(
- &'db self,
+ fn impl_trait_with_diagnostics(
+ &self,
def: ImplId,
- ) -> Option<(EarlyBinder<'db, TraitRef<'db>>, Diagnostics)>;
+ ) -> &Option<TyLoweringResult<StoredEarlyBinder<StoredTraitRef>>>;
#[salsa::invoke(crate::lower::impl_trait_query)]
#[salsa::transparent]
fn impl_trait<'db>(&'db self, def: ImplId) -> Option<EarlyBinder<'db, TraitRef<'db>>>;
- #[salsa::invoke(crate::lower::field_types_with_diagnostics_query)]
+ #[salsa::invoke(crate::lower::field_types_with_diagnostics)]
#[salsa::transparent]
fn field_types_with_diagnostics(
&self,
var: VariantId,
- ) -> &(ArenaMap<LocalFieldId, StoredEarlyBinder<StoredTy>>, Diagnostics);
+ ) -> &TyLoweringResult<ArenaMap<LocalFieldId, StoredEarlyBinder<StoredTy>>>;
#[salsa::invoke(crate::lower::field_types_query)]
#[salsa::transparent]
@@ -195,23 +239,51 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
def: CallableDefId,
) -> EarlyBinder<'db, PolyFnSig<'db>>;
+ #[salsa::invoke(crate::lower::callable_item_signature_with_diagnostics)]
+ #[salsa::transparent]
+ fn callable_item_signature_with_diagnostics(
+ &self,
+ def: CallableDefId,
+ ) -> &TyLoweringResult<StoredEarlyBinder<StoredPolyFnSig>>;
+
#[salsa::invoke(crate::lower::trait_environment)]
#[salsa::transparent]
fn trait_environment<'db>(&'db self, def: ExpressionStoreOwnerId) -> ParamEnv<'db>;
- #[salsa::invoke(crate::lower::generic_defaults_with_diagnostics_query)]
- #[salsa::cycle(cycle_result = crate::lower::generic_defaults_with_diagnostics_cycle_result)]
+ #[salsa::invoke(crate::lower::generic_defaults_with_diagnostics)]
+ #[salsa::transparent]
fn generic_defaults_with_diagnostics(
&self,
def: GenericDefId,
- ) -> (GenericDefaults, Diagnostics);
+ ) -> &TyLoweringResult<GenericDefaults>;
/// This returns an empty list if no parameter has default.
///
/// The binders of the returned defaults are only up to (not including) this parameter.
- #[salsa::invoke(crate::lower::generic_defaults_query)]
+ #[salsa::invoke(crate::lower::generic_defaults)]
#[salsa::transparent]
- fn generic_defaults(&self, def: GenericDefId) -> GenericDefaults;
+ fn generic_defaults(&self, def: GenericDefId) -> GenericDefaultsRef<'_>;
+
+ #[salsa::invoke(crate::lower::type_alias_bounds_with_diagnostics)]
+ #[salsa::transparent]
+ fn type_alias_bounds_with_diagnostics(
+ &self,
+ type_alias: TypeAliasId,
+ ) -> &TyLoweringResult<TypeAliasBounds<StoredEarlyBinder<StoredClauses>>>;
+
+ #[salsa::invoke(crate::lower::type_alias_bounds)]
+ #[salsa::transparent]
+ fn type_alias_bounds<'db>(
+ &'db self,
+ type_alias: TypeAliasId,
+ ) -> EarlyBinder<'db, &'db [Clause<'db>]>;
+
+ #[salsa::invoke(crate::lower::type_alias_self_bounds)]
+ #[salsa::transparent]
+ fn type_alias_self_bounds<'db>(
+ &'db self,
+ type_alias: TypeAliasId,
+ ) -> EarlyBinder<'db, &'db [Clause<'db>]>;
// Interned IDs for solver integration
#[salsa::interned]
@@ -248,7 +320,7 @@ pub struct InternedOpaqueTyId {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct InternedClosure {
- pub owner: ExpressionStoreOwnerId,
+ pub owner: InferBodyId,
pub expr: ExprId,
pub kind: ClosureKind,
}
@@ -263,7 +335,7 @@ impl InternedClosureId {
#[inline]
pub fn new(db: &dyn HirDatabase, loc: InternedClosure) -> Self {
if cfg!(debug_assertions) {
- let store = ExpressionStore::of(db, loc.owner);
+ let store = ExpressionStore::of(db, loc.owner.expression_store_owner(db));
let expr = &store[loc.expr];
assert!(
matches!(
@@ -291,7 +363,7 @@ impl InternedCoroutineId {
#[inline]
pub fn new(db: &dyn HirDatabase, loc: InternedClosure) -> Self {
if cfg!(debug_assertions) {
- let store = ExpressionStore::of(db, loc.owner);
+ let store = ExpressionStore::of(db, loc.owner.expression_store_owner(db));
let expr = &store[loc.expr];
assert!(
matches!(
@@ -320,7 +392,7 @@ impl InternedCoroutineClosureId {
#[inline]
pub fn new(db: &dyn HirDatabase, loc: InternedClosure) -> Self {
if cfg!(debug_assertions) {
- let store = ExpressionStore::of(db, loc.owner);
+ let store = ExpressionStore::of(db, loc.owner.expression_store_owner(db));
let expr = &store[loc.expr];
assert!(
matches!(
@@ -337,3 +409,112 @@ impl InternedCoroutineClosureId {
Self::new_impl(db, loc)
}
}
+
+/// An anonymous const expression that appears in a type position (e.g., array lengths,
+/// const generic arguments like `{ N + 1 }`, or const param defaults). Unlike named constants,
+/// these don't have their own `Body` — their expressions live in the parent's signature `ExpressionStore`.
+#[derive(Debug, Hash, PartialEq, Eq, Clone)]
+pub struct AnonConstLoc {
+ /// The owner store containing this expression.
+ pub owner: ExpressionStoreOwnerId,
+ /// The ExprId within the owner's ExpressionStore that is the root
+ /// of this anonymous const expression.
+ pub expr: ExprId,
+ pub ty: StoredEarlyBinder<StoredTy>,
+ /// Whether to allow using generic params from the owner.
+ /// true for array repeats, false for everything else.
+ pub(crate) allow_using_generic_params: bool,
+}
+
+#[salsa_macros::interned(debug, no_lifetime, revisions = usize::MAX)]
+#[derive(PartialOrd, Ord)]
+pub struct AnonConstId {
+ #[returns(ref)]
+ pub loc: AnonConstLoc,
+}
+
+impl HasModule for AnonConstId {
+ fn module(&self, db: &dyn DefDatabase) -> ModuleId {
+ self.loc(db).owner.module(db)
+ }
+}
+
+impl HasResolver for AnonConstId {
+ fn resolver(self, db: &dyn DefDatabase) -> Resolver<'_> {
+ self.loc(db).owner.resolver(db)
+ }
+}
+
+impl AnonConstId {
+ pub fn all_from_signature(
+ db: &dyn HirDatabase,
+ def: GenericDefId,
+ ) -> ArrayVec<&[AnonConstId], 5> {
+ let mut result = ArrayVec::new();
+
+ // Queries common to all generic defs:
+ result.push(db.generic_defaults_with_diagnostics(def).defined_anon_consts());
+ result.push(GenericPredicates::query_with_diagnostics(db, def).defined_anon_consts());
+ result.push(db.const_param_types_with_diagnostics(def).defined_anon_consts());
+
+ match def {
+ GenericDefId::ImplId(id) => {
+ result.push(db.impl_self_ty_with_diagnostics(id).defined_anon_consts());
+ if let Some(trait_ref) = db.impl_trait_with_diagnostics(id) {
+ result.push(trait_ref.defined_anon_consts());
+ }
+ }
+ GenericDefId::TypeAliasId(id) => {
+ result.push(db.type_for_type_alias_with_diagnostics(id).defined_anon_consts());
+ result.push(db.type_alias_bounds_with_diagnostics(id).defined_anon_consts());
+ }
+ GenericDefId::FunctionId(id) => result
+ .push(db.callable_item_signature_with_diagnostics(id.into()).defined_anon_consts()),
+ GenericDefId::ConstId(def) => {
+ result.push(db.type_for_const_with_diagnostics(def).defined_anon_consts())
+ }
+ GenericDefId::StaticId(def) => {
+ result.push(db.type_for_static_with_diagnostics(def).defined_anon_consts())
+ }
+ GenericDefId::TraitId(_) | GenericDefId::AdtId(_) => {}
+ }
+
+ result
+ }
+}
+
+/// A constant, which might appears as a const item, an anonymous const block in expressions
+/// or patterns, or as a constant in types with const generics.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype)]
+pub enum GeneralConstId {
+ ConstId(ConstId),
+ StaticId(StaticId),
+ AnonConstId(AnonConstId),
+}
+
+impl_from!(ConstId, StaticId, AnonConstId for GeneralConstId);
+
+impl GeneralConstId {
+ pub fn generic_def(self, db: &dyn HirDatabase) -> Option<GenericDefId> {
+ match self {
+ GeneralConstId::ConstId(it) => Some(it.into()),
+ GeneralConstId::StaticId(it) => Some(it.into()),
+ GeneralConstId::AnonConstId(it) => Some(it.loc(db).owner.generic_def(db)),
+ }
+ }
+
+ pub fn name(self, db: &dyn DefDatabase) -> String {
+ match self {
+ GeneralConstId::StaticId(it) => {
+ StaticSignature::of(db, it).name.display(db, Edition::CURRENT).to_string()
+ }
+ GeneralConstId::ConstId(const_id) => {
+ ConstSignature::of(db, const_id).name.as_ref().map_or_else(
+ || "_".to_owned(),
+ |name| name.display(db, Edition::CURRENT).to_string(),
+ )
+ }
+ GeneralConstId::AnonConstId(_) => "{const}".to_owned(),
+ }
+ }
+}