mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-31 21:47:15 +03:00
Rollup merge of #148872 - ShoyuVanilla:issue-148192, r=chenyukang
fix: Do not ICE when missing match arm with ill-formed subty is met Fixes rust-lang/rust#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.
This commit is contained in:
@@ -191,7 +191,18 @@ pub(crate) fn variant_sub_tys(
|
||||
variant.fields.iter().map(move |field| {
|
||||
let ty = field.ty(self.tcx, args);
|
||||
// `field.ty()` doesn't normalize after instantiating.
|
||||
let ty = self.tcx.normalize_erasing_regions(self.typing_env, ty);
|
||||
let ty =
|
||||
self.tcx.try_normalize_erasing_regions(self.typing_env, ty).unwrap_or_else(|e| {
|
||||
self.tcx.dcx().span_delayed_bug(
|
||||
self.scrut_span,
|
||||
format!(
|
||||
"Failed to normalize {:?} in typing_env={:?} while getting variant sub tys for {ty:?}",
|
||||
e.get_type_for_failure(),
|
||||
self.typing_env,
|
||||
),
|
||||
);
|
||||
ty
|
||||
});
|
||||
let ty = self.reveal_opaque_ty(ty);
|
||||
(field, ty)
|
||||
})
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
trait WhereTrait {
|
||||
type Type;
|
||||
}
|
||||
|
||||
fn foo(e: Enum) {
|
||||
if let Enum::Map(_) = e {}
|
||||
|
||||
match e {
|
||||
//~^ ERROR: non-exhaustive patterns: `Enum::Map2(_)` not covered
|
||||
Enum::Map(_) => (),
|
||||
}
|
||||
}
|
||||
|
||||
enum Enum {
|
||||
Map(()),
|
||||
Map2(<() as WhereTrait>::Type),
|
||||
//~^ ERROR: the trait bound `(): WhereTrait` is not satisfied
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,37 @@
|
||||
error[E0277]: the trait bound `(): WhereTrait` is not satisfied
|
||||
--> $DIR/missing-ctor-with-ill-formed-inner-ty-issue-148192.rs:16:10
|
||||
|
|
||||
LL | Map2(<() as WhereTrait>::Type),
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `WhereTrait` is not implemented for `()`
|
||||
|
|
||||
help: this trait has no implementations, consider adding one
|
||||
--> $DIR/missing-ctor-with-ill-formed-inner-ty-issue-148192.rs:1:1
|
||||
|
|
||||
LL | trait WhereTrait {
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0004]: non-exhaustive patterns: `Enum::Map2(_)` not covered
|
||||
--> $DIR/missing-ctor-with-ill-formed-inner-ty-issue-148192.rs:8:11
|
||||
|
|
||||
LL | match e {
|
||||
| ^ pattern `Enum::Map2(_)` not covered
|
||||
|
|
||||
note: `Enum` defined here
|
||||
--> $DIR/missing-ctor-with-ill-formed-inner-ty-issue-148192.rs:14:6
|
||||
|
|
||||
LL | enum Enum {
|
||||
| ^^^^
|
||||
LL | Map(()),
|
||||
LL | Map2(<() as WhereTrait>::Type),
|
||||
| ---- not covered
|
||||
= note: the matched value is of type `Enum`
|
||||
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
||||
|
|
||||
LL ~ Enum::Map(_) => (),
|
||||
LL ~ Enum::Map2(_) => todo!(),
|
||||
|
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0004, E0277.
|
||||
For more information about an error, try `rustc --explain E0004`.
|
||||
Reference in New Issue
Block a user