[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

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`)
#[salsa::tracked(debug)]
#[salsa::tracked(debug, heap_size=ruff_memory_usage::heap_size)]
pub struct FileModule<'db> {
#[returns(ref)]
name: ModuleName,
@ -226,7 +226,7 @@ pub struct FileModule<'db> {
///
/// Namespace packages are special because there are
/// 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> {
#[returns(ref)]
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
#[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 {
/// Stubs are allowed to appear.
///
@ -60,7 +60,7 @@ pub(crate) enum ModuleResolveMode {
StubsNotAllowed,
}
#[salsa::interned]
#[salsa::interned(heap_size=ruff_memory_usage::heap_size)]
#[derive(Debug)]
pub(crate) struct ModuleResolveModeIngredient<'db> {
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)
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[derive(Clone, Debug, PartialEq, Eq, get_size2::GetSize)]
pub struct SearchPaths {
/// Search paths that have been statically determined purely from reading
/// 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.
///
/// 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> {
#[returns(ref)]
pub(super) name: ModuleName,

View file

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

View file

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

View file

@ -1,7 +1,7 @@
use std::fmt::{Display, Formatter};
/// The target platform to assume when resolving types.
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq, get_size2::GetSize)]
#[cfg_attr(
feature = "serde",
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
/// 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.
#[salsa::tracked(debug)]
#[salsa::tracked(debug, heap_size=ruff_memory_usage::heap_size)]
pub struct Definition<'db> {
/// The file in which the definition occurs.
pub file: File,
@ -645,7 +645,7 @@ impl DefinitionCategory {
/// [`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
/// for an in-depth explanation of why this is necessary.
#[derive(Clone, Debug)]
#[derive(Clone, Debug, get_size2::GetSize)]
pub enum DefinitionKind<'db> {
Import(ImportDefinitionKind),
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> {
Sequence(UnpackPosition, Unpack<'db>),
/// 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 {
node: AstNodeRef<ast::StmtImportFrom>,
symbol_id: ScopedSymbolId,
@ -880,7 +880,7 @@ impl StarImportDefinitionKind {
}
}
#[derive(Clone, Debug)]
#[derive(Clone, Debug, get_size2::GetSize)]
pub struct MatchPatternDefinitionKind {
pattern: AstNodeRef<ast::Pattern>,
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;
/// 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.
#[derive(Clone, Debug)]
#[derive(Clone, Debug, get_size2::GetSize)]
pub struct ComprehensionDefinitionKind<'db> {
target_kind: TargetKind<'db>,
iterable: AstNodeRef<ast::Expr>,
@ -933,7 +933,7 @@ impl<'db> ComprehensionDefinitionKind<'db> {
}
}
#[derive(Clone, Debug)]
#[derive(Clone, Debug, get_size2::GetSize)]
pub struct ImportDefinitionKind {
node: AstNodeRef<ast::StmtImport>,
alias_index: usize,
@ -954,7 +954,7 @@ impl ImportDefinitionKind {
}
}
#[derive(Clone, Debug)]
#[derive(Clone, Debug, get_size2::GetSize)]
pub struct ImportFromDefinitionKind {
node: AstNodeRef<ast::StmtImportFrom>,
alias_index: usize,
@ -975,7 +975,7 @@ impl ImportFromDefinitionKind {
}
}
#[derive(Clone, Debug)]
#[derive(Clone, Debug, get_size2::GetSize)]
pub struct AssignmentDefinitionKind<'db> {
target_kind: TargetKind<'db>,
value: AstNodeRef<ast::Expr>,
@ -996,7 +996,7 @@ impl<'db> AssignmentDefinitionKind<'db> {
}
}
#[derive(Clone, Debug)]
#[derive(Clone, Debug, get_size2::GetSize)]
pub struct AnnotatedAssignmentDefinitionKind {
annotation: 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> {
target_kind: TargetKind<'db>,
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> {
target_kind: TargetKind<'db>,
iterable: AstNodeRef<ast::Expr>,
@ -1069,7 +1069,7 @@ impl<'db> ForStmtDefinitionKind<'db> {
}
}
#[derive(Clone, Debug)]
#[derive(Clone, Debug, get_size2::GetSize)]
pub struct ExceptHandlerDefinitionKind {
handler: AstNodeRef<ast::ExceptHandlerExceptHandler>,
is_star: bool,

View file

@ -10,7 +10,7 @@ use salsa;
/// a type expression. For example, in `self.x: <annotation> = <value>`, the
/// `<annotation>` is inferred as a type expression, while `<value>` is inferred
/// 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 {
Normal,
TypeExpression,
@ -31,7 +31,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(debug)]
#[salsa::tracked(debug, heap_size=ruff_memory_usage::heap_size)]
pub(crate) struct Expression<'db> {
/// The file in which the expression occurs.
pub(crate) file: File,

View file

@ -117,7 +117,7 @@ pub(crate) enum PredicateNode<'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 {
Irrefutable,
Refutable,
@ -130,7 +130,7 @@ impl ClassPatternKind {
}
/// 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> {
Singleton(Singleton),
Value(Expression<'db>),
@ -140,7 +140,7 @@ pub(crate) enum PatternPredicateKind<'db> {
Unsupported,
}
#[salsa::tracked(debug)]
#[salsa::tracked(debug, heap_size=ruff_memory_usage::heap_size)]
pub(crate) struct PatternPredicate<'db> {
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`]
///
/// [Truthiness]: [crate::types::Truthiness]
#[salsa::tracked(debug)]
#[salsa::tracked(debug, heap_size=ruff_memory_usage::heap_size)]
pub(crate) struct StarImportPlaceholderPredicate<'db> {
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.
#[salsa::tracked(debug)]
#[salsa::tracked(debug, heap_size=ruff_memory_usage::heap_size)]
pub struct ScopeId<'db> {
pub file: File,

View file

@ -385,7 +385,7 @@ pub(crate) use todo_type;
/// # Ordering
/// 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.
#[salsa::interned(debug)]
#[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)]
pub struct PropertyInstanceType<'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,
/// since we sometimes have to apply type mappings lazily (e.g., to the signature of a function
/// literal).
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
#[derive(Clone, Debug, Eq, Hash, PartialEq, get_size2::GetSize)]
pub enum TypeMapping<'a, 'db> {
/// Applies a specialization to the type
Specialization(Specialization<'db>),
@ -6610,7 +6610,7 @@ impl<'db> InvalidTypeExpression<'db> {
}
/// 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)]
pub struct DeprecatedInstance<'db> {
/// 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
/// `dataclasses.field()`.
#[salsa::interned(debug)]
#[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)]
pub struct FieldInstance<'db> {
/// 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,
/// 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 {
/// `T = TypeVar("T")`
Legacy,
@ -6694,7 +6694,7 @@ pub enum TypeVarKind {
/// # Ordering
/// 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.
#[salsa::interned(debug)]
#[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)]
pub struct TypeVarInstance<'db> {
/// The name of this TypeVar (e.g. `T`)
@ -6789,7 +6789,7 @@ impl<'db> TypeVarInstance<'db> {
}
/// 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> {
/// The definition of the generic class, function, or type alias that binds this typevar.
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
/// concrete type.
#[salsa::interned(debug)]
#[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)]
pub struct BoundTypeVarInstance<'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 {
Invariant,
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> {
UpperBound(Type<'db>),
Constraints(UnionType<'db>),
@ -7916,7 +7916,7 @@ impl From<bool> for Truthiness {
/// # Ordering
/// 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.
#[salsa::interned(debug)]
#[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)]
pub struct BoundMethodType<'db> {
/// The function that is being bound. Corresponds to the `__func__` attribute on a
@ -7992,7 +7992,7 @@ impl<'db> BoundMethodType<'db> {
/// # Ordering
/// 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.
#[salsa::interned(debug)]
#[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)]
pub struct CallableType<'db> {
#[returns(ref)]
@ -8270,7 +8270,7 @@ pub enum WrapperDescriptorKind {
/// # Ordering
/// 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.
#[salsa::interned(debug)]
#[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)]
pub struct ModuleLiteralType<'db> {
/// The imported module.
@ -8380,7 +8380,7 @@ impl<'db> ModuleLiteralType<'db> {
/// # Ordering
/// 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.
#[salsa::interned(debug)]
#[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)]
pub struct PEP695TypeAliasType<'db> {
#[returns(ref)]
@ -8427,7 +8427,7 @@ impl<'db> PEP695TypeAliasType<'db> {
/// # Ordering
/// 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.
#[salsa::interned(debug)]
#[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)]
pub struct BareTypeAliasType<'db> {
#[returns(ref)]
@ -8522,7 +8522,7 @@ pub(super) struct MetaclassCandidate<'db> {
explicit_metaclass_of: ClassLiteral<'db>,
}
#[salsa::interned(debug)]
#[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
pub struct UnionType<'db> {
/// The union type includes values in any of these types.
#[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> {
/// The intersection type includes only values in all of these types.
#[returns(ref)]
@ -8938,12 +8938,17 @@ impl<'db> IntersectionType<'db> {
pub fn has_one_element(&self, db: &'db dyn Db) -> bool {
(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 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.
#[salsa::interned(debug)]
#[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)]
pub struct StringLiteralType<'db> {
#[returns(deref)]
@ -8971,7 +8976,7 @@ impl<'db> StringLiteralType<'db> {
/// # Ordering
/// 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.
#[salsa::interned(debug)]
#[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)]
pub struct BytesLiteralType<'db> {
#[returns(deref)]
@ -8996,7 +9001,7 @@ impl<'db> BytesLiteralType<'db> {
/// NO = 0
/// YES = 1
/// ```
#[salsa::interned(debug)]
#[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)]
pub struct EnumLiteralType<'db> {
/// 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
/// a given `TypedDict` schema.
#[salsa::interned(debug)]
#[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)]
pub struct TypedDictType<'db> {
/// 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> {
Dynamic(DynamicType),
Class(ClassType<'db>),
@ -9193,7 +9198,7 @@ impl<'db> From<SuperOwnerKind<'db>> for Type<'db> {
}
/// 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 pivot_class: ClassBase<'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> {
return_type: Type<'db>,
/// The ID of the scope to which the place belongs

View file

@ -212,7 +212,7 @@ impl CodeGeneratorKind {
/// # Ordering
/// 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.
#[salsa::interned(debug)]
#[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)]
pub struct GenericAlias<'db> {
pub(crate) origin: ClassLiteral<'db>,
@ -1147,7 +1147,7 @@ pub(crate) struct Field<'db> {
/// # Ordering
/// 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.
#[salsa::interned(debug)]
#[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)]
pub struct ClassLiteral<'db> {
/// 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
/// places.
/// 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))]
pub enum KnownClass {
// 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 {
pub(super) fn from_decorator_type(db: &dyn Db, decorator_type: Type) -> Self {
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
/// values. The id may change between runs, or when the function literal was garbage collected and
/// recreated.
#[salsa::interned(debug)]
#[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)]
pub struct OverloadLiteral<'db> {
/// 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
/// values. The id may change between runs, or when the function literal was garbage collected and
/// recreated.
#[salsa::interned(debug)]
#[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)]
pub struct FunctionLiteral<'db> {
pub(crate) last_definition: OverloadLiteral<'db>,
@ -433,6 +435,9 @@ pub struct FunctionLiteral<'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>(
db: &'db dyn 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
/// generic function.
#[salsa::interned(debug)]
#[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)]
pub struct FunctionType<'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
/// have special behavior.
#[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")]
#[cfg_attr(test, derive(strum_macros::EnumIter))]

View file

@ -89,7 +89,7 @@ pub(crate) fn bind_typevar<'db>(
/// # Ordering
/// 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.
#[salsa::interned(debug)]
#[salsa::interned(debug, heap_size=GenericContext::heap_size)]
#[derive(PartialOrd, Ord)]
pub struct GenericContext<'db> {
#[returns(ref)]
@ -363,6 +363,10 @@ impl<'db> GenericContext<'db> {
.collect();
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)]
@ -390,7 +394,7 @@ impl std::fmt::Display for LegacyGenericBase {
///
/// TODO: Handle nested specializations better, with actual parent links to the specialization of
/// the lexically containing context.
#[salsa::interned(debug)]
#[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
pub struct Specialization<'db> {
pub(crate) generic_context: GenericContext<'db>,
#[returns(deref)]
@ -401,6 +405,9 @@ pub struct Specialization<'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>(
db: &'db dyn 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
/// 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> {
generic_context: GenericContext<'db>,
types: Cow<'a, [Type<'db>]>,

View file

@ -70,7 +70,7 @@ impl<'db> Deref for ProtocolClassLiteral<'db> {
/// # Ordering
/// 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.
#[salsa::interned(debug)]
#[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)]
pub(super) struct ProtocolInterface<'db> {
#[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> {
kind: ProtocolMemberKind<'db>,
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> {
Method(CallableType<'db>),
Property(PropertyInstanceType<'db>),

View file

@ -125,7 +125,7 @@ impl TupleLength {
/// # Ordering
/// 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.
#[salsa::interned(debug, constructor=new_internal)]
#[salsa::interned(debug, constructor=new_internal, heap_size=ruff_memory_usage::heap_size)]
#[derive(PartialOrd, Ord)]
pub struct TupleType<'db> {
#[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
// `static-frame` as part of a mypy_primer run! This is because it's called
// 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> {
let tuple_class = KnownClass::Tuple
.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
/// 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>);
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
/// 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(crate) prefix: Vec<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
/// 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> {
Fixed(FixedLengthTuple<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 field of a type that is a return type 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) file: File,
@ -46,6 +46,9 @@ pub(crate) struct Unpack<'db> {
pub(crate) value: UnpackValue<'db>,
}
// The Salsa heap is tracked separately.
impl get_size2::GetSize for Unpack<'_> {}
impl<'db> Unpack<'db> {
pub(crate) fn target<'ast>(
self,
@ -67,7 +70,7 @@ impl<'db> Unpack<'db> {
}
/// 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> {
/// The kind of unpack expression
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 {
Sync,
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 {
/// An iterable expression like the one in a `for` loop or a comprehension.
Iterable { mode: EvaluationMode },
@ -130,7 +133,7 @@ pub(crate) enum UnpackKind {
}
/// 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 {
/// The target element is in the first position of the unpacking.
First,