[ty] Use an interval map for scopes by expression (#19025)

This commit is contained in:
Micha Reiser 2025-07-14 13:50:58 +02:00 committed by GitHub
parent f22da352db
commit 3560f86450
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 136 additions and 22 deletions

View file

@ -1,7 +1,7 @@
use ruff_db::files::{File, FilePath};
use ruff_db::source::line_index;
use ruff_python_ast as ast;
use ruff_python_ast::{Expr, ExprRef, name::Name};
use ruff_python_ast::{Expr, ExprRef, HasNodeIndex, name::Name};
use ruff_source_file::LineIndex;
use crate::Db;
@ -126,7 +126,7 @@ impl<'db> SemanticModel<'db> {
// expression that we're in, then just
// fall back to the global scope.
None => Some(FileScopeId::global()),
Some(expr) => index.try_expression_scope_id(expr),
Some(expr) => index.try_expression_scope_id(&expr),
},
}) else {
return vec![];
@ -297,7 +297,7 @@ pub trait HasType {
impl HasType for ast::ExprRef<'_> {
fn inferred_type<'db>(&self, model: &SemanticModel<'db>) -> Type<'db> {
let index = semantic_index(model.db, model.file);
let file_scope = index.expression_scope_id(*self);
let file_scope = index.expression_scope_id(self);
let scope = file_scope.to_scope_id(model.db, model.file);
infer_scope_types(model.db, scope).expression_type(*self)
@ -419,6 +419,18 @@ impl HasType for ast::Alias {
}
}
/// Implemented by types for which the semantic index tracks their scope.
pub(crate) trait HasTrackedScope: HasNodeIndex {}
impl HasTrackedScope for ast::Expr {}
impl HasTrackedScope for ast::ExprRef<'_> {}
impl HasTrackedScope for &ast::ExprRef<'_> {}
// See https://github.com/astral-sh/ty/issues/572 why this implementation exists
// even when we never register identifiers during semantic index building.
impl HasTrackedScope for ast::Identifier {}
#[cfg(test)]
mod tests {
use ruff_db::files::system_path_to_file;