Skip to main content

rustc_middle/ty/inhabitedness/
inhabited_predicate.rs

1use rustc_macros::StableHash;
2use rustc_span::bug;
3use rustc_span::def_id::{LocalModId, ModId};
4use smallvec::SmallVec;
5use tracing::instrument;
6
7use crate::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypingEnv, Unnormalized};
8
9/// Represents whether some type is inhabited in a given context.
10/// Examples of uninhabited types are `!`, `enum Void {}`, or a struct
11/// containing either of those types.
12/// A type's inhabitedness may depend on the `ParamEnv` as well as what types
13/// are visible in the current module.
14#[derive(#[automatically_derived]
#[doc(hidden)]
unsafe impl<'tcx> ::core::clone::TrivialClone for InhabitedPredicate<'tcx> { }
#[automatically_derived]
impl<'tcx> ::core::clone::Clone for InhabitedPredicate<'tcx> {
    #[inline]
    fn clone(&self) -> InhabitedPredicate<'tcx> {
        let _: ::core::clone::AssertParamIsClone<ty::Const<'tcx>>;
        let _: ::core::clone::AssertParamIsClone<ModId>;
        let _: ::core::clone::AssertParamIsClone<Ty<'tcx>>;
        let _: ::core::clone::AssertParamIsClone<OpaqueTypeKey<'tcx>>;
        let _:
                ::core::clone::AssertParamIsClone<&'tcx [InhabitedPredicate<'tcx>; 2]>;
        let _:
                ::core::clone::AssertParamIsClone<&'tcx [InhabitedPredicate<'tcx>; 2]>;
        *self
    }
}Clone, #[automatically_derived]
impl<'tcx> ::core::marker::Copy for InhabitedPredicate<'tcx> { }Copy, #[automatically_derived]
impl<'tcx> ::core::fmt::Debug for InhabitedPredicate<'tcx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            InhabitedPredicate::True =>
                ::core::fmt::Formatter::write_str(f, "True"),
            InhabitedPredicate::False =>
                ::core::fmt::Formatter::write_str(f, "False"),
            InhabitedPredicate::ConstIsZero(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "ConstIsZero", &__self_0),
            InhabitedPredicate::NotInModule(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "NotInModule", &__self_0),
            InhabitedPredicate::GenericType(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "GenericType", &__self_0),
            InhabitedPredicate::OpaqueType(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "OpaqueType", &__self_0),
            InhabitedPredicate::And(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "And",
                    &__self_0),
            InhabitedPredicate::Or(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Or",
                    &__self_0),
        }
    }
}Debug, #[automatically_derived]
impl<'tcx> ::core::marker::StructuralPartialEq for InhabitedPredicate<'tcx> {
}
#[automatically_derived]
impl<'tcx> ::core::cmp::PartialEq for InhabitedPredicate<'tcx> {
    #[inline]
    fn eq(&self, other: &InhabitedPredicate<'tcx>) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (InhabitedPredicate::ConstIsZero(__self_0),
                    InhabitedPredicate::ConstIsZero(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (InhabitedPredicate::NotInModule(__self_0),
                    InhabitedPredicate::NotInModule(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (InhabitedPredicate::GenericType(__self_0),
                    InhabitedPredicate::GenericType(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (InhabitedPredicate::OpaqueType(__self_0),
                    InhabitedPredicate::OpaqueType(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (InhabitedPredicate::And(__self_0),
                    InhabitedPredicate::And(__arg1_0)) => __self_0 == __arg1_0,
                (InhabitedPredicate::Or(__self_0),
                    InhabitedPredicate::Or(__arg1_0)) => __self_0 == __arg1_0,
                _ => true,
            }
    }
}PartialEq, const _: () =
    {
        impl<'tcx> ::rustc_data_structures::stable_hash::StableHash for
            InhabitedPredicate<'tcx> {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                ::std::mem::discriminant(self).stable_hash(__hcx, __hasher);
                match *self {
                    InhabitedPredicate::True => {}
                    InhabitedPredicate::False => {}
                    InhabitedPredicate::ConstIsZero(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                    InhabitedPredicate::NotInModule(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                    InhabitedPredicate::GenericType(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                    InhabitedPredicate::OpaqueType(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                    InhabitedPredicate::And(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                    InhabitedPredicate::Or(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash)]
15pub enum InhabitedPredicate<'tcx> {
16    /// Inhabited
17    True,
18    /// Uninhabited
19    False,
20    /// Uninhabited when a const value is non-zero. This occurs when there is an
21    /// array of uninhabited items, but the array is inhabited if it is empty.
22    ConstIsZero(ty::Const<'tcx>),
23    /// Uninhabited if within a certain module. This occurs when an uninhabited
24    /// type has restricted visibility.
25    NotInModule(ModId),
26    /// Inhabited if some generic type is inhabited.
27    /// These are replaced by calling [`Self::instantiate`].
28    GenericType(Ty<'tcx>),
29    /// Inhabited if either we don't know the hidden type or we know it and it is inhabited.
30    OpaqueType(OpaqueTypeKey<'tcx>),
31    /// A AND B
32    And(&'tcx [InhabitedPredicate<'tcx>; 2]),
33    /// A OR B
34    Or(&'tcx [InhabitedPredicate<'tcx>; 2]),
35}
36
37impl<'tcx> InhabitedPredicate<'tcx> {
38    /// Returns true if the corresponding type is inhabited in the given `ParamEnv` and module.
39    pub fn apply(
40        self,
41        tcx: TyCtxt<'tcx>,
42        typing_env: TypingEnv<'tcx>,
43        module_def_id: LocalModId,
44    ) -> bool {
45        self.apply_revealing_opaque(tcx, typing_env, module_def_id, &|_| None)
46    }
47
48    /// Returns true if the corresponding type is inhabited in the given `ParamEnv` and module,
49    /// revealing opaques when possible.
50    pub fn apply_revealing_opaque(
51        self,
52        tcx: TyCtxt<'tcx>,
53        typing_env: TypingEnv<'tcx>,
54        module_def_id: LocalModId,
55        reveal_opaque: &impl Fn(OpaqueTypeKey<'tcx>) -> Option<Ty<'tcx>>,
56    ) -> bool {
57        let Ok(result) = self.apply_inner::<!>(
58            tcx,
59            typing_env,
60            &mut Default::default(),
61            &|id| Ok(tcx.is_descendant_of(module_def_id, id)),
62            reveal_opaque,
63        );
64        result
65    }
66
67    /// Same as `apply`, but returns `None` if self contains a module predicate
68    pub fn apply_any_module(self, tcx: TyCtxt<'tcx>, typing_env: TypingEnv<'tcx>) -> Option<bool> {
69        self.apply_inner(tcx, typing_env, &mut Default::default(), &|_| Err(()), &|_| None).ok()
70    }
71
72    /// Same as `apply`, but `NotInModule(_)` predicates yield `false`. That is,
73    /// privately uninhabited types are considered always uninhabited.
74    pub fn apply_ignore_module(self, tcx: TyCtxt<'tcx>, typing_env: TypingEnv<'tcx>) -> bool {
75        let Ok(result) =
76            self.apply_inner::<!>(tcx, typing_env, &mut Default::default(), &|_| Ok(true), &|_| {
77                None
78            });
79        result
80    }
81
82    {}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL &&
            ::tracing::Level::DEBUG <=
                ::tracing::level_filters::LevelFilter::current() || { false }
    {
    __tracing_attr_span =
        {
            use ::tracing::__macro_support::Callsite as _;
            static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                {
                    static META: ::tracing::Metadata<'static> =
                        {
                            ::tracing_core::metadata::Metadata::new("apply_inner",
                                "rustc_middle::ty::inhabitedness::inhabited_predicate",
                                ::tracing::Level::DEBUG,
                                ::tracing_core::__macro_support::Option::Some("/rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs"),
                                ::tracing_core::__macro_support::Option::Some(82u32),
                                ::tracing_core::__macro_support::Option::Some("rustc_middle::ty::inhabitedness::inhabited_predicate"),
                                ::tracing_core::field::FieldSet::new(&[{
                                                    const NAME:
                                                        ::tracing::__macro_support::FieldName<{
                                                            ::tracing::__macro_support::FieldName::len("self")
                                                        }> =
                                                        ::tracing::__macro_support::FieldName::new("self");
                                                    NAME.as_str()
                                                },
                                                {
                                                    const NAME:
                                                        ::tracing::__macro_support::FieldName<{
                                                            ::tracing::__macro_support::FieldName::len("eval_stack")
                                                        }> =
                                                        ::tracing::__macro_support::FieldName::new("eval_stack");
                                                    NAME.as_str()
                                                }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                ::tracing::metadata::Kind::SPAN)
                        };
                    ::tracing::callsite::DefaultCallsite::new(&META)
                };
            let mut interest = ::tracing::subscriber::Interest::never();
            if ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::LevelFilter::current() &&
                        { interest = __CALLSITE.interest(); !interest.is_never() }
                    &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest) {
                let meta = __CALLSITE.metadata();
                ::tracing::Span::new(meta,
                    &{
                            #[allow(unused_imports)]
                            use ::tracing::field::{debug, display, Value};
                            meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&self)
                                                        as &dyn ::tracing::field::Value)),
                                            (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&eval_stack)
                                                        as &dyn ::tracing::field::Value))])
                        })
            } else {
                let span =
                    ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                {};
                span
            }
        };
    __tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
    (move ||
                {

                    #[allow(unknown_lints, unreachable_code, clippy ::
                    diverging_sub_expression, clippy :: empty_loop, clippy ::
                    let_unit_value, clippy :: let_with_type_underscore, clippy
                    :: needless_return, clippy :: unreachable)]
                    if false {
                        let __tracing_attr_fake_return: Result<bool, E> = loop {};
                        return __tracing_attr_fake_return;
                    }
                    {
                        match self {
                            Self::False => Ok(false),
                            Self::True => Ok(true),
                            Self::ConstIsZero(const_) =>
                                match const_.try_to_target_usize(tcx) {
                                    None | Some(0) => Ok(true),
                                    Some(1..) => Ok(false),
                                },
                            Self::NotInModule(id) =>
                                in_module(id).map(|in_mod| !in_mod),
                            Self::GenericType(t) => {
                                let normalized_pred =
                                    tcx.try_normalize_erasing_regions(typing_env,
                                            Unnormalized::new_wip(t)).map_or(self,
                                        |t| t.inhabited_predicate(tcx));
                                match normalized_pred {
                                    Self::GenericType(_) => Ok(true),
                                    pred => {
                                        if eval_stack.contains(&t) { return Ok(true); }
                                        eval_stack.push(t);
                                        let ret =
                                            pred.apply_inner(tcx, typing_env, eval_stack, in_module,
                                                reveal_opaque);
                                        eval_stack.pop();
                                        ret
                                    }
                                }
                            }
                            Self::OpaqueType(key) =>
                                match reveal_opaque(key) {
                                    None => Ok(true),
                                    Some(t) => {
                                        if eval_stack.contains(&t) { return Ok(true); }
                                        eval_stack.push(t);
                                        let ret =
                                            t.inhabited_predicate(tcx).apply_inner(tcx, typing_env,
                                                eval_stack, in_module, reveal_opaque);
                                        eval_stack.pop();
                                        ret
                                    }
                                },
                            Self::And([a, b]) =>
                                try_and(a, b,
                                    |x|
                                        {
                                            x.apply_inner(tcx, typing_env, eval_stack, in_module,
                                                reveal_opaque)
                                        }),
                            Self::Or([a, b]) =>
                                try_or(a, b,
                                    |x|
                                        {
                                            x.apply_inner(tcx, typing_env, eval_stack, in_module,
                                                reveal_opaque)
                                        }),
                        }
                    }
                })();
{
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs:82",
                        "rustc_middle::ty::inhabitedness::inhabited_predicate",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs"),
                        ::tracing_core::__macro_support::Option::Some(82u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_middle::ty::inhabitedness::inhabited_predicate"),
                        ::tracing_core::field::FieldSet::new(&[{
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("return")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("return");
                                            NAME.as_str()
                                        }], ::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(&::tracing::field::debug(&x)
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};
x;#[instrument(level = "debug", skip(tcx, typing_env, in_module, reveal_opaque), ret)]
83    fn apply_inner<E: std::fmt::Debug>(
84        self,
85        tcx: TyCtxt<'tcx>,
86        typing_env: TypingEnv<'tcx>,
87        eval_stack: &mut SmallVec<[Ty<'tcx>; 1]>, // for cycle detection
88        in_module: &impl Fn(ModId) -> Result<bool, E>,
89        reveal_opaque: &impl Fn(OpaqueTypeKey<'tcx>) -> Option<Ty<'tcx>>,
90    ) -> Result<bool, E> {
91        match self {
92            Self::False => Ok(false),
93            Self::True => Ok(true),
94            Self::ConstIsZero(const_) => match const_.try_to_target_usize(tcx) {
95                None | Some(0) => Ok(true),
96                Some(1..) => Ok(false),
97            },
98            Self::NotInModule(id) => in_module(id).map(|in_mod| !in_mod),
99            // `t` may be a projection, for which `inhabited_predicate` returns a `GenericType`. As
100            // we have a param_env available, we can do better.
101            Self::GenericType(t) => {
102                let normalized_pred = tcx
103                    .try_normalize_erasing_regions(typing_env, Unnormalized::new_wip(t))
104                    .map_or(self, |t| t.inhabited_predicate(tcx));
105                match normalized_pred {
106                    // We don't have more information than we started with, so consider inhabited.
107                    Self::GenericType(_) => Ok(true),
108                    pred => {
109                        // A type which is cyclic when monomorphized can happen here since the
110                        // layout error would only trigger later. See e.g. `tests/ui/sized/recursive-type-2.rs`.
111                        if eval_stack.contains(&t) {
112                            return Ok(true); // Recover; this will error later.
113                        }
114                        eval_stack.push(t);
115                        let ret =
116                            pred.apply_inner(tcx, typing_env, eval_stack, in_module, reveal_opaque);
117                        eval_stack.pop();
118                        ret
119                    }
120                }
121            }
122            Self::OpaqueType(key) => match reveal_opaque(key) {
123                // Unknown opaque is assumed inhabited.
124                None => Ok(true),
125                // Known opaque type is inspected recursively.
126                Some(t) => {
127                    // A cyclic opaque type can happen in corner cases that would only error later.
128                    // See e.g. `tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.rs`.
129                    if eval_stack.contains(&t) {
130                        return Ok(true); // Recover; this will error later.
131                    }
132                    eval_stack.push(t);
133                    let ret = t.inhabited_predicate(tcx).apply_inner(
134                        tcx,
135                        typing_env,
136                        eval_stack,
137                        in_module,
138                        reveal_opaque,
139                    );
140                    eval_stack.pop();
141                    ret
142                }
143            },
144            Self::And([a, b]) => try_and(a, b, |x| {
145                x.apply_inner(tcx, typing_env, eval_stack, in_module, reveal_opaque)
146            }),
147            Self::Or([a, b]) => try_or(a, b, |x| {
148                x.apply_inner(tcx, typing_env, eval_stack, in_module, reveal_opaque)
149            }),
150        }
151    }
152
153    pub fn and(self, tcx: TyCtxt<'tcx>, other: Self) -> Self {
154        self.reduce_and(tcx, other).unwrap_or_else(|| Self::And(tcx.arena.alloc([self, other])))
155    }
156
157    pub fn or(self, tcx: TyCtxt<'tcx>, other: Self) -> Self {
158        self.reduce_or(tcx, other).unwrap_or_else(|| Self::Or(tcx.arena.alloc([self, other])))
159    }
160
161    pub fn all(tcx: TyCtxt<'tcx>, iter: impl IntoIterator<Item = Self>) -> Self {
162        let mut result = Self::True;
163        for pred in iter {
164            if pred == Self::False {
165                return Self::False;
166            }
167            result = result.and(tcx, pred);
168        }
169        result
170    }
171
172    pub fn any(tcx: TyCtxt<'tcx>, iter: impl IntoIterator<Item = Self>) -> Self {
173        let mut result = Self::False;
174        for pred in iter {
175            if pred == Self::True {
176                return Self::True;
177            }
178            result = result.or(tcx, pred);
179        }
180        result
181    }
182
183    fn reduce_and(self, tcx: TyCtxt<'tcx>, other: Self) -> Option<Self> {
184        match (self, other) {
185            (Self::True, a) | (a, Self::True) => Some(a),
186            (Self::False, _) | (_, Self::False) => Some(Self::False),
187            (Self::ConstIsZero(a), Self::ConstIsZero(b)) if a == b => Some(Self::ConstIsZero(a)),
188            (Self::NotInModule(a), Self::NotInModule(b)) if a == b => Some(Self::NotInModule(a)),
189            (Self::NotInModule(a), Self::NotInModule(b)) if tcx.is_descendant_of(a, b) => {
190                Some(Self::NotInModule(b))
191            }
192            (Self::NotInModule(a), Self::NotInModule(b)) if tcx.is_descendant_of(b, a) => {
193                Some(Self::NotInModule(a))
194            }
195            (Self::GenericType(a), Self::GenericType(b)) if a == b => Some(Self::GenericType(a)),
196            (Self::And(&[a, b]), c) | (c, Self::And(&[a, b])) => {
197                if let Some(ac) = a.reduce_and(tcx, c) {
198                    Some(ac.and(tcx, b))
199                } else if let Some(bc) = b.reduce_and(tcx, c) {
200                    Some(Self::And(tcx.arena.alloc([a, bc])))
201                } else {
202                    None
203                }
204            }
205            _ => None,
206        }
207    }
208
209    fn reduce_or(self, tcx: TyCtxt<'tcx>, other: Self) -> Option<Self> {
210        match (self, other) {
211            (Self::True, _) | (_, Self::True) => Some(Self::True),
212            (Self::False, a) | (a, Self::False) => Some(a),
213            (Self::ConstIsZero(a), Self::ConstIsZero(b)) if a == b => Some(Self::ConstIsZero(a)),
214            (Self::NotInModule(a), Self::NotInModule(b)) if a == b => Some(Self::NotInModule(a)),
215            (Self::NotInModule(a), Self::NotInModule(b)) if tcx.is_descendant_of(a, b) => {
216                Some(Self::NotInModule(a))
217            }
218            (Self::NotInModule(a), Self::NotInModule(b)) if tcx.is_descendant_of(b, a) => {
219                Some(Self::NotInModule(b))
220            }
221            (Self::GenericType(a), Self::GenericType(b)) if a == b => Some(Self::GenericType(a)),
222            (Self::Or(&[a, b]), c) | (c, Self::Or(&[a, b])) => {
223                if let Some(ac) = a.reduce_or(tcx, c) {
224                    Some(ac.or(tcx, b))
225                } else if let Some(bc) = b.reduce_or(tcx, c) {
226                    Some(Self::Or(tcx.arena.alloc([a, bc])))
227                } else {
228                    None
229                }
230            }
231            _ => None,
232        }
233    }
234
235    /// Replaces generic types with its corresponding predicate
236    pub fn instantiate(self, tcx: TyCtxt<'tcx>, args: ty::GenericArgsRef<'tcx>) -> Self {
237        self.instantiate_opt(tcx, args).unwrap_or(self)
238    }
239
240    /// Same as [`Self::instantiate`], but if there is no generics to
241    /// instantiate, returns `None`. This is useful because it lets us avoid
242    /// allocating a recursive copy of everything when the result is unchanged.
243    ///
244    /// Only used to implement `instantiate` itself.
245    fn instantiate_opt(self, tcx: TyCtxt<'tcx>, args: ty::GenericArgsRef<'tcx>) -> Option<Self> {
246        match self {
247            Self::ConstIsZero(c) => {
248                let c = ty::EarlyBinder::bind(tcx, c).instantiate(tcx, args).skip_norm_wip();
249                let pred = match c.try_to_target_usize(tcx) {
250                    Some(0) => Self::True,
251                    Some(1..) => Self::False,
252                    None => Self::ConstIsZero(c),
253                };
254                Some(pred)
255            }
256            Self::GenericType(t) => Some(
257                ty::EarlyBinder::bind(tcx, t)
258                    .instantiate(tcx, args)
259                    .skip_norm_wip()
260                    .inhabited_predicate(tcx),
261            ),
262            Self::And(&[a, b]) => match a.instantiate_opt(tcx, args) {
263                None => b.instantiate_opt(tcx, args).map(|b| a.and(tcx, b)),
264                Some(InhabitedPredicate::False) => Some(InhabitedPredicate::False),
265                Some(a) => Some(a.and(tcx, b.instantiate_opt(tcx, args).unwrap_or(b))),
266            },
267            Self::Or(&[a, b]) => match a.instantiate_opt(tcx, args) {
268                None => b.instantiate_opt(tcx, args).map(|b| a.or(tcx, b)),
269                Some(InhabitedPredicate::True) => Some(InhabitedPredicate::True),
270                Some(a) => Some(a.or(tcx, b.instantiate_opt(tcx, args).unwrap_or(b))),
271            },
272            Self::True | Self::False | Self::NotInModule(_) => None,
273            Self::OpaqueType(_) => {
274                bug_impl(None, format_args!("unexpected OpaqueType in InhabitedPredicate"),
    Location::caller());bug!("unexpected OpaqueType in InhabitedPredicate");
275            }
276        }
277    }
278}
279
280// this is basically like `f(a)? && f(b)?` but different in the case of
281// `Ok(false) && Err(_) -> Ok(false)`
282fn try_and<T, E>(a: T, b: T, mut f: impl FnMut(T) -> Result<bool, E>) -> Result<bool, E> {
283    let a = f(a);
284    if #[allow(non_exhaustive_omitted_patterns)] match a {
    Ok(false) => true,
    _ => false,
}matches!(a, Ok(false)) {
285        return Ok(false);
286    }
287    match (a, f(b)) {
288        (_, Ok(false)) | (Ok(false), _) => Ok(false),
289        (Ok(true), Ok(true)) => Ok(true),
290        (Err(e), _) | (_, Err(e)) => Err(e),
291    }
292}
293
294fn try_or<T, E>(a: T, b: T, mut f: impl FnMut(T) -> Result<bool, E>) -> Result<bool, E> {
295    let a = f(a);
296    if #[allow(non_exhaustive_omitted_patterns)] match a {
    Ok(true) => true,
    _ => false,
}matches!(a, Ok(true)) {
297        return Ok(true);
298    }
299    match (a, f(b)) {
300        (_, Ok(true)) | (Ok(true), _) => Ok(true),
301        (Ok(false), Ok(false)) => Ok(false),
302        (Err(e), _) | (_, Err(e)) => Err(e),
303    }
304}