@@ -22,7 +22,8 @@ use crate::{
2222 db:: DefDatabase ,
2323 expander:: Expander ,
2424 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 ,
2627 } ,
2728 item_tree:: AttrOwner ,
2829 nameres:: DefMap ,
@@ -286,7 +287,8 @@ impl Body {
286287 | Pat :: Path ( ..)
287288 | Pat :: ConstBlock ( ..)
288289 | Pat :: Wild
289- | Pat :: Missing => { }
290+ | Pat :: Missing
291+ | Pat :: Expr ( _) => { }
290292 & Pat :: Bind { subpat, .. } => {
291293 if let Some ( subpat) = subpat {
292294 f ( subpat) ;
@@ -322,6 +324,143 @@ impl Body {
322324 None => true ,
323325 }
324326 }
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+ }
325464}
326465
327466impl Default for Body {
0 commit comments