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#[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 True,
18 False,
20 ConstIsZero(ty::Const<'tcx>),
23 NotInModule(ModId),
26 GenericType(Ty<'tcx>),
29 OpaqueType(OpaqueTypeKey<'tcx>),
31 And(&'tcx [InhabitedPredicate<'tcx>; 2]),
33 Or(&'tcx [InhabitedPredicate<'tcx>; 2]),
35}
36
37impl<'tcx> InhabitedPredicate<'tcx> {
38 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 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 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 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]>, 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 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 Self::GenericType(_) => Ok(true),
108 pred => {
109 if eval_stack.contains(&t) {
112 return Ok(true); }
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 None => Ok(true),
125 Some(t) => {
127 if eval_stack.contains(&t) {
130 return Ok(true); }
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 pub fn instantiate(self, tcx: TyCtxt<'tcx>, args: ty::GenericArgsRef<'tcx>) -> Self {
237 self.instantiate_opt(tcx, args).unwrap_or(self)
238 }
239
240 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
280fn 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}