Skip to main content

rustc_type_ir/
generic_visit.rs

1//! Special visiting used by rust-analyzer only.
2//!
3//! It is different from `TypeVisitable` in two ways:
4//!
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
11
12use std::sync::Arc;
13
14use rustc_index::{Idx, IndexVec};
15use smallvec::SmallVec;
16use thin_vec::ThinVec;
17
18use crate::Interner;
19
20/// This trait is implemented for every type that can be visited,
21/// providing the skeleton of the traversal.
22///
23/// ## Safety
24///
25/// A manual implementation **must visit** every field.
26///
27/// Therefore, it is advised to instead derive this using the derive
28/// macro located in `rustc_macros`.
29pub unsafe trait GenericTypeVisitable<V> {
30    fn generic_visit_with(&self, visitor: &mut V);
31}
32
33///////////////////////////////////////////////////////////////////////////
34// Traversal implementations.
35
36unsafe impl<V, T: ?Sized + GenericTypeVisitable<V>> GenericTypeVisitable<V> for &T {
37    fn generic_visit_with(&self, visitor: &mut V) {
38        T::generic_visit_with(*self, visitor)
39    }
40}
41
42unsafe impl<V, T: GenericTypeVisitable<V>, U: GenericTypeVisitable<V>> GenericTypeVisitable<V>
43    for (T, U)
44{
45    fn generic_visit_with(&self, visitor: &mut V) {
46        self.0.generic_visit_with(visitor);
47        self.1.generic_visit_with(visitor);
48    }
49}
50
51unsafe impl<V, A: GenericTypeVisitable<V>, B: GenericTypeVisitable<V>, C: GenericTypeVisitable<V>>
52    GenericTypeVisitable<V> for (A, B, C)
53{
54    fn generic_visit_with(&self, visitor: &mut V) {
55        self.0.generic_visit_with(visitor);
56        self.1.generic_visit_with(visitor);
57        self.2.generic_visit_with(visitor);
58    }
59}
60
61unsafe impl<V, T: GenericTypeVisitable<V>> GenericTypeVisitable<V> for Option<T> {
62    fn generic_visit_with(&self, visitor: &mut V) {
63        match self {
64            Some(v) => v.generic_visit_with(visitor),
65            None => {}
66        }
67    }
68}
69
70unsafe impl<V, T: GenericTypeVisitable<V>, E: GenericTypeVisitable<V>> GenericTypeVisitable<V>
71    for Result<T, E>
72{
73    fn generic_visit_with(&self, visitor: &mut V) {
74        match self {
75            Ok(v) => v.generic_visit_with(visitor),
76            Err(e) => e.generic_visit_with(visitor),
77        }
78    }
79}
80
81unsafe impl<V, T: ?Sized + GenericTypeVisitable<V>> GenericTypeVisitable<V> for Arc<T> {
82    fn generic_visit_with(&self, visitor: &mut V) {
83        (**self).generic_visit_with(visitor)
84    }
85}
86
87unsafe impl<V, T: ?Sized + GenericTypeVisitable<V>> GenericTypeVisitable<V> for Box<T> {
88    fn generic_visit_with(&self, visitor: &mut V) {
89        (**self).generic_visit_with(visitor)
90    }
91}
92
93unsafe impl<V, T: GenericTypeVisitable<V>> GenericTypeVisitable<V> for Vec<T> {
94    fn generic_visit_with(&self, visitor: &mut V) {
95        self.iter().for_each(|it| it.generic_visit_with(visitor));
96    }
97}
98
99unsafe impl<V, T: GenericTypeVisitable<V>> GenericTypeVisitable<V> for ThinVec<T> {
100    fn generic_visit_with(&self, visitor: &mut V) {
101        self.iter().for_each(|it| it.generic_visit_with(visitor));
102    }
103}
104
105unsafe impl<V, T: GenericTypeVisitable<V>, const N: usize> GenericTypeVisitable<V>
106    for SmallVec<[T; N]>
107{
108    fn generic_visit_with(&self, visitor: &mut V) {
109        self.iter().for_each(|it| it.generic_visit_with(visitor));
110    }
111}
112
113unsafe impl<V, T: GenericTypeVisitable<V>> GenericTypeVisitable<V> for [T] {
114    fn generic_visit_with(&self, visitor: &mut V) {
115        self.iter().for_each(|it| it.generic_visit_with(visitor));
116    }
117}
118
119unsafe impl<V, T: GenericTypeVisitable<V>, Ix: Idx> GenericTypeVisitable<V> for IndexVec<Ix, T> {
120    fn generic_visit_with(&self, visitor: &mut V) {
121        self.iter().for_each(|it| it.generic_visit_with(visitor));
122    }
123}
124
125unsafe impl<S, V> GenericTypeVisitable<V> for std::hash::BuildHasherDefault<S> {
126    fn generic_visit_with(&self, _visitor: &mut V) {}
127}
128
129#[expect(rustc::default_hash_types, rustc::potential_query_instability)]
130unsafe impl<
131    Visitor,
132    Key: GenericTypeVisitable<Visitor>,
133    Value: GenericTypeVisitable<Visitor>,
134    S: GenericTypeVisitable<Visitor>,
135> GenericTypeVisitable<Visitor> for std::collections::HashMap<Key, Value, S>
136{
137    fn generic_visit_with(&self, visitor: &mut Visitor) {
138        self.iter().for_each(|it| it.generic_visit_with(visitor));
139        self.hasher().generic_visit_with(visitor);
140    }
141}
142
143#[expect(rustc::default_hash_types, rustc::potential_query_instability)]
144unsafe impl<V, T: GenericTypeVisitable<V>, S: GenericTypeVisitable<V>> GenericTypeVisitable<V>
145    for std::collections::HashSet<T, S>
146{
147    fn generic_visit_with(&self, visitor: &mut V) {
148        self.iter().for_each(|it| it.generic_visit_with(visitor));
149        self.hasher().generic_visit_with(visitor);
150    }
151}
152
153unsafe impl<
154    Visitor,
155    Key: GenericTypeVisitable<Visitor>,
156    Value: GenericTypeVisitable<Visitor>,
157    S: GenericTypeVisitable<Visitor>,
158> GenericTypeVisitable<Visitor> for indexmap::IndexMap<Key, Value, S>
159{
160    fn generic_visit_with(&self, visitor: &mut Visitor) {
161        self.iter().for_each(|it| it.generic_visit_with(visitor));
162        self.hasher().generic_visit_with(visitor);
163    }
164}
165
166unsafe impl<V, T: GenericTypeVisitable<V>, S: GenericTypeVisitable<V>> GenericTypeVisitable<V>
167    for indexmap::IndexSet<T, S>
168{
169    fn generic_visit_with(&self, visitor: &mut V) {
170        self.iter().for_each(|it| it.generic_visit_with(visitor));
171        self.hasher().generic_visit_with(visitor);
172    }
173}
174
175macro_rules! trivial_impls {
176    ( $($ty:ty),* $(,)? ) => {
177        $(
178            unsafe impl<V>
179                GenericTypeVisitable<V> for $ty
180            {
181                fn generic_visit_with(&self, _visitor: &mut V) {}
182            }
183        )*
184    };
185}
186
187unsafe impl<T: ?Sized, V> GenericTypeVisitable<V> for std::marker::PhantomData<T> {
188    fn generic_visit_with(&self, _visitor: &mut V) {}
189}
190
191unsafe impl<V> GenericTypeVisitable<V> for rustc_abi::ExternAbi {
    fn generic_visit_with(&self, _visitor: &mut V) {}
}trivial_impls!(
192    (),
193    rustc_ast_ir::Mutability,
194    bool,
195    i8,
196    i16,
197    i32,
198    i64,
199    i128,
200    isize,
201    u8,
202    u16,
203    u32,
204    u64,
205    u128,
206    usize,
207    crate::ClausePolarity,
208    crate::BoundConstness,
209    crate::DebruijnIndex,
210    crate::solve::Certainty,
211    crate::UniverseIndex,
212    crate::BoundVar,
213    crate::InferTy,
214    crate::IntTy,
215    crate::UintTy,
216    crate::FloatTy,
217    crate::InferConst,
218    crate::RegionVid,
219    rustc_hash::FxBuildHasher,
220    crate::TypeFlags,
221    crate::solve::GoalSource,
222    crate::solve::VisibleForLeakCheck,
223    rustc_abi::ExternAbi,
224);
225
226// SAFETY: `FnSigKind` is a packed representation, therefore visiting its fields doesn't make sense
227unsafe impl<I: Interner, V> GenericTypeVisitable<V> for crate::FnSigKind<I> {
228    fn generic_visit_with(&self, _visitor: &mut V) {}
229}