Skip to content

Commit 305492b

Browse files
authored
Unrolled build for #148872
Rollup merge of #148872 - ShoyuVanilla:issue-148192, r=chenyukang fix: Do not ICE when missing match arm with ill-formed subty is met Fixes #148192 The ICE comes from the following line, calling `normalize_erasing_regions` to a projection type whose trait bound is not met: https://github.com/rust-lang/rust/blob/2fcbda6c1a70606bdb09857e01d01fc6229da712/compiler/rustc_pattern_analysis/src/rustc.rs#L185-L194 The above function is called while trying to lint missing match arms, or scrutinize ctors of missing(not necessary error) match arms. So, the following code can trigger ICEs. ```rust trait WhereTrait { type Type; } fn foo(e: Enum) { match e { Enum::Map(_) => (), // ICE, while trying to lint missing arms } if let Enum::Map(_) = e {} // ICE, while trying to scrutinize missing ctors (even worse) } enum Enum { Map(()), Map2(<() as WhereTrait>::Type), } ``` This ICE won't be triggered with the following code, as this is filtered out before `check_match` as the existence of ill-formed type inside the variant marks the body as tainted by error in `hir_typeck`, but for the above code, the `hir_typeck` complains nothing because everything it sees is locally correct. ```rust fn foo(e: Enum) { match e { Enum::Map2(_) => (), // No ICE } } ``` I've considered visiting and wf checking for the match scrutinee before entering `check_match`, but that might regress the perf and I think just emitting delayed bug would enough as the normalization failure would be originated by other errors like ill-formdness.
2 parents 503dce3 + dae003b commit 305492b

File tree

3 files changed

+69
-1
lines changed

3 files changed

+69
-1
lines changed

compiler/rustc_pattern_analysis/src/rustc.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,18 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
191191
variant.fields.iter().map(move |field| {
192192
let ty = field.ty(self.tcx, args);
193193
// `field.ty()` doesn't normalize after instantiating.
194-
let ty = self.tcx.normalize_erasing_regions(self.typing_env, ty);
194+
let ty =
195+
self.tcx.try_normalize_erasing_regions(self.typing_env, ty).unwrap_or_else(|e| {
196+
self.tcx.dcx().span_delayed_bug(
197+
self.scrut_span,
198+
format!(
199+
"Failed to normalize {:?} in typing_env={:?} while getting variant sub tys for {ty:?}",
200+
e.get_type_for_failure(),
201+
self.typing_env,
202+
),
203+
);
204+
ty
205+
});
195206
let ty = self.reveal_opaque_ty(ty);
196207
(field, ty)
197208
})
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
trait WhereTrait {
2+
type Type;
3+
}
4+
5+
fn foo(e: Enum) {
6+
if let Enum::Map(_) = e {}
7+
8+
match e {
9+
//~^ ERROR: non-exhaustive patterns: `Enum::Map2(_)` not covered
10+
Enum::Map(_) => (),
11+
}
12+
}
13+
14+
enum Enum {
15+
Map(()),
16+
Map2(<() as WhereTrait>::Type),
17+
//~^ ERROR: the trait bound `(): WhereTrait` is not satisfied
18+
}
19+
20+
fn main() {}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
error[E0277]: the trait bound `(): WhereTrait` is not satisfied
2+
--> $DIR/missing-ctor-with-ill-formed-inner-ty-issue-148192.rs:16:10
3+
|
4+
LL | Map2(<() as WhereTrait>::Type),
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `WhereTrait` is not implemented for `()`
6+
|
7+
help: this trait has no implementations, consider adding one
8+
--> $DIR/missing-ctor-with-ill-formed-inner-ty-issue-148192.rs:1:1
9+
|
10+
LL | trait WhereTrait {
11+
| ^^^^^^^^^^^^^^^^
12+
13+
error[E0004]: non-exhaustive patterns: `Enum::Map2(_)` not covered
14+
--> $DIR/missing-ctor-with-ill-formed-inner-ty-issue-148192.rs:8:11
15+
|
16+
LL | match e {
17+
| ^ pattern `Enum::Map2(_)` not covered
18+
|
19+
note: `Enum` defined here
20+
--> $DIR/missing-ctor-with-ill-formed-inner-ty-issue-148192.rs:14:6
21+
|
22+
LL | enum Enum {
23+
| ^^^^
24+
LL | Map(()),
25+
LL | Map2(<() as WhereTrait>::Type),
26+
| ---- not covered
27+
= note: the matched value is of type `Enum`
28+
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
29+
|
30+
LL ~ Enum::Map(_) => (),
31+
LL ~ Enum::Map2(_) => todo!(),
32+
|
33+
34+
error: aborting due to 2 previous errors
35+
36+
Some errors have detailed explanations: E0004, E0277.
37+
For more information about an error, try `rustc --explain E0004`.

0 commit comments

Comments
 (0)