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.rs | 317 |
1 files changed, 257 insertions, 60 deletions
diff --git a/crates/hir-ty/src/db.rs b/crates/hir-ty/src/db.rs index 3bf2d9a6a6..c24a5b943d 100644 --- a/crates/hir-ty/src/db.rs +++ b/crates/hir-ty/src/db.rs @@ -1,28 +1,38 @@ //! 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, builtin_derive::BuiltinDeriveImplMethod, - db::DefDatabase, expr_store::ExpressionStore, hir::ExprId, layout::TargetDataLayout, + 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, 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}, }; @@ -33,33 +43,44 @@ 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::invoke(crate::mir::mir_body_query)] - #[salsa::cycle(cycle_result = crate::mir::mir_body_cycle_result)] - fn mir_body(&self, def: DefWithBodyId) -> Result<Arc<MirBody>, MirLowerError>; + #[salsa::transparent] + fn mir_body(&self, def: InferBodyId) -> Result<&MirBody, MirLowerError> { + crate::mir::mir_body_query(self, def).as_ref().map_err(|err| err.clone()) + } - #[salsa::invoke(crate::mir::mir_body_for_closure_query)] - fn mir_body_for_closure(&self, def: InternedClosureId) -> Result<Arc<MirBody>, MirLowerError>; + #[salsa::transparent] + fn mir_body_for_closure(&self, def: InternedClosureId) -> Result<&MirBody, MirLowerError> { + crate::mir::mir_body_for_closure_query(self, def).as_ref().map_err(|err| err.clone()) + } - #[salsa::invoke(crate::mir::monomorphized_mir_body_query)] - #[salsa::cycle(cycle_result = crate::mir::monomorphized_mir_body_cycle_result)] + #[salsa::transparent] fn monomorphized_mir_body( &self, - def: DefWithBodyId, + def: InferBodyId, subst: StoredGenericArgs, env: StoredParamEnvAndCrate, - ) -> Result<Arc<MirBody>, MirLowerError>; + ) -> Result<&MirBody, MirLowerError> { + crate::mir::monomorphized_mir_body_query(self, def, subst, env) + .as_ref() + .map_err(|err| err.clone()) + } - #[salsa::invoke(crate::mir::monomorphized_mir_body_for_closure_query)] + #[salsa::transparent] fn monomorphized_mir_body_for_closure( &self, def: InternedClosureId, subst: StoredGenericArgs, env: StoredParamEnvAndCrate, - ) -> Result<Arc<MirBody>, MirLowerError>; + ) -> Result<&MirBody, MirLowerError> { + crate::mir::monomorphized_mir_body_for_closure_query(self, def, subst, env) + .as_ref() + .map_err(|err| err.clone()) + } - #[salsa::invoke(crate::mir::borrowck_query)] - #[salsa::lru(2024)] - fn borrowck(&self, def: DefWithBodyId) -> Result<Arc<[BorrowckResult]>, MirLowerError>; + #[salsa::transparent] + fn borrowck(&self, def: InferBodyId) -> Result<&[BorrowckResult], MirLowerError> { + crate::mir::borrowck_query(self, def).as_ref().map(|it| &**it).map_err(|err| err.clone()) + } #[salsa::invoke(crate::consteval::const_eval)] #[salsa::transparent] @@ -70,6 +91,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>; @@ -106,8 +136,10 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug { env: StoredParamEnvAndCrate, ) -> Result<Arc<Layout>, LayoutError>; - #[salsa::invoke(crate::layout::target_data_layout_query)] - fn target_data_layout(&self, krate: Crate) -> Result<Arc<TargetDataLayout>, TargetLoadError>; + #[salsa::transparent] + fn target_data_layout(&self, krate: Crate) -> Result<&TargetDataLayout, TargetLoadError> { + crate::layout::target_data_layout_query(self, krate).as_ref().map_err(|err| err.clone()) + } #[salsa::invoke(crate::dyn_compatibility::dyn_compatibility_of_trait_query)] fn dyn_compatibility_of_trait(&self, trait_: TraitId) -> Option<DynCompatibilityViolation>; @@ -118,10 +150,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. @@ -129,43 +161,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_types_with_diagnostics( + &self, + def: GenericDefId, + ) -> &TyLoweringResult<ArenaMap<LocalTypeOrConstParamId, StoredTy>>; + + #[salsa::invoke(crate::lower::const_param_types)] #[salsa::transparent] - fn const_param_ty_with_diagnostics<'db>(&'db self, def: ConstParamId) - -> (Ty<'db>, Diagnostics); + fn const_param_types(&self, def: GenericDefId) -> &ArenaMap<LocalTypeOrConstParamId, StoredTy>; - #[salsa::invoke(crate::lower::const_param_ty_query)] + #[salsa::invoke(crate::lower::const_param_ty)] #[salsa::transparent] - fn const_param_ty_ns<'db>(&'db self, def: ConstParamId) -> Ty<'db>; + 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] @@ -178,27 +238,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) -> GenericDefaultsRef<'_>; + + #[salsa::invoke(crate::lower::type_alias_bounds_with_diagnostics)] #[salsa::transparent] - fn generic_defaults(&self, def: GenericDefId) -> GenericDefaults; + 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>]>; - // Interned IDs for solver integration - #[salsa::interned] - fn intern_impl_trait_id(&self, id: ImplTraitId) -> InternedOpaqueTyId; + #[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>]>; #[salsa::invoke(crate::variance::variances_of)] #[salsa::transparent] @@ -229,8 +313,12 @@ pub struct InternedOpaqueTyId { pub loc: ImplTraitId, } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct InternedClosure(pub ExpressionStoreOwnerId, pub ExprId); +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct InternedClosure { + pub owner: InferBodyId, + pub expr: ExprId, + pub kind: ClosureKind, +} #[salsa_macros::interned(constructor = new_impl, no_lifetime, debug, revisions = usize::MAX)] #[derive(PartialOrd, Ord)] @@ -242,8 +330,8 @@ impl InternedClosureId { #[inline] pub fn new(db: &dyn HirDatabase, loc: InternedClosure) -> Self { if cfg!(debug_assertions) { - let store = ExpressionStore::of(db, loc.0); - let expr = &store[loc.1]; + let store = ExpressionStore::of(db, loc.owner.expression_store_owner(db)); + let expr = &store[loc.expr]; assert!( matches!( expr, @@ -270,14 +358,14 @@ impl InternedCoroutineId { #[inline] pub fn new(db: &dyn HirDatabase, loc: InternedClosure) -> Self { if cfg!(debug_assertions) { - let store = ExpressionStore::of(db, loc.0); - let expr = &store[loc.1]; + let store = ExpressionStore::of(db, loc.owner.expression_store_owner(db)); + let expr = &store[loc.expr]; assert!( matches!( expr, hir_def::hir::Expr::Closure { - closure_kind: hir_def::hir::ClosureKind::Coroutine(_) - | hir_def::hir::ClosureKind::AsyncBlock { .. }, + closure_kind: hir_def::hir::ClosureKind::OldCoroutine(_) + | hir_def::hir::ClosureKind::Coroutine { .. }, .. } ), @@ -299,13 +387,13 @@ impl InternedCoroutineClosureId { #[inline] pub fn new(db: &dyn HirDatabase, loc: InternedClosure) -> Self { if cfg!(debug_assertions) { - let store = ExpressionStore::of(db, loc.0); - let expr = &store[loc.1]; + let store = ExpressionStore::of(db, loc.owner.expression_store_owner(db)); + let expr = &store[loc.expr]; assert!( matches!( expr, hir_def::hir::Expr::Closure { - closure_kind: hir_def::hir::ClosureKind::AsyncClosure, + closure_kind: hir_def::hir::ClosureKind::CoroutineClosure(_), .. } ), @@ -316,3 +404,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(), + } + } +} |