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