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