Skip to content

Commit 4b1d068

Browse files
authored
Rollup merge of #113103 - cjgillot:normalize-inhabited, r=compiler-errors
Normalize types when applying uninhabited predicate. Fixes #112997
2 parents d505582 + 6f3f878 commit 4b1d068

File tree

2 files changed

+44
-1
lines changed

2 files changed

+44
-1
lines changed

compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,18 @@ impl<'tcx> InhabitedPredicate<'tcx> {
6262
Some(1..) => Ok(false),
6363
},
6464
Self::NotInModule(id) => in_module(id).map(|in_mod| !in_mod),
65-
Self::GenericType(_) => Ok(true),
65+
// `t` may be a projection, for which `inhabited_predicate` returns a `GenericType`. As
66+
// we have a param_env available, we can do better.
67+
Self::GenericType(t) => {
68+
let normalized_pred = tcx
69+
.try_normalize_erasing_regions(param_env, t)
70+
.map_or(self, |t| t.inhabited_predicate(tcx));
71+
match normalized_pred {
72+
// We don't have more information than we started with, so consider inhabited.
73+
Self::GenericType(_) => Ok(true),
74+
pred => pred.apply_inner(tcx, param_env, in_module),
75+
}
76+
}
6677
Self::And([a, b]) => try_and(a, b, |x| x.apply_inner(tcx, param_env, in_module)),
6778
Self::Or([a, b]) => try_or(a, b, |x| x.apply_inner(tcx, param_env, in_module)),
6879
}

tests/ui/uninhabited/projection.rs

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// check-pass
2+
3+
#![feature(never_type, exhaustive_patterns)]
4+
5+
trait Tag {
6+
type TagType;
7+
}
8+
9+
enum Keep {}
10+
enum Erase {}
11+
12+
impl Tag for Keep {
13+
type TagType = ();
14+
}
15+
16+
impl Tag for Erase {
17+
type TagType = !;
18+
}
19+
20+
enum TagInt<T: Tag> {
21+
Untagged(i32),
22+
Tagged(T::TagType, i32)
23+
}
24+
25+
fn test(keep: TagInt<Keep>, erase: TagInt<Erase>) {
26+
match erase {
27+
TagInt::Untagged(_) => (),
28+
TagInt::Tagged(_, _) => ()
29+
};
30+
}
31+
32+
fn main() {}

0 commit comments

Comments
 (0)