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//! - `TypeVisitable`. 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//! - `TypeVisitor`. 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 `TypeVisitable` impls handle most of the traversal, and call into
26//! `TypeVisitor` when they encounter a type of interest.
27//! - A `TypeVisitor` may call into another `TypeVisitable` impl, because some of
28//! the types of interest are recursive and can contain other types of interest.
29//! - A `TypeVisitor` 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: TypeVisitable` and `U:
35//! TypeVisitable`, and an instance `s = S(ty, u)`, it would be visited like so:
36//! ```text
37//! s.visit_with(visitor) calls
38//! - ty.visit_with(visitor) calls
39//! - visitor.visit_ty(ty) may call
40//! - ty.super_visit_with(visitor)
41//! - u.visit_with(visitor)
42//! ```
4344use std::fmt;
45use std::ops::ControlFlow;
46use std::sync::Arc;
4748pub use rustc_ast_ir::visit::VisitorResult;
49pub use rustc_ast_ir::{try_visit, walk_visitable_list};
50use rustc_index::{Idx, IndexVec};
51use smallvec::SmallVec;
52use thin_vec::ThinVec;
5354use crate::inherent::*;
55use crate::{selfas ty, Interner, TypeFlags};
5657/// This trait is implemented for every type that can be visited,
58/// providing the skeleton of the traversal.
59///
60/// To implement this conveniently, use the derive macro located in
61/// `rustc_macros`.
62pub trait TypeVisitable<I: Interner>: fmt::Debug {
63/// The entry point for visiting. To visit a value `t` with a visitor `v`
64 /// call: `t.visit_with(v)`.
65 ///
66 /// For most types, this just traverses the value, calling `visit_with` on
67 /// each field/element.
68 ///
69 /// For types of interest (such as `Ty`), the implementation of this method
70 /// calls a visitor method specifically for that type (such as
71 /// `V::visit_ty`). This is where control transfers from `TypeVisitable` to
72 /// `TypeVisitor`.
73fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result;
74}
7576// This trait is implemented for types of interest.
77pub trait TypeSuperVisitable<I: Interner>: TypeVisitable<I> {
78/// Provides a default visit for a recursive type of interest. This should
79 /// only be called within `TypeVisitor` methods, when a non-custom
80 /// traversal is desired for the value of the type of interest passed to
81 /// that method. For example, in `MyVisitor::visit_ty(ty)`, it is valid to
82 /// call `ty.super_visit_with(self)`, but any other visiting should be done
83 /// with `xyz.visit_with(self)`.
84fn super_visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result;
85}
8687/// This trait is implemented for every visiting traversal. There is a visit
88/// method defined for every type of interest. Each such method has a default
89/// that recurses into the type's fields in a non-custom fashion.
90pub trait TypeVisitor<I: Interner>: Sized {
91#[cfg(feature = "nightly")]
92type Result: VisitorResult = ();
9394#[cfg(not(feature = "nightly"))]
95type Result: VisitorResult;
9697fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &ty::Binder<I, T>) -> Self::Result {
98t.super_visit_with(self)
99 }
100101fn visit_ty(&mut self, t: I::Ty) -> Self::Result {
102t.super_visit_with(self)
103 }
104105// `Region` is non-recursive so the default region visitor has no
106 // `super_visit_with` method to call.
107fn visit_region(&mut self, r: I::Region) -> Self::Result {
108if let ty::ReError(guar) = r.kind() {
109self.visit_error(guar)
110 } else {
111Self::Result::output()
112 }
113 }
114115fn visit_const(&mut self, c: I::Const) -> Self::Result {
116c.super_visit_with(self)
117 }
118119fn visit_predicate(&mut self, p: I::Predicate) -> Self::Result {
120p.super_visit_with(self)
121 }
122123fn visit_clauses(&mut self, c: I::Clauses) -> Self::Result {
124c.super_visit_with(self)
125 }
126127fn visit_error(&mut self, _guar: I::ErrorGuaranteed) -> Self::Result {
128Self::Result::output()
129 }
130}
131132///////////////////////////////////////////////////////////////////////////
133// Traversal implementations.
134135impl<I: Interner, T: TypeVisitable<I>, U: TypeVisitable<I>> TypeVisitable<I> for (T, U) {
136fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
137match ::rustc_ast_ir::visit::VisitorResult::branch(self.0.visit_with(visitor))
{
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};try_visit!(self.0.visit_with(visitor));
138self.1.visit_with(visitor)
139 }
140}
141142impl<I: Interner, A: TypeVisitable<I>, B: TypeVisitable<I>, C: TypeVisitable<I>> TypeVisitable<I>
143for (A, B, C)
144{
145fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
146match ::rustc_ast_ir::visit::VisitorResult::branch(self.0.visit_with(visitor))
{
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};try_visit!(self.0.visit_with(visitor));
147match ::rustc_ast_ir::visit::VisitorResult::branch(self.1.visit_with(visitor))
{
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};try_visit!(self.1.visit_with(visitor));
148self.2.visit_with(visitor)
149 }
150}
151152impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Option<T> {
153fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
154match self {
155Some(v) => v.visit_with(visitor),
156None => V::Result::output(),
157 }
158 }
159}
160161impl<I: Interner, T: TypeVisitable<I>, E: TypeVisitable<I>> TypeVisitable<I> for Result<T, E> {
162fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
163match self {
164Ok(v) => v.visit_with(visitor),
165Err(e) => e.visit_with(visitor),
166 }
167 }
168}
169170impl<I: Interner, T: TypeVisitable<I> + ?Sized> TypeVisitable<I> for &T {
171fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
172 (**self).visit_with(visitor)
173 }
174}
175176impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Arc<T> {
177fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
178 (**self).visit_with(visitor)
179 }
180}
181182impl<I: Interner, T: TypeVisitable<I> + ?Sized> TypeVisitable<I> for Box<T> {
183fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
184 (**self).visit_with(visitor)
185 }
186}
187188impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Vec<T> {
189fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
190for elem in self.iter() {
match ::rustc_ast_ir::visit::VisitorResult::branch(elem.visit_with(visitor))
{
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};
};walk_visitable_list!(visitor, self.iter());
191 V::Result::output()
192 }
193}
194195impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for ThinVec<T> {
196fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
197for elem in self.iter() {
match ::rustc_ast_ir::visit::VisitorResult::branch(elem.visit_with(visitor))
{
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};
};walk_visitable_list!(visitor, self.iter());
198 V::Result::output()
199 }
200}
201202impl<I: Interner, T: TypeVisitable<I>, const N: usize> TypeVisitable<I> for SmallVec<[T; N]> {
203fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
204for elem in self.iter() {
match ::rustc_ast_ir::visit::VisitorResult::branch(elem.visit_with(visitor))
{
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};
};walk_visitable_list!(visitor, self.iter());
205 V::Result::output()
206 }
207}
208209// `TypeFoldable` isn't impl'd for `&[T]`. It doesn't make sense in the general
210// case, because we can't return a new slice. But note that there are a couple
211// of trivial impls of `TypeFoldable` for specific slice types elsewhere.
212impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for [T] {
213fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
214for elem in self.iter() {
match ::rustc_ast_ir::visit::VisitorResult::branch(elem.visit_with(visitor))
{
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};
};walk_visitable_list!(visitor, self.iter());
215 V::Result::output()
216 }
217}
218219impl<const N: usize, I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for [T; N] {
220fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
221for elem in self.iter() {
match ::rustc_ast_ir::visit::VisitorResult::branch(elem.visit_with(visitor))
{
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};
};walk_visitable_list!(visitor, self.iter());
222 V::Result::output()
223 }
224}
225226impl<I: Interner, T: TypeVisitable<I>, Ix: Idx> TypeVisitable<I> for IndexVec<Ix, T> {
227fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
228for elem in self.iter() {
match ::rustc_ast_ir::visit::VisitorResult::branch(elem.visit_with(visitor))
{
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};
};walk_visitable_list!(visitor, self.iter());
229 V::Result::output()
230 }
231}
232233impl<I: Interner, T: TypeVisitable<I>, S> TypeVisitable<I> for indexmap::IndexSet<T, S> {
234fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
235for elem in self.iter() {
match ::rustc_ast_ir::visit::VisitorResult::branch(elem.visit_with(visitor))
{
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};
};walk_visitable_list!(visitor, self.iter());
236 V::Result::output()
237 }
238}
239240pub trait Flags {
241fn flags(&self) -> TypeFlags;
242fn outer_exclusive_binder(&self) -> ty::DebruijnIndex;
243}
244245pub trait TypeVisitableExt<I: Interner>: TypeVisitable<I> {
246fn has_type_flags(&self, flags: TypeFlags) -> bool;
247248/// Returns `true` if `self` has any late-bound regions that are either
249 /// bound by `binder` or bound by some binder outside of `binder`.
250 /// If `binder` is `ty::INNERMOST`, this indicates whether
251 /// there are any late-bound regions that appear free.
252fn has_vars_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool;
253254/// Returns `true` if this type has any regions that escape `binder` (and
255 /// hence are not bound by it).
256fn has_vars_bound_above(&self, binder: ty::DebruijnIndex) -> bool {
257self.has_vars_bound_at_or_above(binder.shifted_in(1))
258 }
259260/// Returns `true` if this type has regions that are not a part of the
261 /// type. For example, given a `for<'a> fn(&'a i32)` this function returns
262 /// `false`, while given a `fn(&'a i32)` it returns `true`. The latter can
263 /// occur when traversing through the former.
264 ///
265 /// See [`HasEscapingVarsVisitor`] for more information.
266fn has_escaping_bound_vars(&self) -> bool {
267self.has_vars_bound_at_or_above(ty::INNERMOST)
268 }
269270fn has_aliases(&self) -> bool {
271self.has_type_flags(TypeFlags::HAS_ALIAS)
272 }
273274fn has_opaque_types(&self) -> bool {
275self.has_type_flags(TypeFlags::HAS_TY_OPAQUE)
276 }
277278fn has_coroutines(&self) -> bool {
279self.has_type_flags(TypeFlags::HAS_TY_CORO)
280 }
281282fn references_error(&self) -> bool {
283self.has_type_flags(TypeFlags::HAS_ERROR)
284 }
285286fn error_reported(&self) -> Result<(), I::ErrorGuaranteed>;
287288fn non_region_error_reported(&self) -> Result<(), I::ErrorGuaranteed>;
289290fn has_non_region_param(&self) -> bool {
291self.has_type_flags(TypeFlags::HAS_PARAM - TypeFlags::HAS_RE_PARAM)
292 }
293294fn has_regions(&self) -> bool {
295self.has_type_flags(TypeFlags::HAS_REGIONS)
296 }
297298fn has_infer_regions(&self) -> bool {
299self.has_type_flags(TypeFlags::HAS_RE_INFER)
300 }
301302fn has_infer_types(&self) -> bool {
303self.has_type_flags(TypeFlags::HAS_TY_INFER)
304 }
305306fn has_non_region_infer(&self) -> bool {
307self.has_type_flags(TypeFlags::HAS_INFER - TypeFlags::HAS_RE_INFER)
308 }
309310fn has_infer(&self) -> bool {
311self.has_type_flags(TypeFlags::HAS_INFER)
312 }
313314fn has_placeholders(&self) -> bool {
315self.has_type_flags(TypeFlags::HAS_PLACEHOLDER)
316 }
317318fn has_non_region_placeholders(&self) -> bool {
319self.has_type_flags(TypeFlags::HAS_PLACEHOLDER - TypeFlags::HAS_RE_PLACEHOLDER)
320 }
321322fn has_param(&self) -> bool {
323self.has_type_flags(TypeFlags::HAS_PARAM)
324 }
325326/// "Free" regions in this context means that it has any region
327 /// that is not (a) erased or (b) late-bound.
328fn has_free_regions(&self) -> bool {
329self.has_type_flags(TypeFlags::HAS_FREE_REGIONS)
330 }
331332fn has_erased_regions(&self) -> bool {
333self.has_type_flags(TypeFlags::HAS_RE_ERASED)
334 }
335336/// True if there are any un-erased free regions.
337fn has_erasable_regions(&self) -> bool {
338self.has_type_flags(TypeFlags::HAS_FREE_REGIONS)
339 }
340341/// Indicates whether this value references only 'global'
342 /// generic parameters that are the same regardless of what fn we are
343 /// in. This is used for caching.
344fn is_global(&self) -> bool {
345 !self.has_type_flags(TypeFlags::HAS_FREE_LOCAL_NAMES)
346 }
347348/// True if there are any late-bound regions
349fn has_bound_regions(&self) -> bool {
350self.has_type_flags(TypeFlags::HAS_RE_BOUND)
351 }
352/// True if there are any late-bound non-region variables
353fn has_non_region_bound_vars(&self) -> bool {
354self.has_type_flags(TypeFlags::HAS_BOUND_VARS - TypeFlags::HAS_RE_BOUND)
355 }
356/// True if there are any bound variables
357fn has_bound_vars(&self) -> bool {
358self.has_type_flags(TypeFlags::HAS_BOUND_VARS)
359 }
360361/// Indicates whether this value still has parameters/placeholders/inference variables
362 /// which could be replaced later, in a way that would change the results of `impl`
363 /// specialization.
364fn still_further_specializable(&self) -> bool {
365self.has_type_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE)
366 }
367368/// True if a type or const error is reachable
369fn has_non_region_error(&self) -> bool {
370self.has_type_flags(TypeFlags::HAS_NON_REGION_ERROR)
371 }
372373/// True if an alias has `IsRigid::Yes`. Used for skipping normalization.
374fn has_rigid_aliases(&self) -> bool {
375self.has_type_flags(TypeFlags::HAS_RIGID_ALIAS)
376 }
377378/// True if an alias has `IsRigid::No`.
379fn has_non_rigid_aliases(&self) -> bool {
380self.has_type_flags(TypeFlags::HAS_NON_RIGID_ALIAS)
381 }
382}
383384impl<I: Interner, T: TypeVisitable<I>> TypeVisitableExt<I> for T {
385fn has_type_flags(&self, flags: TypeFlags) -> bool {
386self.visit_with(&mut HasTypeFlagsVisitor { flags }) == ControlFlow::Break(FoundFlags)
387 }
388389fn has_vars_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool {
390self.visit_with(&mut HasEscapingVarsVisitor { outer_index: binder })
391 == ControlFlow::Break(FoundEscapingVars)
392 }
393394fn error_reported(&self) -> Result<(), I::ErrorGuaranteed> {
395if self.references_error() {
396if let ControlFlow::Break(guar) = self.visit_with(&mut HasErrorVisitor) {
397Err(guar)
398 } else {
399{
::core::panicking::panic_fmt(format_args!("type flags said there was an error, but now there is not"));
}panic!("type flags said there was an error, but now there is not")400 }
401 } else {
402Ok(())
403 }
404 }
405406fn non_region_error_reported(&self) -> Result<(), I::ErrorGuaranteed> {
407if self.has_non_region_error() {
408if let ControlFlow::Break(guar) = self.visit_with(&mut HasErrorVisitor) {
409Err(guar)
410 } else {
411{
::core::panicking::panic_fmt(format_args!("type flags said there was an non region error, but now there is not"));
}panic!("type flags said there was an non region error, but now there is not")412 }
413 } else {
414Ok(())
415 }
416 }
417}
418419#[derive(#[automatically_derived]
impl ::core::fmt::Debug for FoundFlags {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "FoundFlags")
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for FoundFlags {
#[inline]
fn eq(&self, other: &FoundFlags) -> bool { true }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for FoundFlags {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::marker::Copy for FoundFlags { }Copy, #[automatically_derived]
impl ::core::clone::Clone for FoundFlags {
#[inline]
fn clone(&self) -> FoundFlags { *self }
}Clone)]
420struct FoundFlags;
421422// FIXME: Optimize for checking for infer flags
423struct HasTypeFlagsVisitor {
424 flags: ty::TypeFlags,
425}
426427impl std::fmt::Debugfor HasTypeFlagsVisitor {
428fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
429self.flags.fmt(fmt)
430 }
431}
432433// Note: this visitor traverses values down to the level of
434// `Ty`/`Const`/`Predicate`, but not within those types. This is because the
435// type flags at the outer layer are enough. So it's faster than it first
436// looks, particular for `Ty`/`Predicate` where it's just a field access.
437//
438// N.B. The only case where this isn't totally true is binders, which also
439// add `HAS_BINDER_VARS` flag depending on the *bound variables* that
440// are present, regardless of whether those bound variables are used. This
441// is important for anonymization of binders in `TyCtxt::erase_and_anonymize_regions`. We
442// specifically detect this case in `visit_binder`.
443impl<I: Interner> TypeVisitor<I> for HasTypeFlagsVisitor {
444type Result = ControlFlow<FoundFlags>;
445446fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &ty::Binder<I, T>) -> Self::Result {
447// If we're looking for the HAS_BINDER_VARS flag, check if the
448 // binder has vars. This won't be present in the binder's bound
449 // value, so we need to check here too.
450if self.flags.intersects(TypeFlags::HAS_BINDER_VARS) && !t.bound_vars().is_empty() {
451return ControlFlow::Break(FoundFlags);
452 }
453454t.super_visit_with(self)
455 }
456457#[inline]
458fn visit_ty(&mut self, t: I::Ty) -> Self::Result {
459// Note: no `super_visit_with` call.
460if t.flags().intersects(self.flags) {
461 ControlFlow::Break(FoundFlags)
462 } else {
463 ControlFlow::Continue(())
464 }
465 }
466467#[inline]
468fn visit_region(&mut self, r: I::Region) -> Self::Result {
469// Note: no `super_visit_with` call, as usual for `Region`.
470if r.flags().intersects(self.flags) {
471 ControlFlow::Break(FoundFlags)
472 } else {
473 ControlFlow::Continue(())
474 }
475 }
476477#[inline]
478fn visit_const(&mut self, c: I::Const) -> Self::Result {
479// Note: no `super_visit_with` call.
480if c.flags().intersects(self.flags) {
481 ControlFlow::Break(FoundFlags)
482 } else {
483 ControlFlow::Continue(())
484 }
485 }
486487#[inline]
488fn visit_predicate(&mut self, predicate: I::Predicate) -> Self::Result {
489// Note: no `super_visit_with` call.
490if predicate.flags().intersects(self.flags) {
491 ControlFlow::Break(FoundFlags)
492 } else {
493 ControlFlow::Continue(())
494 }
495 }
496497#[inline]
498fn visit_clauses(&mut self, clauses: I::Clauses) -> Self::Result {
499// Note: no `super_visit_with` call.
500if clauses.flags().intersects(self.flags) {
501 ControlFlow::Break(FoundFlags)
502 } else {
503 ControlFlow::Continue(())
504 }
505 }
506507#[inline]
508fn visit_error(&mut self, _guar: <I as Interner>::ErrorGuaranteed) -> Self::Result {
509if self.flags.intersects(TypeFlags::HAS_ERROR) {
510 ControlFlow::Break(FoundFlags)
511 } else {
512 ControlFlow::Continue(())
513 }
514 }
515}
516517#[derive(#[automatically_derived]
impl ::core::fmt::Debug for FoundEscapingVars {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "FoundEscapingVars")
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for FoundEscapingVars {
#[inline]
fn eq(&self, other: &FoundEscapingVars) -> bool { true }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for FoundEscapingVars {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::marker::Copy for FoundEscapingVars { }Copy, #[automatically_derived]
impl ::core::clone::Clone for FoundEscapingVars {
#[inline]
fn clone(&self) -> FoundEscapingVars { *self }
}Clone)]
518struct FoundEscapingVars;
519520/// An "escaping var" is a bound var whose binder is not part of `t`. A bound var can be a
521/// bound region or a bound type.
522///
523/// So, for example, consider a type like the following, which has two binders:
524///
525/// for<'a> fn(x: for<'b> fn(&'a isize, &'b isize))
526/// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ outer scope
527/// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ inner scope
528///
529/// This type has *bound regions* (`'a`, `'b`), but it does not have escaping regions, because the
530/// binders of both `'a` and `'b` are part of the type itself. However, if we consider the *inner
531/// fn type*, that type has an escaping region: `'a`.
532///
533/// Note that what I'm calling an "escaping var" is often just called a "free var". However,
534/// we already use the term "free var". It refers to the regions or types that we use to represent
535/// bound regions or type params on a fn definition while we are type checking its body.
536///
537/// To clarify, conceptually there is no particular difference between
538/// an "escaping" var and a "free" var. However, there is a big
539/// difference in practice. Basically, when "entering" a binding
540/// level, one is generally required to do some sort of processing to
541/// a bound var, such as replacing it with a fresh/placeholder
542/// var, or making an entry in the environment to represent the
543/// scope to which it is attached, etc. An escaping var represents
544/// a bound var for which this processing has not yet been done.
545struct HasEscapingVarsVisitor {
546/// Anything bound by `outer_index` or "above" is escaping.
547outer_index: ty::DebruijnIndex,
548}
549550impl<I: Interner> TypeVisitor<I> for HasEscapingVarsVisitor {
551type Result = ControlFlow<FoundEscapingVars>;
552553fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &ty::Binder<I, T>) -> Self::Result {
554self.outer_index.shift_in(1);
555let result = t.super_visit_with(self);
556self.outer_index.shift_out(1);
557result558 }
559560#[inline]
561fn visit_ty(&mut self, t: I::Ty) -> Self::Result {
562// If the outer-exclusive-binder is *strictly greater* than
563 // `outer_index`, that means that `t` contains some content
564 // bound at `outer_index` or above (because
565 // `outer_exclusive_binder` is always 1 higher than the
566 // content in `t`). Therefore, `t` has some escaping vars.
567if t.outer_exclusive_binder() > self.outer_index {
568 ControlFlow::Break(FoundEscapingVars)
569 } else {
570 ControlFlow::Continue(())
571 }
572 }
573574#[inline]
575fn visit_region(&mut self, r: I::Region) -> Self::Result {
576// If the region is bound by `outer_index` or anything outside
577 // of outer index, then it escapes the binders we have
578 // visited.
579if r.outer_exclusive_binder() > self.outer_index {
580 ControlFlow::Break(FoundEscapingVars)
581 } else {
582 ControlFlow::Continue(())
583 }
584 }
585586fn visit_const(&mut self, ct: I::Const) -> Self::Result {
587// If the outer-exclusive-binder is *strictly greater* than
588 // `outer_index`, that means that `ct` contains some content
589 // bound at `outer_index` or above (because
590 // `outer_exclusive_binder` is always 1 higher than the
591 // content in `ct`). Therefore, `ct` has some escaping vars.
592if ct.outer_exclusive_binder() > self.outer_index {
593 ControlFlow::Break(FoundEscapingVars)
594 } else {
595 ControlFlow::Continue(())
596 }
597 }
598599#[inline]
600fn visit_predicate(&mut self, predicate: I::Predicate) -> Self::Result {
601if predicate.outer_exclusive_binder() > self.outer_index {
602 ControlFlow::Break(FoundEscapingVars)
603 } else {
604 ControlFlow::Continue(())
605 }
606 }
607608#[inline]
609fn visit_clauses(&mut self, clauses: I::Clauses) -> Self::Result {
610if clauses.outer_exclusive_binder() > self.outer_index {
611 ControlFlow::Break(FoundEscapingVars)
612 } else {
613 ControlFlow::Continue(())
614 }
615 }
616}
617618struct HasErrorVisitor;
619620impl<I: Interner> TypeVisitor<I> for HasErrorVisitor {
621type Result = ControlFlow<I::ErrorGuaranteed>;
622623fn visit_error(&mut self, guar: <I as Interner>::ErrorGuaranteed) -> Self::Result {
624 ControlFlow::Break(guar)
625 }
626}