@@ -7,7 +7,7 @@ use crate::{
7
7
body:: Body ,
8
8
db:: DefDatabase ,
9
9
hir:: { Binding , BindingId , Expr , ExprId , LabelId , Pat , PatId , Statement } ,
10
- BlockId , DefWithBodyId ,
10
+ BlockId , ConstBlockId , DefWithBodyId ,
11
11
} ;
12
12
13
13
pub type ScopeId = Idx < ScopeData > ;
@@ -46,7 +46,9 @@ pub struct ScopeData {
46
46
impl ExprScopes {
47
47
pub ( crate ) fn expr_scopes_query ( db : & dyn DefDatabase , def : DefWithBodyId ) -> Arc < ExprScopes > {
48
48
let body = db. body ( def) ;
49
- let mut scopes = ExprScopes :: new ( & body) ;
49
+ let mut scopes = ExprScopes :: new ( & body, |const_block| {
50
+ db. lookup_intern_anonymous_const ( const_block) . root
51
+ } ) ;
50
52
scopes. shrink_to_fit ( ) ;
51
53
Arc :: new ( scopes)
52
54
}
@@ -89,7 +91,10 @@ fn empty_entries(idx: usize) -> IdxRange<ScopeEntry> {
89
91
}
90
92
91
93
impl ExprScopes {
92
- fn new ( body : & Body ) -> ExprScopes {
94
+ fn new (
95
+ body : & Body ,
96
+ resolve_const_block : impl ( Fn ( ConstBlockId ) -> ExprId ) + Copy ,
97
+ ) -> ExprScopes {
93
98
let mut scopes = ExprScopes {
94
99
scopes : Arena :: default ( ) ,
95
100
scope_entries : Arena :: default ( ) ,
@@ -100,7 +105,7 @@ impl ExprScopes {
100
105
scopes. add_bindings ( body, root, self_param) ;
101
106
}
102
107
scopes. add_params_bindings ( body, root, & body. params ) ;
103
- compute_expr_scopes ( body. body_expr , body, & mut scopes, & mut root) ;
108
+ compute_expr_scopes ( body. body_expr , body, & mut scopes, & mut root, resolve_const_block ) ;
104
109
scopes
105
110
}
106
111
@@ -183,89 +188,101 @@ fn compute_block_scopes(
183
188
body : & Body ,
184
189
scopes : & mut ExprScopes ,
185
190
scope : & mut ScopeId ,
191
+ resolve_const_block : impl ( Fn ( ConstBlockId ) -> ExprId ) + Copy ,
186
192
) {
187
193
for stmt in statements {
188
194
match stmt {
189
195
Statement :: Let { pat, initializer, else_branch, .. } => {
190
196
if let Some ( expr) = initializer {
191
- compute_expr_scopes ( * expr, body, scopes, scope) ;
197
+ compute_expr_scopes ( * expr, body, scopes, scope, resolve_const_block ) ;
192
198
}
193
199
if let Some ( expr) = else_branch {
194
- compute_expr_scopes ( * expr, body, scopes, scope) ;
200
+ compute_expr_scopes ( * expr, body, scopes, scope, resolve_const_block ) ;
195
201
}
196
202
197
203
* scope = scopes. new_scope ( * scope) ;
198
204
scopes. add_pat_bindings ( body, * scope, * pat) ;
199
205
}
200
206
Statement :: Expr { expr, .. } => {
201
- compute_expr_scopes ( * expr, body, scopes, scope) ;
207
+ compute_expr_scopes ( * expr, body, scopes, scope, resolve_const_block ) ;
202
208
}
203
209
Statement :: Item => ( ) ,
204
210
}
205
211
}
206
212
if let Some ( expr) = tail {
207
- compute_expr_scopes ( expr, body, scopes, scope) ;
213
+ compute_expr_scopes ( expr, body, scopes, scope, resolve_const_block ) ;
208
214
}
209
215
}
210
216
211
- fn compute_expr_scopes ( expr : ExprId , body : & Body , scopes : & mut ExprScopes , scope : & mut ScopeId ) {
217
+ fn compute_expr_scopes (
218
+ expr : ExprId ,
219
+ body : & Body ,
220
+ scopes : & mut ExprScopes ,
221
+ scope : & mut ScopeId ,
222
+ resolve_const_block : impl ( Fn ( ConstBlockId ) -> ExprId ) + Copy ,
223
+ ) {
212
224
let make_label =
213
225
|label : & Option < LabelId > | label. map ( |label| ( label, body. labels [ label] . name . clone ( ) ) ) ;
214
226
227
+ let compute_expr_scopes = |scopes : & mut ExprScopes , expr : ExprId , scope : & mut ScopeId | {
228
+ compute_expr_scopes ( expr, body, scopes, scope, resolve_const_block)
229
+ } ;
230
+
215
231
scopes. set_scope ( expr, * scope) ;
216
232
match & body[ expr] {
217
233
Expr :: Block { statements, tail, id, label } => {
218
234
let mut scope = scopes. new_block_scope ( * scope, * id, make_label ( label) ) ;
219
235
// Overwrite the old scope for the block expr, so that every block scope can be found
220
236
// via the block itself (important for blocks that only contain items, no expressions).
221
237
scopes. set_scope ( expr, scope) ;
222
- compute_block_scopes ( statements, * tail, body, scopes, & mut scope) ;
238
+ compute_block_scopes ( statements, * tail, body, scopes, & mut scope, resolve_const_block ) ;
223
239
}
224
- Expr :: Const ( _) => {
225
- // FIXME: This is broken.
240
+ Expr :: Const ( id) => {
241
+ let mut scope = scopes. root_scope ( ) ;
242
+ compute_expr_scopes ( scopes, resolve_const_block ( * id) , & mut scope) ;
226
243
}
227
244
Expr :: Unsafe { id, statements, tail } | Expr :: Async { id, statements, tail } => {
228
245
let mut scope = scopes. new_block_scope ( * scope, * id, None ) ;
229
246
// Overwrite the old scope for the block expr, so that every block scope can be found
230
247
// via the block itself (important for blocks that only contain items, no expressions).
231
248
scopes. set_scope ( expr, scope) ;
232
- compute_block_scopes ( statements, * tail, body, scopes, & mut scope) ;
249
+ compute_block_scopes ( statements, * tail, body, scopes, & mut scope, resolve_const_block ) ;
233
250
}
234
251
Expr :: Loop { body : body_expr, label } => {
235
252
let mut scope = scopes. new_labeled_scope ( * scope, make_label ( label) ) ;
236
- compute_expr_scopes ( * body_expr , body , scopes , & mut scope) ;
253
+ compute_expr_scopes ( scopes , * body_expr , & mut scope) ;
237
254
}
238
255
Expr :: Closure { args, body : body_expr, .. } => {
239
256
let mut scope = scopes. new_scope ( * scope) ;
240
257
scopes. add_params_bindings ( body, scope, args) ;
241
- compute_expr_scopes ( * body_expr , body , scopes , & mut scope) ;
258
+ compute_expr_scopes ( scopes , * body_expr , & mut scope) ;
242
259
}
243
260
Expr :: Match { expr, arms } => {
244
- compute_expr_scopes ( * expr , body , scopes , scope) ;
261
+ compute_expr_scopes ( scopes , * expr , scope) ;
245
262
for arm in arms. iter ( ) {
246
263
let mut scope = scopes. new_scope ( * scope) ;
247
264
scopes. add_pat_bindings ( body, scope, arm. pat ) ;
248
265
if let Some ( guard) = arm. guard {
249
266
scope = scopes. new_scope ( scope) ;
250
- compute_expr_scopes ( guard , body , scopes , & mut scope) ;
267
+ compute_expr_scopes ( scopes , guard , & mut scope) ;
251
268
}
252
- compute_expr_scopes ( arm. expr , body , scopes , & mut scope) ;
269
+ compute_expr_scopes ( scopes , arm. expr , & mut scope) ;
253
270
}
254
271
}
255
272
& Expr :: If { condition, then_branch, else_branch } => {
256
273
let mut then_branch_scope = scopes. new_scope ( * scope) ;
257
- compute_expr_scopes ( condition , body , scopes , & mut then_branch_scope) ;
258
- compute_expr_scopes ( then_branch , body , scopes , & mut then_branch_scope) ;
274
+ compute_expr_scopes ( scopes , condition , & mut then_branch_scope) ;
275
+ compute_expr_scopes ( scopes , then_branch , & mut then_branch_scope) ;
259
276
if let Some ( else_branch) = else_branch {
260
- compute_expr_scopes ( else_branch , body , scopes , scope) ;
277
+ compute_expr_scopes ( scopes , else_branch , scope) ;
261
278
}
262
279
}
263
280
& Expr :: Let { pat, expr } => {
264
- compute_expr_scopes ( expr , body , scopes , scope) ;
281
+ compute_expr_scopes ( scopes , expr , scope) ;
265
282
* scope = scopes. new_scope ( * scope) ;
266
283
scopes. add_pat_bindings ( body, * scope, pat) ;
267
284
}
268
- e => e. walk_child_exprs ( |e| compute_expr_scopes ( e , body , scopes , scope) ) ,
285
+ e => e. walk_child_exprs ( |e| compute_expr_scopes ( scopes , e , scope) ) ,
269
286
} ;
270
287
}
271
288
0 commit comments