mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-29 10:58:02 +00:00
Switch to home-made db attaching infrastructure
Instead of using Salsa's, as we can no longer can a `dyn HirDatabase` from the `dyn salsa::Database` Salsa provides.
This commit is contained in:
parent
a7234f8b3a
commit
c6ef51e550
52 changed files with 499 additions and 418 deletions
18
Cargo.lock
generated
18
Cargo.lock
generated
|
|
@ -235,7 +235,6 @@ name = "cfg"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arbitrary",
|
"arbitrary",
|
||||||
"derive_arbitrary",
|
|
||||||
"expect-test",
|
"expect-test",
|
||||||
"intern",
|
"intern",
|
||||||
"oorandom",
|
"oorandom",
|
||||||
|
|
@ -1615,7 +1614,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "54acf3a685220b533e437e264e4d932cfbdc4cc7ec0cd232ed73c08d03b8a7ca"
|
checksum = "54acf3a685220b533e437e264e4d932cfbdc4cc7ec0cd232ed73c08d03b8a7ca"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fixedbitset",
|
"fixedbitset",
|
||||||
"hashbrown 0.15.4",
|
"hashbrown 0.15.5",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -2145,8 +2144,9 @@ checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "salsa"
|
name = "salsa"
|
||||||
version = "0.23.0"
|
version = "0.24.0"
|
||||||
source = "git+https://github.com/salsa-rs/salsa.git?rev=e257df12eabd566825ba53bb12d782560b9a4dcd#e257df12eabd566825ba53bb12d782560b9a4dcd"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "27956164373aeec733ac24ff1736de8541234e3a8e7e6f916b28175b5752af3b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"boxcar",
|
"boxcar",
|
||||||
"crossbeam-queue",
|
"crossbeam-queue",
|
||||||
|
|
@ -2169,13 +2169,15 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "salsa-macro-rules"
|
name = "salsa-macro-rules"
|
||||||
version = "0.23.0"
|
version = "0.24.0"
|
||||||
source = "git+https://github.com/salsa-rs/salsa.git?rev=e257df12eabd566825ba53bb12d782560b9a4dcd#e257df12eabd566825ba53bb12d782560b9a4dcd"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6ca3b9d6e47c08b5de4b218e0c5f7ec910b51bce6314e651c8e7b9d154d174da"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "salsa-macros"
|
name = "salsa-macros"
|
||||||
version = "0.23.0"
|
version = "0.24.0"
|
||||||
source = "git+https://github.com/salsa-rs/salsa.git?rev=e257df12eabd566825ba53bb12d782560b9a4dcd#e257df12eabd566825ba53bb12d782560b9a4dcd"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6337b62f2968be6b8afa30017d7564ecbde6832ada47ed2261fb14d0fd402ff4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|
|
||||||
|
|
@ -137,13 +137,12 @@ rayon = "1.10.0"
|
||||||
rowan = "=0.15.15"
|
rowan = "=0.15.15"
|
||||||
# Ideally we'd not enable the macros feature but unfortunately the `tracked` attribute does not work
|
# Ideally we'd not enable the macros feature but unfortunately the `tracked` attribute does not work
|
||||||
# on impls without it
|
# on impls without it
|
||||||
salsa = { git = "https://github.com/salsa-rs/salsa.git", rev = "e257df12eabd566825ba53bb12d782560b9a4dcd", default-features = true, features = [
|
salsa = { version = "0.24.0", default-features = true, features = [
|
||||||
"rayon",
|
"rayon",
|
||||||
"salsa_unstable",
|
"salsa_unstable",
|
||||||
"macros",
|
"macros",
|
||||||
] }
|
] }
|
||||||
# salsa-macros = "0.23.0"
|
salsa-macros = "0.24.0"
|
||||||
salsa-macros = { git = "https://github.com/salsa-rs/salsa.git", rev = "e257df12eabd566825ba53bb12d782560b9a4dcd" }
|
|
||||||
semver = "1.0.26"
|
semver = "1.0.26"
|
||||||
serde = { version = "1.0.219" }
|
serde = { version = "1.0.219" }
|
||||||
serde_derive = { version = "1.0.219" }
|
serde_derive = { version = "1.0.219" }
|
||||||
|
|
|
||||||
|
|
@ -23,11 +23,7 @@ intern.workspace = true
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
expect-test = "1.5.1"
|
expect-test = "1.5.1"
|
||||||
oorandom = "11.1.5"
|
oorandom = "11.1.5"
|
||||||
# We depend on both individually instead of using `features = ["derive"]` to microoptimize the
|
arbitrary = { version = "1.4.1", features = ["derive"] }
|
||||||
# build graph: if the feature was enabled, syn would be built early on in the graph if `smolstr`
|
|
||||||
# supports `arbitrary`. This way, we avoid feature unification.
|
|
||||||
arbitrary = "1.4.1"
|
|
||||||
derive_arbitrary = "1.4.1"
|
|
||||||
|
|
||||||
# local deps
|
# local deps
|
||||||
syntax-bridge.workspace = true
|
syntax-bridge.workspace = true
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ impl fmt::Display for CfgAtom {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
#[cfg_attr(test, derive(derive_arbitrary::Arbitrary))]
|
#[cfg_attr(test, derive(arbitrary::Arbitrary))]
|
||||||
pub enum CfgExpr {
|
pub enum CfgExpr {
|
||||||
Invalid,
|
Invalid,
|
||||||
Atom(CfgAtom),
|
Atom(CfgAtom),
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
//! Database used for testing `hir_def`.
|
//! Database used for testing `hir_def`.
|
||||||
|
|
||||||
use salsa::database::AsDynDatabase;
|
|
||||||
use std::{fmt, panic, sync::Mutex};
|
use std::{fmt, panic, sync::Mutex};
|
||||||
|
|
||||||
use base_db::{
|
use base_db::{
|
||||||
|
|
@ -8,7 +7,7 @@ use base_db::{
|
||||||
SourceDatabase, SourceRoot, SourceRootId, SourceRootInput,
|
SourceDatabase, SourceRoot, SourceRootId, SourceRootInput,
|
||||||
};
|
};
|
||||||
use hir_expand::{InFile, files::FilePosition};
|
use hir_expand::{InFile, files::FilePosition};
|
||||||
use salsa::{Durability, database::AsDynDatabase};
|
use salsa::Durability;
|
||||||
use span::FileId;
|
use span::FileId;
|
||||||
use syntax::{AstNode, algo, ast};
|
use syntax::{AstNode, algo, ast};
|
||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
|
|
@ -304,8 +303,7 @@ impl TestDB {
|
||||||
// This is pretty horrible, but `Debug` is the only way to inspect
|
// This is pretty horrible, but `Debug` is the only way to inspect
|
||||||
// QueryDescriptor at the moment.
|
// QueryDescriptor at the moment.
|
||||||
salsa::EventKind::WillExecute { database_key } => {
|
salsa::EventKind::WillExecute { database_key } => {
|
||||||
let ingredient = self
|
let ingredient = (self as &dyn salsa::Database)
|
||||||
.as_dyn_database()
|
|
||||||
.ingredient_debug_name(database_key.ingredient_index());
|
.ingredient_debug_name(database_key.ingredient_index());
|
||||||
Some(ingredient.to_string())
|
Some(ingredient.to_string())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ fn check_fail(
|
||||||
error: impl FnOnce(ConstEvalError<'_>) -> bool,
|
error: impl FnOnce(ConstEvalError<'_>) -> bool,
|
||||||
) {
|
) {
|
||||||
let (db, file_id) = TestDB::with_single_file(ra_fixture);
|
let (db, file_id) = TestDB::with_single_file(ra_fixture);
|
||||||
salsa::attach(&db, || match eval_goal(&db, file_id) {
|
crate::attach_db(&db, || match eval_goal(&db, file_id) {
|
||||||
Ok(_) => panic!("Expected fail, but it succeeded"),
|
Ok(_) => panic!("Expected fail, but it succeeded"),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
assert!(error(simplify(e.clone())), "Actual error was: {}", pretty_print_err(e, &db))
|
assert!(error(simplify(e.clone())), "Actual error was: {}", pretty_print_err(e, &db))
|
||||||
|
|
@ -79,7 +79,7 @@ fn check_answer(
|
||||||
check: impl FnOnce(&[u8], &MemoryMap<'_>),
|
check: impl FnOnce(&[u8], &MemoryMap<'_>),
|
||||||
) {
|
) {
|
||||||
let (db, file_ids) = TestDB::with_many_files(ra_fixture);
|
let (db, file_ids) = TestDB::with_many_files(ra_fixture);
|
||||||
salsa::attach(&db, || {
|
crate::attach_db(&db, || {
|
||||||
let file_id = *file_ids.last().unwrap();
|
let file_id = *file_ids.last().unwrap();
|
||||||
let r = match eval_goal(&db, file_id) {
|
let r = match eval_goal(&db, file_id) {
|
||||||
Ok(t) => t,
|
Ok(t) => t,
|
||||||
|
|
@ -2506,8 +2506,10 @@ fn enums() {
|
||||||
const GOAL: E = E::A;
|
const GOAL: E = E::A;
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
|
crate::attach_db(&db, || {
|
||||||
let r = eval_goal(&db, file_id).unwrap();
|
let r = eval_goal(&db, file_id).unwrap();
|
||||||
assert_eq!(try_const_usize(&db, &r), Some(1));
|
assert_eq!(try_const_usize(&db, &r), Some(1));
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ fn check_dyn_compatibility<'a>(
|
||||||
};
|
};
|
||||||
let mut osvs = FxHashSet::default();
|
let mut osvs = FxHashSet::default();
|
||||||
let db = &db;
|
let db = &db;
|
||||||
salsa::attach(db, || {
|
crate::attach_db(db, || {
|
||||||
_ = dyn_compatibility_with_callback(db, trait_id, &mut |osv| {
|
_ = dyn_compatibility_with_callback(db, trait_id, &mut |osv| {
|
||||||
osvs.insert(match osv {
|
osvs.insert(match osv {
|
||||||
DynCompatibilityViolation::SizedSelf => SizedSelf,
|
DynCompatibilityViolation::SizedSelf => SizedSelf,
|
||||||
|
|
|
||||||
|
|
@ -400,7 +400,7 @@ fn pointer_kind<'db>(
|
||||||
Ok(Some(PointerKind::Thin))
|
Ok(Some(PointerKind::Thin))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TyKind::Tuple(subst) => match subst.iter().last() {
|
TyKind::Tuple(subst) => match subst.iter().next_back() {
|
||||||
None => Ok(Some(PointerKind::Thin)),
|
None => Ok(Some(PointerKind::Thin)),
|
||||||
Some(ty) => pointer_kind(ty, ctx),
|
Some(ty) => pointer_kind(ty, ctx),
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -385,7 +385,7 @@ fn struct_tail_erasing_lifetimes<'a>(db: &'a dyn HirDatabase, pointee: Ty<'a>) -
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TyKind::Tuple(tys) => {
|
TyKind::Tuple(tys) => {
|
||||||
if let Some(last_field_ty) = tys.iter().last() {
|
if let Some(last_field_ty) = tys.iter().next_back() {
|
||||||
struct_tail_erasing_lifetimes(db, last_field_ty)
|
struct_tail_erasing_lifetimes(db, last_field_ty)
|
||||||
} else {
|
} else {
|
||||||
pointee
|
pointee
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ fn eval_goal(
|
||||||
Some(adt_or_type_alias_id)
|
Some(adt_or_type_alias_id)
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
salsa::attach(&db, || {
|
crate::attach_db(&db, || {
|
||||||
let interner = DbInterner::new_with(&db, None, None);
|
let interner = DbInterner::new_with(&db, None, None);
|
||||||
let goal_ty = match adt_or_type_alias_id {
|
let goal_ty = match adt_or_type_alias_id {
|
||||||
Either::Left(adt_id) => crate::next_solver::Ty::new_adt(
|
Either::Left(adt_id) => crate::next_solver::Ty::new_adt(
|
||||||
|
|
@ -112,6 +112,7 @@ fn eval_expr(
|
||||||
);
|
);
|
||||||
|
|
||||||
let (db, file_id) = TestDB::with_single_file(&ra_fixture);
|
let (db, file_id) = TestDB::with_single_file(&ra_fixture);
|
||||||
|
crate::attach_db(&db, || {
|
||||||
let module_id = db.module_for_file(file_id.file_id(&db));
|
let module_id = db.module_for_file(file_id.file_id(&db));
|
||||||
let def_map = module_id.def_map(&db);
|
let def_map = module_id.def_map(&db);
|
||||||
let scope = &def_map[module_id.local_id].scope;
|
let scope = &def_map[module_id.local_id].scope;
|
||||||
|
|
@ -119,8 +120,11 @@ fn eval_expr(
|
||||||
.declarations()
|
.declarations()
|
||||||
.find_map(|x| match x {
|
.find_map(|x| match x {
|
||||||
hir_def::ModuleDefId::FunctionId(x) => {
|
hir_def::ModuleDefId::FunctionId(x) => {
|
||||||
let name =
|
let name = db
|
||||||
db.function_signature(x).name.display_no_db(file_id.edition(&db)).to_smolstr();
|
.function_signature(x)
|
||||||
|
.name
|
||||||
|
.display_no_db(file_id.edition(&db))
|
||||||
|
.to_smolstr();
|
||||||
(name == "main").then_some(x)
|
(name == "main").then_some(x)
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
|
|
@ -134,7 +138,8 @@ fn eval_expr(
|
||||||
.0;
|
.0;
|
||||||
let infer = db.infer(function_id.into());
|
let infer = db.infer(function_id.into());
|
||||||
let goal_ty = infer.type_of_binding[b];
|
let goal_ty = infer.type_of_binding[b];
|
||||||
salsa::attach(&db, || db.layout_of_ty(goal_ty, db.trait_environment(function_id.into())))
|
db.layout_of_ty(goal_ty, db.trait_environment(function_id.into()))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,7 @@ pub use mapping::{
|
||||||
to_foreign_def_id, to_placeholder_idx, to_placeholder_idx_no_index,
|
to_foreign_def_id, to_placeholder_idx, to_placeholder_idx_no_index,
|
||||||
};
|
};
|
||||||
pub use method_resolution::check_orphan_rules;
|
pub use method_resolution::check_orphan_rules;
|
||||||
|
pub use next_solver::interner::{attach_db, attach_db_allow_change, with_attached_db};
|
||||||
pub use target_feature::TargetFeatures;
|
pub use target_feature::TargetFeatures;
|
||||||
pub use traits::TraitEnvironment;
|
pub use traits::TraitEnvironment;
|
||||||
pub use utils::{
|
pub use utils::{
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ use crate::{
|
||||||
use super::{MirEvalError, interpret_mir};
|
use super::{MirEvalError, interpret_mir};
|
||||||
|
|
||||||
fn eval_main(db: &TestDB, file_id: EditionedFileId) -> Result<(String, String), MirEvalError<'_>> {
|
fn eval_main(db: &TestDB, file_id: EditionedFileId) -> Result<(String, String), MirEvalError<'_>> {
|
||||||
salsa::attach(db, || {
|
crate::attach_db(db, || {
|
||||||
let module_id = db.module_for_file(file_id.file_id(db));
|
let module_id = db.module_for_file(file_id.file_id(db));
|
||||||
let def_map = module_id.def_map(db);
|
let def_map = module_id.def_map(db);
|
||||||
let scope = &def_map[module_id.local_id].scope;
|
let scope = &def_map[module_id.local_id].scope;
|
||||||
|
|
@ -56,7 +56,7 @@ fn check_pass_and_stdio(
|
||||||
) {
|
) {
|
||||||
let _tracing = setup_tracing();
|
let _tracing = setup_tracing();
|
||||||
let (db, file_ids) = TestDB::with_many_files(ra_fixture);
|
let (db, file_ids) = TestDB::with_many_files(ra_fixture);
|
||||||
salsa::attach(&db, || {
|
crate::attach_db(&db, || {
|
||||||
let file_id = *file_ids.last().unwrap();
|
let file_id = *file_ids.last().unwrap();
|
||||||
let x = eval_main(&db, file_id);
|
let x = eval_main(&db, file_id);
|
||||||
match x {
|
match x {
|
||||||
|
|
@ -102,7 +102,7 @@ fn check_pass_and_stdio(
|
||||||
|
|
||||||
fn check_panic(#[rust_analyzer::rust_fixture] ra_fixture: &str, expected_panic: &str) {
|
fn check_panic(#[rust_analyzer::rust_fixture] ra_fixture: &str, expected_panic: &str) {
|
||||||
let (db, file_ids) = TestDB::with_many_files(ra_fixture);
|
let (db, file_ids) = TestDB::with_many_files(ra_fixture);
|
||||||
salsa::attach(&db, || {
|
crate::attach_db(&db, || {
|
||||||
let file_id = *file_ids.last().unwrap();
|
let file_id = *file_ids.last().unwrap();
|
||||||
let e = eval_main(&db, file_id).unwrap_err();
|
let e = eval_main(&db, file_id).unwrap_err();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
@ -117,7 +117,7 @@ fn check_error_with(
|
||||||
expect_err: impl FnOnce(MirEvalError<'_>) -> bool,
|
expect_err: impl FnOnce(MirEvalError<'_>) -> bool,
|
||||||
) {
|
) {
|
||||||
let (db, file_ids) = TestDB::with_many_files(ra_fixture);
|
let (db, file_ids) = TestDB::with_many_files(ra_fixture);
|
||||||
salsa::attach(&db, || {
|
crate::attach_db(&db, || {
|
||||||
let file_id = *file_ids.last().unwrap();
|
let file_id = *file_ids.last().unwrap();
|
||||||
let e = eval_main(&db, file_id).unwrap_err();
|
let e = eval_main(&db, file_id).unwrap_err();
|
||||||
assert!(expect_err(e));
|
assert!(expect_err(e));
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ fn lower_mir(
|
||||||
) -> FxHashMap<String, Result<Arc<MirBody>, ()>> {
|
) -> FxHashMap<String, Result<Arc<MirBody>, ()>> {
|
||||||
let _tracing = setup_tracing();
|
let _tracing = setup_tracing();
|
||||||
let (db, file_ids) = TestDB::with_many_files(ra_fixture);
|
let (db, file_ids) = TestDB::with_many_files(ra_fixture);
|
||||||
|
crate::attach_db(&db, || {
|
||||||
let file_id = *file_ids.last().unwrap();
|
let file_id = *file_ids.last().unwrap();
|
||||||
let module_id = db.module_for_file(file_id.file_id(&db));
|
let module_id = db.module_for_file(file_id.file_id(&db));
|
||||||
let def_map = module_id.def_map(&db);
|
let def_map = module_id.def_map(&db);
|
||||||
|
|
@ -21,11 +22,13 @@ fn lower_mir(
|
||||||
});
|
});
|
||||||
funcs
|
funcs
|
||||||
.map(|func| {
|
.map(|func| {
|
||||||
let name = db.function_signature(func).name.display(&db, Edition::CURRENT).to_string();
|
let name =
|
||||||
|
db.function_signature(func).name.display(&db, Edition::CURRENT).to_string();
|
||||||
let mir = db.mir_body(func.into());
|
let mir = db.mir_body(func.into());
|
||||||
(name, mir.map_err(drop))
|
(name, mir.map_err(drop))
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -41,13 +41,12 @@ impl<'db> Const<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inner(&self) -> &WithCachedTypeInfo<ConstKind<'db>> {
|
pub fn inner(&self) -> &WithCachedTypeInfo<ConstKind<'db>> {
|
||||||
salsa::with_attached_database(|db| {
|
crate::with_attached_db(|db| {
|
||||||
let inner = &self.kind_(db).0;
|
let inner = &self.kind_(db).0;
|
||||||
// SAFETY: The caller already has access to a `Const<'db>`, so borrowchecking will
|
// SAFETY: The caller already has access to a `Const<'db>`, so borrowchecking will
|
||||||
// make sure that our returned value is valid for the lifetime `'db`.
|
// make sure that our returned value is valid for the lifetime `'db`.
|
||||||
unsafe { std::mem::transmute(inner) }
|
unsafe { std::mem::transmute(inner) }
|
||||||
})
|
})
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn error(interner: DbInterner<'db>) -> Self {
|
pub fn error(interner: DbInterner<'db>) -> Self {
|
||||||
|
|
@ -197,21 +196,19 @@ pub struct Valtree<'db> {
|
||||||
|
|
||||||
impl<'db> Valtree<'db> {
|
impl<'db> Valtree<'db> {
|
||||||
pub fn new(bytes: ConstBytes<'db>) -> Self {
|
pub fn new(bytes: ConstBytes<'db>) -> Self {
|
||||||
salsa::with_attached_database(|db| unsafe {
|
crate::with_attached_db(|db| unsafe {
|
||||||
// SAFETY: ¯\_(ツ)_/¯
|
// SAFETY: ¯\_(ツ)_/¯
|
||||||
std::mem::transmute(Valtree::new_(db, bytes))
|
std::mem::transmute(Valtree::new_(db, bytes))
|
||||||
})
|
})
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inner(&self) -> &ConstBytes<'db> {
|
pub fn inner(&self) -> &ConstBytes<'db> {
|
||||||
salsa::with_attached_database(|db| {
|
crate::with_attached_db(|db| {
|
||||||
let inner = self.bytes_(db);
|
let inner = self.bytes_(db);
|
||||||
// SAFETY: The caller already has access to a `Valtree<'db>`, so borrowchecking will
|
// SAFETY: The caller already has access to a `Valtree<'db>`, so borrowchecking will
|
||||||
// make sure that our returned value is valid for the lifetime `'db`.
|
// make sure that our returned value is valid for the lifetime `'db`.
|
||||||
unsafe { std::mem::transmute(inner) }
|
unsafe { std::mem::transmute(inner) }
|
||||||
})
|
})
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
//! Things related to the Interner in the next-trait-solver.
|
//! Things related to the Interner in the next-trait-solver.
|
||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
|
|
||||||
|
pub use tls_db::{attach_db, attach_db_allow_change, with_attached_db};
|
||||||
|
|
||||||
use base_db::Crate;
|
use base_db::Crate;
|
||||||
use chalk_ir::{ProgramClauseImplication, SeparatorTraitRef, Variances};
|
use chalk_ir::{ProgramClauseImplication, SeparatorTraitRef, Variances};
|
||||||
use hir_def::lang_item::LangItem;
|
use hir_def::lang_item::LangItem;
|
||||||
|
|
@ -127,11 +129,10 @@ macro_rules! _interned_vec_nolifetime_salsa {
|
||||||
|
|
||||||
pub fn inner(&self) -> &smallvec::SmallVec<[$ty; 2]> {
|
pub fn inner(&self) -> &smallvec::SmallVec<[$ty; 2]> {
|
||||||
// SAFETY: ¯\_(ツ)_/¯
|
// SAFETY: ¯\_(ツ)_/¯
|
||||||
salsa::with_attached_database(|db| {
|
$crate::with_attached_db(|db| {
|
||||||
let inner = self.inner_(db);
|
let inner = self.inner_(db);
|
||||||
unsafe { std::mem::transmute(inner) }
|
unsafe { std::mem::transmute(inner) }
|
||||||
})
|
})
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -230,11 +231,10 @@ macro_rules! _interned_vec_db {
|
||||||
|
|
||||||
pub fn inner(&self) -> &smallvec::SmallVec<[$ty<'db>; 2]> {
|
pub fn inner(&self) -> &smallvec::SmallVec<[$ty<'db>; 2]> {
|
||||||
// SAFETY: ¯\_(ツ)_/¯
|
// SAFETY: ¯\_(ツ)_/¯
|
||||||
salsa::with_attached_database(|db| {
|
$crate::with_attached_db(|db| {
|
||||||
let inner = self.inner_(db);
|
let inner = self.inner_(db);
|
||||||
unsafe { std::mem::transmute(inner) }
|
unsafe { std::mem::transmute(inner) }
|
||||||
})
|
})
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -285,12 +285,11 @@ unsafe impl Sync for DbInterner<'_> {}
|
||||||
impl<'db> DbInterner<'db> {
|
impl<'db> DbInterner<'db> {
|
||||||
// FIXME(next-solver): remove this method
|
// FIXME(next-solver): remove this method
|
||||||
pub fn conjure() -> DbInterner<'db> {
|
pub fn conjure() -> DbInterner<'db> {
|
||||||
salsa::with_attached_database(|db| DbInterner {
|
crate::with_attached_db(|db| DbInterner {
|
||||||
db: unsafe { std::mem::transmute::<&dyn salsa::Database, &'db dyn HirDatabase>(db) },
|
db: unsafe { std::mem::transmute::<&dyn HirDatabase, &'db dyn HirDatabase>(db) },
|
||||||
krate: None,
|
krate: None,
|
||||||
block: None,
|
block: None,
|
||||||
})
|
})
|
||||||
.expect("db is expected to be attached")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_with(
|
pub fn new_with(
|
||||||
|
|
@ -583,12 +582,11 @@ impl AdtDef {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inner(&self) -> &AdtDefInner {
|
pub fn inner(&self) -> &AdtDefInner {
|
||||||
salsa::with_attached_database(|db| {
|
crate::with_attached_db(|db| {
|
||||||
let inner = self.data_(db);
|
let inner = self.data_(db);
|
||||||
// SAFETY: ¯\_(ツ)_/¯
|
// SAFETY: ¯\_(ツ)_/¯
|
||||||
unsafe { std::mem::transmute(inner) }
|
unsafe { std::mem::transmute(inner) }
|
||||||
})
|
})
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_enum(&self) -> bool {
|
pub fn is_enum(&self) -> bool {
|
||||||
|
|
@ -706,21 +704,20 @@ impl<'db> inherent::AdtDef<DbInterner<'db>> for AdtDef {
|
||||||
|
|
||||||
impl fmt::Debug for AdtDef {
|
impl fmt::Debug for AdtDef {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
salsa::with_attached_database(|db| match self.inner().id {
|
crate::with_attached_db(|db| match self.inner().id {
|
||||||
AdtId::StructId(struct_id) => {
|
AdtId::StructId(struct_id) => {
|
||||||
let data = db.as_view::<dyn HirDatabase>().struct_signature(struct_id);
|
let data = db.struct_signature(struct_id);
|
||||||
f.write_str(data.name.as_str())
|
f.write_str(data.name.as_str())
|
||||||
}
|
}
|
||||||
AdtId::UnionId(union_id) => {
|
AdtId::UnionId(union_id) => {
|
||||||
let data = db.as_view::<dyn HirDatabase>().union_signature(union_id);
|
let data = db.union_signature(union_id);
|
||||||
f.write_str(data.name.as_str())
|
f.write_str(data.name.as_str())
|
||||||
}
|
}
|
||||||
AdtId::EnumId(enum_id) => {
|
AdtId::EnumId(enum_id) => {
|
||||||
let data = db.as_view::<dyn HirDatabase>().enum_signature(enum_id);
|
let data = db.enum_signature(enum_id);
|
||||||
f.write_str(data.name.as_str())
|
f.write_str(data.name.as_str())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|| f.write_str(&format!("AdtDef({:?})", self.inner().id)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -776,13 +773,12 @@ impl<'db> Pattern<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inner(&self) -> &PatternKind<'db> {
|
pub fn inner(&self) -> &PatternKind<'db> {
|
||||||
salsa::with_attached_database(|db| {
|
crate::with_attached_db(|db| {
|
||||||
let inner = &self.kind_(db).0;
|
let inner = &self.kind_(db).0;
|
||||||
// SAFETY: The caller already has access to a `Ty<'db>`, so borrowchecking will
|
// SAFETY: The caller already has access to a `Ty<'db>`, so borrowchecking will
|
||||||
// make sure that our returned value is valid for the lifetime `'db`.
|
// make sure that our returned value is valid for the lifetime `'db`.
|
||||||
unsafe { std::mem::transmute(inner) }
|
unsafe { std::mem::transmute(inner) }
|
||||||
})
|
})
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1018,17 +1014,7 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
|
||||||
self,
|
self,
|
||||||
f: impl FnOnce(&mut rustc_type_ir::search_graph::GlobalCache<Self>) -> R,
|
f: impl FnOnce(&mut rustc_type_ir::search_graph::GlobalCache<Self>) -> R,
|
||||||
) -> R {
|
) -> R {
|
||||||
salsa::with_attached_database(|db| {
|
tls_cache::with_cache(self.db, f)
|
||||||
tls_cache::with_cache(
|
|
||||||
unsafe {
|
|
||||||
std::mem::transmute::<&dyn HirDatabase, &'db dyn HirDatabase>(
|
|
||||||
db.as_view::<dyn HirDatabase>(),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
f,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn canonical_param_env_cache_get_or_insert<R>(
|
fn canonical_param_env_cache_get_or_insert<R>(
|
||||||
|
|
@ -2104,6 +2090,117 @@ TrivialTypeTraversalImpls! {
|
||||||
Placeholder<BoundVar>,
|
Placeholder<BoundVar>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod tls_db {
|
||||||
|
use std::{cell::Cell, ptr::NonNull};
|
||||||
|
|
||||||
|
use crate::db::HirDatabase;
|
||||||
|
|
||||||
|
struct Attached {
|
||||||
|
database: Cell<Option<NonNull<dyn HirDatabase>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Attached {
|
||||||
|
#[inline]
|
||||||
|
fn attach<R>(&self, db: &dyn HirDatabase, op: impl FnOnce() -> R) -> R {
|
||||||
|
struct DbGuard<'s> {
|
||||||
|
state: Option<&'s Attached>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'s> DbGuard<'s> {
|
||||||
|
#[inline]
|
||||||
|
fn new(attached: &'s Attached, db: &dyn HirDatabase) -> Self {
|
||||||
|
match attached.database.get() {
|
||||||
|
Some(current_db) => {
|
||||||
|
let new_db = NonNull::from(db);
|
||||||
|
if !std::ptr::addr_eq(current_db.as_ptr(), new_db.as_ptr()) {
|
||||||
|
panic!(
|
||||||
|
"Cannot change attached database. This is likely a bug.\n\
|
||||||
|
If this is not a bug, you can use `attach_db_allow_change()`."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Self { state: None }
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
// Otherwise, set the database.
|
||||||
|
attached.database.set(Some(NonNull::from(db)));
|
||||||
|
Self { state: Some(attached) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for DbGuard<'_> {
|
||||||
|
#[inline]
|
||||||
|
fn drop(&mut self) {
|
||||||
|
// Reset database to null if we did anything in `DbGuard::new`.
|
||||||
|
if let Some(attached) = self.state {
|
||||||
|
attached.database.set(None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let _guard = DbGuard::new(self, db);
|
||||||
|
op()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn attach_allow_change<R>(&self, db: &dyn HirDatabase, op: impl FnOnce() -> R) -> R {
|
||||||
|
struct DbGuard<'s> {
|
||||||
|
state: &'s Attached,
|
||||||
|
prev: Option<NonNull<dyn HirDatabase>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'s> DbGuard<'s> {
|
||||||
|
#[inline]
|
||||||
|
fn new(attached: &'s Attached, db: &dyn HirDatabase) -> Self {
|
||||||
|
let prev = attached.database.replace(Some(NonNull::from(db)));
|
||||||
|
Self { state: attached, prev }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for DbGuard<'_> {
|
||||||
|
#[inline]
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.state.database.set(self.prev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let _guard = DbGuard::new(self, db);
|
||||||
|
op()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn with<R>(&self, op: impl FnOnce(&dyn HirDatabase) -> R) -> R {
|
||||||
|
let db = self.database.get().expect("Try to use attached db, but not db is attached");
|
||||||
|
|
||||||
|
// SAFETY: The db is attached, so it must be valid.
|
||||||
|
op(unsafe { db.as_ref() })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
thread_local! {
|
||||||
|
static GLOBAL_DB: Attached = const { Attached { database: Cell::new(None) } };
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn attach_db<R>(db: &dyn HirDatabase, op: impl FnOnce() -> R) -> R {
|
||||||
|
GLOBAL_DB.with(|global_db| global_db.attach(db, op))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn attach_db_allow_change<R>(db: &dyn HirDatabase, op: impl FnOnce() -> R) -> R {
|
||||||
|
GLOBAL_DB.with(|global_db| global_db.attach_allow_change(db, op))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn with_attached_db<R>(op: impl FnOnce(&dyn HirDatabase) -> R) -> R {
|
||||||
|
GLOBAL_DB.with(
|
||||||
|
#[inline]
|
||||||
|
|a| a.with(op),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mod tls_cache {
|
mod tls_cache {
|
||||||
use crate::db::HirDatabase;
|
use crate::db::HirDatabase;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,10 @@ impl<'db> IrPrint<ty::AliasTy<Self>> for DbInterner<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_debug(t: &ty::AliasTy<Self>, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn print_debug(t: &ty::AliasTy<Self>, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
salsa::with_attached_database(|db| match t.def_id {
|
crate::with_attached_db(|db| match t.def_id {
|
||||||
SolverDefId::TypeAliasId(id) => fmt.write_str(&format!(
|
SolverDefId::TypeAliasId(id) => fmt.write_str(&format!(
|
||||||
"AliasTy({:?}[{:?}])",
|
"AliasTy({:?}[{:?}])",
|
||||||
db.as_view::<dyn HirDatabase>().type_alias_signature(id).name.as_str(),
|
db.type_alias_signature(id).name.as_str(),
|
||||||
t.args
|
t.args
|
||||||
)),
|
)),
|
||||||
SolverDefId::InternedOpaqueTyId(id) => {
|
SolverDefId::InternedOpaqueTyId(id) => {
|
||||||
|
|
@ -27,7 +27,6 @@ impl<'db> IrPrint<ty::AliasTy<Self>> for DbInterner<'db> {
|
||||||
}
|
}
|
||||||
_ => panic!("Expected TypeAlias or OpaqueTy."),
|
_ => panic!("Expected TypeAlias or OpaqueTy."),
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|| fmt.write_str(&format!("AliasTy({:?}[{:?}])", t.def_id, t.args)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -37,10 +36,10 @@ impl<'db> IrPrint<ty::AliasTerm<Self>> for DbInterner<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_debug(t: &ty::AliasTerm<Self>, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn print_debug(t: &ty::AliasTerm<Self>, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
salsa::with_attached_database(|db| match t.def_id {
|
crate::with_attached_db(|db| match t.def_id {
|
||||||
SolverDefId::TypeAliasId(id) => fmt.write_str(&format!(
|
SolverDefId::TypeAliasId(id) => fmt.write_str(&format!(
|
||||||
"AliasTerm({:?}[{:?}])",
|
"AliasTerm({:?}[{:?}])",
|
||||||
db.as_view::<dyn HirDatabase>().type_alias_signature(id).name.as_str(),
|
db.type_alias_signature(id).name.as_str(),
|
||||||
t.args
|
t.args
|
||||||
)),
|
)),
|
||||||
SolverDefId::InternedOpaqueTyId(id) => {
|
SolverDefId::InternedOpaqueTyId(id) => {
|
||||||
|
|
@ -48,7 +47,6 @@ impl<'db> IrPrint<ty::AliasTerm<Self>> for DbInterner<'db> {
|
||||||
}
|
}
|
||||||
_ => panic!("Expected TypeAlias or OpaqueTy."),
|
_ => panic!("Expected TypeAlias or OpaqueTy."),
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|| fmt.write_str(&format!("AliasTerm({:?}[{:?}])", t.def_id, t.args)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'db> IrPrint<ty::TraitRef<Self>> for DbInterner<'db> {
|
impl<'db> IrPrint<ty::TraitRef<Self>> for DbInterner<'db> {
|
||||||
|
|
@ -57,29 +55,25 @@ impl<'db> IrPrint<ty::TraitRef<Self>> for DbInterner<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_debug(t: &ty::TraitRef<Self>, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn print_debug(t: &ty::TraitRef<Self>, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
salsa::with_attached_database(|db| {
|
crate::with_attached_db(|db| {
|
||||||
let trait_ = t.def_id.0;
|
let trait_ = t.def_id.0;
|
||||||
let self_ty = &t.args.as_slice()[0];
|
let self_ty = &t.args.as_slice()[0];
|
||||||
let trait_args = &t.args.as_slice()[1..];
|
let trait_args = &t.args.as_slice()[1..];
|
||||||
if trait_args.is_empty() {
|
if trait_args.is_empty() {
|
||||||
let db = db.zalsa().views().downcaster_for::<dyn HirDatabase>();
|
|
||||||
db.downcast_unchecked(db)
|
|
||||||
fmt.write_str(&format!(
|
fmt.write_str(&format!(
|
||||||
"{:?}: {}",
|
"{:?}: {}",
|
||||||
self_ty,
|
self_ty,
|
||||||
db.as_dyn_database().as_dyn_database(),
|
db.trait_signature(trait_).name.as_str()
|
||||||
db.as_view::<dyn HirDatabase>().trait_signature(trait_).name.as_str()
|
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
fmt.write_str(&format!(
|
fmt.write_str(&format!(
|
||||||
"{:?}: {}<{:?}>",
|
"{:?}: {}<{:?}>",
|
||||||
self_ty,
|
self_ty,
|
||||||
db.as_view::<dyn HirDatabase>().trait_signature(trait_).name.as_str(),
|
db.trait_signature(trait_).name.as_str(),
|
||||||
trait_args
|
trait_args
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|| fmt.write_str(&format!("TraitRef({:?}[{:?}])", t.def_id, t.args)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'db> IrPrint<ty::TraitPredicate<Self>> for DbInterner<'db> {
|
impl<'db> IrPrint<ty::TraitPredicate<Self>> for DbInterner<'db> {
|
||||||
|
|
@ -121,17 +115,14 @@ impl<'db> IrPrint<ty::ExistentialTraitRef<Self>> for DbInterner<'db> {
|
||||||
t: &ty::ExistentialTraitRef<Self>,
|
t: &ty::ExistentialTraitRef<Self>,
|
||||||
fmt: &mut std::fmt::Formatter<'_>,
|
fmt: &mut std::fmt::Formatter<'_>,
|
||||||
) -> std::fmt::Result {
|
) -> std::fmt::Result {
|
||||||
salsa::with_attached_database(|db| {
|
crate::with_attached_db(|db| {
|
||||||
let trait_ = t.def_id.0;
|
let trait_ = t.def_id.0;
|
||||||
fmt.write_str(&format!(
|
fmt.write_str(&format!(
|
||||||
"ExistentialTraitRef({:?}[{:?}])",
|
"ExistentialTraitRef({:?}[{:?}])",
|
||||||
db.as_view::<dyn HirDatabase>().trait_signature(trait_).name.as_str(),
|
db.trait_signature(trait_).name.as_str(),
|
||||||
t.args
|
t.args
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|| {
|
|
||||||
fmt.write_str(&format!("ExistentialTraitRef({:?}[{:?}])", t.def_id, t.args))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'db> IrPrint<ty::ExistentialProjection<Self>> for DbInterner<'db> {
|
impl<'db> IrPrint<ty::ExistentialProjection<Self>> for DbInterner<'db> {
|
||||||
|
|
@ -146,24 +137,18 @@ impl<'db> IrPrint<ty::ExistentialProjection<Self>> for DbInterner<'db> {
|
||||||
t: &ty::ExistentialProjection<Self>,
|
t: &ty::ExistentialProjection<Self>,
|
||||||
fmt: &mut std::fmt::Formatter<'_>,
|
fmt: &mut std::fmt::Formatter<'_>,
|
||||||
) -> std::fmt::Result {
|
) -> std::fmt::Result {
|
||||||
salsa::with_attached_database(|db| {
|
crate::with_attached_db(|db| {
|
||||||
let id = match t.def_id {
|
let id = match t.def_id {
|
||||||
SolverDefId::TypeAliasId(id) => id,
|
SolverDefId::TypeAliasId(id) => id,
|
||||||
_ => panic!("Expected trait."),
|
_ => panic!("Expected trait."),
|
||||||
};
|
};
|
||||||
fmt.write_str(&format!(
|
fmt.write_str(&format!(
|
||||||
"ExistentialProjection(({:?}[{:?}]) -> {:?})",
|
"ExistentialProjection(({:?}[{:?}]) -> {:?})",
|
||||||
db.as_view::<dyn HirDatabase>().type_alias_signature(id).name.as_str(),
|
db.type_alias_signature(id).name.as_str(),
|
||||||
t.args,
|
t.args,
|
||||||
t.term
|
t.term
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|| {
|
|
||||||
fmt.write_str(&format!(
|
|
||||||
"ExistentialProjection(({:?}[{:?}]) -> {:?})",
|
|
||||||
t.def_id, t.args, t.term
|
|
||||||
))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'db> IrPrint<ty::ProjectionPredicate<Self>> for DbInterner<'db> {
|
impl<'db> IrPrint<ty::ProjectionPredicate<Self>> for DbInterner<'db> {
|
||||||
|
|
@ -178,24 +163,18 @@ impl<'db> IrPrint<ty::ProjectionPredicate<Self>> for DbInterner<'db> {
|
||||||
t: &ty::ProjectionPredicate<Self>,
|
t: &ty::ProjectionPredicate<Self>,
|
||||||
fmt: &mut std::fmt::Formatter<'_>,
|
fmt: &mut std::fmt::Formatter<'_>,
|
||||||
) -> std::fmt::Result {
|
) -> std::fmt::Result {
|
||||||
salsa::with_attached_database(|db| {
|
crate::with_attached_db(|db| {
|
||||||
let id = match t.projection_term.def_id {
|
let id = match t.projection_term.def_id {
|
||||||
SolverDefId::TypeAliasId(id) => id,
|
SolverDefId::TypeAliasId(id) => id,
|
||||||
_ => panic!("Expected trait."),
|
_ => panic!("Expected trait."),
|
||||||
};
|
};
|
||||||
fmt.write_str(&format!(
|
fmt.write_str(&format!(
|
||||||
"ProjectionPredicate(({:?}[{:?}]) -> {:?})",
|
"ProjectionPredicate(({:?}[{:?}]) -> {:?})",
|
||||||
db.as_view::<dyn HirDatabase>().type_alias_signature(id).name.as_str(),
|
db.type_alias_signature(id).name.as_str(),
|
||||||
t.projection_term.args,
|
t.projection_term.args,
|
||||||
t.term
|
t.term
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|| {
|
|
||||||
fmt.write_str(&format!(
|
|
||||||
"ProjectionPredicate(({:?}[{:?}]) -> {:?})",
|
|
||||||
t.projection_term.def_id, t.projection_term.args, t.term
|
|
||||||
))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'db> IrPrint<ty::NormalizesTo<Self>> for DbInterner<'db> {
|
impl<'db> IrPrint<ty::NormalizesTo<Self>> for DbInterner<'db> {
|
||||||
|
|
|
||||||
|
|
@ -24,12 +24,11 @@ impl<'db> PredefinedOpaques<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inner(&self) -> &PredefinedOpaquesData<'db> {
|
pub fn inner(&self) -> &PredefinedOpaquesData<'db> {
|
||||||
salsa::with_attached_database(|db| {
|
crate::with_attached_db(|db| {
|
||||||
let inner = self.kind_(db);
|
let inner = self.kind_(db);
|
||||||
// SAFETY: ¯\_(ツ)_/¯
|
// SAFETY: ¯\_(ツ)_/¯
|
||||||
unsafe { std::mem::transmute(inner) }
|
unsafe { std::mem::transmute(inner) }
|
||||||
})
|
})
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -96,12 +95,11 @@ impl<'db> ExternalConstraints<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inner(&self) -> &ExternalConstraintsData<'db> {
|
pub fn inner(&self) -> &ExternalConstraintsData<'db> {
|
||||||
salsa::with_attached_database(|db| {
|
crate::with_attached_db(|db| {
|
||||||
let inner = self.kind_(db);
|
let inner = self.kind_(db);
|
||||||
// SAFETY: ¯\_(ツ)_/¯
|
// SAFETY: ¯\_(ツ)_/¯
|
||||||
unsafe { std::mem::transmute(inner) }
|
unsafe { std::mem::transmute(inner) }
|
||||||
})
|
})
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -232,13 +232,12 @@ impl<'db> Predicate<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inner(&self) -> &WithCachedTypeInfo<Binder<'db, PredicateKind<'db>>> {
|
pub fn inner(&self) -> &WithCachedTypeInfo<Binder<'db, PredicateKind<'db>>> {
|
||||||
salsa::with_attached_database(|db| {
|
crate::with_attached_db(|db| {
|
||||||
let inner = &self.kind_(db).0;
|
let inner = &self.kind_(db).0;
|
||||||
// SAFETY: The caller already has access to a `Predicate<'db>`, so borrowchecking will
|
// SAFETY: The caller already has access to a `Predicate<'db>`, so borrowchecking will
|
||||||
// make sure that our returned value is valid for the lifetime `'db`.
|
// make sure that our returned value is valid for the lifetime `'db`.
|
||||||
unsafe { std::mem::transmute(inner) }
|
unsafe { std::mem::transmute(inner) }
|
||||||
})
|
})
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Flips the polarity of a Predicate.
|
/// Flips the polarity of a Predicate.
|
||||||
|
|
@ -303,13 +302,12 @@ impl<'db> Clauses<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inner(&self) -> &InternedClausesWrapper<'db> {
|
pub fn inner(&self) -> &InternedClausesWrapper<'db> {
|
||||||
salsa::with_attached_database(|db| {
|
crate::with_attached_db(|db| {
|
||||||
let inner = self.inner_(db);
|
let inner = self.inner_(db);
|
||||||
// SAFETY: The caller already has access to a `Clauses<'db>`, so borrowchecking will
|
// SAFETY: The caller already has access to a `Clauses<'db>`, so borrowchecking will
|
||||||
// make sure that our returned value is valid for the lifetime `'db`.
|
// make sure that our returned value is valid for the lifetime `'db`.
|
||||||
unsafe { std::mem::transmute(inner) }
|
unsafe { std::mem::transmute(inner) }
|
||||||
})
|
})
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,13 +35,12 @@ impl<'db> Region<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inner(&self) -> &RegionKind<'db> {
|
pub fn inner(&self) -> &RegionKind<'db> {
|
||||||
salsa::with_attached_database(|db| {
|
crate::with_attached_db(|db| {
|
||||||
let inner = self.kind_(db);
|
let inner = self.kind_(db);
|
||||||
// SAFETY: The caller already has access to a `Region<'db>`, so borrowchecking will
|
// SAFETY: The caller already has access to a `Region<'db>`, so borrowchecking will
|
||||||
// make sure that our returned value is valid for the lifetime `'db`.
|
// make sure that our returned value is valid for the lifetime `'db`.
|
||||||
unsafe { std::mem::transmute::<&RegionKind<'_>, &RegionKind<'db>>(inner) }
|
unsafe { std::mem::transmute::<&RegionKind<'_>, &RegionKind<'db>>(inner) }
|
||||||
})
|
})
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_early_param(
|
pub fn new_early_param(
|
||||||
|
|
|
||||||
|
|
@ -68,13 +68,12 @@ impl<'db> Ty<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inner(&self) -> &WithCachedTypeInfo<TyKind<'db>> {
|
pub fn inner(&self) -> &WithCachedTypeInfo<TyKind<'db>> {
|
||||||
salsa::with_attached_database(|db| {
|
crate::with_attached_db(|db| {
|
||||||
let inner = &self.kind_(db).0;
|
let inner = &self.kind_(db).0;
|
||||||
// SAFETY: The caller already has access to a `Ty<'db>`, so borrowchecking will
|
// SAFETY: The caller already has access to a `Ty<'db>`, so borrowchecking will
|
||||||
// make sure that our returned value is valid for the lifetime `'db`.
|
// make sure that our returned value is valid for the lifetime `'db`.
|
||||||
unsafe { std::mem::transmute(inner) }
|
unsafe { std::mem::transmute(inner) }
|
||||||
})
|
})
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_adt(interner: DbInterner<'db>, adt_id: AdtId, args: GenericArgs<'db>) -> Self {
|
pub fn new_adt(interner: DbInterner<'db>, adt_id: AdtId, args: GenericArgs<'db>) -> Self {
|
||||||
|
|
|
||||||
|
|
@ -486,7 +486,7 @@ pub fn sizedness_constraint_for_ty<'db>(
|
||||||
|
|
||||||
Tuple(tys) => tys
|
Tuple(tys) => tys
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.last()
|
.next_back()
|
||||||
.and_then(|ty| sizedness_constraint_for_ty(interner, sizedness, ty)),
|
.and_then(|ty| sizedness_constraint_for_ty(interner, sizedness, ty)),
|
||||||
|
|
||||||
Adt(adt, args) => {
|
Adt(adt, args) => {
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ use base_db::{
|
||||||
use hir_def::{ModuleId, db::DefDatabase, nameres::crate_def_map};
|
use hir_def::{ModuleId, db::DefDatabase, nameres::crate_def_map};
|
||||||
use hir_expand::EditionedFileId;
|
use hir_expand::EditionedFileId;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use salsa::{AsDynDatabase, Durability};
|
use salsa::Durability;
|
||||||
use span::FileId;
|
use span::FileId;
|
||||||
use syntax::TextRange;
|
use syntax::TextRange;
|
||||||
use test_utils::extract_annotations;
|
use test_utils::extract_annotations;
|
||||||
|
|
@ -191,8 +191,7 @@ impl TestDB {
|
||||||
// This is pretty horrible, but `Debug` is the only way to inspect
|
// This is pretty horrible, but `Debug` is the only way to inspect
|
||||||
// QueryDescriptor at the moment.
|
// QueryDescriptor at the moment.
|
||||||
salsa::EventKind::WillExecute { database_key } => {
|
salsa::EventKind::WillExecute { database_key } => {
|
||||||
let ingredient = self
|
let ingredient = (self as &dyn salsa::Database)
|
||||||
.as_dyn_database()
|
|
||||||
.ingredient_debug_name(database_key.ingredient_index());
|
.ingredient_debug_name(database_key.ingredient_index());
|
||||||
Some(ingredient.to_string())
|
Some(ingredient.to_string())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ fn check_impl(
|
||||||
let _tracing = setup_tracing();
|
let _tracing = setup_tracing();
|
||||||
let (db, files) = TestDB::with_many_files(ra_fixture);
|
let (db, files) = TestDB::with_many_files(ra_fixture);
|
||||||
|
|
||||||
salsa::attach(&db, || {
|
crate::attach_db(&db, || {
|
||||||
let mut had_annotations = false;
|
let mut had_annotations = false;
|
||||||
let mut mismatches = FxHashMap::default();
|
let mut mismatches = FxHashMap::default();
|
||||||
let mut types = FxHashMap::default();
|
let mut types = FxHashMap::default();
|
||||||
|
|
@ -283,7 +283,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
|
||||||
let _tracing = setup_tracing();
|
let _tracing = setup_tracing();
|
||||||
let (db, file_id) = TestDB::with_single_file(content);
|
let (db, file_id) = TestDB::with_single_file(content);
|
||||||
|
|
||||||
salsa::attach(&db, || {
|
crate::attach_db(&db, || {
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
|
|
||||||
let mut infer_def = |inference_result: Arc<InferenceResult<'_>>,
|
let mut infer_def = |inference_result: Arc<InferenceResult<'_>>,
|
||||||
|
|
@ -558,6 +558,7 @@ fn salsa_bug() {
|
||||||
",
|
",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
crate::attach_db(&db, || {
|
||||||
let module = db.module_for_file(pos.file_id.file_id(&db));
|
let module = db.module_for_file(pos.file_id.file_id(&db));
|
||||||
let crate_def_map = module.def_map(&db);
|
let crate_def_map = module.def_map(&db);
|
||||||
visit_module(&db, crate_def_map, module.local_id, &mut |def| {
|
visit_module(&db, crate_def_map, module.local_id, &mut |def| {
|
||||||
|
|
@ -569,6 +570,7 @@ fn salsa_bug() {
|
||||||
_ => return,
|
_ => return,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
let new_text = "
|
let new_text = "
|
||||||
//- /lib.rs
|
//- /lib.rs
|
||||||
|
|
@ -597,6 +599,7 @@ fn salsa_bug() {
|
||||||
|
|
||||||
db.set_file_text(pos.file_id.file_id(&db), new_text);
|
db.set_file_text(pos.file_id.file_id(&db), new_text);
|
||||||
|
|
||||||
|
crate::attach_db(&db, || {
|
||||||
let module = db.module_for_file(pos.file_id.file_id(&db));
|
let module = db.module_for_file(pos.file_id.file_id(&db));
|
||||||
let crate_def_map = module.def_map(&db);
|
let crate_def_map = module.def_map(&db);
|
||||||
visit_module(&db, crate_def_map, module.local_id, &mut |def| {
|
visit_module(&db, crate_def_map, module.local_id, &mut |def| {
|
||||||
|
|
@ -608,4 +611,5 @@ fn salsa_bug() {
|
||||||
_ => return,
|
_ => return,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ use super::{setup_tracing, visit_module};
|
||||||
fn check_closure_captures(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
|
fn check_closure_captures(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
|
||||||
let _tracing = setup_tracing();
|
let _tracing = setup_tracing();
|
||||||
let (db, file_id) = TestDB::with_single_file(ra_fixture);
|
let (db, file_id) = TestDB::with_single_file(ra_fixture);
|
||||||
|
crate::attach_db(&db, || {
|
||||||
let module = db.module_for_file(file_id.file_id(&db));
|
let module = db.module_for_file(file_id.file_id(&db));
|
||||||
let def_map = module.def_map(&db);
|
let def_map = module.def_map(&db);
|
||||||
|
|
||||||
|
|
@ -35,7 +36,8 @@ fn check_closure_captures(#[rust_analyzer::rust_fixture] ra_fixture: &str, expec
|
||||||
};
|
};
|
||||||
let infer = db.infer(def);
|
let infer = db.infer(def);
|
||||||
let db = &db;
|
let db = &db;
|
||||||
captures_info.extend(infer.closure_info.iter().flat_map(|(closure_id, (captures, _))| {
|
captures_info.extend(infer.closure_info.iter().flat_map(
|
||||||
|
|(closure_id, (captures, _))| {
|
||||||
let closure = db.lookup_intern_closure(*closure_id);
|
let closure = db.lookup_intern_closure(*closure_id);
|
||||||
let source_map = db.body_with_source_map(closure.0).1;
|
let source_map = db.body_with_source_map(closure.0).1;
|
||||||
let closure_text_range = source_map
|
let closure_text_range = source_map
|
||||||
|
|
@ -54,7 +56,8 @@ fn check_closure_captures(#[rust_analyzer::rust_fixture] ra_fixture: &str, expec
|
||||||
|
|
||||||
// FIXME: Deduplicate this with hir::Local::sources().
|
// FIXME: Deduplicate this with hir::Local::sources().
|
||||||
let (body, source_map) = db.body_with_source_map(closure.0);
|
let (body, source_map) = db.body_with_source_map(closure.0);
|
||||||
let local_text_range = match body.self_param.zip(source_map.self_param_syntax()) {
|
let local_text_range =
|
||||||
|
match body.self_param.zip(source_map.self_param_syntax()) {
|
||||||
Some((param, source)) if param == capture.local() => {
|
Some((param, source)) if param == capture.local() => {
|
||||||
format!("{:?}", text_range(db, source))
|
format!("{:?}", text_range(db, source))
|
||||||
}
|
}
|
||||||
|
|
@ -68,13 +71,11 @@ fn check_closure_captures(#[rust_analyzer::rust_fixture] ra_fixture: &str, expec
|
||||||
.join(", "),
|
.join(", "),
|
||||||
};
|
};
|
||||||
let place = capture.display_place(closure.0, db);
|
let place = capture.display_place(closure.0, db);
|
||||||
let capture_ty = salsa::attach(db, || {
|
let capture_ty = capture
|
||||||
capture
|
|
||||||
.ty
|
.ty
|
||||||
.skip_binder()
|
.skip_binder()
|
||||||
.display_test(db, DisplayTarget::from_crate(db, module.krate()))
|
.display_test(db, DisplayTarget::from_crate(db, module.krate()))
|
||||||
.to_string()
|
.to_string();
|
||||||
});
|
|
||||||
let spans = capture
|
let spans = capture
|
||||||
.spans()
|
.spans()
|
||||||
.iter()
|
.iter()
|
||||||
|
|
@ -99,9 +100,17 @@ fn check_closure_captures(#[rust_analyzer::rust_fixture] ra_fixture: &str, expec
|
||||||
.map(|it| format!("{it:?}"))
|
.map(|it| format!("{it:?}"))
|
||||||
.join(",");
|
.join(",");
|
||||||
|
|
||||||
(closure_text_range, local_text_range, spans, place, capture_ty, capture.kind())
|
(
|
||||||
|
closure_text_range,
|
||||||
|
local_text_range,
|
||||||
|
spans,
|
||||||
|
place,
|
||||||
|
capture_ty,
|
||||||
|
capture.kind(),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
}));
|
},
|
||||||
|
));
|
||||||
}
|
}
|
||||||
captures_info.sort_unstable_by_key(|(closure_text_range, local_text_range, ..)| {
|
captures_info.sort_unstable_by_key(|(closure_text_range, local_text_range, ..)| {
|
||||||
(closure_text_range.start(), local_text_range.clone())
|
(closure_text_range.start(), local_text_range.clone())
|
||||||
|
|
@ -117,6 +126,7 @@ fn check_closure_captures(#[rust_analyzer::rust_fixture] ra_fixture: &str, expec
|
||||||
.join("\n");
|
.join("\n");
|
||||||
|
|
||||||
expect.assert_eq(&rendered);
|
expect.assert_eq(&rendered);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -710,8 +710,8 @@ fn execute_assert_events(
|
||||||
required: &[(&str, usize)],
|
required: &[(&str, usize)],
|
||||||
expect: Expect,
|
expect: Expect,
|
||||||
) {
|
) {
|
||||||
|
crate::attach_db(db, || {
|
||||||
let (executed, events) = db.log_executed(f);
|
let (executed, events) = db.log_executed(f);
|
||||||
salsa::attach(db, || {
|
|
||||||
for (event, count) in required {
|
for (event, count) in required {
|
||||||
let n = executed.iter().filter(|it| it.contains(event)).count();
|
let n = executed.iter().filter(|it| it.contains(event)).count();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
|
||||||
|
|
@ -1001,6 +1001,7 @@ struct FixedPoint<T, U, V>(&'static FixedPoint<(), T, U>, V);
|
||||||
// ));
|
// ));
|
||||||
let (db, file_id) = TestDB::with_single_file(ra_fixture);
|
let (db, file_id) = TestDB::with_single_file(ra_fixture);
|
||||||
|
|
||||||
|
crate::attach_db(&db, || {
|
||||||
let mut defs: Vec<GenericDefId> = Vec::new();
|
let mut defs: Vec<GenericDefId> = Vec::new();
|
||||||
let module = db.module_for_file_opt(file_id.file_id(&db)).unwrap();
|
let module = db.module_for_file_opt(file_id.file_id(&db)).unwrap();
|
||||||
let def_map = module.def_map(&db);
|
let def_map = module.def_map(&db);
|
||||||
|
|
@ -1080,5 +1081,6 @@ struct FixedPoint<T, U, V>(&'static FixedPoint<(), T, U>, V);
|
||||||
}
|
}
|
||||||
|
|
||||||
expected.assert_eq(&res);
|
expected.assert_eq(&res);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -157,7 +157,7 @@ pub use {
|
||||||
tt,
|
tt,
|
||||||
},
|
},
|
||||||
hir_ty::{
|
hir_ty::{
|
||||||
CastError, DropGlue, FnAbi, PointerCast, Variance,
|
CastError, DropGlue, FnAbi, PointerCast, Variance, attach_db, attach_db_allow_change,
|
||||||
consteval::ConstEvalError,
|
consteval::ConstEvalError,
|
||||||
diagnostics::UnsafetyReason,
|
diagnostics::UnsafetyReason,
|
||||||
display::{ClosureStyle, DisplayTarget, HirDisplay, HirDisplayError, HirWrite},
|
display::{ClosureStyle, DisplayTarget, HirDisplay, HirDisplayError, HirWrite},
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@ use crate::{
|
||||||
db::HirDatabase,
|
db::HirDatabase,
|
||||||
semantics::{PathResolution, PathResolutionPerNs},
|
semantics::{PathResolution, PathResolutionPerNs},
|
||||||
};
|
};
|
||||||
use base_db::salsa;
|
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
AdtId, AssocItemId, CallableDefId, ConstId, DefWithBodyId, FieldId, FunctionId, GenericDefId,
|
AdtId, AssocItemId, CallableDefId, ConstId, DefWithBodyId, FieldId, FunctionId, GenericDefId,
|
||||||
|
|
@ -1637,7 +1636,7 @@ fn resolve_hir_path_(
|
||||||
Some(unresolved) => resolver
|
Some(unresolved) => resolver
|
||||||
.generic_def()
|
.generic_def()
|
||||||
.and_then(|def| {
|
.and_then(|def| {
|
||||||
salsa::attach(db, || {
|
hir_ty::attach_db(db, || {
|
||||||
hir_ty::associated_type_shorthand_candidates(
|
hir_ty::associated_type_shorthand_candidates(
|
||||||
db,
|
db,
|
||||||
def,
|
def,
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ use hir::{Semantics, db::HirDatabase, setup_tracing};
|
||||||
use ide_db::{
|
use ide_db::{
|
||||||
EditionedFileId, FileRange, RootDatabase, SnippetCap,
|
EditionedFileId, FileRange, RootDatabase, SnippetCap,
|
||||||
assists::ExprFillDefaultMode,
|
assists::ExprFillDefaultMode,
|
||||||
base_db::{SourceDatabase, salsa},
|
base_db::SourceDatabase,
|
||||||
imports::insert_use::{ImportGranularity, InsertUseConfig},
|
imports::insert_use::{ImportGranularity, InsertUseConfig},
|
||||||
source_change::FileSystemEdit,
|
source_change::FileSystemEdit,
|
||||||
};
|
};
|
||||||
|
|
@ -109,7 +109,7 @@ fn assists(
|
||||||
resolve: AssistResolveStrategy,
|
resolve: AssistResolveStrategy,
|
||||||
range: ide_db::FileRange,
|
range: ide_db::FileRange,
|
||||||
) -> Vec<Assist> {
|
) -> Vec<Assist> {
|
||||||
salsa::attach(db, || {
|
hir::attach_db(db, || {
|
||||||
HirDatabase::zalsa_register_downcaster(db);
|
HirDatabase::zalsa_register_downcaster(db);
|
||||||
crate::assists(db, config, resolve, range)
|
crate::assists(db, config, resolve, range)
|
||||||
})
|
})
|
||||||
|
|
@ -332,7 +332,7 @@ fn check_with_config(
|
||||||
_ => AssistResolveStrategy::All,
|
_ => AssistResolveStrategy::All,
|
||||||
};
|
};
|
||||||
let mut acc = Assists::new(&ctx, resolve);
|
let mut acc = Assists::new(&ctx, resolve);
|
||||||
salsa::attach(&db, || {
|
hir::attach_db(&db, || {
|
||||||
HirDatabase::zalsa_register_downcaster(&db);
|
HirDatabase::zalsa_register_downcaster(&db);
|
||||||
handler(&mut acc, &ctx);
|
handler(&mut acc, &ctx);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
//! Module responsible for analyzing the code surrounding the cursor for completion.
|
//! Module responsible for analyzing the code surrounding the cursor for completion.
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
use base_db::salsa;
|
|
||||||
use hir::{ExpandResult, InFile, Semantics, Type, TypeInfo, Variant};
|
use hir::{ExpandResult, InFile, Semantics, Type, TypeInfo, Variant};
|
||||||
use ide_db::{RootDatabase, active_parameter::ActiveParameter};
|
use ide_db::{RootDatabase, active_parameter::ActiveParameter};
|
||||||
use itertools::Either;
|
use itertools::Either;
|
||||||
|
|
@ -86,7 +85,7 @@ pub(super) fn expand_and_analyze<'db>(
|
||||||
let original_offset = expansion.original_offset + relative_offset;
|
let original_offset = expansion.original_offset + relative_offset;
|
||||||
let token = expansion.original_file.token_at_offset(original_offset).left_biased()?;
|
let token = expansion.original_file.token_at_offset(original_offset).left_biased()?;
|
||||||
|
|
||||||
salsa::attach(sema.db, || analyze(sema, expansion, original_token, &token)).map(
|
hir::attach_db(sema.db, || analyze(sema, expansion, original_token, &token)).map(
|
||||||
|(analysis, expected, qualifier_ctx)| AnalysisResult {
|
|(analysis, expected, qualifier_ctx)| AnalysisResult {
|
||||||
analysis,
|
analysis,
|
||||||
expected,
|
expected,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
use base_db::salsa;
|
|
||||||
use expect_test::{Expect, expect};
|
use expect_test::{Expect, expect};
|
||||||
use hir::HirDisplay;
|
use hir::HirDisplay;
|
||||||
|
|
||||||
|
|
@ -11,12 +10,12 @@ fn check_expected_type_and_name(#[rust_analyzer::rust_fixture] ra_fixture: &str,
|
||||||
let (db, pos) = position(ra_fixture);
|
let (db, pos) = position(ra_fixture);
|
||||||
let config = TEST_CONFIG;
|
let config = TEST_CONFIG;
|
||||||
let (completion_context, _analysis) =
|
let (completion_context, _analysis) =
|
||||||
salsa::attach(&db, || CompletionContext::new(&db, pos, &config).unwrap());
|
hir::attach_db(&db, || CompletionContext::new(&db, pos, &config).unwrap());
|
||||||
|
|
||||||
let ty = completion_context
|
let ty = completion_context
|
||||||
.expected_type
|
.expected_type
|
||||||
.map(|t| {
|
.map(|t| {
|
||||||
salsa::attach(&db, || {
|
hir::attach_db(&db, || {
|
||||||
t.display_test(&db, completion_context.krate.to_display_target(&db)).to_string()
|
t.display_test(&db, completion_context.krate.to_display_target(&db)).to_string()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ mod type_pos;
|
||||||
mod use_tree;
|
mod use_tree;
|
||||||
mod visibility;
|
mod visibility;
|
||||||
|
|
||||||
use base_db::{SourceDatabase, salsa};
|
use base_db::SourceDatabase;
|
||||||
use expect_test::Expect;
|
use expect_test::Expect;
|
||||||
use hir::db::HirDatabase;
|
use hir::db::HirDatabase;
|
||||||
use hir::{PrefixKind, setup_tracing};
|
use hir::{PrefixKind, setup_tracing};
|
||||||
|
|
@ -244,7 +244,7 @@ pub(crate) fn check_edit_with_config(
|
||||||
let ra_fixture_after = trim_indent(ra_fixture_after);
|
let ra_fixture_after = trim_indent(ra_fixture_after);
|
||||||
let (db, position) = position(ra_fixture_before);
|
let (db, position) = position(ra_fixture_before);
|
||||||
let completions: Vec<CompletionItem> =
|
let completions: Vec<CompletionItem> =
|
||||||
salsa::attach(&db, || crate::completions(&db, &config, position, None).unwrap());
|
hir::attach_db(&db, || crate::completions(&db, &config, position, None).unwrap());
|
||||||
let (completion,) = completions
|
let (completion,) = completions
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|it| it.lookup() == what)
|
.filter(|it| it.lookup() == what)
|
||||||
|
|
@ -307,7 +307,7 @@ pub(crate) fn get_all_items(
|
||||||
trigger_character: Option<char>,
|
trigger_character: Option<char>,
|
||||||
) -> Vec<CompletionItem> {
|
) -> Vec<CompletionItem> {
|
||||||
let (db, position) = position(code);
|
let (db, position) = position(code);
|
||||||
let res = salsa::attach(&db, || {
|
let res = hir::attach_db(&db, || {
|
||||||
HirDatabase::zalsa_register_downcaster(&db);
|
HirDatabase::zalsa_register_downcaster(&db);
|
||||||
crate::completions(&db, &config, position, trigger_character)
|
crate::completions(&db, &config, position, trigger_character)
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
use base_db::salsa;
|
|
||||||
use expect_test::{Expect, expect};
|
use expect_test::{Expect, expect};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
@ -20,7 +19,7 @@ fn check_with_config(
|
||||||
let (ctx, analysis) = crate::context::CompletionContext::new(&db, position, &config).unwrap();
|
let (ctx, analysis) = crate::context::CompletionContext::new(&db, position, &config).unwrap();
|
||||||
|
|
||||||
let mut acc = crate::completions::Completions::default();
|
let mut acc = crate::completions::Completions::default();
|
||||||
salsa::attach(ctx.db, || {
|
hir::attach_db(ctx.db, || {
|
||||||
if let CompletionAnalysis::Name(NameContext { kind: NameKind::IdentPat(pat_ctx), .. }) =
|
if let CompletionAnalysis::Name(NameContext { kind: NameKind::IdentPat(pat_ctx), .. }) =
|
||||||
&analysis
|
&analysis
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -134,7 +134,7 @@ fn library_symbols(db: &dyn SymbolsDatabase, source_root_id: SourceRootId) -> Ar
|
||||||
let _p = tracing::info_span!("library_symbols").entered();
|
let _p = tracing::info_span!("library_symbols").entered();
|
||||||
|
|
||||||
// We call this without attaching because this runs in parallel, so we need to attach here.
|
// We call this without attaching because this runs in parallel, so we need to attach here.
|
||||||
salsa::attach(db, || {
|
hir::attach_db(db, || {
|
||||||
let mut symbol_collector = SymbolCollector::new(db);
|
let mut symbol_collector = SymbolCollector::new(db);
|
||||||
|
|
||||||
db.source_root_crates(source_root_id)
|
db.source_root_crates(source_root_id)
|
||||||
|
|
@ -153,7 +153,7 @@ fn module_symbols(db: &dyn SymbolsDatabase, module: Module) -> Arc<SymbolIndex>
|
||||||
let _p = tracing::info_span!("module_symbols").entered();
|
let _p = tracing::info_span!("module_symbols").entered();
|
||||||
|
|
||||||
// We call this without attaching because this runs in parallel, so we need to attach here.
|
// We call this without attaching because this runs in parallel, so we need to attach here.
|
||||||
salsa::attach(db, || Arc::new(SymbolIndex::new(SymbolCollector::new_module(db, module))))
|
hir::attach_db(db, || Arc::new(SymbolIndex::new(SymbolCollector::new_module(db, module))))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn crate_symbols(db: &dyn SymbolsDatabase, krate: Crate) -> Box<[Arc<SymbolIndex>]> {
|
pub fn crate_symbols(db: &dyn SymbolsDatabase, krate: Crate) -> Box<[Arc<SymbolIndex>]> {
|
||||||
|
|
|
||||||
|
|
@ -473,7 +473,7 @@ mod tests {
|
||||||
frange.range,
|
frange.range,
|
||||||
"selection is not an expression(yet contained in one)"
|
"selection is not an expression(yet contained in one)"
|
||||||
);
|
);
|
||||||
let name = salsa::attach(sema.db, || NameGenerator::default().for_variable(&expr, &sema));
|
let name = hir::attach_db(sema.db, || NameGenerator::default().for_variable(&expr, &sema));
|
||||||
assert_eq!(&name, expected);
|
assert_eq!(&name, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ use hir::setup_tracing;
|
||||||
use ide_db::{
|
use ide_db::{
|
||||||
LineIndexDatabase, RootDatabase,
|
LineIndexDatabase, RootDatabase,
|
||||||
assists::{AssistResolveStrategy, ExprFillDefaultMode},
|
assists::{AssistResolveStrategy, ExprFillDefaultMode},
|
||||||
base_db::{SourceDatabase, salsa},
|
base_db::SourceDatabase,
|
||||||
};
|
};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use stdx::trim_indent;
|
use stdx::trim_indent;
|
||||||
|
|
@ -74,7 +74,7 @@ fn check_nth_fix_with_config(
|
||||||
let after = trim_indent(ra_fixture_after);
|
let after = trim_indent(ra_fixture_after);
|
||||||
|
|
||||||
let (db, file_position) = RootDatabase::with_position(ra_fixture_before);
|
let (db, file_position) = RootDatabase::with_position(ra_fixture_before);
|
||||||
let diagnostic = salsa::attach(&db, || {
|
let diagnostic = hir::attach_db(&db, || {
|
||||||
super::full_diagnostics(
|
super::full_diagnostics(
|
||||||
&db,
|
&db,
|
||||||
&config,
|
&config,
|
||||||
|
|
@ -129,7 +129,7 @@ pub(crate) fn check_has_fix(
|
||||||
let (db, file_position) = RootDatabase::with_position(ra_fixture_before);
|
let (db, file_position) = RootDatabase::with_position(ra_fixture_before);
|
||||||
let mut conf = DiagnosticsConfig::test_sample();
|
let mut conf = DiagnosticsConfig::test_sample();
|
||||||
conf.expr_fill_default = ExprFillDefaultMode::Default;
|
conf.expr_fill_default = ExprFillDefaultMode::Default;
|
||||||
let fix = salsa::attach(&db, || {
|
let fix = hir::attach_db(&db, || {
|
||||||
super::full_diagnostics(
|
super::full_diagnostics(
|
||||||
&db,
|
&db,
|
||||||
&conf,
|
&conf,
|
||||||
|
|
@ -170,7 +170,7 @@ pub(crate) fn check_has_fix(
|
||||||
/// Checks that there's a diagnostic *without* fix at `$0`.
|
/// Checks that there's a diagnostic *without* fix at `$0`.
|
||||||
pub(crate) fn check_no_fix(#[rust_analyzer::rust_fixture] ra_fixture: &str) {
|
pub(crate) fn check_no_fix(#[rust_analyzer::rust_fixture] ra_fixture: &str) {
|
||||||
let (db, file_position) = RootDatabase::with_position(ra_fixture);
|
let (db, file_position) = RootDatabase::with_position(ra_fixture);
|
||||||
let diagnostic = salsa::attach(&db, || {
|
let diagnostic = hir::attach_db(&db, || {
|
||||||
super::full_diagnostics(
|
super::full_diagnostics(
|
||||||
&db,
|
&db,
|
||||||
&DiagnosticsConfig::test_sample(),
|
&DiagnosticsConfig::test_sample(),
|
||||||
|
|
@ -212,7 +212,7 @@ pub(crate) fn check_diagnostics_with_config(
|
||||||
.iter()
|
.iter()
|
||||||
.copied()
|
.copied()
|
||||||
.flat_map(|file_id| {
|
.flat_map(|file_id| {
|
||||||
salsa::attach(&db, || {
|
hir::attach_db(&db, || {
|
||||||
super::full_diagnostics(
|
super::full_diagnostics(
|
||||||
&db,
|
&db,
|
||||||
&config,
|
&config,
|
||||||
|
|
@ -288,12 +288,12 @@ fn test_disabled_diagnostics() {
|
||||||
let (db, file_id) = RootDatabase::with_single_file(r#"mod foo;"#);
|
let (db, file_id) = RootDatabase::with_single_file(r#"mod foo;"#);
|
||||||
let file_id = file_id.file_id(&db);
|
let file_id = file_id.file_id(&db);
|
||||||
|
|
||||||
let diagnostics = salsa::attach(&db, || {
|
let diagnostics = hir::attach_db(&db, || {
|
||||||
super::full_diagnostics(&db, &config, &AssistResolveStrategy::All, file_id)
|
super::full_diagnostics(&db, &config, &AssistResolveStrategy::All, file_id)
|
||||||
});
|
});
|
||||||
assert!(diagnostics.is_empty());
|
assert!(diagnostics.is_empty());
|
||||||
|
|
||||||
let diagnostics = salsa::attach(&db, || {
|
let diagnostics = hir::attach_db(&db, || {
|
||||||
super::full_diagnostics(
|
super::full_diagnostics(
|
||||||
&db,
|
&db,
|
||||||
&DiagnosticsConfig::test_sample(),
|
&DiagnosticsConfig::test_sample(),
|
||||||
|
|
|
||||||
|
|
@ -791,8 +791,6 @@ impl PatternIterator {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use ide_db::base_db::salsa;
|
|
||||||
|
|
||||||
use crate::{MatchFinder, SsrRule};
|
use crate::{MatchFinder, SsrRule};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -801,7 +799,7 @@ mod tests {
|
||||||
let input = "fn foo() {} fn bar() {} fn main() { foo(1+2); }";
|
let input = "fn foo() {} fn bar() {} fn main() { foo(1+2); }";
|
||||||
|
|
||||||
let (db, position, selections) = crate::tests::single_file(input);
|
let (db, position, selections) = crate::tests::single_file(input);
|
||||||
salsa::attach(&db, || {
|
hir::attach_db(&db, || {
|
||||||
let position = ide_db::FilePosition {
|
let position = ide_db::FilePosition {
|
||||||
file_id: position.file_id.file_id(&db),
|
file_id: position.file_id.file_id(&db),
|
||||||
offset: position.offset,
|
offset: position.offset,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
//! This module is responsible for resolving paths within rules.
|
//! This module is responsible for resolving paths within rules.
|
||||||
|
|
||||||
use hir::AsAssocItem;
|
use hir::AsAssocItem;
|
||||||
use ide_db::{FxHashMap, base_db::salsa};
|
use ide_db::FxHashMap;
|
||||||
use parsing::Placeholder;
|
use parsing::Placeholder;
|
||||||
use syntax::{
|
use syntax::{
|
||||||
SmolStr, SyntaxKind, SyntaxNode, SyntaxToken,
|
SmolStr, SyntaxKind, SyntaxNode, SyntaxToken,
|
||||||
|
|
@ -48,7 +48,7 @@ impl<'db> ResolvedRule<'db> {
|
||||||
resolution_scope: &ResolutionScope<'db>,
|
resolution_scope: &ResolutionScope<'db>,
|
||||||
index: usize,
|
index: usize,
|
||||||
) -> Result<ResolvedRule<'db>, SsrError> {
|
) -> Result<ResolvedRule<'db>, SsrError> {
|
||||||
salsa::attach(resolution_scope.scope.db, || {
|
hir::attach_db(resolution_scope.scope.db, || {
|
||||||
let resolver = Resolver {
|
let resolver = Resolver {
|
||||||
resolution_scope,
|
resolution_scope,
|
||||||
placeholders_by_stand_in: rule.placeholders_by_stand_in,
|
placeholders_by_stand_in: rule.placeholders_by_stand_in,
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,7 @@ use expect_test::{Expect, expect};
|
||||||
use hir::{FilePosition, FileRange};
|
use hir::{FilePosition, FileRange};
|
||||||
use ide_db::{
|
use ide_db::{
|
||||||
EditionedFileId, FxHashSet,
|
EditionedFileId, FxHashSet,
|
||||||
base_db::{
|
base_db::{SourceDatabase, salsa::Durability},
|
||||||
SourceDatabase,
|
|
||||||
salsa::{self, Durability},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
use test_utils::RangeOrOffset;
|
use test_utils::RangeOrOffset;
|
||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
|
|
@ -101,7 +98,7 @@ fn assert_ssr_transform(rule: &str, input: &str, expected: Expect) {
|
||||||
|
|
||||||
fn assert_ssr_transforms(rules: &[&str], input: &str, expected: Expect) {
|
fn assert_ssr_transforms(rules: &[&str], input: &str, expected: Expect) {
|
||||||
let (db, position, selections) = single_file(input);
|
let (db, position, selections) = single_file(input);
|
||||||
salsa::attach(&db, || {
|
hir::attach_db(&db, || {
|
||||||
let position = ide_db::FilePosition {
|
let position = ide_db::FilePosition {
|
||||||
file_id: position.file_id.file_id(&db),
|
file_id: position.file_id.file_id(&db),
|
||||||
offset: position.offset,
|
offset: position.offset,
|
||||||
|
|
@ -149,7 +146,7 @@ fn print_match_debug_info(match_finder: &MatchFinder<'_>, file_id: EditionedFile
|
||||||
|
|
||||||
fn assert_matches(pattern: &str, code: &str, expected: &[&str]) {
|
fn assert_matches(pattern: &str, code: &str, expected: &[&str]) {
|
||||||
let (db, position, selections) = single_file(code);
|
let (db, position, selections) = single_file(code);
|
||||||
salsa::attach(&db, || {
|
hir::attach_db(&db, || {
|
||||||
let mut match_finder = MatchFinder::in_context(
|
let mut match_finder = MatchFinder::in_context(
|
||||||
&db,
|
&db,
|
||||||
ide_db::FilePosition {
|
ide_db::FilePosition {
|
||||||
|
|
@ -177,7 +174,7 @@ fn assert_matches(pattern: &str, code: &str, expected: &[&str]) {
|
||||||
|
|
||||||
fn assert_no_match(pattern: &str, code: &str) {
|
fn assert_no_match(pattern: &str, code: &str) {
|
||||||
let (db, position, selections) = single_file(code);
|
let (db, position, selections) = single_file(code);
|
||||||
salsa::attach(&db, || {
|
hir::attach_db(&db, || {
|
||||||
let mut match_finder = MatchFinder::in_context(
|
let mut match_finder = MatchFinder::in_context(
|
||||||
&db,
|
&db,
|
||||||
ide_db::FilePosition {
|
ide_db::FilePosition {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ use expect_test::{Expect, expect};
|
||||||
use hir::Semantics;
|
use hir::Semantics;
|
||||||
use ide_db::{
|
use ide_db::{
|
||||||
FilePosition, FileRange, RootDatabase,
|
FilePosition, FileRange, RootDatabase,
|
||||||
base_db::salsa,
|
|
||||||
defs::Definition,
|
defs::Definition,
|
||||||
documentation::{DocsRangeMap, Documentation, HasDocs},
|
documentation::{DocsRangeMap, Documentation, HasDocs},
|
||||||
};
|
};
|
||||||
|
|
@ -48,7 +47,7 @@ fn check_rewrite(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect
|
||||||
let sema = &Semantics::new(&analysis.db);
|
let sema = &Semantics::new(&analysis.db);
|
||||||
let (cursor_def, docs, range) = def_under_cursor(sema, &position);
|
let (cursor_def, docs, range) = def_under_cursor(sema, &position);
|
||||||
let res =
|
let res =
|
||||||
salsa::attach(sema.db, || rewrite_links(sema.db, docs.as_str(), cursor_def, Some(range)));
|
hir::attach_db(sema.db, || rewrite_links(sema.db, docs.as_str(), cursor_def, Some(range)));
|
||||||
expect.assert_eq(&res)
|
expect.assert_eq(&res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -65,7 +64,7 @@ fn check_doc_links(#[rust_analyzer::rust_fixture] ra_fixture: &str) {
|
||||||
.flat_map(|(text_range, link, ns)| {
|
.flat_map(|(text_range, link, ns)| {
|
||||||
let attr = range.map(text_range);
|
let attr = range.map(text_range);
|
||||||
let is_inner_attr = attr.map(|(_file, attr)| attr.is_inner_attr()).unwrap_or(false);
|
let is_inner_attr = attr.map(|(_file, attr)| attr.is_inner_attr()).unwrap_or(false);
|
||||||
let def = salsa::attach(sema.db, || {
|
let def = hir::attach_db(sema.db, || {
|
||||||
resolve_doc_path_for_def(sema.db, cursor_def, &link, ns, is_inner_attr)
|
resolve_doc_path_for_def(sema.db, cursor_def, &link, ns, is_inner_attr)
|
||||||
.unwrap_or_else(|| panic!("Failed to resolve {link}"))
|
.unwrap_or_else(|| panic!("Failed to resolve {link}"))
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,7 @@ use hir::{
|
||||||
ClosureStyle, DisplayTarget, EditionedFileId, HasVisibility, HirDisplay, HirDisplayError,
|
ClosureStyle, DisplayTarget, EditionedFileId, HasVisibility, HirDisplay, HirDisplayError,
|
||||||
HirWrite, InRealFile, ModuleDef, ModuleDefId, Semantics, sym,
|
HirWrite, InRealFile, ModuleDef, ModuleDefId, Semantics, sym,
|
||||||
};
|
};
|
||||||
use ide_db::{
|
use ide_db::{FileRange, RootDatabase, famous_defs::FamousDefs, text_edit::TextEditBuilder};
|
||||||
FileRange, RootDatabase, base_db::salsa, famous_defs::FamousDefs, text_edit::TextEditBuilder,
|
|
||||||
};
|
|
||||||
use ide_db::{FxHashSet, text_edit::TextEdit};
|
use ide_db::{FxHashSet, text_edit::TextEdit};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use smallvec::{SmallVec, smallvec};
|
use smallvec::{SmallVec, smallvec};
|
||||||
|
|
@ -107,7 +105,7 @@ pub(crate) fn inlay_hints(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let mut preorder = file.preorder();
|
let mut preorder = file.preorder();
|
||||||
salsa::attach(sema.db, || {
|
hir::attach_db(sema.db, || {
|
||||||
while let Some(event) = preorder.next() {
|
while let Some(event) = preorder.next() {
|
||||||
if matches!((&event, range_limit), (WalkEvent::Enter(node), Some(range)) if range.intersect(node.text_range()).is_none())
|
if matches!((&event, range_limit), (WalkEvent::Enter(node), Some(range)) if range.intersect(node.text_range()).is_none())
|
||||||
{
|
{
|
||||||
|
|
@ -739,7 +737,7 @@ fn label_of_ty(
|
||||||
config: &InlayHintsConfig,
|
config: &InlayHintsConfig,
|
||||||
display_target: DisplayTarget,
|
display_target: DisplayTarget,
|
||||||
) -> Result<(), HirDisplayError> {
|
) -> Result<(), HirDisplayError> {
|
||||||
salsa::attach(sema.db, || {
|
hir::attach_db(sema.db, || {
|
||||||
let iter_item_type = hint_iterator(sema, famous_defs, ty);
|
let iter_item_type = hint_iterator(sema, famous_defs, ty);
|
||||||
match iter_item_type {
|
match iter_item_type {
|
||||||
Some((iter_trait, item, ty)) => {
|
Some((iter_trait, item, ty)) => {
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ use hir::{
|
||||||
Adjust, Adjustment, AutoBorrow, DisplayTarget, HirDisplay, Mutability, OverloadedDeref,
|
Adjust, Adjustment, AutoBorrow, DisplayTarget, HirDisplay, Mutability, OverloadedDeref,
|
||||||
PointerCast, Safety,
|
PointerCast, Safety,
|
||||||
};
|
};
|
||||||
use ide_db::{base_db::salsa, famous_defs::FamousDefs};
|
use ide_db::famous_defs::FamousDefs;
|
||||||
|
|
||||||
use ide_db::text_edit::TextEditBuilder;
|
use ide_db::text_edit::TextEditBuilder;
|
||||||
use syntax::ast::{self, AstNode, prec::ExprPrecedence};
|
use syntax::ast::{self, AstNode, prec::ExprPrecedence};
|
||||||
|
|
@ -216,7 +216,7 @@ pub(super) fn hints(
|
||||||
text: if postfix { format!(".{}", text.trim_end()) } else { text.to_owned() },
|
text: if postfix { format!(".{}", text.trim_end()) } else { text.to_owned() },
|
||||||
linked_location: None,
|
linked_location: None,
|
||||||
tooltip: Some(config.lazy_tooltip(|| {
|
tooltip: Some(config.lazy_tooltip(|| {
|
||||||
salsa::attach(sema.db, || {
|
hir::attach_db(sema.db, || {
|
||||||
InlayTooltip::Markdown(format!(
|
InlayTooltip::Markdown(format!(
|
||||||
"`{}` → `{}`\n\n**{}**\n\n{}",
|
"`{}` → `{}`\n\n**{}**\n\n{}",
|
||||||
source.display(sema.db, display_target),
|
source.display(sema.db, display_target),
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ use ide_db::{
|
||||||
FxHashMap, FxIndexSet, LineIndexDatabase,
|
FxHashMap, FxIndexSet, LineIndexDatabase,
|
||||||
base_db::{
|
base_db::{
|
||||||
CrateOrigin, CrateWorkspaceData, Env, FileSet, RootQueryDb, SourceDatabase, VfsPath,
|
CrateOrigin, CrateWorkspaceData, Env, FileSet, RootQueryDb, SourceDatabase, VfsPath,
|
||||||
salsa::{self, Cancelled},
|
salsa::Cancelled,
|
||||||
},
|
},
|
||||||
prime_caches, symbol_index,
|
prime_caches, symbol_index,
|
||||||
};
|
};
|
||||||
|
|
@ -480,7 +480,7 @@ impl Analysis {
|
||||||
// if we were to attach it here.
|
// if we were to attach it here.
|
||||||
Cancelled::catch(|| {
|
Cancelled::catch(|| {
|
||||||
let symbols = symbol_index::world_symbols(&self.db, query);
|
let symbols = symbol_index::world_symbols(&self.db, query);
|
||||||
salsa::attach(&self.db, || {
|
hir::attach_db(&self.db, || {
|
||||||
symbols
|
symbols
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|s| s.try_to_nav(&Semantics::new(&self.db)))
|
.filter_map(|s| s.try_to_nav(&Semantics::new(&self.db)))
|
||||||
|
|
@ -899,7 +899,7 @@ impl Analysis {
|
||||||
where
|
where
|
||||||
F: FnOnce(&RootDatabase) -> T + std::panic::UnwindSafe,
|
F: FnOnce(&RootDatabase) -> T + std::panic::UnwindSafe,
|
||||||
{
|
{
|
||||||
salsa::attach(&self.db, || {
|
hir::attach_db(&self.db, || {
|
||||||
// the trait solver code may invoke `as_view<HirDatabase>` outside of queries,
|
// the trait solver code may invoke `as_view<HirDatabase>` outside of queries,
|
||||||
// so technically we might run into a panic in salsa if the downcaster has not yet been registered.
|
// so technically we might run into a panic in salsa if the downcaster has not yet been registered.
|
||||||
HirDatabase::zalsa_register_downcaster(&self.db);
|
HirDatabase::zalsa_register_downcaster(&self.db);
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ use hir::{
|
||||||
};
|
};
|
||||||
use ide_db::{
|
use ide_db::{
|
||||||
FileId, FileRange, RootDatabase, SymbolKind,
|
FileId, FileRange, RootDatabase, SymbolKind,
|
||||||
base_db::{CrateOrigin, LangCrateOrigin, RootQueryDb, salsa},
|
base_db::{CrateOrigin, LangCrateOrigin, RootQueryDb},
|
||||||
defs::{Definition, find_std_module},
|
defs::{Definition, find_std_module},
|
||||||
documentation::{Documentation, HasDocs},
|
documentation::{Documentation, HasDocs},
|
||||||
famous_defs::FamousDefs,
|
famous_defs::FamousDefs,
|
||||||
|
|
@ -399,7 +399,7 @@ where
|
||||||
)
|
)
|
||||||
.map(|mut res| {
|
.map(|mut res| {
|
||||||
res.docs = self.docs(db);
|
res.docs = self.docs(db);
|
||||||
res.description = salsa::attach(db, || {
|
res.description = hir::attach_db(db, || {
|
||||||
Some(self.display(db, self.krate(db).to_display_target(db)).to_string())
|
Some(self.display(db, self.krate(db).to_display_target(db)).to_string())
|
||||||
});
|
});
|
||||||
res.container_name = self.container_name(db);
|
res.container_name = self.container_name(db);
|
||||||
|
|
@ -520,7 +520,7 @@ impl TryToNav for hir::Field {
|
||||||
NavigationTarget::from_named(db, src.with_value(it), SymbolKind::Field).map(
|
NavigationTarget::from_named(db, src.with_value(it), SymbolKind::Field).map(
|
||||||
|mut res| {
|
|mut res| {
|
||||||
res.docs = self.docs(db);
|
res.docs = self.docs(db);
|
||||||
res.description = salsa::attach(db, || {
|
res.description = hir::attach_db(db, || {
|
||||||
Some(self.display(db, krate.to_display_target(db)).to_string())
|
Some(self.display(db, krate.to_display_target(db)).to_string())
|
||||||
});
|
});
|
||||||
res
|
res
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ use hir::{
|
||||||
use ide_assists::utils::{has_test_related_attribute, test_related_attribute_syn};
|
use ide_assists::utils::{has_test_related_attribute, test_related_attribute_syn};
|
||||||
use ide_db::{
|
use ide_db::{
|
||||||
FilePosition, FxHashMap, FxIndexMap, FxIndexSet, RootDatabase, SymbolKind,
|
FilePosition, FxHashMap, FxIndexMap, FxIndexSet, RootDatabase, SymbolKind,
|
||||||
base_db::{RootQueryDb, salsa},
|
base_db::RootQueryDb,
|
||||||
defs::Definition,
|
defs::Definition,
|
||||||
documentation::docs_from_attrs,
|
documentation::docs_from_attrs,
|
||||||
helpers::visit_file_defs,
|
helpers::visit_file_defs,
|
||||||
|
|
@ -413,7 +413,7 @@ pub(crate) fn runnable_impl(
|
||||||
let ty = def.self_ty(sema.db);
|
let ty = def.self_ty(sema.db);
|
||||||
let adt_name = ty.as_adt()?.name(sema.db);
|
let adt_name = ty.as_adt()?.name(sema.db);
|
||||||
let mut ty_args = ty.generic_parameters(sema.db, display_target).peekable();
|
let mut ty_args = ty.generic_parameters(sema.db, display_target).peekable();
|
||||||
let params = salsa::attach(sema.db, || {
|
let params = hir::attach_db(sema.db, || {
|
||||||
if ty_args.peek().is_some() {
|
if ty_args.peek().is_some() {
|
||||||
format!("<{}>", ty_args.format_with(",", |ty, cb| cb(&ty)))
|
format!("<{}>", ty_args.format_with(",", |ty, cb| cb(&ty)))
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -522,7 +522,7 @@ fn module_def_doctest(sema: &Semantics<'_, RootDatabase>, def: Definition) -> Op
|
||||||
let mut ty_args = ty.generic_parameters(db, display_target).peekable();
|
let mut ty_args = ty.generic_parameters(db, display_target).peekable();
|
||||||
format_to!(path, "{}", name.display(db, edition));
|
format_to!(path, "{}", name.display(db, edition));
|
||||||
if ty_args.peek().is_some() {
|
if ty_args.peek().is_some() {
|
||||||
salsa::attach(db, || {
|
hir::attach_db(db, || {
|
||||||
format_to!(path, "<{}>", ty_args.format_with(",", |ty, cb| cb(&ty)));
|
format_to!(path, "<{}>", ty_args.format_with(",", |ty, cb| cb(&ty)));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ use hir::{
|
||||||
use ide_db::{
|
use ide_db::{
|
||||||
FilePosition, FxIndexMap,
|
FilePosition, FxIndexMap,
|
||||||
active_parameter::{callable_for_arg_list, generic_def_for_node},
|
active_parameter::{callable_for_arg_list, generic_def_for_node},
|
||||||
base_db::salsa,
|
|
||||||
documentation::{Documentation, HasDocs},
|
documentation::{Documentation, HasDocs},
|
||||||
};
|
};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
@ -267,7 +266,7 @@ fn signature_help_for_call(
|
||||||
// In that case, fall back to render definitions of the respective parameters.
|
// In that case, fall back to render definitions of the respective parameters.
|
||||||
// This is overly conservative: we do not substitute known type vars
|
// This is overly conservative: we do not substitute known type vars
|
||||||
// (see FIXME in tests::impl_trait) and falling back on any unknowns.
|
// (see FIXME in tests::impl_trait) and falling back on any unknowns.
|
||||||
salsa::attach(db, || match (p.ty().contains_unknown(), fn_params.as_deref()) {
|
hir::attach_db(db, || match (p.ty().contains_unknown(), fn_params.as_deref()) {
|
||||||
(true, Some(fn_params)) => {
|
(true, Some(fn_params)) => {
|
||||||
format_to!(buf, "{}", fn_params[idx].ty().display(db, display_target))
|
format_to!(buf, "{}", fn_params[idx].ty().display(db, display_target))
|
||||||
}
|
}
|
||||||
|
|
@ -730,7 +729,7 @@ fn signature_help_for_tuple_pat_ish<'db>(
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
||||||
use expect_test::{Expect, expect};
|
use expect_test::{Expect, expect};
|
||||||
use ide_db::{FilePosition, base_db::salsa};
|
use ide_db::FilePosition;
|
||||||
use stdx::format_to;
|
use stdx::format_to;
|
||||||
use test_fixture::ChangeFixture;
|
use test_fixture::ChangeFixture;
|
||||||
|
|
||||||
|
|
@ -759,7 +758,7 @@ mod tests {
|
||||||
"#
|
"#
|
||||||
);
|
);
|
||||||
let (db, position) = position(&fixture);
|
let (db, position) = position(&fixture);
|
||||||
let sig_help = salsa::attach(&db, || crate::signature_help::signature_help(&db, position));
|
let sig_help = hir::attach_db(&db, || crate::signature_help::signature_help(&db, position));
|
||||||
let actual = match sig_help {
|
let actual = match sig_help {
|
||||||
Some(sig_help) => {
|
Some(sig_help) => {
|
||||||
let mut rendered = String::new();
|
let mut rendered = String::new();
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ use arrayvec::ArrayVec;
|
||||||
use hir::{Crate, Module, Semantics, db::HirDatabase};
|
use hir::{Crate, Module, Semantics, db::HirDatabase};
|
||||||
use ide_db::{
|
use ide_db::{
|
||||||
FileId, FileRange, FxHashMap, FxHashSet, RootDatabase,
|
FileId, FileRange, FxHashMap, FxHashSet, RootDatabase,
|
||||||
base_db::{RootQueryDb, SourceDatabase, VfsPath, salsa},
|
base_db::{RootQueryDb, SourceDatabase, VfsPath},
|
||||||
defs::{Definition, IdentClass},
|
defs::{Definition, IdentClass},
|
||||||
documentation::Documentation,
|
documentation::Documentation,
|
||||||
famous_defs::FamousDefs,
|
famous_defs::FamousDefs,
|
||||||
|
|
@ -276,7 +276,7 @@ impl StaticIndex<'_> {
|
||||||
for token in tokens {
|
for token in tokens {
|
||||||
let range = token.text_range();
|
let range = token.text_range();
|
||||||
let node = token.parent().unwrap();
|
let node = token.parent().unwrap();
|
||||||
match salsa::attach(self.db, || get_definitions(&sema, token.clone())) {
|
match hir::attach_db(self.db, || get_definitions(&sema, token.clone())) {
|
||||||
Some(it) => {
|
Some(it) => {
|
||||||
for i in it {
|
for i in it {
|
||||||
add_token(i, range, &node);
|
add_token(i, range, &node);
|
||||||
|
|
@ -293,7 +293,7 @@ impl StaticIndex<'_> {
|
||||||
vendored_libs_config: VendoredLibrariesConfig<'_>,
|
vendored_libs_config: VendoredLibrariesConfig<'_>,
|
||||||
) -> StaticIndex<'a> {
|
) -> StaticIndex<'a> {
|
||||||
let db = &analysis.db;
|
let db = &analysis.db;
|
||||||
salsa::attach(db, || {
|
hir::attach_db(db, || {
|
||||||
let work = all_modules(db).into_iter().filter(|module| {
|
let work = all_modules(db).into_iter().filter(|module| {
|
||||||
let file_id = module.definition_source_file_id(db).original_file(db);
|
let file_id = module.definition_source_file_id(db).original_file(db);
|
||||||
let source_root =
|
let source_root =
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ use std::ops::ControlFlow;
|
||||||
|
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use hir::{DefWithBody, EditionedFileId, InFile, InRealFile, MacroKind, Name, Semantics};
|
use hir::{DefWithBody, EditionedFileId, InFile, InRealFile, MacroKind, Name, Semantics};
|
||||||
use ide_db::{FxHashMap, FxHashSet, Ranker, RootDatabase, SymbolKind, base_db::salsa};
|
use ide_db::{FxHashMap, FxHashSet, Ranker, RootDatabase, SymbolKind};
|
||||||
use syntax::{
|
use syntax::{
|
||||||
AstNode, AstToken, NodeOrToken,
|
AstNode, AstToken, NodeOrToken,
|
||||||
SyntaxKind::*,
|
SyntaxKind::*,
|
||||||
|
|
@ -428,7 +428,7 @@ fn traverse(
|
||||||
Some(current_body) => {
|
Some(current_body) => {
|
||||||
let (ops, bindings) = per_body_cache.entry(current_body).or_insert_with(|| {
|
let (ops, bindings) = per_body_cache.entry(current_body).or_insert_with(|| {
|
||||||
(
|
(
|
||||||
salsa::attach(sema.db, || sema.get_unsafe_ops(current_body)),
|
hir::attach_db(sema.db, || sema.get_unsafe_ops(current_body)),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
@ -440,7 +440,7 @@ fn traverse(
|
||||||
|node| unsafe_ops.contains(&InFile::new(descended_element.file_id, node));
|
|node| unsafe_ops.contains(&InFile::new(descended_element.file_id, node));
|
||||||
let element = match descended_element.value {
|
let element = match descended_element.value {
|
||||||
NodeOrToken::Node(name_like) => {
|
NodeOrToken::Node(name_like) => {
|
||||||
let hl = salsa::attach(sema.db, || {
|
let hl = hir::attach_db(sema.db, || {
|
||||||
highlight::name_like(
|
highlight::name_like(
|
||||||
sema,
|
sema,
|
||||||
krate,
|
krate,
|
||||||
|
|
@ -458,7 +458,7 @@ fn traverse(
|
||||||
}
|
}
|
||||||
hl
|
hl
|
||||||
}
|
}
|
||||||
NodeOrToken::Token(token) => salsa::attach(sema.db, || {
|
NodeOrToken::Token(token) => hir::attach_db(sema.db, || {
|
||||||
highlight::token(sema, token, edition, &is_unsafe_node, tt_level > 0)
|
highlight::token(sema, token, edition, &is_unsafe_node, tt_level > 0)
|
||||||
.zip(Some(None))
|
.zip(Some(None))
|
||||||
}),
|
}),
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ use std::mem;
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use hir::{EditionedFileId, HirFileId, InFile, Semantics, sym};
|
use hir::{EditionedFileId, HirFileId, InFile, Semantics, sym};
|
||||||
use ide_db::{
|
use ide_db::{
|
||||||
SymbolKind, active_parameter::ActiveParameter, base_db::salsa, defs::Definition,
|
SymbolKind, active_parameter::ActiveParameter, defs::Definition,
|
||||||
documentation::docs_with_rangemap, rust_doc::is_rust_fence,
|
documentation::docs_with_rangemap, rust_doc::is_rust_fence,
|
||||||
};
|
};
|
||||||
use syntax::{
|
use syntax::{
|
||||||
|
|
@ -27,7 +27,7 @@ pub(super) fn ra_fixture(
|
||||||
expanded: &ast::String,
|
expanded: &ast::String,
|
||||||
) -> Option<()> {
|
) -> Option<()> {
|
||||||
let active_parameter =
|
let active_parameter =
|
||||||
salsa::attach(sema.db, || ActiveParameter::at_token(sema, expanded.syntax().clone()))?;
|
hir::attach_db(sema.db, || ActiveParameter::at_token(sema, expanded.syntax().clone()))?;
|
||||||
let has_rust_fixture_attr = active_parameter.attrs().is_some_and(|attrs| {
|
let has_rust_fixture_attr = active_parameter.attrs().is_some_and(|attrs| {
|
||||||
attrs.filter_map(|attr| attr.as_simple_path()).any(|path| {
|
attrs.filter_map(|attr| attr.as_simple_path()).any(|path| {
|
||||||
path.segments()
|
path.segments()
|
||||||
|
|
@ -128,7 +128,7 @@ pub(super) fn doc_comment(
|
||||||
|
|
||||||
// Extract intra-doc links and emit highlights for them.
|
// Extract intra-doc links and emit highlights for them.
|
||||||
if let Some((docs, doc_mapping)) = docs_with_rangemap(sema.db, &attributes) {
|
if let Some((docs, doc_mapping)) = docs_with_rangemap(sema.db, &attributes) {
|
||||||
salsa::attach(sema.db, || {
|
hir::attach_db(sema.db, || {
|
||||||
extract_definitions_from_docs(&docs)
|
extract_definitions_from_docs(&docs)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|(range, link, ns)| {
|
.filter_map(|(range, link, ns)| {
|
||||||
|
|
|
||||||
|
|
@ -213,14 +213,13 @@ mod tests {
|
||||||
|
|
||||||
use crate::fixture;
|
use crate::fixture;
|
||||||
use expect_test::expect;
|
use expect_test::expect;
|
||||||
use ide_db::base_db::salsa;
|
|
||||||
|
|
||||||
fn make_memory_layout(
|
fn make_memory_layout(
|
||||||
#[rust_analyzer::rust_fixture] ra_fixture: &str,
|
#[rust_analyzer::rust_fixture] ra_fixture: &str,
|
||||||
) -> Option<RecursiveMemoryLayout> {
|
) -> Option<RecursiveMemoryLayout> {
|
||||||
let (analysis, position, _) = fixture::annotations(ra_fixture);
|
let (analysis, position, _) = fixture::annotations(ra_fixture);
|
||||||
|
|
||||||
salsa::attach(&analysis.db, || view_memory_layout(&analysis.db, position))
|
hir::attach_db(&analysis.db, || view_memory_layout(&analysis.db, position))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -26,10 +26,7 @@ use ide::{
|
||||||
};
|
};
|
||||||
use ide_db::{
|
use ide_db::{
|
||||||
EditionedFileId, LineIndexDatabase, SnippetCap,
|
EditionedFileId, LineIndexDatabase, SnippetCap,
|
||||||
base_db::{
|
base_db::{SourceDatabase, salsa::Database},
|
||||||
SourceDatabase,
|
|
||||||
salsa::{self, Database},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use load_cargo::{LoadCargoConfig, ProcMacroServerChoice, load_workspace};
|
use load_cargo::{LoadCargoConfig, ProcMacroServerChoice, load_workspace};
|
||||||
|
|
@ -315,7 +312,7 @@ impl flags::AnalysisStats {
|
||||||
shuffle(&mut rng, &mut bodies);
|
shuffle(&mut rng, &mut bodies);
|
||||||
}
|
}
|
||||||
|
|
||||||
salsa::attach(db, || {
|
hir::attach_db(db, || {
|
||||||
if !self.skip_lowering {
|
if !self.skip_lowering {
|
||||||
self.run_body_lowering(db, &vfs, &bodies, verbosity);
|
self.run_body_lowering(db, &vfs, &bodies, verbosity);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,16 @@ const _: () = {
|
||||||
self.parent.hash(state);
|
self.parent.hash(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl zalsa_::HasJar for SyntaxContext {
|
||||||
|
type Jar = zalsa_struct_::JarImpl<SyntaxContext>;
|
||||||
|
const KIND: zalsa_::JarKind = zalsa_::JarKind::Struct;
|
||||||
|
}
|
||||||
|
|
||||||
|
zalsa_::register_jar! {
|
||||||
|
zalsa_::ErasedJar::erase::<SyntaxContext>()
|
||||||
|
}
|
||||||
|
|
||||||
/// Key to use during hash lookups. Each field is some type that implements `Lookup<T>`
|
/// Key to use during hash lookups. Each field is some type that implements `Lookup<T>`
|
||||||
/// for the owned type. This permits interning with an `&str` when a `String` is required and so forth.
|
/// for the owned type. This permits interning with an `&str` when a `String` is required and so forth.
|
||||||
#[derive(Hash)]
|
#[derive(Hash)]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue