@@ -22,7 +22,8 @@ use crate::{
22
22
db:: DefDatabase ,
23
23
expander:: Expander ,
24
24
hir:: {
25
- dummy_expr_id, Binding , BindingId , Expr , ExprId , Label , LabelId , Pat , PatId , RecordFieldPat ,
25
+ dummy_expr_id, Array , AsmOperand , Binding , BindingId , Expr , ExprId , Label , LabelId , Pat ,
26
+ PatId , RecordFieldPat , Statement ,
26
27
} ,
27
28
item_tree:: AttrOwner ,
28
29
nameres:: DefMap ,
@@ -286,7 +287,8 @@ impl Body {
286
287
| Pat :: Path ( ..)
287
288
| Pat :: ConstBlock ( ..)
288
289
| Pat :: Wild
289
- | Pat :: Missing => { }
290
+ | Pat :: Missing
291
+ | Pat :: Expr ( _) => { }
290
292
& Pat :: Bind { subpat, .. } => {
291
293
if let Some ( subpat) = subpat {
292
294
f ( subpat) ;
@@ -322,6 +324,143 @@ impl Body {
322
324
None => true ,
323
325
}
324
326
}
327
+
328
+ pub fn walk_child_exprs ( & self , expr_id : ExprId , mut f : impl FnMut ( ExprId ) ) {
329
+ let expr = & self [ expr_id] ;
330
+ match expr {
331
+ Expr :: Continue { .. }
332
+ | Expr :: Const ( _)
333
+ | Expr :: Missing
334
+ | Expr :: Path ( _)
335
+ | Expr :: OffsetOf ( _)
336
+ | Expr :: Literal ( _)
337
+ | Expr :: Underscore => { }
338
+ Expr :: InlineAsm ( it) => it. operands . iter ( ) . for_each ( |( _, op) | match op {
339
+ AsmOperand :: In { expr, .. }
340
+ | AsmOperand :: Out { expr : Some ( expr) , .. }
341
+ | AsmOperand :: InOut { expr, .. } => f ( * expr) ,
342
+ AsmOperand :: SplitInOut { in_expr, out_expr, .. } => {
343
+ f ( * in_expr) ;
344
+ if let Some ( out_expr) = out_expr {
345
+ f ( * out_expr) ;
346
+ }
347
+ }
348
+ AsmOperand :: Out { expr : None , .. }
349
+ | AsmOperand :: Const ( _)
350
+ | AsmOperand :: Label ( _)
351
+ | AsmOperand :: Sym ( _) => ( ) ,
352
+ } ) ,
353
+ Expr :: If { condition, then_branch, else_branch } => {
354
+ f ( * condition) ;
355
+ f ( * then_branch) ;
356
+ if let & Some ( else_branch) = else_branch {
357
+ f ( else_branch) ;
358
+ }
359
+ }
360
+ Expr :: Let { expr, .. } => {
361
+ f ( * expr) ;
362
+ }
363
+ Expr :: Block { statements, tail, .. }
364
+ | Expr :: Unsafe { statements, tail, .. }
365
+ | Expr :: Async { statements, tail, .. } => {
366
+ for stmt in statements. iter ( ) {
367
+ match stmt {
368
+ Statement :: Let { initializer, else_branch, pat, .. } => {
369
+ if let & Some ( expr) = initializer {
370
+ f ( expr) ;
371
+ }
372
+ if let & Some ( expr) = else_branch {
373
+ f ( expr) ;
374
+ }
375
+ walk_exprs_in_pat ( self , * pat, & mut f) ;
376
+ }
377
+ Statement :: Expr { expr : expression, .. } => f ( * expression) ,
378
+ Statement :: Item => ( ) ,
379
+ }
380
+ }
381
+ if let & Some ( expr) = tail {
382
+ f ( expr) ;
383
+ }
384
+ }
385
+ Expr :: Loop { body, .. } => f ( * body) ,
386
+ Expr :: Call { callee, args, .. } => {
387
+ f ( * callee) ;
388
+ args. iter ( ) . copied ( ) . for_each ( f) ;
389
+ }
390
+ Expr :: MethodCall { receiver, args, .. } => {
391
+ f ( * receiver) ;
392
+ args. iter ( ) . copied ( ) . for_each ( f) ;
393
+ }
394
+ Expr :: Match { expr, arms } => {
395
+ f ( * expr) ;
396
+ arms. iter ( ) . map ( |arm| arm. expr ) . for_each ( f) ;
397
+ }
398
+ Expr :: Break { expr, .. }
399
+ | Expr :: Return { expr }
400
+ | Expr :: Yield { expr }
401
+ | Expr :: Yeet { expr } => {
402
+ if let & Some ( expr) = expr {
403
+ f ( expr) ;
404
+ }
405
+ }
406
+ Expr :: Become { expr } => f ( * expr) ,
407
+ Expr :: RecordLit { fields, spread, .. } => {
408
+ for field in fields. iter ( ) {
409
+ f ( field. expr ) ;
410
+ }
411
+ if let & Some ( expr) = spread {
412
+ f ( expr) ;
413
+ }
414
+ }
415
+ Expr :: Closure { body, .. } => {
416
+ f ( * body) ;
417
+ }
418
+ Expr :: BinaryOp { lhs, rhs, .. } => {
419
+ f ( * lhs) ;
420
+ f ( * rhs) ;
421
+ }
422
+ Expr :: Range { lhs, rhs, .. } => {
423
+ if let & Some ( lhs) = rhs {
424
+ f ( lhs) ;
425
+ }
426
+ if let & Some ( rhs) = lhs {
427
+ f ( rhs) ;
428
+ }
429
+ }
430
+ Expr :: Index { base, index, .. } => {
431
+ f ( * base) ;
432
+ f ( * index) ;
433
+ }
434
+ Expr :: Field { expr, .. }
435
+ | Expr :: Await { expr }
436
+ | Expr :: Cast { expr, .. }
437
+ | Expr :: Ref { expr, .. }
438
+ | Expr :: UnaryOp { expr, .. }
439
+ | Expr :: Box { expr } => {
440
+ f ( * expr) ;
441
+ }
442
+ Expr :: Tuple { exprs, .. } => exprs. iter ( ) . copied ( ) . for_each ( f) ,
443
+ Expr :: Array ( a) => match a {
444
+ Array :: ElementList { elements, .. } => elements. iter ( ) . copied ( ) . for_each ( f) ,
445
+ Array :: Repeat { initializer, repeat } => {
446
+ f ( * initializer) ;
447
+ f ( * repeat)
448
+ }
449
+ } ,
450
+ & Expr :: Assignment { target, value } => {
451
+ walk_exprs_in_pat ( self , target, & mut f) ;
452
+ f ( value) ;
453
+ }
454
+ }
455
+
456
+ fn walk_exprs_in_pat ( this : & Body , pat_id : PatId , f : & mut impl FnMut ( ExprId ) ) {
457
+ this. walk_pats ( pat_id, & mut |pat| {
458
+ if let Pat :: Expr ( expr) | Pat :: ConstBlock ( expr) = this[ pat] {
459
+ f ( expr) ;
460
+ }
461
+ } ) ;
462
+ }
463
+ }
325
464
}
326
465
327
466
impl Default for Body {
0 commit comments