mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-28 21:05:08 +00:00
[red-knot] Resolve references in eager nested scopes eagerly (#16079)
We now resolve references in "eager" scopes correctly — using the bindings and declarations that are visible at the point where the eager scope is created, not the "public" type of the symbol (typically the bindings visible at the end of the scope). --------- Co-authored-by: Alex Waygood <alex.waygood@gmail.com>
This commit is contained in:
parent
f50849aeef
commit
cfc6941d5c
7 changed files with 645 additions and 47 deletions
|
@ -19,7 +19,7 @@ use crate::semantic_index::expression::Expression;
|
|||
use crate::semantic_index::symbol::{
|
||||
FileScopeId, NodeWithScopeKey, NodeWithScopeRef, Scope, ScopeId, ScopedSymbolId, SymbolTable,
|
||||
};
|
||||
use crate::semantic_index::use_def::UseDefMap;
|
||||
use crate::semantic_index::use_def::{EagerBindingsKey, ScopedEagerBindingsId, UseDefMap};
|
||||
use crate::Db;
|
||||
|
||||
pub mod ast_ids;
|
||||
|
@ -165,6 +165,9 @@ pub(crate) struct SemanticIndex<'db> {
|
|||
/// Maps from class body scopes to attribute assignments that were found
|
||||
/// in methods of that class.
|
||||
attribute_assignments: FxHashMap<FileScopeId, Arc<AttributeAssignments<'db>>>,
|
||||
|
||||
/// Map of all of the eager bindings that appear in this file.
|
||||
eager_bindings: FxHashMap<EagerBindingsKey, ScopedEagerBindingsId>,
|
||||
}
|
||||
|
||||
impl<'db> SemanticIndex<'db> {
|
||||
|
@ -220,7 +223,7 @@ impl<'db> SemanticIndex<'db> {
|
|||
/// Returns the id of the parent scope.
|
||||
pub(crate) fn parent_scope_id(&self, scope_id: FileScopeId) -> Option<FileScopeId> {
|
||||
let scope = self.scope(scope_id);
|
||||
scope.parent
|
||||
scope.parent()
|
||||
}
|
||||
|
||||
/// Returns the parent scope of `scope_id`.
|
||||
|
@ -290,6 +293,23 @@ impl<'db> SemanticIndex<'db> {
|
|||
pub(super) fn has_future_annotations(&self) -> bool {
|
||||
self.has_future_annotations
|
||||
}
|
||||
|
||||
/// Returns an iterator of bindings for a particular nested eager scope reference.
|
||||
pub(crate) fn eager_bindings(
|
||||
&self,
|
||||
enclosing_scope: FileScopeId,
|
||||
symbol: &str,
|
||||
nested_scope: FileScopeId,
|
||||
) -> Option<BindingWithConstraintsIterator<'_, 'db>> {
|
||||
let symbol_id = self.symbol_tables[enclosing_scope].symbol_id_by_name(symbol)?;
|
||||
let key = EagerBindingsKey {
|
||||
enclosing_scope,
|
||||
enclosing_symbol: symbol_id,
|
||||
nested_scope,
|
||||
};
|
||||
let id = self.eager_bindings.get(&key)?;
|
||||
self.use_def_maps[enclosing_scope].eager_bindings(*id)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AncestorsIter<'a> {
|
||||
|
@ -312,7 +332,7 @@ impl<'a> Iterator for AncestorsIter<'a> {
|
|||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let current_id = self.next_id?;
|
||||
let current = &self.scopes[current_id];
|
||||
self.next_id = current.parent;
|
||||
self.next_id = current.parent();
|
||||
|
||||
Some((current_id, current))
|
||||
}
|
||||
|
@ -328,7 +348,7 @@ pub struct DescendentsIter<'a> {
|
|||
impl<'a> DescendentsIter<'a> {
|
||||
fn new(symbol_table: &'a SemanticIndex, scope_id: FileScopeId) -> Self {
|
||||
let scope = &symbol_table.scopes[scope_id];
|
||||
let scopes = &symbol_table.scopes[scope.descendents.clone()];
|
||||
let scopes = &symbol_table.scopes[scope.descendents()];
|
||||
|
||||
Self {
|
||||
next_id: scope_id + 1,
|
||||
|
@ -378,7 +398,7 @@ impl<'a> Iterator for ChildrenIter<'a> {
|
|||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.descendents
|
||||
.find(|(_, scope)| scope.parent == Some(self.parent))
|
||||
.find(|(_, scope)| scope.parent() == Some(self.parent))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue