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