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, c: I::Clauses) -> Self::Result {
124        c.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_CORO)
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}