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::consts::ConstExt;
8use crate::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypingEnv, Unnormalized};
9
10/// Represents whether some type is inhabited in a given context.
11/// Examples of uninhabited types are `!`, `enum Void {}`, or a struct
12/// containing either of those types.
13/// A type's inhabitedness may depend on the `ParamEnv` as well as what types
14/// are visible in the current module.
15#[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) -> Self {
        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 {
            Self::True => ::core::fmt::Formatter::write_str(f, "True"),
            Self::False => ::core::fmt::Formatter::write_str(f, "False"),
            Self::ConstIsZero(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "ConstIsZero", &__self_0),
            Self::NotInModule(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "NotInModule", &__self_0),
            Self::GenericType(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "GenericType", &__self_0),
            Self::OpaqueType(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "OpaqueType", &__self_0),
            Self::And(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "And",
                    &__self_0),
            Self::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: &Self) -> bool {
        ::core::intrinsics::discriminant_value(self) ==
                ::core::intrinsics::discriminant_value(other) &&
            match (self, other) {
                (Self::ConstIsZero(__self_0), Self::ConstIsZero(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (Self::NotInModule(__self_0), Self::NotInModule(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (Self::GenericType(__self_0), Self::GenericType(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (Self::OpaqueType(__self_0), Self::OpaqueType(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (Self::And(__self_0), Self::And(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (Self::Or(__self_0), Self::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)]
16pub enum InhabitedPredicate<'tcx> {
17    /// Inhabited
18    True,
19    /// Uninhabited
20    False,
21    /// Uninhabited when a const value is non-zero. This occurs when there is an
22    /// array of uninhabited items, but the array is inhabited if it is empty.
23    ConstIsZero(ty::Const<'tcx>),
24    /// Uninhabited if within a certain module. This occurs when an uninhabited
25    /// type has restricted visibility.
26    NotInModule(ModId),
27    /// Inhabited if some generic type is inhabited.
28    /// These are replaced by calling [`Self::instantiate`].
29    GenericType(Ty<'tcx>),
30    /// Inhabited if either we don't know the hidden type or we know it and it is inhabited.
31    OpaqueType(OpaqueTypeKey<'tcx>),
32    /// A AND B
33    And(&'tcx [InhabitedPredicate<'tcx>; 2]),
34    /// A OR B
35    Or(&'tcx [InhabitedPredicate<'tcx>; 2]),
36}
37
38impl<'tcx> InhabitedPredicate<'tcx> {
39    /// Returns true if the corresponding type is inhabited in the given `ParamEnv` and module.
40    pub fn apply(
41        self,
42        tcx: TyCtxt<'tcx>,
43        typing_env: TypingEnv<'tcx>,
44        module_def_id: LocalModId,
45    ) -> bool {
46        self.apply_revealing_opaque(tcx, typing_env, module_def_id, &|_| None)
47    }
48
49    /// Returns true if the corresponding type is inhabited in the given `ParamEnv` and module,
50    /// revealing opaques when possible.
51    pub fn apply_revealing_opaque(
52        self,
53        tcx: TyCtxt<'tcx>,
54        typing_env: TypingEnv<'tcx>,
55        module_def_id: LocalModId,
56        reveal_opaque: &impl Fn(OpaqueTypeKey<'tcx>) -> Option<Ty<'tcx>>,
57    ) -> bool {
58        let Ok(result) = self.apply_inner::<!>(
59            tcx,
60            typing_env,
61            &mut Default::default(),
62            &|id| Ok(tcx.is_descendant_of(module_def_id, id)),
63            reveal_opaque,
64        );
65        result
66    }
67
68    /// Same as `apply`, but returns `None` if self contains a module predicate
69    pub fn apply_any_module(self, tcx: TyCtxt<'tcx>, typing_env: TypingEnv<'tcx>) -> Option<bool> {
70        self.apply_inner(tcx, typing_env, &mut Default::default(), &|_| Err(()), &|_| None).ok()
71    }
72
73    /// Same as `apply`, but `NotInModule(_)` predicates yield `false`. That is,
74    /// privately uninhabited types are considered always uninhabited.
75    pub fn apply_ignore_module(self, tcx: TyCtxt<'tcx>, typing_env: TypingEnv<'tcx>) -> bool {
76        let Ok(result) =
77            self.apply_inner::<!>(tcx, typing_env, &mut Default::default(), &|_| Ok(true), &|_| {
78                None
79            });
80        result
81    }
82
83    {}
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/c1070d69382b8d2f2eb65119c738a77d9e324c9e/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs"),
                                ::tracing_core::__macro_support::Option::Some(83u32),
                                ::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/c1070d69382b8d2f2eb65119c738a77d9e324c9e/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs:83",
                        "rustc_middle::ty::inhabitedness::inhabited_predicate",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/c1070d69382b8d2f2eb65119c738a77d9e324c9e/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs"),
                        ::tracing_core::__macro_support::Option::Some(83u32),
                        ::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)]
84    fn apply_inner<E: std::fmt::Debug>(
85        self,
86        tcx: TyCtxt<'tcx>,
87        typing_env: TypingEnv<'tcx>,
88        eval_stack: &mut SmallVec<[Ty<'tcx>; 1]>, // for cycle detection
89        in_module: &impl Fn(ModId) -> Result<bool, E>,
90        reveal_opaque: &impl Fn(OpaqueTypeKey<'tcx>) -> Option<Ty<'tcx>>,
91    ) -> Result<bool, E> {
92        match self {
93            Self::False => Ok(false),
94            Self::True => Ok(true),
95            Self::ConstIsZero(const_) => match const_.try_to_target_usize(tcx) {
96                None | Some(0) => Ok(true),
97                Some(1..) => Ok(false),
98            },
99            Self::NotInModule(id) => in_module(id).map(|in_mod| !in_mod),
100            // `t` may be a projection, for which `inhabited_predicate` returns a `GenericType`. As
101            // we have a param_env available, we can do better.
102            Self::GenericType(t) => {
103                let normalized_pred = tcx
104                    .try_normalize_erasing_regions(typing_env, Unnormalized::new_wip(t))
105                    .map_or(self, |t| t.inhabited_predicate(tcx));
106                match normalized_pred {
107                    // We don't have more information than we started with, so consider inhabited.
108                    Self::GenericType(_) => Ok(true),
109                    pred => {
110                        // A type which is cyclic when monomorphized can happen here since the
111                        // layout error would only trigger later. See e.g. `tests/ui/sized/recursive-type-2.rs`.
112                        if eval_stack.contains(&t) {
113                            return Ok(true); // Recover; this will error later.
114                        }
115                        eval_stack.push(t);
116                        let ret =
117                            pred.apply_inner(tcx, typing_env, eval_stack, in_module, reveal_opaque);
118                        eval_stack.pop();
119                        ret
120                    }
121                }
122            }
123            Self::OpaqueType(key) => match reveal_opaque(key) {
124                // Unknown opaque is assumed inhabited.
125                None => Ok(true),
126                // Known opaque type is inspected recursively.
127                Some(t) => {
128                    // A cyclic opaque type can happen in corner cases that would only error later.
129                    // See e.g. `tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.rs`.
130                    if eval_stack.contains(&t) {
131                        return Ok(true); // Recover; this will error later.
132                    }
133                    eval_stack.push(t);
134                    let ret = t.inhabited_predicate(tcx).apply_inner(
135                        tcx,
136                        typing_env,
137                        eval_stack,
138                        in_module,
139                        reveal_opaque,
140                    );
141                    eval_stack.pop();
142                    ret
143                }
144            },
145            Self::And([a, b]) => try_and(a, b, |x| {
146                x.apply_inner(tcx, typing_env, eval_stack, in_module, reveal_opaque)
147            }),
148            Self::Or([a, b]) => try_or(a, b, |x| {
149                x.apply_inner(tcx, typing_env, eval_stack, in_module, reveal_opaque)
150            }),
151        }
152    }
153
154    pub fn and(self, tcx: TyCtxt<'tcx>, other: Self) -> Self {
155        self.reduce_and(tcx, other).unwrap_or_else(|| Self::And(tcx.arena.alloc([self, other])))
156    }
157
158    pub fn or(self, tcx: TyCtxt<'tcx>, other: Self) -> Self {
159        self.reduce_or(tcx, other).unwrap_or_else(|| Self::Or(tcx.arena.alloc([self, other])))
160    }
161
162    pub fn all(tcx: TyCtxt<'tcx>, iter: impl IntoIterator<Item = Self>) -> Self {
163        let mut result = Self::True;
164        for pred in iter {
165            if pred == Self::False {
166                return Self::False;
167            }
168            result = result.and(tcx, pred);
169        }
170        result
171    }
172
173    pub fn any(tcx: TyCtxt<'tcx>, iter: impl IntoIterator<Item = Self>) -> Self {
174        let mut result = Self::False;
175        for pred in iter {
176            if pred == Self::True {
177                return Self::True;
178            }
179            result = result.or(tcx, pred);
180        }
181        result
182    }
183
184    fn reduce_and(self, tcx: TyCtxt<'tcx>, other: Self) -> Option<Self> {
185        match (self, other) {
186            (Self::True, a) | (a, Self::True) => Some(a),
187            (Self::False, _) | (_, Self::False) => Some(Self::False),
188            (Self::ConstIsZero(a), Self::ConstIsZero(b)) if a == b => Some(Self::ConstIsZero(a)),
189            (Self::NotInModule(a), Self::NotInModule(b)) if a == b => Some(Self::NotInModule(a)),
190            (Self::NotInModule(a), Self::NotInModule(b)) if tcx.is_descendant_of(a, b) => {
191                Some(Self::NotInModule(b))
192            }
193            (Self::NotInModule(a), Self::NotInModule(b)) if tcx.is_descendant_of(b, a) => {
194                Some(Self::NotInModule(a))
195            }
196            (Self::GenericType(a), Self::GenericType(b)) if a == b => Some(Self::GenericType(a)),
197            (Self::And(&[a, b]), c) | (c, Self::And(&[a, b])) => {
198                if let Some(ac) = a.reduce_and(tcx, c) {
199                    Some(ac.and(tcx, b))
200                } else if let Some(bc) = b.reduce_and(tcx, c) {
201                    Some(Self::And(tcx.arena.alloc([a, bc])))
202                } else {
203                    None
204                }
205            }
206            _ => None,
207        }
208    }
209
210    fn reduce_or(self, tcx: TyCtxt<'tcx>, other: Self) -> Option<Self> {
211        match (self, other) {
212            (Self::True, _) | (_, Self::True) => Some(Self::True),
213            (Self::False, a) | (a, Self::False) => Some(a),
214            (Self::ConstIsZero(a), Self::ConstIsZero(b)) if a == b => Some(Self::ConstIsZero(a)),
215            (Self::NotInModule(a), Self::NotInModule(b)) if a == b => Some(Self::NotInModule(a)),
216            (Self::NotInModule(a), Self::NotInModule(b)) if tcx.is_descendant_of(a, b) => {
217                Some(Self::NotInModule(a))
218            }
219            (Self::NotInModule(a), Self::NotInModule(b)) if tcx.is_descendant_of(b, a) => {
220                Some(Self::NotInModule(b))
221            }
222            (Self::GenericType(a), Self::GenericType(b)) if a == b => Some(Self::GenericType(a)),
223            (Self::Or(&[a, b]), c) | (c, Self::Or(&[a, b])) => {
224                if let Some(ac) = a.reduce_or(tcx, c) {
225                    Some(ac.or(tcx, b))
226                } else if let Some(bc) = b.reduce_or(tcx, c) {
227                    Some(Self::Or(tcx.arena.alloc([a, bc])))
228                } else {
229                    None
230                }
231            }
232            _ => None,
233        }
234    }
235
236    /// Replaces generic types with its corresponding predicate
237    pub fn instantiate(self, tcx: TyCtxt<'tcx>, args: ty::GenericArgsRef<'tcx>) -> Self {
238        self.instantiate_opt(tcx, args).unwrap_or(self)
239    }
240
241    /// Same as [`Self::instantiate`], but if there is no generics to
242    /// instantiate, returns `None`. This is useful because it lets us avoid
243    /// allocating a recursive copy of everything when the result is unchanged.
244    ///
245    /// Only used to implement `instantiate` itself.
246    fn instantiate_opt(self, tcx: TyCtxt<'tcx>, args: ty::GenericArgsRef<'tcx>) -> Option<Self> {
247        match self {
248            Self::ConstIsZero(c) => {
249                let c = ty::EarlyBinder::bind(tcx, c).instantiate(tcx, args).skip_norm_wip();
250                let pred = match c.try_to_target_usize(tcx) {
251                    Some(0) => Self::True,
252                    Some(1..) => Self::False,
253                    None => Self::ConstIsZero(c),
254                };
255                Some(pred)
256            }
257            Self::GenericType(t) => Some(
258                ty::EarlyBinder::bind(tcx, t)
259                    .instantiate(tcx, args)
260                    .skip_norm_wip()
261                    .inhabited_predicate(tcx),
262            ),
263            Self::And(&[a, b]) => match a.instantiate_opt(tcx, args) {
264                None => b.instantiate_opt(tcx, args).map(|b| a.and(tcx, b)),
265                Some(InhabitedPredicate::False) => Some(InhabitedPredicate::False),
266                Some(a) => Some(a.and(tcx, b.instantiate_opt(tcx, args).unwrap_or(b))),
267            },
268            Self::Or(&[a, b]) => match a.instantiate_opt(tcx, args) {
269                None => b.instantiate_opt(tcx, args).map(|b| a.or(tcx, b)),
270                Some(InhabitedPredicate::True) => Some(InhabitedPredicate::True),
271                Some(a) => Some(a.or(tcx, b.instantiate_opt(tcx, args).unwrap_or(b))),
272            },
273            Self::True | Self::False | Self::NotInModule(_) => None,
274            Self::OpaqueType(_) => {
275                ::rustc_span::macros::bug_impl(None,
    format_args!("unexpected OpaqueType in InhabitedPredicate"),
    Location::caller());bug!("unexpected OpaqueType in InhabitedPredicate");
276            }
277        }
278    }
279}
280
281// this is basically like `f(a)? && f(b)?` but different in the case of
282// `Ok(false) && Err(_) -> Ok(false)`
283fn try_and<T, E>(a: T, b: T, mut f: impl FnMut(T) -> Result<bool, E>) -> Result<bool, E> {
284    let a = f(a);
285    if #[allow(non_exhaustive_omitted_patterns)] match a {
    Ok(false) => true,
    _ => false,
}matches!(a, Ok(false)) {
286        return Ok(false);
287    }
288    match (a, f(b)) {
289        (_, Ok(false)) | (Ok(false), _) => Ok(false),
290        (Ok(true), Ok(true)) => Ok(true),
291        (Err(e), _) | (_, Err(e)) => Err(e),
292    }
293}
294
295fn try_or<T, E>(a: T, b: T, mut f: impl FnMut(T) -> Result<bool, E>) -> Result<bool, E> {
296    let a = f(a);
297    if #[allow(non_exhaustive_omitted_patterns)] match a {
    Ok(true) => true,
    _ => false,
}matches!(a, Ok(true)) {
298        return Ok(true);
299    }
300    match (a, f(b)) {
301        (_, Ok(true)) | (Ok(true), _) => Ok(true),
302        (Ok(false), Ok(false)) => Ok(false),
303        (Err(e), _) | (_, Err(e)) => Err(e),
304    }
305}