]>
Commit | Line | Data |
---|---|---|
f9f354fc XL |
1 | //! Traits for visiting bits of IR. |
2 | use std::fmt::Debug; | |
3 | ||
4 | use crate::{ | |
f035d41b | 5 | BoundVar, Const, ConstValue, DebruijnIndex, DomainGoal, Goal, InferenceVar, Interner, Lifetime, |
29967ef6 | 6 | LifetimeData, PlaceholderIndex, ProgramClause, Ty, TyKind, WhereClause, |
f9f354fc XL |
7 | }; |
8 | ||
9 | mod binder_impls; | |
10 | mod boring_impls; | |
11 | pub mod visitors; | |
12 | ||
13 | pub use visitors::VisitExt; | |
14 | ||
5869c6ff XL |
15 | /// An copy of the unstable `std::ops::ControlFlow` for use in Chalk visitors. |
16 | pub enum ControlFlow<B, C = ()> { | |
17 | /// Continue in the loop, using the given value for the next iteration | |
18 | Continue(C), | |
19 | /// Exit the loop, yielding the given value | |
20 | Break(B), | |
21 | } | |
22 | ||
23 | impl<B, C> ControlFlow<B, C> { | |
24 | /// Returns `true` if this is a `Break` variant. | |
25 | #[inline] | |
26 | pub fn is_break(&self) -> bool { | |
27 | matches!(*self, ControlFlow::Break(_)) | |
28 | } | |
29 | ||
30 | /// Returns `true` if this is a `Continue` variant. | |
31 | #[inline] | |
32 | pub fn is_continue(&self) -> bool { | |
33 | matches!(*self, ControlFlow::Continue(_)) | |
34 | } | |
35 | ||
36 | /// Converts the `ControlFlow` into an `Option` which is `Some` | |
37 | /// if the `ControlFlow` was `Break` and `None` otherwise. | |
38 | #[inline] | |
39 | pub fn break_value(self) -> Option<B> { | |
40 | match self { | |
41 | ControlFlow::Continue(..) => None, | |
42 | ControlFlow::Break(x) => Some(x), | |
f9f354fc XL |
43 | } |
44 | } | |
45 | } | |
46 | ||
5869c6ff XL |
47 | impl<B> ControlFlow<B, ()> { |
48 | /// It's frequently the case that there's no value needed with `Continue`, | |
49 | /// so this provides a way to avoid typing `(())`, if you prefer it. | |
50 | pub const CONTINUE: Self = ControlFlow::Continue(()); | |
51 | } | |
f9f354fc | 52 | |
5869c6ff XL |
53 | impl<C> ControlFlow<(), C> { |
54 | /// APIs like `try_for_each` don't need values with `Break`, | |
55 | /// so this provides a way to avoid typing `(())`, if you prefer it. | |
56 | pub const BREAK: Self = ControlFlow::Break(()); | |
57 | } | |
58 | ||
59 | /// Unwraps a `ControlFlow` or propagates its `Break` value. | |
60 | /// This replaces the `Try` implementation that would be used | |
61 | /// with `std::ops::ControlFlow`. | |
62 | #[macro_export] | |
63 | macro_rules! try_break { | |
64 | ($expr:expr) => { | |
65 | match $expr { | |
66 | $crate::visit::ControlFlow::Continue(c) => c, | |
67 | $crate::visit::ControlFlow::Break(b) => return $crate::visit::ControlFlow::Break(b), | |
68 | } | |
69 | }; | |
f9f354fc XL |
70 | } |
71 | ||
72 | /// A "visitor" recursively folds some term -- that is, some bit of IR, | |
73 | /// such as a `Goal`, and computes a value as a result. | |
74 | /// | |
75 | /// | |
76 | /// To **apply** a visitor, use the `Visit::visit_with` method, like so | |
77 | /// | |
78 | /// ```rust,ignore | |
79 | /// let result = x.visit_with(&mut visitor, 0); | |
80 | /// ``` | |
81 | pub trait Visitor<'i, I: Interner> | |
82 | where | |
83 | I: 'i, | |
84 | { | |
5869c6ff XL |
85 | /// The "break type" of the visitor, often `()`. It represents the result |
86 | /// the visitor yields when it stops visiting. | |
87 | type BreakTy; | |
f9f354fc XL |
88 | |
89 | /// Creates a `dyn` value from this visitor. Unfortunately, this | |
90 | /// must be added manually to each impl of visitor; it permits the | |
91 | /// default implements below to create a `&mut dyn Visitor` from | |
92 | /// `Self` without knowing what `Self` is (by invoking this | |
93 | /// method). Effectively, this limits impls of `visitor` to types | |
94 | /// for which we are able to create a dyn value (i.e., not `[T]` | |
95 | /// types). | |
5869c6ff | 96 | fn as_dyn(&mut self) -> &mut dyn Visitor<'i, I, BreakTy = Self::BreakTy>; |
f9f354fc XL |
97 | |
98 | /// Top-level callback: invoked for each `Ty<I>` that is | |
99 | /// encountered when visiting. By default, invokes | |
100 | /// `super_visit_with`, which will in turn invoke the more | |
f035d41b | 101 | /// specialized visiting methods below, like `visit_free_var`. |
5869c6ff | 102 | fn visit_ty(&mut self, ty: &Ty<I>, outer_binder: DebruijnIndex) -> ControlFlow<Self::BreakTy> { |
f9f354fc XL |
103 | ty.super_visit_with(self.as_dyn(), outer_binder) |
104 | } | |
105 | ||
106 | /// Top-level callback: invoked for each `Lifetime<I>` that is | |
107 | /// encountered when visiting. By default, invokes | |
108 | /// `super_visit_with`, which will in turn invoke the more | |
f035d41b | 109 | /// specialized visiting methods below, like `visit_free_var`. |
f9f354fc XL |
110 | fn visit_lifetime( |
111 | &mut self, | |
112 | lifetime: &Lifetime<I>, | |
113 | outer_binder: DebruijnIndex, | |
5869c6ff | 114 | ) -> ControlFlow<Self::BreakTy> { |
f9f354fc XL |
115 | lifetime.super_visit_with(self.as_dyn(), outer_binder) |
116 | } | |
117 | ||
f035d41b XL |
118 | /// Top-level callback: invoked for each `Const<I>` that is |
119 | /// encountered when visiting. By default, invokes | |
120 | /// `super_visit_with`, which will in turn invoke the more | |
121 | /// specialized visiting methods below, like `visit_free_var`. | |
5869c6ff XL |
122 | fn visit_const( |
123 | &mut self, | |
124 | constant: &Const<I>, | |
125 | outer_binder: DebruijnIndex, | |
126 | ) -> ControlFlow<Self::BreakTy> { | |
f035d41b XL |
127 | constant.super_visit_with(self.as_dyn(), outer_binder) |
128 | } | |
129 | ||
f9f354fc XL |
130 | /// Invoked for every program clause. By default, recursively visits the goals contents. |
131 | fn visit_program_clause( | |
132 | &mut self, | |
133 | clause: &ProgramClause<I>, | |
134 | outer_binder: DebruijnIndex, | |
5869c6ff | 135 | ) -> ControlFlow<Self::BreakTy> { |
f9f354fc XL |
136 | clause.super_visit_with(self.as_dyn(), outer_binder) |
137 | } | |
138 | ||
139 | /// Invoked for every goal. By default, recursively visits the goals contents. | |
5869c6ff XL |
140 | fn visit_goal( |
141 | &mut self, | |
142 | goal: &Goal<I>, | |
143 | outer_binder: DebruijnIndex, | |
144 | ) -> ControlFlow<Self::BreakTy> { | |
f9f354fc XL |
145 | goal.super_visit_with(self.as_dyn(), outer_binder) |
146 | } | |
147 | ||
f035d41b | 148 | /// Invoked for each domain goal. |
f9f354fc XL |
149 | fn visit_domain_goal( |
150 | &mut self, | |
151 | domain_goal: &DomainGoal<I>, | |
152 | outer_binder: DebruijnIndex, | |
5869c6ff | 153 | ) -> ControlFlow<Self::BreakTy> { |
f9f354fc XL |
154 | domain_goal.super_visit_with(self.as_dyn(), outer_binder) |
155 | } | |
156 | ||
157 | /// If overridden to return true, then visiting will panic if a | |
158 | /// free variable is encountered. This should be done if free | |
f035d41b | 159 | /// type/lifetime/const variables are not expected. |
f9f354fc XL |
160 | fn forbid_free_vars(&self) -> bool { |
161 | false | |
162 | } | |
163 | ||
f035d41b | 164 | /// Invoked for `BoundVar` instances that are not bound |
f9f354fc | 165 | /// within the type being visited over: |
5869c6ff XL |
166 | fn visit_free_var( |
167 | &mut self, | |
168 | bound_var: BoundVar, | |
169 | outer_binder: DebruijnIndex, | |
170 | ) -> ControlFlow<Self::BreakTy> { | |
f9f354fc XL |
171 | if self.forbid_free_vars() { |
172 | panic!( | |
173 | "unexpected free variable `{:?}` with outer binder {:?}", | |
174 | bound_var, outer_binder | |
175 | ) | |
176 | } else { | |
5869c6ff | 177 | ControlFlow::CONTINUE |
f9f354fc XL |
178 | } |
179 | } | |
180 | ||
f035d41b | 181 | /// If overridden to return true, we will panic when a free |
f9f354fc XL |
182 | /// placeholder type/lifetime is encountered. |
183 | fn forbid_free_placeholders(&self) -> bool { | |
184 | false | |
185 | } | |
186 | ||
187 | /// Invoked for each occurrence of a placeholder type; these are | |
188 | /// used when we instantiate binders universally. | |
f035d41b | 189 | fn visit_free_placeholder( |
f9f354fc XL |
190 | &mut self, |
191 | universe: PlaceholderIndex, | |
192 | _outer_binder: DebruijnIndex, | |
5869c6ff | 193 | ) -> ControlFlow<Self::BreakTy> { |
f9f354fc XL |
194 | if self.forbid_free_placeholders() { |
195 | panic!("unexpected placeholder type `{:?}`", universe) | |
196 | } else { | |
5869c6ff | 197 | ControlFlow::CONTINUE |
f9f354fc XL |
198 | } |
199 | } | |
200 | ||
f035d41b | 201 | /// Invoked for each where clause. |
f9f354fc XL |
202 | fn visit_where_clause( |
203 | &mut self, | |
204 | where_clause: &WhereClause<I>, | |
205 | outer_binder: DebruijnIndex, | |
5869c6ff | 206 | ) -> ControlFlow<Self::BreakTy> { |
f9f354fc XL |
207 | where_clause.super_visit_with(self.as_dyn(), outer_binder) |
208 | } | |
209 | ||
f9f354fc XL |
210 | /// If overridden to return true, inference variables will trigger |
211 | /// panics when visited. Used when inference variables are | |
212 | /// unexpected. | |
213 | fn forbid_inference_vars(&self) -> bool { | |
214 | false | |
215 | } | |
216 | ||
217 | /// Invoked for each occurrence of a inference type; these are | |
218 | /// used when we instantiate binders universally. | |
f035d41b | 219 | fn visit_inference_var( |
f9f354fc XL |
220 | &mut self, |
221 | var: InferenceVar, | |
222 | _outer_binder: DebruijnIndex, | |
5869c6ff | 223 | ) -> ControlFlow<Self::BreakTy> { |
f9f354fc XL |
224 | if self.forbid_inference_vars() { |
225 | panic!("unexpected inference type `{:?}`", var) | |
226 | } else { | |
5869c6ff | 227 | ControlFlow::CONTINUE |
f9f354fc XL |
228 | } |
229 | } | |
230 | ||
f035d41b | 231 | /// Gets the visitor's interner. |
f9f354fc XL |
232 | fn interner(&self) -> &'i I; |
233 | } | |
234 | ||
235 | /// Applies the given `visitor` to a value, producing a visited result | |
236 | /// of type `Visitor::Result`. | |
237 | pub trait Visit<I: Interner>: Debug { | |
238 | /// Apply the given visitor `visitor` to `self`; `binders` is the | |
239 | /// number of binders that are in scope when beginning the | |
240 | /// visitor. Typically `binders` starts as 0, but is adjusted when | |
241 | /// we encounter `Binders<T>` in the IR or other similar | |
242 | /// constructs. | |
5869c6ff | 243 | fn visit_with<'i, B>( |
f9f354fc | 244 | &self, |
5869c6ff | 245 | visitor: &mut dyn Visitor<'i, I, BreakTy = B>, |
f9f354fc | 246 | outer_binder: DebruijnIndex, |
5869c6ff | 247 | ) -> ControlFlow<B> |
f9f354fc XL |
248 | where |
249 | I: 'i; | |
250 | } | |
251 | ||
252 | /// For types where "visit" invokes a callback on the `visitor`, the | |
253 | /// `SuperVisit` trait captures the recursive behavior that visits all | |
254 | /// the contents of the type. | |
255 | pub trait SuperVisit<I: Interner>: Visit<I> { | |
f035d41b | 256 | /// Recursively visits the type contents. |
5869c6ff | 257 | fn super_visit_with<'i, B>( |
f9f354fc | 258 | &self, |
5869c6ff | 259 | visitor: &mut dyn Visitor<'i, I, BreakTy = B>, |
f9f354fc | 260 | outer_binder: DebruijnIndex, |
5869c6ff | 261 | ) -> ControlFlow<B> |
f9f354fc XL |
262 | where |
263 | I: 'i; | |
264 | } | |
265 | ||
266 | /// "visiting" a type invokes the `visit_ty` method on the visitor; this | |
267 | /// usually (in turn) invokes `super_visit_ty` to visit the individual | |
268 | /// parts. | |
269 | impl<I: Interner> Visit<I> for Ty<I> { | |
5869c6ff | 270 | fn visit_with<'i, B>( |
f9f354fc | 271 | &self, |
5869c6ff | 272 | visitor: &mut dyn Visitor<'i, I, BreakTy = B>, |
f9f354fc | 273 | outer_binder: DebruijnIndex, |
5869c6ff | 274 | ) -> ControlFlow<B> |
f9f354fc XL |
275 | where |
276 | I: 'i, | |
277 | { | |
278 | visitor.visit_ty(self, outer_binder) | |
279 | } | |
280 | } | |
281 | ||
5869c6ff | 282 | /// "Super visit" for a type invokes the more detailed callbacks on the type |
f9f354fc XL |
283 | impl<I> SuperVisit<I> for Ty<I> |
284 | where | |
285 | I: Interner, | |
286 | { | |
5869c6ff | 287 | fn super_visit_with<'i, B>( |
f9f354fc | 288 | &self, |
5869c6ff | 289 | visitor: &mut dyn Visitor<'i, I, BreakTy = B>, |
f9f354fc | 290 | outer_binder: DebruijnIndex, |
5869c6ff | 291 | ) -> ControlFlow<B> |
f9f354fc XL |
292 | where |
293 | I: 'i, | |
294 | { | |
295 | let interner = visitor.interner(); | |
29967ef6 XL |
296 | match self.kind(interner) { |
297 | TyKind::BoundVar(bound_var) => { | |
f9f354fc | 298 | if let Some(_) = bound_var.shifted_out_to(outer_binder) { |
f035d41b | 299 | visitor.visit_free_var(*bound_var, outer_binder) |
f9f354fc | 300 | } else { |
5869c6ff | 301 | ControlFlow::CONTINUE |
f9f354fc XL |
302 | } |
303 | } | |
29967ef6 XL |
304 | TyKind::Dyn(clauses) => clauses.visit_with(visitor, outer_binder), |
305 | TyKind::InferenceVar(var, _) => visitor.visit_inference_var(*var, outer_binder), | |
306 | TyKind::Placeholder(ui) => visitor.visit_free_placeholder(*ui, outer_binder), | |
307 | TyKind::Alias(proj) => proj.visit_with(visitor, outer_binder), | |
308 | TyKind::Function(fun) => fun.visit_with(visitor, outer_binder), | |
309 | TyKind::Adt(_id, substitution) => substitution.visit_with(visitor, outer_binder), | |
310 | TyKind::AssociatedType(_assoc_ty, substitution) => { | |
311 | substitution.visit_with(visitor, outer_binder) | |
312 | } | |
313 | TyKind::Scalar(scalar) => scalar.visit_with(visitor, outer_binder), | |
5869c6ff XL |
314 | TyKind::Str => ControlFlow::CONTINUE, |
315 | TyKind::Tuple(arity, substitution) => { | |
316 | try_break!(arity.visit_with(visitor, outer_binder)); | |
317 | substitution.visit_with(visitor, outer_binder) | |
318 | } | |
319 | TyKind::OpaqueType(opaque_ty, substitution) => { | |
320 | try_break!(opaque_ty.visit_with(visitor, outer_binder)); | |
321 | substitution.visit_with(visitor, outer_binder) | |
322 | } | |
29967ef6 | 323 | TyKind::Slice(substitution) => substitution.visit_with(visitor, outer_binder), |
5869c6ff XL |
324 | TyKind::FnDef(fn_def, substitution) => { |
325 | try_break!(fn_def.visit_with(visitor, outer_binder)); | |
326 | substitution.visit_with(visitor, outer_binder) | |
327 | } | |
29967ef6 | 328 | TyKind::Ref(mutability, lifetime, ty) => { |
5869c6ff XL |
329 | try_break!(mutability.visit_with(visitor, outer_binder)); |
330 | try_break!(lifetime.visit_with(visitor, outer_binder)); | |
331 | ty.visit_with(visitor, outer_binder) | |
332 | } | |
333 | TyKind::Raw(mutability, ty) => { | |
334 | try_break!(mutability.visit_with(visitor, outer_binder)); | |
335 | ty.visit_with(visitor, outer_binder) | |
336 | } | |
337 | TyKind::Never => ControlFlow::CONTINUE, | |
338 | TyKind::Array(ty, const_) => { | |
339 | try_break!(ty.visit_with(visitor, outer_binder)); | |
340 | const_.visit_with(visitor, outer_binder) | |
341 | } | |
342 | TyKind::Closure(id, substitution) => { | |
343 | try_break!(id.visit_with(visitor, outer_binder)); | |
344 | substitution.visit_with(visitor, outer_binder) | |
345 | } | |
346 | TyKind::Generator(generator, substitution) => { | |
347 | try_break!(generator.visit_with(visitor, outer_binder)); | |
348 | substitution.visit_with(visitor, outer_binder) | |
349 | } | |
350 | TyKind::GeneratorWitness(witness, substitution) => { | |
351 | try_break!(witness.visit_with(visitor, outer_binder)); | |
352 | substitution.visit_with(visitor, outer_binder) | |
29967ef6 | 353 | } |
29967ef6 | 354 | TyKind::Foreign(foreign_ty) => foreign_ty.visit_with(visitor, outer_binder), |
5869c6ff | 355 | TyKind::Error => ControlFlow::CONTINUE, |
f9f354fc XL |
356 | } |
357 | } | |
358 | } | |
359 | ||
360 | impl<I: Interner> Visit<I> for Lifetime<I> { | |
5869c6ff | 361 | fn visit_with<'i, B>( |
f9f354fc | 362 | &self, |
5869c6ff | 363 | visitor: &mut dyn Visitor<'i, I, BreakTy = B>, |
f9f354fc | 364 | outer_binder: DebruijnIndex, |
5869c6ff | 365 | ) -> ControlFlow<B> |
f9f354fc XL |
366 | where |
367 | I: 'i, | |
368 | { | |
369 | visitor.visit_lifetime(self, outer_binder) | |
370 | } | |
371 | } | |
372 | ||
373 | impl<I: Interner> SuperVisit<I> for Lifetime<I> { | |
5869c6ff | 374 | fn super_visit_with<'i, B>( |
f9f354fc | 375 | &self, |
5869c6ff | 376 | visitor: &mut dyn Visitor<'i, I, BreakTy = B>, |
f9f354fc | 377 | outer_binder: DebruijnIndex, |
5869c6ff | 378 | ) -> ControlFlow<B> |
f9f354fc XL |
379 | where |
380 | I: 'i, | |
381 | { | |
382 | let interner = visitor.interner(); | |
383 | match self.data(interner) { | |
384 | LifetimeData::BoundVar(bound_var) => { | |
385 | if let Some(_) = bound_var.shifted_out_to(outer_binder) { | |
f035d41b | 386 | visitor.visit_free_var(*bound_var, outer_binder) |
f9f354fc | 387 | } else { |
5869c6ff | 388 | ControlFlow::CONTINUE |
f9f354fc XL |
389 | } |
390 | } | |
f035d41b | 391 | LifetimeData::InferenceVar(var) => visitor.visit_inference_var(*var, outer_binder), |
f9f354fc | 392 | LifetimeData::Placeholder(universe) => { |
f035d41b | 393 | visitor.visit_free_placeholder(*universe, outer_binder) |
f9f354fc | 394 | } |
5869c6ff XL |
395 | LifetimeData::Static | LifetimeData::Empty(_) | LifetimeData::Erased => { |
396 | ControlFlow::CONTINUE | |
397 | } | |
398 | LifetimeData::Phantom(void, ..) => match *void {}, | |
f9f354fc XL |
399 | } |
400 | } | |
401 | } | |
402 | ||
f035d41b | 403 | impl<I: Interner> Visit<I> for Const<I> { |
5869c6ff | 404 | fn visit_with<'i, B>( |
f035d41b | 405 | &self, |
5869c6ff | 406 | visitor: &mut dyn Visitor<'i, I, BreakTy = B>, |
f035d41b | 407 | outer_binder: DebruijnIndex, |
5869c6ff | 408 | ) -> ControlFlow<B> |
f035d41b XL |
409 | where |
410 | I: 'i, | |
411 | { | |
412 | visitor.visit_const(self, outer_binder) | |
413 | } | |
414 | } | |
415 | ||
416 | impl<I: Interner> SuperVisit<I> for Const<I> { | |
5869c6ff | 417 | fn super_visit_with<'i, B>( |
f035d41b | 418 | &self, |
5869c6ff | 419 | visitor: &mut dyn Visitor<'i, I, BreakTy = B>, |
f035d41b | 420 | outer_binder: DebruijnIndex, |
5869c6ff | 421 | ) -> ControlFlow<B> |
f035d41b XL |
422 | where |
423 | I: 'i, | |
424 | { | |
425 | let interner = visitor.interner(); | |
426 | match &self.data(interner).value { | |
427 | ConstValue::BoundVar(bound_var) => { | |
428 | if let Some(_) = bound_var.shifted_out_to(outer_binder) { | |
429 | visitor.visit_free_var(*bound_var, outer_binder) | |
430 | } else { | |
5869c6ff | 431 | ControlFlow::CONTINUE |
f035d41b XL |
432 | } |
433 | } | |
434 | ConstValue::InferenceVar(var) => visitor.visit_inference_var(*var, outer_binder), | |
435 | ConstValue::Placeholder(universe) => { | |
436 | visitor.visit_free_placeholder(*universe, outer_binder) | |
437 | } | |
5869c6ff | 438 | ConstValue::Concrete(_) => ControlFlow::CONTINUE, |
f035d41b XL |
439 | } |
440 | } | |
441 | } | |
442 | ||
f9f354fc | 443 | impl<I: Interner> Visit<I> for Goal<I> { |
5869c6ff | 444 | fn visit_with<'i, B>( |
f9f354fc | 445 | &self, |
5869c6ff | 446 | visitor: &mut dyn Visitor<'i, I, BreakTy = B>, |
f9f354fc | 447 | outer_binder: DebruijnIndex, |
5869c6ff | 448 | ) -> ControlFlow<B> |
f9f354fc XL |
449 | where |
450 | I: 'i, | |
451 | { | |
452 | visitor.visit_goal(self, outer_binder) | |
453 | } | |
454 | } | |
455 | ||
456 | impl<I: Interner> SuperVisit<I> for Goal<I> { | |
5869c6ff | 457 | fn super_visit_with<'i, B>( |
f9f354fc | 458 | &self, |
5869c6ff | 459 | visitor: &mut dyn Visitor<'i, I, BreakTy = B>, |
f9f354fc | 460 | outer_binder: DebruijnIndex, |
5869c6ff | 461 | ) -> ControlFlow<B> |
f9f354fc XL |
462 | where |
463 | I: 'i, | |
464 | { | |
465 | let interner = visitor.interner(); | |
466 | self.data(interner).visit_with(visitor, outer_binder) | |
467 | } | |
468 | } | |
469 | ||
470 | impl<I: Interner> Visit<I> for ProgramClause<I> { | |
5869c6ff | 471 | fn visit_with<'i, B>( |
f9f354fc | 472 | &self, |
5869c6ff | 473 | visitor: &mut dyn Visitor<'i, I, BreakTy = B>, |
f9f354fc | 474 | outer_binder: DebruijnIndex, |
5869c6ff | 475 | ) -> ControlFlow<B> |
f9f354fc XL |
476 | where |
477 | I: 'i, | |
478 | { | |
479 | visitor.visit_program_clause(self, outer_binder) | |
480 | } | |
481 | } | |
482 | ||
483 | impl<I: Interner> Visit<I> for WhereClause<I> { | |
5869c6ff | 484 | fn visit_with<'i, B>( |
f9f354fc | 485 | &self, |
5869c6ff | 486 | visitor: &mut dyn Visitor<'i, I, BreakTy = B>, |
f9f354fc | 487 | outer_binder: DebruijnIndex, |
5869c6ff | 488 | ) -> ControlFlow<B> |
f9f354fc XL |
489 | where |
490 | I: 'i, | |
491 | { | |
492 | visitor.visit_where_clause(self, outer_binder) | |
493 | } | |
494 | } | |
495 | ||
496 | impl<I: Interner> Visit<I> for DomainGoal<I> { | |
5869c6ff | 497 | fn visit_with<'i, B>( |
f9f354fc | 498 | &self, |
5869c6ff | 499 | visitor: &mut dyn Visitor<'i, I, BreakTy = B>, |
f9f354fc | 500 | outer_binder: DebruijnIndex, |
5869c6ff | 501 | ) -> ControlFlow<B> |
f9f354fc XL |
502 | where |
503 | I: 'i, | |
504 | { | |
505 | visitor.visit_domain_goal(self, outer_binder) | |
506 | } | |
507 | } |