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