From 1956286368809718c70692e422893559ec487c62 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Tue, 9 Feb 2021 17:11:44 +0100 Subject: Add expression scopes for blocks --- crates/hir_def/src/body/scope.rs | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/crates/hir_def/src/body/scope.rs b/crates/hir_def/src/body/scope.rs index 49f1427b4..210b4a617 100644 --- a/crates/hir_def/src/body/scope.rs +++ b/crates/hir_def/src/body/scope.rs @@ -9,7 +9,7 @@ use crate::{ body::Body, db::DefDatabase, expr::{Expr, ExprId, Pat, PatId, Statement}, - DefWithBodyId, + BlockId, DefWithBodyId, }; pub type ScopeId = Idx; @@ -39,6 +39,7 @@ impl ScopeEntry { #[derive(Debug, PartialEq, Eq)] pub struct ScopeData { parent: Option, + block: Option, entries: Vec, } @@ -61,6 +62,11 @@ impl ExprScopes { &self.scopes[scope].entries } + /// If `scope` refers to a block expression scope, returns the corresponding `BlockId`. + pub fn block(&self, scope: ScopeId) -> Option { + self.scopes[scope].block + } + pub fn scope_chain(&self, scope: Option) -> impl Iterator + '_ { std::iter::successors(scope, move |&scope| self.scopes[scope].parent) } @@ -79,11 +85,15 @@ impl ExprScopes { } fn root_scope(&mut self) -> ScopeId { - self.scopes.alloc(ScopeData { parent: None, entries: vec![] }) + self.scopes.alloc(ScopeData { parent: None, block: None, entries: vec![] }) } fn new_scope(&mut self, parent: ScopeId) -> ScopeId { - self.scopes.alloc(ScopeData { parent: Some(parent), entries: vec![] }) + self.scopes.alloc(ScopeData { parent: Some(parent), block: None, entries: vec![] }) + } + + fn new_block_scope(&mut self, parent: ScopeId, block: BlockId) -> ScopeId { + self.scopes.alloc(ScopeData { parent: Some(parent), block: Some(block), entries: vec![] }) } fn add_bindings(&mut self, body: &Body, scope: ScopeId, pat: PatId) { @@ -136,7 +146,11 @@ fn compute_block_scopes( fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope: ScopeId) { scopes.set_scope(expr, scope); match &body[expr] { - Expr::Block { statements, tail, .. } => { + Expr::Block { statements, tail, id, .. } => { + let scope = scopes.new_block_scope(scope, *id); + // Overwrite the old scope for the block expr, so that every block scope can be found + // via the block itself (important for blocks that only contain items, no expressions). + scopes.set_scope(expr, scope); compute_block_scopes(&statements, *tail, body, scopes, scope); } Expr::For { iterable, pat, body: body_expr, .. } => { -- cgit v1.2.3