diff --git a/crates/ruff/src/checkers/ast/deferred.rs b/crates/ruff/src/checkers/ast/deferred.rs index e72f7dbd46..fdf375f30d 100644 --- a/crates/ruff/src/checkers/ast/deferred.rs +++ b/crates/ruff/src/checkers/ast/deferred.rs @@ -1,13 +1,14 @@ use ruff_text_size::TextRange; use rustpython_parser::ast::Expr; -use ruff_python_semantic::Snapshot; +use ruff_python_semantic::{ScopeId, Snapshot}; /// A collection of AST nodes that are deferred for later analysis. /// Used to, e.g., store functions, whose bodies shouldn't be analyzed until all /// module-level definitions have been analyzed. #[derive(Debug, Default)] pub(crate) struct Deferred<'a> { + pub(crate) scopes: Vec, pub(crate) string_type_definitions: Vec<(TextRange, &'a str, Snapshot)>, pub(crate) future_type_definitions: Vec<(&'a Expr, Snapshot)>, pub(crate) functions: Vec, diff --git a/crates/ruff/src/checkers/ast/mod.rs b/crates/ruff/src/checkers/ast/mod.rs index f6f3f1ab45..67237eb737 100644 --- a/crates/ruff/src/checkers/ast/mod.rs +++ b/crates/ruff/src/checkers/ast/mod.rs @@ -2038,10 +2038,12 @@ where // Post-visit. match stmt { Stmt::FunctionDef(_) | Stmt::AsyncFunctionDef(_) => { + self.deferred.scopes.push(self.semantic.scope_id); self.semantic.pop_scope(); self.semantic.pop_definition(); } Stmt::ClassDef(ast::StmtClassDef { name, .. }) => { + self.deferred.scopes.push(self.semantic.scope_id); self.semantic.pop_scope(); self.semantic.pop_definition(); self.add_binding( @@ -3785,6 +3787,7 @@ where | Expr::ListComp(_) | Expr::DictComp(_) | Expr::SetComp(_) => { + self.deferred.scopes.push(self.semantic.scope_id); self.semantic.pop_scope(); } _ => {} @@ -4692,7 +4695,7 @@ impl<'a> Checker<'a> { } } - fn check_dead_scopes(&mut self) { + fn check_deferred_scopes(&mut self) { if !self.any_enabled(&[ Rule::UnusedImport, Rule::GlobalVariableNotAssigned, @@ -4771,7 +4774,7 @@ impl<'a> Checker<'a> { }; let mut diagnostics: Vec = vec![]; - for scope_id in self.semantic.dead_scopes.iter().rev() { + for scope_id in self.deferred.scopes.iter().rev() { let scope = &self.semantic.scopes[*scope_id]; if scope.kind.is_module() { @@ -5256,8 +5259,8 @@ pub(crate) fn check_ast( // Reset the scope to module-level, and check all consumed scopes. checker.semantic.scope_id = ScopeId::global(); - checker.semantic.dead_scopes.push(ScopeId::global()); - checker.check_dead_scopes(); + checker.deferred.scopes.push(ScopeId::global()); + checker.check_deferred_scopes(); checker.diagnostics } diff --git a/crates/ruff_python_semantic/src/model.rs b/crates/ruff_python_semantic/src/model.rs index 56778df02e..c69e52f999 100644 --- a/crates/ruff_python_semantic/src/model.rs +++ b/crates/ruff_python_semantic/src/model.rs @@ -40,7 +40,6 @@ pub struct SemanticModel<'a> { /// Stack of all scopes, along with the identifier of the current scope. pub scopes: Scopes<'a>, pub scope_id: ScopeId, - pub dead_scopes: Vec, /// Stack of all definitions created in any scope, at any point in execution. pub definitions: Definitions<'a>, @@ -130,7 +129,6 @@ impl<'a> SemanticModel<'a> { exprs: Vec::default(), scopes: Scopes::default(), scope_id: ScopeId::global(), - dead_scopes: Vec::default(), definitions: Definitions::for_module(module), definition_id: DefinitionId::module(), bindings: Bindings::default(), @@ -596,7 +594,6 @@ impl<'a> SemanticModel<'a> { /// Pop the current [`Scope`] off the stack. pub fn pop_scope(&mut self) { - self.dead_scopes.push(self.scope_id); self.scope_id = self.scopes[self.scope_id] .parent .expect("Attempted to pop without scope");