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#[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 True,
19 False,
21 ConstIsZero(ty::Const<'tcx>),
24 NotInModule(ModId),
27 GenericType(Ty<'tcx>),
30 OpaqueType(OpaqueTypeKey<'tcx>),
32 And(&'tcx [InhabitedPredicate<'tcx>; 2]),
34 Or(&'tcx [InhabitedPredicate<'tcx>; 2]),
36}
37
38impl<'tcx> InhabitedPredicate<'tcx> {
39 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 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 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 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]>, 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 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 Self::GenericType(_) => Ok(true),
109 pred => {
110 if eval_stack.contains(&t) {
113 return Ok(true); }
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 None => Ok(true),
126 Some(t) => {
128 if eval_stack.contains(&t) {
131 return Ok(true); }
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 pub fn instantiate(self, tcx: TyCtxt<'tcx>, args: ty::GenericArgsRef<'tcx>) -> Self {
238 self.instantiate_opt(tcx, args).unwrap_or(self)
239 }
240
241 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
281fn 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}