From 955138b74ab5157cec5f136bfcfd50ee8f2cd2aa Mon Sep 17 00:00:00 2001 From: Micha Reiser Date: Mon, 1 Jul 2024 15:50:07 +0200 Subject: [PATCH] Refactor `ast_ids` traits to take `ScopeId` instead of `VfsFile` plus `FileScopeId`. (#12139) --- .../src/semantic_index/ast_ids.rs | 67 +++++++------------ .../src/semantic_model.rs | 11 ++- .../src/types/infer.rs | 18 ++--- 3 files changed, 38 insertions(+), 58 deletions(-) diff --git a/crates/red_knot_python_semantic/src/semantic_index/ast_ids.rs b/crates/red_knot_python_semantic/src/semantic_index/ast_ids.rs index dd5081a1bf..5a69d7b507 100644 --- a/crates/red_knot_python_semantic/src/semantic_index/ast_ids.rs +++ b/crates/red_knot_python_semantic/src/semantic_index/ast_ids.rs @@ -74,10 +74,7 @@ pub trait HasScopedAstId { type Id: Copy; /// Returns the ID that uniquely identifies the node in `scope`. - /// - /// ## Panics - /// Panics if the node doesn't belong to `file` or is outside `scope`. - fn scoped_ast_id(&self, db: &dyn Db, file: VfsFile, scope: FileScopeId) -> Self::Id; + fn scoped_ast_id(&self, db: &dyn Db, scope: ScopeId) -> Self::Id; } /// Node that can be uniquely identified by an id in a [`FileScopeId`]. @@ -85,8 +82,8 @@ pub trait ScopedAstIdNode: HasScopedAstId { /// Looks up the AST node by its ID. /// /// ## Panics - /// May panic if the `id` does not belong to the AST of `file`, or is outside `scope`. - fn lookup_in_scope(db: &dyn Db, file: VfsFile, scope: FileScopeId, id: Self::Id) -> &Self + /// May panic if the `id` does not belong to the AST of `scope`. + fn lookup_in_scope<'db>(db: &'db dyn Db, scope: ScopeId<'db>, id: Self::Id) -> &'db Self where Self: Sized; } @@ -98,9 +95,9 @@ pub trait AstIdNode { /// Resolves the AST id of the node. /// /// ## Panics - /// May panic if the node does not belongs to `file`'s AST or is outside of `scope`. It may also + /// May panic if the node does not belong to `scope`. It may also /// return an incorrect node if that's the case. - fn ast_id(&self, db: &dyn Db, file: VfsFile, scope: FileScopeId) -> AstId; + fn ast_id(&self, db: &dyn Db, scope: ScopeId) -> AstId; /// Resolves the AST node for `id`. /// @@ -118,17 +115,21 @@ where { type ScopeId = T::Id; - fn ast_id(&self, db: &dyn Db, file: VfsFile, scope: FileScopeId) -> AstId { - let in_scope_id = self.scoped_ast_id(db, file, scope); - AstId { scope, in_scope_id } + fn ast_id(&self, db: &dyn Db, scope: ScopeId) -> AstId { + let in_scope_id = self.scoped_ast_id(db, scope); + AstId { + scope: scope.file_scope_id(db), + in_scope_id, + } } fn lookup(db: &dyn Db, file: VfsFile, id: AstId) -> &Self where Self: Sized, { - let scope = id.scope; - Self::lookup_in_scope(db, file, scope, id.in_scope_id) + let scope = id.scope.to_scope_id(db, file); + + Self::lookup_in_scope(db, scope, id.in_scope_id) } } @@ -161,14 +162,9 @@ macro_rules! impl_has_scoped_expression_id { impl HasScopedAstId for $ty { type Id = ScopedExpressionId; - fn scoped_ast_id( - &self, - db: &dyn Db, - file: VfsFile, - file_scope: FileScopeId, - ) -> Self::Id { + fn scoped_ast_id(&self, db: &dyn Db, scope: ScopeId) -> Self::Id { let expression_ref = ExpressionRef::from(self); - expression_ref.scoped_ast_id(db, file, file_scope) + expression_ref.scoped_ast_id(db, scope) } } }; @@ -211,16 +207,14 @@ impl_has_scoped_expression_id!(ast::Expr); impl HasScopedAstId for ast::ExpressionRef<'_> { type Id = ScopedExpressionId; - fn scoped_ast_id(&self, db: &dyn Db, file: VfsFile, file_scope: FileScopeId) -> Self::Id { - let scope = file_scope.to_scope_id(db, file); + fn scoped_ast_id(&self, db: &dyn Db, scope: ScopeId) -> Self::Id { let ast_ids = ast_ids(db, scope); ast_ids.expression_id(*self) } } impl ScopedAstIdNode for ast::Expr { - fn lookup_in_scope(db: &dyn Db, file: VfsFile, file_scope: FileScopeId, id: Self::Id) -> &Self { - let scope = file_scope.to_scope_id(db, file); + fn lookup_in_scope<'db>(db: &'db dyn Db, scope: ScopeId<'db>, id: Self::Id) -> &'db Self { let ast_ids = ast_ids(db, scope); ast_ids.expressions[id].node() } @@ -235,13 +229,7 @@ macro_rules! impl_has_scoped_statement_id { impl HasScopedAstId for $ty { type Id = ScopedStatementId; - fn scoped_ast_id( - &self, - db: &dyn Db, - file: VfsFile, - file_scope: FileScopeId, - ) -> Self::Id { - let scope = file_scope.to_scope_id(db, file); + fn scoped_ast_id(&self, db: &dyn Db, scope: ScopeId) -> Self::Id { let ast_ids = ast_ids(db, scope); ast_ids.statement_id(self) } @@ -252,8 +240,7 @@ macro_rules! impl_has_scoped_statement_id { impl_has_scoped_statement_id!(ast::Stmt); impl ScopedAstIdNode for ast::Stmt { - fn lookup_in_scope(db: &dyn Db, file: VfsFile, file_scope: FileScopeId, id: Self::Id) -> &Self { - let scope = file_scope.to_scope_id(db, file); + fn lookup_in_scope<'db>(db: &'db dyn Db, scope: ScopeId<'db>, id: Self::Id) -> &'db Self { let ast_ids = ast_ids(db, scope); ast_ids.statements[id].node() @@ -266,16 +253,15 @@ pub struct ScopedFunctionId(pub(super) ScopedStatementId); impl HasScopedAstId for ast::StmtFunctionDef { type Id = ScopedFunctionId; - fn scoped_ast_id(&self, db: &dyn Db, file: VfsFile, file_scope: FileScopeId) -> Self::Id { - let scope = file_scope.to_scope_id(db, file); + fn scoped_ast_id(&self, db: &dyn Db, scope: ScopeId) -> Self::Id { let ast_ids = ast_ids(db, scope); ScopedFunctionId(ast_ids.statement_id(self)) } } impl ScopedAstIdNode for ast::StmtFunctionDef { - fn lookup_in_scope(db: &dyn Db, file: VfsFile, scope: FileScopeId, id: Self::Id) -> &Self { - ast::Stmt::lookup_in_scope(db, file, scope, id.0) + fn lookup_in_scope<'db>(db: &'db dyn Db, scope: ScopeId<'db>, id: Self::Id) -> &'db Self { + ast::Stmt::lookup_in_scope(db, scope, id.0) .as_function_def_stmt() .unwrap() } @@ -287,16 +273,15 @@ pub struct ScopedClassId(pub(super) ScopedStatementId); impl HasScopedAstId for ast::StmtClassDef { type Id = ScopedClassId; - fn scoped_ast_id(&self, db: &dyn Db, file: VfsFile, file_scope: FileScopeId) -> Self::Id { - let scope = file_scope.to_scope_id(db, file); + fn scoped_ast_id(&self, db: &dyn Db, scope: ScopeId) -> Self::Id { let ast_ids = ast_ids(db, scope); ScopedClassId(ast_ids.statement_id(self)) } } impl ScopedAstIdNode for ast::StmtClassDef { - fn lookup_in_scope(db: &dyn Db, file: VfsFile, scope: FileScopeId, id: Self::Id) -> &Self { - let statement = ast::Stmt::lookup_in_scope(db, file, scope, id.0); + fn lookup_in_scope<'db>(db: &'db dyn Db, scope: ScopeId<'db>, id: Self::Id) -> &'db Self { + let statement = ast::Stmt::lookup_in_scope(db, scope, id.0); statement.as_class_def_stmt().unwrap() } } diff --git a/crates/red_knot_python_semantic/src/semantic_model.rs b/crates/red_knot_python_semantic/src/semantic_model.rs index 3768631d91..6e5800bc5c 100644 --- a/crates/red_knot_python_semantic/src/semantic_model.rs +++ b/crates/red_knot_python_semantic/src/semantic_model.rs @@ -45,9 +45,10 @@ impl HasTy for ast::ExpressionRef<'_> { fn ty<'db>(&self, model: &SemanticModel<'db>) -> Type<'db> { let index = semantic_index(model.db, model.file); let file_scope = index.expression_scope_id(*self); - let expression_id = self.scoped_ast_id(model.db, model.file, file_scope); - let scope = file_scope.to_scope_id(model.db, model.file); + + let expression_id = self.scoped_ast_id(model.db, scope); + infer_types(model.db, scope).expression_ty(expression_id) } } @@ -152,8 +153,7 @@ impl HasTy for ast::StmtFunctionDef { let scope = parent_scope_id.to_scope_id(model.db, model.file); let types = infer_types(model.db, scope); - let definition = - Definition::FunctionDef(self.scoped_ast_id(model.db, model.file, parent_scope_id)); + let definition = Definition::FunctionDef(self.scoped_ast_id(model.db, scope)); types.definition_ty(definition) } @@ -175,8 +175,7 @@ impl HasTy for StmtClassDef { let scope = parent_scope_id.to_scope_id(model.db, model.file); let types = infer_types(model.db, scope); - let definition = - Definition::ClassDef(self.scoped_ast_id(model.db, model.file, parent_scope_id)); + let definition = Definition::ClassDef(self.scoped_ast_id(model.db, scope)); types.definition_ty(definition) } diff --git a/crates/red_knot_python_semantic/src/types/infer.rs b/crates/red_knot_python_semantic/src/types/infer.rs index 6830a58d6b..423fce7955 100644 --- a/crates/red_knot_python_semantic/src/types/infer.rs +++ b/crates/red_knot_python_semantic/src/types/infer.rs @@ -191,7 +191,7 @@ impl<'db> TypeInferenceBuilder<'db> { decorator_list, } = function; - let function_id = function.scoped_ast_id(self.db, self.file_id, self.file_scope_id); + let function_id = function.scoped_ast_id(self.db, self.scope); let decorator_tys = decorator_list .iter() .map(|decorator| self.infer_decorator(decorator)) @@ -231,7 +231,7 @@ impl<'db> TypeInferenceBuilder<'db> { body: _, } = class; - let class_id = class.scoped_ast_id(self.db, self.file_id, self.file_scope_id); + let class_id = class.scoped_ast_id(self.db, self.scope); for decorator in decorator_list { self.infer_decorator(decorator); @@ -303,7 +303,7 @@ impl<'db> TypeInferenceBuilder<'db> { self.infer_expression(target); } - let assign_id = assignment.scoped_ast_id(self.db, self.file_id, self.file_scope_id); + let assign_id = assignment.scoped_ast_id(self.db, self.scope); // TODO: Handle multiple targets. self.types @@ -328,11 +328,7 @@ impl<'db> TypeInferenceBuilder<'db> { self.infer_expression(target); self.types.definition_tys.insert( - Definition::AnnotatedAssignment(assignment.scoped_ast_id( - self.db, - self.file_id, - self.file_scope_id, - )), + Definition::AnnotatedAssignment(assignment.scoped_ast_id(self.db, self.scope)), annotation_ty, ); } @@ -356,7 +352,7 @@ impl<'db> TypeInferenceBuilder<'db> { fn infer_import_statement(&mut self, import: &ast::StmtImport) { let ast::StmtImport { range: _, names } = import; - let import_id = import.scoped_ast_id(self.db, self.file_id, self.file_scope_id); + let import_id = import.scoped_ast_id(self.db, self.scope); for (i, alias) in names.iter().enumerate() { let ast::Alias { @@ -389,7 +385,7 @@ impl<'db> TypeInferenceBuilder<'db> { level: _, } = import; - let import_id = import.scoped_ast_id(self.db, self.file_id, self.file_scope_id); + let import_id = import.scoped_ast_id(self.db, self.scope); let module_name = ModuleName::new(module.as_deref().expect("Support relative imports")); let module = @@ -492,7 +488,7 @@ impl<'db> TypeInferenceBuilder<'db> { self.infer_expression(target); self.types.definition_tys.insert( - Definition::NamedExpr(named.scoped_ast_id(self.db, self.file_id, self.file_scope_id)), + Definition::NamedExpr(named.scoped_ast_id(self.db, self.scope)), value_ty, );