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