1use rustc_macros::StableHash;
2use rustc_span::def_id::{LocalModId, ModId};
3use smallvec::SmallVec;
4use tracing::instrument;
5
6use crate::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypingEnv, Unnormalized};
7
8#[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)]
14pub enum InhabitedPredicate<'tcx> {
15 True,
17 False,
19 ConstIsZero(ty::Const<'tcx>),
22 NotInModule(ModId),
25 GenericType(Ty<'tcx>),
28 OpaqueType(OpaqueTypeKey<'tcx>),
30 And(&'tcx [InhabitedPredicate<'tcx>; 2]),
32 Or(&'tcx [InhabitedPredicate<'tcx>; 2]),
34}
35
36impl<'tcx> InhabitedPredicate<'tcx> {
37 pub fn apply(
39 self,
40 tcx: TyCtxt<'tcx>,
41 typing_env: TypingEnv<'tcx>,
42 module_def_id: LocalModId,
43 ) -> bool {
44 self.apply_revealing_opaque(tcx, typing_env, module_def_id, &|_| None)
45 }
46
47 pub fn apply_revealing_opaque(
50 self,
51 tcx: TyCtxt<'tcx>,
52 typing_env: TypingEnv<'tcx>,
53 module_def_id: LocalModId,
54 reveal_opaque: &impl Fn(OpaqueTypeKey<'tcx>) -> Option<Ty<'tcx>>,
55 ) -> bool {
56 let Ok(result) = self.apply_inner::<!>(
57 tcx,
58 typing_env,
59 &mut Default::default(),
60 &|id| Ok(tcx.is_descendant_of(module_def_id, id)),
61 reveal_opaque,
62 );
63 result
64 }
65
66 pub fn apply_any_module(self, tcx: TyCtxt<'tcx>, typing_env: TypingEnv<'tcx>) -> Option<bool> {
68 self.apply_inner(tcx, typing_env, &mut Default::default(), &|_| Err(()), &|_| None).ok()
69 }
70
71 pub fn apply_ignore_module(self, tcx: TyCtxt<'tcx>, typing_env: TypingEnv<'tcx>) -> bool {
74 let Ok(result) =
75 self.apply_inner::<!>(tcx, typing_env, &mut Default::default(), &|_| Ok(true), &|_| {
76 None
77 });
78 result
79 }
80
81 {}
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/4aa1fbcf467cf38ce58abfa8eb9213a789c5381c/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs"),
::tracing_core::__macro_support::Option::Some(81u32),
::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/4aa1fbcf467cf38ce58abfa8eb9213a789c5381c/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs:81",
"rustc_middle::ty::inhabitedness::inhabited_predicate",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/4aa1fbcf467cf38ce58abfa8eb9213a789c5381c/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs"),
::tracing_core::__macro_support::Option::Some(81u32),
::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)]
82 fn apply_inner<E: std::fmt::Debug>(
83 self,
84 tcx: TyCtxt<'tcx>,
85 typing_env: TypingEnv<'tcx>,
86 eval_stack: &mut SmallVec<[Ty<'tcx>; 1]>, in_module: &impl Fn(ModId) -> Result<bool, E>,
88 reveal_opaque: &impl Fn(OpaqueTypeKey<'tcx>) -> Option<Ty<'tcx>>,
89 ) -> Result<bool, E> {
90 match self {
91 Self::False => Ok(false),
92 Self::True => Ok(true),
93 Self::ConstIsZero(const_) => match const_.try_to_target_usize(tcx) {
94 None | Some(0) => Ok(true),
95 Some(1..) => Ok(false),
96 },
97 Self::NotInModule(id) => in_module(id).map(|in_mod| !in_mod),
98 Self::GenericType(t) => {
101 let normalized_pred = tcx
102 .try_normalize_erasing_regions(typing_env, Unnormalized::new_wip(t))
103 .map_or(self, |t| t.inhabited_predicate(tcx));
104 match normalized_pred {
105 Self::GenericType(_) => Ok(true),
107 pred => {
108 if eval_stack.contains(&t) {
111 return Ok(true); }
113 eval_stack.push(t);
114 let ret =
115 pred.apply_inner(tcx, typing_env, eval_stack, in_module, reveal_opaque);
116 eval_stack.pop();
117 ret
118 }
119 }
120 }
121 Self::OpaqueType(key) => match reveal_opaque(key) {
122 None => Ok(true),
124 Some(t) => {
126 if eval_stack.contains(&t) {
129 return Ok(true); }
131 eval_stack.push(t);
132 let ret = t.inhabited_predicate(tcx).apply_inner(
133 tcx,
134 typing_env,
135 eval_stack,
136 in_module,
137 reveal_opaque,
138 );
139 eval_stack.pop();
140 ret
141 }
142 },
143 Self::And([a, b]) => try_and(a, b, |x| {
144 x.apply_inner(tcx, typing_env, eval_stack, in_module, reveal_opaque)
145 }),
146 Self::Or([a, b]) => try_or(a, b, |x| {
147 x.apply_inner(tcx, typing_env, eval_stack, in_module, reveal_opaque)
148 }),
149 }
150 }
151
152 pub fn and(self, tcx: TyCtxt<'tcx>, other: Self) -> Self {
153 self.reduce_and(tcx, other).unwrap_or_else(|| Self::And(tcx.arena.alloc([self, other])))
154 }
155
156 pub fn or(self, tcx: TyCtxt<'tcx>, other: Self) -> Self {
157 self.reduce_or(tcx, other).unwrap_or_else(|| Self::Or(tcx.arena.alloc([self, other])))
158 }
159
160 pub fn all(tcx: TyCtxt<'tcx>, iter: impl IntoIterator<Item = Self>) -> Self {
161 let mut result = Self::True;
162 for pred in iter {
163 if pred == Self::False {
164 return Self::False;
165 }
166 result = result.and(tcx, pred);
167 }
168 result
169 }
170
171 pub fn any(tcx: TyCtxt<'tcx>, iter: impl IntoIterator<Item = Self>) -> Self {
172 let mut result = Self::False;
173 for pred in iter {
174 if pred == Self::True {
175 return Self::True;
176 }
177 result = result.or(tcx, pred);
178 }
179 result
180 }
181
182 fn reduce_and(self, tcx: TyCtxt<'tcx>, other: Self) -> Option<Self> {
183 match (self, other) {
184 (Self::True, a) | (a, Self::True) => Some(a),
185 (Self::False, _) | (_, Self::False) => Some(Self::False),
186 (Self::ConstIsZero(a), Self::ConstIsZero(b)) if a == b => Some(Self::ConstIsZero(a)),
187 (Self::NotInModule(a), Self::NotInModule(b)) if a == b => Some(Self::NotInModule(a)),
188 (Self::NotInModule(a), Self::NotInModule(b)) if tcx.is_descendant_of(a, b) => {
189 Some(Self::NotInModule(b))
190 }
191 (Self::NotInModule(a), Self::NotInModule(b)) if tcx.is_descendant_of(b, a) => {
192 Some(Self::NotInModule(a))
193 }
194 (Self::GenericType(a), Self::GenericType(b)) if a == b => Some(Self::GenericType(a)),
195 (Self::And(&[a, b]), c) | (c, Self::And(&[a, b])) => {
196 if let Some(ac) = a.reduce_and(tcx, c) {
197 Some(ac.and(tcx, b))
198 } else if let Some(bc) = b.reduce_and(tcx, c) {
199 Some(Self::And(tcx.arena.alloc([a, bc])))
200 } else {
201 None
202 }
203 }
204 _ => None,
205 }
206 }
207
208 fn reduce_or(self, tcx: TyCtxt<'tcx>, other: Self) -> Option<Self> {
209 match (self, other) {
210 (Self::True, _) | (_, Self::True) => Some(Self::True),
211 (Self::False, a) | (a, Self::False) => Some(a),
212 (Self::ConstIsZero(a), Self::ConstIsZero(b)) if a == b => Some(Self::ConstIsZero(a)),
213 (Self::NotInModule(a), Self::NotInModule(b)) if a == b => Some(Self::NotInModule(a)),
214 (Self::NotInModule(a), Self::NotInModule(b)) if tcx.is_descendant_of(a, b) => {
215 Some(Self::NotInModule(a))
216 }
217 (Self::NotInModule(a), Self::NotInModule(b)) if tcx.is_descendant_of(b, a) => {
218 Some(Self::NotInModule(b))
219 }
220 (Self::GenericType(a), Self::GenericType(b)) if a == b => Some(Self::GenericType(a)),
221 (Self::Or(&[a, b]), c) | (c, Self::Or(&[a, b])) => {
222 if let Some(ac) = a.reduce_or(tcx, c) {
223 Some(ac.or(tcx, b))
224 } else if let Some(bc) = b.reduce_or(tcx, c) {
225 Some(Self::Or(tcx.arena.alloc([a, bc])))
226 } else {
227 None
228 }
229 }
230 _ => None,
231 }
232 }
233
234 pub fn instantiate(self, tcx: TyCtxt<'tcx>, args: ty::GenericArgsRef<'tcx>) -> Self {
236 self.instantiate_opt(tcx, args).unwrap_or(self)
237 }
238
239 fn instantiate_opt(self, tcx: TyCtxt<'tcx>, args: ty::GenericArgsRef<'tcx>) -> Option<Self> {
245 match self {
246 Self::ConstIsZero(c) => {
247 let c = ty::EarlyBinder::bind(tcx, c).instantiate(tcx, args).skip_norm_wip();
248 let pred = match c.try_to_target_usize(tcx) {
249 Some(0) => Self::True,
250 Some(1..) => Self::False,
251 None => Self::ConstIsZero(c),
252 };
253 Some(pred)
254 }
255 Self::GenericType(t) => Some(
256 ty::EarlyBinder::bind(tcx, t)
257 .instantiate(tcx, args)
258 .skip_norm_wip()
259 .inhabited_predicate(tcx),
260 ),
261 Self::And(&[a, b]) => match a.instantiate_opt(tcx, args) {
262 None => b.instantiate_opt(tcx, args).map(|b| a.and(tcx, b)),
263 Some(InhabitedPredicate::False) => Some(InhabitedPredicate::False),
264 Some(a) => Some(a.and(tcx, b.instantiate_opt(tcx, args).unwrap_or(b))),
265 },
266 Self::Or(&[a, b]) => match a.instantiate_opt(tcx, args) {
267 None => b.instantiate_opt(tcx, args).map(|b| a.or(tcx, b)),
268 Some(InhabitedPredicate::True) => Some(InhabitedPredicate::True),
269 Some(a) => Some(a.or(tcx, b.instantiate_opt(tcx, args).unwrap_or(b))),
270 },
271 Self::True | Self::False | Self::NotInModule(_) => None,
272 Self::OpaqueType(_) => {
273 crate::util::bug::bug_fmt(format_args!("unexpected OpaqueType in InhabitedPredicate"));bug!("unexpected OpaqueType in InhabitedPredicate");
274 }
275 }
276 }
277}
278
279fn try_and<T, E>(a: T, b: T, mut f: impl FnMut(T) -> Result<bool, E>) -> Result<bool, E> {
282 let a = f(a);
283 if #[allow(non_exhaustive_omitted_patterns)] match a {
Ok(false) => true,
_ => false,
}matches!(a, Ok(false)) {
284 return Ok(false);
285 }
286 match (a, f(b)) {
287 (_, Ok(false)) | (Ok(false), _) => Ok(false),
288 (Ok(true), Ok(true)) => Ok(true),
289 (Err(e), _) | (_, Err(e)) => Err(e),
290 }
291}
292
293fn try_or<T, E>(a: T, b: T, mut f: impl FnMut(T) -> Result<bool, E>) -> Result<bool, E> {
294 let a = f(a);
295 if #[allow(non_exhaustive_omitted_patterns)] match a {
Ok(true) => true,
_ => false,
}matches!(a, Ok(true)) {
296 return Ok(true);
297 }
298 match (a, f(b)) {
299 (_, Ok(true)) | (Ok(true), _) => Ok(true),
300 (Ok(false), Ok(false)) => Ok(false),
301 (Err(e), _) | (_, Err(e)) => Err(e),
302 }
303}