diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:43 +0000 |
commit | 3e3e70d529d8c7d7c4d7bc4fefc9f109393b9245 (patch) | |
tree | daf049b282ab10e8c3d03e409b3cd84ff3f7690c /compiler/rustc_middle/src/ty/visit.rs | |
parent | Adding debian version 1.68.2+dfsg1-1. (diff) | |
download | rustc-3e3e70d529d8c7d7c4d7bc4fefc9f109393b9245.tar.xz rustc-3e3e70d529d8c7d7c4d7bc4fefc9f109393b9245.zip |
Merging upstream version 1.69.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_middle/src/ty/visit.rs')
-rw-r--r-- | compiler/rustc_middle/src/ty/visit.rs | 135 |
1 files changed, 22 insertions, 113 deletions
diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index bee3cc4d7..6814cadb9 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -1,69 +1,13 @@ -//! A visiting traversal mechanism for complex data structures that contain type -//! information. -//! -//! This is a read-only traversal of the data structure. -//! -//! 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 groups of traits involved in each traversal. -//! - `TypeVisitable`. 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 each type of interest, -//! and defines the visiting "skeleton" for these types. -//! - `TypeVisitor`. 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 `TypeVisitable` impls handle most of the traversal, and call into -//! `TypeVisitor` when they encounter a type of interest. -//! - A `TypeVisitor` may call into another `TypeVisitable` impl, because some of -//! the types of interest are recursive and can contain other types of interest. -//! - A `TypeVisitor` 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: TypeVisitable` and `U: -//! TypeVisitable`, and an instance `s = S(ty, u)`, it would be visited like so: -//! ```text -//! s.visit_with(visitor) calls -//! - ty.visit_with(visitor) calls -//! - visitor.visit_ty(ty) may call -//! - ty.super_visit_with(visitor) -//! - u.visit_with(visitor) -//! ``` use crate::ty::{self, flags::FlagComputation, Binder, Ty, TyCtxt, TypeFlags}; use rustc_errors::ErrorGuaranteed; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sso::SsoHashSet; -use std::fmt; use std::ops::ControlFlow; -/// This trait is implemented for every type that can be visited, -/// providing the skeleton of the traversal. -/// -/// To implement this conveniently, use the derive macro located in -/// `rustc_macros`. -pub trait TypeVisitable<'tcx>: fmt::Debug + Clone { - /// The entry point for visiting. To visit a value `t` with a visitor `v` - /// call: `t.visit_with(v)`. - /// - /// For most types, this just traverses the value, calling `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 `TypeFoldable` to - /// `TypeVisitor`. - fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy>; +pub use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; +pub trait TypeVisitableExt<'tcx>: TypeVisitable<TyCtxt<'tcx>> { /// Returns `true` if `self` has any late-bound regions that are either /// bound by `binder` or bound by some binder outside of `binder`. /// If `binder` is `ty::INNERMOST`, this indicates whether @@ -100,6 +44,9 @@ pub trait TypeVisitable<'tcx>: fmt::Debug + Clone { fn has_opaque_types(&self) -> bool { self.has_type_flags(TypeFlags::HAS_TY_OPAQUE) } + fn has_generators(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_TY_GENERATOR) + } fn references_error(&self) -> bool { self.has_type_flags(TypeFlags::HAS_ERROR) } @@ -182,45 +129,7 @@ pub trait TypeVisitable<'tcx>: fmt::Debug + Clone { } } -pub trait TypeSuperVisitable<'tcx>: TypeVisitable<'tcx> { - /// Provides a default visit for a type of interest. This should only be - /// called within `TypeVisitor` methods, when a non-custom traversal is - /// desired for the value of the type of interest passed to that method. - /// For example, in `MyVisitor::visit_ty(ty)`, it is valid to call - /// `ty.super_visit_with(self)`, but any other visiting should be done - /// with `xyz.visit_with(self)`. - fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy>; -} - -/// This trait is implemented for every visiting traversal. There is a visit -/// method defined for every type of interest. Each such method has a default -/// that recurses into the type's fields in a non-custom fashion. -pub trait TypeVisitor<'tcx>: Sized { - type BreakTy = !; - - fn visit_binder<T: TypeVisitable<'tcx>>( - &mut self, - t: &Binder<'tcx, T>, - ) -> ControlFlow<Self::BreakTy> { - t.super_visit_with(self) - } - - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { - t.super_visit_with(self) - } - - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { - r.super_visit_with(self) - } - - fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { - c.super_visit_with(self) - } - - fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> { - p.super_visit_with(self) - } -} +impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>>> TypeVisitableExt<'tcx> for T {} /////////////////////////////////////////////////////////////////////////// // Region folder @@ -229,7 +138,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Invoke `callback` on every region appearing free in `value`. pub fn for_each_free_region( self, - value: &impl TypeVisitable<'tcx>, + value: &impl TypeVisitable<TyCtxt<'tcx>>, mut callback: impl FnMut(ty::Region<'tcx>), ) { self.any_free_region_meets(value, |r| { @@ -241,7 +150,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Returns `true` if `callback` returns true for every region appearing free in `value`. pub fn all_free_regions_meet( self, - value: &impl TypeVisitable<'tcx>, + value: &impl TypeVisitable<TyCtxt<'tcx>>, mut callback: impl FnMut(ty::Region<'tcx>) -> bool, ) -> bool { !self.any_free_region_meets(value, |r| !callback(r)) @@ -250,7 +159,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Returns `true` if `callback` returns true for some region appearing free in `value`. pub fn any_free_region_meets( self, - value: &impl TypeVisitable<'tcx>, + value: &impl TypeVisitable<TyCtxt<'tcx>>, callback: impl FnMut(ty::Region<'tcx>) -> bool, ) -> bool { struct RegionVisitor<F> { @@ -275,13 +184,13 @@ impl<'tcx> TyCtxt<'tcx> { callback: F, } - impl<'tcx, F> TypeVisitor<'tcx> for RegionVisitor<F> + impl<'tcx, F> TypeVisitor<TyCtxt<'tcx>> for RegionVisitor<F> where F: FnMut(ty::Region<'tcx>) -> bool, { type BreakTy = (); - fn visit_binder<T: TypeVisitable<'tcx>>( + fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>( &mut self, t: &Binder<'tcx, T>, ) -> ControlFlow<Self::BreakTy> { @@ -328,7 +237,7 @@ impl<'tcx> TyCtxt<'tcx> { value: &Binder<'tcx, T>, ) -> FxHashSet<ty::BoundRegionKind> where - T: TypeVisitable<'tcx>, + T: TypeVisitable<TyCtxt<'tcx>>, { self.collect_late_bound_regions(value, true) } @@ -339,7 +248,7 @@ impl<'tcx> TyCtxt<'tcx> { value: &Binder<'tcx, T>, ) -> FxHashSet<ty::BoundRegionKind> where - T: TypeVisitable<'tcx>, + T: TypeVisitable<TyCtxt<'tcx>>, { self.collect_late_bound_regions(value, false) } @@ -350,7 +259,7 @@ impl<'tcx> TyCtxt<'tcx> { just_constraint: bool, ) -> FxHashSet<ty::BoundRegionKind> where - T: TypeVisitable<'tcx>, + T: TypeVisitable<TyCtxt<'tcx>>, { let mut collector = LateBoundRegionsCollector::new(just_constraint); let result = value.as_ref().skip_binder().visit_with(&mut collector); @@ -377,10 +286,10 @@ impl<'tcx> ValidateBoundVars<'tcx> { } } -impl<'tcx> TypeVisitor<'tcx> for ValidateBoundVars<'tcx> { +impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ValidateBoundVars<'tcx> { type BreakTy = (); - fn visit_binder<T: TypeVisitable<'tcx>>( + fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>( &mut self, t: &Binder<'tcx, T>, ) -> ControlFlow<Self::BreakTy> { @@ -489,10 +398,10 @@ struct HasEscapingVarsVisitor { outer_index: ty::DebruijnIndex, } -impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor { +impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasEscapingVarsVisitor { type BreakTy = FoundEscapingVars; - fn visit_binder<T: TypeVisitable<'tcx>>( + fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>( &mut self, t: &Binder<'tcx, T>, ) -> ControlFlow<Self::BreakTy> { @@ -566,7 +475,7 @@ impl std::fmt::Debug for HasTypeFlagsVisitor { } } -impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor { +impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasTypeFlagsVisitor { type BreakTy = FoundFlags; #[inline] @@ -636,8 +545,8 @@ impl LateBoundRegionsCollector { } } -impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector { - fn visit_binder<T: TypeVisitable<'tcx>>( +impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for LateBoundRegionsCollector { + fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>( &mut self, t: &Binder<'tcx, T>, ) -> ControlFlow<Self::BreakTy> { @@ -698,7 +607,7 @@ impl MaxUniverse { } } -impl<'tcx> TypeVisitor<'tcx> for MaxUniverse { +impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MaxUniverse { fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { if let ty::Placeholder(placeholder) = t.kind() { self.max_universe = ty::UniverseIndex::from_u32( |