Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions compiler/rustc_type_ir/src/binder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -956,7 +956,7 @@ pub enum BoundVarIndexKind {
/// identified by both a universe, as well as a name residing within that universe. Distinct bound
/// regions/types/consts within the same universe simply have an unknown relationship to one
#[derive_where(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash; I: Interner, T)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, GenericTypeVisitable)]
#[cfg_attr(
feature = "nightly",
derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
Expand Down Expand Up @@ -995,7 +995,7 @@ where
}

#[derive_where(Clone, Copy, PartialEq, Eq, Hash; I: Interner)]
#[derive(Lift_Generic)]
#[derive(Lift_Generic, GenericTypeVisitable)]
#[cfg_attr(
feature = "nightly",
derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
Expand Down Expand Up @@ -1058,7 +1058,7 @@ impl<I: Interner> BoundRegionKind<I> {
}

#[derive_where(Clone, Copy, PartialEq, Eq, Debug, Hash; I: Interner)]
#[derive(Lift_Generic)]
#[derive(Lift_Generic, GenericTypeVisitable)]
#[cfg_attr(
feature = "nightly",
derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
Expand All @@ -1069,7 +1069,7 @@ pub enum BoundTyKind<I: Interner> {
}

#[derive_where(Clone, Copy, PartialEq, Eq, Debug, Hash; I: Interner)]
#[derive(Lift_Generic)]
#[derive(Lift_Generic, GenericTypeVisitable)]
#[cfg_attr(
feature = "nightly",
derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
Expand Down Expand Up @@ -1104,6 +1104,7 @@ impl<I: Interner> BoundVariableKind<I> {
}

#[derive_where(Clone, Copy, PartialEq, Eq, Hash; I: Interner)]
#[derive(GenericTypeVisitable)]
#[cfg_attr(
feature = "nightly",
derive(Encodable_NoContext, HashStable_NoContext, Decodable_NoContext)
Expand Down Expand Up @@ -1164,6 +1165,7 @@ impl<I: Interner> PlaceholderRegion<I> {
}

#[derive_where(Clone, Copy, PartialEq, Eq, Hash; I: Interner)]
#[derive(GenericTypeVisitable)]
#[cfg_attr(
feature = "nightly",
derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
Expand Down Expand Up @@ -1229,6 +1231,7 @@ impl<I: Interner> PlaceholderType<I> {
}

#[derive_where(Clone, Copy, PartialEq, Debug, Eq, Hash; I: Interner)]
#[derive(GenericTypeVisitable)]
#[cfg_attr(
feature = "nightly",
derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_type_ir/src/const_kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ impl<Hcx> HashStable<Hcx> for InferConst {
/// `ValTree` does not have this problem with representation, as it only contains integers or
/// lists of (nested) `ty::Const`s (which may indirectly contain more `ValTree`s).
#[derive_where(Clone, Copy, Debug, Hash, Eq, PartialEq; I: Interner)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, GenericTypeVisitable)]
#[cfg_attr(
feature = "nightly",
derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext)
Expand Down
62 changes: 12 additions & 50 deletions compiler/rustc_type_ir/src/generic_visit.rs
Original file line number Diff line number Diff line change
@@ -1,45 +1,13 @@
//! A visiting traversal mechanism for complex data structures that contain type
//! information.
//! Special visiting used by rust-analyzer only.
//!
//! This is a read-only traversal of the data structure.
//! It is different from `TypeVisitable` in two ways:
//!
//! This traversal has limited flexibility. Only a small number of "types of
//! interest" within the complex data structures can receive custom
//! visitation. These are the ones containing the most important type-related
//! information, such as `Ty`, `Predicate`, `Region`, and `Const`.
//!
//! There are three traits involved in each traversal.
//! - `GenericTypeVisitable`. This is implemented once for many types, including:
//! - Types of interest, for which the methods delegate to the visitor.
//! - All other types, including generic containers like `Vec` and `Option`.
//! It defines a "skeleton" of how they should be visited.
//! - `TypeSuperVisitable`. This is implemented only for recursive types of
//! interest, and defines the visiting "skeleton" for these types. (This
//! excludes `Region` because it is non-recursive, i.e. it never contains
//! other types of interest.)
//! - `CustomizableTypeVisitor`. This is implemented for each visitor. This defines how
//! types of interest are visited.
//!
//! This means each visit is a mixture of (a) generic visiting operations, and (b)
//! custom visit operations that are specific to the visitor.
//! - The `GenericTypeVisitable` impls handle most of the traversal, and call into
//! `CustomizableTypeVisitor` when they encounter a type of interest.
//! - A `CustomizableTypeVisitor` may call into another `GenericTypeVisitable` impl, because some of
//! the types of interest are recursive and can contain other types of interest.
//! - A `CustomizableTypeVisitor` may also call into a `TypeSuperVisitable` impl, because each
//! visitor might provide custom handling only for some types of interest, or
//! only for some variants of each type of interest, and then use default
//! traversal for the remaining cases.
//!
//! For example, if you have `struct S(Ty, U)` where `S: GenericTypeVisitable` and `U:
//! GenericTypeVisitable`, and an instance `s = S(ty, u)`, it would be visited like so:
//! ```text
//! s.generic_visit_with(visitor) calls
//! - ty.generic_visit_with(visitor) calls
//! - visitor.visit_ty(ty) may call
//! - ty.super_generic_visit_with(visitor)
//! - u.generic_visit_with(visitor)
//! ```
//! - The visitor is a generic of the trait and not the method, allowing types to attach
//! special behavior to visitors (as long as they know it; we don't use this capability
//! in rustc crates, but rust-analyzer needs it).
//! - It **must visit** every field. This is why we don't have an attribute like `#[type_visitable(ignore)]`
//! for this visit. The reason for this is soundness: rust-analyzer uses this visit to
//! garbage collect types, so a missing field can mean a use after free

use std::sync::Arc;

Expand All @@ -53,16 +21,6 @@ use thin_vec::ThinVec;
/// To implement this conveniently, use the derive macro located in
/// `rustc_macros`.
pub trait GenericTypeVisitable<V> {
/// The entry point for visiting. To visit a value `t` with a visitor `v`
/// call: `t.generic_visit_with(v)`.
///
/// For most types, this just traverses the value, calling `generic_visit_with` on
/// each field/element.
///
/// For types of interest (such as `Ty`), the implementation of this method
/// that calls a visitor method specifically for that type (such as
/// `V::visit_ty`). This is where control transfers from `GenericTypeVisitable` to
/// `CustomizableTypeVisitor`.
fn generic_visit_with(&self, visitor: &mut V);
}

Expand Down Expand Up @@ -216,6 +174,10 @@ macro_rules! trivial_impls {
};
}

impl<T: ?Sized, V> GenericTypeVisitable<V> for std::marker::PhantomData<T> {
fn generic_visit_with(&self, _visitor: &mut V) {}
}

trivial_impls!(
(),
rustc_ast_ir::Mutability,
Expand Down
Loading