[ty] Use `ThinVec` in various places

This commit is contained in:
Micha Reiser 2025-07-18 09:19:48 +02:00
parent b8d2037373
commit 3e7cfca47c
No known key found for this signature in database
9 changed files with 122 additions and 12 deletions

1
Cargo.lock generated
View File

@ -4287,6 +4287,7 @@ dependencies = [
"strum_macros", "strum_macros",
"tempfile", "tempfile",
"test-case", "test-case",
"thin-vec",
"thiserror 2.0.12", "thiserror 2.0.12",
"tracing", "tracing",
"ty_python_semantic", "ty_python_semantic",

View File

@ -163,6 +163,7 @@ strum_macros = { version = "0.27.0" }
syn = { version = "2.0.55" } syn = { version = "2.0.55" }
tempfile = { version = "3.9.0" } tempfile = { version = "3.9.0" }
test-case = { version = "3.3.1" } test-case = { version = "3.3.1" }
thin-vec = { version = "0.2.14" }
thiserror = { version = "2.0.0" } thiserror = { version = "2.0.0" }
tikv-jemallocator = { version = "0.6.0" } tikv-jemallocator = { version = "0.6.0" }
toml = { version = "0.9.0" } toml = { version = "0.9.0" }

View File

@ -35,6 +35,7 @@ indexmap = { workspace = true }
itertools = { workspace = true } itertools = { workspace = true }
ordermap = { workspace = true } ordermap = { workspace = true }
salsa = { workspace = true, features = ["compact_str"] } salsa = { workspace = true, features = ["compact_str"] }
thin-vec = { workspace = true }
thiserror = { workspace = true } thiserror = { workspace = true }
tracing = { workspace = true } tracing = { workspace = true }
rustc-hash = { workspace = true } rustc-hash = { workspace = true }

View File

@ -26,6 +26,7 @@ use crate::semantic_index::place::{
}; };
use crate::semantic_index::use_def::{EagerSnapshotKey, ScopedEagerSnapshotId, UseDefMap}; use crate::semantic_index::use_def::{EagerSnapshotKey, ScopedEagerSnapshotId, UseDefMap};
use crate::semantic_model::HasTrackedScope; use crate::semantic_model::HasTrackedScope;
use crate::util::get_size::ThinVecSized;
use crate::util::get_size::untracked_arc_size; use crate::util::get_size::untracked_arc_size;
pub mod ast_ids; pub mod ast_ids;
@ -238,7 +239,7 @@ pub(crate) struct SemanticIndex<'db> {
eager_snapshots: FxHashMap<EagerSnapshotKey, ScopedEagerSnapshotId>, eager_snapshots: FxHashMap<EagerSnapshotKey, ScopedEagerSnapshotId>,
/// List of all semantic syntax errors in this file. /// List of all semantic syntax errors in this file.
semantic_syntax_errors: Vec<SemanticSyntaxError>, semantic_syntax_errors: ThinVecSized<SemanticSyntaxError>,
/// Set of all generator functions in this file. /// Set of all generator functions in this file.
generator_functions: FxHashSet<FileScopeId>, generator_functions: FxHashSet<FileScopeId>,

View File

@ -115,7 +115,7 @@ pub(super) struct SemanticIndexBuilder<'db, 'ast> {
generator_functions: FxHashSet<FileScopeId>, generator_functions: FxHashSet<FileScopeId>,
eager_snapshots: FxHashMap<EagerSnapshotKey, ScopedEagerSnapshotId>, eager_snapshots: FxHashMap<EagerSnapshotKey, ScopedEagerSnapshotId>,
/// Errors collected by the `semantic_checker`. /// Errors collected by the `semantic_checker`.
semantic_syntax_errors: RefCell<Vec<SemanticSyntaxError>>, semantic_syntax_errors: RefCell<thin_vec::ThinVec<SemanticSyntaxError>>,
} }
impl<'db, 'ast> SemanticIndexBuilder<'db, 'ast> { impl<'db, 'ast> SemanticIndexBuilder<'db, 'ast> {
@ -1063,7 +1063,7 @@ impl<'db, 'ast> SemanticIndexBuilder<'db, 'ast> {
imported_modules: Arc::new(self.imported_modules), imported_modules: Arc::new(self.imported_modules),
has_future_annotations: self.has_future_annotations, has_future_annotations: self.has_future_annotations,
eager_snapshots: self.eager_snapshots, eager_snapshots: self.eager_snapshots,
semantic_syntax_errors: self.semantic_syntax_errors.into_inner(), semantic_syntax_errors: self.semantic_syntax_errors.into_inner().into(),
generator_functions: self.generator_functions, generator_functions: self.generator_functions,
} }
} }

View File

@ -10,13 +10,13 @@ use ruff_index::{IndexVec, newtype_index};
use ruff_python_ast as ast; use ruff_python_ast as ast;
use ruff_python_ast::name::Name; use ruff_python_ast::name::Name;
use rustc_hash::FxHasher; use rustc_hash::FxHasher;
use smallvec::{SmallVec, smallvec};
use crate::Db; use crate::Db;
use crate::ast_node_ref::AstNodeRef; use crate::ast_node_ref::AstNodeRef;
use crate::node_key::NodeKey; use crate::node_key::NodeKey;
use crate::semantic_index::reachability_constraints::ScopedReachabilityConstraintId; use crate::semantic_index::reachability_constraints::ScopedReachabilityConstraintId;
use crate::semantic_index::{PlaceSet, SemanticIndex, semantic_index}; use crate::semantic_index::{PlaceSet, SemanticIndex, semantic_index};
use crate::util::get_size::ThinVecSized;
#[derive(Debug, Clone, PartialEq, Eq, Hash, get_size2::GetSize)] #[derive(Debug, Clone, PartialEq, Eq, Hash, get_size2::GetSize)]
pub(crate) enum PlaceExprSubSegment { pub(crate) enum PlaceExprSubSegment {
@ -41,7 +41,7 @@ impl PlaceExprSubSegment {
#[derive(Eq, PartialEq, Debug, get_size2::GetSize)] #[derive(Eq, PartialEq, Debug, get_size2::GetSize)]
pub struct PlaceExpr { pub struct PlaceExpr {
root_name: Name, root_name: Name,
sub_segments: SmallVec<[PlaceExprSubSegment; 1]>, sub_segments: ThinVecSized<PlaceExprSubSegment>,
} }
impl std::fmt::Display for PlaceExpr { impl std::fmt::Display for PlaceExpr {
@ -165,7 +165,7 @@ impl PlaceExpr {
pub(crate) fn name(name: Name) -> Self { pub(crate) fn name(name: Name) -> Self {
Self { Self {
root_name: name, root_name: name,
sub_segments: smallvec![], sub_segments: ThinVecSized::new(),
} }
} }
@ -230,7 +230,9 @@ impl std::fmt::Display for PlaceExprWithFlags {
} }
impl PlaceExprWithFlags { impl PlaceExprWithFlags {
pub(crate) fn new(expr: PlaceExpr) -> Self { pub(crate) fn new(mut expr: PlaceExpr) -> Self {
expr.sub_segments.shrink_to_fit();
PlaceExprWithFlags { PlaceExprWithFlags {
expr, expr,
flags: PlaceFlags::empty(), flags: PlaceFlags::empty(),

View File

@ -93,7 +93,7 @@ mod definition;
#[cfg(test)] #[cfg(test)]
mod property_tests; mod property_tests;
pub fn check_types(db: &dyn Db, file: File) -> Vec<Diagnostic> { pub fn check_types(db: &dyn Db, file: File) -> thin_vec::ThinVec<Diagnostic> {
let _span = tracing::trace_span!("check_types", ?file).entered(); let _span = tracing::trace_span!("check_types", ?file).entered();
tracing::debug!("Checking file '{path}'", path = file.path(db)); tracing::debug!("Checking file '{path}'", path = file.path(db));

View File

@ -18,6 +18,7 @@ use crate::types::string_annotation::{
use crate::types::tuple::TupleType; use crate::types::tuple::TupleType;
use crate::types::{SpecialFormType, Type, protocol_class::ProtocolClassLiteral}; use crate::types::{SpecialFormType, Type, protocol_class::ProtocolClassLiteral};
use crate::util::diagnostics::format_enumeration; use crate::util::diagnostics::format_enumeration;
use crate::util::get_size::ThinVecSized;
use crate::{Db, FxIndexMap, Module, ModuleName, Program, declare_lint}; use crate::{Db, FxIndexMap, Module, ModuleName, Program, declare_lint};
use itertools::Itertools; use itertools::Itertools;
use ruff_db::diagnostic::{Annotation, Diagnostic, Severity, SubDiagnostic}; use ruff_db::diagnostic::{Annotation, Diagnostic, Severity, SubDiagnostic};
@ -1614,7 +1615,7 @@ declare_lint! {
/// A collection of type check diagnostics. /// A collection of type check diagnostics.
#[derive(Default, Eq, PartialEq, get_size2::GetSize)] #[derive(Default, Eq, PartialEq, get_size2::GetSize)]
pub struct TypeCheckDiagnostics { pub struct TypeCheckDiagnostics {
diagnostics: Vec<Diagnostic>, diagnostics: ThinVecSized<Diagnostic>,
used_suppressions: FxHashSet<FileSuppressionId>, used_suppressions: FxHashSet<FileSuppressionId>,
} }
@ -1649,8 +1650,8 @@ impl TypeCheckDiagnostics {
self.diagnostics.shrink_to_fit(); self.diagnostics.shrink_to_fit();
} }
pub(crate) fn into_vec(self) -> Vec<Diagnostic> { pub(crate) fn into_vec(self) -> thin_vec::ThinVec<Diagnostic> {
self.diagnostics self.diagnostics.into_inner()
} }
pub fn iter(&self) -> std::slice::Iter<'_, Diagnostic> { pub fn iter(&self) -> std::slice::Iter<'_, Diagnostic> {
@ -1666,7 +1667,7 @@ impl std::fmt::Debug for TypeCheckDiagnostics {
impl IntoIterator for TypeCheckDiagnostics { impl IntoIterator for TypeCheckDiagnostics {
type Item = Diagnostic; type Item = Diagnostic;
type IntoIter = std::vec::IntoIter<Diagnostic>; type IntoIter = thin_vec::IntoIter<Diagnostic>;
fn into_iter(self) -> Self::IntoIter { fn into_iter(self) -> Self::IntoIter {
self.diagnostics.into_iter() self.diagnostics.into_iter()

View File

@ -1,3 +1,4 @@
use std::ops::{Deref, DerefMut};
use std::sync::Arc; use std::sync::Arc;
use get_size2::GetSize; use get_size2::GetSize;
@ -13,3 +14,105 @@ where
{ {
T::get_heap_size(&**arc) T::get_heap_size(&**arc)
} }
#[derive(Clone, Hash, PartialEq, Eq)]
pub(crate) struct ThinVecSized<T>(thin_vec::ThinVec<T>);
impl<T> ThinVecSized<T> {
pub(crate) fn into_inner(self) -> thin_vec::ThinVec<T> {
self.0
}
pub(crate) fn new() -> Self {
Self(thin_vec::ThinVec::new())
}
}
impl<T> Default for ThinVecSized<T> {
fn default() -> Self {
Self::new()
}
}
#[allow(unsafe_code)]
unsafe impl<T> salsa::Update for ThinVecSized<T>
where
T: salsa::Update,
{
unsafe fn maybe_update(old_pointer: *mut Self, new_value: Self) -> bool {
let old: &mut Self = unsafe { &mut *old_pointer };
unsafe { salsa::Update::maybe_update(&raw mut old.0, new_value.0) }
}
}
impl<T> std::fmt::Debug for ThinVecSized<T>
where
T: std::fmt::Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f)
}
}
impl<T> From<thin_vec::ThinVec<T>> for ThinVecSized<T> {
fn from(vec: thin_vec::ThinVec<T>) -> Self {
Self(vec)
}
}
impl<T> Deref for ThinVecSized<T> {
type Target = thin_vec::ThinVec<T>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> DerefMut for ThinVecSized<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<T> GetSize for ThinVecSized<T>
where
T: GetSize,
{
fn get_heap_size(&self) -> usize {
let mut total = 0;
for v in self {
total += GetSize::get_size(v);
}
let additional: usize = self.capacity() - self.len();
total += additional * T::get_stack_size();
total
}
}
impl<'a, T> IntoIterator for &'a ThinVecSized<T> {
type Item = &'a T;
type IntoIter = std::slice::Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.0.iter()
}
}
impl<'a, T> IntoIterator for &'a mut ThinVecSized<T> {
type Item = &'a mut T;
type IntoIter = std::slice::IterMut<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.0.iter_mut()
}
}
impl<T> IntoIterator for ThinVecSized<T> {
type Item = T;
type IntoIter = thin_vec::IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}