Skip to main content

charon_lib/ast/
visitor.rs

1//! Defines two overrideable visitor traits that can be used to conveniently traverse the whole
2//! contents of an item. This is useful when e.g. dealing with types, which show up pretty much
3//! everywhere in the ast.
4//!
5//! The crate defines two traits:
6//! - `AstVisitable` is a trait implemented by all the types that can be visited by this;
7//! - `VisitAst[Mut]` is a (pair of) visitor trait(s) that can be implemented by visitors.
8//!   To define a visitor, implement `VisitAst[Mut]` and override the methods you need. Calling
9//!   `x.drive[_mut](&mut visitor)` will then traverse `x`, calling the visitor methods on all the
10//!   subvalues encountered.
11//!
12//! Underneath it all, this uses `derive_generic_visitor::Drive[Mut]` to do the actual visiting.
13use std::mem;
14use std::path::PathBuf;
15use std::{any::Any, hash::Hash};
16
17use crate::ast::from_rustc;
18use crate::ast::from_rustc::{
19    AttributeKind, DeprecatedSince, Deprecation, Ident, LangItem, OptimizeAttr,
20};
21use crate::ast::*;
22use crate::ids::{Idx, IndexVec};
23use derive_generic_visitor::*;
24
25/// An overrideable visitor trait that can be used to conveniently traverse the whole contents of
26/// an item. This is useful when e.g. dealing with types, which show up pretty much everywhere in
27/// the ast.
28///
29/// This defines three traits:
30/// - `AstVisitable` is a trait implemented by all the types listed below; it has a
31/// `drive[_mut]` method that takes a `VisitAst[Mut]` visitor and calls its methods on all
32/// the relevant subvalues of `self` encountered.
33/// - `VisitAst[Mut]` is a (pair of) visitor trait(s) that can be implemented by visitors. To
34/// define a visitor, implement `VisitAst[Mut]` and override the methods you need.
35///
36/// This trait has a `drive[_mut]` method that knows how to drive a `VisitAst[Mut]` visitor. This
37/// trait is implemented for all the listed types. If listed as `override`, the corresponding
38/// visitor trait has an overrideable method to visit this type. If listed as `drive`, the type
39/// will only be visited by recursing into its contents.
40///
41/// Morally this represents the predicate `for<V: VisitAst[Mut]> Self:
42/// Drive[Mut]<AstVisitableWrapper<V>>`
43#[visitable_group(
44    // Defines the `Visit[Mut]` traits and the `drive[_mut]` method that drives them.
45    visitor(drive(&VisitAst)),
46    visitor(drive_mut(&mut VisitAstMut)),
47    visitor(drive_two(&two ZipAst)),
48    // Types that are skipped by normal visitors but compared for equality by `ZipAst`.
49    skip_but_eq(
50        (),
51        Abi,
52        AsmKind,
53        AsmOperandId,
54        AsmOptions,
55        AsmRegister,
56        BranchId,
57        BuiltinImplData,
58        BuiltinPathElem,
59        CallSafety,
60        DeprecatedSince,
61        DropKind,
62        Error,
63        FieldPredecessor,
64        FileName,
65        GlobalKind,
66        ItemOpacity,
67        LangItem,
68        LifetimeMutability,
69        OptimizeAttr,
70        OverflowMode,
71        PathBuf,
72        ReprOptions,
73        RuntimeChecks,
74        String,
75        Variance,
76        WithRetag,
77        bool,
78        char,
79        crate::options::CliOpts,
80        from_rustc::Linkage,
81        i128,
82        std::ops::RangeInclusive<IntegerValue>,
83        u128,
84        u32,
85        u64,
86        u8,
87        ullbc_ast::UnwindKind,
88        usize,
89        ustr::Ustr,
90    ),
91    // Types that are completely skipped, even by `ZipAst`.
92    skip(
93        DeclarationGroup,
94        ImplementsMarkerTraits,
95        PredicateOrigin,
96        TargetInfo,
97        TypeInfo,
98        llbc_ast::BlockId,
99        llbc_ast::StatementId,
100    ),
101    // Types that we unconditionally explore.
102    drive(
103        AsmOperand,
104        AsmTemplatePiece,
105        Assert,
106        AssocConstId,
107        AssocItemId,
108        AssocItemNames,
109        AssocTypeId,
110        AttributeKind,
111        BinOp,
112        BinderKind,
113        BorrowKind,
114        BorrowckStatement,
115        BuiltinAdt,
116        BuiltinAssertKind,
117        Byte,
118        Call,
119        CastKind,
120        ClosureInfo,
121        ClosureKind,
122        ConstGenericParam,
123        ConstGenericVarId,
124        ConstProjectionElem,
125        Deprecation,
126        Disambiguator,
127        Discriminator,
128        DynPredicate,
129        Field,
130        FieldId,
131        File,
132        FloatTy,
133        FloatValue,
134        FnOperand,
135        FnPtrKind,
136        GlobalPlaceKind,
137        GlobalProvenance,
138        Ident,
139        InlineAsm,
140        InlineAttr,
141        IntTy,
142        IntegerTy,
143        IntegerValue,
144        ItemByVal,
145        ItemId,
146        Loc,
147        Local,
148        LocalId,
149        Locals,
150        MaybeAssocItemId,
151        NullOp,
152        OffsetExpr,
153        OffsetGuarantee,
154        Operand,
155        PathElem,
156        PlaceKind,
157        PtrMetadata,
158        RawAttribute,
159        RefKind,
160        RegionArgs,
161        RegionId,
162        ScalarTy,
163        SerializedSpan,
164        Size,
165        SpanData,
166        SwitchData,
167        SwitchScrutinee,
168        TraitItemName,
169        TraitMethodId,
170        TranslatedCrate,
171        TypeDeclKind,
172        TypeParam,
173        TypePattern,
174        TypeVarId,
175        UIntTy,
176        UnOp,
177        UnsizingMetadata,
178        VTableDecl,
179        VTableField,
180        Variant,
181        VariantId,
182        VariantLayout,
183        from_rustc::InlineAttr,
184        llbc_ast::ExprBody,
185        llbc_ast::StatementKind,
186        ullbc_ast::BlockData,
187        ullbc_ast::BlockId,
188        ullbc_ast::ExprBody,
189        ullbc_ast::StatementKind,
190        ullbc_ast::TerminatorKind,
191        for<A: AstVisitable, B: AstVisitable, C: AstVisitable> (A, B, C),
192        for<A: AstVisitable, B: AstVisitable> (A, B),
193        for<A: AstVisitable, B: AstVisitable> OutlivesPred<A, B>,
194        for<A: AstVisitable, B: AstVisitable> Result<A, B>,
195        for<I: Idx, T: AstVisitable> IndexMap<I, T>,
196        for<I: Idx, T: AstVisitable> IndexVec<I, T>,
197        for<Id: AstVisitable> DeclRef<Id>,
198        for<T: AstVisitable + HashConsable> HashConsed<T>,
199        for<T: AstVisitable> Box<T>,
200        for<T: AstVisitable> Option<T>,
201        for<T: AstVisitable> Vec<T>,
202    ),
203    // Types for which we call the corresponding `visit_$ty` method, which by default explores the
204    // type but can be overridden.
205    override(
206        AbortKind,
207        AggregateKind,
208        AttrInfo,
209        Attribute,
210        Body,
211        ConstantExpr,
212        ConstantExprKind,
213        DeBruijnId,
214        FileId,
215        FnPtr,
216        FunDecl,
217        FunDeclId,
218        FunDeclRef,
219        FunSig,
220        FunSource,
221        GenericArgs,
222        GenericParams,
223        GlobalDecl,
224        GlobalDeclId,
225        GlobalDeclRef,
226        GlobalPlace,
227        GlobalSource,
228        ImplElem,
229        InhabitedPredicate,
230        InhabitedPredicateKind,
231        ItemMeta,
232        Layout,
233        MetadataValue,
234        Name,
235        Place,
236        PolyTraitRef,
237        ProjectionElem,
238        Region,
239        RegionParam,
240        Rvalue,
241        SizeExpr,
242        SizeExprKind,
243        Span,
244        TraitAssocConst,
245        TraitAssocTy,
246        TraitAssocTyImpl,
247        TraitClauseId,
248        TraitDecl,
249        TraitDeclId,
250        TraitDeclRef,
251        TraitDeclSource,
252        TraitImpl,
253        TraitImplId,
254        TraitImplRef,
255        TraitImplSource,
256        TraitMethod,
257        TraitParam,
258        TraitRef,
259        TraitRefContents,
260        TraitRefKind,
261        TraitTypeConstraint,
262        Ty,
263        TyKind,
264        TypeDecl,
265        TypeDeclId,
266        TypeDeclRef,
267        TypeSource,
268        llbc_block: llbc_ast::Block,
269        llbc_statement: llbc_ast::Statement,
270        ullbc_statement: ullbc_ast::Statement,
271        ullbc_terminator: ullbc_ast::Terminator,
272        for<T: AstVisitable + Idx> DeBruijnVar<T>,
273        for<T: AstVisitable> Binder<T>,
274        for<T: AstVisitable> RegionBinder<T>,
275        for<T: AstVisitable> WithCachedTypeInfo<T>,
276    )
277)]
278pub trait AstVisitable: Any {
279    /// The name of the type, used for debug logging.
280    fn name(&self) -> &'static str {
281        std::any::type_name::<Self>()
282    }
283    /// Visit all occurrences of that type inside `self`, in pre-order traversal.
284    fn dyn_visit<T: AstVisitable>(&self, f: impl FnMut(&T))
285    where
286        Self: Sized,
287    {
288        let _ = VisitAst::visit(&mut DynVisitor::new_shared::<T>(f), self);
289    }
290    /// Visit all occurrences of that type inside `self`, in pre-order traversal.
291    fn dyn_visit_mut<T: AstVisitable>(&mut self, f: impl FnMut(&mut T))
292    where
293        Self: Sized,
294    {
295        let _ = VisitAstMut::visit(&mut DynVisitor::new_mut::<T>(f), self);
296    }
297}
298
299/// Manual impl that visits the keys and values
300impl<K: AstVisitable + Hash + Eq, T: AstVisitable> AstVisitable for SeqHashMap<K, T> {
301    fn drive<V: VisitAst>(&self, v: &mut V) -> ControlFlow<V::Break> {
302        for (k, x) in self {
303            v.visit(k)?;
304            v.visit(x)?;
305        }
306        Continue(())
307    }
308    fn drive_mut<V: VisitAstMut>(&mut self, v: &mut V) -> ControlFlow<V::Break> {
309        for (mut k, mut x) in mem::take(self) {
310            v.visit(&mut k)?;
311            v.visit(&mut x)?;
312            self.insert(k, x);
313        }
314        Continue(())
315    }
316    fn drive_two<V: ZipAst>(&self, other: &Self, v: &mut V) -> ControlFlow<V::Break> {
317        if self.len() != other.len() {
318            return Break(Default::default());
319        }
320        for ((key, value), (other_key, other_value)) in self.iter().zip(other) {
321            v.visit(key, other_key)?;
322            v.visit(value, other_value)?;
323        }
324        Continue(())
325    }
326}
327impl<K: BodyVisitable + Hash + Eq, T: BodyVisitable> BodyVisitable for SeqHashMap<K, T> {
328    fn drive_body<V: VisitBody>(&self, v: &mut V) -> ControlFlow<V::Break> {
329        for (k, x) in self {
330            v.visit(k)?;
331            v.visit(x)?;
332        }
333        Continue(())
334    }
335    fn drive_body_mut<V: VisitBodyMut>(&mut self, v: &mut V) -> ControlFlow<V::Break> {
336        for (mut k, mut x) in mem::take(self) {
337            v.visit(&mut k)?;
338            v.visit(&mut x)?;
339            self.insert(k, x);
340        }
341        Continue(())
342    }
343}
344
345/// A smaller visitor group just for function bodies. This explores statements, places and
346/// operands, but does not recurse into types.
347///
348/// This defines three traits:
349/// - `BodyVisitable` is a trait implemented by all the types listed below; it has a
350/// `drive_body[_mut]` method that takes a `VisitBody[Mut]` visitor and calls its methods on all
351/// the relevant subvalues of `self` encountered.
352/// - `VisitBody[Mut]` is a (pair of) visitor trait(s) that can be implemented by visitors. To
353/// define a visitor, implement `VisitBody[Mut]` and override the methods you need.
354///
355/// Morally this represents the predicate `for<V: VisitBody[Mut]> Self:
356/// Drive[Mut]<BodyVisitableWrapper<V>>`
357#[visitable_group(
358    // Defines the `VisitBody[Mut]` traits and the `drive_body[_mut]` method that drives them.
359    visitor(drive_body(&VisitBody)),
360    visitor(drive_body_mut(&mut VisitBodyMut)),
361    // Types that are ignored when encountered.
362    skip(
363        (),
364        AbortKind,
365        AsmKind,
366        AsmOperandId,
367        AsmOptions,
368        AsmRegister,
369        AsmTemplatePiece,
370        BinOp,
371        BorrowKind,
372        BranchId,
373        BuiltinAdt,
374        BuiltinPathElem,
375        CallSafety,
376        ConstantExpr,
377        DropKind,
378        Error,
379        FieldId,
380        FnPtrKind,
381        FunDeclId,
382        FunDeclRef,
383        GenericArgs,
384        GlobalDeclRef,
385        IntTy,
386        IntegerTy,
387        IntegerValue,
388        Name,
389        NullOp,
390        PathBuf,
391        PolyTraitRef,
392        RefKind,
393        Region,
394        RegionArgs,
395        RegionId,
396        ScalarTy,
397        Span,
398        String,
399        TraitRef,
400        Ty,
401        TypeDeclId,
402        TypeDeclRef,
403        UIntTy,
404        UnOp,
405        Variance,
406        VariantId,
407        WithRetag,
408        bool,
409        llbc_ast::BlockId,
410        llbc_ast::StatementId,
411        u32,
412        ullbc_ast::UnwindKind,
413        usize,
414    ),
415    // Types that we unconditionally explore.
416    drive(
417        Assert,
418        BorrowckStatement,
419        BuiltinAssertKind,
420        InlineAsm,
421        PlaceKind,
422        SwitchData,
423        SwitchScrutinee,
424        llbc_ast::StatementKind,
425        ullbc_ast::StatementKind,
426        ullbc_ast::TerminatorKind,
427        for<A: BodyVisitable, B: BodyVisitable, C: BodyVisitable> (A, B, C),
428        for<A: BodyVisitable, B: BodyVisitable> (A, B),
429        for<I: Idx, T: BodyVisitable> IndexMap<I, T>,
430        for<I: Idx, T: BodyVisitable> IndexVec<I, T>,
431        for<T: BodyVisitable, E: BodyVisitable> Result<T, E>,
432        for<T: BodyVisitable> Box<T>,
433        for<T: BodyVisitable> GExprBody<T>,
434        for<T: BodyVisitable> Option<T>,
435        for<T: BodyVisitable> Vec<T>,
436    ),
437    // Types for which we call the corresponding `visit_$ty` method, which by default explores the
438    // type but can be overridden.
439    override(
440        AggregateKind,
441        AsmOperand,
442        Body,
443        Call,
444        FnOperand,
445        FnPtr,
446        Local,
447        LocalId,
448        Locals,
449        Operand,
450        Place,
451        ProjectionElem,
452        Rvalue,
453        llbc_block: llbc_ast::Block,
454        llbc_statement: llbc_ast::Statement,
455        ullbc_block: ullbc_ast::BlockData,
456        ullbc_block_id: ullbc_ast::BlockId,
457        ullbc_statement: ullbc_ast::Statement,
458        ullbc_terminator: ullbc_ast::Terminator,
459    )
460)]
461pub trait BodyVisitable: Any {
462    /// Visit all occurrences of that type inside `self`, in pre-order traversal.
463    fn dyn_visit_in_body<T: BodyVisitable>(&self, f: impl FnMut(&T))
464    where
465        Self: Sized,
466    {
467        let _ = VisitBody::visit(&mut DynVisitor::new_shared::<T>(f), self);
468    }
469
470    /// Visit all occurrences of that type inside `self`, in pre-order traversal.
471    fn dyn_visit_in_body_mut<T: BodyVisitable>(&mut self, f: impl FnMut(&mut T))
472    where
473        Self: Sized,
474    {
475        let _ = VisitBodyMut::visit(&mut DynVisitor::new_mut::<T>(f), self);
476    }
477}
478
479/// Ast and body visitor that uses dynamic dispatch to call the provided function on the visited
480/// values of the right type.
481#[derive(Visitor)]
482pub struct DynVisitor<F> {
483    enter: F,
484}
485impl DynVisitor<()> {
486    pub fn new_shared<T: Any>(mut f: impl FnMut(&T)) -> DynVisitor<impl FnMut(&dyn Any)> {
487        let enter = move |x: &dyn Any| {
488            if let Some(x) = x.downcast_ref::<T>() {
489                f(x);
490            }
491        };
492        DynVisitor { enter }
493    }
494    pub fn new_mut<T: Any>(mut f: impl FnMut(&mut T)) -> DynVisitor<impl FnMut(&mut dyn Any)> {
495        let enter = move |x: &mut dyn Any| {
496            if let Some(x) = x.downcast_mut::<T>() {
497                f(x);
498            }
499        };
500        DynVisitor { enter }
501    }
502}
503impl<F> VisitAst for DynVisitor<F>
504where
505    F: FnMut(&dyn Any),
506{
507    fn visit<T: AstVisitable>(&mut self, x: &T) -> ControlFlow<Self::Break> {
508        (self.enter)(x);
509        x.drive(self)?;
510        Continue(())
511    }
512}
513impl<F> VisitAstMut for DynVisitor<F>
514where
515    F: FnMut(&mut dyn Any),
516{
517    fn visit<T: AstVisitable>(&mut self, x: &mut T) -> ControlFlow<Self::Break> {
518        (self.enter)(x);
519        x.drive_mut(self)?;
520        Continue(())
521    }
522}
523impl<F> VisitBody for DynVisitor<F>
524where
525    F: FnMut(&dyn Any),
526{
527    fn visit<T: BodyVisitable>(&mut self, x: &T) -> ControlFlow<Self::Break> {
528        (self.enter)(x);
529        x.drive_body(self)?;
530        Continue(())
531    }
532}
533impl<F> VisitBodyMut for DynVisitor<F>
534where
535    F: FnMut(&mut dyn Any),
536{
537    fn visit<T: BodyVisitable>(&mut self, x: &mut T) -> ControlFlow<Self::Break> {
538        (self.enter)(x);
539        x.drive_body_mut(self)?;
540        Continue(())
541    }
542}
543
544pub use wrappers::*;
545mod wrappers {
546    //! This module defines a bunch of visitor wrappers, in the model described in the `derive_generic_visitor` crate.
547    //! Each such wrapper is a non-recursive visitor; the only thing it does is that its `.visit()`
548    //! method calls into the appropriate `visit_foo` of the wrapper, then continues visiting with
549    //! the wrapped visitor.
550    //!
551    //! To use such a wrapper, just override the `visit` method of your visitor to call
552    //! `TheWrapper::new(self).visit(x)`. This will integrate the wrapper into the normal behavior of
553    //! your visitor.
554    //!
555    //! Each wrapper interacts with its wrapped visitor via a trait. To be able to use several
556    //! wrappers at once, they must implement the wrapper-specific trait themselves and forward to
557    //! their wrappee visitor. It's a bit annoying as that potentially requires N^2 impls. I don't
558    //! know of a better design.
559    use std::mem;
560
561    use crate::ast::*;
562    use derive_generic_visitor::*;
563
564    /// Struct that we use to be able to use our visitor wrappers with each other to share
565    /// functionality, while still making the wrappers composable. We can implement e.g.
566    /// `VisitorWithItem for DontLeakImplDetails<Wrapper<V>>` while still retaining the capacity to
567    /// implement `impl<V: VisitorWithItem> VisitorWithItem for Wrapper<V>` that forwards to the
568    /// inner visitor.
569    #[repr(transparent)]
570    pub struct DontLeakImplDetails<V>(V);
571
572    impl<V> DontLeakImplDetails<V> {
573        pub fn new(v: &mut V) -> &mut Self {
574            // SAFETY: `repr(transparent)`
575            unsafe { std::mem::transmute(v) }
576        }
577        pub fn inner(&mut self) -> &mut V {
578            // SAFETY: `repr(transparent)`
579            unsafe { std::mem::transmute(self) }
580        }
581    }
582
583    impl<V: Visitor> Visitor for DontLeakImplDetails<V> {
584        type Break = V::Break;
585    }
586    impl<V: VisitAst> VisitAst for DontLeakImplDetails<V> {
587        /// Just forward to the wrapped visitor.
588        fn visit_inner<T>(&mut self, x: &T) -> ControlFlow<Self::Break>
589        where
590            T: AstVisitable,
591        {
592            x.drive(self.inner())
593        }
594    }
595    impl<V: VisitAstMut> VisitAstMut for DontLeakImplDetails<V> {
596        /// Just forward to the wrapped visitor.
597        fn visit_inner<T>(&mut self, x: &mut T) -> ControlFlow<Self::Break>
598        where
599            T: AstVisitable,
600        {
601            x.drive_mut(self.inner())
602        }
603    }
604
605    /// Visitor wrapper that tracks the depth of binders. To use it, make a visitor that implements
606    /// `VisitorWithBinderDepth` and override its `visit` function as follows:
607    /// ```ignore
608    /// impl VisitAst for MyVisitor {
609    ///     fn visit<'a, T: AstVisitable>(&'a mut self, x: &T) -> ControlFlow<Self::Break> {
610    ///         VisitWithBinderDepth::new(self).visit(x)
611    ///     }
612    ///     ...
613    /// }
614    /// ```
615    #[repr(transparent)]
616    pub struct VisitWithBinderDepth<V>(V);
617
618    impl<V: VisitorWithBinderDepth> VisitWithBinderDepth<V> {
619        pub fn new(v: &mut V) -> &mut Self {
620            // SAFETY: `repr(transparent)`
621            unsafe { std::mem::transmute(v) }
622        }
623        pub fn inner(&mut self) -> &mut V {
624            // SAFETY: `repr(transparent)`
625            unsafe { std::mem::transmute(self) }
626        }
627    }
628
629    pub trait VisitorWithBinderDepth {
630        fn binder_depth_mut(&mut self) -> &mut DeBruijnId;
631    }
632
633    impl<V: Visitor> Visitor for VisitWithBinderDepth<V> {
634        type Break = V::Break;
635    }
636    impl<V: VisitAst + VisitorWithBinderDepth> VisitAst for VisitWithBinderDepth<V> {
637        fn visit_inner<T>(&mut self, x: &T) -> ControlFlow<Self::Break>
638        where
639            T: AstVisitable,
640        {
641            x.drive(self.inner())
642        }
643        fn enter_region_binder<T: AstVisitable>(&mut self, _: &RegionBinder<T>) {
644            let binder_depth = self.0.binder_depth_mut();
645            *binder_depth = binder_depth.incr()
646        }
647        fn exit_region_binder<T: AstVisitable>(&mut self, _: &RegionBinder<T>) {
648            let binder_depth = self.0.binder_depth_mut();
649            *binder_depth = binder_depth.decr()
650        }
651        fn enter_binder<T: AstVisitable>(&mut self, _: &Binder<T>) {
652            let binder_depth = self.0.binder_depth_mut();
653            *binder_depth = binder_depth.incr()
654        }
655        fn exit_binder<T: AstVisitable>(&mut self, _: &Binder<T>) {
656            let binder_depth = self.0.binder_depth_mut();
657            *binder_depth = binder_depth.decr()
658        }
659    }
660    impl<V: VisitAstMut + VisitorWithBinderDepth> VisitAstMut for VisitWithBinderDepth<V> {
661        fn visit_inner<T>(&mut self, x: &mut T) -> ControlFlow<Self::Break>
662        where
663            T: AstVisitable,
664        {
665            x.drive_mut(self.inner())
666        }
667        fn enter_region_binder<T: AstVisitable>(&mut self, _: &mut RegionBinder<T>) {
668            let binder_depth = self.0.binder_depth_mut();
669            *binder_depth = binder_depth.incr()
670        }
671        fn exit_region_binder<T: AstVisitable>(&mut self, _: &mut RegionBinder<T>) {
672            let binder_depth = self.0.binder_depth_mut();
673            *binder_depth = binder_depth.decr()
674        }
675        fn enter_binder<T: AstVisitable>(&mut self, _: &mut Binder<T>) {
676            let binder_depth = self.0.binder_depth_mut();
677            *binder_depth = binder_depth.incr()
678        }
679        fn exit_binder<T: AstVisitable>(&mut self, _: &mut Binder<T>) {
680            let binder_depth = self.0.binder_depth_mut();
681            *binder_depth = binder_depth.decr()
682        }
683    }
684
685    /// Visitor wrapper that tracks the variance of the current position. To use it, make a visitor
686    /// that implements [`VisitorWithVariance`] and delegate its `visit` method to this wrapper.
687    pub struct VisitWithVariance<'a, 'ctx, V> {
688        inner: &'a mut V,
689        krate: &'ctx TranslatedCrate,
690    }
691
692    impl<'a, 'ctx, V: VisitorWithVariance> VisitWithVariance<'a, 'ctx, V> {
693        pub fn new(inner: &'a mut V, krate: &'ctx TranslatedCrate) -> Self {
694            Self { inner, krate }
695        }
696    }
697
698    pub trait VisitorWithVariance {
699        fn ambient_variance_mut(&mut self) -> &mut Variance;
700    }
701
702    impl<V: Visitor> Visitor for VisitWithVariance<'_, '_, V> {
703        type Break = V::Break;
704    }
705
706    impl<V: VisitAst + VisitorWithVariance> VisitWithVariance<'_, '_, V> {
707        fn with(
708            &mut self,
709            variance: Variance,
710            f: impl FnOnce(&mut Self) -> ControlFlow<V::Break>,
711        ) -> ControlFlow<V::Break> {
712            let old = *self.inner.ambient_variance_mut();
713            *self.inner.ambient_variance_mut() = Variance::compose(old, variance);
714            let result = f(self);
715            *self.inner.ambient_variance_mut() = old;
716            result
717        }
718
719        fn visit_with<T: AstVisitable>(
720            &mut self,
721            variance: Variance,
722            value: &T,
723        ) -> ControlFlow<V::Break> {
724            self.with(variance, |this| this.visit(value))
725        }
726
727        fn visit_inner_with(&mut self, variance: Variance, ty: &Ty) -> ControlFlow<V::Break> {
728            self.with(variance, |this| this.visit_inner(ty))
729        }
730    }
731
732    impl<V: VisitAst + VisitorWithVariance> VisitAst for VisitWithVariance<'_, '_, V> {
733        fn visit_inner<T: AstVisitable>(&mut self, value: &T) -> ControlFlow<Self::Break> {
734            value.drive(self.inner)
735        }
736
737        fn visit_ty(&mut self, ty: &Ty) -> ControlFlow<Self::Break> {
738            match ty.kind() {
739                TyKind::Ref(region, inner, kind) => {
740                    self.visit(region)?;
741                    match kind {
742                        RefKind::Shared => self.visit(inner)?,
743                        RefKind::Mut => self.visit_with(Variance::Invariant, inner)?,
744                    }
745                }
746                TyKind::RawPtr(inner, RefKind::Shared) => self.visit(inner)?,
747                TyKind::RawPtr(inner, RefKind::Mut) => {
748                    self.visit_with(Variance::Invariant, inner)?;
749                }
750                TyKind::FnPtr(..)
751                | TyKind::Adt(..)
752                | TyKind::Array(..)
753                | TyKind::Slice(..)
754                | TyKind::Pattern(..) => {
755                    self.visit_inner(ty)?;
756                }
757                TyKind::TraitType(..)
758                | TyKind::DynTrait(..)
759                | TyKind::FnDef(..)
760                | TyKind::PtrMetadata(..) => {
761                    self.visit_inner_with(Variance::Invariant, ty)?;
762                }
763                TyKind::TypeVar(..) | TyKind::Scalar(..) | TyKind::Never | TyKind::Error(..) => {}
764            }
765            Continue(())
766        }
767
768        fn visit_fun_sig(&mut self, sig: &FunSig) -> ControlFlow<Self::Break> {
769            for input in &sig.inputs {
770                self.visit_with(Variance::Contravariant, input)?;
771            }
772            self.visit(&sig.output)?;
773            Continue(())
774        }
775
776        fn visit_type_decl_ref(&mut self, type_ref: &TypeDeclRef) -> ControlFlow<Self::Break> {
777            if let Some(decl) = self.krate.type_decls.get(type_ref.id) {
778                let params = &decl.generics;
779                for (param, region) in params.regions.iter().zip(&type_ref.generics.regions) {
780                    self.visit_with(param.variance, region)?;
781                }
782                for (param, ty) in params.types.iter().zip(&type_ref.generics.types) {
783                    self.visit_with(param.variance, ty)?;
784                }
785            } else {
786                self.visit_with(Variance::Covariant, &type_ref.generics.regions)?;
787                self.visit_with(Variance::Covariant, &type_ref.generics.types)?;
788            }
789            Continue(())
790        }
791    }
792
793    /// Visitor wrapper that adds item-generic `enter_item` and `exit_item` methods.
794    #[repr(transparent)]
795    pub struct VisitWithItem<V>(V);
796
797    impl<V> VisitWithItem<V> {
798        pub fn new(v: &mut V) -> &mut Self {
799            // SAFETY: `repr(transparent)`
800            unsafe { std::mem::transmute(v) }
801        }
802        pub fn inner(&mut self) -> &mut V {
803            // SAFETY: `repr(transparent)`
804            unsafe { std::mem::transmute(self) }
805        }
806    }
807
808    pub trait VisitorWithItem: VisitAst {
809        fn enter_item(&mut self, _item: ItemRef<'_>) {}
810        fn exit_item(&mut self, _item: ItemRef<'_>) {}
811        fn visit_item(&mut self, item: ItemRef<'_>) -> ControlFlow<Self::Break> {
812            self.enter_item(item);
813            item.drive(self)?;
814            self.exit_item(item);
815            Continue(())
816        }
817    }
818    pub trait VisitorWithItemMut: VisitAstMut {
819        fn enter_item(&mut self, _item: ItemRefMut<'_>) {}
820        fn exit_item(&mut self, _item: ItemRefMut<'_>) {}
821        fn visit_item(&mut self, mut item: ItemRefMut<'_>) -> ControlFlow<Self::Break> {
822            self.enter_item(item.reborrow());
823            item.drive_mut(self)?;
824            self.exit_item(item);
825            Continue(())
826        }
827    }
828
829    impl<V: Visitor> Visitor for VisitWithItem<V> {
830        type Break = V::Break;
831    }
832    impl<V: VisitAst + VisitorWithItem> VisitAst for VisitWithItem<V> {
833        fn visit_inner<T>(&mut self, x: &T) -> ControlFlow<Self::Break>
834        where
835            T: AstVisitable,
836        {
837            x.drive(self.inner())
838        }
839        fn visit_fun_decl(&mut self, x: &FunDecl) -> ControlFlow<Self::Break> {
840            self.0.visit_item(ItemRef::Fun(x))
841        }
842        fn visit_type_decl(&mut self, x: &TypeDecl) -> ControlFlow<Self::Break> {
843            self.0.visit_item(ItemRef::Type(x))
844        }
845        fn visit_global_decl(&mut self, x: &GlobalDecl) -> ControlFlow<Self::Break> {
846            self.0.visit_item(ItemRef::Global(x))
847        }
848        fn visit_trait_decl(&mut self, x: &TraitDecl) -> ControlFlow<Self::Break> {
849            self.0.visit_item(ItemRef::TraitDecl(x))
850        }
851        fn visit_trait_impl(&mut self, x: &TraitImpl) -> ControlFlow<Self::Break> {
852            self.0.visit_item(ItemRef::TraitImpl(x))
853        }
854    }
855    impl<V: VisitAstMut + VisitorWithItemMut> VisitAstMut for VisitWithItem<V> {
856        fn visit_inner<T>(&mut self, x: &mut T) -> ControlFlow<Self::Break>
857        where
858            T: AstVisitable,
859        {
860            x.drive_mut(self.inner())
861        }
862        fn visit_fun_decl(&mut self, x: &mut FunDecl) -> ControlFlow<Self::Break> {
863            self.0.visit_item(ItemRefMut::Fun(x))
864        }
865        fn visit_type_decl(&mut self, x: &mut TypeDecl) -> ControlFlow<Self::Break> {
866            self.0.visit_item(ItemRefMut::Type(x))
867        }
868        fn visit_global_decl(&mut self, x: &mut GlobalDecl) -> ControlFlow<Self::Break> {
869            self.0.visit_item(ItemRefMut::Global(x))
870        }
871        fn visit_trait_decl(&mut self, x: &mut TraitDecl) -> ControlFlow<Self::Break> {
872            self.0.visit_item(ItemRefMut::TraitDecl(x))
873        }
874        fn visit_trait_impl(&mut self, x: &mut TraitImpl) -> ControlFlow<Self::Break> {
875            self.0.visit_item(ItemRefMut::TraitImpl(x))
876        }
877    }
878
879    /// Visitor wrapper that catches references to top-level items.
880    #[repr(transparent)]
881    pub struct VisitWithItemRef<V>(V);
882
883    impl<V> VisitWithItemRef<V> {
884        pub fn new(v: &mut V) -> &mut Self {
885            // SAFETY: `repr(transparent)`
886            unsafe { std::mem::transmute(v) }
887        }
888        pub fn inner(&mut self) -> &mut V {
889            // SAFETY: `repr(transparent)`
890            unsafe { std::mem::transmute(self) }
891        }
892    }
893
894    pub trait VisitorWithItemRef: VisitAst {
895        fn enter_item_ref(&mut self, _item_id: ItemId, _args: &GenericArgs) {}
896        fn exit_item_ref(&mut self, _item_id: ItemId, _args: &GenericArgs) {}
897        fn visit_item_ref(
898            &mut self,
899            item_id: ItemId,
900            args: &GenericArgs,
901        ) -> ControlFlow<Self::Break> {
902            self.enter_item_ref(item_id, args);
903            self.visit_inner(args)?;
904            self.exit_item_ref(item_id, args);
905            Continue(())
906        }
907    }
908    pub trait VisitorWithItemRefMut: VisitAstMut {
909        fn enter_item_ref(&mut self, _item_id: ItemId, _args: &mut GenericArgs) {}
910        fn exit_item_ref(&mut self, _item_id: ItemId, _args: &mut GenericArgs) {}
911        fn visit_item_ref(
912            &mut self,
913            item_id: ItemId,
914            args: &mut GenericArgs,
915        ) -> ControlFlow<Self::Break> {
916            self.enter_item_ref(item_id, args);
917            self.visit_inner(args)?;
918            self.exit_item_ref(item_id, args);
919            Continue(())
920        }
921    }
922
923    impl<V: Visitor> Visitor for VisitWithItemRef<V> {
924        type Break = V::Break;
925    }
926    impl<V: VisitAst + VisitorWithItemRef> VisitAst for VisitWithItemRef<V> {
927        fn visit_inner<T>(&mut self, x: &T) -> ControlFlow<Self::Break>
928        where
929            T: AstVisitable,
930        {
931            x.drive(self.inner())
932        }
933        fn visit_type_decl_ref(&mut self, x: &TypeDeclRef) -> ControlFlow<Self::Break> {
934            self.0.visit_item_ref(ItemId::Type(x.id), &x.generics)
935        }
936        fn visit_fun_decl_ref(&mut self, x: &FunDeclRef) -> ControlFlow<Self::Break> {
937            self.0.visit_item_ref(ItemId::Fun(x.id), &x.generics)
938        }
939        fn visit_global_decl_ref(&mut self, x: &GlobalDeclRef) -> ControlFlow<Self::Break> {
940            self.0.visit_item_ref(ItemId::Global(x.id), &x.generics)
941        }
942        fn visit_trait_decl_ref(&mut self, x: &TraitDeclRef) -> ControlFlow<Self::Break> {
943            self.0.visit_item_ref(ItemId::TraitDecl(x.id), &x.generics)
944        }
945        fn visit_trait_impl_ref(&mut self, x: &TraitImplRef) -> ControlFlow<Self::Break> {
946            self.0.visit_item_ref(ItemId::TraitImpl(x.id), &x.generics)
947        }
948        fn visit_fn_ptr(&mut self, x: &FnPtr) -> ControlFlow<Self::Break> {
949            match x.kind.as_ref() {
950                FnPtrKind::Fun(id) => self.0.visit_item_ref(ItemId::Fun(*id), &x.generics),
951                FnPtrKind::Trait(..) => self.visit_inner(x),
952            }
953        }
954    }
955    impl<V: VisitAstMut + VisitorWithItemRefMut> VisitAstMut for VisitWithItemRef<V> {
956        fn visit_inner<T>(&mut self, x: &mut T) -> ControlFlow<Self::Break>
957        where
958            T: AstVisitable,
959        {
960            x.drive_mut(self.inner())
961        }
962        fn visit_type_decl_ref(&mut self, x: &mut TypeDeclRef) -> ControlFlow<Self::Break> {
963            self.0.visit_item_ref(ItemId::Type(x.id), &mut x.generics)
964        }
965        fn visit_fun_decl_ref(&mut self, x: &mut FunDeclRef) -> ControlFlow<Self::Break> {
966            self.0.visit_item_ref(ItemId::Fun(x.id), &mut x.generics)
967        }
968        fn visit_global_decl_ref(&mut self, x: &mut GlobalDeclRef) -> ControlFlow<Self::Break> {
969            self.0.visit_item_ref(ItemId::Global(x.id), &mut x.generics)
970        }
971        fn visit_trait_decl_ref(&mut self, x: &mut TraitDeclRef) -> ControlFlow<Self::Break> {
972            self.0
973                .visit_item_ref(ItemId::TraitDecl(x.id), &mut x.generics)
974        }
975        fn visit_trait_impl_ref(&mut self, x: &mut TraitImplRef) -> ControlFlow<Self::Break> {
976            self.0
977                .visit_item_ref(ItemId::TraitImpl(x.id), &mut x.generics)
978        }
979        fn visit_fn_ptr(&mut self, x: &mut FnPtr) -> ControlFlow<Self::Break> {
980            match x.kind.as_ref() {
981                FnPtrKind::Fun(id) => self.0.visit_item_ref(ItemId::Fun(*id), &mut x.generics),
982                FnPtrKind::Trait(..) => self.visit_inner(x),
983            }
984        }
985    }
986
987    /// Visitor wrapper that tracks the stack of binders seen so far. See [`VisitWithBinderDepth`] for how to use.
988    #[repr(transparent)]
989    pub struct VisitWithBinderStack<V>(V);
990
991    impl<V: VisitorWithBinderStack> VisitWithBinderStack<V> {
992        // Helper
993        fn wrap(v: &mut V) -> &mut Self {
994            // SAFETY: `repr(transparent)`
995            unsafe { std::mem::transmute(v) }
996        }
997        pub fn new(v: &mut V) -> &mut VisitWithItem<DontLeakImplDetails<Self>> {
998            // Use the `WithItem` wrapper to simplify the implementation of this wrapper. We use
999            // `DontLeakImplDetails` to use the specific `VisitorWithItem` impl we care about
1000            // instead of the one that forwards to the `VisitorWithItem` of the containted `V`.
1001            VisitWithItem::new(DontLeakImplDetails::new(Self::wrap(v)))
1002        }
1003        pub fn inner(&mut self) -> &mut V {
1004            // SAFETY: `repr(transparent)`
1005            unsafe { std::mem::transmute(self) }
1006        }
1007    }
1008
1009    pub trait VisitorWithBinderStack {
1010        fn binder_stack_mut(&mut self) -> &mut BindingStack<GenericParams>;
1011    }
1012
1013    impl<V: VisitAst + VisitorWithBinderStack> VisitorWithItem
1014        for DontLeakImplDetails<VisitWithBinderStack<V>>
1015    {
1016        fn enter_item(&mut self, item: ItemRef<'_>) {
1017            self.0
1018                .0
1019                .binder_stack_mut()
1020                .push(item.generic_params().clone());
1021        }
1022        fn exit_item(&mut self, _item: ItemRef<'_>) {
1023            self.0.0.binder_stack_mut().pop();
1024        }
1025    }
1026    impl<V: VisitAstMut + VisitorWithBinderStack> VisitorWithItemMut
1027        for DontLeakImplDetails<VisitWithBinderStack<V>>
1028    {
1029        fn enter_item(&mut self, item: ItemRefMut<'_>) {
1030            self.0
1031                .0
1032                .binder_stack_mut()
1033                .push(item.as_ref().generic_params().clone());
1034        }
1035        fn exit_item(&mut self, _item: ItemRefMut<'_>) {
1036            self.0.0.binder_stack_mut().pop();
1037        }
1038    }
1039
1040    impl<V: Visitor> Visitor for VisitWithBinderStack<V> {
1041        type Break = V::Break;
1042    }
1043    impl<V: VisitAst + VisitorWithBinderStack> VisitAst for VisitWithBinderStack<V> {
1044        fn visit_inner<T>(&mut self, x: &T) -> ControlFlow<Self::Break>
1045        where
1046            T: AstVisitable,
1047        {
1048            x.drive(self.inner())
1049        }
1050        fn visit_binder<T: AstVisitable>(
1051            &mut self,
1052            binder: &Binder<T>,
1053        ) -> ControlFlow<Self::Break> {
1054            self.0.binder_stack_mut().push(binder.params.clone());
1055            self.visit_inner(binder)?;
1056            self.0.binder_stack_mut().pop();
1057            Continue(())
1058        }
1059        fn visit_region_binder<T: AstVisitable>(
1060            &mut self,
1061            binder: &RegionBinder<T>,
1062        ) -> ControlFlow<Self::Break> {
1063            self.0.binder_stack_mut().push(binder.to_params());
1064            self.visit_inner(binder)?;
1065            self.0.binder_stack_mut().pop();
1066            Continue(())
1067        }
1068    }
1069    impl<V: VisitAstMut + VisitorWithBinderStack> VisitAstMut for VisitWithBinderStack<V> {
1070        fn visit_inner<T>(&mut self, x: &mut T) -> ControlFlow<Self::Break>
1071        where
1072            T: AstVisitable,
1073        {
1074            x.drive_mut(self.inner())
1075        }
1076        fn visit_binder<T: AstVisitable>(
1077            &mut self,
1078            binder: &mut Binder<T>,
1079        ) -> ControlFlow<Self::Break> {
1080            self.0.binder_stack_mut().push(binder.params.clone());
1081            self.visit_inner(binder)?;
1082            self.0.binder_stack_mut().pop();
1083            Continue(())
1084        }
1085        fn visit_region_binder<T: AstVisitable>(
1086            &mut self,
1087            binder: &mut RegionBinder<T>,
1088        ) -> ControlFlow<Self::Break> {
1089            self.0.binder_stack_mut().push(binder.to_params());
1090            self.visit_inner(binder)?;
1091            self.0.binder_stack_mut().pop();
1092            Continue(())
1093        }
1094    }
1095
1096    /// Visitor wrapper that tracks the current span. See [`VisitWithBinderDepth`] for how to use.
1097    #[repr(transparent)]
1098    pub struct VisitWithSpan<V>(V);
1099
1100    impl<V: VisitorWithSpan> VisitWithSpan<V> {
1101        // Helper
1102        fn wrap(v: &mut V) -> &mut Self {
1103            // SAFETY: `repr(transparent)`
1104            unsafe { std::mem::transmute(v) }
1105        }
1106        pub fn new(v: &mut V) -> &mut VisitWithItem<DontLeakImplDetails<Self>> {
1107            // Use the `WithItem` wrapper to simplify the implementation of this wrapper. We use
1108            // `DontLeakImplDetails` to use the specific `VisitorWithItem` impl we care about
1109            // instead of the one that forwards to the `VisitorWithItem` of the containted `V`.
1110            VisitWithItem::new(DontLeakImplDetails::new(Self::wrap(v)))
1111        }
1112        pub fn inner(&mut self) -> &mut V {
1113            // SAFETY: `repr(transparent)`
1114            unsafe { std::mem::transmute(self) }
1115        }
1116    }
1117
1118    pub trait VisitorWithSpan {
1119        fn current_span(&mut self) -> &mut Span;
1120    }
1121
1122    impl<V: VisitAst + VisitorWithSpan> VisitorWithItem for DontLeakImplDetails<VisitWithSpan<V>> {
1123        fn visit_item(&mut self, item: ItemRef<'_>) -> ControlFlow<Self::Break> {
1124            let old_span = mem::replace(self.0.0.current_span(), item.item_meta().span);
1125            item.drive(self)?;
1126            *self.0.0.current_span() = old_span;
1127            Continue(())
1128        }
1129    }
1130    impl<V: VisitAstMut + VisitorWithSpan> VisitorWithItemMut
1131        for DontLeakImplDetails<VisitWithSpan<V>>
1132    {
1133        fn visit_item(&mut self, mut item: ItemRefMut<'_>) -> ControlFlow<Self::Break> {
1134            let span = item.as_ref().item_meta().span;
1135            let old_span = mem::replace(self.0.0.current_span(), span);
1136            item.drive_mut(self)?;
1137            *self.0.0.current_span() = old_span;
1138            Continue(())
1139        }
1140    }
1141
1142    impl<V: Visitor> Visitor for VisitWithSpan<V> {
1143        type Break = V::Break;
1144    }
1145    impl<V: VisitAst + VisitorWithSpan> VisitWithSpan<V> {
1146        fn visit_inner_track_span<T>(&mut self, x: &T, span: Span) -> ControlFlow<V::Break>
1147        where
1148            T: AstVisitable,
1149            T: for<'s> derive_generic_visitor::Drive<'s, AstVisitableWrapper<Self>>,
1150        {
1151            let old_span = mem::replace(self.0.current_span(), span);
1152            self.visit_inner(x)?;
1153            *self.0.current_span() = old_span;
1154            Continue(())
1155        }
1156    }
1157    impl<V: VisitAstMut + VisitorWithSpan> VisitWithSpan<V> {
1158        fn visit_inner_mut_track_span<T>(&mut self, x: &mut T, span: Span) -> ControlFlow<V::Break>
1159        where
1160            T: AstVisitable,
1161            T: for<'s> derive_generic_visitor::DriveMut<'s, AstVisitableWrapper<Self>>,
1162        {
1163            let old_span = mem::replace(self.0.current_span(), span);
1164            self.visit_inner(x)?;
1165            *self.0.current_span() = old_span;
1166            Continue(())
1167        }
1168    }
1169    impl<V: VisitAst + VisitorWithSpan> VisitAst for VisitWithSpan<V> {
1170        fn visit_inner<T>(&mut self, x: &T) -> ControlFlow<Self::Break>
1171        where
1172            T: AstVisitable,
1173        {
1174            x.drive(self.inner())
1175        }
1176        fn visit_trait_param(&mut self, x: &TraitParam) -> ControlFlow<Self::Break> {
1177            match x.span {
1178                Some(span) => self.visit_inner_track_span(x, span),
1179                None => self.visit_inner(x),
1180            }
1181        }
1182        fn visit_ullbc_statement(&mut self, x: &ullbc_ast::Statement) -> ControlFlow<Self::Break> {
1183            self.visit_inner_track_span(x, x.span)
1184        }
1185        fn visit_ullbc_terminator(
1186            &mut self,
1187            x: &ullbc_ast::Terminator,
1188        ) -> ControlFlow<Self::Break> {
1189            self.visit_inner_track_span(x, x.span)
1190        }
1191        fn visit_llbc_statement(&mut self, x: &llbc_ast::Statement) -> ControlFlow<Self::Break> {
1192            self.visit_inner_track_span(x, x.span)
1193        }
1194        fn visit_llbc_block(&mut self, x: &llbc_ast::Block) -> ControlFlow<Self::Break> {
1195            self.visit_inner_track_span(x, x.span)
1196        }
1197    }
1198    impl<V: VisitAstMut + VisitorWithSpan> VisitAstMut for VisitWithSpan<V> {
1199        fn visit_inner<T>(&mut self, x: &mut T) -> ControlFlow<Self::Break>
1200        where
1201            T: AstVisitable,
1202        {
1203            x.drive_mut(self.inner())
1204        }
1205        fn visit_trait_param(&mut self, x: &mut TraitParam) -> ControlFlow<Self::Break> {
1206            match x.span {
1207                Some(span) => self.visit_inner_mut_track_span(x, span),
1208                None => self.visit_inner(x),
1209            }
1210        }
1211        fn visit_ullbc_statement(
1212            &mut self,
1213            x: &mut ullbc_ast::Statement,
1214        ) -> ControlFlow<Self::Break> {
1215            self.visit_inner_mut_track_span(x, x.span)
1216        }
1217        fn visit_ullbc_terminator(
1218            &mut self,
1219            x: &mut ullbc_ast::Terminator,
1220        ) -> ControlFlow<Self::Break> {
1221            self.visit_inner_mut_track_span(x, x.span)
1222        }
1223        fn visit_llbc_statement(
1224            &mut self,
1225            x: &mut llbc_ast::Statement,
1226        ) -> ControlFlow<Self::Break> {
1227            self.visit_inner_mut_track_span(x, x.span)
1228        }
1229        fn visit_llbc_block(&mut self, x: &mut llbc_ast::Block) -> ControlFlow<Self::Break> {
1230            self.visit_inner_mut_track_span(x, x.span)
1231        }
1232    }
1233
1234    /// Combo impls to be able to use some wrappers together.
1235    impl<V: VisitorWithSpan> VisitorWithSpan for VisitWithBinderStack<V> {
1236        fn current_span(&mut self) -> &mut Span {
1237            self.0.current_span()
1238        }
1239    }
1240    impl<V: VisitorWithSpan> VisitorWithSpan for VisitWithItem<V> {
1241        fn current_span(&mut self) -> &mut Span {
1242            self.0.current_span()
1243        }
1244    }
1245    impl<V: VisitorWithSpan> VisitorWithSpan for DontLeakImplDetails<V> {
1246        fn current_span(&mut self) -> &mut Span {
1247            self.0.current_span()
1248        }
1249    }
1250    impl<V: VisitorWithBinderDepth> VisitorWithBinderDepth for VisitWithItemRef<V> {
1251        fn binder_depth_mut(&mut self) -> &mut DeBruijnId {
1252            self.0.binder_depth_mut()
1253        }
1254    }
1255}