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 references_error(&self) -> bool {
273 self.has_type_flags(TypeFlags::HAS_ERROR)
274 }
275
276 fn error_reported(&self) -> Result<(), I::ErrorGuaranteed>;
277
278 fn has_non_region_param(&self) -> bool {
279 self.has_type_flags(TypeFlags::HAS_PARAM - TypeFlags::HAS_RE_PARAM)
280 }
281
282 fn has_infer_regions(&self) -> bool {
283 self.has_type_flags(TypeFlags::HAS_RE_INFER)
284 }
285
286 fn has_infer_types(&self) -> bool {
287 self.has_type_flags(TypeFlags::HAS_TY_INFER)
288 }
289
290 fn has_non_region_infer(&self) -> bool {
291 self.has_type_flags(TypeFlags::HAS_INFER - TypeFlags::HAS_RE_INFER)
292 }
293
294 fn has_infer(&self) -> bool {
295 self.has_type_flags(TypeFlags::HAS_INFER)
296 }
297
298 fn has_placeholders(&self) -> bool {
299 self.has_type_flags(TypeFlags::HAS_PLACEHOLDER)
300 }
301
302 fn has_non_region_placeholders(&self) -> bool {
303 self.has_type_flags(TypeFlags::HAS_PLACEHOLDER - TypeFlags::HAS_RE_PLACEHOLDER)
304 }
305
306 fn has_param(&self) -> bool {
307 self.has_type_flags(TypeFlags::HAS_PARAM)
308 }
309
310 fn has_free_regions(&self) -> bool {
313 self.has_type_flags(TypeFlags::HAS_FREE_REGIONS)
314 }
315
316 fn has_erased_regions(&self) -> bool {
317 self.has_type_flags(TypeFlags::HAS_RE_ERASED)
318 }
319
320 fn has_erasable_regions(&self) -> bool {
322 self.has_type_flags(TypeFlags::HAS_FREE_REGIONS)
323 }
324
325 fn is_global(&self) -> bool {
329 !self.has_type_flags(TypeFlags::HAS_FREE_LOCAL_NAMES)
330 }
331
332 fn has_bound_regions(&self) -> bool {
334 self.has_type_flags(TypeFlags::HAS_RE_BOUND)
335 }
336 fn has_non_region_bound_vars(&self) -> bool {
338 self.has_type_flags(TypeFlags::HAS_BOUND_VARS - TypeFlags::HAS_RE_BOUND)
339 }
340 fn has_bound_vars(&self) -> bool {
342 self.has_type_flags(TypeFlags::HAS_BOUND_VARS)
343 }
344
345 fn still_further_specializable(&self) -> bool {
349 self.has_type_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE)
350 }
351}
352
353impl<I: Interner, T: TypeVisitable<I>> TypeVisitableExt<I> for T {
354 fn has_type_flags(&self, flags: TypeFlags) -> bool {
355 let res =
356 self.visit_with(&mut HasTypeFlagsVisitor { flags }) == ControlFlow::Break(FoundFlags);
357 res
358 }
359
360 fn has_vars_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool {
361 self.visit_with(&mut HasEscapingVarsVisitor { outer_index: binder }).is_break()
362 }
363
364 fn error_reported(&self) -> Result<(), I::ErrorGuaranteed> {
365 if self.references_error() {
366 if let ControlFlow::Break(guar) = self.visit_with(&mut HasErrorVisitor) {
367 Err(guar)
368 } else {
369 panic!("type flags said there was an error, but now there is not")
370 }
371 } else {
372 Ok(())
373 }
374 }
375}
376
377#[derive(Debug, PartialEq, Eq, Copy, Clone)]
378struct FoundFlags;
379
380struct HasTypeFlagsVisitor {
382 flags: ty::TypeFlags,
383}
384
385impl std::fmt::Debug for HasTypeFlagsVisitor {
386 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
387 self.flags.fmt(fmt)
388 }
389}
390
391impl<I: Interner> TypeVisitor<I> for HasTypeFlagsVisitor {
402 type Result = ControlFlow<FoundFlags>;
403
404 fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &ty::Binder<I, T>) -> Self::Result {
405 if self.flags.intersects(TypeFlags::HAS_BINDER_VARS) && !t.bound_vars().is_empty() {
409 return ControlFlow::Break(FoundFlags);
410 }
411
412 t.super_visit_with(self)
413 }
414
415 #[inline]
416 fn visit_ty(&mut self, t: I::Ty) -> Self::Result {
417 let flags = t.flags();
419 if flags.intersects(self.flags) {
420 ControlFlow::Break(FoundFlags)
421 } else {
422 ControlFlow::Continue(())
423 }
424 }
425
426 #[inline]
427 fn visit_region(&mut self, r: I::Region) -> Self::Result {
428 let flags = r.flags();
430 if flags.intersects(self.flags) {
431 ControlFlow::Break(FoundFlags)
432 } else {
433 ControlFlow::Continue(())
434 }
435 }
436
437 #[inline]
438 fn visit_const(&mut self, c: I::Const) -> Self::Result {
439 if c.flags().intersects(self.flags) {
441 ControlFlow::Break(FoundFlags)
442 } else {
443 ControlFlow::Continue(())
444 }
445 }
446
447 #[inline]
448 fn visit_predicate(&mut self, predicate: I::Predicate) -> Self::Result {
449 if predicate.flags().intersects(self.flags) {
451 ControlFlow::Break(FoundFlags)
452 } else {
453 ControlFlow::Continue(())
454 }
455 }
456
457 #[inline]
458 fn visit_clauses(&mut self, clauses: I::Clauses) -> Self::Result {
459 if clauses.flags().intersects(self.flags) {
461 ControlFlow::Break(FoundFlags)
462 } else {
463 ControlFlow::Continue(())
464 }
465 }
466
467 #[inline]
468 fn visit_error(&mut self, _guar: <I as Interner>::ErrorGuaranteed) -> Self::Result {
469 if self.flags.intersects(TypeFlags::HAS_ERROR) {
470 ControlFlow::Break(FoundFlags)
471 } else {
472 ControlFlow::Continue(())
473 }
474 }
475}
476
477#[derive(Debug, PartialEq, Eq, Copy, Clone)]
478struct FoundEscapingVars;
479
480struct HasEscapingVarsVisitor {
506 outer_index: ty::DebruijnIndex,
508}
509
510impl<I: Interner> TypeVisitor<I> for HasEscapingVarsVisitor {
511 type Result = ControlFlow<FoundEscapingVars>;
512
513 fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &ty::Binder<I, T>) -> Self::Result {
514 self.outer_index.shift_in(1);
515 let result = t.super_visit_with(self);
516 self.outer_index.shift_out(1);
517 result
518 }
519
520 #[inline]
521 fn visit_ty(&mut self, t: I::Ty) -> Self::Result {
522 if t.outer_exclusive_binder() > self.outer_index {
528 ControlFlow::Break(FoundEscapingVars)
529 } else {
530 ControlFlow::Continue(())
531 }
532 }
533
534 #[inline]
535 fn visit_region(&mut self, r: I::Region) -> Self::Result {
536 if r.outer_exclusive_binder() > self.outer_index {
540 ControlFlow::Break(FoundEscapingVars)
541 } else {
542 ControlFlow::Continue(())
543 }
544 }
545
546 fn visit_const(&mut self, ct: I::Const) -> Self::Result {
547 if ct.outer_exclusive_binder() > self.outer_index {
553 ControlFlow::Break(FoundEscapingVars)
554 } else {
555 ControlFlow::Continue(())
556 }
557 }
558
559 #[inline]
560 fn visit_predicate(&mut self, predicate: I::Predicate) -> Self::Result {
561 if predicate.outer_exclusive_binder() > self.outer_index {
562 ControlFlow::Break(FoundEscapingVars)
563 } else {
564 ControlFlow::Continue(())
565 }
566 }
567
568 #[inline]
569 fn visit_clauses(&mut self, clauses: I::Clauses) -> Self::Result {
570 if clauses.outer_exclusive_binder() > self.outer_index {
571 ControlFlow::Break(FoundEscapingVars)
572 } else {
573 ControlFlow::Continue(())
574 }
575 }
576}
577
578struct HasErrorVisitor;
579
580impl<I: Interner> TypeVisitor<I> for HasErrorVisitor {
581 type Result = ControlFlow<I::ErrorGuaranteed>;
582
583 fn visit_error(&mut self, guar: <I as Interner>::ErrorGuaranteed) -> Self::Result {
584 ControlFlow::Break(guar)
585 }
586}