Skip to main content

rustc_type_ir/
universe.rs

1use tracing::{debug, instrument};
2
3use crate::data_structures::HashSet;
4use crate::inherent::*;
5use crate::visit::TypeVisitableExt;
6use crate::{
7    ConstKind, InferCtxtLike, InferTy, Interner, Region, RegionKind, TyKind, TypeFoldable,
8    TypeSuperVisitable, TypeVisitable, TypeVisitor, UniverseIndex,
9};
10
11/// The largest universe a variable or placeholder was from in `t`
12pub fn max_universe<Infcx: InferCtxtLike<Interner = I>, I: Interner, T: TypeFoldable<I>>(
13    infcx: &Infcx,
14    t: T,
15) -> UniverseIndex {
16    max_universe_inner::<_, _, _, true, true>(infcx, t)
17}
18
19/// The largest universe a variable was from in `t`
20pub fn max_universe_of_infer_vars<
21    Infcx: InferCtxtLike<Interner = I>,
22    I: Interner,
23    T: TypeFoldable<I>,
24>(
25    infcx: &Infcx,
26    t: T,
27) -> UniverseIndex {
28    max_universe_inner::<_, _, _, false, true>(infcx, t)
29}
30
31/// The largest universe a placeholder was from in `t`
32pub fn max_universe_of_placeholders<
33    Infcx: InferCtxtLike<Interner = I>,
34    I: Interner,
35    T: TypeFoldable<I>,
36>(
37    infcx: &Infcx,
38    t: T,
39) -> UniverseIndex {
40    max_universe_inner::<_, _, _, true, false>(infcx, t)
41}
42
43fn max_universe_inner<
44    Infcx: InferCtxtLike<Interner = I>,
45    I: Interner,
46    T: TypeFoldable<I>,
47    const VISIT_PLACEHOLDER: bool,
48    const VISIT_INFER: bool,
49>(
50    infcx: &Infcx,
51    t: T,
52) -> UniverseIndex {
53    if !MaxUniverse::<Infcx, I, VISIT_PLACEHOLDER, VISIT_INFER>::needs_visit(&t) {
54        return UniverseIndex::ROOT;
55    }
56
57    let mut visitor = MaxUniverse::<_, _, VISIT_PLACEHOLDER, VISIT_INFER>::new(infcx);
58    // FIXME: make this a debug_assert and let callers resolve vars. Then the input only needs to
59    // be `TypeVisitable`.
60    let t = infcx.resolve_vars_if_possible(t);
61    t.visit_with(&mut visitor);
62    visitor.max_universe()
63}
64
65struct MaxUniverse<
66    'a,
67    Infcx: InferCtxtLike<Interner = I>,
68    I: Interner,
69    const VISIT_PLACEHOLDER: bool,
70    const VISIT_INFER: bool,
71> {
72    max_universe: UniverseIndex,
73    infcx: &'a Infcx,
74    cache: HashSet<I::Ty>,
75}
76
77impl<
78    'a,
79    Infcx: InferCtxtLike<Interner = I>,
80    I: Interner,
81    const VISIT_PLACEHOLDER: bool,
82    const VISIT_INFER: bool,
83> MaxUniverse<'a, Infcx, I, VISIT_PLACEHOLDER, VISIT_INFER>
84{
85    fn new(infcx: &'a Infcx) -> Self {
86        MaxUniverse { infcx, max_universe: UniverseIndex::ROOT, cache: Default::default() }
87    }
88
89    fn max_universe(self) -> UniverseIndex {
90        self.max_universe
91    }
92
93    x;#[instrument(ret, level = "debug")]
94    fn needs_visit<T: TypeVisitable<I>>(t: &T) -> bool {
95        (VISIT_PLACEHOLDER && t.has_placeholders()) || (VISIT_INFER && t.has_infer())
96    }
97}
98
99impl<
100    'a,
101    Infcx: InferCtxtLike<Interner = I>,
102    I: Interner,
103    const VISIT_PLACEHOLDER: bool,
104    const VISIT_INFER: bool,
105> TypeVisitor<I> for MaxUniverse<'a, Infcx, I, VISIT_PLACEHOLDER, VISIT_INFER>
106{
107    type Result = ();
108
109    fn visit_ty(&mut self, t: I::Ty) {
110        if !Self::needs_visit(&t) {
111            return;
112        }
113
114        if self.cache.contains(&t) {
115            return;
116        }
117
118        match t.kind() {
119            TyKind::Placeholder(p) if VISIT_PLACEHOLDER => {
120                self.max_universe = self.max_universe.max(p.universe)
121            }
122            TyKind::Infer(InferTy::TyVar(inf)) if VISIT_INFER => {
123                let u = self.infcx.universe_of_ty(inf).unwrap();
124                {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_type_ir/src/universe.rs:124",
                        "rustc_type_ir::universe", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_type_ir/src/universe.rs"),
                        ::tracing_core::__macro_support::Option::Some(124u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_type_ir::universe"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("var {0:?} in universe {1:?}",
                                                    inf, u) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("var {inf:?} in universe {u:?}");
125                self.max_universe = self.max_universe.max(u);
126            }
127            _ => t.super_visit_with(self),
128        }
129
130        if !self.cache.insert(t) {
    {
        ::core::panicking::panic_fmt(format_args!("we shouldn\'t visit {0:?} twice",
                t));
    }
};assert!(self.cache.insert(t), "we shouldn't visit {t:?} twice");
131    }
132
133    fn visit_const(&mut self, c: I::Const) {
134        if !Self::needs_visit(&c) {
135            return;
136        }
137
138        match c.kind() {
139            ConstKind::Placeholder(p) if VISIT_PLACEHOLDER => {
140                self.max_universe = self.max_universe.max(p.universe)
141            }
142            ConstKind::Infer(rustc_type_ir::InferConst::Var(inf)) if VISIT_INFER => {
143                let u = self.infcx.universe_of_ct(inf).unwrap();
144                {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_type_ir/src/universe.rs:144",
                        "rustc_type_ir::universe", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_type_ir/src/universe.rs"),
                        ::tracing_core::__macro_support::Option::Some(144u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_type_ir::universe"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("var {0:?} in universe {1:?}",
                                                    inf, u) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("var {inf:?} in universe {u:?}");
145                self.max_universe = self.max_universe.max(u);
146            }
147            _ => c.super_visit_with(self),
148        }
149    }
150
151    fn visit_region(&mut self, r: Region<I>) {
152        match r.kind() {
153            RegionKind::RePlaceholder(p) if VISIT_PLACEHOLDER => {
154                self.max_universe = self.max_universe.max(p.universe)
155            }
156            RegionKind::ReVar(var) if VISIT_INFER => {
157                match self.infcx.opportunistic_resolve_lt_var(var).kind() {
158                    RegionKind::RePlaceholder(p) if VISIT_PLACEHOLDER => {
159                        self.max_universe = self.max_universe.max(p.universe)
160                    }
161                    RegionKind::ReVar(var) if VISIT_INFER => {
162                        let u = self.infcx.universe_of_lt(var).unwrap();
163                        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_type_ir/src/universe.rs:163",
                        "rustc_type_ir::universe", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_type_ir/src/universe.rs"),
                        ::tracing_core::__macro_support::Option::Some(163u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_type_ir::universe"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("var {0:?} in universe {1:?}",
                                                    var, u) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("var {var:?} in universe {u:?}");
164                        self.max_universe = self.max_universe.max(u);
165                    }
166                    _ => (),
167                }
168            }
169            _ => (),
170        }
171    }
172}