summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_middle/src/ty/inhabitedness
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_middle/src/ty/inhabitedness')
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs19
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/mod.rs2
2 files changed, 16 insertions, 5 deletions
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
index ac42d6e05..295cb1464 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
@@ -62,7 +62,18 @@ impl<'tcx> InhabitedPredicate<'tcx> {
Some(1..) => Ok(false),
},
Self::NotInModule(id) => in_module(id).map(|in_mod| !in_mod),
- Self::GenericType(_) => Ok(true),
+ // `t` may be a projection, for which `inhabited_predicate` returns a `GenericType`. As
+ // we have a param_env available, we can do better.
+ Self::GenericType(t) => {
+ let normalized_pred = tcx
+ .try_normalize_erasing_regions(param_env, t)
+ .map_or(self, |t| t.inhabited_predicate(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),
+ }
+ }
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)),
}
@@ -158,8 +169,8 @@ impl<'tcx> InhabitedPredicate<'tcx> {
fn subst_opt(self, tcx: TyCtxt<'tcx>, substs: ty::SubstsRef<'tcx>) -> Option<Self> {
match self {
Self::ConstIsZero(c) => {
- let c = ty::EarlyBinder(c).subst(tcx, substs);
- let pred = match c.kind().try_to_target_usize(tcx) {
+ let c = ty::EarlyBinder::bind(c).subst(tcx, substs);
+ let pred = match c.try_to_target_usize(tcx) {
Some(0) => Self::True,
Some(1..) => Self::False,
None => Self::ConstIsZero(c),
@@ -167,7 +178,7 @@ impl<'tcx> InhabitedPredicate<'tcx> {
Some(pred)
}
Self::GenericType(t) => {
- Some(ty::EarlyBinder(t).subst(tcx, substs).inhabited_predicate(tcx))
+ Some(ty::EarlyBinder::bind(t).subst(tcx, substs).inhabited_predicate(tcx))
}
Self::And(&[a, b]) => match a.subst_opt(tcx, substs) {
None => b.subst_opt(tcx, substs).map(|b| a.and(tcx, b)),
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
index 422350284..b92d84152 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
@@ -197,7 +197,7 @@ fn inhabited_predicate_type<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> InhabitedP
// If we can evaluate the array length before having a `ParamEnv`, then
// we can simplify the predicate. This is an optimization.
- Array(ty, len) => match len.kind().try_to_target_usize(tcx) {
+ Array(ty, len) => match len.try_to_target_usize(tcx) {
Some(0) => InhabitedPredicate::True,
Some(1..) => ty.inhabited_predicate(tcx),
None => ty.inhabited_predicate(tcx).or(tcx, InhabitedPredicate::ConstIsZero(len)),