1use std::fmt;
45use std::ops::ControlFlow;
46use std::sync::Arc;
47
48pub 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;
53
54use crate::inherent::*;
55use crate::{self as ty, Interner, TypeFlags};
56
57pub trait TypeVisitable<I: Interner>: fmt::Debug {
63 fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result;
74}
75
76pub trait TypeSuperVisitable<I: Interner>: TypeVisitable<I> {
78 fn super_visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result;
85}
86
87pub trait TypeVisitor<I: Interner>: Sized {
91 #[cfg(feature = "nightly")]
92 type Result: VisitorResult = ();
93
94 #[cfg(not(feature = "nightly"))]
95 type Result: VisitorResult;
96
97 fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &ty::Binder<I, T>) -> Self::Result {
98 t.super_visit_with(self)
99 }
100
101 fn visit_ty(&mut self, t: I::Ty) -> Self::Result {
102 t.super_visit_with(self)
103 }
104
105 fn visit_region(&mut self, r: I::Region) -> Self::Result {
108 if let ty::ReError(guar) = r.kind() {
109 self.visit_error(guar)
110 } else {
111 Self::Result::output()
112 }
113 }
114
115 fn visit_const(&mut self, c: I::Const) -> Self::Result {
116 c.super_visit_with(self)
117 }
118
119 fn visit_predicate(&mut self, p: I::Predicate) -> Self::Result {
120 p.super_visit_with(self)
121 }
122
123 fn visit_clauses(&mut self, p: I::Clauses) -> Self::Result {
124 p.super_visit_with(self)
125 }
126
127 fn visit_error(&mut self, _guar: I::ErrorGuaranteed) -> Self::Result {
128 Self::Result::output()
129 }
130}
131
132impl<I: Interner, T: TypeVisitable<I>, U: TypeVisitable<I>> TypeVisitable<I> for (T, U) {
136 fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
137 try_visit!(self.0.visit_with(visitor));
138 self.1.visit_with(visitor)
139 }
140}
141
142impl<I: Interner, A: TypeVisitable<I>, B: TypeVisitable<I>, C: TypeVisitable<I>> TypeVisitable<I>
143 for (A, B, C)
144{
145 fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
146 try_visit!(self.0.visit_with(visitor));
147 try_visit!(self.1.visit_with(visitor));
148 self.2.visit_with(visitor)
149 }
150}
151
152impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Option<T> {
153 fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
154 match self {
155 Some(v) => v.visit_with(visitor),
156 None => V::Result::output(),
157 }
158 }
159}
160
161impl<I: Interner, T: TypeVisitable<I>, E: TypeVisitable<I>> TypeVisitable<I> for Result<T, E> {
162 fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
163 match self {
164 Ok(v) => v.visit_with(visitor),
165 Err(e) => e.visit_with(visitor),
166 }
167 }
168}
169
170impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Arc<T> {
171 fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
172 (**self).visit_with(visitor)
173 }
174}
175
176impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Box<T> {
177 fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
178 (**self).visit_with(visitor)
179 }
180}
181
182impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Vec<T> {
183 fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
184 walk_visitable_list!(visitor, self.iter());
185 V::Result::output()
186 }
187}
188
189impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for ThinVec<T> {
190 fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
191 walk_visitable_list!(visitor, self.iter());
192 V::Result::output()
193 }
194}
195
196impl<I: Interner, T: TypeVisitable<I>, const N: usize> TypeVisitable<I> for SmallVec<[T; N]> {
197 fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
198 walk_visitable_list!(visitor, self.iter());
199 V::Result::output()
200 }
201}
202
203impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for &[T] {
207 fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
208 walk_visitable_list!(visitor, self.iter());
209 V::Result::output()
210 }
211}
212
213impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Box<[T]> {
214 fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
215 walk_visitable_list!(visitor, self.iter());
216 V::Result::output()
217 }
218}
219
220impl<I: Interner, T: TypeVisitable<I>, Ix: Idx> TypeVisitable<I> for IndexVec<Ix, T> {
221 fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
222 walk_visitable_list!(visitor, self.iter());
223 V::Result::output()
224 }
225}
226
227impl<I: Interner, T: TypeVisitable<I>, S> TypeVisitable<I> for indexmap::IndexSet<T, S> {
228 fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
229 walk_visitable_list!(visitor, self.iter());
230 V::Result::output()
231 }
232}
233
234pub trait Flags {
235 fn flags(&self) -> TypeFlags;
236 fn outer_exclusive_binder(&self) -> ty::DebruijnIndex;
237}
238
239pub trait TypeVisitableExt<I: Interner>: TypeVisitable<I> {
240 fn has_type_flags(&self, flags: TypeFlags) -> bool;
241
242 fn has_vars_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool;
247
248 fn has_vars_bound_above(&self, binder: ty::DebruijnIndex) -> bool {
251 self.has_vars_bound_at_or_above(binder.shifted_in(1))
252 }
253
254 fn has_escaping_bound_vars(&self) -> bool {
261 self.has_vars_bound_at_or_above(ty::INNERMOST)
262 }
263
264 fn has_aliases(&self) -> bool {
265 self.has_type_flags(TypeFlags::HAS_ALIAS)
266 }
267
268 fn has_opaque_types(&self) -> bool {
269 self.has_type_flags(TypeFlags::HAS_TY_OPAQUE)
270 }
271
272 fn has_coroutines(&self) -> bool {
273 self.has_type_flags(TypeFlags::HAS_TY_COROUTINE)
274 }
275
276 fn references_error(&self) -> bool {
277 self.has_type_flags(TypeFlags::HAS_ERROR)
278 }
279
280 fn error_reported(&self) -> Result<(), I::ErrorGuaranteed>;
281
282 fn has_non_region_param(&self) -> bool {
283 self.has_type_flags(TypeFlags::HAS_PARAM - TypeFlags::HAS_RE_PARAM)
284 }
285
286 fn has_infer_regions(&self) -> bool {
287 self.has_type_flags(TypeFlags::HAS_RE_INFER)
288 }
289
290 fn has_infer_types(&self) -> bool {
291 self.has_type_flags(TypeFlags::HAS_TY_INFER)
292 }
293
294 fn has_non_region_infer(&self) -> bool {
295 self.has_type_flags(TypeFlags::HAS_INFER - TypeFlags::HAS_RE_INFER)
296 }
297
298 fn has_infer(&self) -> bool {
299 self.has_type_flags(TypeFlags::HAS_INFER)
300 }
301
302 fn has_placeholders(&self) -> bool {
303 self.has_type_flags(TypeFlags::HAS_PLACEHOLDER)
304 }
305
306 fn has_non_region_placeholders(&self) -> bool {
307 self.has_type_flags(TypeFlags::HAS_PLACEHOLDER - TypeFlags::HAS_RE_PLACEHOLDER)
308 }
309
310 fn has_param(&self) -> bool {
311 self.has_type_flags(TypeFlags::HAS_PARAM)
312 }
313
314 fn has_free_regions(&self) -> bool {
317 self.has_type_flags(TypeFlags::HAS_FREE_REGIONS)
318 }
319
320 fn has_erased_regions(&self) -> bool {
321 self.has_type_flags(TypeFlags::HAS_RE_ERASED)
322 }
323
324 fn has_erasable_regions(&self) -> bool {
326 self.has_type_flags(TypeFlags::HAS_FREE_REGIONS)
327 }
328
329 fn is_global(&self) -> bool {
333 !self.has_type_flags(TypeFlags::HAS_FREE_LOCAL_NAMES)
334 }
335
336 fn has_bound_regions(&self) -> bool {
338 self.has_type_flags(TypeFlags::HAS_RE_BOUND)
339 }
340 fn has_non_region_bound_vars(&self) -> bool {
342 self.has_type_flags(TypeFlags::HAS_BOUND_VARS - TypeFlags::HAS_RE_BOUND)
343 }
344 fn has_bound_vars(&self) -> bool {
346 self.has_type_flags(TypeFlags::HAS_BOUND_VARS)
347 }
348
349 fn still_further_specializable(&self) -> bool {
353 self.has_type_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE)
354 }
355}
356
357impl<I: Interner, T: TypeVisitable<I>> TypeVisitableExt<I> for T {
358 fn has_type_flags(&self, flags: TypeFlags) -> bool {
359 let res =
360 self.visit_with(&mut HasTypeFlagsVisitor { flags }) == ControlFlow::Break(FoundFlags);
361 res
362 }
363
364 fn has_vars_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool {
365 self.visit_with(&mut HasEscapingVarsVisitor { outer_index: binder }).is_break()
366 }
367
368 fn error_reported(&self) -> Result<(), I::ErrorGuaranteed> {
369 if self.references_error() {
370 if let ControlFlow::Break(guar) = self.visit_with(&mut HasErrorVisitor) {
371 Err(guar)
372 } else {
373 panic!("type flags said there was an error, but now there is not")
374 }
375 } else {
376 Ok(())
377 }
378 }
379}
380
381#[derive(Debug, PartialEq, Eq, Copy, Clone)]
382struct FoundFlags;
383
384struct HasTypeFlagsVisitor {
386 flags: ty::TypeFlags,
387}
388
389impl std::fmt::Debug for HasTypeFlagsVisitor {
390 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
391 self.flags.fmt(fmt)
392 }
393}
394
395impl<I: Interner> TypeVisitor<I> for HasTypeFlagsVisitor {
406 type Result = ControlFlow<FoundFlags>;
407
408 fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &ty::Binder<I, T>) -> Self::Result {
409 if self.flags.intersects(TypeFlags::HAS_BINDER_VARS) && !t.bound_vars().is_empty() {
413 return ControlFlow::Break(FoundFlags);
414 }
415
416 t.super_visit_with(self)
417 }
418
419 #[inline]
420 fn visit_ty(&mut self, t: I::Ty) -> Self::Result {
421 let flags = t.flags();
423 if flags.intersects(self.flags) {
424 ControlFlow::Break(FoundFlags)
425 } else {
426 ControlFlow::Continue(())
427 }
428 }
429
430 #[inline]
431 fn visit_region(&mut self, r: I::Region) -> Self::Result {
432 let flags = r.flags();
434 if flags.intersects(self.flags) {
435 ControlFlow::Break(FoundFlags)
436 } else {
437 ControlFlow::Continue(())
438 }
439 }
440
441 #[inline]
442 fn visit_const(&mut self, c: I::Const) -> Self::Result {
443 if c.flags().intersects(self.flags) {
445 ControlFlow::Break(FoundFlags)
446 } else {
447 ControlFlow::Continue(())
448 }
449 }
450
451 #[inline]
452 fn visit_predicate(&mut self, predicate: I::Predicate) -> Self::Result {
453 if predicate.flags().intersects(self.flags) {
455 ControlFlow::Break(FoundFlags)
456 } else {
457 ControlFlow::Continue(())
458 }
459 }
460
461 #[inline]
462 fn visit_clauses(&mut self, clauses: I::Clauses) -> Self::Result {
463 if clauses.flags().intersects(self.flags) {
465 ControlFlow::Break(FoundFlags)
466 } else {
467 ControlFlow::Continue(())
468 }
469 }
470
471 #[inline]
472 fn visit_error(&mut self, _guar: <I as Interner>::ErrorGuaranteed) -> Self::Result {
473 if self.flags.intersects(TypeFlags::HAS_ERROR) {
474 ControlFlow::Break(FoundFlags)
475 } else {
476 ControlFlow::Continue(())
477 }
478 }
479}
480
481#[derive(Debug, PartialEq, Eq, Copy, Clone)]
482struct FoundEscapingVars;
483
484struct HasEscapingVarsVisitor {
510 outer_index: ty::DebruijnIndex,
512}
513
514impl<I: Interner> TypeVisitor<I> for HasEscapingVarsVisitor {
515 type Result = ControlFlow<FoundEscapingVars>;
516
517 fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &ty::Binder<I, T>) -> Self::Result {
518 self.outer_index.shift_in(1);
519 let result = t.super_visit_with(self);
520 self.outer_index.shift_out(1);
521 result
522 }
523
524 #[inline]
525 fn visit_ty(&mut self, t: I::Ty) -> Self::Result {
526 if t.outer_exclusive_binder() > self.outer_index {
532 ControlFlow::Break(FoundEscapingVars)
533 } else {
534 ControlFlow::Continue(())
535 }
536 }
537
538 #[inline]
539 fn visit_region(&mut self, r: I::Region) -> Self::Result {
540 if r.outer_exclusive_binder() > self.outer_index {
544 ControlFlow::Break(FoundEscapingVars)
545 } else {
546 ControlFlow::Continue(())
547 }
548 }
549
550 fn visit_const(&mut self, ct: I::Const) -> Self::Result {
551 if ct.outer_exclusive_binder() > self.outer_index {
557 ControlFlow::Break(FoundEscapingVars)
558 } else {
559 ControlFlow::Continue(())
560 }
561 }
562
563 #[inline]
564 fn visit_predicate(&mut self, predicate: I::Predicate) -> Self::Result {
565 if predicate.outer_exclusive_binder() > self.outer_index {
566 ControlFlow::Break(FoundEscapingVars)
567 } else {
568 ControlFlow::Continue(())
569 }
570 }
571
572 #[inline]
573 fn visit_clauses(&mut self, clauses: I::Clauses) -> Self::Result {
574 if clauses.outer_exclusive_binder() > self.outer_index {
575 ControlFlow::Break(FoundEscapingVars)
576 } else {
577 ControlFlow::Continue(())
578 }
579 }
580}
581
582struct HasErrorVisitor;
583
584impl<I: Interner> TypeVisitor<I> for HasErrorVisitor {
585 type Result = ControlFlow<I::ErrorGuaranteed>;
586
587 fn visit_error(&mut self, guar: <I as Interner>::ErrorGuaranteed) -> Self::Result {
588 ControlFlow::Break(guar)
589 }
590}