diff --git a/Cargo.lock b/Cargo.lock index b7b7feff2124c..1ba625e2ea7cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3408,7 +3408,7 @@ checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "salsa" version = "0.19.0" -source = "git+https://github.com/salsa-rs/salsa.git?rev=095d8b2b8115c3cf8bf31914dd9ea74648bb7cf9#095d8b2b8115c3cf8bf31914dd9ea74648bb7cf9" +source = "git+https://github.com/salsa-rs/salsa.git?rev=d758691ba17ee1a60c5356ea90888d529e1782ad#d758691ba17ee1a60c5356ea90888d529e1782ad" dependencies = [ "boxcar", "compact_str 0.8.1", @@ -3430,12 +3430,12 @@ dependencies = [ [[package]] name = "salsa-macro-rules" version = "0.19.0" -source = "git+https://github.com/salsa-rs/salsa.git?rev=095d8b2b8115c3cf8bf31914dd9ea74648bb7cf9#095d8b2b8115c3cf8bf31914dd9ea74648bb7cf9" +source = "git+https://github.com/salsa-rs/salsa.git?rev=d758691ba17ee1a60c5356ea90888d529e1782ad#d758691ba17ee1a60c5356ea90888d529e1782ad" [[package]] name = "salsa-macros" version = "0.19.0" -source = "git+https://github.com/salsa-rs/salsa.git?rev=095d8b2b8115c3cf8bf31914dd9ea74648bb7cf9#095d8b2b8115c3cf8bf31914dd9ea74648bb7cf9" +source = "git+https://github.com/salsa-rs/salsa.git?rev=d758691ba17ee1a60c5356ea90888d529e1782ad#d758691ba17ee1a60c5356ea90888d529e1782ad" dependencies = [ "heck", "proc-macro2", diff --git a/Cargo.toml b/Cargo.toml index a812ced4d1f47..27152d3f3912b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -123,7 +123,7 @@ rayon = { version = "1.10.0" } regex = { version = "1.10.2" } rustc-hash = { version = "2.0.0" } # When updating salsa, make sure to also update the revision in `fuzz/Cargo.toml` -salsa = { git = "https://github.com/salsa-rs/salsa.git", rev = "095d8b2b8115c3cf8bf31914dd9ea74648bb7cf9" } +salsa = { git = "https://github.com/salsa-rs/salsa.git", rev = "d758691ba17ee1a60c5356ea90888d529e1782ad" } schemars = { version = "0.8.16" } seahash = { version = "4.1.0" } serde = { version = "1.0.197", features = ["derive"] } diff --git a/crates/red_knot_project/src/db.rs b/crates/red_knot_project/src/db.rs index 1245c83055a50..6b941fe71d0f7 100644 --- a/crates/red_knot_project/src/db.rs +++ b/crates/red_knot_project/src/db.rs @@ -59,9 +59,8 @@ impl ProjectDatabase { self.with_db(|db| db.project().check(db)) } + #[tracing::instrument(level = "debug", skip(self))] pub fn check_file(&self, file: File) -> Result>, Cancelled> { - let _span = tracing::debug_span!("check_file", file=%file.path(self)).entered(); - self.with_db(|db| self.project().check_file(db, file)) } diff --git a/crates/red_knot_project/src/lib.rs b/crates/red_knot_project/src/lib.rs index 580b000486a02..5ef9be3ca9124 100644 --- a/crates/red_knot_project/src/lib.rs +++ b/crates/red_knot_project/src/lib.rs @@ -195,7 +195,8 @@ impl Project { let project_span = project_span.clone(); scope.spawn(move |_| { - let check_file_span = tracing::debug_span!(parent: &project_span, "check_file", file=%file.path(&db)); + let check_file_span = + tracing::debug_span!(parent: &project_span, "check_file", ?file); let _entered = check_file_span.entered(); let file_diagnostics = check_file_impl(&db, file); @@ -325,7 +326,7 @@ impl Project { self.files(db).contains(&file) } - #[tracing::instrument(level = "debug", skip(db))] + #[tracing::instrument(level = "debug", skip(self, db))] pub fn remove_file(self, db: &mut dyn Db, file: File) { tracing::debug!( "Removing file `{}` from project `{}`", diff --git a/crates/red_knot_python_semantic/src/module_resolver/resolver.rs b/crates/red_knot_python_semantic/src/module_resolver/resolver.rs index 26efbccf10fe8..d983e718954c5 100644 --- a/crates/red_knot_python_semantic/src/module_resolver/resolver.rs +++ b/crates/red_knot_python_semantic/src/module_resolver/resolver.rs @@ -534,7 +534,7 @@ impl<'db> Iterator for PthFileIterator<'db> { /// A thin wrapper around `ModuleName` to make it a Salsa ingredient. /// /// This is needed because Salsa requires that all query arguments are salsa ingredients. -#[salsa::interned] +#[salsa::interned(debug)] struct ModuleNameIngredient<'db> { #[return_ref] pub(super) name: ModuleName, diff --git a/crates/red_knot_python_semantic/src/semantic_index.rs b/crates/red_knot_python_semantic/src/semantic_index.rs index dd103425eb3ab..59745505b5cba 100644 --- a/crates/red_knot_python_semantic/src/semantic_index.rs +++ b/crates/red_knot_python_semantic/src/semantic_index.rs @@ -45,7 +45,7 @@ type SymbolMap = hashbrown::HashMap; /// Prefer using [`symbol_table`] when working with symbols from a single scope. #[salsa::tracked(return_ref, no_eq)] pub(crate) fn semantic_index(db: &dyn Db, file: File) -> SemanticIndex<'_> { - let _span = tracing::trace_span!("semantic_index", file = %file.path(db)).entered(); + let _span = tracing::trace_span!("semantic_index", ?file).entered(); let parsed = parsed_module(db.upcast(), file); @@ -60,8 +60,7 @@ pub(crate) fn semantic_index(db: &dyn Db, file: File) -> SemanticIndex<'_> { #[salsa::tracked] pub(crate) fn symbol_table<'db>(db: &'db dyn Db, scope: ScopeId<'db>) -> Arc { let file = scope.file(db); - let _span = - tracing::trace_span!("symbol_table", scope=?scope.as_id(), file=%file.path(db)).entered(); + let _span = tracing::trace_span!("symbol_table", scope=?scope.as_id(), ?file).entered(); let index = semantic_index(db, file); index.symbol_table(scope.file_scope_id(db)) @@ -91,8 +90,7 @@ pub(crate) fn imported_modules<'db>(db: &'db dyn Db, file: File) -> Arc(db: &'db dyn Db, scope: ScopeId<'db>) -> Arc> { let file = scope.file(db); - let _span = - tracing::trace_span!("use_def_map", scope=?scope.as_id(), file=%file.path(db)).entered(); + let _span = tracing::trace_span!("use_def_map", scope=?scope.as_id(), ?file).entered(); let index = semantic_index(db, file); index.use_def_map(scope.file_scope_id(db)) @@ -120,7 +118,7 @@ pub(crate) fn attribute_assignments<'db>( /// Returns the module global scope of `file`. #[salsa::tracked] pub(crate) fn global_scope(db: &dyn Db, file: File) -> ScopeId<'_> { - let _span = tracing::trace_span!("global_scope", file = %file.path(db)).entered(); + let _span = tracing::trace_span!("global_scope", ?file).entered(); FileScopeId::global().to_scope_id(db, file) } diff --git a/crates/red_knot_python_semantic/src/semantic_index/definition.rs b/crates/red_knot_python_semantic/src/semantic_index/definition.rs index 350483225d8e1..6739f59f9b642 100644 --- a/crates/red_knot_python_semantic/src/semantic_index/definition.rs +++ b/crates/red_knot_python_semantic/src/semantic_index/definition.rs @@ -22,7 +22,7 @@ use crate::Db; /// * a return type of a cross-module query /// * a field of a type that is a return type of a cross-module query /// * an argument of a cross-module query -#[salsa::tracked] +#[salsa::tracked(debug)] pub struct Definition<'db> { /// The file in which the definition occurs. pub(crate) file: File, diff --git a/crates/red_knot_python_semantic/src/semantic_index/expression.rs b/crates/red_knot_python_semantic/src/semantic_index/expression.rs index 6189c4cb68c56..9ac1fd30b81eb 100644 --- a/crates/red_knot_python_semantic/src/semantic_index/expression.rs +++ b/crates/red_knot_python_semantic/src/semantic_index/expression.rs @@ -30,7 +30,7 @@ pub(crate) enum ExpressionKind { /// * a return type of a cross-module query /// * a field of a type that is a return type of a cross-module query /// * an argument of a cross-module query -#[salsa::tracked] +#[salsa::tracked(debug)] pub(crate) struct Expression<'db> { /// The file in which the expression occurs. pub(crate) file: File, diff --git a/crates/red_knot_python_semantic/src/semantic_index/predicate.rs b/crates/red_knot_python_semantic/src/semantic_index/predicate.rs index f68c632ae2d8d..a46216d7bfbcb 100644 --- a/crates/red_knot_python_semantic/src/semantic_index/predicate.rs +++ b/crates/red_knot_python_semantic/src/semantic_index/predicate.rs @@ -63,7 +63,7 @@ pub(crate) enum PatternPredicateKind<'db> { Unsupported, } -#[salsa::tracked] +#[salsa::tracked(debug)] pub(crate) struct PatternPredicate<'db> { pub(crate) file: File, diff --git a/crates/red_knot_python_semantic/src/semantic_index/symbol.rs b/crates/red_knot_python_semantic/src/semantic_index/symbol.rs index 9604de384d0a1..ba5e786b04cc0 100644 --- a/crates/red_knot_python_semantic/src/semantic_index/symbol.rs +++ b/crates/red_knot_python_semantic/src/semantic_index/symbol.rs @@ -100,7 +100,7 @@ impl From for ScopedSymbolId { pub struct ScopedSymbolId; /// A cross-module identifier of a scope that can be used as a salsa query parameter. -#[salsa::tracked] +#[salsa::tracked(debug)] pub struct ScopeId<'db> { pub file: File, diff --git a/crates/red_knot_python_semantic/src/types.rs b/crates/red_knot_python_semantic/src/types.rs index 673eb000dea71..41ddaa1a4b2f5 100644 --- a/crates/red_knot_python_semantic/src/types.rs +++ b/crates/red_knot_python_semantic/src/types.rs @@ -62,7 +62,7 @@ mod property_tests; #[salsa::tracked(return_ref)] pub fn check_types(db: &dyn Db, file: File) -> TypeCheckDiagnostics { - let _span = tracing::trace_span!("check_types", file=?file.path(db)).entered(); + let _span = tracing::trace_span!("check_types", ?file).entered(); tracing::debug!("Checking file '{path}'", path = file.path(db)); @@ -3605,7 +3605,7 @@ impl<'db> InvalidTypeExpression<'db> { /// This must be a tracked struct, not an interned one, because typevar equivalence is by identity, /// not by value. Two typevars that have the same name, bound/constraints, and default, are still /// different typevars: if used in the same scope, they may be bound to different types. -#[salsa::tracked] +#[salsa::tracked(debug)] pub struct TypeVarInstance<'db> { /// The name of this TypeVar (e.g. `T`) #[return_ref] @@ -4308,7 +4308,7 @@ impl From for Truthiness { } } -#[salsa::interned] +#[salsa::interned(debug)] pub struct FunctionType<'db> { /// name of the function at definition #[return_ref] @@ -4538,7 +4538,7 @@ impl KnownFunction { /// on an instance of a class. For example, the expression `Path("a.txt").touch` creates /// a bound method object that represents the `Path.touch` method which is bound to the /// instance `Path("a.txt")`. -#[salsa::tracked] +#[salsa::tracked(debug)] pub struct BoundMethodType<'db> { /// The function that is being bound. Corresponds to the `__func__` attribute on a /// bound method object @@ -4550,7 +4550,7 @@ pub struct BoundMethodType<'db> { /// This type represents a general callable type that are used to represent `typing.Callable` /// and `lambda` expressions. -#[salsa::interned] +#[salsa::interned(debug)] pub struct GeneralCallableType<'db> { #[return_ref] signature: Signature<'db>, @@ -4734,7 +4734,7 @@ enum ParameterExpectation { TypeExpression, } -#[salsa::interned] +#[salsa::interned(debug)] pub struct ModuleLiteralType<'db> { /// The file in which this module was imported. /// @@ -4783,7 +4783,7 @@ impl<'db> ModuleLiteralType<'db> { } } -#[salsa::interned] +#[salsa::interned(debug)] pub struct TypeAliasType<'db> { #[return_ref] pub name: ast::name::Name, @@ -4811,7 +4811,7 @@ pub(super) struct MetaclassCandidate<'db> { explicit_metaclass_of: Class<'db>, } -#[salsa::interned] +#[salsa::interned(debug)] pub struct UnionType<'db> { /// The union type includes values in any of these types. #[return_ref] @@ -5022,7 +5022,7 @@ impl<'db> UnionType<'db> { } } -#[salsa::interned] +#[salsa::interned(debug)] pub struct IntersectionType<'db> { /// The intersection type includes only values in all of these types. #[return_ref] @@ -5253,7 +5253,7 @@ impl<'db> IntersectionType<'db> { } } -#[salsa::interned] +#[salsa::interned(debug)] pub struct StringLiteralType<'db> { #[return_ref] value: Box, @@ -5266,7 +5266,7 @@ impl<'db> StringLiteralType<'db> { } } -#[salsa::interned] +#[salsa::interned(debug)] pub struct BytesLiteralType<'db> { #[return_ref] value: Box<[u8]>, @@ -5278,7 +5278,7 @@ impl<'db> BytesLiteralType<'db> { } } -#[salsa::interned] +#[salsa::interned(debug)] pub struct SliceLiteralType<'db> { start: Option, stop: Option, @@ -5290,7 +5290,7 @@ impl SliceLiteralType<'_> { (self.start(db), self.stop(db), self.step(db)) } } -#[salsa::interned] +#[salsa::interned(debug)] pub struct TupleType<'db> { #[return_ref] elements: Box<[Type<'db>]>, diff --git a/crates/red_knot_python_semantic/src/types/class.rs b/crates/red_knot_python_semantic/src/types/class.rs index 02e56a3b3596c..dd0e825c85e4f 100644 --- a/crates/red_knot_python_semantic/src/types/class.rs +++ b/crates/red_knot_python_semantic/src/types/class.rs @@ -32,7 +32,7 @@ use super::{ /// /// Does not in itself represent a type, /// but is used as the inner data for several structs that *do* represent types. -#[salsa::interned] +#[salsa::interned(debug)] pub struct Class<'db> { /// Name of the class at definition #[return_ref] diff --git a/crates/red_knot_python_semantic/src/types/infer.rs b/crates/red_knot_python_semantic/src/types/infer.rs index 478f62be89840..0de06d02b281f 100644 --- a/crates/red_knot_python_semantic/src/types/infer.rs +++ b/crates/red_knot_python_semantic/src/types/infer.rs @@ -111,9 +111,7 @@ use super::{CallDunderError, ParameterExpectation, ParameterExpectations}; #[salsa::tracked(return_ref, cycle_fn=scope_cycle_recover, cycle_initial=scope_cycle_initial)] pub(crate) fn infer_scope_types<'db>(db: &'db dyn Db, scope: ScopeId<'db>) -> TypeInference<'db> { let file = scope.file(db); - let _span = - tracing::trace_span!("infer_scope_types", scope=?scope.as_id(), file=%file.path(db)) - .entered(); + let _span = tracing::trace_span!("infer_scope_types", scope=?scope.as_id(), ?file).entered(); // Using the index here is fine because the code below depends on the AST anyway. // The isolation of the query is by the return inferred types. @@ -146,7 +144,7 @@ pub(crate) fn infer_definition_types<'db>( let _span = tracing::trace_span!( "infer_definition_types", range = ?definition.kind(db).target_range(), - file = %file.path(db) + ?file ) .entered(); @@ -185,7 +183,7 @@ pub(crate) fn infer_deferred_types<'db>( "infer_deferred_types", definition = ?definition.as_id(), range = ?definition.kind(db).target_range(), - file = %file.path(db) + ?file ) .entered(); @@ -221,7 +219,7 @@ pub(crate) fn infer_expression_types<'db>( "infer_expression_types", expression = ?expression.as_id(), range = ?expression.node_ref(db).range(), - file = %file.path(db) + ?file ) .entered(); @@ -302,8 +300,7 @@ fn single_expression_cycle_initial<'db>( pub(super) fn infer_unpack_types<'db>(db: &'db dyn Db, unpack: Unpack<'db>) -> UnpackResult<'db> { let file = unpack.file(db); let _span = - tracing::trace_span!("infer_unpack_types", range=?unpack.range(db), file=%file.path(db)) - .entered(); + tracing::trace_span!("infer_unpack_types", range=?unpack.range(db), ?file).entered(); let mut unpacker = Unpacker::new(db, unpack.scope(db)); unpacker.unpack(unpack.target(db), unpack.value(db)); diff --git a/crates/red_knot_python_semantic/src/types/string_annotation.rs b/crates/red_knot_python_semantic/src/types/string_annotation.rs index e5a5b4741fe9c..d472a1d578aed 100644 --- a/crates/red_knot_python_semantic/src/types/string_annotation.rs +++ b/crates/red_knot_python_semantic/src/types/string_annotation.rs @@ -134,7 +134,8 @@ pub(crate) fn parse_string_annotation( let file = context.file(); let db = context.db(); - let _span = tracing::trace_span!("parse_string_annotation", string=?string_expr.range(), file=%file.path(db)).entered(); + let _span = tracing::trace_span!("parse_string_annotation", string=?string_expr.range(), ?file) + .entered(); let source = source_text(db.upcast(), file); diff --git a/crates/red_knot_python_semantic/src/unpack.rs b/crates/red_knot_python_semantic/src/unpack.rs index 00736e7110ea4..c7f16459988ce 100644 --- a/crates/red_knot_python_semantic/src/unpack.rs +++ b/crates/red_knot_python_semantic/src/unpack.rs @@ -26,7 +26,7 @@ use crate::Db; /// * a return type of a cross-module query /// * a field of a type that is a return type of a cross-module query /// * an argument of a cross-module query -#[salsa::tracked] +#[salsa::tracked(debug)] pub(crate) struct Unpack<'db> { pub(crate) file: File, diff --git a/crates/ruff_db/src/files.rs b/crates/ruff_db/src/files.rs index 46f23fe2e4ff6..9b7cabe426298 100644 --- a/crates/ruff_db/src/files.rs +++ b/crates/ruff_db/src/files.rs @@ -1,14 +1,14 @@ -use std::fmt::Formatter; +use std::fmt; use std::sync::Arc; use countme::Count; use dashmap::mapref::entry::Entry; -use salsa::{Durability, Setter}; - pub use file_root::{FileRoot, FileRootKind}; pub use path::FilePath; use ruff_notebook::{Notebook, NotebookError}; use ruff_python_ast::PySourceType; +use salsa::plumbing::AsId; +use salsa::{Durability, Setter}; use crate::file_revision::FileRevision; use crate::files::file_root::FileRoots; @@ -255,7 +255,7 @@ impl Files { } } -impl std::fmt::Debug for Files { +impl fmt::Debug for Files { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let mut map = f.debug_map(); @@ -429,6 +429,24 @@ impl File { } } +impl fmt::Debug for File { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + salsa::with_attached_database(|db| { + if f.alternate() { + f.debug_struct("File") + .field("path", &self.path(db)) + .field("status", &self.status(db)) + .field("permissions", &self.permissions(db)) + .field("revision", &self.revision(db)) + .finish() + } else { + f.debug_tuple("File").field(&self.path(db)).finish() + } + }) + .unwrap_or_else(|| f.debug_tuple("file").field(&self.as_id()).finish()) + } +} + /// A virtual file that doesn't exist on the file system. /// /// This is a wrapper around a [`File`] that provides additional methods to interact with a virtual @@ -481,8 +499,8 @@ pub enum FileError { NotFound, } -impl std::fmt::Display for FileError { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { +impl fmt::Display for FileError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result { match self { FileError::IsADirectory => f.write_str("Is a directory"), FileError::NotFound => f.write_str("Not found"), diff --git a/crates/ruff_db/src/files/file_root.rs b/crates/ruff_db/src/files/file_root.rs index e4fe54102b6d6..c991d337ac2a8 100644 --- a/crates/ruff_db/src/files/file_root.rs +++ b/crates/ruff_db/src/files/file_root.rs @@ -16,7 +16,7 @@ use crate::Db; /// The main usage of file roots is to determine a file's durability. But it can also be used /// to make a salsa query dependent on whether a file in a root has changed without writing any /// manual invalidation logic. -#[salsa::input] +#[salsa::input(debug)] pub struct FileRoot { /// The path of a root is guaranteed to never change. #[return_ref] diff --git a/crates/ruff_db/src/parsed.rs b/crates/ruff_db/src/parsed.rs index 4f0971f5b7a8a..33c7b7425e00b 100644 --- a/crates/ruff_db/src/parsed.rs +++ b/crates/ruff_db/src/parsed.rs @@ -22,7 +22,7 @@ use crate::Db; /// for determining if a query result is unchanged. #[salsa::tracked(return_ref, no_eq)] pub fn parsed_module(db: &dyn Db, file: File) -> ParsedModule { - let _span = tracing::trace_span!("parsed_module", file = %file.path(db)).entered(); + let _span = tracing::trace_span!("parsed_module", ?file).entered(); let source = source_text(db, file); let path = file.path(db); diff --git a/crates/ruff_db/src/source.rs b/crates/ruff_db/src/source.rs index 6eb1f5e7085e6..6d7d9157519c2 100644 --- a/crates/ruff_db/src/source.rs +++ b/crates/ruff_db/src/source.rs @@ -159,7 +159,7 @@ pub enum SourceTextError { /// Computes the [`LineIndex`] for `file`. #[salsa::tracked] pub fn line_index(db: &dyn Db, file: File) -> LineIndex { - let _span = tracing::trace_span!("line_index", file = ?file.path(db)).entered(); + let _span = tracing::trace_span!("line_index", ?file).entered(); let source = source_text(db, file); diff --git a/crates/ruff_db/src/testing.rs b/crates/ruff_db/src/testing.rs index 880a6fccc8867..9bd683ccad8d8 100644 --- a/crates/ruff_db/src/testing.rs +++ b/crates/ruff_db/src/testing.rs @@ -223,7 +223,7 @@ fn query_was_not_run() { use crate::tests::TestDb; use salsa::prelude::*; - #[salsa::input] + #[salsa::input(debug)] struct Input { text: String, } @@ -258,7 +258,7 @@ fn query_was_not_run_fails_if_query_was_run() { use crate::tests::TestDb; use salsa::prelude::*; - #[salsa::input] + #[salsa::input(debug)] struct Input { text: String, } @@ -321,7 +321,7 @@ fn query_was_run_fails_if_query_was_not_run() { use crate::tests::TestDb; use salsa::prelude::*; - #[salsa::input] + #[salsa::input(debug)] struct Input { text: String, } diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 64e8dc0f898bb..20fa191972b2c 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -29,7 +29,7 @@ ruff_python_formatter = { path = "../crates/ruff_python_formatter" } ruff_text_size = { path = "../crates/ruff_text_size" } libfuzzer-sys = { git = "https://github.com/rust-fuzz/libfuzzer", default-features = false } -salsa = { git = "https://github.com/salsa-rs/salsa.git", rev = "095d8b2b8115c3cf8bf31914dd9ea74648bb7cf9" } +salsa = { git = "https://github.com/salsa-rs/salsa.git", rev = "d758691ba17ee1a60c5356ea90888d529e1782ad" } similar = { version = "2.5.0" } tracing = { version = "0.1.40" }