1- //! A visiting traversal mechanism for complex data structures that contain type
2- //! information.
1+ //! Special visiting used by rust-analyzer only.
32//!
4- //! This is a read-only traversal of the data structure.
3+ //! It is different from `TypeVisitable` in two ways:
54//!
6- //! This traversal has limited flexibility. Only a small number of "types of
7- //! interest" within the complex data structures can receive custom
8- //! visitation. These are the ones containing the most important type-related
9- //! information, such as `Ty`, `Predicate`, `Region`, and `Const`.
10- //!
11- //! There are three traits involved in each traversal.
12- //! - `GenericTypeVisitable`. This is implemented once for many types, including:
13- //! - Types of interest, for which the methods delegate to the visitor.
14- //! - All other types, including generic containers like `Vec` and `Option`.
15- //! It defines a "skeleton" of how they should be visited.
16- //! - `TypeSuperVisitable`. This is implemented only for recursive types of
17- //! interest, and defines the visiting "skeleton" for these types. (This
18- //! excludes `Region` because it is non-recursive, i.e. it never contains
19- //! other types of interest.)
20- //! - `CustomizableTypeVisitor`. This is implemented for each visitor. This defines how
21- //! types of interest are visited.
22- //!
23- //! This means each visit is a mixture of (a) generic visiting operations, and (b)
24- //! custom visit operations that are specific to the visitor.
25- //! - The `GenericTypeVisitable` impls handle most of the traversal, and call into
26- //! `CustomizableTypeVisitor` when they encounter a type of interest.
27- //! - A `CustomizableTypeVisitor` may call into another `GenericTypeVisitable` impl, because some of
28- //! the types of interest are recursive and can contain other types of interest.
29- //! - A `CustomizableTypeVisitor` may also call into a `TypeSuperVisitable` impl, because each
30- //! visitor might provide custom handling only for some types of interest, or
31- //! only for some variants of each type of interest, and then use default
32- //! traversal for the remaining cases.
33- //!
34- //! For example, if you have `struct S(Ty, U)` where `S: GenericTypeVisitable` and `U:
35- //! GenericTypeVisitable`, and an instance `s = S(ty, u)`, it would be visited like so:
36- //! ```text
37- //! s.generic_visit_with(visitor) calls
38- //! - ty.generic_visit_with(visitor) calls
39- //! - visitor.visit_ty(ty) may call
40- //! - ty.super_generic_visit_with(visitor)
41- //! - u.generic_visit_with(visitor)
42- //! ```
5+ //! - The visitor is a generic of the trait and not the method, allowing types to attach
6+ //! special behavior to visitors (as long as they know it; we don't use this capability
7+ //! in rustc crates, but rust-analyzer needs it).
8+ //! - It **must visit** every field. This is why we don't have an attribute like `#[type_visitable(ignore)]`
9+ //! for this visit. The reason for this is soundness: rust-analyzer uses this visit to
10+ //! garbage collect types, so a missing field can mean a use after free
4311
4412use std:: sync:: Arc ;
4513
@@ -53,16 +21,6 @@ use thin_vec::ThinVec;
5321/// To implement this conveniently, use the derive macro located in
5422/// `rustc_macros`.
5523pub trait GenericTypeVisitable < V > {
56- /// The entry point for visiting. To visit a value `t` with a visitor `v`
57- /// call: `t.generic_visit_with(v)`.
58- ///
59- /// For most types, this just traverses the value, calling `generic_visit_with` on
60- /// each field/element.
61- ///
62- /// For types of interest (such as `Ty`), the implementation of this method
63- /// that calls a visitor method specifically for that type (such as
64- /// `V::visit_ty`). This is where control transfers from `GenericTypeVisitable` to
65- /// `CustomizableTypeVisitor`.
6624 fn generic_visit_with ( & self , visitor : & mut V ) ;
6725}
6826
@@ -216,6 +174,10 @@ macro_rules! trivial_impls {
216174 } ;
217175}
218176
177+ impl < T : ?Sized , V > GenericTypeVisitable < V > for std:: marker:: PhantomData < T > {
178+ fn generic_visit_with ( & self , _visitor : & mut V ) { }
179+ }
180+
219181trivial_impls ! (
220182 ( ) ,
221183 rustc_ast_ir:: Mutability ,
0 commit comments