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 EarlyParsedAttribute,
370 Movability,
371 Mutability,
372 Pinnedness,
373 Result<(), rustc_span::ErrorGuaranteed>,
374 rustc_data_structures::fx::FxHashMap<Symbol, usize>,
375 rustc_span::ErrorGuaranteed,
376 std::borrow::Cow<'_, str>,
377 Symbol,
378 u8,
379 usize,
380 );
381 $(impl_visitable_noop!(<$lt> Span,);)?
383
384 impl_visitable_list!(<$($lt)? $($mut)?>
388 ThinVec<AngleBracketedArg>,
389 ThinVec<Attribute>,
390 ThinVec<(Ident, Option<Ident>)>,
391 ThinVec<(NodeId, Path)>,
392 ThinVec<PathSegment>,
393 ThinVec<PreciseCapturingArg>,
394 ThinVec<Pat>,
395 ThinVec<Box<Ty>>,
396 ThinVec<TyPat>,
397 ThinVec<EiiImpl>,
398 );
399
400 impl_visitable_direct!(<$($lt)? $($mut)?>
404 AngleBracketedArg,
405 AngleBracketedArgs,
406 AsmMacro,
407 AssignOpKind,
408 AssocItemConstraintKind,
409 AttrArgs,
410 AttrItem,
411 AttrKind,
412 AttrStyle,
413 FnPtrTy,
414 BindingMode,
415 GenBlockKind,
416 RangeLimits,
417 UnsafeBinderCastKind,
418 BinOpKind,
419 BlockCheckMode,
420 MgcaDisambiguation,
421 BorrowKind,
422 BoundAsyncness,
423 BoundConstness,
424 BoundPolarity,
425 ByRef,
426 Closure,
427 Const,
428 ConstItem,
429 ConstItemRhs,
430 Defaultness,
431 Delegation,
432 DelegationMac,
433 DelimArgs,
434 DelimSpan,
435 EnumDef,
436 Extern,
437 ForLoopKind,
438 FormatArgPosition,
439 FormatArgsPiece,
440 FormatArgument,
441 FormatArgumentKind,
442 FormatArguments,
443 FormatPlaceholder,
444 GenericParamKind,
445 Impl,
446 ImplPolarity,
447 Inline,
448 InlineAsmOperand,
449 InlineAsmRegOrRegClass,
450 InlineAsmTemplatePiece,
451 IsAuto,
452 LocalKind,
453 MacCallStmt,
454 MacStmtStyle,
455 MatchKind,
456 MethodCall,
457 ModKind,
458 ModSpans,
459 MutTy,
460 NormalAttr,
461 AttrItemKind,
462 Parens,
463 ParenthesizedArgs,
464 PatFieldsRest,
465 PatKind,
466 RangeEnd,
467 RangeSyntax,
468 Recovered,
469 Safety,
470 StaticItem,
471 StrLit,
472 StrStyle,
473 StructExpr,
474 StructRest,
475 Term,
476 Trait,
477 TraitBoundModifiers,
478 TraitObjectSyntax,
479 TyAlias,
480 TyKind,
481 TyPatKind,
482 UnOp,
483 UnsafeBinderTy,
484 UnsafeSource,
485 UseTreeKind,
486 VisibilityKind,
487 WhereBoundPredicate,
488 WhereClause,
489 WhereEqPredicate,
490 WhereRegionPredicate,
491 YieldKind,
492 EiiDecl,
493 EiiImpl,
494 );
495
496 #[doc = concat!(" e.g., the `visit_item` method by default calls `visit"$(, "_", stringify!($mut))?, "::walk_item`.")]
500 pub trait $Visitor<$($lt)?> : Sized $(${ignore($mut)} + MutVisitorResult<Result = ()>)? {
510 $(
511 ${ignore($lt)}
512 type Result: VisitorResult = ();
515 )?
516
517 fn visit_ident(&mut self, Ident { name: _, span }: &$($lt)? $($mut)? Ident) -> Self::Result {
545 impl_visitable!(|&$($lt)? $($mut)? self: Ident, visitor: &mut V, _extra: ()| {
546 visitor.visit_ident(self)
547 });
548 visit_span(self, span)
549 }
550
551 impl_visitable_calling_walkable!(<$($lt)? $($mut)?>
555 fn visit_anon_const(AnonConst);
556 fn visit_arm(Arm);
557 fn visit_assoc_item_constraint(AssocItemConstraint);
559 fn visit_attribute(Attribute);
560 fn visit_block(Block);
561 fn visit_capture_by(CaptureBy);
563 fn visit_closure_binder(ClosureBinder);
564 fn visit_contract(FnContract);
565 fn visit_coroutine_kind(CoroutineKind);
566 fn visit_crate(Crate);
567 fn visit_expr(Expr);
568 fn visit_expr_field(ExprField);
569 fn visit_field_def(FieldDef);
570 fn visit_fn_decl(FnDecl);
571 fn visit_fn_header(FnHeader);
572 fn visit_fn_ret_ty(FnRetTy);
573 fn visit_foreign_mod(ForeignMod);
575 fn visit_format_args(FormatArgs);
576 fn visit_generic_arg(GenericArg);
577 fn visit_generic_args(GenericArgs);
578 fn visit_generic_param(GenericParam);
579 fn visit_generics(Generics);
580 fn visit_inline_asm(InlineAsm);
581 fn visit_inline_asm_sym(InlineAsmSym);
582 fn visit_label(Label);
584 fn visit_lifetime(Lifetime, _ctxt: LifetimeCtxt);
585 fn visit_local(Local);
586 fn visit_mac_call(MacCall);
587 fn visit_macro_def(MacroDef);
588 fn visit_param_bound(GenericBound, _ctxt: BoundKind);
589 fn visit_param(Param);
590 fn visit_pat_field(PatField);
591 fn visit_path(Path);
592 fn visit_path_segment(PathSegment);
593 fn visit_pat(Pat);
594 fn visit_poly_trait_ref(PolyTraitRef);
595 fn visit_precise_capturing_arg(PreciseCapturingArg);
596 fn visit_qself(QSelf);
597 fn visit_trait_ref(TraitRef);
598 fn visit_ty_pat(TyPat);
599 fn visit_ty(Ty);
600 fn visit_use_tree(UseTree);
601 fn visit_variant_data(VariantData);
602 fn visit_variant(Variant);
603 fn visit_vis(Visibility);
604 fn visit_where_predicate_kind(WherePredicateKind);
605 fn visit_where_predicate(WherePredicate);
606 );
607
608 fn visit_id(&mut self, _id: $(&$mut)? NodeId) -> Self::Result {
610 $(impl_visitable!(
611 |&$lt self: NodeId, visitor: &mut V, _extra: ()| {
612 visitor.visit_id(*self)
613 }
614 );)?
615 $(impl_visitable!(
616 |&$mut self: NodeId, visitor: &mut V, _extra: ()| {
617 visitor.visit_id(self)
618 }
619 );)?
620 Self::Result::output()
621 }
622
623 fn visit_method_receiver_expr(&mut self, ex: &$($lt)? $($mut)? Expr) -> Self::Result {
626 self.visit_expr(ex)
627 }
628
629 fn visit_item(&mut self, item: &$($lt)? $($mut)? Item) -> Self::Result {
630 impl_visitable!(|&$($lt)? $($mut)? self: Item, vis: &mut V, _extra: ()| {
631 vis.visit_item(self)
632 });
633 walk_item(self, item)
634 }
635
636 fn visit_foreign_item(&mut self, item: &$($lt)? $($mut)? ForeignItem) -> Self::Result {
637 impl_visitable!(|&$($lt)? $($mut)? self: ForeignItem, vis: &mut V, _extra: ()| {
638 vis.visit_foreign_item(self)
639 });
640 walk_item(self, item)
641 }
642
643 fn visit_assoc_item(&mut self, item: &$($lt)? $($mut)? AssocItem, ctxt: AssocCtxt) -> Self::Result {
644 impl_visitable!(|&$($lt)? $($mut)? self: AssocItem, vis: &mut V, ctxt: AssocCtxt| {
645 vis.visit_assoc_item(self, ctxt)
646 });
647 walk_assoc_item(self, item, ctxt)
648 }
649
650 fn visit_fn(
652 &mut self,
653 fk: FnKind<$($lt)? $(${ignore($mut)} '_)?>,
654 _: &AttrVec,
655 _: Span,
656 _: NodeId,
657 ) -> Self::Result {
658 walk_fn(self, fk)
659 }
660
661 $(
663 fn visit_stmt(&mut self, s: &$lt Stmt) -> Self::Result {
664 walk_stmt(self, s)
665 }
666
667 fn visit_nested_use_tree(&mut self, use_tree: &$lt UseTree, id: NodeId) -> Self::Result {
668 try_visit!(self.visit_id(id));
669 self.visit_use_tree(use_tree)
670 }
671 )?
672
673 $(
675 #[inline]
678 fn visit_span(&mut self, _sp: &$mut Span) {
679 impl_visitable!(|&mut self: Span, visitor: &mut V, _extra: ()| {
680 visitor.visit_span(self)
681 });
682 }
684
685 fn flat_map_foreign_item(&mut self, ni: Box<ForeignItem>) -> SmallVec<[Box<ForeignItem>; 1]> {
686 walk_flat_map_foreign_item(self, ni)
687 }
688
689 fn flat_map_item(&mut self, i: Box<Item>) -> SmallVec<[Box<Item>; 1]> {
690 walk_flat_map_item(self, i)
691 }
692
693 fn flat_map_field_def(&mut self, fd: FieldDef) -> SmallVec<[FieldDef; 1]> {
694 walk_flat_map_field_def(self, fd)
695 }
696
697 fn flat_map_assoc_item(
698 &mut self,
699 i: Box<AssocItem>,
700 ctxt: AssocCtxt,
701 ) -> SmallVec<[Box<AssocItem>; 1]> {
702 walk_flat_map_assoc_item(self, i, ctxt)
703 }
704
705 fn flat_map_stmt(&mut self, s: Stmt) -> SmallVec<[Stmt; 1]> {
706 walk_flat_map_stmt(self, s)
707 }
708
709 fn flat_map_arm(&mut self, arm: Arm) -> SmallVec<[Arm; 1]> {
710 walk_flat_map_arm(self, arm)
711 }
712
713 fn filter_map_expr(&mut self, e: Box<Expr>) -> Option<Box<Expr>> {
714 walk_filter_map_expr(self, e)
715 }
716
717 fn flat_map_variant(&mut self, v: Variant) -> SmallVec<[Variant; 1]> {
718 walk_flat_map_variant(self, v)
719 }
720
721 fn flat_map_param(&mut self, param: Param) -> SmallVec<[Param; 1]> {
722 walk_flat_map_param(self, param)
723 }
724
725 fn flat_map_generic_param(&mut self, param: GenericParam) -> SmallVec<[GenericParam; 1]> {
726 walk_flat_map_generic_param(self, param)
727 }
728
729 fn flat_map_expr_field(&mut self, f: ExprField) -> SmallVec<[ExprField; 1]> {
730 walk_flat_map_expr_field(self, f)
731 }
732
733 fn flat_map_where_predicate(
734 &mut self,
735 where_predicate: WherePredicate,
736 ) -> SmallVec<[WherePredicate; 1]> {
737 walk_flat_map_where_predicate(self, where_predicate)
738 }
739
740 fn flat_map_pat_field(&mut self, fp: PatField) -> SmallVec<[PatField; 1]> {
741 walk_flat_map_pat_field(self, fp)
742 }
743 )?
744 }
745
746 pub trait WalkItemKind {
747 type Ctxt;
748 fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(
749 &$($lt)? $($mut)? self,
750 attrs: &AttrVec,
751 span: Span,
752 id: NodeId,
753 visibility: &$($lt)? $($mut)? Visibility,
754 ctxt: Self::Ctxt,
755 vis: &mut V,
756 ) -> V::Result;
757 }
758
759 $(${ignore($lt)}
761 #[expect(unused, rustc::pass_by_value)]
762 #[inline]
763 )?
764 fn visit_span<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, span: &$($lt)? $($mut)? Span) -> V::Result {
765 $(${ignore($mut)} vis.visit_span(span))?;
766 V::Result::output()
767 }
768
769 $(impl_visitable!(|&$lt self: ThinVec<(UseTree, NodeId)>, vis: &mut V, _extra: ()| {
770 for (nested_tree, nested_id) in self {
771 try_visit!(vis.visit_nested_use_tree(nested_tree, *nested_id));
772 }
773 V::Result::output()
774 });)?
775 $(impl_visitable_list!(<$mut> ThinVec<(UseTree, NodeId)>,);)?
776
777 fn walk_item_inner<$($lt,)? K: WalkItemKind, V: $Visitor$(<$lt>)?>(
778 visitor: &mut V,
779 item: &$($mut)? $($lt)? Item<K>,
780 ctxt: K::Ctxt,
781 ) -> V::Result {
782 let Item { attrs, id, kind, vis, span, tokens: _ } = item;
783 visit_visitable!($($mut)? visitor, id, attrs, vis);
784 try_visit!(kind.walk(attrs, *span, *id, vis, ctxt, visitor));
785 visit_visitable!($($mut)? visitor, span);
786 V::Result::output()
787 }
788
789 pub fn walk_item<$($lt,)? K: WalkItemKind<Ctxt = ()>, V: $Visitor$(<$lt>)?>(
791 visitor: &mut V,
792 item: &$($mut)? $($lt)? Item<K>,
793 ) -> V::Result {
794 walk_item_inner(visitor, item, ())
795 }
796
797 pub fn walk_assoc_item<$($lt,)? K: WalkItemKind<Ctxt = AssocCtxt>, V: $Visitor$(<$lt>)?>(
799 visitor: &mut V,
800 item: &$($mut)? $($lt)? Item<K>,
801 ctxt: AssocCtxt,
802 ) -> V::Result {
803 walk_item_inner(visitor, item, ctxt)
804 }
805
806 impl WalkItemKind for ItemKind {
807 type Ctxt = ();
808 fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(
809 &$($lt)? $($mut)? self,
810 attrs: &AttrVec,
811 span: Span,
812 id: NodeId,
813 visibility: &$($lt)? $($mut)? Visibility,
814 _ctxt: Self::Ctxt,
815 vis: &mut V,
816 ) -> V::Result {
817 match self {
818 ItemKind::Fn(func) => {
819 let kind = FnKind::Fn(FnCtxt::Free, visibility, &$($mut)? *func);
820 try_visit!(vis.visit_fn(kind, attrs, span, id));
821 }
822 ItemKind::ExternCrate(orig_name, ident) =>
823 visit_visitable!($($mut)? vis, orig_name, ident),
824 ItemKind::Use(use_tree) =>
825 visit_visitable!($($mut)? vis, use_tree),
826 ItemKind::Static(item) =>
827 visit_visitable!($($mut)? vis, item),
828 ItemKind::Const(item) =>
829 visit_visitable!($($mut)? vis, item),
830 ItemKind::Mod(safety, ident, mod_kind) =>
831 visit_visitable!($($mut)? vis, safety, ident, mod_kind),
832 ItemKind::ForeignMod(nm) =>
833 visit_visitable!($($mut)? vis, nm),
834 ItemKind::GlobalAsm(asm) =>
835 visit_visitable!($($mut)? vis, asm),
836 ItemKind::TyAlias(ty_alias) =>
837 visit_visitable!($($mut)? vis, ty_alias),
838 ItemKind::Enum(ident, generics, enum_definition) =>
839 visit_visitable!($($mut)? vis, ident, generics, enum_definition),
840 ItemKind::Struct(ident, generics, variant_data)
841 | ItemKind::Union(ident, generics, variant_data) =>
842 visit_visitable!($($mut)? vis, ident, generics, variant_data),
843 ItemKind::Impl(impl_) =>
844 visit_visitable!($($mut)? vis, impl_),
845 ItemKind::Trait(trait_) =>
846 visit_visitable!($($mut)? vis, trait_),
847 ItemKind::TraitAlias(box TraitAlias { constness, ident, generics, bounds}) => {
848 visit_visitable!($($mut)? vis, constness, ident, generics);
849 visit_visitable_with!($($mut)? vis, bounds, BoundKind::Bound)
850 }
851 ItemKind::MacCall(m) =>
852 visit_visitable!($($mut)? vis, m),
853 ItemKind::MacroDef(ident, def) =>
854 visit_visitable!($($mut)? vis, ident, def),
855 ItemKind::Delegation(delegation) =>
856 visit_visitable!($($mut)? vis, delegation),
857 ItemKind::DelegationMac(dm) =>
858 visit_visitable!($($mut)? vis, dm),
859 }
860 V::Result::output()
861 }
862 }
863
864 impl WalkItemKind for AssocItemKind {
865 type Ctxt = AssocCtxt;
866 fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(
867 &$($lt)? $($mut)? self,
868 attrs: &AttrVec,
869 span: Span,
870 id: NodeId,
871 visibility: &$($lt)? $($mut)? Visibility,
872 ctxt: Self::Ctxt,
873 vis: &mut V,
874 ) -> V::Result {
875 match self {
876 AssocItemKind::Const(item) =>
877 visit_visitable!($($mut)? vis, item),
878 AssocItemKind::Fn(func) => {
879 let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), visibility, &$($mut)? *func);
880 try_visit!(vis.visit_fn(kind, attrs, span, id))
881 }
882 AssocItemKind::Type(alias) =>
883 visit_visitable!($($mut)? vis, alias),
884 AssocItemKind::MacCall(mac) =>
885 visit_visitable!($($mut)? vis, mac),
886 AssocItemKind::Delegation(delegation) =>
887 visit_visitable!($($mut)? vis, delegation),
888 AssocItemKind::DelegationMac(dm) =>
889 visit_visitable!($($mut)? vis, dm),
890 }
891 V::Result::output()
892 }
893 }
894
895 impl WalkItemKind for ForeignItemKind {
896 type Ctxt = ();
897 fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(
898 &$($lt)? $($mut)? self,
899 attrs: &AttrVec,
900 span: Span,
901 id: NodeId,
902 visibility: &$($lt)? $($mut)? Visibility,
903 _ctxt: Self::Ctxt,
904 vis: &mut V,
905 ) -> V::Result {
906 match self {
907 ForeignItemKind::Static(item) =>
908 visit_visitable!($($mut)? vis, item),
909 ForeignItemKind::Fn(func) => {
910 let kind = FnKind::Fn(FnCtxt::Foreign, visibility, &$($mut)?*func);
911 try_visit!(vis.visit_fn(kind, attrs, span, id))
912 }
913 ForeignItemKind::TyAlias(alias) =>
914 visit_visitable!($($mut)? vis, alias),
915 ForeignItemKind::MacCall(mac) =>
916 visit_visitable!($($mut)? vis, mac),
917 }
918 V::Result::output()
919 }
920 }
921
922 pub fn walk_fn<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, kind: FnKind<$($lt)? $(${ignore($mut)} '_)?>) -> V::Result {
923 match kind {
924 FnKind::Fn(
925 _ctxt,
926 _vis,
928 Fn { defaultness, ident, sig, generics, contract, body, define_opaque, eii_impls },
929 ) => {
930 let FnSig { header, decl, span } = sig;
931 visit_visitable!($($mut)? vis,
932 defaultness, ident, header, generics, decl,
933 contract, body, span, define_opaque, eii_impls
934 );
935 }
936 FnKind::Closure(binder, coroutine_kind, decl, body) =>
937 visit_visitable!($($mut)? vis, binder, coroutine_kind, decl, body),
938 }
939 V::Result::output()
940 }
941
942 impl_walkable!(|&$($mut)? $($lt)? self: Impl, vis: &mut V| {
943 let Impl { generics, of_trait, self_ty, items, constness: _ } = self;
944 try_visit!(vis.visit_generics(generics));
945 if let Some(box of_trait) = of_trait {
946 let TraitImplHeader { defaultness, safety, polarity, trait_ref } = of_trait;
947 visit_visitable!($($mut)? vis, defaultness, safety, polarity, trait_ref);
948 }
949 try_visit!(vis.visit_ty(self_ty));
950 visit_visitable_with!($($mut)? vis, items, AssocCtxt::Impl { of_trait: of_trait.is_some() });
951 V::Result::output()
952 });
953
954 impl_walkable!(|&$($mut)? $($lt)? self: MethodCall, vis: &mut V| {
956 let MethodCall { seg, receiver, args, span } = self;
957 try_visit!(vis.visit_method_receiver_expr(receiver));
958 visit_visitable!($($mut)? vis, seg, args, span);
959 V::Result::output()
960 });
961
962 impl_walkable!(|&$($mut)? $($lt)? self: Expr, vis: &mut V| {
963 let Expr { id, kind, span, attrs, tokens: _ } = self;
964 visit_visitable!($($mut)? vis, id, attrs);
965 match kind {
966 ExprKind::Array(exprs) =>
967 visit_visitable!($($mut)? vis, exprs),
968 ExprKind::ConstBlock(anon_const) =>
969 visit_visitable!($($mut)? vis, anon_const),
970 ExprKind::Repeat(element, count) =>
971 visit_visitable!($($mut)? vis, element, count),
972 ExprKind::Struct(se) =>
973 visit_visitable!($($mut)? vis, se),
974 ExprKind::Tup(exprs) =>
975 visit_visitable!($($mut)? vis, exprs),
976 ExprKind::Call(callee_expression, arguments) =>
977 visit_visitable!($($mut)? vis, callee_expression, arguments),
978 ExprKind::MethodCall(mc) =>
979 visit_visitable!($($mut)? vis, mc),
980 ExprKind::Binary(op, lhs, rhs) =>
981 visit_visitable!($($mut)? vis, op, lhs, rhs),
982 ExprKind::AddrOf(kind, mutbl, subexpression) =>
983 visit_visitable!($($mut)? vis, kind, mutbl, subexpression),
984 ExprKind::Unary(op, subexpression) =>
985 visit_visitable!($($mut)? vis, op, subexpression),
986 ExprKind::Cast(subexpression, typ) | ExprKind::Type(subexpression, typ) =>
987 visit_visitable!($($mut)? vis, subexpression, typ),
988 ExprKind::Let(pat, expr, span, _recovered) =>
989 visit_visitable!($($mut)? vis, pat, expr, span),
990 ExprKind::If(head_expression, if_block, optional_else) =>
991 visit_visitable!($($mut)? vis, head_expression, if_block, optional_else),
992 ExprKind::While(subexpression, block, opt_label) =>
993 visit_visitable!($($mut)? vis, subexpression, block, opt_label),
994 ExprKind::ForLoop { pat, iter, body, label, kind } =>
995 visit_visitable!($($mut)? vis, pat, iter, body, label, kind),
996 ExprKind::Loop(block, opt_label, span) =>
997 visit_visitable!($($mut)? vis, block, opt_label, span),
998 ExprKind::Match(subexpression, arms, kind) =>
999 visit_visitable!($($mut)? vis, subexpression, arms, kind),
1000 ExprKind::Closure(box Closure {
1001 binder,
1002 capture_clause,
1003 coroutine_kind,
1004 constness,
1005 movability,
1006 fn_decl,
1007 body,
1008 fn_decl_span,
1009 fn_arg_span,
1010 }) => {
1011 visit_visitable!($($mut)? vis, constness, movability, capture_clause);
1012 let kind = FnKind::Closure(binder, coroutine_kind, fn_decl, body);
1013 try_visit!(vis.visit_fn(kind, attrs, *span, *id));
1014 visit_visitable!($($mut)? vis, fn_decl_span, fn_arg_span);
1015 }
1016 ExprKind::Block(block, opt_label) =>
1017 visit_visitable!($($mut)? vis, block, opt_label),
1018 ExprKind::Gen(capt, body, kind, decl_span) =>
1019 visit_visitable!($($mut)? vis, capt, body, kind, decl_span),
1020 ExprKind::Await(expr, span) | ExprKind::Use(expr, span) =>
1021 visit_visitable!($($mut)? vis, expr, span),
1022 ExprKind::Assign(lhs, rhs, span) =>
1023 visit_visitable!($($mut)? vis, lhs, rhs, span),
1024 ExprKind::AssignOp(op, lhs, rhs) =>
1025 visit_visitable!($($mut)? vis, op, lhs, rhs),
1026 ExprKind::Field(subexpression, ident) =>
1027 visit_visitable!($($mut)? vis, subexpression, ident),
1028 ExprKind::Index(main_expression, index_expression, span) =>
1029 visit_visitable!($($mut)? vis, main_expression, index_expression, span),
1030 ExprKind::Range(start, end, limit) =>
1031 visit_visitable!($($mut)? vis, start, end, limit),
1032 ExprKind::Underscore => {}
1033 ExprKind::Path(maybe_qself, path) =>
1034 visit_visitable!($($mut)? vis, maybe_qself, path),
1035 ExprKind::Break(opt_label, opt_expr) =>
1036 visit_visitable!($($mut)? vis, opt_label, opt_expr),
1037 ExprKind::Continue(opt_label) =>
1038 visit_visitable!($($mut)? vis, opt_label),
1039 ExprKind::Ret(optional_expression) | ExprKind::Yeet(optional_expression) =>
1040 visit_visitable!($($mut)? vis, optional_expression),
1041 ExprKind::Become(expr) =>
1042 visit_visitable!($($mut)? vis, expr),
1043 ExprKind::MacCall(mac) =>
1044 visit_visitable!($($mut)? vis, mac),
1045 ExprKind::Paren(subexpression) =>
1046 visit_visitable!($($mut)? vis, subexpression),
1047 ExprKind::InlineAsm(asm) =>
1048 visit_visitable!($($mut)? vis, asm),
1049 ExprKind::FormatArgs(f) =>
1050 visit_visitable!($($mut)? vis, f),
1051 ExprKind::OffsetOf(container, fields) =>
1052 visit_visitable!($($mut)? vis, container, fields),
1053 ExprKind::Yield(kind) =>
1054 visit_visitable!($($mut)? vis, kind),
1055 ExprKind::Try(subexpression) =>
1056 visit_visitable!($($mut)? vis, subexpression),
1057 ExprKind::TryBlock(body, optional_type) =>
1058 visit_visitable!($($mut)? vis, body, optional_type),
1059 ExprKind::Lit(token) =>
1060 visit_visitable!($($mut)? vis, token),
1061 ExprKind::IncludedBytes(bytes) =>
1062 visit_visitable!($($mut)? vis, bytes),
1063 ExprKind::UnsafeBinderCast(kind, expr, ty) =>
1064 visit_visitable!($($mut)? vis, kind, expr, ty),
1065 ExprKind::Err(_guar) => {}
1066 ExprKind::Dummy => {}
1067 }
1068
1069 visit_span(vis, span)
1070 });
1071
1072 define_named_walk!($(($mut))? $Visitor$(<$lt>)?
1073 pub fn walk_anon_const(AnonConst);
1074 pub fn walk_arm(Arm);
1075 pub fn walk_assoc_item_constraint(AssocItemConstraint);
1077 pub fn walk_attribute(Attribute);
1078 pub fn walk_block(Block);
1079 pub fn walk_capture_by(CaptureBy);
1081 pub fn walk_closure_binder(ClosureBinder);
1082 pub fn walk_contract(FnContract);
1083 pub fn walk_coroutine_kind(CoroutineKind);
1084 pub fn walk_crate(Crate);
1085 pub fn walk_expr(Expr);
1086 pub fn walk_expr_field(ExprField);
1087 pub fn walk_field_def(FieldDef);
1088 pub fn walk_fn_decl(FnDecl);
1089 pub fn walk_fn_header(FnHeader);
1090 pub fn walk_fn_ret_ty(FnRetTy);
1091 pub fn walk_foreign_mod(ForeignMod);
1093 pub fn walk_format_args(FormatArgs);
1094 pub fn walk_generic_arg(GenericArg);
1095 pub fn walk_generic_args(GenericArgs);
1096 pub fn walk_generic_param(GenericParam);
1097 pub fn walk_generics(Generics);
1098 pub fn walk_inline_asm(InlineAsm);
1099 pub fn walk_inline_asm_sym(InlineAsmSym);
1100 pub fn walk_label(Label);
1102 pub fn walk_lifetime(Lifetime);
1103 pub fn walk_local(Local);
1104 pub fn walk_mac(MacCall);
1105 pub fn walk_macro_def(MacroDef);
1106 pub fn walk_param_bound(GenericBound);
1107 pub fn walk_param(Param);
1108 pub fn walk_pat_field(PatField);
1109 pub fn walk_path(Path);
1110 pub fn walk_path_segment(PathSegment);
1111 pub fn walk_pat(Pat);
1112 pub fn walk_poly_trait_ref(PolyTraitRef);
1113 pub fn walk_precise_capturing_arg(PreciseCapturingArg);
1114 pub fn walk_qself(QSelf);
1115 pub fn walk_trait_ref(TraitRef);
1116 pub fn walk_ty_pat(TyPat);
1117 pub fn walk_ty(Ty);
1118 pub fn walk_use_tree(UseTree);
1119 pub fn walk_variant_data(VariantData);
1120 pub fn walk_variant(Variant);
1121 pub fn walk_vis(Visibility);
1122 pub fn walk_where_predicate_kind(WherePredicateKind);
1123 pub fn walk_where_predicate(WherePredicate);
1124 );
1125 };
1126}
1127
1128common_visitor_and_walkers!(Visitor<'a>);
1129
1130macro_rules! generate_list_visit_fns {
1131 ($($name:ident, $Ty:ty, $visit_fn:ident$(, $param:ident: $ParamTy:ty)*;)+) => {
1132 $(
1133 #[allow(unused_parens)]
1134 impl<'a, V: Visitor<'a>> Visitable<'a, V> for ThinVec<$Ty> {
1135 type Extra = ($($ParamTy),*);
1136
1137 #[inline]
1138 fn visit(
1139 &'a self,
1140 visitor: &mut V,
1141 ($($param),*): Self::Extra,
1142 ) -> V::Result {
1143 $name(visitor, self $(, $param)*)
1144 }
1145 }
1146
1147 fn $name<'a, V: Visitor<'a>>(
1148 vis: &mut V,
1149 values: &'a ThinVec<$Ty>,
1150 $(
1151 $param: $ParamTy,
1152 )*
1153 ) -> V::Result {
1154 walk_list!(vis, $visit_fn, values$(,$param)*);
1155 V::Result::output()
1156 }
1157 )+
1158 }
1159}
1160
1161generate_list_visit_fns! {
1162 visit_items, Box<Item>, visit_item;
1163 visit_foreign_items, Box<ForeignItem>, visit_foreign_item;
1164 visit_generic_params, GenericParam, visit_generic_param;
1165 visit_stmts, Stmt, visit_stmt;
1166 visit_exprs, Box<Expr>, visit_expr;
1167 visit_expr_fields, ExprField, visit_expr_field;
1168 visit_pat_fields, PatField, visit_pat_field;
1169 visit_variants, Variant, visit_variant;
1170 visit_assoc_items, Box<AssocItem>, visit_assoc_item, ctxt: AssocCtxt;
1171 visit_where_predicates, WherePredicate, visit_where_predicate;
1172 visit_params, Param, visit_param;
1173 visit_field_defs, FieldDef, visit_field_def;
1174 visit_arms, Arm, visit_arm;
1175}
1176
1177pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) -> V::Result {
1178 let Stmt { id, kind, span: _ } = statement;
1179 try_visit!(visitor.visit_id(*id));
1180 match kind {
1181 StmtKind::Let(local) => try_visit!(visitor.visit_local(local)),
1182 StmtKind::Item(item) => try_visit!(visitor.visit_item(item)),
1183 StmtKind::Expr(expr) | StmtKind::Semi(expr) => try_visit!(visitor.visit_expr(expr)),
1184 StmtKind::Empty => {}
1185 StmtKind::MacCall(mac) => {
1186 let MacCallStmt { mac, attrs, style: _, tokens: _ } = &**mac;
1187 walk_list!(visitor, visit_attribute, attrs);
1188 try_visit!(visitor.visit_mac_call(mac));
1189 }
1190 }
1191 V::Result::output()
1192}