[ty] Track heap usage of salsa structs (#19790)

Co-authored-by: Micha Reiser <micha@reiser.io>
This commit is contained in:
Ibraheem Ahmed 2025-08-12 07:28:44 -04:00 committed by GitHub
parent 6a05d46ef6
commit f34b65b7a0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
35 changed files with 269 additions and 124 deletions

1
Cargo.lock generated
View file

@ -3073,6 +3073,7 @@ name = "ruff_memory_usage"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"get-size2", "get-size2",
"ordermap",
] ]
[[package]] [[package]]

View file

@ -9,7 +9,7 @@ use crate::system::file_time_now;
/// * The last modification time of the file. /// * The last modification time of the file.
/// * The hash of the file's content. /// * The hash of the file's content.
/// * The revision as it comes from an external system, for example the LSP. /// * The revision as it comes from an external system, for example the LSP.
#[derive(Copy, Clone, Debug, Eq, PartialEq, Default)] #[derive(Copy, Clone, Debug, Eq, PartialEq, Default, get_size2::GetSize)]
pub struct FileRevision(u128); pub struct FileRevision(u128);
impl FileRevision { impl FileRevision {

View file

@ -289,7 +289,7 @@ impl std::panic::RefUnwindSafe for Files {}
/// # Ordering /// # Ordering
/// Ordering is based on the file's salsa-assigned id and not on its values. /// Ordering is based on the file's salsa-assigned id and not on its values.
/// The id may change between runs. /// The id may change between runs.
#[salsa::input] #[salsa::input(heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)] #[derive(PartialOrd, Ord)]
pub struct File { pub struct File {
/// The path of the file (immutable). /// The path of the file (immutable).
@ -521,7 +521,7 @@ impl VirtualFile {
// The types in here need to be public because they're salsa ingredients but we // The types in here need to be public because they're salsa ingredients but we
// don't want them to be publicly accessible. That's why we put them into a private module. // don't want them to be publicly accessible. That's why we put them into a private module.
mod private { mod private {
#[derive(Copy, Clone, Debug, Eq, PartialEq, Default)] #[derive(Copy, Clone, Debug, Eq, PartialEq, Default, get_size2::GetSize)]
pub enum FileStatus { pub enum FileStatus {
/// The file exists. /// The file exists.
#[default] #[default]

View file

@ -16,7 +16,7 @@ use crate::system::{SystemPath, SystemPathBuf};
/// The main usage of file roots is to determine a file's durability. But it can also be used /// 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 /// to make a salsa query dependent on whether a file in a root has changed without writing any
/// manual invalidation logic. /// manual invalidation logic.
#[salsa::input(debug)] #[salsa::input(debug, heap_size=ruff_memory_usage::heap_size)]
pub struct FileRoot { pub struct FileRoot {
/// The path of a root is guaranteed to never change. /// The path of a root is guaranteed to never change.
#[returns(deref)] #[returns(deref)]
@ -37,7 +37,7 @@ impl FileRoot {
} }
} }
#[derive(Copy, Clone, Debug, Eq, PartialEq)] #[derive(Copy, Clone, Debug, Eq, PartialEq, get_size2::GetSize)]
pub enum FileRootKind { pub enum FileRootKind {
/// The root of a project. /// The root of a project.
Project, Project,

View file

@ -11,7 +11,7 @@ use std::fmt::{Display, Formatter};
/// * a file stored on the [host system](crate::system::System). /// * a file stored on the [host system](crate::system::System).
/// * a virtual file stored on the [host system](crate::system::System). /// * a virtual file stored on the [host system](crate::system::System).
/// * a vendored file stored in the [vendored file system](crate::vendored::VendoredFileSystem). /// * a vendored file stored in the [vendored file system](crate::vendored::VendoredFileSystem).
#[derive(Clone, Debug, Eq, PartialEq, Hash)] #[derive(Clone, Debug, Eq, PartialEq, Hash, get_size2::GetSize)]
pub enum FilePath { pub enum FilePath {
/// Path to a file on the [host system](crate::system::System). /// Path to a file on the [host system](crate::system::System).
System(SystemPathBuf), System(SystemPathBuf),

View file

@ -762,7 +762,7 @@ impl SystemVirtualPath {
} }
/// An owned, virtual path on [`System`](`super::System`) (akin to [`String`]). /// An owned, virtual path on [`System`](`super::System`) (akin to [`String`]).
#[derive(Eq, PartialEq, Clone, Hash, PartialOrd, Ord)] #[derive(Eq, PartialEq, Clone, Hash, PartialOrd, Ord, get_size2::GetSize)]
pub struct SystemVirtualPathBuf(String); pub struct SystemVirtualPathBuf(String);
impl SystemVirtualPathBuf { impl SystemVirtualPathBuf {

View file

@ -12,6 +12,7 @@ license = { workspace = true }
[dependencies] [dependencies]
get-size2 = { workspace = true } get-size2 = { workspace = true }
ordermap = { workspace = true }
[lints] [lints]
workspace = true workspace = true

View file

@ -1,6 +1,7 @@
use std::sync::{LazyLock, Mutex}; use std::sync::{LazyLock, Mutex};
use get_size2::{GetSize, StandardTracker}; use get_size2::{GetSize, StandardTracker};
use ordermap::OrderSet;
/// Returns the memory usage of the provided object, using a global tracker to avoid /// Returns the memory usage of the provided object, using a global tracker to avoid
/// double-counting shared objects. /// double-counting shared objects.
@ -12,3 +13,8 @@ pub fn heap_size<T: GetSize>(value: &T) -> usize {
.get_heap_size_with_tracker(&mut *TRACKER.lock().unwrap()) .get_heap_size_with_tracker(&mut *TRACKER.lock().unwrap())
.0 .0
} }
/// An implementation of [`GetSize::get_heap_size`] for [`OrderSet`].
pub fn order_set_heap_size<T: GetSize, S>(set: &OrderSet<T, S>) -> usize {
(set.capacity() * T::get_stack_size()) + set.iter().map(heap_size).sum::<usize>()
}

View file

@ -128,18 +128,49 @@ impl ProjectDatabase {
/// to the CLI after a typechecker run. /// to the CLI after a typechecker run.
pub fn salsa_memory_dump(&self) -> SalsaMemoryDump { pub fn salsa_memory_dump(&self) -> SalsaMemoryDump {
let memory_usage = <dyn salsa::Database>::memory_usage(self); let memory_usage = <dyn salsa::Database>::memory_usage(self);
let mut ingredients = memory_usage.structs; let mut ingredients = memory_usage
let mut memos = memory_usage.queries.into_iter().collect::<Vec<_>>(); .structs
.into_iter()
.filter(|ingredient| ingredient.count() > 0)
.collect::<Vec<_>>();
let mut memos = memory_usage
.queries
.into_iter()
.filter(|(_, memos)| memos.count() > 0)
.collect::<Vec<_>>();
ingredients.sort_by_key(|ingredient| cmp::Reverse(ingredient.size_of_fields())); ingredients.sort_by_key(|ingredient| {
memos.sort_by_key(|(_, memo)| cmp::Reverse(memo.size_of_fields())); let heap_size = ingredient.heap_size_of_fields().unwrap_or_else(|| {
// Salsa currently does not expose a way to track the heap size of interned
// query arguments.
if !ingredient.debug_name().contains("interned_arguments") {
tracing::warn!(
"expected `heap_size` to be provided by Salsa struct `{}`",
ingredient.debug_name()
);
}
0
});
cmp::Reverse(ingredient.size_of_fields() + heap_size)
});
memos.sort_by_key(|(query, memo)| {
let heap_size = memo.heap_size_of_fields().unwrap_or_else(|| {
tracing::warn!("expected `heap_size` to be provided by Salsa query `{query}`");
0
});
cmp::Reverse(memo.size_of_fields() + heap_size)
});
let mut total_fields = 0; let mut total_fields = 0;
let mut total_metadata = 0; let mut total_metadata = 0;
for ingredient in &ingredients { for ingredient in &ingredients {
total_metadata += ingredient.size_of_metadata();
total_fields += ingredient.size_of_fields(); total_fields += ingredient.size_of_fields();
total_fields += ingredient.heap_size_of_fields().unwrap_or(0); total_fields += ingredient.heap_size_of_fields().unwrap_or(0);
total_metadata += ingredient.size_of_metadata();
} }
let mut total_memo_fields = 0; let mut total_memo_fields = 0;
@ -171,7 +202,7 @@ impl std::fmt::Debug for ProjectDatabase {
} }
} }
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)] #[derive(Default, Debug, Clone, Copy, PartialEq, Eq, get_size2::GetSize)]
#[cfg_attr(test, derive(serde::Serialize))] #[cfg_attr(test, derive(serde::Serialize))]
pub enum CheckMode { pub enum CheckMode {
/// Checks the open files in the project. /// Checks the open files in the project.
@ -281,12 +312,15 @@ impl SalsaMemoryDump {
writeln!(f, "=======SALSA STRUCTS=======")?; writeln!(f, "=======SALSA STRUCTS=======")?;
for ingredient in ingredients { for ingredient in ingredients {
let size_of_fields =
ingredient.size_of_fields() + ingredient.heap_size_of_fields().unwrap_or(0);
writeln!( writeln!(
f, f,
"{:<50} metadata={:<8} fields={:<8} count={}", "{:<50} metadata={:<8} fields={:<8} count={}",
format!("`{}`", ingredient.debug_name()), format!("`{}`", ingredient.debug_name()),
format!("{:.2}MB", bytes_to_mb(ingredient.size_of_metadata())), format!("{:.2}MB", bytes_to_mb(ingredient.size_of_metadata())),
format!("{:.2}MB", bytes_to_mb(ingredient.size_of_fields())), format!("{:.2}MB", bytes_to_mb(size_of_fields)),
ingredient.count() ingredient.count()
)?; )?;
} }
@ -294,13 +328,16 @@ impl SalsaMemoryDump {
writeln!(f, "=======SALSA QUERIES=======")?; writeln!(f, "=======SALSA QUERIES=======")?;
for (query_fn, memo) in memos { for (query_fn, memo) in memos {
let size_of_fields =
memo.size_of_fields() + memo.heap_size_of_fields().unwrap_or(0);
writeln!(f, "`{query_fn} -> {}`", memo.debug_name())?; writeln!(f, "`{query_fn} -> {}`", memo.debug_name())?;
writeln!( writeln!(
f, f,
" metadata={:<8} fields={:<8} count={}", " metadata={:<8} fields={:<8} count={}",
format!("{:.2}MB", bytes_to_mb(memo.size_of_metadata())), format!("{:.2}MB", bytes_to_mb(memo.size_of_metadata())),
format!("{:.2}MB", bytes_to_mb(memo.size_of_fields())), format!("{:.2}MB", bytes_to_mb(size_of_fields)),
memo.count() memo.count()
)?; )?;
} }

View file

@ -20,7 +20,7 @@ use crate::{IOErrorDiagnostic, Project};
/// so no query can be depending on the contents of the indexed files before that. All subsequent mutations to /// so no query can be depending on the contents of the indexed files before that. All subsequent mutations to
/// the indexed files must go through `IndexedMut`, which uses the Salsa setter `project.set_file_set` to /// the indexed files must go through `IndexedMut`, which uses the Salsa setter `project.set_file_set` to
/// ensure that Salsa always knows when the set of indexed files have changed. /// ensure that Salsa always knows when the set of indexed files have changed.
#[derive(Debug)] #[derive(Debug, get_size2::GetSize)]
pub struct IndexedFiles { pub struct IndexedFiles {
state: std::sync::Mutex<State>, state: std::sync::Mutex<State>,
} }
@ -102,7 +102,7 @@ impl Default for IndexedFiles {
} }
} }
#[derive(Debug)] #[derive(Debug, get_size2::GetSize)]
enum State { enum State {
/// The files of a package haven't been indexed yet. /// The files of a package haven't been indexed yet.
Lazy, Lazy,
@ -150,7 +150,7 @@ pub struct Indexed<'db> {
_lifetime: PhantomData<&'db ()>, _lifetime: PhantomData<&'db ()>,
} }
#[derive(Debug)] #[derive(Debug, get_size2::GetSize)]
struct IndexedInner { struct IndexedInner {
files: FxHashSet<File>, files: FxHashSet<File>,
diagnostics: Vec<IOErrorDiagnostic>, diagnostics: Vec<IOErrorDiagnostic>,

View file

@ -13,7 +13,7 @@ mod portable;
/// Path filtering based on an an exclude and include glob pattern set. /// Path filtering based on an an exclude and include glob pattern set.
/// ///
/// Exclude patterns take precedence over includes. /// Exclude patterns take precedence over includes.
#[derive(Clone, Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq, get_size2::GetSize)]
pub struct IncludeExcludeFilter { pub struct IncludeExcludeFilter {
include: IncludeFilter, include: IncludeFilter,
exclude: ExcludeFilter, exclude: ExcludeFilter,

View file

@ -23,7 +23,7 @@ use crate::glob::portable::AbsolutePortableGlobPattern;
/// Two filters are equal if they're constructed from the same patterns (including order). /// Two filters are equal if they're constructed from the same patterns (including order).
/// Two filters that exclude the exact same files but were constructed from different patterns aren't considered /// Two filters that exclude the exact same files but were constructed from different patterns aren't considered
/// equal. /// equal.
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq, get_size2::GetSize)]
pub(crate) struct ExcludeFilter { pub(crate) struct ExcludeFilter {
ignore: Gitignore, ignore: Gitignore,
} }
@ -118,10 +118,12 @@ impl ExcludeFilterBuilder {
/// Two ignore matches are only equal if they're constructed from the same patterns (including order). /// Two ignore matches are only equal if they're constructed from the same patterns (including order).
/// Two matchers that were constructed from different patterns but result in /// Two matchers that were constructed from different patterns but result in
/// including the same files don't compare equal. /// including the same files don't compare equal.
#[derive(Clone)] #[derive(Clone, get_size2::GetSize)]
struct Gitignore { struct Gitignore {
#[get_size(ignore)]
set: GlobSet, set: GlobSet,
globs: Vec<IgnoreGlob>, globs: Vec<IgnoreGlob>,
#[get_size(ignore)]
matches: Option<Arc<Pool<Vec<usize>>>>, matches: Option<Arc<Pool<Vec<usize>>>>,
} }
@ -185,7 +187,7 @@ enum Match {
Allow, Allow,
} }
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq, get_size2::GetSize)]
struct IgnoreGlob { struct IgnoreGlob {
/// The pattern that was originally parsed. /// The pattern that was originally parsed.
original: String, original: String,

View file

@ -29,13 +29,20 @@ const DFA_SIZE_LIMIT: usize = 1_000_000;
/// ///
/// Because of that, two filters that include the exact same files but were /// Because of that, two filters that include the exact same files but were
/// constructed from different patterns (or even just order) compare unequal. /// constructed from different patterns (or even just order) compare unequal.
#[derive(Clone)] #[derive(Clone, get_size2::GetSize)]
pub(crate) struct IncludeFilter { pub(crate) struct IncludeFilter {
#[get_size(ignore)]
glob_set: GlobSet, glob_set: GlobSet,
original_patterns: Box<[String]>, original_patterns: Box<[String]>,
#[get_size(size_fn = dfa_memory_usage)]
dfa: Option<dfa::dense::DFA<Vec<u32>>>, dfa: Option<dfa::dense::DFA<Vec<u32>>>,
} }
#[allow(clippy::ref_option)]
fn dfa_memory_usage(dfa: &Option<dfa::dense::DFA<Vec<u32>>>) -> usize {
dfa.as_ref().map(dfa::dense::DFA::memory_usage).unwrap_or(0)
}
impl IncludeFilter { impl IncludeFilter {
/// Whether the file matches any of the globs. /// Whether the file matches any of the globs.
pub(crate) fn match_file(&self, path: impl AsRef<SystemPath>) -> bool { pub(crate) fn match_file(&self, path: impl AsRef<SystemPath>) -> bool {

View file

@ -55,7 +55,7 @@ pub fn default_lints_registry() -> LintRegistry {
/// 2. Running `ruff check` with different target versions results in different programs (settings) but /// 2. Running `ruff check` with different target versions results in different programs (settings) but
/// it remains the same project. That's why program is a narrowed view of the project only /// it remains the same project. That's why program is a narrowed view of the project only
/// holding on to the most fundamental settings required for checking. /// holding on to the most fundamental settings required for checking.
#[salsa::input] #[salsa::input(heap_size=ruff_memory_usage::heap_size)]
#[derive(Debug)] #[derive(Debug)]
pub struct Project { pub struct Project {
/// The files that are open in the project, [`None`] if there are no open files. /// The files that are open in the project, [`None`] if there are no open files.
@ -636,7 +636,7 @@ impl Iterator for ProjectFilesIter<'_> {
impl FusedIterator for ProjectFilesIter<'_> {} impl FusedIterator for ProjectFilesIter<'_> {}
#[derive(Debug, Clone)] #[derive(Debug, Clone, get_size2::GetSize)]
pub struct IOErrorDiagnostic { pub struct IOErrorDiagnostic {
file: Option<File>, file: Option<File>,
error: IOErrorKind, error: IOErrorKind,
@ -652,7 +652,7 @@ impl IOErrorDiagnostic {
} }
} }
#[derive(Error, Debug, Clone)] #[derive(Error, Debug, Clone, get_size2::GetSize)]
enum IOErrorKind { enum IOErrorKind {
#[error(transparent)] #[error(transparent)]
Walk(#[from] walk::WalkError), Walk(#[from] walk::WalkError),

View file

@ -19,7 +19,7 @@ pub mod pyproject;
pub mod settings; pub mod settings;
pub mod value; pub mod value;
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq, get_size2::GetSize)]
#[cfg_attr(test, derive(serde::Serialize))] #[cfg_attr(test, derive(serde::Serialize))]
pub struct ProjectMetadata { pub struct ProjectMetadata {
pub(super) name: Name, pub(super) name: Name,

View file

@ -36,7 +36,16 @@ use ty_python_semantic::{
}; };
#[derive( #[derive(
Debug, Default, Clone, PartialEq, Eq, Combine, Serialize, Deserialize, OptionsMetadata, Debug,
Default,
Clone,
PartialEq,
Eq,
Combine,
Serialize,
Deserialize,
OptionsMetadata,
get_size2::GetSize,
)] )]
#[serde(rename_all = "kebab-case", deny_unknown_fields)] #[serde(rename_all = "kebab-case", deny_unknown_fields)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
@ -395,7 +404,16 @@ impl Options {
} }
#[derive( #[derive(
Debug, Default, Clone, Eq, PartialEq, Combine, Serialize, Deserialize, OptionsMetadata, Debug,
Default,
Clone,
Eq,
PartialEq,
Combine,
Serialize,
Deserialize,
OptionsMetadata,
get_size2::GetSize,
)] )]
#[serde(rename_all = "kebab-case", deny_unknown_fields)] #[serde(rename_all = "kebab-case", deny_unknown_fields)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
@ -516,7 +534,16 @@ pub struct EnvironmentOptions {
} }
#[derive( #[derive(
Debug, Default, Clone, Eq, PartialEq, Combine, Serialize, Deserialize, OptionsMetadata, Debug,
Default,
Clone,
Eq,
PartialEq,
Combine,
Serialize,
Deserialize,
OptionsMetadata,
get_size2::GetSize,
)] )]
#[serde(rename_all = "kebab-case", deny_unknown_fields)] #[serde(rename_all = "kebab-case", deny_unknown_fields)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
@ -679,11 +706,14 @@ impl SrcOptions {
} }
} }
#[derive(Debug, Default, Clone, Eq, PartialEq, Combine, Serialize, Deserialize, Hash)] #[derive(
Debug, Default, Clone, Eq, PartialEq, Combine, Serialize, Deserialize, Hash, get_size2::GetSize,
)]
#[serde(rename_all = "kebab-case", transparent)] #[serde(rename_all = "kebab-case", transparent)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub struct Rules { pub struct Rules {
#[cfg_attr(feature = "schemars", schemars(with = "schema::Rules"))] #[cfg_attr(feature = "schemars", schemars(with = "schema::Rules"))]
#[get_size(ignore)] // TODO: Add `GetSize` support for `OrderMap`.
inner: OrderMap<RangedValue<String>, RangedValue<Level>, BuildHasherDefault<FxHasher>>, inner: OrderMap<RangedValue<String>, RangedValue<Level>, BuildHasherDefault<FxHasher>>,
} }
@ -1002,7 +1032,9 @@ impl GlobFilterContext {
} }
/// The diagnostic output format. /// The diagnostic output format.
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)] #[derive(
Debug, Default, Clone, Copy, Eq, PartialEq, Serialize, Deserialize, get_size2::GetSize,
)]
#[serde(rename_all = "kebab-case", deny_unknown_fields)] #[serde(rename_all = "kebab-case", deny_unknown_fields)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub enum OutputFormat { pub enum OutputFormat {
@ -1035,7 +1067,16 @@ impl From<OutputFormat> for DiagnosticFormat {
} }
#[derive( #[derive(
Debug, Default, Clone, Eq, PartialEq, Combine, Serialize, Deserialize, OptionsMetadata, Debug,
Default,
Clone,
Eq,
PartialEq,
Combine,
Serialize,
Deserialize,
OptionsMetadata,
get_size2::GetSize,
)] )]
#[serde(rename_all = "kebab-case", deny_unknown_fields)] #[serde(rename_all = "kebab-case", deny_unknown_fields)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
@ -1095,7 +1136,18 @@ pub struct TerminalOptions {
/// [tool.ty.overrides.rules] /// [tool.ty.overrides.rules]
/// possibly-unresolved-reference = "ignore" /// possibly-unresolved-reference = "ignore"
/// ``` /// ```
#[derive(Debug, Default, Clone, PartialEq, Eq, Combine, Serialize, Deserialize, RustDoc)] #[derive(
Debug,
Default,
Clone,
PartialEq,
Eq,
Combine,
Serialize,
Deserialize,
RustDoc,
get_size2::GetSize,
)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[serde(transparent)] #[serde(transparent)]
pub struct OverridesOptions(Vec<RangedValue<OverrideOptions>>); pub struct OverridesOptions(Vec<RangedValue<OverrideOptions>>);
@ -1119,7 +1171,16 @@ impl Deref for OverridesOptions {
} }
#[derive( #[derive(
Debug, Default, Clone, Eq, PartialEq, Combine, Serialize, Deserialize, OptionsMetadata, Debug,
Default,
Clone,
Eq,
PartialEq,
Combine,
Serialize,
Deserialize,
OptionsMetadata,
get_size2::GetSize,
)] )]
#[serde(rename_all = "kebab-case", deny_unknown_fields)] #[serde(rename_all = "kebab-case", deny_unknown_fields)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
@ -1339,7 +1400,7 @@ impl RangedValue<OverrideOptions> {
} }
/// The options for an override but without the include/exclude patterns. /// The options for an override but without the include/exclude patterns.
#[derive(Debug, Clone, PartialEq, Eq, Hash, Combine)] #[derive(Debug, Clone, PartialEq, Eq, Hash, Combine, get_size2::GetSize)]
pub(super) struct InnerOverrideOptions { pub(super) struct InnerOverrideOptions {
/// Raw rule options as specified in the configuration. /// Raw rule options as specified in the configuration.
/// Used when multiple overrides match a file and need to be merged. /// Used when multiple overrides match a file and need to be merged.
@ -1463,7 +1524,7 @@ pub enum TyTomlError {
TomlSyntax(#[from] toml::de::Error), TomlSyntax(#[from] toml::de::Error),
} }
#[derive(Debug, PartialEq, Eq, Clone)] #[derive(Debug, PartialEq, Eq, Clone, get_size2::GetSize)]
pub struct OptionDiagnostic { pub struct OptionDiagnostic {
id: DiagnosticId, id: DiagnosticId,
message: String, message: String,

View file

@ -20,7 +20,7 @@ use crate::{Db, glob::IncludeExcludeFilter};
/// This can be achieved by adding a salsa query for the type checking specific settings. /// This can be achieved by adding a salsa query for the type checking specific settings.
/// ///
/// Settings that are part of [`ty_python_semantic::ProgramSettings`] are not included here. /// Settings that are part of [`ty_python_semantic::ProgramSettings`] are not included here.
#[derive(Clone, Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq, get_size2::GetSize)]
pub struct Settings { pub struct Settings {
pub(super) rules: Arc<RuleSelection>, pub(super) rules: Arc<RuleSelection>,
pub(super) terminal: TerminalSettings, pub(super) terminal: TerminalSettings,
@ -56,20 +56,20 @@ impl Settings {
} }
} }
#[derive(Debug, Clone, PartialEq, Eq, Default)] #[derive(Debug, Clone, PartialEq, Eq, Default, get_size2::GetSize)]
pub struct TerminalSettings { pub struct TerminalSettings {
pub output_format: OutputFormat, pub output_format: OutputFormat,
pub error_on_warning: bool, pub error_on_warning: bool,
} }
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq, get_size2::GetSize)]
pub struct SrcSettings { pub struct SrcSettings {
pub respect_ignore_files: bool, pub respect_ignore_files: bool,
pub files: IncludeExcludeFilter, pub files: IncludeExcludeFilter,
} }
/// A single configuration override that applies to files matching specific patterns. /// A single configuration override that applies to files matching specific patterns.
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq, get_size2::GetSize)]
pub struct Override { pub struct Override {
/// File pattern filter to determine which files this override applies to. /// File pattern filter to determine which files this override applies to.
pub(super) files: IncludeExcludeFilter, pub(super) files: IncludeExcludeFilter,

View file

@ -16,7 +16,7 @@ use std::sync::Arc;
use toml::Spanned; use toml::Spanned;
use ty_combine::Combine; use ty_combine::Combine;
#[derive(Clone, Debug)] #[derive(Clone, Debug, get_size2::GetSize)]
pub enum ValueSource { pub enum ValueSource {
/// Value loaded from a project's configuration file. /// Value loaded from a project's configuration file.
/// ///
@ -84,7 +84,7 @@ impl Drop for ValueSourceGuard {
/// ///
/// This ensures that two resolved configurations are identical even if the position of a value has changed /// This ensures that two resolved configurations are identical even if the position of a value has changed
/// or if the values were loaded from different sources. /// or if the values were loaded from different sources.
#[derive(Clone, serde::Serialize)] #[derive(Clone, serde::Serialize, get_size2::GetSize)]
#[serde(transparent)] #[serde(transparent)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub struct RangedValue<T> { pub struct RangedValue<T> {
@ -325,6 +325,7 @@ where
Ord, Ord,
Hash, Hash,
Combine, Combine,
get_size2::GetSize,
)] )]
#[serde(transparent)] #[serde(transparent)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
@ -394,6 +395,7 @@ impl fmt::Display for RelativePathBuf {
Ord, Ord,
Hash, Hash,
Combine, Combine,
get_size2::GetSize,
)] )]
#[serde(transparent)] #[serde(transparent)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]

View file

@ -310,7 +310,7 @@ impl<'a> ProjectFilesWalker<'a> {
} }
} }
#[derive(Error, Debug, Clone)] #[derive(Error, Debug, Clone, get_size2::GetSize)]
pub(crate) enum WalkError { pub(crate) enum WalkError {
#[error("`{path}`: {error}")] #[error("`{path}`: {error}")]
IOPathError { path: SystemPathBuf, error: String }, IOPathError { path: SystemPathBuf, error: String },

View file

@ -211,7 +211,7 @@ fn all_submodule_names_for_package(db: &dyn Db, file: File) -> Option<Vec<Name>>
} }
/// A module that resolves to a file (`lib.py` or `package/__init__.py`) /// A module that resolves to a file (`lib.py` or `package/__init__.py`)
#[salsa::tracked(debug)] #[salsa::tracked(debug, heap_size=ruff_memory_usage::heap_size)]
pub struct FileModule<'db> { pub struct FileModule<'db> {
#[returns(ref)] #[returns(ref)]
name: ModuleName, name: ModuleName,
@ -226,7 +226,7 @@ pub struct FileModule<'db> {
/// ///
/// Namespace packages are special because there are /// Namespace packages are special because there are
/// multiple possible paths and they have no corresponding code file. /// multiple possible paths and they have no corresponding code file.
#[salsa::tracked(debug)] #[salsa::tracked(debug, heap_size=ruff_memory_usage::heap_size)]
pub struct NamespacePackage<'db> { pub struct NamespacePackage<'db> {
#[returns(ref)] #[returns(ref)]
name: ModuleName, name: ModuleName,

View file

@ -45,7 +45,7 @@ pub fn resolve_real_module<'db>(db: &'db dyn Db, module_name: &ModuleName) -> Op
} }
/// Which files should be visible when doing a module query /// Which files should be visible when doing a module query
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, get_size2::GetSize)]
pub(crate) enum ModuleResolveMode { pub(crate) enum ModuleResolveMode {
/// Stubs are allowed to appear. /// Stubs are allowed to appear.
/// ///
@ -60,7 +60,7 @@ pub(crate) enum ModuleResolveMode {
StubsNotAllowed, StubsNotAllowed,
} }
#[salsa::interned] #[salsa::interned(heap_size=ruff_memory_usage::heap_size)]
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct ModuleResolveModeIngredient<'db> { pub(crate) struct ModuleResolveModeIngredient<'db> {
mode: ModuleResolveMode, mode: ModuleResolveMode,
@ -172,7 +172,7 @@ pub(crate) fn search_paths(db: &dyn Db, resolve_mode: ModuleResolveMode) -> Sear
Program::get(db).search_paths(db).iter(db, resolve_mode) Program::get(db).search_paths(db).iter(db, resolve_mode)
} }
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq, get_size2::GetSize)]
pub struct SearchPaths { pub struct SearchPaths {
/// Search paths that have been statically determined purely from reading /// Search paths that have been statically determined purely from reading
/// ty's configuration settings. These shouldn't ever change unless the /// ty's configuration settings. These shouldn't ever change unless the
@ -643,7 +643,7 @@ impl<'db> Iterator for PthFileIterator<'db> {
/// A thin wrapper around `ModuleName` to make it a Salsa ingredient. /// A thin wrapper around `ModuleName` to make it a Salsa ingredient.
/// ///
/// 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(debug)] #[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
struct ModuleNameIngredient<'db> { struct ModuleNameIngredient<'db> {
#[returns(ref)] #[returns(ref)]
pub(super) name: ModuleName, pub(super) name: ModuleName,

View file

@ -74,7 +74,7 @@ pub(crate) enum TypeshedVersionsParseErrorKind {
VersionParseError(#[from] PythonVersionDeserializationError), VersionParseError(#[from] PythonVersionDeserializationError),
} }
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq, get_size2::GetSize)]
pub(crate) struct TypeshedVersions(FxHashMap<ModuleName, PyVersionRange>); pub(crate) struct TypeshedVersions(FxHashMap<ModuleName, PyVersionRange>);
impl TypeshedVersions { impl TypeshedVersions {
@ -230,7 +230,7 @@ impl fmt::Display for TypeshedVersions {
} }
} }
#[derive(Debug, Clone, Eq, PartialEq, Hash)] #[derive(Debug, Clone, Eq, PartialEq, Hash, get_size2::GetSize)]
pub(crate) enum PyVersionRange { pub(crate) enum PyVersionRange {
AvailableFrom(RangeFrom<PythonVersion>), AvailableFrom(RangeFrom<PythonVersion>),
AvailableWithin(RangeInclusive<PythonVersion>), AvailableWithin(RangeInclusive<PythonVersion>),

View file

@ -13,7 +13,7 @@ use ruff_text_size::TextRange;
use salsa::Durability; use salsa::Durability;
use salsa::Setter; use salsa::Setter;
#[salsa::input(singleton)] #[salsa::input(singleton, heap_size=ruff_memory_usage::heap_size)]
pub struct Program { pub struct Program {
#[returns(ref)] #[returns(ref)]
pub python_version_with_source: PythonVersionWithSource, pub python_version_with_source: PythonVersionWithSource,
@ -93,7 +93,7 @@ pub struct ProgramSettings {
pub search_paths: SearchPaths, pub search_paths: SearchPaths,
} }
#[derive(Clone, Debug, Eq, PartialEq, Default)] #[derive(Clone, Debug, Eq, PartialEq, Default, get_size2::GetSize)]
pub enum PythonVersionSource { pub enum PythonVersionSource {
/// Value loaded from a project's configuration file. /// Value loaded from a project's configuration file.
ConfigFile(PythonVersionFileSource), ConfigFile(PythonVersionFileSource),
@ -123,7 +123,7 @@ pub enum PythonVersionSource {
/// Information regarding the file and [`TextRange`] of the configuration /// Information regarding the file and [`TextRange`] of the configuration
/// from which we inferred the Python version. /// from which we inferred the Python version.
#[derive(Debug, PartialEq, Eq, Clone)] #[derive(Debug, PartialEq, Eq, Clone, get_size2::GetSize)]
pub struct PythonVersionFileSource { pub struct PythonVersionFileSource {
path: Arc<SystemPathBuf>, path: Arc<SystemPathBuf>,
range: Option<TextRange>, range: Option<TextRange>,
@ -145,7 +145,7 @@ impl PythonVersionFileSource {
} }
} }
#[derive(Eq, PartialEq, Debug, Clone)] #[derive(Eq, PartialEq, Debug, Clone, get_size2::GetSize)]
pub struct PythonVersionWithSource { pub struct PythonVersionWithSource {
pub version: PythonVersion, pub version: PythonVersion,
pub source: PythonVersionSource, pub source: PythonVersionSource,

View file

@ -1,7 +1,7 @@
use std::fmt::{Display, Formatter}; use std::fmt::{Display, Formatter};
/// The target platform to assume when resolving types. /// The target platform to assume when resolving types.
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq, get_size2::GetSize)]
#[cfg_attr( #[cfg_attr(
feature = "serde", feature = "serde",
derive(serde::Serialize, serde::Deserialize, ruff_macros::RustDoc), derive(serde::Serialize, serde::Deserialize, ruff_macros::RustDoc),

View file

@ -22,7 +22,7 @@ use crate::unpack::{Unpack, UnpackPosition};
/// because a new scope gets inserted before the `Definition` or a new place is inserted /// because a new scope gets inserted before the `Definition` or a new place is inserted
/// before this `Definition`. However, the ID can be considered stable and it is okay to use /// before this `Definition`. However, the ID can be considered stable and it is okay to use
/// `Definition` in cross-module` salsa queries or as a field on other salsa tracked structs. /// `Definition` in cross-module` salsa queries or as a field on other salsa tracked structs.
#[salsa::tracked(debug)] #[salsa::tracked(debug, heap_size=ruff_memory_usage::heap_size)]
pub struct Definition<'db> { pub struct Definition<'db> {
/// The file in which the definition occurs. /// The file in which the definition occurs.
pub file: File, pub file: File,
@ -645,7 +645,7 @@ impl DefinitionCategory {
/// [`DefinitionKind`] fields in salsa tracked structs should be tracked (attributed with `#[tracked]`) /// [`DefinitionKind`] fields in salsa tracked structs should be tracked (attributed with `#[tracked]`)
/// because the kind is a thin wrapper around [`AstNodeRef`]. See the [`AstNodeRef`] documentation /// because the kind is a thin wrapper around [`AstNodeRef`]. See the [`AstNodeRef`] documentation
/// for an in-depth explanation of why this is necessary. /// for an in-depth explanation of why this is necessary.
#[derive(Clone, Debug)] #[derive(Clone, Debug, get_size2::GetSize)]
pub enum DefinitionKind<'db> { pub enum DefinitionKind<'db> {
Import(ImportDefinitionKind), Import(ImportDefinitionKind),
ImportFrom(ImportFromDefinitionKind), ImportFrom(ImportFromDefinitionKind),
@ -834,7 +834,7 @@ impl DefinitionKind<'_> {
} }
} }
#[derive(Copy, Clone, Debug, PartialEq, Hash)] #[derive(Copy, Clone, Debug, PartialEq, Hash, get_size2::GetSize)]
pub(crate) enum TargetKind<'db> { pub(crate) enum TargetKind<'db> {
Sequence(UnpackPosition, Unpack<'db>), Sequence(UnpackPosition, Unpack<'db>),
/// Name, attribute, or subscript. /// Name, attribute, or subscript.
@ -850,7 +850,7 @@ impl<'db> From<Option<(UnpackPosition, Unpack<'db>)>> for TargetKind<'db> {
} }
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug, get_size2::GetSize)]
pub struct StarImportDefinitionKind { pub struct StarImportDefinitionKind {
node: AstNodeRef<ast::StmtImportFrom>, node: AstNodeRef<ast::StmtImportFrom>,
symbol_id: ScopedSymbolId, symbol_id: ScopedSymbolId,
@ -880,7 +880,7 @@ impl StarImportDefinitionKind {
} }
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug, get_size2::GetSize)]
pub struct MatchPatternDefinitionKind { pub struct MatchPatternDefinitionKind {
pattern: AstNodeRef<ast::Pattern>, pattern: AstNodeRef<ast::Pattern>,
identifier: AstNodeRef<ast::Identifier>, identifier: AstNodeRef<ast::Identifier>,
@ -902,7 +902,7 @@ impl MatchPatternDefinitionKind {
/// But if the target is an attribute or subscript, its definition is not in the comprehension's scope; /// But if the target is an attribute or subscript, its definition is not in the comprehension's scope;
/// it is in the scope in which the root variable is bound. /// it is in the scope in which the root variable is bound.
/// TODO: currently we don't model this correctly and simply assume that it is in a scope outside the comprehension. /// TODO: currently we don't model this correctly and simply assume that it is in a scope outside the comprehension.
#[derive(Clone, Debug)] #[derive(Clone, Debug, get_size2::GetSize)]
pub struct ComprehensionDefinitionKind<'db> { pub struct ComprehensionDefinitionKind<'db> {
target_kind: TargetKind<'db>, target_kind: TargetKind<'db>,
iterable: AstNodeRef<ast::Expr>, iterable: AstNodeRef<ast::Expr>,
@ -933,7 +933,7 @@ impl<'db> ComprehensionDefinitionKind<'db> {
} }
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug, get_size2::GetSize)]
pub struct ImportDefinitionKind { pub struct ImportDefinitionKind {
node: AstNodeRef<ast::StmtImport>, node: AstNodeRef<ast::StmtImport>,
alias_index: usize, alias_index: usize,
@ -954,7 +954,7 @@ impl ImportDefinitionKind {
} }
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug, get_size2::GetSize)]
pub struct ImportFromDefinitionKind { pub struct ImportFromDefinitionKind {
node: AstNodeRef<ast::StmtImportFrom>, node: AstNodeRef<ast::StmtImportFrom>,
alias_index: usize, alias_index: usize,
@ -975,7 +975,7 @@ impl ImportFromDefinitionKind {
} }
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug, get_size2::GetSize)]
pub struct AssignmentDefinitionKind<'db> { pub struct AssignmentDefinitionKind<'db> {
target_kind: TargetKind<'db>, target_kind: TargetKind<'db>,
value: AstNodeRef<ast::Expr>, value: AstNodeRef<ast::Expr>,
@ -996,7 +996,7 @@ impl<'db> AssignmentDefinitionKind<'db> {
} }
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug, get_size2::GetSize)]
pub struct AnnotatedAssignmentDefinitionKind { pub struct AnnotatedAssignmentDefinitionKind {
annotation: AstNodeRef<ast::Expr>, annotation: AstNodeRef<ast::Expr>,
value: Option<AstNodeRef<ast::Expr>>, value: Option<AstNodeRef<ast::Expr>>,
@ -1017,7 +1017,7 @@ impl AnnotatedAssignmentDefinitionKind {
} }
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug, get_size2::GetSize)]
pub struct WithItemDefinitionKind<'db> { pub struct WithItemDefinitionKind<'db> {
target_kind: TargetKind<'db>, target_kind: TargetKind<'db>,
context_expr: AstNodeRef<ast::Expr>, context_expr: AstNodeRef<ast::Expr>,
@ -1043,7 +1043,7 @@ impl<'db> WithItemDefinitionKind<'db> {
} }
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug, get_size2::GetSize)]
pub struct ForStmtDefinitionKind<'db> { pub struct ForStmtDefinitionKind<'db> {
target_kind: TargetKind<'db>, target_kind: TargetKind<'db>,
iterable: AstNodeRef<ast::Expr>, iterable: AstNodeRef<ast::Expr>,
@ -1069,7 +1069,7 @@ impl<'db> ForStmtDefinitionKind<'db> {
} }
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug, get_size2::GetSize)]
pub struct ExceptHandlerDefinitionKind { pub struct ExceptHandlerDefinitionKind {
handler: AstNodeRef<ast::ExceptHandlerExceptHandler>, handler: AstNodeRef<ast::ExceptHandlerExceptHandler>,
is_star: bool, is_star: bool,

View file

@ -10,7 +10,7 @@ use salsa;
/// a type expression. For example, in `self.x: <annotation> = <value>`, the /// a type expression. For example, in `self.x: <annotation> = <value>`, the
/// `<annotation>` is inferred as a type expression, while `<value>` is inferred /// `<annotation>` is inferred as a type expression, while `<value>` is inferred
/// as a normal expression. /// as a normal expression.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, get_size2::GetSize)]
pub(crate) enum ExpressionKind { pub(crate) enum ExpressionKind {
Normal, Normal,
TypeExpression, TypeExpression,
@ -31,7 +31,7 @@ pub(crate) enum ExpressionKind {
/// * a return type of a cross-module query /// * a return type of a cross-module query
/// * a field of a type that is 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 /// * an argument of a cross-module query
#[salsa::tracked(debug)] #[salsa::tracked(debug, heap_size=ruff_memory_usage::heap_size)]
pub(crate) struct Expression<'db> { pub(crate) struct Expression<'db> {
/// The file in which the expression occurs. /// The file in which the expression occurs.
pub(crate) file: File, pub(crate) file: File,

View file

@ -117,7 +117,7 @@ pub(crate) enum PredicateNode<'db> {
StarImportPlaceholder(StarImportPlaceholderPredicate<'db>), StarImportPlaceholder(StarImportPlaceholderPredicate<'db>),
} }
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, salsa::Update)] #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, salsa::Update, get_size2::GetSize)]
pub(crate) enum ClassPatternKind { pub(crate) enum ClassPatternKind {
Irrefutable, Irrefutable,
Refutable, Refutable,
@ -130,7 +130,7 @@ impl ClassPatternKind {
} }
/// Pattern kinds for which we support type narrowing and/or static reachability analysis. /// Pattern kinds for which we support type narrowing and/or static reachability analysis.
#[derive(Debug, Clone, Hash, PartialEq, salsa::Update)] #[derive(Debug, Clone, Hash, PartialEq, salsa::Update, get_size2::GetSize)]
pub(crate) enum PatternPredicateKind<'db> { pub(crate) enum PatternPredicateKind<'db> {
Singleton(Singleton), Singleton(Singleton),
Value(Expression<'db>), Value(Expression<'db>),
@ -140,7 +140,7 @@ pub(crate) enum PatternPredicateKind<'db> {
Unsupported, Unsupported,
} }
#[salsa::tracked(debug)] #[salsa::tracked(debug, heap_size=ruff_memory_usage::heap_size)]
pub(crate) struct PatternPredicate<'db> { pub(crate) struct PatternPredicate<'db> {
pub(crate) file: File, pub(crate) file: File,
@ -206,7 +206,7 @@ impl<'db> PatternPredicate<'db> {
/// - If it resolves to a possibly bound symbol, then the predicate resolves to [`Truthiness::Ambiguous`] /// - If it resolves to a possibly bound symbol, then the predicate resolves to [`Truthiness::Ambiguous`]
/// ///
/// [Truthiness]: [crate::types::Truthiness] /// [Truthiness]: [crate::types::Truthiness]
#[salsa::tracked(debug)] #[salsa::tracked(debug, heap_size=ruff_memory_usage::heap_size)]
pub(crate) struct StarImportPlaceholderPredicate<'db> { pub(crate) struct StarImportPlaceholderPredicate<'db> {
pub(crate) importing_file: File, pub(crate) importing_file: File,

View file

@ -14,7 +14,7 @@ use crate::{
}; };
/// 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(debug)] #[salsa::tracked(debug, heap_size=ruff_memory_usage::heap_size)]
pub struct ScopeId<'db> { pub struct ScopeId<'db> {
pub file: File, pub file: File,

View file

@ -385,7 +385,7 @@ pub(crate) use todo_type;
/// # Ordering /// # Ordering
/// Ordering is based on the property instance's salsa-assigned id and not on its values. /// Ordering is based on the property instance's salsa-assigned id and not on its values.
/// The id may change between runs, or when the property instance was garbage collected and recreated. /// The id may change between runs, or when the property instance was garbage collected and recreated.
#[salsa::interned(debug)] #[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)] #[derive(PartialOrd, Ord)]
pub struct PropertyInstanceType<'db> { pub struct PropertyInstanceType<'db> {
getter: Option<Type<'db>>, getter: Option<Type<'db>>,
@ -6079,7 +6079,7 @@ impl<'db> From<&Type<'db>> for Type<'db> {
/// This is represented as an enum (with some variants using `Cow`), and not an `FnMut` trait, /// This is represented as an enum (with some variants using `Cow`), and not an `FnMut` trait,
/// since we sometimes have to apply type mappings lazily (e.g., to the signature of a function /// since we sometimes have to apply type mappings lazily (e.g., to the signature of a function
/// literal). /// literal).
#[derive(Clone, Debug, Eq, Hash, PartialEq)] #[derive(Clone, Debug, Eq, Hash, PartialEq, get_size2::GetSize)]
pub enum TypeMapping<'a, 'db> { pub enum TypeMapping<'a, 'db> {
/// Applies a specialization to the type /// Applies a specialization to the type
Specialization(Specialization<'db>), Specialization(Specialization<'db>),
@ -6610,7 +6610,7 @@ impl<'db> InvalidTypeExpression<'db> {
} }
/// Data regarding a `warnings.deprecated` or `typing_extensions.deprecated` decorator. /// Data regarding a `warnings.deprecated` or `typing_extensions.deprecated` decorator.
#[salsa::interned(debug)] #[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)] #[derive(PartialOrd, Ord)]
pub struct DeprecatedInstance<'db> { pub struct DeprecatedInstance<'db> {
/// The message for the deprecation /// The message for the deprecation
@ -6622,7 +6622,7 @@ impl get_size2::GetSize for DeprecatedInstance<'_> {}
/// Contains information about instances of `dataclasses.Field`, typically created using /// Contains information about instances of `dataclasses.Field`, typically created using
/// `dataclasses.field()`. /// `dataclasses.field()`.
#[salsa::interned(debug)] #[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)] #[derive(PartialOrd, Ord)]
pub struct FieldInstance<'db> { pub struct FieldInstance<'db> {
/// The type of the default value for this field. This is derived from the `default` or /// The type of the default value for this field. This is derived from the `default` or
@ -6648,7 +6648,7 @@ impl<'db> FieldInstance<'db> {
/// Whether this typevar was created via the legacy `TypeVar` constructor, using PEP 695 syntax, /// Whether this typevar was created via the legacy `TypeVar` constructor, using PEP 695 syntax,
/// or an implicit typevar like `Self` was used. /// or an implicit typevar like `Self` was used.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, get_size2::GetSize)]
pub enum TypeVarKind { pub enum TypeVarKind {
/// `T = TypeVar("T")` /// `T = TypeVar("T")`
Legacy, Legacy,
@ -6694,7 +6694,7 @@ pub enum TypeVarKind {
/// # Ordering /// # Ordering
/// Ordering is based on the type var instance's salsa-assigned id and not on its values. /// Ordering is based on the type var instance's salsa-assigned id and not on its values.
/// The id may change between runs, or when the type var instance was garbage collected and recreated. /// The id may change between runs, or when the type var instance was garbage collected and recreated.
#[salsa::interned(debug)] #[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)] #[derive(PartialOrd, Ord)]
pub struct TypeVarInstance<'db> { pub struct TypeVarInstance<'db> {
/// The name of this TypeVar (e.g. `T`) /// The name of this TypeVar (e.g. `T`)
@ -6789,7 +6789,7 @@ impl<'db> TypeVarInstance<'db> {
} }
/// Where a type variable is bound and usable. /// Where a type variable is bound and usable.
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, salsa::Update)] #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, salsa::Update, get_size2::GetSize)]
pub enum BindingContext<'db> { pub enum BindingContext<'db> {
/// The definition of the generic class, function, or type alias that binds this typevar. /// The definition of the generic class, function, or type alias that binds this typevar.
Definition(Definition<'db>), Definition(Definition<'db>),
@ -6809,7 +6809,7 @@ impl<'db> BindingContext<'db> {
/// A type variable that has been bound to a generic context, and which can be specialized to a /// A type variable that has been bound to a generic context, and which can be specialized to a
/// concrete type. /// concrete type.
#[salsa::interned(debug)] #[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)] #[derive(PartialOrd, Ord)]
pub struct BoundTypeVarInstance<'db> { pub struct BoundTypeVarInstance<'db> {
pub typevar: TypeVarInstance<'db>, pub typevar: TypeVarInstance<'db>,
@ -6874,7 +6874,7 @@ impl<'db> BoundTypeVarInstance<'db> {
} }
} }
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, salsa::Update)] #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, salsa::Update, get_size2::GetSize)]
pub enum TypeVarVariance { pub enum TypeVarVariance {
Invariant, Invariant,
Covariant, Covariant,
@ -6896,7 +6896,7 @@ impl TypeVarVariance {
} }
} }
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, salsa::Update)] #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, salsa::Update, get_size2::GetSize)]
pub enum TypeVarBoundOrConstraints<'db> { pub enum TypeVarBoundOrConstraints<'db> {
UpperBound(Type<'db>), UpperBound(Type<'db>),
Constraints(UnionType<'db>), Constraints(UnionType<'db>),
@ -7916,7 +7916,7 @@ impl From<bool> for Truthiness {
/// # Ordering /// # Ordering
/// Ordering is based on the bounded method's salsa-assigned id and not on its values. /// Ordering is based on the bounded method's salsa-assigned id and not on its values.
/// The id may change between runs, or when the bounded method was garbage collected and recreated. /// The id may change between runs, or when the bounded method was garbage collected and recreated.
#[salsa::interned(debug)] #[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)] #[derive(PartialOrd, Ord)]
pub struct BoundMethodType<'db> { pub struct BoundMethodType<'db> {
/// The function that is being bound. Corresponds to the `__func__` attribute on a /// The function that is being bound. Corresponds to the `__func__` attribute on a
@ -7992,7 +7992,7 @@ impl<'db> BoundMethodType<'db> {
/// # Ordering /// # Ordering
/// Ordering is based on the callable type's salsa-assigned id and not on its values. /// Ordering is based on the callable type's salsa-assigned id and not on its values.
/// The id may change between runs, or when the callable type was garbage collected and recreated. /// The id may change between runs, or when the callable type was garbage collected and recreated.
#[salsa::interned(debug)] #[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)] #[derive(PartialOrd, Ord)]
pub struct CallableType<'db> { pub struct CallableType<'db> {
#[returns(ref)] #[returns(ref)]
@ -8270,7 +8270,7 @@ pub enum WrapperDescriptorKind {
/// # Ordering /// # Ordering
/// Ordering is based on the module literal's salsa-assigned id and not on its values. /// Ordering is based on the module literal's salsa-assigned id and not on its values.
/// The id may change between runs, or when the module literal was garbage collected and recreated. /// The id may change between runs, or when the module literal was garbage collected and recreated.
#[salsa::interned(debug)] #[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)] #[derive(PartialOrd, Ord)]
pub struct ModuleLiteralType<'db> { pub struct ModuleLiteralType<'db> {
/// The imported module. /// The imported module.
@ -8380,7 +8380,7 @@ impl<'db> ModuleLiteralType<'db> {
/// # Ordering /// # Ordering
/// Ordering is based on the type alias's salsa-assigned id and not on its values. /// Ordering is based on the type alias's salsa-assigned id and not on its values.
/// The id may change between runs, or when the alias was garbage collected and recreated. /// The id may change between runs, or when the alias was garbage collected and recreated.
#[salsa::interned(debug)] #[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)] #[derive(PartialOrd, Ord)]
pub struct PEP695TypeAliasType<'db> { pub struct PEP695TypeAliasType<'db> {
#[returns(ref)] #[returns(ref)]
@ -8427,7 +8427,7 @@ impl<'db> PEP695TypeAliasType<'db> {
/// # Ordering /// # Ordering
/// Ordering is based on the type alias's salsa-assigned id and not on its values. /// Ordering is based on the type alias's salsa-assigned id and not on its values.
/// The id may change between runs, or when the alias was garbage collected and recreated. /// The id may change between runs, or when the alias was garbage collected and recreated.
#[salsa::interned(debug)] #[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)] #[derive(PartialOrd, Ord)]
pub struct BareTypeAliasType<'db> { pub struct BareTypeAliasType<'db> {
#[returns(ref)] #[returns(ref)]
@ -8522,7 +8522,7 @@ pub(super) struct MetaclassCandidate<'db> {
explicit_metaclass_of: ClassLiteral<'db>, explicit_metaclass_of: ClassLiteral<'db>,
} }
#[salsa::interned(debug)] #[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
pub struct UnionType<'db> { pub struct UnionType<'db> {
/// The union type includes values in any of these types. /// The union type includes values in any of these types.
#[returns(deref)] #[returns(deref)]
@ -8744,7 +8744,7 @@ impl<'db> UnionType<'db> {
} }
} }
#[salsa::interned(debug)] #[salsa::interned(debug, heap_size=IntersectionType::heap_size)]
pub struct IntersectionType<'db> { 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.
#[returns(ref)] #[returns(ref)]
@ -8938,12 +8938,17 @@ impl<'db> IntersectionType<'db> {
pub fn has_one_element(&self, db: &'db dyn Db) -> bool { pub fn has_one_element(&self, db: &'db dyn Db) -> bool {
(self.positive(db).len() + self.negative(db).len()) == 1 (self.positive(db).len() + self.negative(db).len()) == 1
} }
fn heap_size((positive, negative): &(FxOrderSet<Type<'db>>, FxOrderSet<Type<'db>>)) -> usize {
ruff_memory_usage::order_set_heap_size(positive)
+ ruff_memory_usage::order_set_heap_size(negative)
}
} }
/// # Ordering /// # Ordering
/// Ordering is based on the string literal's salsa-assigned id and not on its value. /// Ordering is based on the string literal's salsa-assigned id and not on its value.
/// The id may change between runs, or when the string literal was garbage collected and recreated. /// The id may change between runs, or when the string literal was garbage collected and recreated.
#[salsa::interned(debug)] #[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)] #[derive(PartialOrd, Ord)]
pub struct StringLiteralType<'db> { pub struct StringLiteralType<'db> {
#[returns(deref)] #[returns(deref)]
@ -8971,7 +8976,7 @@ impl<'db> StringLiteralType<'db> {
/// # Ordering /// # Ordering
/// Ordering is based on the byte literal's salsa-assigned id and not on its value. /// Ordering is based on the byte literal's salsa-assigned id and not on its value.
/// The id may change between runs, or when the byte literal was garbage collected and recreated. /// The id may change between runs, or when the byte literal was garbage collected and recreated.
#[salsa::interned(debug)] #[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)] #[derive(PartialOrd, Ord)]
pub struct BytesLiteralType<'db> { pub struct BytesLiteralType<'db> {
#[returns(deref)] #[returns(deref)]
@ -8996,7 +9001,7 @@ impl<'db> BytesLiteralType<'db> {
/// NO = 0 /// NO = 0
/// YES = 1 /// YES = 1
/// ``` /// ```
#[salsa::interned(debug)] #[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)] #[derive(PartialOrd, Ord)]
pub struct EnumLiteralType<'db> { pub struct EnumLiteralType<'db> {
/// A reference to the enum class this literal belongs to /// A reference to the enum class this literal belongs to
@ -9017,7 +9022,7 @@ impl<'db> EnumLiteralType<'db> {
/// Type that represents the set of all inhabitants (`dict` instances) that conform to /// Type that represents the set of all inhabitants (`dict` instances) that conform to
/// a given `TypedDict` schema. /// a given `TypedDict` schema.
#[salsa::interned(debug)] #[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)] #[derive(PartialOrd, Ord)]
pub struct TypedDictType<'db> { pub struct TypedDictType<'db> {
/// A reference to the class (inheriting from `typing.TypedDict`) that specifies the /// A reference to the class (inheriting from `typing.TypedDict`) that specifies the
@ -9104,7 +9109,7 @@ impl BoundSuperError<'_> {
} }
} }
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, get_size2::GetSize)]
pub enum SuperOwnerKind<'db> { pub enum SuperOwnerKind<'db> {
Dynamic(DynamicType), Dynamic(DynamicType),
Class(ClassType<'db>), Class(ClassType<'db>),
@ -9193,7 +9198,7 @@ impl<'db> From<SuperOwnerKind<'db>> for Type<'db> {
} }
/// Represent a bound super object like `super(PivotClass, owner)` /// Represent a bound super object like `super(PivotClass, owner)`
#[salsa::interned(debug)] #[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
pub struct BoundSuperType<'db> { pub struct BoundSuperType<'db> {
pub pivot_class: ClassBase<'db>, pub pivot_class: ClassBase<'db>,
pub owner: SuperOwnerKind<'db>, pub owner: SuperOwnerKind<'db>,
@ -9381,7 +9386,7 @@ impl<'db> BoundSuperType<'db> {
} }
} }
#[salsa::interned(debug)] #[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
pub struct TypeIsType<'db> { pub struct TypeIsType<'db> {
return_type: Type<'db>, return_type: Type<'db>,
/// The ID of the scope to which the place belongs /// The ID of the scope to which the place belongs

View file

@ -212,7 +212,7 @@ impl CodeGeneratorKind {
/// # Ordering /// # Ordering
/// Ordering is based on the generic aliases's salsa-assigned id and not on its values. /// Ordering is based on the generic aliases's salsa-assigned id and not on its values.
/// The id may change between runs, or when the alias was garbage collected and recreated. /// The id may change between runs, or when the alias was garbage collected and recreated.
#[salsa::interned(debug)] #[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)] #[derive(PartialOrd, Ord)]
pub struct GenericAlias<'db> { pub struct GenericAlias<'db> {
pub(crate) origin: ClassLiteral<'db>, pub(crate) origin: ClassLiteral<'db>,
@ -1147,7 +1147,7 @@ pub(crate) struct Field<'db> {
/// # Ordering /// # Ordering
/// Ordering is based on the class's id assigned by salsa and not on the class literal's values. /// Ordering is based on the class's id assigned by salsa and not on the class literal's values.
/// The id may change between runs, or when the class literal was garbage collected and recreated. /// The id may change between runs, or when the class literal was garbage collected and recreated.
#[salsa::interned(debug)] #[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)] #[derive(PartialOrd, Ord)]
pub struct ClassLiteral<'db> { pub struct ClassLiteral<'db> {
/// Name of the class at definition /// Name of the class at definition
@ -2998,7 +2998,7 @@ pub(super) enum SolidBaseKind {
/// Feel free to expand this enum if you ever find yourself using the same class in multiple /// Feel free to expand this enum if you ever find yourself using the same class in multiple
/// places. /// places.
/// Note: good candidates are any classes in `[crate::module_resolver::module::KnownModule]` /// Note: good candidates are any classes in `[crate::module_resolver::module::KnownModule]`
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, get_size2::GetSize)]
#[cfg_attr(test, derive(strum_macros::EnumIter))] #[cfg_attr(test, derive(strum_macros::EnumIter))]
pub enum KnownClass { pub enum KnownClass {
// To figure out where an stdlib symbol is defined, you can go into `crates/ty_vendored` // To figure out where an stdlib symbol is defined, you can go into `crates/ty_vendored`

View file

@ -120,6 +120,8 @@ bitflags! {
} }
} }
impl get_size2::GetSize for FunctionDecorators {}
impl FunctionDecorators { impl FunctionDecorators {
pub(super) fn from_decorator_type(db: &dyn Db, decorator_type: Type) -> Self { pub(super) fn from_decorator_type(db: &dyn Db, decorator_type: Type) -> Self {
match decorator_type { match decorator_type {
@ -184,7 +186,7 @@ impl Default for DataclassTransformerParams {
/// Ordering is based on the function's id assigned by salsa and not on the function literal's /// Ordering is based on the function's id assigned by salsa and not on the function literal's
/// values. The id may change between runs, or when the function literal was garbage collected and /// values. The id may change between runs, or when the function literal was garbage collected and
/// recreated. /// recreated.
#[salsa::interned(debug)] #[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)] #[derive(PartialOrd, Ord)]
pub struct OverloadLiteral<'db> { pub struct OverloadLiteral<'db> {
/// Name of the function at definition. /// Name of the function at definition.
@ -406,7 +408,7 @@ impl<'db> OverloadLiteral<'db> {
/// Ordering is based on the function's id assigned by salsa and not on the function literal's /// Ordering is based on the function's id assigned by salsa and not on the function literal's
/// values. The id may change between runs, or when the function literal was garbage collected and /// values. The id may change between runs, or when the function literal was garbage collected and
/// recreated. /// recreated.
#[salsa::interned(debug)] #[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)] #[derive(PartialOrd, Ord)]
pub struct FunctionLiteral<'db> { pub struct FunctionLiteral<'db> {
pub(crate) last_definition: OverloadLiteral<'db>, pub(crate) last_definition: OverloadLiteral<'db>,
@ -433,6 +435,9 @@ pub struct FunctionLiteral<'db> {
inherited_generic_context: Option<GenericContext<'db>>, inherited_generic_context: Option<GenericContext<'db>>,
} }
// The Salsa heap is tracked separately.
impl get_size2::GetSize for FunctionLiteral<'_> {}
fn walk_function_literal<'db, V: super::visitor::TypeVisitor<'db> + ?Sized>( fn walk_function_literal<'db, V: super::visitor::TypeVisitor<'db> + ?Sized>(
db: &'db dyn Db, db: &'db dyn Db,
function: FunctionLiteral<'db>, function: FunctionLiteral<'db>,
@ -609,7 +614,7 @@ impl<'db> FunctionLiteral<'db> {
/// Represents a function type, which might be a non-generic function, or a specialization of a /// Represents a function type, which might be a non-generic function, or a specialization of a
/// generic function. /// generic function.
#[salsa::interned(debug)] #[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)] #[derive(PartialOrd, Ord)]
pub struct FunctionType<'db> { pub struct FunctionType<'db> {
pub(crate) literal: FunctionLiteral<'db>, pub(crate) literal: FunctionLiteral<'db>,
@ -1057,7 +1062,15 @@ fn last_definition_signature_cycle_initial<'db>(
/// Non-exhaustive enumeration of known functions (e.g. `builtins.reveal_type`, ...) that might /// Non-exhaustive enumeration of known functions (e.g. `builtins.reveal_type`, ...) that might
/// have special behavior. /// have special behavior.
#[derive( #[derive(
Debug, Copy, Clone, PartialEq, Eq, Hash, strum_macros::EnumString, strum_macros::IntoStaticStr, Debug,
Copy,
Clone,
PartialEq,
Eq,
Hash,
strum_macros::EnumString,
strum_macros::IntoStaticStr,
get_size2::GetSize,
)] )]
#[strum(serialize_all = "snake_case")] #[strum(serialize_all = "snake_case")]
#[cfg_attr(test, derive(strum_macros::EnumIter))] #[cfg_attr(test, derive(strum_macros::EnumIter))]

View file

@ -89,7 +89,7 @@ pub(crate) fn bind_typevar<'db>(
/// # Ordering /// # Ordering
/// Ordering is based on the context's salsa-assigned id and not on its values. /// Ordering is based on the context's salsa-assigned id and not on its values.
/// The id may change between runs, or when the context was garbage collected and recreated. /// The id may change between runs, or when the context was garbage collected and recreated.
#[salsa::interned(debug)] #[salsa::interned(debug, heap_size=GenericContext::heap_size)]
#[derive(PartialOrd, Ord)] #[derive(PartialOrd, Ord)]
pub struct GenericContext<'db> { pub struct GenericContext<'db> {
#[returns(ref)] #[returns(ref)]
@ -363,6 +363,10 @@ impl<'db> GenericContext<'db> {
.collect(); .collect();
Self::new(db, variables) Self::new(db, variables)
} }
fn heap_size((variables,): &(FxOrderSet<BoundTypeVarInstance<'db>>,)) -> usize {
ruff_memory_usage::order_set_heap_size(variables)
}
} }
#[derive(Debug, Copy, Clone, PartialEq, Eq)] #[derive(Debug, Copy, Clone, PartialEq, Eq)]
@ -390,7 +394,7 @@ impl std::fmt::Display for LegacyGenericBase {
/// ///
/// TODO: Handle nested specializations better, with actual parent links to the specialization of /// TODO: Handle nested specializations better, with actual parent links to the specialization of
/// the lexically containing context. /// the lexically containing context.
#[salsa::interned(debug)] #[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
pub struct Specialization<'db> { pub struct Specialization<'db> {
pub(crate) generic_context: GenericContext<'db>, pub(crate) generic_context: GenericContext<'db>,
#[returns(deref)] #[returns(deref)]
@ -401,6 +405,9 @@ pub struct Specialization<'db> {
tuple_inner: Option<TupleType<'db>>, tuple_inner: Option<TupleType<'db>>,
} }
// The Salsa heap is tracked separately.
impl get_size2::GetSize for Specialization<'_> {}
pub(super) fn walk_specialization<'db, V: super::visitor::TypeVisitor<'db> + ?Sized>( pub(super) fn walk_specialization<'db, V: super::visitor::TypeVisitor<'db> + ?Sized>(
db: &'db dyn Db, db: &'db dyn Db,
specialization: Specialization<'db>, specialization: Specialization<'db>,
@ -655,7 +662,7 @@ impl<'db> Specialization<'db> {
/// ///
/// You will usually use [`Specialization`] instead of this type. This type is used when we need to /// You will usually use [`Specialization`] instead of this type. This type is used when we need to
/// substitute types for type variables before we have fully constructed a [`Specialization`]. /// substitute types for type variables before we have fully constructed a [`Specialization`].
#[derive(Clone, Debug, Eq, Hash, PartialEq)] #[derive(Clone, Debug, Eq, Hash, PartialEq, get_size2::GetSize)]
pub struct PartialSpecialization<'a, 'db> { pub struct PartialSpecialization<'a, 'db> {
generic_context: GenericContext<'db>, generic_context: GenericContext<'db>,
types: Cow<'a, [Type<'db>]>, types: Cow<'a, [Type<'db>]>,

View file

@ -70,7 +70,7 @@ impl<'db> Deref for ProtocolClassLiteral<'db> {
/// # Ordering /// # Ordering
/// Ordering is based on the protocol interface member's salsa-assigned id and not on its members. /// Ordering is based on the protocol interface member's salsa-assigned id and not on its members.
/// The id may change between runs, or when the protocol instance members was garbage collected and recreated. /// The id may change between runs, or when the protocol instance members was garbage collected and recreated.
#[salsa::interned(debug)] #[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)] #[derive(PartialOrd, Ord)]
pub(super) struct ProtocolInterface<'db> { pub(super) struct ProtocolInterface<'db> {
#[returns(ref)] #[returns(ref)]
@ -241,7 +241,7 @@ impl<'db> ProtocolInterface<'db> {
} }
} }
#[derive(Debug, PartialEq, Eq, Clone, Hash, salsa::Update)] #[derive(Debug, PartialEq, Eq, Clone, Hash, salsa::Update, get_size2::GetSize)]
pub(super) struct ProtocolMemberData<'db> { pub(super) struct ProtocolMemberData<'db> {
kind: ProtocolMemberKind<'db>, kind: ProtocolMemberKind<'db>,
qualifiers: TypeQualifiers, qualifiers: TypeQualifiers,
@ -319,7 +319,7 @@ impl<'db> ProtocolMemberData<'db> {
} }
} }
#[derive(Debug, Copy, Clone, PartialEq, Eq, salsa::Update, Hash)] #[derive(Debug, Copy, Clone, PartialEq, Eq, salsa::Update, Hash, get_size2::GetSize)]
enum ProtocolMemberKind<'db> { enum ProtocolMemberKind<'db> {
Method(CallableType<'db>), Method(CallableType<'db>),
Property(PropertyInstanceType<'db>), Property(PropertyInstanceType<'db>),

View file

@ -125,7 +125,7 @@ impl TupleLength {
/// # Ordering /// # Ordering
/// Ordering is based on the tuple's salsa-assigned id and not on its elements. /// Ordering is based on the tuple's salsa-assigned id and not on its elements.
/// The id may change between runs, or when the tuple was garbage collected and recreated. /// The id may change between runs, or when the tuple was garbage collected and recreated.
#[salsa::interned(debug, constructor=new_internal)] #[salsa::interned(debug, constructor=new_internal, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)] #[derive(PartialOrd, Ord)]
pub struct TupleType<'db> { pub struct TupleType<'db> {
#[returns(ref)] #[returns(ref)]
@ -223,7 +223,7 @@ impl<'db> TupleType<'db> {
// N.B. If this method is not Salsa-tracked, we take 10 minutes to check // N.B. If this method is not Salsa-tracked, we take 10 minutes to check
// `static-frame` as part of a mypy_primer run! This is because it's called // `static-frame` as part of a mypy_primer run! This is because it's called
// from `NominalInstanceType::class()`, which is a very hot method. // from `NominalInstanceType::class()`, which is a very hot method.
#[salsa::tracked] #[salsa::tracked(heap_size=ruff_memory_usage::heap_size)]
pub(crate) fn to_class_type(self, db: &'db dyn Db) -> ClassType<'db> { pub(crate) fn to_class_type(self, db: &'db dyn Db) -> ClassType<'db> {
let tuple_class = KnownClass::Tuple let tuple_class = KnownClass::Tuple
.try_to_class_literal(db) .try_to_class_literal(db)
@ -302,7 +302,7 @@ pub(crate) type TupleSpec<'db> = Tuple<Type<'db>>;
/// ///
/// Our tuple representation can hold instances of any Rust type. For tuples containing Python /// Our tuple representation can hold instances of any Rust type. For tuples containing Python
/// types, use [`TupleSpec`], which defines some additional type-specific methods. /// types, use [`TupleSpec`], which defines some additional type-specific methods.
#[derive(Clone, Debug, Eq, Hash, PartialEq)] #[derive(Clone, Debug, Eq, Hash, PartialEq, get_size2::GetSize)]
pub struct FixedLengthTuple<T>(Vec<T>); pub struct FixedLengthTuple<T>(Vec<T>);
impl<T> FixedLengthTuple<T> { impl<T> FixedLengthTuple<T> {
@ -516,7 +516,7 @@ impl<'db> PySlice<'db> for FixedLengthTuple<Type<'db>> {
/// ///
/// Our tuple representation can hold instances of any Rust type. For tuples containing Python /// Our tuple representation can hold instances of any Rust type. For tuples containing Python
/// types, use [`TupleSpec`], which defines some additional type-specific methods. /// types, use [`TupleSpec`], which defines some additional type-specific methods.
#[derive(Clone, Debug, Eq, Hash, PartialEq)] #[derive(Clone, Debug, Eq, Hash, PartialEq, get_size2::GetSize)]
pub struct VariableLengthTuple<T> { pub struct VariableLengthTuple<T> {
pub(crate) prefix: Vec<T>, pub(crate) prefix: Vec<T>,
pub(crate) variable: T, pub(crate) variable: T,
@ -956,7 +956,7 @@ impl<'db> PyIndex<'db> for &VariableLengthTuple<Type<'db>> {
/// ///
/// Our tuple representation can hold instances of any Rust type. For tuples containing Python /// Our tuple representation can hold instances of any Rust type. For tuples containing Python
/// types, use [`TupleSpec`], which defines some additional type-specific methods. /// types, use [`TupleSpec`], which defines some additional type-specific methods.
#[derive(Clone, Debug, Eq, Hash, PartialEq)] #[derive(Clone, Debug, Eq, Hash, PartialEq, get_size2::GetSize)]
pub enum Tuple<T> { pub enum Tuple<T> {
Fixed(FixedLengthTuple<T>), Fixed(FixedLengthTuple<T>),
Variable(VariableLengthTuple<T>), Variable(VariableLengthTuple<T>),

View file

@ -26,7 +26,7 @@ use crate::semantic_index::scope::{FileScopeId, ScopeId};
/// * a return type of a cross-module query /// * a return type of a cross-module query
/// * a field of a type that is 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 /// * an argument of a cross-module query
#[salsa::tracked(debug)] #[salsa::tracked(debug, heap_size=ruff_memory_usage::heap_size)]
pub(crate) struct Unpack<'db> { pub(crate) struct Unpack<'db> {
pub(crate) file: File, pub(crate) file: File,
@ -46,6 +46,9 @@ pub(crate) struct Unpack<'db> {
pub(crate) value: UnpackValue<'db>, pub(crate) value: UnpackValue<'db>,
} }
// The Salsa heap is tracked separately.
impl get_size2::GetSize for Unpack<'_> {}
impl<'db> Unpack<'db> { impl<'db> Unpack<'db> {
pub(crate) fn target<'ast>( pub(crate) fn target<'ast>(
self, self,
@ -67,7 +70,7 @@ impl<'db> Unpack<'db> {
} }
/// The expression that is being unpacked. /// The expression that is being unpacked.
#[derive(Clone, Copy, Debug, Hash, salsa::Update)] #[derive(Clone, Copy, Debug, Hash, salsa::Update, get_size2::GetSize)]
pub(crate) struct UnpackValue<'db> { pub(crate) struct UnpackValue<'db> {
/// The kind of unpack expression /// The kind of unpack expression
kind: UnpackKind, kind: UnpackKind,
@ -99,7 +102,7 @@ impl<'db> UnpackValue<'db> {
} }
} }
#[derive(Clone, Copy, Debug, Hash, salsa::Update)] #[derive(Clone, Copy, Debug, Hash, salsa::Update, get_size2::GetSize)]
pub(crate) enum EvaluationMode { pub(crate) enum EvaluationMode {
Sync, Sync,
Async, Async,
@ -119,7 +122,7 @@ impl EvaluationMode {
} }
} }
#[derive(Clone, Copy, Debug, Hash, salsa::Update)] #[derive(Clone, Copy, Debug, Hash, salsa::Update, get_size2::GetSize)]
pub(crate) enum UnpackKind { pub(crate) enum UnpackKind {
/// An iterable expression like the one in a `for` loop or a comprehension. /// An iterable expression like the one in a `for` loop or a comprehension.
Iterable { mode: EvaluationMode }, Iterable { mode: EvaluationMode },
@ -130,7 +133,7 @@ pub(crate) enum UnpackKind {
} }
/// The position of the target element in an unpacking. /// The position of the target element in an unpacking.
#[derive(Clone, Copy, Debug, Hash, PartialEq, salsa::Update)] #[derive(Clone, Copy, Debug, Hash, PartialEq, salsa::Update, get_size2::GetSize)]
pub(crate) enum UnpackPosition { pub(crate) enum UnpackPosition {
/// The target element is in the first position of the unpacking. /// The target element is in the first position of the unpacking.
First, First,