aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonas Schievink <[email protected]>2021-02-09 16:11:44 +0000
committerJonas Schievink <[email protected]>2021-02-09 16:11:44 +0000
commit1956286368809718c70692e422893559ec487c62 (patch)
tree949e74c9e03c956a8d7fdaaab6aca9568d75a950
parent12c7b66a7c6963d42ab5f33a9ac3f0b30e351b69 (diff)
Add expression scopes for blocks
-rw-r--r--crates/hir_def/src/body/scope.rs22
1 files 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::{
9 body::Body, 9 body::Body,
10 db::DefDatabase, 10 db::DefDatabase,
11 expr::{Expr, ExprId, Pat, PatId, Statement}, 11 expr::{Expr, ExprId, Pat, PatId, Statement},
12 DefWithBodyId, 12 BlockId, DefWithBodyId,
13}; 13};
14 14
15pub type ScopeId = Idx<ScopeData>; 15pub type ScopeId = Idx<ScopeData>;
@@ -39,6 +39,7 @@ impl ScopeEntry {
39#[derive(Debug, PartialEq, Eq)] 39#[derive(Debug, PartialEq, Eq)]
40pub struct ScopeData { 40pub struct ScopeData {
41 parent: Option<ScopeId>, 41 parent: Option<ScopeId>,
42 block: Option<BlockId>,
42 entries: Vec<ScopeEntry>, 43 entries: Vec<ScopeEntry>,
43} 44}
44 45
@@ -61,6 +62,11 @@ impl ExprScopes {
61 &self.scopes[scope].entries 62 &self.scopes[scope].entries
62 } 63 }
63 64
65 /// If `scope` refers to a block expression scope, returns the corresponding `BlockId`.
66 pub fn block(&self, scope: ScopeId) -> Option<BlockId> {
67 self.scopes[scope].block
68 }
69
64 pub fn scope_chain(&self, scope: Option<ScopeId>) -> impl Iterator<Item = ScopeId> + '_ { 70 pub fn scope_chain(&self, scope: Option<ScopeId>) -> impl Iterator<Item = ScopeId> + '_ {
65 std::iter::successors(scope, move |&scope| self.scopes[scope].parent) 71 std::iter::successors(scope, move |&scope| self.scopes[scope].parent)
66 } 72 }
@@ -79,11 +85,15 @@ impl ExprScopes {
79 } 85 }
80 86
81 fn root_scope(&mut self) -> ScopeId { 87 fn root_scope(&mut self) -> ScopeId {
82 self.scopes.alloc(ScopeData { parent: None, entries: vec![] }) 88 self.scopes.alloc(ScopeData { parent: None, block: None, entries: vec![] })
83 } 89 }
84 90
85 fn new_scope(&mut self, parent: ScopeId) -> ScopeId { 91 fn new_scope(&mut self, parent: ScopeId) -> ScopeId {
86 self.scopes.alloc(ScopeData { parent: Some(parent), entries: vec![] }) 92 self.scopes.alloc(ScopeData { parent: Some(parent), block: None, entries: vec![] })
93 }
94
95 fn new_block_scope(&mut self, parent: ScopeId, block: BlockId) -> ScopeId {
96 self.scopes.alloc(ScopeData { parent: Some(parent), block: Some(block), entries: vec![] })
87 } 97 }
88 98
89 fn add_bindings(&mut self, body: &Body, scope: ScopeId, pat: PatId) { 99 fn add_bindings(&mut self, body: &Body, scope: ScopeId, pat: PatId) {
@@ -136,7 +146,11 @@ fn compute_block_scopes(
136fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope: ScopeId) { 146fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope: ScopeId) {
137 scopes.set_scope(expr, scope); 147 scopes.set_scope(expr, scope);
138 match &body[expr] { 148 match &body[expr] {
139 Expr::Block { statements, tail, .. } => { 149 Expr::Block { statements, tail, id, .. } => {
150 let scope = scopes.new_block_scope(scope, *id);
151 // Overwrite the old scope for the block expr, so that every block scope can be found
152 // via the block itself (important for blocks that only contain items, no expressions).
153 scopes.set_scope(expr, scope);
140 compute_block_scopes(&statements, *tail, body, scopes, scope); 154 compute_block_scopes(&statements, *tail, body, scopes, scope);
141 } 155 }
142 Expr::For { iterable, pat, body: body_expr, .. } => { 156 Expr::For { iterable, pat, body: body_expr, .. } => {