summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_middle/src/ty/inhabitedness
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-19 09:26:03 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-19 09:26:03 +0000
commit9918693037dce8aa4bb6f08741b6812923486c18 (patch)
tree21d2b40bec7e6a7ea664acee056eb3d08e15a1cf /compiler/rustc_middle/src/ty/inhabitedness
parentReleasing progress-linux version 1.75.0+dfsg1-5~progress7.99u1. (diff)
downloadrustc-9918693037dce8aa4bb6f08741b6812923486c18.tar.xz
rustc-9918693037dce8aa4bb6f08741b6812923486c18.zip
Merging upstream version 1.76.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_middle/src/ty/inhabitedness')
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs40
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/mod.rs1
2 files changed, 31 insertions, 10 deletions
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
index f278cace9..ae1794278 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
@@ -1,3 +1,5 @@
+use smallvec::SmallVec;
+
use crate::ty::context::TyCtxt;
use crate::ty::{self, DefId, ParamEnv, Ty};
@@ -31,27 +33,31 @@ impl<'tcx> InhabitedPredicate<'tcx> {
/// Returns true if the corresponding type is inhabited in the given
/// `ParamEnv` and module
pub fn apply(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, module_def_id: DefId) -> bool {
- let Ok(result) = self
- .apply_inner::<!>(tcx, param_env, &|id| Ok(tcx.is_descendant_of(module_def_id, id)));
+ let Ok(result) = self.apply_inner::<!>(tcx, param_env, &mut Default::default(), &|id| {
+ Ok(tcx.is_descendant_of(module_def_id, id))
+ });
result
}
/// Same as `apply`, but returns `None` if self contains a module predicate
pub fn apply_any_module(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<bool> {
- self.apply_inner(tcx, param_env, &|_| Err(())).ok()
+ self.apply_inner(tcx, param_env, &mut Default::default(), &|_| Err(())).ok()
}
/// Same as `apply`, but `NotInModule(_)` predicates yield `false`. That is,
/// privately uninhabited types are considered always uninhabited.
pub fn apply_ignore_module(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> bool {
- let Ok(result) = self.apply_inner::<!>(tcx, param_env, &|_| Ok(true));
+ let Ok(result) =
+ self.apply_inner::<!>(tcx, param_env, &mut Default::default(), &|_| Ok(true));
result
}
- fn apply_inner<E>(
+ #[instrument(level = "debug", skip(tcx, param_env, in_module), ret)]
+ fn apply_inner<E: std::fmt::Debug>(
self,
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
+ eval_stack: &mut SmallVec<[Ty<'tcx>; 1]>, // for cycle detection
in_module: &impl Fn(DefId) -> Result<bool, E>,
) -> Result<bool, E> {
match self {
@@ -71,11 +77,25 @@ impl<'tcx> InhabitedPredicate<'tcx> {
match normalized_pred {
// We don't have more information than we started with, so consider inhabited.
Self::GenericType(_) => Ok(true),
- pred => pred.apply_inner(tcx, param_env, in_module),
+ pred => {
+ // A type which is cyclic when monomorphized can happen here since the
+ // layout error would only trigger later. See e.g. `tests/ui/sized/recursive-type-2.rs`.
+ if eval_stack.contains(&t) {
+ return Ok(true); // Recover; this will error later.
+ }
+ eval_stack.push(t);
+ let ret = pred.apply_inner(tcx, param_env, eval_stack, in_module);
+ eval_stack.pop();
+ ret
+ }
}
}
- Self::And([a, b]) => try_and(a, b, |x| x.apply_inner(tcx, param_env, in_module)),
- Self::Or([a, b]) => try_or(a, b, |x| x.apply_inner(tcx, param_env, in_module)),
+ Self::And([a, b]) => {
+ try_and(a, b, |x| x.apply_inner(tcx, param_env, eval_stack, in_module))
+ }
+ Self::Or([a, b]) => {
+ try_or(a, b, |x| x.apply_inner(tcx, param_env, eval_stack, in_module))
+ }
}
}
@@ -197,7 +217,7 @@ impl<'tcx> InhabitedPredicate<'tcx> {
// this is basically like `f(a)? && f(b)?` but different in the case of
// `Ok(false) && Err(_) -> Ok(false)`
-fn try_and<T, E>(a: T, b: T, f: impl Fn(T) -> Result<bool, E>) -> Result<bool, E> {
+fn try_and<T, E>(a: T, b: T, mut f: impl FnMut(T) -> Result<bool, E>) -> Result<bool, E> {
let a = f(a);
if matches!(a, Ok(false)) {
return Ok(false);
@@ -209,7 +229,7 @@ fn try_and<T, E>(a: T, b: T, f: impl Fn(T) -> Result<bool, E>) -> Result<bool, E
}
}
-fn try_or<T, E>(a: T, b: T, f: impl Fn(T) -> Result<bool, E>) -> Result<bool, E> {
+fn try_or<T, E>(a: T, b: T, mut f: impl FnMut(T) -> Result<bool, E>) -> Result<bool, E> {
let a = f(a);
if matches!(a, Ok(true)) {
return Ok(true);
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
index 68ac54e89..d67fb9fd0 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
@@ -103,6 +103,7 @@ impl<'tcx> VariantDef {
}
impl<'tcx> Ty<'tcx> {
+ #[instrument(level = "debug", skip(tcx), ret)]
pub fn inhabited_predicate(self, tcx: TyCtxt<'tcx>) -> InhabitedPredicate<'tcx> {
match self.kind() {
// For now, unions are always considered inhabited