Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/body/scope.rs')
| -rw-r--r-- | crates/hir-def/src/body/scope.rs | 63 |
1 files changed, 40 insertions, 23 deletions
diff --git a/crates/hir-def/src/body/scope.rs b/crates/hir-def/src/body/scope.rs index 0020e4eac3..fd685235e1 100644 --- a/crates/hir-def/src/body/scope.rs +++ b/crates/hir-def/src/body/scope.rs @@ -7,7 +7,7 @@ use crate::{ body::Body, db::DefDatabase, hir::{Binding, BindingId, Expr, ExprId, LabelId, Pat, PatId, Statement}, - BlockId, DefWithBodyId, + BlockId, ConstBlockId, DefWithBodyId, }; pub type ScopeId = Idx<ScopeData>; @@ -46,7 +46,9 @@ pub struct ScopeData { impl ExprScopes { pub(crate) fn expr_scopes_query(db: &dyn DefDatabase, def: DefWithBodyId) -> Arc<ExprScopes> { let body = db.body(def); - let mut scopes = ExprScopes::new(&body); + let mut scopes = ExprScopes::new(&body, |const_block| { + db.lookup_intern_anonymous_const(const_block).root + }); scopes.shrink_to_fit(); Arc::new(scopes) } @@ -89,7 +91,10 @@ fn empty_entries(idx: usize) -> IdxRange<ScopeEntry> { } impl ExprScopes { - fn new(body: &Body) -> ExprScopes { + fn new( + body: &Body, + resolve_const_block: impl (Fn(ConstBlockId) -> ExprId) + Copy, + ) -> ExprScopes { let mut scopes = ExprScopes { scopes: Arena::default(), scope_entries: Arena::default(), @@ -100,7 +105,7 @@ impl ExprScopes { scopes.add_bindings(body, root, self_param); } scopes.add_params_bindings(body, root, &body.params); - compute_expr_scopes(body.body_expr, body, &mut scopes, &mut root); + compute_expr_scopes(body.body_expr, body, &mut scopes, &mut root, resolve_const_block); scopes } @@ -183,35 +188,46 @@ fn compute_block_scopes( body: &Body, scopes: &mut ExprScopes, scope: &mut ScopeId, + resolve_const_block: impl (Fn(ConstBlockId) -> ExprId) + Copy, ) { for stmt in statements { match stmt { Statement::Let { pat, initializer, else_branch, .. } => { if let Some(expr) = initializer { - compute_expr_scopes(*expr, body, scopes, scope); + compute_expr_scopes(*expr, body, scopes, scope, resolve_const_block); } if let Some(expr) = else_branch { - compute_expr_scopes(*expr, body, scopes, scope); + compute_expr_scopes(*expr, body, scopes, scope, resolve_const_block); } *scope = scopes.new_scope(*scope); scopes.add_pat_bindings(body, *scope, *pat); } Statement::Expr { expr, .. } => { - compute_expr_scopes(*expr, body, scopes, scope); + compute_expr_scopes(*expr, body, scopes, scope, resolve_const_block); } Statement::Item => (), } } if let Some(expr) = tail { - compute_expr_scopes(expr, body, scopes, scope); + compute_expr_scopes(expr, body, scopes, scope, resolve_const_block); } } -fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope: &mut ScopeId) { +fn compute_expr_scopes( + expr: ExprId, + body: &Body, + scopes: &mut ExprScopes, + scope: &mut ScopeId, + resolve_const_block: impl (Fn(ConstBlockId) -> ExprId) + Copy, +) { let make_label = |label: &Option<LabelId>| label.map(|label| (label, body.labels[label].name.clone())); + let compute_expr_scopes = |scopes: &mut ExprScopes, expr: ExprId, scope: &mut ScopeId| { + compute_expr_scopes(expr, body, scopes, scope, resolve_const_block) + }; + scopes.set_scope(expr, *scope); match &body[expr] { Expr::Block { statements, tail, id, label } => { @@ -219,53 +235,54 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope // 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, &mut scope); + compute_block_scopes(statements, *tail, body, scopes, &mut scope, resolve_const_block); } - Expr::Const(_) => { - // FIXME: This is broken. + Expr::Const(id) => { + let mut scope = scopes.root_scope(); + compute_expr_scopes(scopes, resolve_const_block(*id), &mut scope); } Expr::Unsafe { id, statements, tail } | Expr::Async { id, statements, tail } => { let mut scope = scopes.new_block_scope(*scope, *id, None); // 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, &mut scope); + compute_block_scopes(statements, *tail, body, scopes, &mut scope, resolve_const_block); } Expr::Loop { body: body_expr, label } => { let mut scope = scopes.new_labeled_scope(*scope, make_label(label)); - compute_expr_scopes(*body_expr, body, scopes, &mut scope); + compute_expr_scopes(scopes, *body_expr, &mut scope); } Expr::Closure { args, body: body_expr, .. } => { let mut scope = scopes.new_scope(*scope); scopes.add_params_bindings(body, scope, args); - compute_expr_scopes(*body_expr, body, scopes, &mut scope); + compute_expr_scopes(scopes, *body_expr, &mut scope); } Expr::Match { expr, arms } => { - compute_expr_scopes(*expr, body, scopes, scope); + compute_expr_scopes(scopes, *expr, scope); for arm in arms.iter() { let mut scope = scopes.new_scope(*scope); scopes.add_pat_bindings(body, scope, arm.pat); if let Some(guard) = arm.guard { scope = scopes.new_scope(scope); - compute_expr_scopes(guard, body, scopes, &mut scope); + compute_expr_scopes(scopes, guard, &mut scope); } - compute_expr_scopes(arm.expr, body, scopes, &mut scope); + compute_expr_scopes(scopes, arm.expr, &mut scope); } } &Expr::If { condition, then_branch, else_branch } => { let mut then_branch_scope = scopes.new_scope(*scope); - compute_expr_scopes(condition, body, scopes, &mut then_branch_scope); - compute_expr_scopes(then_branch, body, scopes, &mut then_branch_scope); + compute_expr_scopes(scopes, condition, &mut then_branch_scope); + compute_expr_scopes(scopes, then_branch, &mut then_branch_scope); if let Some(else_branch) = else_branch { - compute_expr_scopes(else_branch, body, scopes, scope); + compute_expr_scopes(scopes, else_branch, scope); } } &Expr::Let { pat, expr } => { - compute_expr_scopes(expr, body, scopes, scope); + compute_expr_scopes(scopes, expr, scope); *scope = scopes.new_scope(*scope); scopes.add_pat_bindings(body, *scope, pat); } - e => e.walk_child_exprs(|e| compute_expr_scopes(e, body, scopes, scope)), + e => e.walk_child_exprs(|e| compute_expr_scopes(scopes, e, scope)), }; } |