|
| 1 | +//! A visiting traversal mechanism for complex data structures that contain type |
| 2 | +//! information. |
| 3 | +//! |
| 4 | +//! This is a read-only traversal of the data structure. |
| 5 | +//! |
| 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 | +//! - `CustomizableTypeVisitable`. 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 `CustomizableTypeVisitable` 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 `CustomizableTypeVisitable` 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: CustomizableTypeVisitable` and `U: |
| 35 | +//! CustomizableTypeVisitable`, and an instance `s = S(ty, u)`, it would be visited like so: |
| 36 | +//! ```text |
| 37 | +//! s.customizable_visit_with(visitor) calls |
| 38 | +//! - ty.customizable_visit_with(visitor) calls |
| 39 | +//! - visitor.visit_ty(ty) may call |
| 40 | +//! - ty.super_customizable_visit_with(visitor) |
| 41 | +//! - u.customizable_visit_with(visitor) |
| 42 | +//! ``` |
| 43 | +
|
| 44 | +use std::sync::Arc; |
| 45 | + |
| 46 | +use rustc_index::{Idx, IndexVec}; |
| 47 | +use smallvec::SmallVec; |
| 48 | +use thin_vec::ThinVec; |
| 49 | + |
| 50 | +/// This trait is implemented for every type that can be visited, |
| 51 | +/// providing the skeleton of the traversal. |
| 52 | +/// |
| 53 | +/// To implement this conveniently, use the derive macro located in |
| 54 | +/// `rustc_macros`. |
| 55 | +pub trait CustomizableTypeVisitable<V> { |
| 56 | + /// The entry point for visiting. To visit a value `t` with a visitor `v` |
| 57 | + /// call: `t.customizable_visit_with(v)`. |
| 58 | + /// |
| 59 | + /// For most types, this just traverses the value, calling `customizable_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 `CustomizableTypeVisitable` to |
| 65 | + /// `CustomizableTypeVisitor`. |
| 66 | + fn customizable_visit_with(&self, visitor: &mut V); |
| 67 | +} |
| 68 | + |
| 69 | +/////////////////////////////////////////////////////////////////////////// |
| 70 | +// Traversal implementations. |
| 71 | + |
| 72 | +impl<V, T: ?Sized + CustomizableTypeVisitable<V>> CustomizableTypeVisitable<V> for &T { |
| 73 | + fn customizable_visit_with(&self, visitor: &mut V) { |
| 74 | + T::customizable_visit_with(*self, visitor) |
| 75 | + } |
| 76 | +} |
| 77 | + |
| 78 | +impl<V, T: CustomizableTypeVisitable<V>, U: CustomizableTypeVisitable<V>> |
| 79 | + CustomizableTypeVisitable<V> for (T, U) |
| 80 | +{ |
| 81 | + fn customizable_visit_with(&self, visitor: &mut V) { |
| 82 | + self.0.customizable_visit_with(visitor); |
| 83 | + self.1.customizable_visit_with(visitor); |
| 84 | + } |
| 85 | +} |
| 86 | + |
| 87 | +impl< |
| 88 | + V, |
| 89 | + A: CustomizableTypeVisitable<V>, |
| 90 | + B: CustomizableTypeVisitable<V>, |
| 91 | + C: CustomizableTypeVisitable<V>, |
| 92 | +> CustomizableTypeVisitable<V> for (A, B, C) |
| 93 | +{ |
| 94 | + fn customizable_visit_with(&self, visitor: &mut V) { |
| 95 | + self.0.customizable_visit_with(visitor); |
| 96 | + self.1.customizable_visit_with(visitor); |
| 97 | + self.2.customizable_visit_with(visitor); |
| 98 | + } |
| 99 | +} |
| 100 | + |
| 101 | +impl<V, T: CustomizableTypeVisitable<V>> CustomizableTypeVisitable<V> for Option<T> { |
| 102 | + fn customizable_visit_with(&self, visitor: &mut V) { |
| 103 | + match self { |
| 104 | + Some(v) => v.customizable_visit_with(visitor), |
| 105 | + None => {} |
| 106 | + } |
| 107 | + } |
| 108 | +} |
| 109 | + |
| 110 | +impl<V, T: CustomizableTypeVisitable<V>, E: CustomizableTypeVisitable<V>> |
| 111 | + CustomizableTypeVisitable<V> for Result<T, E> |
| 112 | +{ |
| 113 | + fn customizable_visit_with(&self, visitor: &mut V) { |
| 114 | + match self { |
| 115 | + Ok(v) => v.customizable_visit_with(visitor), |
| 116 | + Err(e) => e.customizable_visit_with(visitor), |
| 117 | + } |
| 118 | + } |
| 119 | +} |
| 120 | + |
| 121 | +impl<V, T: ?Sized + CustomizableTypeVisitable<V>> CustomizableTypeVisitable<V> for Arc<T> { |
| 122 | + fn customizable_visit_with(&self, visitor: &mut V) { |
| 123 | + (**self).customizable_visit_with(visitor) |
| 124 | + } |
| 125 | +} |
| 126 | + |
| 127 | +impl<V, T: ?Sized + CustomizableTypeVisitable<V>> CustomizableTypeVisitable<V> for Box<T> { |
| 128 | + fn customizable_visit_with(&self, visitor: &mut V) { |
| 129 | + (**self).customizable_visit_with(visitor) |
| 130 | + } |
| 131 | +} |
| 132 | + |
| 133 | +impl<V, T: CustomizableTypeVisitable<V>> CustomizableTypeVisitable<V> for Vec<T> { |
| 134 | + fn customizable_visit_with(&self, visitor: &mut V) { |
| 135 | + self.iter().for_each(|it| it.customizable_visit_with(visitor)); |
| 136 | + } |
| 137 | +} |
| 138 | + |
| 139 | +impl<V, T: CustomizableTypeVisitable<V>> CustomizableTypeVisitable<V> for ThinVec<T> { |
| 140 | + fn customizable_visit_with(&self, visitor: &mut V) { |
| 141 | + self.iter().for_each(|it| it.customizable_visit_with(visitor)); |
| 142 | + } |
| 143 | +} |
| 144 | + |
| 145 | +impl<V, T: CustomizableTypeVisitable<V>, const N: usize> CustomizableTypeVisitable<V> |
| 146 | + for SmallVec<[T; N]> |
| 147 | +{ |
| 148 | + fn customizable_visit_with(&self, visitor: &mut V) { |
| 149 | + self.iter().for_each(|it| it.customizable_visit_with(visitor)); |
| 150 | + } |
| 151 | +} |
| 152 | + |
| 153 | +impl<V, T: CustomizableTypeVisitable<V>> CustomizableTypeVisitable<V> for [T] { |
| 154 | + fn customizable_visit_with(&self, visitor: &mut V) { |
| 155 | + self.iter().for_each(|it| it.customizable_visit_with(visitor)); |
| 156 | + } |
| 157 | +} |
| 158 | + |
| 159 | +impl<V, T: CustomizableTypeVisitable<V>, Ix: Idx> CustomizableTypeVisitable<V> for IndexVec<Ix, T> { |
| 160 | + fn customizable_visit_with(&self, visitor: &mut V) { |
| 161 | + self.iter().for_each(|it| it.customizable_visit_with(visitor)); |
| 162 | + } |
| 163 | +} |
| 164 | + |
| 165 | +impl<S, V> CustomizableTypeVisitable<V> for std::hash::BuildHasherDefault<S> { |
| 166 | + fn customizable_visit_with(&self, _visitor: &mut V) {} |
| 167 | +} |
| 168 | + |
| 169 | +#[expect(rustc::default_hash_types, rustc::potential_query_instability)] |
| 170 | +impl< |
| 171 | + Visitor, |
| 172 | + Key: CustomizableTypeVisitable<Visitor>, |
| 173 | + Value: CustomizableTypeVisitable<Visitor>, |
| 174 | + S: CustomizableTypeVisitable<Visitor>, |
| 175 | +> CustomizableTypeVisitable<Visitor> for std::collections::HashMap<Key, Value, S> |
| 176 | +{ |
| 177 | + fn customizable_visit_with(&self, visitor: &mut Visitor) { |
| 178 | + self.iter().for_each(|it| it.customizable_visit_with(visitor)); |
| 179 | + self.hasher().customizable_visit_with(visitor); |
| 180 | + } |
| 181 | +} |
| 182 | + |
| 183 | +#[expect(rustc::default_hash_types, rustc::potential_query_instability)] |
| 184 | +impl<V, T: CustomizableTypeVisitable<V>, S: CustomizableTypeVisitable<V>> |
| 185 | + CustomizableTypeVisitable<V> for std::collections::HashSet<T, S> |
| 186 | +{ |
| 187 | + fn customizable_visit_with(&self, visitor: &mut V) { |
| 188 | + self.iter().for_each(|it| it.customizable_visit_with(visitor)); |
| 189 | + self.hasher().customizable_visit_with(visitor); |
| 190 | + } |
| 191 | +} |
| 192 | + |
| 193 | +impl< |
| 194 | + Visitor, |
| 195 | + Key: CustomizableTypeVisitable<Visitor>, |
| 196 | + Value: CustomizableTypeVisitable<Visitor>, |
| 197 | + S: CustomizableTypeVisitable<Visitor>, |
| 198 | +> CustomizableTypeVisitable<Visitor> for indexmap::IndexMap<Key, Value, S> |
| 199 | +{ |
| 200 | + fn customizable_visit_with(&self, visitor: &mut Visitor) { |
| 201 | + self.iter().for_each(|it| it.customizable_visit_with(visitor)); |
| 202 | + self.hasher().customizable_visit_with(visitor); |
| 203 | + } |
| 204 | +} |
| 205 | + |
| 206 | +impl<V, T: CustomizableTypeVisitable<V>, S: CustomizableTypeVisitable<V>> |
| 207 | + CustomizableTypeVisitable<V> for indexmap::IndexSet<T, S> |
| 208 | +{ |
| 209 | + fn customizable_visit_with(&self, visitor: &mut V) { |
| 210 | + self.iter().for_each(|it| it.customizable_visit_with(visitor)); |
| 211 | + self.hasher().customizable_visit_with(visitor); |
| 212 | + } |
| 213 | +} |
| 214 | + |
| 215 | +macro_rules! trivial_impls { |
| 216 | + ( $($ty:ty),* $(,)? ) => { |
| 217 | + $( |
| 218 | + impl<V> |
| 219 | + CustomizableTypeVisitable<V> for $ty |
| 220 | + { |
| 221 | + fn customizable_visit_with(&self, _visitor: &mut V) {} |
| 222 | + } |
| 223 | + )* |
| 224 | + }; |
| 225 | +} |
| 226 | + |
| 227 | +trivial_impls!( |
| 228 | + (), |
| 229 | + rustc_ast_ir::Mutability, |
| 230 | + bool, |
| 231 | + i8, |
| 232 | + i16, |
| 233 | + i32, |
| 234 | + i64, |
| 235 | + i128, |
| 236 | + isize, |
| 237 | + u8, |
| 238 | + u16, |
| 239 | + u32, |
| 240 | + u64, |
| 241 | + u128, |
| 242 | + usize, |
| 243 | + crate::PredicatePolarity, |
| 244 | + crate::BoundConstness, |
| 245 | + crate::AliasRelationDirection, |
| 246 | + crate::DebruijnIndex, |
| 247 | + crate::solve::Certainty, |
| 248 | + crate::UniverseIndex, |
| 249 | + crate::BoundVar, |
| 250 | + crate::InferTy, |
| 251 | + crate::IntTy, |
| 252 | + crate::UintTy, |
| 253 | + crate::FloatTy, |
| 254 | + crate::InferConst, |
| 255 | + crate::RegionVid, |
| 256 | + rustc_hash::FxBuildHasher, |
| 257 | + crate::TypeFlags, |
| 258 | + crate::solve::GoalSource, |
| 259 | +); |
0 commit comments