]>
git.proxmox.com Git - rustc.git/blob - vendor/chalk-ir/src/visit.rs
1 //! Traits for visiting bits of IR.
5 BoundVar
, Const
, ConstValue
, DebruijnIndex
, DomainGoal
, Goal
, InferenceVar
, Interner
, Lifetime
,
6 LifetimeData
, PlaceholderIndex
, ProgramClause
, Ty
, TyKind
, WhereClause
,
13 pub use visitors
::VisitExt
;
15 /// A "result type" that can be returned from a visitor. Visitors pick
16 /// an appropriate result type depending on what sort of operation they
17 /// are doing. A common choice is `FindAny`, which indicates that the visitor
18 /// is searching for something and that the visitor should stop once it is found.
19 pub trait VisitResult
: Sized
{
20 /// Creates a new visitor result.
23 /// Returns true if this result is "complete" and we can stop visiting any
24 /// further parts of the term. This is used by `FindAny`, for example, to
25 /// stop the search after a match has been found.
26 fn return_early(&self) -> bool
;
28 /// Combines two visitor results.
29 fn combine(self, other
: Self) -> Self;
31 /// Convenience helper for use in writing `Visitor` impls. Returns `self`
32 /// if `return_early()` is true, but otherwise combines `self` with the
33 /// result of invoking `op`.
35 /// If you have a struct with two fields, `foo` and `bar`, you can
36 /// thus write code like
39 /// self.foo.visit_with(visitor, outer_binder)
40 /// .and_then(|| self.bar.visit_with(visitor, outer_binder))
43 /// and `bar` will only be visited if necessary.
44 fn and_then(self, op
: impl FnOnce() -> Self) -> Self {
45 if self.return_early() {
53 /// Unit type for a visitor indicates a "side-effecting" visitor that
54 /// should visit an entire term.
55 impl VisitResult
for () {
58 fn return_early(&self) -> bool
{
61 fn combine(self, _other
: Self) {}
64 /// A "visitor" recursively folds some term -- that is, some bit of IR,
65 /// such as a `Goal`, and computes a value as a result.
68 /// To **apply** a visitor, use the `Visit::visit_with` method, like so
71 /// let result = x.visit_with(&mut visitor, 0);
73 pub trait Visitor
<'i
, I
: Interner
>
77 /// The type of result that this visitor produces.
78 type Result
: VisitResult
;
80 /// Creates a `dyn` value from this visitor. Unfortunately, this
81 /// must be added manually to each impl of visitor; it permits the
82 /// default implements below to create a `&mut dyn Visitor` from
83 /// `Self` without knowing what `Self` is (by invoking this
84 /// method). Effectively, this limits impls of `visitor` to types
85 /// for which we are able to create a dyn value (i.e., not `[T]`
87 fn as_dyn(&mut self) -> &mut dyn Visitor
<'i
, I
, Result
= Self::Result
>;
89 /// Top-level callback: invoked for each `Ty<I>` that is
90 /// encountered when visiting. By default, invokes
91 /// `super_visit_with`, which will in turn invoke the more
92 /// specialized visiting methods below, like `visit_free_var`.
93 fn visit_ty(&mut self, ty
: &Ty
<I
>, outer_binder
: DebruijnIndex
) -> Self::Result
{
94 ty
.super_visit_with(self.as_dyn(), outer_binder
)
97 /// Top-level callback: invoked for each `Lifetime<I>` that is
98 /// encountered when visiting. By default, invokes
99 /// `super_visit_with`, which will in turn invoke the more
100 /// specialized visiting methods below, like `visit_free_var`.
103 lifetime
: &Lifetime
<I
>,
104 outer_binder
: DebruijnIndex
,
106 lifetime
.super_visit_with(self.as_dyn(), outer_binder
)
109 /// Top-level callback: invoked for each `Const<I>` that is
110 /// encountered when visiting. By default, invokes
111 /// `super_visit_with`, which will in turn invoke the more
112 /// specialized visiting methods below, like `visit_free_var`.
113 fn visit_const(&mut self, constant
: &Const
<I
>, outer_binder
: DebruijnIndex
) -> Self::Result
{
114 constant
.super_visit_with(self.as_dyn(), outer_binder
)
117 /// Invoked for every program clause. By default, recursively visits the goals contents.
118 fn visit_program_clause(
120 clause
: &ProgramClause
<I
>,
121 outer_binder
: DebruijnIndex
,
123 clause
.super_visit_with(self.as_dyn(), outer_binder
)
126 /// Invoked for every goal. By default, recursively visits the goals contents.
127 fn visit_goal(&mut self, goal
: &Goal
<I
>, outer_binder
: DebruijnIndex
) -> Self::Result
{
128 goal
.super_visit_with(self.as_dyn(), outer_binder
)
131 /// Invoked for each domain goal.
132 fn visit_domain_goal(
134 domain_goal
: &DomainGoal
<I
>,
135 outer_binder
: DebruijnIndex
,
137 domain_goal
.super_visit_with(self.as_dyn(), outer_binder
)
140 /// If overridden to return true, then visiting will panic if a
141 /// free variable is encountered. This should be done if free
142 /// type/lifetime/const variables are not expected.
143 fn forbid_free_vars(&self) -> bool
{
147 /// Invoked for `BoundVar` instances that are not bound
148 /// within the type being visited over:
149 fn visit_free_var(&mut self, bound_var
: BoundVar
, outer_binder
: DebruijnIndex
) -> Self::Result
{
150 if self.forbid_free_vars() {
152 "unexpected free variable `{:?}` with outer binder {:?}",
153 bound_var
, outer_binder
160 /// If overridden to return true, we will panic when a free
161 /// placeholder type/lifetime is encountered.
162 fn forbid_free_placeholders(&self) -> bool
{
166 /// Invoked for each occurrence of a placeholder type; these are
167 /// used when we instantiate binders universally.
168 fn visit_free_placeholder(
170 universe
: PlaceholderIndex
,
171 _outer_binder
: DebruijnIndex
,
173 if self.forbid_free_placeholders() {
174 panic
!("unexpected placeholder type `{:?}`", universe
)
180 /// Invoked for each where clause.
181 fn visit_where_clause(
183 where_clause
: &WhereClause
<I
>,
184 outer_binder
: DebruijnIndex
,
186 where_clause
.super_visit_with(self.as_dyn(), outer_binder
)
189 /// If overridden to return true, inference variables will trigger
190 /// panics when visited. Used when inference variables are
192 fn forbid_inference_vars(&self) -> bool
{
196 /// Invoked for each occurrence of a inference type; these are
197 /// used when we instantiate binders universally.
198 fn visit_inference_var(
201 _outer_binder
: DebruijnIndex
,
203 if self.forbid_inference_vars() {
204 panic
!("unexpected inference type `{:?}`", var
)
210 /// Gets the visitor's interner.
211 fn interner(&self) -> &'i I
;
214 /// Applies the given `visitor` to a value, producing a visited result
215 /// of type `Visitor::Result`.
216 pub trait Visit
<I
: Interner
>: Debug
{
217 /// Apply the given visitor `visitor` to `self`; `binders` is the
218 /// number of binders that are in scope when beginning the
219 /// visitor. Typically `binders` starts as 0, but is adjusted when
220 /// we encounter `Binders<T>` in the IR or other similar
222 fn visit_with
<'i
, R
: VisitResult
>(
224 visitor
: &mut dyn Visitor
<'i
, I
, Result
= R
>,
225 outer_binder
: DebruijnIndex
,
231 /// For types where "visit" invokes a callback on the `visitor`, the
232 /// `SuperVisit` trait captures the recursive behavior that visits all
233 /// the contents of the type.
234 pub trait SuperVisit
<I
: Interner
>: Visit
<I
> {
235 /// Recursively visits the type contents.
236 fn super_visit_with
<'i
, R
: VisitResult
>(
238 visitor
: &mut dyn Visitor
<'i
, I
, Result
= R
>,
239 outer_binder
: DebruijnIndex
,
245 /// "visiting" a type invokes the `visit_ty` method on the visitor; this
246 /// usually (in turn) invokes `super_visit_ty` to visit the individual
248 impl<I
: Interner
> Visit
<I
> for Ty
<I
> {
249 fn visit_with
<'i
, R
: VisitResult
>(
251 visitor
: &mut dyn Visitor
<'i
, I
, Result
= R
>,
252 outer_binder
: DebruijnIndex
,
257 visitor
.visit_ty(self, outer_binder
)
261 /// "Super visit" for a type invokes te more detailed callbacks on the type
262 impl<I
> SuperVisit
<I
> for Ty
<I
>
266 fn super_visit_with
<'i
, R
: VisitResult
>(
268 visitor
: &mut dyn Visitor
<'i
, I
, Result
= R
>,
269 outer_binder
: DebruijnIndex
,
274 let interner
= visitor
.interner();
275 match self.kind(interner
) {
276 TyKind
::BoundVar(bound_var
) => {
277 if let Some(_
) = bound_var
.shifted_out_to(outer_binder
) {
278 visitor
.visit_free_var(*bound_var
, outer_binder
)
283 TyKind
::Dyn(clauses
) => clauses
.visit_with(visitor
, outer_binder
),
284 TyKind
::InferenceVar(var
, _
) => visitor
.visit_inference_var(*var
, outer_binder
),
285 TyKind
::Placeholder(ui
) => visitor
.visit_free_placeholder(*ui
, outer_binder
),
286 TyKind
::Alias(proj
) => proj
.visit_with(visitor
, outer_binder
),
287 TyKind
::Function(fun
) => fun
.visit_with(visitor
, outer_binder
),
288 TyKind
::Adt(_id
, substitution
) => substitution
.visit_with(visitor
, outer_binder
),
289 TyKind
::AssociatedType(_assoc_ty
, substitution
) => {
290 substitution
.visit_with(visitor
, outer_binder
)
292 TyKind
::Scalar(scalar
) => scalar
.visit_with(visitor
, outer_binder
),
293 TyKind
::Str
=> R
::new(),
294 TyKind
::Tuple(arity
, substitution
) => arity
295 .visit_with(visitor
, outer_binder
)
296 .combine(substitution
.visit_with(visitor
, outer_binder
)),
297 TyKind
::OpaqueType(opaque_ty
, substitution
) => opaque_ty
298 .visit_with(visitor
, outer_binder
)
299 .combine(substitution
.visit_with(visitor
, outer_binder
)),
300 TyKind
::Slice(substitution
) => substitution
.visit_with(visitor
, outer_binder
),
301 TyKind
::FnDef(fn_def
, substitution
) => fn_def
302 .visit_with(visitor
, outer_binder
)
303 .combine(substitution
.visit_with(visitor
, outer_binder
)),
304 TyKind
::Ref(mutability
, lifetime
, ty
) => {
305 mutability
.visit_with(visitor
, outer_binder
).combine(
307 .visit_with(visitor
, outer_binder
)
308 .combine(ty
.visit_with(visitor
, outer_binder
)),
311 TyKind
::Raw(mutability
, ty
) => mutability
312 .visit_with(visitor
, outer_binder
)
313 .combine(ty
.visit_with(visitor
, outer_binder
)),
314 TyKind
::Never
=> R
::new(),
315 TyKind
::Array(ty
, const_
) => ty
316 .visit_with(visitor
, outer_binder
)
317 .combine(const_
.visit_with(visitor
, outer_binder
)),
318 TyKind
::Closure(id
, substitution
) => id
319 .visit_with(visitor
, outer_binder
)
320 .combine(substitution
.visit_with(visitor
, outer_binder
)),
321 TyKind
::Generator(generator
, substitution
) => generator
322 .visit_with(visitor
, outer_binder
)
323 .combine(substitution
.visit_with(visitor
, outer_binder
)),
324 TyKind
::GeneratorWitness(witness
, substitution
) => witness
325 .visit_with(visitor
, outer_binder
)
326 .combine(substitution
.visit_with(visitor
, outer_binder
)),
327 TyKind
::Foreign(foreign_ty
) => foreign_ty
.visit_with(visitor
, outer_binder
),
328 TyKind
::Error
=> R
::new(),
333 impl<I
: Interner
> Visit
<I
> for Lifetime
<I
> {
334 fn visit_with
<'i
, R
: VisitResult
>(
336 visitor
: &mut dyn Visitor
<'i
, I
, Result
= R
>,
337 outer_binder
: DebruijnIndex
,
342 visitor
.visit_lifetime(self, outer_binder
)
346 impl<I
: Interner
> SuperVisit
<I
> for Lifetime
<I
> {
347 fn super_visit_with
<'i
, R
: VisitResult
>(
349 visitor
: &mut dyn Visitor
<'i
, I
, Result
= R
>,
350 outer_binder
: DebruijnIndex
,
355 let interner
= visitor
.interner();
356 match self.data(interner
) {
357 LifetimeData
::BoundVar(bound_var
) => {
358 if let Some(_
) = bound_var
.shifted_out_to(outer_binder
) {
359 visitor
.visit_free_var(*bound_var
, outer_binder
)
364 LifetimeData
::InferenceVar(var
) => visitor
.visit_inference_var(*var
, outer_binder
),
365 LifetimeData
::Placeholder(universe
) => {
366 visitor
.visit_free_placeholder(*universe
, outer_binder
)
368 LifetimeData
::Static
=> R
::new(),
369 LifetimeData
::Phantom(..) => unreachable
!(),
374 impl<I
: Interner
> Visit
<I
> for Const
<I
> {
375 fn visit_with
<'i
, R
: VisitResult
>(
377 visitor
: &mut dyn Visitor
<'i
, I
, Result
= R
>,
378 outer_binder
: DebruijnIndex
,
383 visitor
.visit_const(self, outer_binder
)
387 impl<I
: Interner
> SuperVisit
<I
> for Const
<I
> {
388 fn super_visit_with
<'i
, R
: VisitResult
>(
390 visitor
: &mut dyn Visitor
<'i
, I
, Result
= R
>,
391 outer_binder
: DebruijnIndex
,
396 let interner
= visitor
.interner();
397 match &self.data(interner
).value
{
398 ConstValue
::BoundVar(bound_var
) => {
399 if let Some(_
) = bound_var
.shifted_out_to(outer_binder
) {
400 visitor
.visit_free_var(*bound_var
, outer_binder
)
405 ConstValue
::InferenceVar(var
) => visitor
.visit_inference_var(*var
, outer_binder
),
406 ConstValue
::Placeholder(universe
) => {
407 visitor
.visit_free_placeholder(*universe
, outer_binder
)
409 ConstValue
::Concrete(_
) => R
::new(),
414 impl<I
: Interner
> Visit
<I
> for Goal
<I
> {
415 fn visit_with
<'i
, R
: VisitResult
>(
417 visitor
: &mut dyn Visitor
<'i
, I
, Result
= R
>,
418 outer_binder
: DebruijnIndex
,
423 visitor
.visit_goal(self, outer_binder
)
427 impl<I
: Interner
> SuperVisit
<I
> for Goal
<I
> {
428 fn super_visit_with
<'i
, R
: VisitResult
>(
430 visitor
: &mut dyn Visitor
<'i
, I
, Result
= R
>,
431 outer_binder
: DebruijnIndex
,
436 let interner
= visitor
.interner();
437 self.data(interner
).visit_with(visitor
, outer_binder
)
441 impl<I
: Interner
> Visit
<I
> for ProgramClause
<I
> {
442 fn visit_with
<'i
, R
: VisitResult
>(
444 visitor
: &mut dyn Visitor
<'i
, I
, Result
= R
>,
445 outer_binder
: DebruijnIndex
,
450 visitor
.visit_program_clause(self, outer_binder
)
454 impl<I
: Interner
> Visit
<I
> for WhereClause
<I
> {
455 fn visit_with
<'i
, R
: VisitResult
>(
457 visitor
: &mut dyn Visitor
<'i
, I
, Result
= R
>,
458 outer_binder
: DebruijnIndex
,
463 visitor
.visit_where_clause(self, outer_binder
)
467 impl<I
: Interner
> Visit
<I
> for DomainGoal
<I
> {
468 fn visit_with
<'i
, R
: VisitResult
>(
470 visitor
: &mut dyn Visitor
<'i
, I
, Result
= R
>,
471 outer_binder
: DebruijnIndex
,
476 visitor
.visit_domain_goal(self, outer_binder
)