1pub use rustc_ast_ir::visit::VisitorResult;
17pub use rustc_ast_ir::{try_visit, visit_opt, walk_list, walk_visitable_list};
18use rustc_span::source_map::Spanned;
19use rustc_span::{Ident, Span, Symbol};
20use thin_vec::ThinVec;
21
22use crate::ast::*;
23use crate::ptr::P;
24use crate::tokenstream::DelimSpan;
25
26#[derive(Copy, Clone, Debug, PartialEq)]
27pub enum AssocCtxt {
28 Trait,
29 Impl { of_trait: bool },
30}
31
32#[derive(Copy, Clone, Debug, PartialEq)]
33pub enum FnCtxt {
34 Free,
35 Foreign,
36 Assoc(AssocCtxt),
37}
38
39#[derive(Copy, Clone, Debug)]
40pub enum BoundKind {
41 Bound,
44
45 Impl,
48
49 TraitObject,
52
53 SuperTraits,
56}
57impl BoundKind {
58 pub fn descr(self) -> &'static str {
59 match self {
60 BoundKind::Bound => "bounds",
61 BoundKind::Impl => "`impl Trait`",
62 BoundKind::TraitObject => "`dyn` trait object bounds",
63 BoundKind::SuperTraits => "supertrait bounds",
64 }
65 }
66}
67
68#[derive(Copy, Clone, Debug)]
69pub enum LifetimeCtxt {
70 Ref,
72 Bound,
74 GenericArg,
76}
77
78pub(crate) trait Visitable<'a, V: Visitor<'a>> {
79 type Extra: Copy;
80
81 #[must_use]
82 fn visit(&'a self, visitor: &mut V, extra: Self::Extra) -> V::Result;
83}
84
85impl<'a, V: Visitor<'a>, T: ?Sized> Visitable<'a, V> for P<T>
86where
87 T: Visitable<'a, V>,
88{
89 type Extra = T::Extra;
90 fn visit(&'a self, visitor: &mut V, extra: Self::Extra) -> V::Result {
91 (**self).visit(visitor, extra)
92 }
93}
94
95impl<'a, V: Visitor<'a>, T> Visitable<'a, V> for Option<T>
96where
97 T: Visitable<'a, V>,
98{
99 type Extra = T::Extra;
100 fn visit(&'a self, visitor: &mut V, extra: Self::Extra) -> V::Result {
101 if let Some(this) = self {
102 try_visit!(this.visit(visitor, extra));
103 }
104 V::Result::output()
105 }
106}
107
108impl<'a, V: Visitor<'a>, T> Visitable<'a, V> for Spanned<T>
109where
110 T: Visitable<'a, V>,
111{
112 type Extra = T::Extra;
113 fn visit(&'a self, visitor: &mut V, extra: Self::Extra) -> V::Result {
114 let Spanned { span: _, node } = self;
115 node.visit(visitor, extra)
116 }
117}
118
119impl<'a, V: Visitor<'a>, T> Visitable<'a, V> for [T]
120where
121 T: Visitable<'a, V>,
122{
123 type Extra = T::Extra;
124 fn visit(&'a self, visitor: &mut V, extra: Self::Extra) -> V::Result {
125 for item in self {
126 try_visit!(item.visit(visitor, extra));
127 }
128 V::Result::output()
129 }
130}
131
132impl<'a, V: Visitor<'a>, T> Visitable<'a, V> for Vec<T>
133where
134 T: Visitable<'a, V>,
135{
136 type Extra = T::Extra;
137 fn visit(&'a self, visitor: &mut V, extra: Self::Extra) -> V::Result {
138 for item in self {
139 try_visit!(item.visit(visitor, extra));
140 }
141 V::Result::output()
142 }
143}
144
145impl<'a, V: Visitor<'a>, T> Visitable<'a, V> for (T,)
146where
147 T: Visitable<'a, V>,
148{
149 type Extra = T::Extra;
150 fn visit(&'a self, visitor: &mut V, extra: Self::Extra) -> V::Result {
151 self.0.visit(visitor, extra)
152 }
153}
154
155impl<'a, V: Visitor<'a>, T1, T2> Visitable<'a, V> for (T1, T2)
156where
157 T1: Visitable<'a, V, Extra = ()>,
158 T2: Visitable<'a, V, Extra = ()>,
159{
160 type Extra = ();
161 fn visit(&'a self, visitor: &mut V, extra: Self::Extra) -> V::Result {
162 try_visit!(self.0.visit(visitor, extra));
163 try_visit!(self.1.visit(visitor, extra));
164 V::Result::output()
165 }
166}
167
168impl<'a, V: Visitor<'a>, T1, T2, T3> Visitable<'a, V> for (T1, T2, T3)
169where
170 T1: Visitable<'a, V, Extra = ()>,
171 T2: Visitable<'a, V, Extra = ()>,
172 T3: Visitable<'a, V, Extra = ()>,
173{
174 type Extra = ();
175 fn visit(&'a self, visitor: &mut V, extra: Self::Extra) -> V::Result {
176 try_visit!(self.0.visit(visitor, extra));
177 try_visit!(self.1.visit(visitor, extra));
178 try_visit!(self.2.visit(visitor, extra));
179 V::Result::output()
180 }
181}
182
183impl<'a, V: Visitor<'a>, T1, T2, T3, T4> Visitable<'a, V> for (T1, T2, T3, T4)
184where
185 T1: Visitable<'a, V, Extra = ()>,
186 T2: Visitable<'a, V, Extra = ()>,
187 T3: Visitable<'a, V, Extra = ()>,
188 T4: Visitable<'a, V, Extra = ()>,
189{
190 type Extra = ();
191 fn visit(&'a self, visitor: &mut V, extra: Self::Extra) -> V::Result {
192 try_visit!(self.0.visit(visitor, extra));
193 try_visit!(self.1.visit(visitor, extra));
194 try_visit!(self.2.visit(visitor, extra));
195 try_visit!(self.3.visit(visitor, extra));
196 V::Result::output()
197 }
198}
199
200pub(crate) trait Walkable<'a, V: Visitor<'a>> {
201 #[must_use]
202 fn walk_ref(&'a self, visitor: &mut V) -> V::Result;
203}
204
205macro_rules! visit_visitable {
206 ($visitor:expr, $($expr:expr),* $(,)?) => {{
207 $(try_visit!(Visitable::visit($expr, $visitor, ()));)*
208 }};
209}
210
211macro_rules! visit_visitable_with {
212 ($visitor:expr, $expr:expr, $extra:expr $(,)?) => {
213 try_visit!(Visitable::visit($expr, $visitor, $extra))
214 };
215}
216
217macro_rules! walk_walkable {
218 ($visitor:expr, $expr:expr, ) => {
219 Walkable::walk_ref($expr, $visitor)
220 };
221}
222
223macro_rules! impl_visitable {
224 (|&$lt:lifetime $self:ident: $self_ty:ty,
225 $vis:ident: &mut $vis_ty:ident,
226 $extra:ident: $extra_ty:ty| $block:block) => {
227 #[allow(unused_parens, non_local_definitions)]
228 impl<$lt, $vis_ty: Visitor<$lt>> Visitable<$lt, $vis_ty> for $self_ty {
229 type Extra = $extra_ty;
230 fn visit(&$lt $self, $vis: &mut $vis_ty, $extra: Self::Extra) -> V::Result {
231 $block
232 }
233 }
234 };
235}
236
237macro_rules! impl_walkable {
238 ($(<$K:ident: $Kb:ident>)? |&$lt:lifetime $self:ident: $self_ty:ty,
239 $vis:ident: &mut $vis_ty:ident| $block:block) => {
240 #[allow(unused_parens, non_local_definitions)]
241 impl<$($K: $Kb,)? $lt, $vis_ty: Visitor<$lt>> Walkable<$lt, $vis_ty> for $self_ty {
242 fn walk_ref(&$lt $self, $vis: &mut $vis_ty) -> V::Result {
243 $block
244 }
245 }
246 };
247}
248
249macro_rules! impl_visitable_noop {
250 (<$lt:lifetime> $($ty:ty,)*) => {
251 $(
252 impl_visitable!(|&$lt self: $ty, _vis: &mut V, _extra: ()| {
253 V::Result::output()
254 });
255 )*
256 };
257}
258
259macro_rules! impl_visitable_list {
260 (<$lt:lifetime> $($ty:ty,)*) => {
261 $(impl<$lt, V: Visitor<$lt>, T> Visitable<$lt, V> for $ty
262 where
263 &$lt $ty: IntoIterator<Item = &$lt T>,
264 T: $lt + Visitable<$lt, V>,
265 {
266 type Extra = <T as Visitable<$lt, V>>::Extra;
267
268 #[inline]
269 fn visit(&$lt self, visitor: &mut V, extra: Self::Extra) -> V::Result {
270 for i in self {
271 try_visit!(i.visit(visitor, extra));
272 }
273 V::Result::output()
274 }
275 })*
276 };
277}
278
279macro_rules! impl_visitable_direct {
280 (<$lt:lifetime> $($ty:ty,)*) => {
281 $(impl_visitable!(
282 |&$lt self: $ty, visitor: &mut V, _extra: ()| {
283 Walkable::walk_ref(self, visitor)
284 }
285 );)*
286 };
287}
288
289macro_rules! impl_visitable_calling_walkable {
290 (<$lt:lifetime>
291 $( fn $method:ident($ty:ty $(, $extra_name:ident: $extra_ty:ty)?); )*
292 ) => {
293 $(fn $method(&mut self, node: &$lt $ty $(, $extra_name:$extra_ty)?) -> Self::Result {
294 impl_visitable!(|&$lt self: $ty, visitor: &mut V, extra: ($($extra_ty)?)| {
295 let ($($extra_name)?) = extra;
296 visitor.$method(self $(, $extra_name)?)
297 });
298 walk_walkable!(self, node, )
299 })*
300 };
301}
302
303macro_rules! define_named_walk {
304 ($Visitor:ident<$lt:lifetime>
305 $( pub fn $method:ident($ty:ty); )*
306 ) => {
307 $(pub fn $method<$lt, V: $Visitor<$lt>>(visitor: &mut V, node: &$lt $ty) -> V::Result {
308 walk_walkable!(visitor, node,)
309 })*
310 };
311}
312
313#[macro_export]
314macro_rules! common_visitor_and_walkers {
315 ($(($mut: ident))? $Visitor:ident$(<$lt:lifetime>)?) => {
316 $(${ignore($lt)}
317 #[derive(Copy, Clone)]
318 )?
319 #[derive(Debug)]
320 pub enum FnKind<'a> {
321 Fn(FnCtxt, &'a $($mut)? Visibility, &'a $($mut)? Fn),
323
324 Closure(&'a $($mut)? ClosureBinder, &'a $($mut)? Option<CoroutineKind>, &'a $($mut)? P<FnDecl>, &'a $($mut)? P<Expr>),
326 }
327
328 impl<'a> FnKind<'a> {
329 pub fn header(&'a $($mut)? self) -> Option<&'a $($mut)? FnHeader> {
330 match *self {
331 FnKind::Fn(_, _, Fn { sig, .. }) => Some(&$($mut)? sig.header),
332 FnKind::Closure(..) => None,
333 }
334 }
335
336 pub fn ident(&'a $($mut)? self) -> Option<&'a $($mut)? Ident> {
337 match self {
338 FnKind::Fn(_, _, Fn { ident, .. }) => Some(ident),
339 _ => None,
340 }
341 }
342
343 pub fn decl(&'a $($mut)? self) -> &'a $($mut)? FnDecl {
344 match self {
345 FnKind::Fn(_, _, Fn { sig, .. }) => &$($mut)? sig.decl,
346 FnKind::Closure(_, _, decl, _) => decl,
347 }
348 }
349
350 pub fn ctxt(&self) -> Option<FnCtxt> {
351 match self {
352 FnKind::Fn(ctxt, ..) => Some(*ctxt),
353 FnKind::Closure(..) => None,
354 }
355 }
356 }
357
358 impl_visitable_noop!(<$($lt)? $($mut)?>
360 AttrId,
361 bool,
362 rustc_span::ByteSymbol,
363 char,
364 crate::token::CommentKind,
365 crate::token::Delimiter,
366 crate::token::Lit,
367 crate::token::LitKind,
368 crate::tokenstream::LazyAttrTokenStream,
369 crate::tokenstream::TokenStream,
370 Movability,
371 Mutability,
372 Result<(), rustc_span::ErrorGuaranteed>,
373 rustc_data_structures::fx::FxHashMap<Symbol, usize>,
374 rustc_span::ErrorGuaranteed,
375 std::borrow::Cow<'_, str>,
376 Symbol,
377 u8,
378 usize,
379 );
380 $(impl_visitable_noop!(<$lt> Span,);)?
382
383 impl_visitable_list!(<$($lt)? $($mut)?>
387 ThinVec<AngleBracketedArg>,
388 ThinVec<Attribute>,
389 ThinVec<(Ident, Option<Ident>)>,
390 ThinVec<(NodeId, Path)>,
391 ThinVec<PathSegment>,
392 ThinVec<PreciseCapturingArg>,
393 ThinVec<P<Pat>>,
394 ThinVec<P<Ty>>,
395 ThinVec<P<TyPat>>,
396 );
397
398 impl_visitable_direct!(<$($lt)? $($mut)?>
402 AngleBracketedArg,
403 AngleBracketedArgs,
404 AsmMacro,
405 AssignOpKind,
406 AssocItemConstraintKind,
407 AttrArgs,
408 AttrItem,
409 AttrKind,
410 AttrStyle,
411 FnPtrTy,
412 BindingMode,
413 GenBlockKind,
414 RangeLimits,
415 UnsafeBinderCastKind,
416 BinOpKind,
417 BlockCheckMode,
418 BorrowKind,
419 BoundAsyncness,
420 BoundConstness,
421 BoundPolarity,
422 ByRef,
423 Closure,
424 Const,
425 ConstItem,
426 Defaultness,
427 Delegation,
428 DelegationMac,
429 DelimArgs,
430 DelimSpan,
431 EnumDef,
432 Extern,
433 ForLoopKind,
434 FormatArgPosition,
435 FormatArgsPiece,
436 FormatArgument,
437 FormatArgumentKind,
438 FormatArguments,
439 FormatPlaceholder,
440 GenericParamKind,
441 Impl,
442 ImplPolarity,
443 Inline,
444 InlineAsmOperand,
445 InlineAsmRegOrRegClass,
446 InlineAsmTemplatePiece,
447 IsAuto,
448 LocalKind,
449 MacCallStmt,
450 MacStmtStyle,
451 MatchKind,
452 MethodCall,
453 ModKind,
454 ModSpans,
455 MutTy,
456 NormalAttr,
457 Parens,
458 ParenthesizedArgs,
459 PatFieldsRest,
460 PatKind,
461 RangeEnd,
462 RangeSyntax,
463 Recovered,
464 Safety,
465 StaticItem,
466 StrLit,
467 StrStyle,
468 StructExpr,
469 StructRest,
470 Term,
471 Trait,
472 TraitBoundModifiers,
473 TraitObjectSyntax,
474 TyAlias,
475 TyAliasWhereClause,
476 TyAliasWhereClauses,
477 TyKind,
478 TyPatKind,
479 UnOp,
480 UnsafeBinderTy,
481 UnsafeSource,
482 UseTreeKind,
483 VisibilityKind,
484 WhereBoundPredicate,
485 WhereClause,
486 WhereEqPredicate,
487 WhereRegionPredicate,
488 YieldKind,
489 );
490
491 #[doc = concat!(" e.g., the `visit_item` method by default calls `visit"$(, "_", stringify!($mut))?, "::walk_item`.")]
495 pub trait $Visitor<$($lt)?> : Sized $(${ignore($mut)} + MutVisitorResult<Result = ()>)? {
505 $(
506 ${ignore($lt)}
507 type Result: VisitorResult = ();
510 )?
511
512 fn visit_ident(&mut self, Ident { name: _, span }: &$($lt)? $($mut)? Ident) -> Self::Result {
540 impl_visitable!(|&$($lt)? $($mut)? self: Ident, visitor: &mut V, _extra: ()| {
541 visitor.visit_ident(self)
542 });
543 visit_span(self, span)
544 }
545
546 impl_visitable_calling_walkable!(<$($lt)? $($mut)?>
550 fn visit_anon_const(AnonConst);
551 fn visit_arm(Arm);
552 fn visit_assoc_item_constraint(AssocItemConstraint);
554 fn visit_attribute(Attribute);
555 fn visit_block(Block);
556 fn visit_capture_by(CaptureBy);
558 fn visit_closure_binder(ClosureBinder);
559 fn visit_contract(FnContract);
560 fn visit_coroutine_kind(CoroutineKind);
561 fn visit_crate(Crate);
562 fn visit_expr(Expr);
563 fn visit_expr_field(ExprField);
564 fn visit_field_def(FieldDef);
565 fn visit_fn_decl(FnDecl);
566 fn visit_fn_header(FnHeader);
567 fn visit_fn_ret_ty(FnRetTy);
568 fn visit_foreign_mod(ForeignMod);
570 fn visit_format_args(FormatArgs);
571 fn visit_generic_arg(GenericArg);
572 fn visit_generic_args(GenericArgs);
573 fn visit_generic_param(GenericParam);
574 fn visit_generics(Generics);
575 fn visit_inline_asm(InlineAsm);
576 fn visit_inline_asm_sym(InlineAsmSym);
577 fn visit_label(Label);
579 fn visit_lifetime(Lifetime, _ctxt: LifetimeCtxt);
580 fn visit_local(Local);
581 fn visit_mac_call(MacCall);
582 fn visit_macro_def(MacroDef);
583 fn visit_param_bound(GenericBound, _ctxt: BoundKind);
584 fn visit_param(Param);
585 fn visit_pat_field(PatField);
586 fn visit_path(Path);
587 fn visit_path_segment(PathSegment);
588 fn visit_pat(Pat);
589 fn visit_poly_trait_ref(PolyTraitRef);
590 fn visit_precise_capturing_arg(PreciseCapturingArg);
591 fn visit_qself(QSelf);
592 fn visit_trait_ref(TraitRef);
593 fn visit_ty_pat(TyPat);
594 fn visit_ty(Ty);
595 fn visit_use_tree(UseTree);
596 fn visit_variant_data(VariantData);
597 fn visit_variant(Variant);
598 fn visit_vis(Visibility);
599 fn visit_where_predicate_kind(WherePredicateKind);
600 fn visit_where_predicate(WherePredicate);
601 );
602
603 fn visit_id(&mut self, _id: $(&$mut)? NodeId) -> Self::Result {
605 $(impl_visitable!(
606 |&$lt self: NodeId, visitor: &mut V, _extra: ()| {
607 visitor.visit_id(*self)
608 }
609 );)?
610 $(impl_visitable!(
611 |&$mut self: NodeId, visitor: &mut V, _extra: ()| {
612 visitor.visit_id(self)
613 }
614 );)?
615 Self::Result::output()
616 }
617
618 fn visit_method_receiver_expr(&mut self, ex: &$($lt)? $($mut)? Expr) -> Self::Result {
621 self.visit_expr(ex)
622 }
623
624 fn visit_item(&mut self, item: &$($lt)? $($mut)? Item) -> Self::Result {
625 impl_visitable!(|&$($lt)? $($mut)? self: Item, vis: &mut V, _extra: ()| {
626 vis.visit_item(self)
627 });
628 walk_item(self, item)
629 }
630
631 fn visit_foreign_item(&mut self, item: &$($lt)? $($mut)? ForeignItem) -> Self::Result {
632 impl_visitable!(|&$($lt)? $($mut)? self: ForeignItem, vis: &mut V, _extra: ()| {
633 vis.visit_foreign_item(self)
634 });
635 walk_item(self, item)
636 }
637
638 fn visit_assoc_item(&mut self, item: &$($lt)? $($mut)? AssocItem, ctxt: AssocCtxt) -> Self::Result {
639 impl_visitable!(|&$($lt)? $($mut)? self: AssocItem, vis: &mut V, ctxt: AssocCtxt| {
640 vis.visit_assoc_item(self, ctxt)
641 });
642 walk_assoc_item(self, item, ctxt)
643 }
644
645 fn visit_fn(
647 &mut self,
648 fk: FnKind<$($lt)? $(${ignore($mut)} '_)?>,
649 _: Span,
650 _: NodeId
651 ) -> Self::Result {
652 walk_fn(self, fk)
653 }
654
655 $(
657 fn visit_stmt(&mut self, s: &$lt Stmt) -> Self::Result {
658 walk_stmt(self, s)
659 }
660
661 fn visit_nested_use_tree(&mut self, use_tree: &$lt UseTree, id: NodeId) -> Self::Result {
662 try_visit!(self.visit_id(id));
663 self.visit_use_tree(use_tree)
664 }
665 )?
666
667 $(
669 #[inline]
672 fn visit_span(&mut self, _sp: &$mut Span) {
673 impl_visitable!(|&mut self: Span, visitor: &mut V, _extra: ()| {
674 visitor.visit_span(self)
675 });
676 }
678
679 fn flat_map_foreign_item(&mut self, ni: P<ForeignItem>) -> SmallVec<[P<ForeignItem>; 1]> {
680 walk_flat_map_foreign_item(self, ni)
681 }
682
683 fn flat_map_item(&mut self, i: P<Item>) -> SmallVec<[P<Item>; 1]> {
684 walk_flat_map_item(self, i)
685 }
686
687 fn flat_map_field_def(&mut self, fd: FieldDef) -> SmallVec<[FieldDef; 1]> {
688 walk_flat_map_field_def(self, fd)
689 }
690
691 fn flat_map_assoc_item(
692 &mut self,
693 i: P<AssocItem>,
694 ctxt: AssocCtxt,
695 ) -> SmallVec<[P<AssocItem>; 1]> {
696 walk_flat_map_assoc_item(self, i, ctxt)
697 }
698
699 fn flat_map_stmt(&mut self, s: Stmt) -> SmallVec<[Stmt; 1]> {
700 walk_flat_map_stmt(self, s)
701 }
702
703 fn flat_map_arm(&mut self, arm: Arm) -> SmallVec<[Arm; 1]> {
704 walk_flat_map_arm(self, arm)
705 }
706
707 fn filter_map_expr(&mut self, e: P<Expr>) -> Option<P<Expr>> {
708 walk_filter_map_expr(self, e)
709 }
710
711 fn flat_map_variant(&mut self, v: Variant) -> SmallVec<[Variant; 1]> {
712 walk_flat_map_variant(self, v)
713 }
714
715 fn flat_map_param(&mut self, param: Param) -> SmallVec<[Param; 1]> {
716 walk_flat_map_param(self, param)
717 }
718
719 fn flat_map_generic_param(&mut self, param: GenericParam) -> SmallVec<[GenericParam; 1]> {
720 walk_flat_map_generic_param(self, param)
721 }
722
723 fn flat_map_expr_field(&mut self, f: ExprField) -> SmallVec<[ExprField; 1]> {
724 walk_flat_map_expr_field(self, f)
725 }
726
727 fn flat_map_where_predicate(
728 &mut self,
729 where_predicate: WherePredicate,
730 ) -> SmallVec<[WherePredicate; 1]> {
731 walk_flat_map_where_predicate(self, where_predicate)
732 }
733
734 fn flat_map_pat_field(&mut self, fp: PatField) -> SmallVec<[PatField; 1]> {
735 walk_flat_map_pat_field(self, fp)
736 }
737 )?
738 }
739
740 pub trait WalkItemKind {
741 type Ctxt;
742 fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(
743 &$($lt)? $($mut)? self,
744 span: Span,
745 id: NodeId,
746 visibility: &$($lt)? $($mut)? Visibility,
747 ctxt: Self::Ctxt,
748 vis: &mut V,
749 ) -> V::Result;
750 }
751
752 $(${ignore($lt)}
754 #[expect(unused, rustc::pass_by_value)]
755 #[inline]
756 )?
757 fn visit_span<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, span: &$($lt)? $($mut)? Span) -> V::Result {
758 $(${ignore($mut)} vis.visit_span(span))?;
759 V::Result::output()
760 }
761
762 $(impl_visitable!(|&$lt self: ThinVec<(UseTree, NodeId)>, vis: &mut V, _extra: ()| {
763 for (nested_tree, nested_id) in self {
764 try_visit!(vis.visit_nested_use_tree(nested_tree, *nested_id));
765 }
766 V::Result::output()
767 });)?
768 $(impl_visitable_list!(<$mut> ThinVec<(UseTree, NodeId)>,);)?
769
770 fn walk_item_inner<$($lt,)? K: WalkItemKind, V: $Visitor$(<$lt>)?>(
771 visitor: &mut V,
772 item: &$($mut)? $($lt)? Item<K>,
773 ctxt: K::Ctxt,
774 ) -> V::Result {
775 let Item { attrs, id, kind, vis, span, tokens: _ } = item;
776 visit_visitable!($($mut)? visitor, id, attrs, vis);
777 try_visit!(kind.walk(*span, *id, vis, ctxt, visitor));
778 visit_visitable!($($mut)? visitor, span);
779 V::Result::output()
780 }
781
782 pub fn walk_item<$($lt,)? K: WalkItemKind<Ctxt = ()>, V: $Visitor$(<$lt>)?>(
784 visitor: &mut V,
785 item: &$($mut)? $($lt)? Item<K>,
786 ) -> V::Result {
787 walk_item_inner(visitor, item, ())
788 }
789
790 pub fn walk_assoc_item<$($lt,)? K: WalkItemKind<Ctxt = AssocCtxt>, V: $Visitor$(<$lt>)?>(
792 visitor: &mut V,
793 item: &$($mut)? $($lt)? Item<K>,
794 ctxt: AssocCtxt,
795 ) -> V::Result {
796 walk_item_inner(visitor, item, ctxt)
797 }
798
799 impl WalkItemKind for ItemKind {
800 type Ctxt = ();
801 fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(
802 &$($lt)? $($mut)? self,
803 span: Span,
804 id: NodeId,
805 visibility: &$($lt)? $($mut)? Visibility,
806 _ctxt: Self::Ctxt,
807 vis: &mut V,
808 ) -> V::Result {
809 match self {
810 ItemKind::Fn(func) => {
811 let kind = FnKind::Fn(FnCtxt::Free, visibility, &$($mut)? *func);
812 try_visit!(vis.visit_fn(kind, span, id));
813 }
814 ItemKind::ExternCrate(orig_name, ident) =>
815 visit_visitable!($($mut)? vis, orig_name, ident),
816 ItemKind::Use(use_tree) =>
817 visit_visitable!($($mut)? vis, use_tree),
818 ItemKind::Static(item) =>
819 visit_visitable!($($mut)? vis, item),
820 ItemKind::Const(item) =>
821 visit_visitable!($($mut)? vis, item),
822 ItemKind::Mod(safety, ident, mod_kind) =>
823 visit_visitable!($($mut)? vis, safety, ident, mod_kind),
824 ItemKind::ForeignMod(nm) =>
825 visit_visitable!($($mut)? vis, nm),
826 ItemKind::GlobalAsm(asm) =>
827 visit_visitable!($($mut)? vis, asm),
828 ItemKind::TyAlias(ty_alias) =>
829 visit_visitable!($($mut)? vis, ty_alias),
830 ItemKind::Enum(ident, generics, enum_definition) =>
831 visit_visitable!($($mut)? vis, ident, generics, enum_definition),
832 ItemKind::Struct(ident, generics, variant_data)
833 | ItemKind::Union(ident, generics, variant_data) =>
834 visit_visitable!($($mut)? vis, ident, generics, variant_data),
835 ItemKind::Impl(impl_) =>
836 visit_visitable!($($mut)? vis, impl_),
837 ItemKind::Trait(trait_) =>
838 visit_visitable!($($mut)? vis, trait_),
839 ItemKind::TraitAlias(ident, generics, bounds) => {
840 visit_visitable!($($mut)? vis, ident, generics);
841 visit_visitable_with!($($mut)? vis, bounds, BoundKind::Bound)
842 }
843 ItemKind::MacCall(m) =>
844 visit_visitable!($($mut)? vis, m),
845 ItemKind::MacroDef(ident, def) =>
846 visit_visitable!($($mut)? vis, ident, def),
847 ItemKind::Delegation(delegation) =>
848 visit_visitable!($($mut)? vis, delegation),
849 ItemKind::DelegationMac(dm) =>
850 visit_visitable!($($mut)? vis, dm),
851 }
852 V::Result::output()
853 }
854 }
855
856 impl WalkItemKind for AssocItemKind {
857 type Ctxt = AssocCtxt;
858 fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(
859 &$($lt)? $($mut)? self,
860 span: Span,
861 id: NodeId,
862 visibility: &$($lt)? $($mut)? Visibility,
863 ctxt: Self::Ctxt,
864 vis: &mut V,
865 ) -> V::Result {
866 match self {
867 AssocItemKind::Const(item) =>
868 visit_visitable!($($mut)? vis, item),
869 AssocItemKind::Fn(func) => {
870 let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), visibility, &$($mut)? *func);
871 try_visit!(vis.visit_fn(kind, span, id))
872 }
873 AssocItemKind::Type(alias) =>
874 visit_visitable!($($mut)? vis, alias),
875 AssocItemKind::MacCall(mac) =>
876 visit_visitable!($($mut)? vis, mac),
877 AssocItemKind::Delegation(delegation) =>
878 visit_visitable!($($mut)? vis, delegation),
879 AssocItemKind::DelegationMac(dm) =>
880 visit_visitable!($($mut)? vis, dm),
881 }
882 V::Result::output()
883 }
884 }
885
886 impl WalkItemKind for ForeignItemKind {
887 type Ctxt = ();
888 fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(
889 &$($lt)? $($mut)? self,
890 span: Span,
891 id: NodeId,
892 visibility: &$($lt)? $($mut)? Visibility,
893 _ctxt: Self::Ctxt,
894 vis: &mut V,
895 ) -> V::Result {
896 match self {
897 ForeignItemKind::Static(item) =>
898 visit_visitable!($($mut)? vis, item),
899 ForeignItemKind::Fn(func) => {
900 let kind = FnKind::Fn(FnCtxt::Foreign, visibility, &$($mut)?*func);
901 try_visit!(vis.visit_fn(kind, span, id))
902 }
903 ForeignItemKind::TyAlias(alias) =>
904 visit_visitable!($($mut)? vis, alias),
905 ForeignItemKind::MacCall(mac) =>
906 visit_visitable!($($mut)? vis, mac),
907 }
908 V::Result::output()
909 }
910 }
911
912 pub fn walk_fn<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, kind: FnKind<$($lt)? $(${ignore($mut)} '_)?>) -> V::Result {
913 match kind {
914 FnKind::Fn(
915 _ctxt,
916 _vis,
918 Fn { defaultness, ident, sig, generics, contract, body, define_opaque },
919 ) => {
920 let FnSig { header, decl, span } = sig;
921 visit_visitable!($($mut)? vis,
922 defaultness, ident, header, generics, decl,
923 contract, body, span, define_opaque
924 )
925 }
926 FnKind::Closure(binder, coroutine_kind, decl, body) =>
927 visit_visitable!($($mut)? vis, binder, coroutine_kind, decl, body),
928 }
929 V::Result::output()
930 }
931
932 impl_walkable!(|&$($mut)? $($lt)? self: Impl, vis: &mut V| {
933 let Impl { defaultness, safety, generics, constness, polarity, of_trait, self_ty, items } = self;
934 visit_visitable!($($mut)? vis, defaultness, safety, generics, constness, polarity, of_trait, self_ty);
935 visit_visitable_with!($($mut)? vis, items, AssocCtxt::Impl { of_trait: of_trait.is_some() });
936 V::Result::output()
937 });
938
939 impl_walkable!(|&$($mut)? $($lt)? self: MethodCall, vis: &mut V| {
941 let MethodCall { seg, receiver, args, span } = self;
942 try_visit!(vis.visit_method_receiver_expr(receiver));
943 visit_visitable!($($mut)? vis, seg, args, span);
944 V::Result::output()
945 });
946
947 impl_walkable!(|&$($mut)? $($lt)? self: Expr, vis: &mut V| {
948 let Expr { id, kind, span, attrs, tokens: _ } = self;
949 visit_visitable!($($mut)? vis, id, attrs);
950 match kind {
951 ExprKind::Array(exprs) =>
952 visit_visitable!($($mut)? vis, exprs),
953 ExprKind::ConstBlock(anon_const) =>
954 visit_visitable!($($mut)? vis, anon_const),
955 ExprKind::Repeat(element, count) =>
956 visit_visitable!($($mut)? vis, element, count),
957 ExprKind::Struct(se) =>
958 visit_visitable!($($mut)? vis, se),
959 ExprKind::Tup(exprs) =>
960 visit_visitable!($($mut)? vis, exprs),
961 ExprKind::Call(callee_expression, arguments) =>
962 visit_visitable!($($mut)? vis, callee_expression, arguments),
963 ExprKind::MethodCall(mc) =>
964 visit_visitable!($($mut)? vis, mc),
965 ExprKind::Binary(op, lhs, rhs) =>
966 visit_visitable!($($mut)? vis, op, lhs, rhs),
967 ExprKind::AddrOf(kind, mutbl, subexpression) =>
968 visit_visitable!($($mut)? vis, kind, mutbl, subexpression),
969 ExprKind::Unary(op, subexpression) =>
970 visit_visitable!($($mut)? vis, op, subexpression),
971 ExprKind::Cast(subexpression, typ) | ExprKind::Type(subexpression, typ) =>
972 visit_visitable!($($mut)? vis, subexpression, typ),
973 ExprKind::Let(pat, expr, span, _recovered) =>
974 visit_visitable!($($mut)? vis, pat, expr, span),
975 ExprKind::If(head_expression, if_block, optional_else) =>
976 visit_visitable!($($mut)? vis, head_expression, if_block, optional_else),
977 ExprKind::While(subexpression, block, opt_label) =>
978 visit_visitable!($($mut)? vis, subexpression, block, opt_label),
979 ExprKind::ForLoop { pat, iter, body, label, kind } =>
980 visit_visitable!($($mut)? vis, pat, iter, body, label, kind),
981 ExprKind::Loop(block, opt_label, span) =>
982 visit_visitable!($($mut)? vis, block, opt_label, span),
983 ExprKind::Match(subexpression, arms, kind) =>
984 visit_visitable!($($mut)? vis, subexpression, arms, kind),
985 ExprKind::Closure(box Closure {
986 binder,
987 capture_clause,
988 coroutine_kind,
989 constness,
990 movability,
991 fn_decl,
992 body,
993 fn_decl_span,
994 fn_arg_span,
995 }) => {
996 visit_visitable!($($mut)? vis, constness, movability, capture_clause);
997 let kind = FnKind::Closure(binder, coroutine_kind, fn_decl, body);
998 try_visit!(vis.visit_fn(kind, *span, *id));
999 visit_visitable!($($mut)? vis, fn_decl_span, fn_arg_span);
1000 }
1001 ExprKind::Block(block, opt_label) =>
1002 visit_visitable!($($mut)? vis, block, opt_label),
1003 ExprKind::Gen(capt, body, kind, decl_span) =>
1004 visit_visitable!($($mut)? vis, capt, body, kind, decl_span),
1005 ExprKind::Await(expr, span) | ExprKind::Use(expr, span) =>
1006 visit_visitable!($($mut)? vis, expr, span),
1007 ExprKind::Assign(lhs, rhs, span) =>
1008 visit_visitable!($($mut)? vis, lhs, rhs, span),
1009 ExprKind::AssignOp(op, lhs, rhs) =>
1010 visit_visitable!($($mut)? vis, op, lhs, rhs),
1011 ExprKind::Field(subexpression, ident) =>
1012 visit_visitable!($($mut)? vis, subexpression, ident),
1013 ExprKind::Index(main_expression, index_expression, span) =>
1014 visit_visitable!($($mut)? vis, main_expression, index_expression, span),
1015 ExprKind::Range(start, end, limit) =>
1016 visit_visitable!($($mut)? vis, start, end, limit),
1017 ExprKind::Underscore => {}
1018 ExprKind::Path(maybe_qself, path) =>
1019 visit_visitable!($($mut)? vis, maybe_qself, path),
1020 ExprKind::Break(opt_label, opt_expr) =>
1021 visit_visitable!($($mut)? vis, opt_label, opt_expr),
1022 ExprKind::Continue(opt_label) =>
1023 visit_visitable!($($mut)? vis, opt_label),
1024 ExprKind::Ret(optional_expression) | ExprKind::Yeet(optional_expression) =>
1025 visit_visitable!($($mut)? vis, optional_expression),
1026 ExprKind::Become(expr) =>
1027 visit_visitable!($($mut)? vis, expr),
1028 ExprKind::MacCall(mac) =>
1029 visit_visitable!($($mut)? vis, mac),
1030 ExprKind::Paren(subexpression) =>
1031 visit_visitable!($($mut)? vis, subexpression),
1032 ExprKind::InlineAsm(asm) =>
1033 visit_visitable!($($mut)? vis, asm),
1034 ExprKind::FormatArgs(f) =>
1035 visit_visitable!($($mut)? vis, f),
1036 ExprKind::OffsetOf(container, fields) =>
1037 visit_visitable!($($mut)? vis, container, fields),
1038 ExprKind::Yield(kind) =>
1039 visit_visitable!($($mut)? vis, kind),
1040 ExprKind::Try(subexpression) =>
1041 visit_visitable!($($mut)? vis, subexpression),
1042 ExprKind::TryBlock(body) =>
1043 visit_visitable!($($mut)? vis, body),
1044 ExprKind::Lit(token) =>
1045 visit_visitable!($($mut)? vis, token),
1046 ExprKind::IncludedBytes(bytes) =>
1047 visit_visitable!($($mut)? vis, bytes),
1048 ExprKind::UnsafeBinderCast(kind, expr, ty) =>
1049 visit_visitable!($($mut)? vis, kind, expr, ty),
1050 ExprKind::Err(_guar) => {}
1051 ExprKind::Dummy => {}
1052 }
1053
1054 visit_span(vis, span)
1055 });
1056
1057 define_named_walk!($(($mut))? $Visitor$(<$lt>)?
1058 pub fn walk_anon_const(AnonConst);
1059 pub fn walk_arm(Arm);
1060 pub fn walk_assoc_item_constraint(AssocItemConstraint);
1062 pub fn walk_attribute(Attribute);
1063 pub fn walk_block(Block);
1064 pub fn walk_capture_by(CaptureBy);
1066 pub fn walk_closure_binder(ClosureBinder);
1067 pub fn walk_contract(FnContract);
1068 pub fn walk_coroutine_kind(CoroutineKind);
1069 pub fn walk_crate(Crate);
1070 pub fn walk_expr(Expr);
1071 pub fn walk_expr_field(ExprField);
1072 pub fn walk_field_def(FieldDef);
1073 pub fn walk_fn_decl(FnDecl);
1074 pub fn walk_fn_header(FnHeader);
1075 pub fn walk_fn_ret_ty(FnRetTy);
1076 pub fn walk_foreign_mod(ForeignMod);
1078 pub fn walk_format_args(FormatArgs);
1079 pub fn walk_generic_arg(GenericArg);
1080 pub fn walk_generic_args(GenericArgs);
1081 pub fn walk_generic_param(GenericParam);
1082 pub fn walk_generics(Generics);
1083 pub fn walk_inline_asm(InlineAsm);
1084 pub fn walk_inline_asm_sym(InlineAsmSym);
1085 pub fn walk_label(Label);
1087 pub fn walk_lifetime(Lifetime);
1088 pub fn walk_local(Local);
1089 pub fn walk_mac(MacCall);
1090 pub fn walk_macro_def(MacroDef);
1091 pub fn walk_param_bound(GenericBound);
1092 pub fn walk_param(Param);
1093 pub fn walk_pat_field(PatField);
1094 pub fn walk_path(Path);
1095 pub fn walk_path_segment(PathSegment);
1096 pub fn walk_pat(Pat);
1097 pub fn walk_poly_trait_ref(PolyTraitRef);
1098 pub fn walk_precise_capturing_arg(PreciseCapturingArg);
1099 pub fn walk_qself(QSelf);
1100 pub fn walk_trait_ref(TraitRef);
1101 pub fn walk_ty_pat(TyPat);
1102 pub fn walk_ty(Ty);
1103 pub fn walk_use_tree(UseTree);
1104 pub fn walk_variant_data(VariantData);
1105 pub fn walk_variant(Variant);
1106 pub fn walk_vis(Visibility);
1107 pub fn walk_where_predicate_kind(WherePredicateKind);
1108 pub fn walk_where_predicate(WherePredicate);
1109 );
1110 };
1111}
1112
1113common_visitor_and_walkers!(Visitor<'a>);
1114
1115macro_rules! generate_list_visit_fns {
1116 ($($name:ident, $Ty:ty, $visit_fn:ident$(, $param:ident: $ParamTy:ty)*;)+) => {
1117 $(
1118 #[allow(unused_parens)]
1119 impl<'a, V: Visitor<'a>> Visitable<'a, V> for ThinVec<$Ty> {
1120 type Extra = ($($ParamTy),*);
1121
1122 #[inline]
1123 fn visit(
1124 &'a self,
1125 visitor: &mut V,
1126 ($($param),*): Self::Extra,
1127 ) -> V::Result {
1128 $name(visitor, self $(, $param)*)
1129 }
1130 }
1131
1132 fn $name<'a, V: Visitor<'a>>(
1133 vis: &mut V,
1134 values: &'a ThinVec<$Ty>,
1135 $(
1136 $param: $ParamTy,
1137 )*
1138 ) -> V::Result {
1139 walk_list!(vis, $visit_fn, values$(,$param)*);
1140 V::Result::output()
1141 }
1142 )+
1143 }
1144}
1145
1146generate_list_visit_fns! {
1147 visit_items, P<Item>, visit_item;
1148 visit_foreign_items, P<ForeignItem>, visit_foreign_item;
1149 visit_generic_params, GenericParam, visit_generic_param;
1150 visit_stmts, Stmt, visit_stmt;
1151 visit_exprs, P<Expr>, visit_expr;
1152 visit_expr_fields, ExprField, visit_expr_field;
1153 visit_pat_fields, PatField, visit_pat_field;
1154 visit_variants, Variant, visit_variant;
1155 visit_assoc_items, P<AssocItem>, visit_assoc_item, ctxt: AssocCtxt;
1156 visit_where_predicates, WherePredicate, visit_where_predicate;
1157 visit_params, Param, visit_param;
1158 visit_field_defs, FieldDef, visit_field_def;
1159 visit_arms, Arm, visit_arm;
1160}
1161
1162pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) -> V::Result {
1163 let Stmt { id, kind, span: _ } = statement;
1164 try_visit!(visitor.visit_id(*id));
1165 match kind {
1166 StmtKind::Let(local) => try_visit!(visitor.visit_local(local)),
1167 StmtKind::Item(item) => try_visit!(visitor.visit_item(item)),
1168 StmtKind::Expr(expr) | StmtKind::Semi(expr) => try_visit!(visitor.visit_expr(expr)),
1169 StmtKind::Empty => {}
1170 StmtKind::MacCall(mac) => {
1171 let MacCallStmt { mac, attrs, style: _, tokens: _ } = &**mac;
1172 walk_list!(visitor, visit_attribute, attrs);
1173 try_visit!(visitor.visit_mac_call(mac));
1174 }
1175 }
1176 V::Result::output()
1177}