mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-30 11:37:31 +00:00
Adapt for new cycle handling changing in Salsa
This commit is contained in:
parent
db72e2ff41
commit
57c019a3c5
15 changed files with 133 additions and 339 deletions
|
|
@ -619,7 +619,7 @@ impl_from!(
|
||||||
|
|
||||||
/// A constant, which might appears as a const item, an anonymous const block in expressions
|
/// 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.
|
/// or patterns, or as a constant in types with const generics.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa::Supertype)]
|
||||||
pub enum GeneralConstId {
|
pub enum GeneralConstId {
|
||||||
ConstId(ConstId),
|
ConstId(ConstId),
|
||||||
StaticId(StaticId),
|
StaticId(StaticId),
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ use hir_def::{
|
||||||
type_ref::LiteralConstRef,
|
type_ref::LiteralConstRef,
|
||||||
};
|
};
|
||||||
use hir_expand::Lookup;
|
use hir_expand::Lookup;
|
||||||
use salsa::Cycle;
|
|
||||||
use stdx::never;
|
use stdx::never;
|
||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
|
|
||||||
|
|
@ -220,9 +219,8 @@ pub fn try_const_isize(db: &dyn HirDatabase, c: &Const) -> Option<i128> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn const_eval_recover(
|
pub(crate) fn const_eval_cycle_result(
|
||||||
_: &dyn HirDatabase,
|
_: &dyn HirDatabase,
|
||||||
_: &Cycle,
|
|
||||||
_: GeneralConstId,
|
_: GeneralConstId,
|
||||||
_: Substitution,
|
_: Substitution,
|
||||||
_: Option<Arc<TraitEnvironment>>,
|
_: Option<Arc<TraitEnvironment>>,
|
||||||
|
|
@ -230,17 +228,15 @@ pub(crate) fn const_eval_recover(
|
||||||
Err(ConstEvalError::MirLowerError(MirLowerError::Loop))
|
Err(ConstEvalError::MirLowerError(MirLowerError::Loop))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn const_eval_static_recover(
|
pub(crate) fn const_eval_static_cycle_result(
|
||||||
_: &dyn HirDatabase,
|
_: &dyn HirDatabase,
|
||||||
_: &Cycle,
|
|
||||||
_: StaticId,
|
_: StaticId,
|
||||||
) -> Result<Const, ConstEvalError> {
|
) -> Result<Const, ConstEvalError> {
|
||||||
Err(ConstEvalError::MirLowerError(MirLowerError::Loop))
|
Err(ConstEvalError::MirLowerError(MirLowerError::Loop))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn const_eval_discriminant_recover(
|
pub(crate) fn const_eval_discriminant_cycle_result(
|
||||||
_: &dyn HirDatabase,
|
_: &dyn HirDatabase,
|
||||||
_: &Cycle,
|
|
||||||
_: EnumVariantId,
|
_: EnumVariantId,
|
||||||
) -> Result<i128, ConstEvalError> {
|
) -> Result<i128, ConstEvalError> {
|
||||||
Err(ConstEvalError::MirLowerError(MirLowerError::Loop))
|
Err(ConstEvalError::MirLowerError(MirLowerError::Loop))
|
||||||
|
|
|
||||||
|
|
@ -36,14 +36,14 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
|
||||||
// region:mir
|
// region:mir
|
||||||
|
|
||||||
#[salsa::invoke(crate::mir::mir_body_query)]
|
#[salsa::invoke(crate::mir::mir_body_query)]
|
||||||
#[salsa::cycle(crate::mir::mir_body_recover)]
|
#[salsa::cycle(cycle_result = crate::mir::mir_body_cycle_result)]
|
||||||
fn mir_body(&self, def: DefWithBodyId) -> Result<Arc<MirBody>, MirLowerError>;
|
fn mir_body(&self, def: DefWithBodyId) -> Result<Arc<MirBody>, MirLowerError>;
|
||||||
|
|
||||||
#[salsa::invoke(crate::mir::mir_body_for_closure_query)]
|
#[salsa::invoke(crate::mir::mir_body_for_closure_query)]
|
||||||
fn mir_body_for_closure(&self, def: InternedClosureId) -> Result<Arc<MirBody>, MirLowerError>;
|
fn mir_body_for_closure(&self, def: InternedClosureId) -> Result<Arc<MirBody>, MirLowerError>;
|
||||||
|
|
||||||
#[salsa::invoke(crate::mir::monomorphized_mir_body_query)]
|
#[salsa::invoke(crate::mir::monomorphized_mir_body_query)]
|
||||||
#[salsa::cycle(crate::mir::monomorphized_mir_body_recover)]
|
#[salsa::cycle(cycle_result = crate::mir::monomorphized_mir_body_cycle_result)]
|
||||||
fn monomorphized_mir_body(
|
fn monomorphized_mir_body(
|
||||||
&self,
|
&self,
|
||||||
def: DefWithBodyId,
|
def: DefWithBodyId,
|
||||||
|
|
@ -64,7 +64,7 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
|
||||||
fn borrowck(&self, def: DefWithBodyId) -> Result<Arc<[BorrowckResult]>, MirLowerError>;
|
fn borrowck(&self, def: DefWithBodyId) -> Result<Arc<[BorrowckResult]>, MirLowerError>;
|
||||||
|
|
||||||
#[salsa::invoke(crate::consteval::const_eval_query)]
|
#[salsa::invoke(crate::consteval::const_eval_query)]
|
||||||
#[salsa::cycle(crate::consteval::const_eval_recover)]
|
#[salsa::cycle(cycle_result = crate::consteval::const_eval_cycle_result)]
|
||||||
fn const_eval(
|
fn const_eval(
|
||||||
&self,
|
&self,
|
||||||
def: GeneralConstId,
|
def: GeneralConstId,
|
||||||
|
|
@ -73,11 +73,11 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
|
||||||
) -> Result<Const, ConstEvalError>;
|
) -> Result<Const, ConstEvalError>;
|
||||||
|
|
||||||
#[salsa::invoke(crate::consteval::const_eval_static_query)]
|
#[salsa::invoke(crate::consteval::const_eval_static_query)]
|
||||||
#[salsa::cycle(crate::consteval::const_eval_static_recover)]
|
#[salsa::cycle(cycle_result = crate::consteval::const_eval_static_cycle_result)]
|
||||||
fn const_eval_static(&self, def: StaticId) -> Result<Const, ConstEvalError>;
|
fn const_eval_static(&self, def: StaticId) -> Result<Const, ConstEvalError>;
|
||||||
|
|
||||||
#[salsa::invoke(crate::consteval::const_eval_discriminant_variant)]
|
#[salsa::invoke(crate::consteval::const_eval_discriminant_variant)]
|
||||||
#[salsa::cycle(crate::consteval::const_eval_discriminant_recover)]
|
#[salsa::cycle(cycle_result = crate::consteval::const_eval_discriminant_cycle_result)]
|
||||||
fn const_eval_discriminant(&self, def: EnumVariantId) -> Result<i128, ConstEvalError>;
|
fn const_eval_discriminant(&self, def: EnumVariantId) -> Result<i128, ConstEvalError>;
|
||||||
|
|
||||||
#[salsa::invoke(crate::method_resolution::lookup_impl_method_query)]
|
#[salsa::invoke(crate::method_resolution::lookup_impl_method_query)]
|
||||||
|
|
@ -91,7 +91,7 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
|
||||||
// endregion:mir
|
// endregion:mir
|
||||||
|
|
||||||
#[salsa::invoke(crate::layout::layout_of_adt_query)]
|
#[salsa::invoke(crate::layout::layout_of_adt_query)]
|
||||||
#[salsa::cycle(crate::layout::layout_of_adt_recover)]
|
#[salsa::cycle(cycle_result = crate::layout::layout_of_adt_cycle_result)]
|
||||||
fn layout_of_adt(
|
fn layout_of_adt(
|
||||||
&self,
|
&self,
|
||||||
def: AdtId,
|
def: AdtId,
|
||||||
|
|
@ -100,7 +100,7 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
|
||||||
) -> Result<Arc<Layout>, LayoutError>;
|
) -> Result<Arc<Layout>, LayoutError>;
|
||||||
|
|
||||||
#[salsa::invoke(crate::layout::layout_of_ty_query)]
|
#[salsa::invoke(crate::layout::layout_of_ty_query)]
|
||||||
#[salsa::cycle(crate::layout::layout_of_ty_recover)]
|
#[salsa::cycle(cycle_result = crate::layout::layout_of_ty_cycle_result)]
|
||||||
fn layout_of_ty(&self, ty: Ty, env: Arc<TraitEnvironment>) -> Result<Arc<Layout>, LayoutError>;
|
fn layout_of_ty(&self, ty: Ty, env: Arc<TraitEnvironment>) -> Result<Arc<Layout>, LayoutError>;
|
||||||
|
|
||||||
#[salsa::invoke(crate::layout::target_data_layout_query)]
|
#[salsa::invoke(crate::layout::target_data_layout_query)]
|
||||||
|
|
@ -113,8 +113,8 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
|
||||||
#[salsa::transparent]
|
#[salsa::transparent]
|
||||||
fn ty(&self, def: TyDefId) -> Binders<Ty>;
|
fn ty(&self, def: TyDefId) -> Binders<Ty>;
|
||||||
|
|
||||||
#[salsa::cycle(crate::lower::type_for_type_alias_with_diagnostics_query_recover)]
|
|
||||||
#[salsa::invoke(crate::lower::type_for_type_alias_with_diagnostics_query)]
|
#[salsa::invoke(crate::lower::type_for_type_alias_with_diagnostics_query)]
|
||||||
|
#[salsa::cycle(cycle_result = crate::lower::type_for_type_alias_with_diagnostics_cycle_result)]
|
||||||
fn type_for_type_alias_with_diagnostics(&self, def: TypeAliasId) -> (Binders<Ty>, Diagnostics);
|
fn type_for_type_alias_with_diagnostics(&self, def: TypeAliasId) -> (Binders<Ty>, Diagnostics);
|
||||||
|
|
||||||
/// Returns the type of the value of the given constant, or `None` if the `ValueTyDefId` is
|
/// Returns the type of the value of the given constant, or `None` if the `ValueTyDefId` is
|
||||||
|
|
@ -123,7 +123,7 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
|
||||||
fn value_ty(&self, def: ValueTyDefId) -> Option<Binders<Ty>>;
|
fn value_ty(&self, def: ValueTyDefId) -> Option<Binders<Ty>>;
|
||||||
|
|
||||||
#[salsa::invoke(crate::lower::impl_self_ty_with_diagnostics_query)]
|
#[salsa::invoke(crate::lower::impl_self_ty_with_diagnostics_query)]
|
||||||
#[salsa::cycle(crate::lower::impl_self_ty_with_diagnostics_recover)]
|
#[salsa::cycle(cycle_result = crate::lower::impl_self_ty_with_diagnostics_cycle_result)]
|
||||||
fn impl_self_ty_with_diagnostics(&self, def: ImplId) -> (Binders<Ty>, Diagnostics);
|
fn impl_self_ty_with_diagnostics(&self, def: ImplId) -> (Binders<Ty>, Diagnostics);
|
||||||
|
|
||||||
#[salsa::invoke(crate::lower::impl_self_ty_query)]
|
#[salsa::invoke(crate::lower::impl_self_ty_query)]
|
||||||
|
|
@ -165,7 +165,7 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
|
||||||
fn type_alias_impl_traits(&self, def: TypeAliasId) -> Option<Arc<Binders<ImplTraits>>>;
|
fn type_alias_impl_traits(&self, def: TypeAliasId) -> Option<Arc<Binders<ImplTraits>>>;
|
||||||
|
|
||||||
#[salsa::invoke(crate::lower::generic_predicates_for_param_query)]
|
#[salsa::invoke(crate::lower::generic_predicates_for_param_query)]
|
||||||
#[salsa::cycle(crate::lower::generic_predicates_for_param_recover)]
|
#[salsa::cycle(cycle_result = crate::lower::generic_predicates_for_param_cycle_result)]
|
||||||
fn generic_predicates_for_param(
|
fn generic_predicates_for_param(
|
||||||
&self,
|
&self,
|
||||||
def: GenericDefId,
|
def: GenericDefId,
|
||||||
|
|
@ -194,7 +194,7 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
|
||||||
fn trait_environment(&self, def: GenericDefId) -> Arc<TraitEnvironment>;
|
fn trait_environment(&self, def: GenericDefId) -> Arc<TraitEnvironment>;
|
||||||
|
|
||||||
#[salsa::invoke(crate::lower::generic_defaults_with_diagnostics_query)]
|
#[salsa::invoke(crate::lower::generic_defaults_with_diagnostics_query)]
|
||||||
#[salsa::cycle(crate::lower::generic_defaults_with_diagnostics_recover)]
|
#[salsa::cycle(cycle_result = crate::lower::generic_defaults_with_diagnostics_cycle_result)]
|
||||||
fn generic_defaults_with_diagnostics(
|
fn generic_defaults_with_diagnostics(
|
||||||
&self,
|
&self,
|
||||||
def: GenericDefId,
|
def: GenericDefId,
|
||||||
|
|
@ -282,7 +282,10 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
|
||||||
fn adt_variance(&self, adt_id: AdtId) -> chalk_db::Variances;
|
fn adt_variance(&self, adt_id: AdtId) -> chalk_db::Variances;
|
||||||
|
|
||||||
#[salsa::invoke(crate::variance::variances_of)]
|
#[salsa::invoke(crate::variance::variances_of)]
|
||||||
#[salsa::cycle(crate::variance::variances_of_cycle)]
|
#[salsa::cycle(
|
||||||
|
cycle_fn = crate::variance::variances_of_cycle_fn,
|
||||||
|
cycle_initial = crate::variance::variances_of_cycle_initial,
|
||||||
|
)]
|
||||||
fn variances_of(&self, def: GenericDefId) -> Option<Arc<[crate::variance::Variance]>>;
|
fn variances_of(&self, def: GenericDefId) -> Option<Arc<[crate::variance::Variance]>>;
|
||||||
|
|
||||||
#[salsa::invoke(chalk_db::associated_ty_value_query)]
|
#[salsa::invoke(chalk_db::associated_ty_value_query)]
|
||||||
|
|
@ -317,7 +320,7 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
|
||||||
) -> chalk_ir::ProgramClauses<Interner>;
|
) -> chalk_ir::ProgramClauses<Interner>;
|
||||||
|
|
||||||
#[salsa::invoke(crate::drop::has_drop_glue)]
|
#[salsa::invoke(crate::drop::has_drop_glue)]
|
||||||
#[salsa::cycle(crate::drop::has_drop_glue_recover)]
|
#[salsa::cycle(cycle_result = crate::drop::has_drop_glue_cycle_result)]
|
||||||
fn has_drop_glue(&self, ty: Ty, env: Arc<TraitEnvironment>) -> DropGlue;
|
fn has_drop_glue(&self, ty: Ty, env: Arc<TraitEnvironment>) -> DropGlue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -193,9 +193,8 @@ fn is_copy(db: &dyn HirDatabase, ty: Ty, env: Arc<TraitEnvironment>) -> bool {
|
||||||
db.trait_solve(env.krate, env.block, goal).is_some()
|
db.trait_solve(env.krate, env.block, goal).is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn has_drop_glue_recover(
|
pub(crate) fn has_drop_glue_cycle_result(
|
||||||
_db: &dyn HirDatabase,
|
_db: &dyn HirDatabase,
|
||||||
_cycle: &salsa::Cycle,
|
|
||||||
_ty: Ty,
|
_ty: Ty,
|
||||||
_env: Arc<TraitEnvironment>,
|
_env: Arc<TraitEnvironment>,
|
||||||
) -> DropGlue {
|
) -> DropGlue {
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ use hir_def::{
|
||||||
use la_arena::{Idx, RawIdx};
|
use la_arena::{Idx, RawIdx};
|
||||||
use rustc_abi::AddressSpace;
|
use rustc_abi::AddressSpace;
|
||||||
use rustc_index::IndexVec;
|
use rustc_index::IndexVec;
|
||||||
use salsa::Cycle;
|
|
||||||
|
|
||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
|
|
||||||
|
|
@ -25,7 +24,7 @@ use crate::{
|
||||||
utils::ClosureSubst,
|
utils::ClosureSubst,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) use self::adt::layout_of_adt_recover;
|
pub(crate) use self::adt::layout_of_adt_cycle_result;
|
||||||
pub use self::{adt::layout_of_adt_query, target::target_data_layout_query};
|
pub use self::{adt::layout_of_adt_query, target::target_data_layout_query};
|
||||||
|
|
||||||
mod adt;
|
mod adt;
|
||||||
|
|
@ -365,9 +364,8 @@ pub fn layout_of_ty_query(
|
||||||
Ok(Arc::new(result))
|
Ok(Arc::new(result))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn layout_of_ty_recover(
|
pub(crate) fn layout_of_ty_cycle_result(
|
||||||
_: &dyn HirDatabase,
|
_: &dyn HirDatabase,
|
||||||
_: &Cycle,
|
|
||||||
_: Ty,
|
_: Ty,
|
||||||
_: Arc<TraitEnvironment>,
|
_: Arc<TraitEnvironment>,
|
||||||
) -> Result<Arc<Layout>, LayoutError> {
|
) -> Result<Arc<Layout>, LayoutError> {
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ use hir_def::{
|
||||||
};
|
};
|
||||||
use intern::sym;
|
use intern::sym;
|
||||||
use rustc_index::IndexVec;
|
use rustc_index::IndexVec;
|
||||||
use salsa::Cycle;
|
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
|
|
||||||
|
|
@ -131,9 +130,8 @@ fn layout_scalar_valid_range(db: &dyn HirDatabase, def: AdtId) -> (Bound<u128>,
|
||||||
(get(sym::rustc_layout_scalar_valid_range_start), get(sym::rustc_layout_scalar_valid_range_end))
|
(get(sym::rustc_layout_scalar_valid_range_start), get(sym::rustc_layout_scalar_valid_range_end))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn layout_of_adt_recover(
|
pub(crate) fn layout_of_adt_cycle_result(
|
||||||
_: &dyn HirDatabase,
|
_: &dyn HirDatabase,
|
||||||
_: &Cycle,
|
|
||||||
_: AdtId,
|
_: AdtId,
|
||||||
_: Substitution,
|
_: Substitution,
|
||||||
_: Arc<TraitEnvironment>,
|
_: Arc<TraitEnvironment>,
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,6 @@ use hir_expand::name::Name;
|
||||||
use la_arena::{Arena, ArenaMap};
|
use la_arena::{Arena, ArenaMap};
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
use rustc_pattern_analysis::Captures;
|
use rustc_pattern_analysis::Captures;
|
||||||
use salsa::Cycle;
|
|
||||||
use stdx::{impl_from, never};
|
use stdx::{impl_from, never};
|
||||||
use triomphe::{Arc, ThinArc};
|
use triomphe::{Arc, ThinArc};
|
||||||
|
|
||||||
|
|
@ -961,9 +960,8 @@ pub(crate) fn generic_predicates_for_param_query(
|
||||||
GenericPredicates(predicates.is_empty().not().then(|| predicates.into()))
|
GenericPredicates(predicates.is_empty().not().then(|| predicates.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn generic_predicates_for_param_recover(
|
pub(crate) fn generic_predicates_for_param_cycle_result(
|
||||||
_db: &dyn HirDatabase,
|
_db: &dyn HirDatabase,
|
||||||
_cycle: &salsa::Cycle,
|
|
||||||
_def: GenericDefId,
|
_def: GenericDefId,
|
||||||
_param_id: TypeOrConstParamId,
|
_param_id: TypeOrConstParamId,
|
||||||
_assoc_name: Option<Name>,
|
_assoc_name: Option<Name>,
|
||||||
|
|
@ -1264,9 +1262,8 @@ pub(crate) fn generic_defaults_with_diagnostics_query(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn generic_defaults_with_diagnostics_recover(
|
pub(crate) fn generic_defaults_with_diagnostics_cycle_result(
|
||||||
_db: &dyn HirDatabase,
|
_db: &dyn HirDatabase,
|
||||||
_cycle: &Cycle,
|
|
||||||
_def: GenericDefId,
|
_def: GenericDefId,
|
||||||
) -> (GenericDefaults, Diagnostics) {
|
) -> (GenericDefaults, Diagnostics) {
|
||||||
(GenericDefaults(None), None)
|
(GenericDefaults(None), None)
|
||||||
|
|
@ -1402,16 +1399,12 @@ fn type_for_enum_variant_constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[salsa::tracked(recovery_fn = type_for_adt_recovery)]
|
#[salsa::tracked(cycle_result = type_for_adt_cycle_result)]
|
||||||
fn type_for_adt_tracked(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> {
|
fn type_for_adt_tracked(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> {
|
||||||
type_for_adt(db, adt)
|
type_for_adt(db, adt)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn type_for_adt_recovery(
|
fn type_for_adt_cycle_result(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> {
|
||||||
db: &dyn HirDatabase,
|
|
||||||
_cycle: &salsa::Cycle,
|
|
||||||
adt: AdtId,
|
|
||||||
) -> Binders<Ty> {
|
|
||||||
let generics = generics(db, adt.into());
|
let generics = generics(db, adt.into());
|
||||||
make_binders(db, &generics, TyKind::Error.intern(Interner))
|
make_binders(db, &generics, TyKind::Error.intern(Interner))
|
||||||
}
|
}
|
||||||
|
|
@ -1449,9 +1442,8 @@ pub(crate) fn type_for_type_alias_with_diagnostics_query(
|
||||||
(make_binders(db, &generics, inner), diags)
|
(make_binders(db, &generics, inner), diags)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn type_for_type_alias_with_diagnostics_query_recover(
|
pub(crate) fn type_for_type_alias_with_diagnostics_cycle_result(
|
||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
_cycle: &salsa::Cycle,
|
|
||||||
adt: TypeAliasId,
|
adt: TypeAliasId,
|
||||||
) -> (Binders<Ty>, Diagnostics) {
|
) -> (Binders<Ty>, Diagnostics) {
|
||||||
let generics = generics(db, adt.into());
|
let generics = generics(db, adt.into());
|
||||||
|
|
@ -1555,12 +1547,11 @@ pub(crate) fn const_param_ty_with_diagnostics_query(
|
||||||
(ty, create_diagnostics(ctx.diagnostics))
|
(ty, create_diagnostics(ctx.diagnostics))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn impl_self_ty_with_diagnostics_recover(
|
pub(crate) fn impl_self_ty_with_diagnostics_cycle_result(
|
||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
_cycle: &salsa::Cycle,
|
|
||||||
impl_id: ImplId,
|
impl_id: ImplId,
|
||||||
) -> (Binders<Ty>, Diagnostics) {
|
) -> (Binders<Ty>, Diagnostics) {
|
||||||
let generics = generics(db, (impl_id).into());
|
let generics = generics(db, impl_id.into());
|
||||||
(make_binders(db, &generics, TyKind::Error.intern(Interner)), None)
|
(make_binders(db, &generics, TyKind::Error.intern(Interner)), None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,8 +41,8 @@ use rustc_hash::FxHashMap;
|
||||||
use smallvec::{SmallVec, smallvec};
|
use smallvec::{SmallVec, smallvec};
|
||||||
use stdx::{impl_from, never};
|
use stdx::{impl_from, never};
|
||||||
|
|
||||||
pub(crate) use lower::mir_body_recover;
|
pub(crate) use lower::mir_body_cycle_result;
|
||||||
pub(crate) use monomorphization::monomorphized_mir_body_recover;
|
pub(crate) use monomorphization::monomorphized_mir_body_cycle_result;
|
||||||
|
|
||||||
use super::consteval::{intern_const_scalar, try_const_usize};
|
use super::consteval::{intern_const_scalar, try_const_usize};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use std::{fmt::Write, iter, mem};
|
use std::{fmt::Write, iter, mem};
|
||||||
|
|
||||||
use base_db::{Crate, salsa::Cycle};
|
use base_db::Crate;
|
||||||
use chalk_ir::{BoundVar, ConstData, DebruijnIndex, TyKind};
|
use chalk_ir::{BoundVar, ConstData, DebruijnIndex, TyKind};
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
AdtId, DefWithBodyId, EnumVariantId, GeneralConstId, HasModule, ItemContainerId, LocalFieldId,
|
AdtId, DefWithBodyId, EnumVariantId, GeneralConstId, HasModule, ItemContainerId, LocalFieldId,
|
||||||
|
|
@ -2145,9 +2145,8 @@ pub fn mir_body_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Result<Arc<Mi
|
||||||
Ok(Arc::new(result))
|
Ok(Arc::new(result))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn mir_body_recover(
|
pub(crate) fn mir_body_cycle_result(
|
||||||
_db: &dyn HirDatabase,
|
_db: &dyn HirDatabase,
|
||||||
_cycle: &Cycle,
|
|
||||||
_def: DefWithBodyId,
|
_def: DefWithBodyId,
|
||||||
) -> Result<Arc<MirBody>> {
|
) -> Result<Arc<MirBody>> {
|
||||||
Err(MirLowerError::Loop)
|
Err(MirLowerError::Loop)
|
||||||
|
|
|
||||||
|
|
@ -313,9 +313,8 @@ pub fn monomorphized_mir_body_query(
|
||||||
Ok(Arc::new(body))
|
Ok(Arc::new(body))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn monomorphized_mir_body_recover(
|
pub(crate) fn monomorphized_mir_body_cycle_result(
|
||||||
_: &dyn HirDatabase,
|
_db: &dyn HirDatabase,
|
||||||
_: &salsa::Cycle,
|
|
||||||
_: DefWithBodyId,
|
_: DefWithBodyId,
|
||||||
_: Substitution,
|
_: Substitution,
|
||||||
_: Arc<crate::TraitEnvironment>,
|
_: Arc<crate::TraitEnvironment>,
|
||||||
|
|
|
||||||
|
|
@ -19,10 +19,10 @@ use crate::{
|
||||||
AliasTy, Const, ConstScalar, DynTyExt, GenericArg, GenericArgData, Interner, Lifetime,
|
AliasTy, Const, ConstScalar, DynTyExt, GenericArg, GenericArgData, Interner, Lifetime,
|
||||||
LifetimeData, Ty, TyKind,
|
LifetimeData, Ty, TyKind,
|
||||||
};
|
};
|
||||||
use base_db::salsa::Cycle;
|
|
||||||
use chalk_ir::Mutability;
|
use chalk_ir::Mutability;
|
||||||
use hir_def::signatures::StructFlags;
|
use hir_def::signatures::StructFlags;
|
||||||
use hir_def::{AdtId, GenericDefId, GenericParamId, VariantId};
|
use hir_def::{AdtId, GenericDefId, GenericParamId, VariantId};
|
||||||
|
use salsa::CycleRecoveryAction;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ops::Not;
|
use std::ops::Not;
|
||||||
use stdx::never;
|
use stdx::never;
|
||||||
|
|
@ -55,9 +55,17 @@ pub(crate) fn variances_of(db: &dyn HirDatabase, def: GenericDefId) -> Option<Ar
|
||||||
variances.is_empty().not().then(|| Arc::from_iter(variances))
|
variances.is_empty().not().then(|| Arc::from_iter(variances))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn variances_of_cycle(
|
pub(crate) fn variances_of_cycle_fn(
|
||||||
|
_db: &dyn HirDatabase,
|
||||||
|
result: &Option<Arc<[Variance]>>,
|
||||||
|
_count: u32,
|
||||||
|
_def: GenericDefId,
|
||||||
|
) -> CycleRecoveryAction<Option<Arc<[Variance]>>> {
|
||||||
|
CycleRecoveryAction::Fallback(result.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn variances_of_cycle_initial(
|
||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
_cycle: &Cycle,
|
|
||||||
def: GenericDefId,
|
def: GenericDefId,
|
||||||
) -> Option<Arc<[Variance]>> {
|
) -> Option<Arc<[Variance]>> {
|
||||||
let generics = generics(db, def);
|
let generics = generics(db, def);
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,13 @@ use queries::{
|
||||||
Queries, SetterKind, TrackedQuery, Transparent,
|
Queries, SetterKind, TrackedQuery, Transparent,
|
||||||
};
|
};
|
||||||
use quote::{ToTokens, format_ident, quote};
|
use quote::{ToTokens, format_ident, quote};
|
||||||
|
use syn::parse::{Parse, ParseStream};
|
||||||
|
use syn::punctuated::Punctuated;
|
||||||
use syn::spanned::Spanned;
|
use syn::spanned::Spanned;
|
||||||
use syn::visit_mut::VisitMut;
|
use syn::visit_mut::VisitMut;
|
||||||
use syn::{
|
use syn::{
|
||||||
Attribute, FnArg, ItemTrait, Path, TraitItem, TraitItemFn, parse_quote, parse_quote_spanned,
|
Attribute, FnArg, ItemTrait, Path, Token, TraitItem, TraitItemFn, parse_quote,
|
||||||
|
parse_quote_spanned,
|
||||||
};
|
};
|
||||||
|
|
||||||
mod queries;
|
mod queries;
|
||||||
|
|
@ -106,6 +109,66 @@ enum QueryKind {
|
||||||
Interned,
|
Interned,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Debug, Clone)]
|
||||||
|
struct Cycle {
|
||||||
|
cycle_fn: Option<(syn::Ident, Path)>,
|
||||||
|
cycle_initial: Option<(syn::Ident, Path)>,
|
||||||
|
cycle_result: Option<(syn::Ident, Path)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parse for Cycle {
|
||||||
|
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
|
||||||
|
let options = Punctuated::<Option, Token![,]>::parse_terminated(input)?;
|
||||||
|
let mut cycle_fn = None;
|
||||||
|
let mut cycle_initial = None;
|
||||||
|
let mut cycle_result = None;
|
||||||
|
for option in options {
|
||||||
|
let name = option.name.to_string();
|
||||||
|
match &*name {
|
||||||
|
"cycle_fn" => {
|
||||||
|
if cycle_fn.is_some() {
|
||||||
|
return Err(syn::Error::new_spanned(&option.name, "duplicate option"));
|
||||||
|
}
|
||||||
|
cycle_fn = Some((option.name, option.value));
|
||||||
|
}
|
||||||
|
"cycle_initial" => {
|
||||||
|
if cycle_initial.is_some() {
|
||||||
|
return Err(syn::Error::new_spanned(&option.name, "duplicate option"));
|
||||||
|
}
|
||||||
|
cycle_initial = Some((option.name, option.value));
|
||||||
|
}
|
||||||
|
"cycle_result" => {
|
||||||
|
if cycle_result.is_some() {
|
||||||
|
return Err(syn::Error::new_spanned(&option.name, "duplicate option"));
|
||||||
|
}
|
||||||
|
cycle_result = Some((option.name, option.value));
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return Err(syn::Error::new_spanned(
|
||||||
|
&option.name,
|
||||||
|
"unknown cycle option. Accepted values: `cycle_result`, `cycle_fn`, `cycle_initial`",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Ok(Self { cycle_fn, cycle_initial, cycle_result });
|
||||||
|
|
||||||
|
struct Option {
|
||||||
|
name: syn::Ident,
|
||||||
|
value: Path,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parse for Option {
|
||||||
|
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||||
|
let name = input.parse()?;
|
||||||
|
input.parse::<Token![=]>()?;
|
||||||
|
let value = input.parse()?;
|
||||||
|
Ok(Self { name, value })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn query_group_impl(
|
pub(crate) fn query_group_impl(
|
||||||
_args: proc_macro::TokenStream,
|
_args: proc_macro::TokenStream,
|
||||||
input: proc_macro::TokenStream,
|
input: proc_macro::TokenStream,
|
||||||
|
|
@ -155,8 +218,8 @@ pub(crate) fn query_group_impl(
|
||||||
for SalsaAttr { name, tts, span } in salsa_attrs {
|
for SalsaAttr { name, tts, span } in salsa_attrs {
|
||||||
match name.as_str() {
|
match name.as_str() {
|
||||||
"cycle" => {
|
"cycle" => {
|
||||||
let path = syn::parse::<Parenthesized<Path>>(tts)?;
|
let c = syn::parse::<Parenthesized<Cycle>>(tts)?;
|
||||||
cycle = Some(path.0.clone())
|
cycle = Some(c.0);
|
||||||
}
|
}
|
||||||
"input" => {
|
"input" => {
|
||||||
if !pat_and_tys.is_empty() {
|
if !pat_and_tys.is_empty() {
|
||||||
|
|
@ -415,7 +478,7 @@ impl<T> syn::parse::Parse for Parenthesized<T>
|
||||||
where
|
where
|
||||||
T: syn::parse::Parse,
|
T: syn::parse::Parse,
|
||||||
{
|
{
|
||||||
fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
|
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
|
||||||
let content;
|
let content;
|
||||||
syn::parenthesized!(content in input);
|
syn::parenthesized!(content in input);
|
||||||
content.parse::<T>().map(Parenthesized)
|
content.parse::<T>().map(Parenthesized)
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,15 @@
|
||||||
use quote::{ToTokens, format_ident, quote, quote_spanned};
|
use quote::{ToTokens, format_ident, quote, quote_spanned};
|
||||||
use syn::{FnArg, Ident, PatType, Path, Receiver, ReturnType, Type, parse_quote, spanned::Spanned};
|
use syn::{FnArg, Ident, PatType, Path, Receiver, ReturnType, Type, parse_quote, spanned::Spanned};
|
||||||
|
|
||||||
|
use crate::Cycle;
|
||||||
|
|
||||||
pub(crate) struct TrackedQuery {
|
pub(crate) struct TrackedQuery {
|
||||||
pub(crate) trait_name: Ident,
|
pub(crate) trait_name: Ident,
|
||||||
pub(crate) signature: syn::Signature,
|
pub(crate) signature: syn::Signature,
|
||||||
pub(crate) pat_and_tys: Vec<PatType>,
|
pub(crate) pat_and_tys: Vec<PatType>,
|
||||||
pub(crate) invoke: Option<Path>,
|
pub(crate) invoke: Option<Path>,
|
||||||
pub(crate) default: Option<syn::Block>,
|
pub(crate) default: Option<syn::Block>,
|
||||||
pub(crate) cycle: Option<Path>,
|
pub(crate) cycle: Option<Cycle>,
|
||||||
pub(crate) lru: Option<u32>,
|
pub(crate) lru: Option<u32>,
|
||||||
pub(crate) generated_struct: Option<GeneratedInputStruct>,
|
pub(crate) generated_struct: Option<GeneratedInputStruct>,
|
||||||
}
|
}
|
||||||
|
|
@ -34,12 +36,20 @@ impl ToTokens for TrackedQuery {
|
||||||
let fn_ident = &sig.ident;
|
let fn_ident = &sig.ident;
|
||||||
let shim: Ident = format_ident!("{}_shim", fn_ident);
|
let shim: Ident = format_ident!("{}_shim", fn_ident);
|
||||||
|
|
||||||
let annotation = match (self.cycle.clone(), self.lru) {
|
let options = self
|
||||||
(Some(cycle), Some(lru)) => quote!(#[salsa::tracked(lru = #lru, recovery_fn = #cycle)]),
|
.cycle
|
||||||
(Some(cycle), None) => quote!(#[salsa::tracked(recovery_fn = #cycle)]),
|
.as_ref()
|
||||||
(None, Some(lru)) => quote!(#[salsa::tracked(lru = #lru)]),
|
.map(|Cycle { cycle_fn, cycle_initial, cycle_result }| {
|
||||||
(None, None) => quote!(#[salsa::tracked]),
|
let cycle_fn = cycle_fn.as_ref().map(|(ident, path)| quote!(#ident=#path));
|
||||||
};
|
let cycle_initial =
|
||||||
|
cycle_initial.as_ref().map(|(ident, path)| quote!(#ident=#path));
|
||||||
|
let cycle_result = cycle_result.as_ref().map(|(ident, path)| quote!(#ident=#path));
|
||||||
|
let options = cycle_fn.into_iter().chain(cycle_initial).chain(cycle_result);
|
||||||
|
quote!(#(#options),*)
|
||||||
|
})
|
||||||
|
.into_iter()
|
||||||
|
.chain(self.lru.map(|lru| quote!(lru = #lru)));
|
||||||
|
let annotation = quote!(#[salsa::tracked( #(#options),* )]);
|
||||||
|
|
||||||
let pat_and_tys = &self.pat_and_tys;
|
let pat_and_tys = &self.pat_and_tys;
|
||||||
let params = self
|
let params = self
|
||||||
|
|
|
||||||
|
|
@ -1,265 +0,0 @@
|
||||||
use std::panic::UnwindSafe;
|
|
||||||
|
|
||||||
use expect_test::expect;
|
|
||||||
use query_group_macro::query_group;
|
|
||||||
use salsa::Setter;
|
|
||||||
|
|
||||||
/// The queries A, B, and C in `Database` can be configured
|
|
||||||
/// to invoke one another in arbitrary ways using this
|
|
||||||
/// enum.
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
|
||||||
enum CycleQuery {
|
|
||||||
None,
|
|
||||||
A,
|
|
||||||
B,
|
|
||||||
C,
|
|
||||||
AthenC,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[salsa::input]
|
|
||||||
struct ABC {
|
|
||||||
a: CycleQuery,
|
|
||||||
b: CycleQuery,
|
|
||||||
c: CycleQuery,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CycleQuery {
|
|
||||||
fn invoke(self, db: &dyn CycleDatabase, abc: ABC) -> Result<(), Error> {
|
|
||||||
match self {
|
|
||||||
CycleQuery::A => db.cycle_a(abc),
|
|
||||||
CycleQuery::B => db.cycle_b(abc),
|
|
||||||
CycleQuery::C => db.cycle_c(abc),
|
|
||||||
CycleQuery::AthenC => {
|
|
||||||
let _ = db.cycle_a(abc);
|
|
||||||
db.cycle_c(abc)
|
|
||||||
}
|
|
||||||
CycleQuery::None => Ok(()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[salsa::input]
|
|
||||||
struct MyInput {}
|
|
||||||
|
|
||||||
#[salsa::tracked]
|
|
||||||
fn memoized_a(db: &dyn CycleDatabase, input: MyInput) {
|
|
||||||
memoized_b(db, input)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[salsa::tracked]
|
|
||||||
fn memoized_b(db: &dyn CycleDatabase, input: MyInput) {
|
|
||||||
memoized_a(db, input)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[salsa::tracked]
|
|
||||||
fn volatile_a(db: &dyn CycleDatabase, input: MyInput) {
|
|
||||||
db.report_untracked_read();
|
|
||||||
volatile_b(db, input)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[salsa::tracked]
|
|
||||||
fn volatile_b(db: &dyn CycleDatabase, input: MyInput) {
|
|
||||||
db.report_untracked_read();
|
|
||||||
volatile_a(db, input)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[track_caller]
|
|
||||||
fn extract_cycle(f: impl FnOnce() + UnwindSafe) -> salsa::Cycle {
|
|
||||||
let v = std::panic::catch_unwind(f);
|
|
||||||
if let Err(d) = &v {
|
|
||||||
if let Some(cycle) = d.downcast_ref::<salsa::Cycle>() {
|
|
||||||
return cycle.clone();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
panic!("unexpected value: {:?}", v)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
|
|
||||||
struct Error {
|
|
||||||
cycle: Vec<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[query_group]
|
|
||||||
trait CycleDatabase: salsa::Database {
|
|
||||||
#[salsa::cycle(recover_a)]
|
|
||||||
fn cycle_a(&self, abc: ABC) -> Result<(), Error>;
|
|
||||||
|
|
||||||
#[salsa::cycle(recover_b)]
|
|
||||||
fn cycle_b(&self, abc: ABC) -> Result<(), Error>;
|
|
||||||
|
|
||||||
fn cycle_c(&self, abc: ABC) -> Result<(), Error>;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn cycle_a(db: &dyn CycleDatabase, abc: ABC) -> Result<(), Error> {
|
|
||||||
abc.a(db).invoke(db, abc)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn recover_a(_db: &dyn CycleDatabase, cycle: &salsa::Cycle, _abc: ABC) -> Result<(), Error> {
|
|
||||||
Err(Error { cycle: cycle.participant_keys().map(|k| format!("{k:?}")).collect() })
|
|
||||||
}
|
|
||||||
|
|
||||||
fn cycle_b(db: &dyn CycleDatabase, abc: ABC) -> Result<(), Error> {
|
|
||||||
abc.b(db).invoke(db, abc)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn recover_b(_db: &dyn CycleDatabase, cycle: &salsa::Cycle, _abc: ABC) -> Result<(), Error> {
|
|
||||||
Err(Error { cycle: cycle.participant_keys().map(|k| format!("{k:?}")).collect() })
|
|
||||||
}
|
|
||||||
|
|
||||||
fn cycle_c(db: &dyn CycleDatabase, abc: ABC) -> Result<(), Error> {
|
|
||||||
abc.c(db).invoke(db, abc)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn cycle_memoized() {
|
|
||||||
let db = salsa::DatabaseImpl::new();
|
|
||||||
|
|
||||||
let input = MyInput::new(&db);
|
|
||||||
let cycle = extract_cycle(|| memoized_a(&db, input));
|
|
||||||
let expected = expect![[r#"
|
|
||||||
[
|
|
||||||
DatabaseKeyIndex(
|
|
||||||
IngredientIndex(
|
|
||||||
1,
|
|
||||||
),
|
|
||||||
Id(0),
|
|
||||||
),
|
|
||||||
DatabaseKeyIndex(
|
|
||||||
IngredientIndex(
|
|
||||||
2,
|
|
||||||
),
|
|
||||||
Id(0),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
"#]];
|
|
||||||
expected.assert_debug_eq(&cycle.all_participants(&db));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn inner_cycle() {
|
|
||||||
// A --> B <-- C
|
|
||||||
// ^ |
|
|
||||||
// +-----+
|
|
||||||
let db = salsa::DatabaseImpl::new();
|
|
||||||
|
|
||||||
let abc = ABC::new(&db, CycleQuery::B, CycleQuery::A, CycleQuery::B);
|
|
||||||
let err = db.cycle_c(abc);
|
|
||||||
assert!(err.is_err());
|
|
||||||
let expected = expect![[r#"
|
|
||||||
[
|
|
||||||
"cycle_a_shim(Id(0))",
|
|
||||||
"cycle_b_shim(Id(0))",
|
|
||||||
]
|
|
||||||
"#]];
|
|
||||||
expected.assert_debug_eq(&err.unwrap_err().cycle);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn cycle_revalidate() {
|
|
||||||
// A --> B
|
|
||||||
// ^ |
|
|
||||||
// +-----+
|
|
||||||
let mut db = salsa::DatabaseImpl::new();
|
|
||||||
let abc = ABC::new(&db, CycleQuery::B, CycleQuery::A, CycleQuery::None);
|
|
||||||
assert!(db.cycle_a(abc).is_err());
|
|
||||||
abc.set_b(&mut db).to(CycleQuery::A); // same value as default
|
|
||||||
assert!(db.cycle_a(abc).is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn cycle_recovery_unchanged_twice() {
|
|
||||||
// A --> B
|
|
||||||
// ^ |
|
|
||||||
// +-----+
|
|
||||||
let mut db = salsa::DatabaseImpl::new();
|
|
||||||
let abc = ABC::new(&db, CycleQuery::B, CycleQuery::A, CycleQuery::None);
|
|
||||||
assert!(db.cycle_a(abc).is_err());
|
|
||||||
|
|
||||||
abc.set_c(&mut db).to(CycleQuery::A); // force new revision
|
|
||||||
assert!(db.cycle_a(abc).is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn cycle_appears() {
|
|
||||||
let mut db = salsa::DatabaseImpl::new();
|
|
||||||
// A --> B
|
|
||||||
let abc = ABC::new(&db, CycleQuery::B, CycleQuery::None, CycleQuery::None);
|
|
||||||
assert!(db.cycle_a(abc).is_ok());
|
|
||||||
|
|
||||||
// A --> B
|
|
||||||
// ^ |
|
|
||||||
// +-----+
|
|
||||||
abc.set_b(&mut db).to(CycleQuery::A);
|
|
||||||
assert!(db.cycle_a(abc).is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn cycle_disappears() {
|
|
||||||
let mut db = salsa::DatabaseImpl::new();
|
|
||||||
|
|
||||||
// A --> B
|
|
||||||
// ^ |
|
|
||||||
// +-----+
|
|
||||||
let abc = ABC::new(&db, CycleQuery::B, CycleQuery::A, CycleQuery::None);
|
|
||||||
assert!(db.cycle_a(abc).is_err());
|
|
||||||
|
|
||||||
// A --> B
|
|
||||||
abc.set_b(&mut db).to(CycleQuery::None);
|
|
||||||
assert!(db.cycle_a(abc).is_ok());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn cycle_multiple() {
|
|
||||||
// No matter whether we start from A or B, we get the same set of participants:
|
|
||||||
let db = salsa::DatabaseImpl::new();
|
|
||||||
|
|
||||||
// Configuration:
|
|
||||||
//
|
|
||||||
// A --> B <-- C
|
|
||||||
// ^ | ^
|
|
||||||
// +-----+ |
|
|
||||||
// | |
|
|
||||||
// +-----+
|
|
||||||
//
|
|
||||||
// Here, conceptually, B encounters a cycle with A and then
|
|
||||||
// recovers.
|
|
||||||
let abc = ABC::new(&db, CycleQuery::B, CycleQuery::AthenC, CycleQuery::A);
|
|
||||||
|
|
||||||
let c = db.cycle_c(abc);
|
|
||||||
let b = db.cycle_b(abc);
|
|
||||||
let a = db.cycle_a(abc);
|
|
||||||
let expected = expect![[r#"
|
|
||||||
(
|
|
||||||
[
|
|
||||||
"cycle_a_shim(Id(0))",
|
|
||||||
"cycle_b_shim(Id(0))",
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"cycle_a_shim(Id(0))",
|
|
||||||
"cycle_b_shim(Id(0))",
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"cycle_a_shim(Id(0))",
|
|
||||||
"cycle_b_shim(Id(0))",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
"#]];
|
|
||||||
expected.assert_debug_eq(&(c.unwrap_err().cycle, b.unwrap_err().cycle, a.unwrap_err().cycle));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn cycle_mixed_1() {
|
|
||||||
let db = salsa::DatabaseImpl::new();
|
|
||||||
// A --> B <-- C
|
|
||||||
// | ^
|
|
||||||
// +-----+
|
|
||||||
let abc = ABC::new(&db, CycleQuery::B, CycleQuery::C, CycleQuery::B);
|
|
||||||
|
|
||||||
let expected = expect![[r#"
|
|
||||||
[
|
|
||||||
"cycle_b_shim(Id(0))",
|
|
||||||
"cycle_c_shim(Id(0))",
|
|
||||||
]
|
|
||||||
"#]];
|
|
||||||
expected.assert_debug_eq(&db.cycle_c(abc).unwrap_err().cycle);
|
|
||||||
}
|
|
||||||
|
|
@ -4,7 +4,7 @@ use std::{
|
||||||
panic, thread,
|
panic, thread,
|
||||||
};
|
};
|
||||||
|
|
||||||
use ide_db::base_db::salsa::{self, Cancelled, Cycle};
|
use ide_db::base_db::salsa::{self, Cancelled};
|
||||||
use lsp_server::{ExtractError, Response, ResponseError};
|
use lsp_server::{ExtractError, Response, ResponseError};
|
||||||
use serde::{Serialize, de::DeserializeOwned};
|
use serde::{Serialize, de::DeserializeOwned};
|
||||||
use stdx::thread::ThreadIntent;
|
use stdx::thread::ThreadIntent;
|
||||||
|
|
@ -309,14 +309,12 @@ impl RequestDispatcher<'_> {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum HandlerCancelledError {
|
enum HandlerCancelledError {
|
||||||
PropagatedPanic,
|
|
||||||
Inner(salsa::Cancelled),
|
Inner(salsa::Cancelled),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::error::Error for HandlerCancelledError {
|
impl std::error::Error for HandlerCancelledError {
|
||||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||||
match self {
|
match self {
|
||||||
HandlerCancelledError::PropagatedPanic => None,
|
|
||||||
HandlerCancelledError::Inner(cancelled) => Some(cancelled),
|
HandlerCancelledError::Inner(cancelled) => Some(cancelled),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -349,9 +347,6 @@ where
|
||||||
if let Some(panic_message) = panic_message {
|
if let Some(panic_message) = panic_message {
|
||||||
message.push_str(": ");
|
message.push_str(": ");
|
||||||
message.push_str(panic_message)
|
message.push_str(panic_message)
|
||||||
} else if let Some(cycle) = panic.downcast_ref::<Cycle>() {
|
|
||||||
tracing::error!("Cycle propagated out of salsa! This is a bug: {cycle:?}");
|
|
||||||
return Err(HandlerCancelledError::PropagatedPanic);
|
|
||||||
} else if let Ok(cancelled) = panic.downcast::<Cancelled>() {
|
} else if let Ok(cancelled) = panic.downcast::<Cancelled>() {
|
||||||
tracing::error!("Cancellation propagated out of salsa! This is a bug");
|
tracing::error!("Cancellation propagated out of salsa! This is a bug");
|
||||||
return Err(HandlerCancelledError::Inner(*cancelled));
|
return Err(HandlerCancelledError::Inner(*cancelled));
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue