@@ -8,7 +8,7 @@ use rustc_hash::FxHashMap;
8
8
use crate :: {
9
9
body:: Body ,
10
10
db:: DefDatabase ,
11
- expr:: { Expr , ExprId , LabelId , MatchGuard , Pat , PatId , Statement } ,
11
+ expr:: { Expr , ExprId , LabelId , Pat , PatId , Statement } ,
12
12
BlockId , DefWithBodyId ,
13
13
} ;
14
14
@@ -53,9 +53,9 @@ impl ExprScopes {
53
53
fn new ( body : & Body ) -> ExprScopes {
54
54
let mut scopes =
55
55
ExprScopes { scopes : Arena :: default ( ) , scope_by_expr : FxHashMap :: default ( ) } ;
56
- let root = scopes. root_scope ( ) ;
56
+ let mut root = scopes. root_scope ( ) ;
57
57
scopes. add_params_bindings ( body, root, & body. params ) ;
58
- compute_expr_scopes ( body. body_expr , body, & mut scopes, root) ;
58
+ compute_expr_scopes ( body. body_expr , body, & mut scopes, & mut root) ;
59
59
scopes
60
60
}
61
61
@@ -151,79 +151,82 @@ fn compute_block_scopes(
151
151
match stmt {
152
152
Statement :: Let { pat, initializer, else_branch, .. } => {
153
153
if let Some ( expr) = initializer {
154
- compute_expr_scopes ( * expr, body, scopes, scope) ;
154
+ compute_expr_scopes ( * expr, body, scopes, & mut scope) ;
155
155
}
156
156
if let Some ( expr) = else_branch {
157
- compute_expr_scopes ( * expr, body, scopes, scope) ;
157
+ compute_expr_scopes ( * expr, body, scopes, & mut scope) ;
158
158
}
159
159
scope = scopes. new_scope ( scope) ;
160
160
scopes. add_bindings ( body, scope, * pat) ;
161
161
}
162
162
Statement :: Expr { expr, .. } => {
163
- compute_expr_scopes ( * expr, body, scopes, scope) ;
163
+ compute_expr_scopes ( * expr, body, scopes, & mut scope) ;
164
164
}
165
165
}
166
166
}
167
167
if let Some ( expr) = tail {
168
- compute_expr_scopes ( expr, body, scopes, scope) ;
168
+ compute_expr_scopes ( expr, body, scopes, & mut scope) ;
169
169
}
170
170
}
171
171
172
- fn compute_expr_scopes ( expr : ExprId , body : & Body , scopes : & mut ExprScopes , scope : ScopeId ) {
172
+ fn compute_expr_scopes ( expr : ExprId , body : & Body , scopes : & mut ExprScopes , scope : & mut ScopeId ) {
173
173
let make_label =
174
174
|label : & Option < LabelId > | label. map ( |label| ( label, body. labels [ label] . name . clone ( ) ) ) ;
175
175
176
- scopes. set_scope ( expr, scope) ;
176
+ scopes. set_scope ( expr, * scope) ;
177
177
match & body[ expr] {
178
178
Expr :: Block { statements, tail, id, label } => {
179
- let scope = scopes. new_block_scope ( scope, * id, make_label ( label) ) ;
179
+ let scope = scopes. new_block_scope ( * scope, * id, make_label ( label) ) ;
180
180
// Overwrite the old scope for the block expr, so that every block scope can be found
181
181
// via the block itself (important for blocks that only contain items, no expressions).
182
182
scopes. set_scope ( expr, scope) ;
183
183
compute_block_scopes ( statements, * tail, body, scopes, scope) ;
184
184
}
185
185
Expr :: For { iterable, pat, body : body_expr, label } => {
186
186
compute_expr_scopes ( * iterable, body, scopes, scope) ;
187
- let scope = scopes. new_labeled_scope ( scope, make_label ( label) ) ;
187
+ let mut scope = scopes. new_labeled_scope ( * scope, make_label ( label) ) ;
188
188
scopes. add_bindings ( body, scope, * pat) ;
189
- compute_expr_scopes ( * body_expr, body, scopes, scope) ;
189
+ compute_expr_scopes ( * body_expr, body, scopes, & mut scope) ;
190
190
}
191
191
Expr :: While { condition, body : body_expr, label } => {
192
- let scope = scopes. new_labeled_scope ( scope, make_label ( label) ) ;
193
- compute_expr_scopes ( * condition, body, scopes, scope) ;
194
- compute_expr_scopes ( * body_expr, body, scopes, scope) ;
192
+ let mut scope = scopes. new_labeled_scope ( * scope, make_label ( label) ) ;
193
+ compute_expr_scopes ( * condition, body, scopes, & mut scope) ;
194
+ compute_expr_scopes ( * body_expr, body, scopes, & mut scope) ;
195
195
}
196
196
Expr :: Loop { body : body_expr, label } => {
197
- let scope = scopes. new_labeled_scope ( scope, make_label ( label) ) ;
198
- compute_expr_scopes ( * body_expr, body, scopes, scope) ;
197
+ let mut scope = scopes. new_labeled_scope ( * scope, make_label ( label) ) ;
198
+ compute_expr_scopes ( * body_expr, body, scopes, & mut scope) ;
199
199
}
200
200
Expr :: Lambda { args, body : body_expr, .. } => {
201
- let scope = scopes. new_scope ( scope) ;
201
+ let mut scope = scopes. new_scope ( * scope) ;
202
202
scopes. add_params_bindings ( body, scope, args) ;
203
- compute_expr_scopes ( * body_expr, body, scopes, scope) ;
203
+ compute_expr_scopes ( * body_expr, body, scopes, & mut scope) ;
204
204
}
205
205
Expr :: Match { expr, arms } => {
206
206
compute_expr_scopes ( * expr, body, scopes, scope) ;
207
207
for arm in arms. iter ( ) {
208
- let mut scope = scopes. new_scope ( scope) ;
208
+ let mut scope = scopes. new_scope ( * scope) ;
209
209
scopes. add_bindings ( body, scope, arm. pat ) ;
210
- match arm. guard {
211
- Some ( MatchGuard :: If { expr : guard } ) => {
212
- scopes. set_scope ( guard, scope) ;
213
- compute_expr_scopes ( guard, body, scopes, scope) ;
214
- }
215
- Some ( MatchGuard :: IfLet { pat, expr : guard } ) => {
216
- scopes. set_scope ( guard, scope) ;
217
- compute_expr_scopes ( guard, body, scopes, scope) ;
218
- scope = scopes. new_scope ( scope) ;
219
- scopes. add_bindings ( body, scope, pat) ;
220
- }
221
- _ => { }
222
- } ;
223
- scopes. set_scope ( arm. expr , scope) ;
224
- compute_expr_scopes ( arm. expr , body, scopes, scope) ;
210
+ if let Some ( guard) = arm. guard {
211
+ scope = scopes. new_scope ( scope) ;
212
+ compute_expr_scopes ( guard, body, scopes, & mut scope) ;
213
+ }
214
+ compute_expr_scopes ( arm. expr , body, scopes, & mut scope) ;
215
+ }
216
+ }
217
+ & Expr :: If { condition, then_branch, else_branch } => {
218
+ let mut then_branch_scope = scopes. new_scope ( * scope) ;
219
+ compute_expr_scopes ( condition, body, scopes, & mut then_branch_scope) ;
220
+ compute_expr_scopes ( then_branch, body, scopes, & mut then_branch_scope) ;
221
+ if let Some ( else_branch) = else_branch {
222
+ compute_expr_scopes ( else_branch, body, scopes, scope) ;
225
223
}
226
224
}
225
+ & Expr :: Let { pat, expr } => {
226
+ compute_expr_scopes ( expr, body, scopes, scope) ;
227
+ * scope = scopes. new_scope ( * scope) ;
228
+ scopes. add_bindings ( body, * scope, pat) ;
229
+ }
227
230
e => e. walk_child_exprs ( |e| compute_expr_scopes ( e, body, scopes, scope) ) ,
228
231
} ;
229
232
}
@@ -500,8 +503,7 @@ fn foo() {
500
503
}
501
504
502
505
#[ test]
503
- fn while_let_desugaring ( ) {
504
- cov_mark:: check!( infer_resolve_while_let) ;
506
+ fn while_let_adds_binding ( ) {
505
507
do_check_local_name (
506
508
r#"
507
509
fn test() {
@@ -513,5 +515,53 @@ fn test() {
513
515
"# ,
514
516
75 ,
515
517
) ;
518
+ do_check_local_name (
519
+ r#"
520
+ fn test() {
521
+ let foo: Option<f32> = None;
522
+ while (((let Option::Some(_) = foo))) && let Option::Some(spam) = foo {
523
+ spam$0
524
+ }
525
+ }
526
+ "# ,
527
+ 107 ,
528
+ ) ;
529
+ }
530
+
531
+ #[ test]
532
+ fn match_guard_if_let ( ) {
533
+ do_check_local_name (
534
+ r#"
535
+ fn test() {
536
+ let foo: Option<f32> = None;
537
+ match foo {
538
+ _ if let Option::Some(spam) = foo => spam$0,
539
+ }
540
+ }
541
+ "# ,
542
+ 93 ,
543
+ ) ;
544
+ }
545
+
546
+ #[ test]
547
+ fn let_chains_can_reference_previous_lets ( ) {
548
+ do_check_local_name (
549
+ r#"
550
+ fn test() {
551
+ let foo: Option<i32> = None;
552
+ if let Some(spam) = foo && spa$0m > 1 && let Some(spam) = foo && spam > 1 {}
553
+ }
554
+ "# ,
555
+ 61 ,
556
+ ) ;
557
+ do_check_local_name (
558
+ r#"
559
+ fn test() {
560
+ let foo: Option<i32> = None;
561
+ if let Some(spam) = foo && spam > 1 && let Some(spam) = foo && sp$0am > 1 {}
562
+ }
563
+ "# ,
564
+ 100 ,
565
+ ) ;
516
566
}
517
567
}
0 commit comments