[red-knot] Upgrade to Salsa 3.0 (#11952)

This commit is contained in:
Micha Reiser 2024-06-20 20:19:16 +01:00 committed by GitHub
parent c8ff89c73c
commit 927069c12f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 211 additions and 216 deletions

86
Cargo.lock generated
View File

@ -376,7 +376,7 @@ dependencies = [
"heck 0.5.0", "heck 0.5.0",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.66", "syn",
] ]
[[package]] [[package]]
@ -617,7 +617,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"strsim 0.10.0", "strsim 0.10.0",
"syn 2.0.66", "syn",
] ]
[[package]] [[package]]
@ -628,7 +628,7 @@ checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f"
dependencies = [ dependencies = [
"darling_core", "darling_core",
"quote", "quote",
"syn 2.0.66", "syn",
] ]
[[package]] [[package]]
@ -699,7 +699,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.66", "syn",
] ]
[[package]] [[package]]
@ -1092,7 +1092,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.66", "syn",
] ]
[[package]] [[package]]
@ -1260,7 +1260,7 @@ dependencies = [
"Inflector", "Inflector",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.66", "syn",
] ]
[[package]] [[package]]
@ -1386,7 +1386,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2ae40017ac09cd2c6a53504cb3c871c7f2b41466eac5bc66ba63f39073b467b" checksum = "a2ae40017ac09cd2c6a53504cb3c871c7f2b41466eac5bc66ba63f39073b467b"
dependencies = [ dependencies = [
"quote", "quote",
"syn 2.0.66", "syn",
] ]
[[package]] [[package]]
@ -2010,7 +2010,7 @@ dependencies = [
"ruff_python_stdlib", "ruff_python_stdlib",
"ruff_text_size", "ruff_text_size",
"rustc-hash", "rustc-hash",
"salsa-2022", "salsa",
"smallvec", "smallvec",
"smol_str", "smol_str",
"tempfile", "tempfile",
@ -2196,7 +2196,7 @@ dependencies = [
"ruff_source_file", "ruff_source_file",
"ruff_text_size", "ruff_text_size",
"rustc-hash", "rustc-hash",
"salsa-2022", "salsa",
"tracing", "tracing",
"zip", "zip",
] ]
@ -2345,7 +2345,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"ruff_python_trivia", "ruff_python_trivia",
"syn 2.0.66", "syn",
] ]
[[package]] [[package]]
@ -2719,9 +2719,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
[[package]] [[package]]
name = "salsa-2022" name = "salsa"
version = "0.1.0" version = "0.18.0"
source = "git+https://github.com/salsa-rs/salsa.git?rev=05b4e3ebdcdc47730cdd359e7e97fb2470527279#05b4e3ebdcdc47730cdd359e7e97fb2470527279" source = "git+https://github.com/salsa-rs/salsa.git?rev=f706aa2d32d473ee633a77c1af01d180c85da308#f706aa2d32d473ee633a77c1af01d180c85da308"
dependencies = [ dependencies = [
"arc-swap", "arc-swap",
"crossbeam", "crossbeam",
@ -2732,20 +2732,21 @@ dependencies = [
"log", "log",
"parking_lot", "parking_lot",
"rustc-hash", "rustc-hash",
"salsa-2022-macros", "salsa-macros",
"smallvec", "smallvec",
] ]
[[package]] [[package]]
name = "salsa-2022-macros" name = "salsa-macros"
version = "0.1.0" version = "0.18.0"
source = "git+https://github.com/salsa-rs/salsa.git?rev=05b4e3ebdcdc47730cdd359e7e97fb2470527279#05b4e3ebdcdc47730cdd359e7e97fb2470527279" source = "git+https://github.com/salsa-rs/salsa.git?rev=f706aa2d32d473ee633a77c1af01d180c85da308#f706aa2d32d473ee633a77c1af01d180c85da308"
dependencies = [ dependencies = [
"eyre", "eyre",
"heck 0.4.1", "heck 0.4.1",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 1.0.109", "syn",
"synstructure",
] ]
[[package]] [[package]]
@ -2778,7 +2779,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"serde_derive_internals", "serde_derive_internals",
"syn 2.0.66", "syn",
] ]
[[package]] [[package]]
@ -2827,7 +2828,7 @@ checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.66", "syn",
] ]
[[package]] [[package]]
@ -2838,7 +2839,7 @@ checksum = "330f01ce65a3a5fe59a60c82f3c9a024b573b8a6e875bd233fe5f934e71d54e3"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.66", "syn",
] ]
[[package]] [[package]]
@ -2860,7 +2861,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.66", "syn",
] ]
[[package]] [[package]]
@ -2901,7 +2902,7 @@ dependencies = [
"darling", "darling",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.66", "syn",
] ]
[[package]] [[package]]
@ -3007,7 +3008,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"rustversion", "rustversion",
"syn 2.0.66", "syn",
] ]
[[package]] [[package]]
@ -3016,17 +3017,6 @@ version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.66" version = "2.0.66"
@ -3046,7 +3036,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.66", "syn",
] ]
[[package]] [[package]]
@ -3102,7 +3092,7 @@ dependencies = [
"cfg-if", "cfg-if",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.66", "syn",
] ]
[[package]] [[package]]
@ -3113,7 +3103,7 @@ checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.66", "syn",
"test-case-core", "test-case-core",
] ]
@ -3134,7 +3124,7 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.66", "syn",
] ]
[[package]] [[package]]
@ -3256,7 +3246,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.66", "syn",
] ]
[[package]] [[package]]
@ -3492,7 +3482,7 @@ checksum = "9881bea7cbe687e36c9ab3b778c36cd0487402e270304e8b1296d5085303c1a2"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.66", "syn",
] ]
[[package]] [[package]]
@ -3577,7 +3567,7 @@ dependencies = [
"once_cell", "once_cell",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.66", "syn",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -3611,7 +3601,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.66", "syn",
"wasm-bindgen-backend", "wasm-bindgen-backend",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -3644,7 +3634,7 @@ checksum = "b7f89739351a2e03cb94beb799d47fb2cac01759b40ec441f7de39b00cbf7ef0"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.66", "syn",
] ]
[[package]] [[package]]
@ -3928,7 +3918,7 @@ checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.66", "syn",
"synstructure", "synstructure",
] ]
@ -3949,7 +3939,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.66", "syn",
] ]
[[package]] [[package]]
@ -3969,7 +3959,7 @@ checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.66", "syn",
"synstructure", "synstructure",
] ]
@ -3998,7 +3988,7 @@ checksum = "97cf56601ee5052b4417d90c8755c6683473c926039908196cf35d99f893ebe7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.66", "syn",
] ]
[[package]] [[package]]

View File

@ -106,7 +106,7 @@ rand = { version = "0.8.5" }
rayon = { version = "1.10.0" } rayon = { version = "1.10.0" }
regex = { version = "1.10.2" } regex = { version = "1.10.2" }
rustc-hash = { version = "1.1.0" } rustc-hash = { version = "1.1.0" }
salsa = { git = "https://github.com/salsa-rs/salsa.git", package = "salsa-2022", rev = "05b4e3ebdcdc47730cdd359e7e97fb2470527279" } salsa = { git = "https://github.com/salsa-rs/salsa.git", rev = "f706aa2d32d473ee633a77c1af01d180c85da308" }
schemars = { version = "0.8.16" } schemars = { version = "0.8.16" }
seahash = { version = "4.1.0" } seahash = { version = "4.1.0" }
serde = { version = "1.0.197", features = ["derive"] } serde = { version = "1.0.197", features = ["derive"] }

View File

@ -13,10 +13,10 @@ use crate::types::{infer_types, public_symbol_ty};
#[salsa::jar(db=Db)] #[salsa::jar(db=Db)]
pub struct Jar( pub struct Jar(
ModuleNameIngredient, ModuleNameIngredient<'_>,
ModuleResolverSearchPaths, ModuleResolverSearchPaths,
ScopeId, ScopeId<'_>,
PublicSymbolId, PublicSymbolId<'_>,
symbol_table, symbol_table,
resolve_module_query, resolve_module_query,
file_to_module, file_to_module,
@ -37,9 +37,10 @@ pub(crate) mod tests {
use std::marker::PhantomData; use std::marker::PhantomData;
use std::sync::Arc; use std::sync::Arc;
use salsa::id::AsId;
use salsa::ingredient::Ingredient; use salsa::ingredient::Ingredient;
use salsa::storage::HasIngredientsFor; use salsa::storage::HasIngredientsFor;
use salsa::{AsId, DebugWithDb}; use salsa::DebugWithDb;
use ruff_db::file_system::{FileSystem, MemoryFileSystem, OsFileSystem}; use ruff_db::file_system::{FileSystem, MemoryFileSystem, OsFileSystem};
use ruff_db::vfs::Vfs; use ruff_db::vfs::Vfs;
@ -82,7 +83,6 @@ pub(crate) mod tests {
/// This useful for testing advanced file system features like permissions, symlinks, etc. /// This useful for testing advanced file system features like permissions, symlinks, etc.
/// ///
/// Note that any files written to the memory file system won't be copied over. /// Note that any files written to the memory file system won't be copied over.
#[allow(unused)]
pub(crate) fn with_os_file_system(&mut self) { pub(crate) fn with_os_file_system(&mut self) {
self.file_system = TestFileSystem::Os(OsFileSystem); self.file_system = TestFileSystem::Os(OsFileSystem);
} }
@ -157,44 +157,43 @@ pub(crate) mod tests {
enum TestFileSystem { enum TestFileSystem {
Memory(MemoryFileSystem), Memory(MemoryFileSystem),
#[allow(unused)]
Os(OsFileSystem), Os(OsFileSystem),
} }
pub(crate) fn assert_will_run_function_query<C, Db, Jar>( pub(crate) fn assert_will_run_function_query<'db, C, Db, Jar>(
db: &Db, db: &'db Db,
to_function: impl FnOnce(&C) -> &salsa::function::FunctionIngredient<C>, to_function: impl FnOnce(&C) -> &salsa::function::FunctionIngredient<C>,
key: C::Key, input: &C::Input<'db>,
events: &[salsa::Event], events: &[salsa::Event],
) where ) where
C: salsa::function::Configuration<Jar = Jar> C: salsa::function::Configuration<Jar = Jar>
+ salsa::storage::IngredientsFor<Jar = Jar, Ingredients = C>, + salsa::storage::IngredientsFor<Jar = Jar, Ingredients = C>,
Jar: HasIngredientsFor<C>, Jar: HasIngredientsFor<C>,
Db: salsa::DbWithJar<Jar>, Db: salsa::DbWithJar<Jar>,
C::Key: AsId, C::Input<'db>: AsId,
{ {
will_run_function_query(db, to_function, key, events, true); will_run_function_query(db, to_function, input, events, true);
} }
pub(crate) fn assert_will_not_run_function_query<C, Db, Jar>( pub(crate) fn assert_will_not_run_function_query<'db, C, Db, Jar>(
db: &Db, db: &'db Db,
to_function: impl FnOnce(&C) -> &salsa::function::FunctionIngredient<C>, to_function: impl FnOnce(&C) -> &salsa::function::FunctionIngredient<C>,
key: C::Key, input: &C::Input<'db>,
events: &[salsa::Event], events: &[salsa::Event],
) where ) where
C: salsa::function::Configuration<Jar = Jar> C: salsa::function::Configuration<Jar = Jar>
+ salsa::storage::IngredientsFor<Jar = Jar, Ingredients = C>, + salsa::storage::IngredientsFor<Jar = Jar, Ingredients = C>,
Jar: HasIngredientsFor<C>, Jar: HasIngredientsFor<C>,
Db: salsa::DbWithJar<Jar>, Db: salsa::DbWithJar<Jar>,
C::Key: AsId, C::Input<'db>: AsId,
{ {
will_run_function_query(db, to_function, key, events, false); will_run_function_query(db, to_function, input, events, false);
} }
fn will_run_function_query<C, Db, Jar>( fn will_run_function_query<'db, C, Db, Jar>(
db: &Db, db: &'db Db,
to_function: impl FnOnce(&C) -> &salsa::function::FunctionIngredient<C>, to_function: impl FnOnce(&C) -> &salsa::function::FunctionIngredient<C>,
key: C::Key, input: &C::Input<'db>,
events: &[salsa::Event], events: &[salsa::Event],
should_run: bool, should_run: bool,
) where ) where
@ -202,7 +201,7 @@ pub(crate) mod tests {
+ salsa::storage::IngredientsFor<Jar = Jar, Ingredients = C>, + salsa::storage::IngredientsFor<Jar = Jar, Ingredients = C>,
Jar: HasIngredientsFor<C>, Jar: HasIngredientsFor<C>,
Db: salsa::DbWithJar<Jar>, Db: salsa::DbWithJar<Jar>,
C::Key: AsId, C::Input<'db>: AsId,
{ {
let (jar, _) = let (jar, _) =
<_ as salsa::storage::HasJar<<C as salsa::storage::IngredientsFor>::Jar>>::jar(db); <_ as salsa::storage::HasJar<<C as salsa::storage::IngredientsFor>::Jar>>::jar(db);
@ -218,7 +217,7 @@ pub(crate) mod tests {
let did_run = events.iter().any(|event| { let did_run = events.iter().any(|event| {
if let salsa::EventKind::WillExecute { database_key } = event.kind { if let salsa::EventKind::WillExecute { database_key } = event.kind {
database_key.ingredient_index() == ingredient_index database_key.ingredient_index() == ingredient_index
&& database_key.key_index() == key.as_id() && database_key.key_index() == input.as_id()
} else { } else {
false false
} }
@ -229,7 +228,7 @@ pub(crate) mod tests {
"Expected query {:?} to run but it didn't", "Expected query {:?} to run but it didn't",
DebugIdx { DebugIdx {
db: PhantomData::<Db>, db: PhantomData::<Db>,
value_id: key.as_id(), value_id: input.as_id(),
ingredient: function_ingredient, ingredient: function_ingredient,
} }
); );
@ -238,7 +237,7 @@ pub(crate) mod tests {
"Expected query {:?} not to run but it did", "Expected query {:?} not to run but it did",
DebugIdx { DebugIdx {
db: PhantomData::<Db>, db: PhantomData::<Db>,
value_id: key.as_id(), value_id: input.as_id(),
ingredient: function_ingredient, ingredient: function_ingredient,
} }
); );

View File

@ -41,9 +41,9 @@ pub fn resolve_module(db: &dyn Db, module_name: ModuleName) -> Option<Module> {
/// This query should not be called directly. Instead, use [`resolve_module`]. It only exists /// This query should not be called directly. Instead, use [`resolve_module`]. It only exists
/// because Salsa requires the module name to be an ingredient. /// because Salsa requires the module name to be an ingredient.
#[salsa::tracked] #[salsa::tracked]
pub(crate) fn resolve_module_query( pub(crate) fn resolve_module_query<'db>(
db: &dyn Db, db: &'db dyn Db,
module_name: internal::ModuleNameIngredient, module_name: internal::ModuleNameIngredient<'db>,
) -> Option<Module> { ) -> Option<Module> {
let _ = tracing::trace_span!("resolve_module", module_name = ?module_name.debug(db)).enter(); let _ = tracing::trace_span!("resolve_module", module_name = ?module_name.debug(db)).enter();
@ -221,7 +221,7 @@ pub(crate) mod internal {
/// ///
/// This is needed because Salsa requires that all query arguments are salsa ingredients. /// This is needed because Salsa requires that all query arguments are salsa ingredients.
#[salsa::interned] #[salsa::interned]
pub(crate) struct ModuleNameIngredient { pub(crate) struct ModuleNameIngredient<'db> {
#[return_ref] #[return_ref]
pub(super) name: ModuleName, pub(super) name: ModuleName,
} }

View File

@ -42,7 +42,7 @@ pub(crate) fn semantic_index(db: &dyn Db, file: VfsFile) -> SemanticIndex {
/// Salsa can avoid invalidating dependent queries if this scope's symbol table /// Salsa can avoid invalidating dependent queries if this scope's symbol table
/// is unchanged. /// is unchanged.
#[salsa::tracked] #[salsa::tracked]
pub(crate) fn symbol_table(db: &dyn Db, scope: ScopeId) -> Arc<SymbolTable> { pub(crate) fn symbol_table<'db>(db: &'db dyn Db, scope: ScopeId<'db>) -> Arc<SymbolTable> {
let _ = tracing::trace_span!("symbol_table", scope = ?scope.debug(db)).enter(); let _ = tracing::trace_span!("symbol_table", scope = ?scope.debug(db)).enter();
let index = semantic_index(db, scope.file(db)); let index = semantic_index(db, scope.file(db));
@ -51,7 +51,7 @@ pub(crate) fn symbol_table(db: &dyn Db, scope: ScopeId) -> Arc<SymbolTable> {
/// Returns the root scope of `file`. /// Returns the root scope of `file`.
#[salsa::tracked] #[salsa::tracked]
pub(crate) fn root_scope(db: &dyn Db, file: VfsFile) -> ScopeId { pub(crate) fn root_scope(db: &dyn Db, file: VfsFile) -> ScopeId<'_> {
let _ = tracing::trace_span!("root_scope", file = ?file.debug(db.upcast())).enter(); let _ = tracing::trace_span!("root_scope", file = ?file.debug(db.upcast())).enter();
FileScopeId::root().to_scope_id(db, file) FileScopeId::root().to_scope_id(db, file)
@ -59,7 +59,11 @@ pub(crate) fn root_scope(db: &dyn Db, file: VfsFile) -> ScopeId {
/// Returns the symbol with the given name in `file`'s public scope or `None` if /// Returns the symbol with the given name in `file`'s public scope or `None` if
/// no symbol with the given name exists. /// no symbol with the given name exists.
pub fn public_symbol(db: &dyn Db, file: VfsFile, name: &str) -> Option<PublicSymbolId> { pub fn public_symbol<'db>(
db: &'db dyn Db,
file: VfsFile,
name: &str,
) -> Option<PublicSymbolId<'db>> {
let root_scope = root_scope(db, file); let root_scope = root_scope(db, file);
let symbol_table = symbol_table(db, root_scope); let symbol_table = symbol_table(db, root_scope);
let local = symbol_table.symbol_id_by_name(name)?; let local = symbol_table.symbol_id_by_name(name)?;
@ -104,7 +108,6 @@ impl SemanticIndex {
} }
/// Returns the ID of the `expression`'s enclosing scope. /// Returns the ID of the `expression`'s enclosing scope.
#[allow(unused)]
pub(crate) fn expression_scope_id(&self, expression: &ast::Expr) -> FileScopeId { pub(crate) fn expression_scope_id(&self, expression: &ast::Expr) -> FileScopeId {
self.expression_scopes[&NodeKey::from_node(expression)] self.expression_scopes[&NodeKey::from_node(expression)]
} }
@ -116,7 +119,6 @@ impl SemanticIndex {
} }
/// Returns the [`Scope`] with the given id. /// Returns the [`Scope`] with the given id.
#[allow(unused)]
pub(crate) fn scope(&self, id: FileScopeId) -> &Scope { pub(crate) fn scope(&self, id: FileScopeId) -> &Scope {
&self.scopes[id] &self.scopes[id]
} }
@ -140,13 +142,11 @@ impl SemanticIndex {
} }
/// Returns an iterator over the direct child scopes of `scope`. /// Returns an iterator over the direct child scopes of `scope`.
#[allow(unused)]
pub(crate) fn child_scopes(&self, scope: FileScopeId) -> ChildrenIter { pub(crate) fn child_scopes(&self, scope: FileScopeId) -> ChildrenIter {
ChildrenIter::new(self, scope) ChildrenIter::new(self, scope)
} }
/// Returns an iterator over all ancestors of `scope`, starting with `scope` itself. /// Returns an iterator over all ancestors of `scope`, starting with `scope` itself.
#[allow(unused)]
pub(crate) fn ancestor_scopes(&self, scope: FileScopeId) -> AncestorsIter { pub(crate) fn ancestor_scopes(&self, scope: FileScopeId) -> AncestorsIter {
AncestorsIter::new(self, scope) AncestorsIter::new(self, scope)
} }

View File

@ -65,7 +65,7 @@ impl std::fmt::Debug for AstIds {
} }
} }
fn ast_ids(db: &dyn Db, scope: ScopeId) -> &AstIds { fn ast_ids<'db>(db: &'db dyn Db, scope: ScopeId) -> &'db AstIds {
semantic_index(db, scope.file(db)).ast_ids(scope.file_scope_id(db)) semantic_index(db, scope.file(db)).ast_ids(scope.file_scope_id(db))
} }

View File

@ -1,7 +1,3 @@
// Allow unused underscore violations generated by the salsa macro
// TODO(micha): Contribute fix upstream
#![allow(clippy::used_underscore_binding)]
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::ops::Range; use std::ops::Range;
@ -78,7 +74,7 @@ bitflags! {
/// ID that uniquely identifies a public symbol defined in a module's root scope. /// ID that uniquely identifies a public symbol defined in a module's root scope.
#[salsa::tracked] #[salsa::tracked]
pub struct PublicSymbolId { pub struct PublicSymbolId<'db> {
#[id] #[id]
pub(crate) file: VfsFile, pub(crate) file: VfsFile,
#[id] #[id]
@ -132,7 +128,7 @@ impl ScopedSymbolId {
/// Returns a mapping from [`FileScopeId`] to globally unique [`ScopeId`]. /// Returns a mapping from [`FileScopeId`] to globally unique [`ScopeId`].
#[salsa::tracked(return_ref)] #[salsa::tracked(return_ref)]
pub(crate) fn scopes_map(db: &dyn Db, file: VfsFile) -> ScopesMap { pub(crate) fn scopes_map(db: &dyn Db, file: VfsFile) -> ScopesMap<'_> {
let _ = tracing::trace_span!("scopes_map", file = ?file.debug(db.upcast())).enter(); let _ = tracing::trace_span!("scopes_map", file = ?file.debug(db.upcast())).enter();
let index = semantic_index(db, file); let index = semantic_index(db, file);
@ -152,19 +148,19 @@ pub(crate) fn scopes_map(db: &dyn Db, file: VfsFile) -> ScopesMap {
/// because they allow for more efficient storage of associated data /// because they allow for more efficient storage of associated data
/// (use of an [`IndexVec`] keyed by [`FileScopeId`] over an [`FxHashMap`] keyed by [`ScopeId`]). /// (use of an [`IndexVec`] keyed by [`FileScopeId`] over an [`FxHashMap`] keyed by [`ScopeId`]).
#[derive(Eq, PartialEq, Debug)] #[derive(Eq, PartialEq, Debug)]
pub(crate) struct ScopesMap { pub(crate) struct ScopesMap<'db> {
scopes: IndexVec<FileScopeId, ScopeId>, scopes: IndexVec<FileScopeId, ScopeId<'db>>,
} }
impl ScopesMap { impl<'db> ScopesMap<'db> {
/// Gets the program-wide unique scope id for the given file specific `scope_id`. /// Gets the program-wide unique scope id for the given file specific `scope_id`.
fn get(&self, scope: FileScopeId) -> ScopeId { fn get(&self, scope: FileScopeId) -> ScopeId<'db> {
self.scopes[scope] self.scopes[scope]
} }
} }
#[salsa::tracked(return_ref)] #[salsa::tracked(return_ref)]
pub(crate) fn public_symbols_map(db: &dyn Db, file: VfsFile) -> PublicSymbolsMap { pub(crate) fn public_symbols_map(db: &dyn Db, file: VfsFile) -> PublicSymbolsMap<'_> {
let _ = tracing::trace_span!("public_symbols_map", file = ?file.debug(db.upcast())).enter(); let _ = tracing::trace_span!("public_symbols_map", file = ?file.debug(db.upcast())).enter();
let module_scope = root_scope(db, file); let module_scope = root_scope(db, file);
@ -182,20 +178,20 @@ pub(crate) fn public_symbols_map(db: &dyn Db, file: VfsFile) -> PublicSymbolsMap
/// Maps [`LocalSymbolId`] of a file's root scope to the corresponding [`PublicSymbolId`] (Salsa ingredients). /// Maps [`LocalSymbolId`] of a file's root scope to the corresponding [`PublicSymbolId`] (Salsa ingredients).
#[derive(Eq, PartialEq, Debug)] #[derive(Eq, PartialEq, Debug)]
pub(crate) struct PublicSymbolsMap { pub(crate) struct PublicSymbolsMap<'db> {
symbols: IndexVec<ScopedSymbolId, PublicSymbolId>, symbols: IndexVec<ScopedSymbolId, PublicSymbolId<'db>>,
} }
impl PublicSymbolsMap { impl<'db> PublicSymbolsMap<'db> {
/// Resolve the [`PublicSymbolId`] for the module-level `symbol_id`. /// Resolve the [`PublicSymbolId`] for the module-level `symbol_id`.
fn public(&self, symbol_id: ScopedSymbolId) -> PublicSymbolId { fn public(&self, symbol_id: ScopedSymbolId) -> PublicSymbolId<'db> {
self.symbols[symbol_id] self.symbols[symbol_id]
} }
} }
/// A cross-module identifier of a scope that can be used as a salsa query parameter. /// A cross-module identifier of a scope that can be used as a salsa query parameter.
#[salsa::tracked] #[salsa::tracked]
pub struct ScopeId { pub struct ScopeId<'db> {
#[allow(clippy::used_underscore_binding)] #[allow(clippy::used_underscore_binding)]
#[id] #[id]
pub file: VfsFile, pub file: VfsFile,
@ -213,7 +209,7 @@ impl FileScopeId {
FileScopeId::from_u32(0) FileScopeId::from_u32(0)
} }
pub fn to_scope_id(self, db: &dyn Db, file: VfsFile) -> ScopeId { pub fn to_scope_id(self, db: &dyn Db, file: VfsFile) -> ScopeId<'_> {
scopes_map(db, file).get(self) scopes_map(db, file).get(self)
} }
} }
@ -284,7 +280,6 @@ impl SymbolTable {
&self.symbols[symbol_id.into()] &self.symbols[symbol_id.into()]
} }
#[allow(unused)]
pub(crate) fn symbol_ids(&self) -> impl Iterator<Item = ScopedSymbolId> { pub(crate) fn symbol_ids(&self) -> impl Iterator<Item = ScopedSymbolId> {
self.symbols.indices() self.symbols.indices()
} }

View File

@ -27,7 +27,11 @@ mod infer;
/// ///
/// Prefer [`public_symbol_ty`] when resolving the type of symbol from another file. /// Prefer [`public_symbol_ty`] when resolving the type of symbol from another file.
#[tracing::instrument(level = "debug", skip(db))] #[tracing::instrument(level = "debug", skip(db))]
pub(crate) fn expression_ty(db: &dyn Db, file: VfsFile, expression: &ast::Expr) -> Type { pub(crate) fn expression_ty<'db>(
db: &'db dyn Db,
file: VfsFile,
expression: &ast::Expr,
) -> Type<'db> {
let index = semantic_index(db, file); let index = semantic_index(db, file);
let file_scope = index.expression_scope_id(expression); let file_scope = index.expression_scope_id(expression);
let expression_id = expression.scope_ast_id(db, file, file_scope); let expression_id = expression.scope_ast_id(db, file, file_scope);
@ -61,7 +65,7 @@ pub(crate) fn expression_ty(db: &dyn Db, file: VfsFile, expression: &ast::Expr)
/// ///
/// This being a query ensures that the invalidation short-circuits if the type of this symbol didn't change. /// This being a query ensures that the invalidation short-circuits if the type of this symbol didn't change.
#[salsa::tracked] #[salsa::tracked]
pub(crate) fn public_symbol_ty(db: &dyn Db, symbol: PublicSymbolId) -> Type { pub(crate) fn public_symbol_ty<'db>(db: &'db dyn Db, symbol: PublicSymbolId<'db>) -> Type<'db> {
let _ = tracing::trace_span!("public_symbol_ty", symbol = ?symbol.debug(db)).enter(); let _ = tracing::trace_span!("public_symbol_ty", symbol = ?symbol.debug(db)).enter();
let file = symbol.file(db); let file = symbol.file(db);
@ -72,14 +76,18 @@ pub(crate) fn public_symbol_ty(db: &dyn Db, symbol: PublicSymbolId) -> Type {
} }
/// Shorthand for `public_symbol_ty` that takes a symbol name instead of a [`PublicSymbolId`]. /// Shorthand for `public_symbol_ty` that takes a symbol name instead of a [`PublicSymbolId`].
pub fn public_symbol_ty_by_name(db: &dyn Db, file: VfsFile, name: &str) -> Option<Type> { pub fn public_symbol_ty_by_name<'db>(
db: &'db dyn Db,
file: VfsFile,
name: &str,
) -> Option<Type<'db>> {
let symbol = public_symbol(db, file, name)?; let symbol = public_symbol(db, file, name)?;
Some(public_symbol_ty(db, symbol)) Some(public_symbol_ty(db, symbol))
} }
/// Infers all types for `scope`. /// Infers all types for `scope`.
#[salsa::tracked(return_ref)] #[salsa::tracked(return_ref)]
pub(crate) fn infer_types(db: &dyn Db, scope: ScopeId) -> TypeInference { pub(crate) fn infer_types<'db>(db: &'db dyn Db, scope: ScopeId<'db>) -> TypeInference<'db> {
let _ = tracing::trace_span!("infer_types", scope = ?scope.debug(db)).enter(); let _ = tracing::trace_span!("infer_types", scope = ?scope.debug(db)).enter();
let file = scope.file(db); let file = scope.file(db);
@ -120,7 +128,7 @@ pub(crate) fn infer_types(db: &dyn Db, scope: ScopeId) -> TypeInference {
/// unique ID for a type /// unique ID for a type
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum Type { pub enum Type<'db> {
/// the dynamic type: a statically-unknown set of values /// the dynamic type: a statically-unknown set of values
Any, Any,
/// the empty set of values /// the empty set of values
@ -133,20 +141,20 @@ pub enum Type {
/// the None object (TODO remove this in favor of Instance(types.NoneType) /// the None object (TODO remove this in favor of Instance(types.NoneType)
None, None,
/// a specific function object /// a specific function object
Function(TypeId<ScopedFunctionTypeId>), Function(TypeId<'db, ScopedFunctionTypeId>),
/// a specific module object /// a specific module object
Module(TypeId<ScopedModuleTypeId>), Module(TypeId<'db, ScopedModuleTypeId>),
/// a specific class object /// a specific class object
Class(TypeId<ScopedClassTypeId>), Class(TypeId<'db, ScopedClassTypeId>),
/// the set of Python objects with the given class in their __class__'s method resolution order /// the set of Python objects with the given class in their __class__'s method resolution order
Instance(TypeId<ScopedClassTypeId>), Instance(TypeId<'db, ScopedClassTypeId>),
Union(TypeId<ScopedUnionTypeId>), Union(TypeId<'db, ScopedUnionTypeId>),
Intersection(TypeId<ScopedIntersectionTypeId>), Intersection(TypeId<'db, ScopedIntersectionTypeId>),
IntLiteral(i64), IntLiteral(i64),
// TODO protocols, callable types, overloads, generics, type vars // TODO protocols, callable types, overloads, generics, type vars
} }
impl Type { impl<'db> Type<'db> {
pub const fn is_unbound(&self) -> bool { pub const fn is_unbound(&self) -> bool {
matches!(self, Type::Unbound) matches!(self, Type::Unbound)
} }
@ -155,7 +163,7 @@ impl Type {
matches!(self, Type::Unknown) matches!(self, Type::Unknown)
} }
pub fn member(&self, context: &TypingContext, name: &Name) -> Option<Type> { pub fn member(&self, context: &TypingContext<'db, '_>, name: &Name) -> Option<Type<'db>> {
match self { match self {
Type::Any => Some(Type::Any), Type::Any => Some(Type::Any),
Type::Never => todo!("attribute lookup on Never type"), Type::Never => todo!("attribute lookup on Never type"),
@ -191,18 +199,18 @@ impl Type {
/// ID that uniquely identifies a type in a program. /// ID that uniquely identifies a type in a program.
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub struct TypeId<L> { pub struct TypeId<'db, L> {
/// The scope in which this type is defined or was created. /// The scope in which this type is defined or was created.
scope: ScopeId, scope: ScopeId<'db>,
/// The type's local ID in its scope. /// The type's local ID in its scope.
scoped: L, scoped: L,
} }
impl<Id> TypeId<Id> impl<'db, Id> TypeId<'db, Id>
where where
Id: Copy, Id: Copy,
{ {
pub fn scope(&self) -> ScopeId { pub fn scope(&self) -> ScopeId<'db> {
self.scope self.scope
} }
@ -211,7 +219,7 @@ where
} }
/// Resolves the type ID to the actual type. /// Resolves the type ID to the actual type.
pub(crate) fn lookup<'a>(self, context: &'a TypingContext) -> &'a Id::Ty pub(crate) fn lookup<'a>(self, context: &'a TypingContext<'db, 'a>) -> &'a Id::Ty<'db>
where where
Id: ScopedTypeId, Id: ScopedTypeId,
{ {
@ -223,13 +231,13 @@ where
/// ID that uniquely identifies a type in a scope. /// ID that uniquely identifies a type in a scope.
pub(crate) trait ScopedTypeId { pub(crate) trait ScopedTypeId {
/// The type that this ID points to. /// The type that this ID points to.
type Ty; type Ty<'db>;
/// Looks up the type in `index`. /// Looks up the type in `index`.
/// ///
/// ## Panics /// ## Panics
/// May panic if this type is from another scope than `index`, or might just return an invalid type. /// May panic if this type is from another scope than `index`, or might just return an invalid type.
fn lookup_scoped(self, index: &TypeInference) -> &Self::Ty; fn lookup_scoped<'a, 'db>(self, index: &'a TypeInference<'db>) -> &'a Self::Ty<'db>;
} }
/// ID uniquely identifying a function type in a `scope`. /// ID uniquely identifying a function type in a `scope`.
@ -237,28 +245,28 @@ pub(crate) trait ScopedTypeId {
pub struct ScopedFunctionTypeId; pub struct ScopedFunctionTypeId;
impl ScopedTypeId for ScopedFunctionTypeId { impl ScopedTypeId for ScopedFunctionTypeId {
type Ty = FunctionType; type Ty<'db> = FunctionType<'db>;
fn lookup_scoped(self, types: &TypeInference) -> &Self::Ty { fn lookup_scoped<'a, 'db>(self, types: &'a TypeInference<'db>) -> &'a Self::Ty<'db> {
types.function_ty(self) types.function_ty(self)
} }
} }
#[derive(Debug, Eq, PartialEq, Clone)] #[derive(Debug, Eq, PartialEq, Clone)]
pub struct FunctionType { pub struct FunctionType<'a> {
/// name of the function at definition /// name of the function at definition
name: Name, name: Name,
/// types of all decorators on this function /// types of all decorators on this function
decorators: Vec<Type>, decorators: Vec<Type<'a>>,
} }
impl FunctionType { impl<'a> FunctionType<'a> {
fn name(&self) -> &str { fn name(&self) -> &str {
self.name.as_str() self.name.as_str()
} }
#[allow(unused)] #[allow(unused)]
pub(crate) fn decorators(&self) -> &[Type] { pub(crate) fn decorators(&self) -> &[Type<'a>] {
self.decorators.as_slice() self.decorators.as_slice()
} }
} }
@ -267,18 +275,18 @@ impl FunctionType {
pub struct ScopedClassTypeId; pub struct ScopedClassTypeId;
impl ScopedTypeId for ScopedClassTypeId { impl ScopedTypeId for ScopedClassTypeId {
type Ty = ClassType; type Ty<'db> = ClassType<'db>;
fn lookup_scoped(self, types: &TypeInference) -> &Self::Ty { fn lookup_scoped<'a, 'db>(self, types: &'a TypeInference<'db>) -> &'a Self::Ty<'db> {
types.class_ty(self) types.class_ty(self)
} }
} }
impl TypeId<ScopedClassTypeId> { impl<'db> TypeId<'db, ScopedClassTypeId> {
/// Returns the class member of this class named `name`. /// Returns the class member of this class named `name`.
/// ///
/// The member resolves to a member of the class itself or any of its bases. /// The member resolves to a member of the class itself or any of its bases.
fn class_member(self, context: &TypingContext, name: &Name) -> Option<Type> { fn class_member(self, context: &TypingContext<'db, '_>, name: &Name) -> Option<Type<'db>> {
if let Some(member) = self.own_class_member(context, name) { if let Some(member) = self.own_class_member(context, name) {
return Some(member); return Some(member);
} }
@ -294,7 +302,7 @@ impl TypeId<ScopedClassTypeId> {
} }
/// Returns the inferred type of the class member named `name`. /// Returns the inferred type of the class member named `name`.
fn own_class_member(self, context: &TypingContext, name: &Name) -> Option<Type> { fn own_class_member(self, context: &TypingContext<'db, '_>, name: &Name) -> Option<Type<'db>> {
let class = self.lookup(context); let class = self.lookup(context);
let symbols = symbol_table(context.db, class.body_scope); let symbols = symbol_table(context.db, class.body_scope);
@ -306,23 +314,23 @@ impl TypeId<ScopedClassTypeId> {
} }
#[derive(Debug, Eq, PartialEq, Clone)] #[derive(Debug, Eq, PartialEq, Clone)]
pub struct ClassType { pub struct ClassType<'db> {
/// Name of the class at definition /// Name of the class at definition
name: Name, name: Name,
/// Types of all class bases /// Types of all class bases
bases: Vec<Type>, bases: Vec<Type<'db>>,
body_scope: ScopeId, body_scope: ScopeId<'db>,
} }
impl ClassType { impl<'db> ClassType<'db> {
fn name(&self) -> &str { fn name(&self) -> &str {
self.name.as_str() self.name.as_str()
} }
#[allow(unused)] #[allow(unused)]
pub(super) fn bases(&self) -> &[Type] { pub(super) fn bases(&self) -> &'db [Type] {
self.bases.as_slice() self.bases.as_slice()
} }
} }
@ -331,26 +339,26 @@ impl ClassType {
pub struct ScopedUnionTypeId; pub struct ScopedUnionTypeId;
impl ScopedTypeId for ScopedUnionTypeId { impl ScopedTypeId for ScopedUnionTypeId {
type Ty = UnionType; type Ty<'db> = UnionType<'db>;
fn lookup_scoped(self, types: &TypeInference) -> &Self::Ty { fn lookup_scoped<'a, 'db>(self, types: &'a TypeInference<'db>) -> &'a Self::Ty<'db> {
types.union_ty(self) types.union_ty(self)
} }
} }
#[derive(Debug, Eq, PartialEq, Clone)] #[derive(Debug, Eq, PartialEq, Clone)]
pub struct UnionType { pub struct UnionType<'db> {
// the union type includes values in any of these types // the union type includes values in any of these types
elements: FxIndexSet<Type>, elements: FxIndexSet<Type<'db>>,
} }
struct UnionTypeBuilder<'a> { struct UnionTypeBuilder<'db, 'a> {
elements: FxIndexSet<Type>, elements: FxIndexSet<Type<'db>>,
context: &'a TypingContext<'a>, context: &'a TypingContext<'db, 'a>,
} }
impl<'a> UnionTypeBuilder<'a> { impl<'db, 'a> UnionTypeBuilder<'db, 'a> {
fn new(context: &'a TypingContext<'a>) -> Self { fn new(context: &'a TypingContext<'db, 'a>) -> Self {
Self { Self {
context, context,
elements: FxIndexSet::default(), elements: FxIndexSet::default(),
@ -358,7 +366,7 @@ impl<'a> UnionTypeBuilder<'a> {
} }
/// Adds a type to this union. /// Adds a type to this union.
fn add(mut self, ty: Type) -> Self { fn add(mut self, ty: Type<'db>) -> Self {
match ty { match ty {
Type::Union(union_id) => { Type::Union(union_id) => {
let union = union_id.lookup(self.context); let union = union_id.lookup(self.context);
@ -372,7 +380,7 @@ impl<'a> UnionTypeBuilder<'a> {
self self
} }
fn build(self) -> UnionType { fn build(self) -> UnionType<'db> {
UnionType { UnionType {
elements: self.elements, elements: self.elements,
} }
@ -383,9 +391,9 @@ impl<'a> UnionTypeBuilder<'a> {
pub struct ScopedIntersectionTypeId; pub struct ScopedIntersectionTypeId;
impl ScopedTypeId for ScopedIntersectionTypeId { impl ScopedTypeId for ScopedIntersectionTypeId {
type Ty = IntersectionType; type Ty<'db> = IntersectionType<'db>;
fn lookup_scoped(self, types: &TypeInference) -> &Self::Ty { fn lookup_scoped<'a, 'db>(self, types: &'a TypeInference<'db>) -> &'a Self::Ty<'db> {
types.intersection_ty(self) types.intersection_ty(self)
} }
} }
@ -397,26 +405,26 @@ impl ScopedTypeId for ScopedIntersectionTypeId {
// have to represent it as a single-element intersection if it did) in exchange for better // have to represent it as a single-element intersection if it did) in exchange for better
// efficiency in the within-intersection case. // efficiency in the within-intersection case.
#[derive(Debug, PartialEq, Eq, Clone)] #[derive(Debug, PartialEq, Eq, Clone)]
pub struct IntersectionType { pub struct IntersectionType<'db> {
// the intersection type includes only values in all of these types // the intersection type includes only values in all of these types
positive: FxIndexSet<Type>, positive: FxIndexSet<Type<'db>>,
// the intersection type does not include any value in any of these types // the intersection type does not include any value in any of these types
negative: FxIndexSet<Type>, negative: FxIndexSet<Type<'db>>,
} }
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub struct ScopedModuleTypeId; pub struct ScopedModuleTypeId;
impl ScopedTypeId for ScopedModuleTypeId { impl ScopedTypeId for ScopedModuleTypeId {
type Ty = ModuleType; type Ty<'db> = ModuleType;
fn lookup_scoped(self, types: &TypeInference) -> &Self::Ty { fn lookup_scoped<'a, 'db>(self, types: &'a TypeInference<'db>) -> &'a Self::Ty<'db> {
types.module_ty() types.module_ty()
} }
} }
impl TypeId<ScopedModuleTypeId> { impl<'db> TypeId<'db, ScopedModuleTypeId> {
fn member(self, context: &TypingContext, name: &Name) -> Option<Type> { fn member(self, context: &TypingContext<'db, '_>, name: &Name) -> Option<Type<'db>> {
context.public_symbol_ty(self.scope.file(context.db), name) context.public_symbol_ty(self.scope.file(context.db), name)
} }
} }
@ -431,24 +439,28 @@ pub struct ModuleType {
/// This abstraction is necessary to support a uniform API that can be used /// This abstraction is necessary to support a uniform API that can be used
/// while in the process of building the type inference structure for a scope /// while in the process of building the type inference structure for a scope
/// but also when all types should be resolved by querying the db. /// but also when all types should be resolved by querying the db.
pub struct TypingContext<'a> { pub struct TypingContext<'db, 'inference> {
db: &'a dyn Db, db: &'db dyn Db,
/// The Local type inference scope that is in the process of being built. /// The Local type inference scope that is in the process of being built.
/// ///
/// Bypass the `db` when resolving the types for this scope. /// Bypass the `db` when resolving the types for this scope.
local: Option<(ScopeId, &'a TypeInference)>, local: Option<(ScopeId<'db>, &'inference TypeInference<'db>)>,
} }
impl<'a> TypingContext<'a> { impl<'db, 'inference> TypingContext<'db, 'inference> {
/// Creates a context that resolves all types by querying the db. /// Creates a context that resolves all types by querying the db.
#[allow(unused)] #[allow(unused)]
pub(super) fn global(db: &'a dyn Db) -> Self { pub(super) fn global(db: &'db dyn Db) -> Self {
Self { db, local: None } Self { db, local: None }
} }
/// Creates a context that by-passes the `db` when resolving types from `scope_id` and instead uses `types`. /// Creates a context that by-passes the `db` when resolving types from `scope_id` and instead uses `types`.
fn scoped(db: &'a dyn Db, scope_id: ScopeId, types: &'a TypeInference) -> Self { fn scoped(
db: &'db dyn Db,
scope_id: ScopeId<'db>,
types: &'inference TypeInference<'db>,
) -> Self {
Self { Self {
db, db,
local: Some((scope_id, types)), local: Some((scope_id, types)),
@ -456,7 +468,7 @@ impl<'a> TypingContext<'a> {
} }
/// Returns the [`TypeInference`] results (not guaranteed to be complete) for `scope_id`. /// Returns the [`TypeInference`] results (not guaranteed to be complete) for `scope_id`.
fn types(&self, scope_id: ScopeId) -> &'a TypeInference { fn types(&self, scope_id: ScopeId<'db>) -> &'inference TypeInference<'db> {
if let Some((scope, local_types)) = self.local { if let Some((scope, local_types)) = self.local {
if scope == scope_id { if scope == scope_id {
return local_types; return local_types;
@ -466,7 +478,7 @@ impl<'a> TypingContext<'a> {
infer_types(self.db, scope_id) infer_types(self.db, scope_id)
} }
fn module_ty(&self, file: VfsFile) -> Type { fn module_ty(&self, file: VfsFile) -> Type<'db> {
let scope = root_scope(self.db, file); let scope = root_scope(self.db, file);
Type::Module(TypeId { Type::Module(TypeId {
@ -479,7 +491,7 @@ impl<'a> TypingContext<'a> {
/// ///
/// This function calls [`public_symbol_ty`] if the local scope isn't the module scope of `file`. /// This function calls [`public_symbol_ty`] if the local scope isn't the module scope of `file`.
/// It otherwise tries to resolve the symbol type locally. /// It otherwise tries to resolve the symbol type locally.
fn public_symbol_ty(&self, file: VfsFile, name: &Name) -> Option<Type> { fn public_symbol_ty(&self, file: VfsFile, name: &Name) -> Option<Type<'db>> {
let symbol = public_symbol(self.db, file, name)?; let symbol = public_symbol(self.db, file, name)?;
if let Some((scope, local_types)) = self.local { if let Some((scope, local_types)) = self.local {
@ -581,7 +593,7 @@ mod tests {
assert_will_run_function_query::<infer_types, _, _>( assert_will_run_function_query::<infer_types, _, _>(
&db, &db,
|ty| &ty.function, |ty| &ty.function,
a_root_scope, &a_root_scope,
&events, &events,
); );
@ -629,7 +641,7 @@ mod tests {
assert_will_not_run_function_query::<infer_types, _, _>( assert_will_not_run_function_query::<infer_types, _, _>(
&db, &db,
|ty| &ty.function, |ty| &ty.function,
a_root_scope, &a_root_scope,
&events, &events,
); );
@ -676,7 +688,7 @@ mod tests {
assert_will_not_run_function_query::<infer_types, _, _>( assert_will_not_run_function_query::<infer_types, _, _>(
&db, &db,
|ty| &ty.function, |ty| &ty.function,
a_root_scope, &a_root_scope,
&events, &events,
); );
Ok(()) Ok(())

View File

@ -4,7 +4,7 @@ use std::fmt::{Display, Formatter};
use crate::types::{IntersectionType, Type, TypingContext, UnionType}; use crate::types::{IntersectionType, Type, TypingContext, UnionType};
impl Type { impl Type<'_> {
pub fn display<'a>(&'a self, context: &'a TypingContext) -> DisplayType<'a> { pub fn display<'a>(&'a self, context: &'a TypingContext) -> DisplayType<'a> {
DisplayType { ty: self, context } DisplayType { ty: self, context }
} }
@ -12,8 +12,8 @@ impl Type {
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct DisplayType<'a> { pub struct DisplayType<'a> {
ty: &'a Type, ty: &'a Type<'a>,
context: &'a TypingContext<'a>, context: &'a TypingContext<'a, 'a>,
} }
impl Display for DisplayType<'_> { impl Display for DisplayType<'_> {
@ -71,15 +71,15 @@ impl std::fmt::Debug for DisplayType<'_> {
} }
} }
impl UnionType { impl UnionType<'_> {
fn display<'a>(&'a self, context: &'a TypingContext<'a>) -> DisplayUnionType<'a> { fn display<'a>(&'a self, context: &'a TypingContext<'a, 'a>) -> DisplayUnionType<'a> {
DisplayUnionType { context, ty: self } DisplayUnionType { context, ty: self }
} }
} }
struct DisplayUnionType<'a> { struct DisplayUnionType<'a> {
ty: &'a UnionType, ty: &'a UnionType<'a>,
context: &'a TypingContext<'a>, context: &'a TypingContext<'a, 'a>,
} }
impl Display for DisplayUnionType<'_> { impl Display for DisplayUnionType<'_> {
@ -134,15 +134,15 @@ impl std::fmt::Debug for DisplayUnionType<'_> {
} }
} }
impl IntersectionType { impl IntersectionType<'_> {
fn display<'a>(&'a self, context: &'a TypingContext<'a>) -> DisplayIntersectionType<'a> { fn display<'a>(&'a self, context: &'a TypingContext<'a, 'a>) -> DisplayIntersectionType<'a> {
DisplayIntersectionType { ty: self, context } DisplayIntersectionType { ty: self, context }
} }
} }
struct DisplayIntersectionType<'a> { struct DisplayIntersectionType<'a> {
ty: &'a IntersectionType, ty: &'a IntersectionType<'a>,
context: &'a TypingContext<'a>, context: &'a TypingContext<'a, 'a>,
} }
impl Display for DisplayIntersectionType<'_> { impl Display for DisplayIntersectionType<'_> {

View File

@ -23,33 +23,33 @@ use crate::Db;
/// The inferred types for a single scope. /// The inferred types for a single scope.
#[derive(Debug, Eq, PartialEq, Default, Clone)] #[derive(Debug, Eq, PartialEq, Default, Clone)]
pub(crate) struct TypeInference { pub(crate) struct TypeInference<'db> {
/// The type of the module if the scope is a module scope. /// The type of the module if the scope is a module scope.
module_type: Option<ModuleType>, module_type: Option<ModuleType>,
/// The types of the defined classes in this scope. /// The types of the defined classes in this scope.
class_types: IndexVec<ScopedClassTypeId, ClassType>, class_types: IndexVec<ScopedClassTypeId, ClassType<'db>>,
/// The types of the defined functions in this scope. /// The types of the defined functions in this scope.
function_types: IndexVec<ScopedFunctionTypeId, FunctionType>, function_types: IndexVec<ScopedFunctionTypeId, FunctionType<'db>>,
union_types: IndexVec<ScopedUnionTypeId, UnionType>, union_types: IndexVec<ScopedUnionTypeId, UnionType<'db>>,
intersection_types: IndexVec<ScopedIntersectionTypeId, IntersectionType>, intersection_types: IndexVec<ScopedIntersectionTypeId, IntersectionType<'db>>,
/// The types of every expression in this scope. /// The types of every expression in this scope.
expression_tys: IndexVec<ScopeExpressionId, Type>, expression_tys: IndexVec<ScopeExpressionId, Type<'db>>,
/// The public types of every symbol in this scope. /// The public types of every symbol in this scope.
symbol_tys: IndexVec<ScopedSymbolId, Type>, symbol_tys: IndexVec<ScopedSymbolId, Type<'db>>,
} }
impl TypeInference { impl<'db> TypeInference<'db> {
#[allow(unused)] #[allow(unused)]
pub(super) fn expression_ty(&self, expression: ScopeExpressionId) -> Type { pub(super) fn expression_ty(&self, expression: ScopeExpressionId) -> Type<'db> {
self.expression_tys[expression] self.expression_tys[expression]
} }
pub(super) fn symbol_ty(&self, symbol: ScopedSymbolId) -> Type { pub(super) fn symbol_ty(&self, symbol: ScopedSymbolId) -> Type<'db> {
self.symbol_tys[symbol] self.symbol_tys[symbol]
} }
@ -57,19 +57,19 @@ impl TypeInference {
self.module_type.as_ref().unwrap() self.module_type.as_ref().unwrap()
} }
pub(super) fn class_ty(&self, id: ScopedClassTypeId) -> &ClassType { pub(super) fn class_ty(&self, id: ScopedClassTypeId) -> &ClassType<'db> {
&self.class_types[id] &self.class_types[id]
} }
pub(super) fn function_ty(&self, id: ScopedFunctionTypeId) -> &FunctionType { pub(super) fn function_ty(&self, id: ScopedFunctionTypeId) -> &FunctionType<'db> {
&self.function_types[id] &self.function_types[id]
} }
pub(super) fn union_ty(&self, id: ScopedUnionTypeId) -> &UnionType { pub(super) fn union_ty(&self, id: ScopedUnionTypeId) -> &UnionType<'db> {
&self.union_types[id] &self.union_types[id]
} }
pub(super) fn intersection_ty(&self, id: ScopedIntersectionTypeId) -> &IntersectionType { pub(super) fn intersection_ty(&self, id: ScopedIntersectionTypeId) -> &IntersectionType<'db> {
&self.intersection_types[id] &self.intersection_types[id]
} }
@ -90,20 +90,20 @@ pub(super) struct TypeInferenceBuilder<'a> {
// Cached lookups // Cached lookups
index: &'a SemanticIndex, index: &'a SemanticIndex,
scope: ScopeId, scope: ScopeId<'a>,
file_scope_id: FileScopeId, file_scope_id: FileScopeId,
file_id: VfsFile, file_id: VfsFile,
symbol_table: Arc<SymbolTable>, symbol_table: Arc<SymbolTable>,
/// The type inference results /// The type inference results
types: TypeInference, types: TypeInference<'a>,
definition_tys: FxHashMap<Definition, Type>, definition_tys: FxHashMap<Definition, Type<'a>>,
children_scopes: ChildrenIter<'a>, children_scopes: ChildrenIter<'a>,
} }
impl<'a> TypeInferenceBuilder<'a> { impl<'db> TypeInferenceBuilder<'db> {
/// Creates a new builder for inferring the types of `scope`. /// Creates a new builder for inferring the types of `scope`.
pub(super) fn new(db: &'a dyn Db, scope: ScopeId, index: &'a SemanticIndex) -> Self { pub(super) fn new(db: &'db dyn Db, scope: ScopeId<'db>, index: &'db SemanticIndex) -> Self {
let file_scope_id = scope.file_scope_id(db); let file_scope_id = scope.file_scope_id(db);
let file = scope.file(db); let file = scope.file(db);
let children_scopes = index.child_scopes(file_scope_id); let children_scopes = index.child_scopes(file_scope_id);
@ -410,7 +410,7 @@ impl<'a> TypeInferenceBuilder<'a> {
} }
} }
fn infer_decorator(&mut self, decorator: &ast::Decorator) -> Type { fn infer_decorator(&mut self, decorator: &ast::Decorator) -> Type<'db> {
let ast::Decorator { let ast::Decorator {
range: _, range: _,
expression, expression,
@ -419,7 +419,7 @@ impl<'a> TypeInferenceBuilder<'a> {
self.infer_expression(expression) self.infer_expression(expression)
} }
fn infer_arguments(&mut self, arguments: &ast::Arguments) -> Vec<Type> { fn infer_arguments(&mut self, arguments: &ast::Arguments) -> Vec<Type<'db>> {
let mut types = Vec::with_capacity( let mut types = Vec::with_capacity(
arguments arguments
.args .args
@ -440,7 +440,7 @@ impl<'a> TypeInferenceBuilder<'a> {
types types
} }
fn infer_expression(&mut self, expression: &ast::Expr) -> Type { fn infer_expression(&mut self, expression: &ast::Expr) -> Type<'db> {
let ty = match expression { let ty = match expression {
ast::Expr::NoneLiteral(ast::ExprNoneLiteral { range: _ }) => Type::None, ast::Expr::NoneLiteral(ast::ExprNoneLiteral { range: _ }) => Type::None,
ast::Expr::NumberLiteral(literal) => self.infer_number_literal_expression(literal), ast::Expr::NumberLiteral(literal) => self.infer_number_literal_expression(literal),
@ -459,7 +459,7 @@ impl<'a> TypeInferenceBuilder<'a> {
} }
#[allow(clippy::unused_self)] #[allow(clippy::unused_self)]
fn infer_number_literal_expression(&mut self, literal: &ast::ExprNumberLiteral) -> Type { fn infer_number_literal_expression(&mut self, literal: &ast::ExprNumberLiteral) -> Type<'db> {
let ast::ExprNumberLiteral { range: _, value } = literal; let ast::ExprNumberLiteral { range: _, value } = literal;
match value { match value {
@ -472,7 +472,7 @@ impl<'a> TypeInferenceBuilder<'a> {
} }
} }
fn infer_named_expression(&mut self, named: &ast::ExprNamed) -> Type { fn infer_named_expression(&mut self, named: &ast::ExprNamed) -> Type<'db> {
let ast::ExprNamed { let ast::ExprNamed {
range: _, range: _,
target, target,
@ -490,7 +490,7 @@ impl<'a> TypeInferenceBuilder<'a> {
value_ty value_ty
} }
fn infer_if_expression(&mut self, if_expression: &ast::ExprIf) -> Type { fn infer_if_expression(&mut self, if_expression: &ast::ExprIf) -> Type<'db> {
let ast::ExprIf { let ast::ExprIf {
range: _, range: _,
test, test,
@ -512,7 +512,7 @@ impl<'a> TypeInferenceBuilder<'a> {
self.union_ty(union) self.union_ty(union)
} }
fn infer_name_expression(&mut self, name: &ast::ExprName) -> Type { fn infer_name_expression(&mut self, name: &ast::ExprName) -> Type<'db> {
let ast::ExprName { range: _, id, ctx } = name; let ast::ExprName { range: _, id, ctx } = name;
match ctx { match ctx {
@ -546,7 +546,7 @@ impl<'a> TypeInferenceBuilder<'a> {
} }
} }
fn infer_attribute_expression(&mut self, attribute: &ast::ExprAttribute) -> Type { fn infer_attribute_expression(&mut self, attribute: &ast::ExprAttribute) -> Type<'db> {
let ast::ExprAttribute { let ast::ExprAttribute {
value, value,
attr, attr,
@ -566,7 +566,7 @@ impl<'a> TypeInferenceBuilder<'a> {
} }
} }
fn infer_binary_expression(&mut self, binary: &ast::ExprBinOp) -> Type { fn infer_binary_expression(&mut self, binary: &ast::ExprBinOp) -> Type<'db> {
let ast::ExprBinOp { let ast::ExprBinOp {
left, left,
op, op,
@ -623,7 +623,7 @@ impl<'a> TypeInferenceBuilder<'a> {
todo!("Infer type parameters") todo!("Infer type parameters")
} }
pub(super) fn finish(mut self) -> TypeInference { pub(super) fn finish(mut self) -> TypeInference<'db> {
let symbol_tys: IndexVec<_, _> = self let symbol_tys: IndexVec<_, _> = self
.index .index
.symbol_table(self.file_scope_id) .symbol_table(self.file_scope_id)
@ -636,32 +636,32 @@ impl<'a> TypeInferenceBuilder<'a> {
self.types self.types
} }
fn union_ty(&mut self, ty: UnionType) -> Type { fn union_ty(&mut self, ty: UnionType<'db>) -> Type<'db> {
Type::Union(TypeId { Type::Union(TypeId {
scope: self.scope, scope: self.scope,
scoped: self.types.union_types.push(ty), scoped: self.types.union_types.push(ty),
}) })
} }
fn function_ty(&mut self, ty: FunctionType) -> Type { fn function_ty(&mut self, ty: FunctionType<'db>) -> Type<'db> {
Type::Function(TypeId { Type::Function(TypeId {
scope: self.scope, scope: self.scope,
scoped: self.types.function_types.push(ty), scoped: self.types.function_types.push(ty),
}) })
} }
fn class_ty(&mut self, ty: ClassType) -> Type { fn class_ty(&mut self, ty: ClassType<'db>) -> Type<'db> {
Type::Class(TypeId { Type::Class(TypeId {
scope: self.scope, scope: self.scope,
scoped: self.types.class_types.push(ty), scoped: self.types.class_types.push(ty),
}) })
} }
fn typing_context(&self) -> TypingContext { fn typing_context(&self) -> TypingContext<'db, '_> {
TypingContext::scoped(self.db, self.scope, &self.types) TypingContext::scoped(self.db, self.scope, &self.types)
} }
fn local_definition_ty(&mut self, symbol: ScopedSymbolId) -> Type { fn local_definition_ty(&mut self, symbol: ScopedSymbolId) -> Type<'db> {
let symbol = self.symbol_table.symbol(symbol); let symbol = self.symbol_table.symbol(symbol);
let mut definitions = symbol let mut definitions = symbol
.definitions() .definitions()

View File

@ -251,7 +251,6 @@ impl VfsFile {
/// an empty string, which is the closest to the content that the file contains now. Returning /// an empty string, which is the closest to the content that the file contains now. Returning
/// an empty string shouldn't be a problem because the query will be re-executed as soon as the /// an empty string shouldn't be a problem because the query will be re-executed as soon as the
/// changes are applied to the database. /// changes are applied to the database.
#[allow(unused)]
pub(crate) fn read(&self, db: &dyn Db) -> String { pub(crate) fn read(&self, db: &dyn Db) -> String {
let path = self.path(db); let path = self.path(db);