Skip to content

Commit c96bd28

Browse files
committed
Recompute MissingConstructors when needed
This only happens in a slow (diagnostics) path, so the code clarity gain is worth it.
1 parent b49f907 commit c96bd28

File tree

1 file changed

+56
-39
lines changed
  • compiler/rustc_mir_build/src/thir/pattern

1 file changed

+56
-39
lines changed

compiler/rustc_mir_build/src/thir/pattern/_match.rs

Lines changed: 56 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1285,7 +1285,9 @@ impl<'tcx> Constructor<'tcx> {
12851285
IntRange(range) => return range.to_pat(pcx.cx.tcx),
12861286
NonExhaustive => PatKind::Wild,
12871287
Opaque => bug!("we should not try to apply an opaque constructor"),
1288-
Wildcard => bug!("we should not try to apply a wildcard constructor"),
1288+
Wildcard => bug!(
1289+
"trying to apply a wildcard constructor; this should have been done in `apply_constructors`"
1290+
),
12891291
};
12901292

12911293
Pat { ty: pcx.ty, span: DUMMY_SP, kind: Box::new(pat) }
@@ -1610,27 +1612,13 @@ impl<'tcx> Usefulness<'tcx> {
16101612
pcx: PatCtxt<'_, 'p, 'tcx>,
16111613
ctor: &Constructor<'tcx>,
16121614
ctor_wild_subpatterns: &Fields<'p, 'tcx>,
1613-
) -> Self {
1614-
match self {
1615-
UsefulWithWitness(witnesses) => UsefulWithWitness(
1616-
witnesses
1617-
.into_iter()
1618-
.map(|witness| witness.apply_constructor(pcx, &ctor, ctor_wild_subpatterns))
1619-
.collect(),
1620-
),
1621-
x => x,
1622-
}
1623-
}
1624-
1625-
fn apply_wildcard<'p>(
1626-
self,
1627-
pcx: PatCtxt<'_, 'p, 'tcx>,
1628-
missing_ctors: MissingConstructors<'tcx>,
1615+
is_top_level: bool,
16291616
) -> Self {
16301617
match self {
16311618
UsefulWithWitness(witnesses) => {
1632-
let new_patterns = missing_ctors.report_patterns(pcx);
1633-
UsefulWithWitness(
1619+
let new_witnesses = if ctor.is_wildcard() {
1620+
let missing_ctors = MissingConstructors::new(pcx, is_top_level);
1621+
let new_patterns = missing_ctors.report_patterns(pcx);
16341622
witnesses
16351623
.into_iter()
16361624
.flat_map(|witness| {
@@ -1640,8 +1628,14 @@ impl<'tcx> Usefulness<'tcx> {
16401628
witness
16411629
})
16421630
})
1643-
.collect(),
1644-
)
1631+
.collect()
1632+
} else {
1633+
witnesses
1634+
.into_iter()
1635+
.map(|witness| witness.apply_constructor(pcx, &ctor, ctor_wild_subpatterns))
1636+
.collect()
1637+
};
1638+
UsefulWithWitness(new_witnesses)
16451639
}
16461640
x => x,
16471641
}
@@ -2419,7 +2413,17 @@ crate fn is_useful<'p, 'tcx>(
24192413
constructor
24202414
.split(pcx, Some(hir_id))
24212415
.into_iter()
2422-
.map(|c| is_useful_specialized(pcx, v, c, witness_preference, hir_id, is_under_guard))
2416+
.map(|c| {
2417+
is_useful_specialized(
2418+
pcx,
2419+
v,
2420+
&c,
2421+
witness_preference,
2422+
hir_id,
2423+
is_under_guard,
2424+
is_top_level,
2425+
)
2426+
})
24232427
.find(|result| result.is_useful())
24242428
.unwrap_or(NotUseful)
24252429
} else {
@@ -2446,20 +2450,31 @@ crate fn is_useful<'p, 'tcx>(
24462450
.into_iter()
24472451
.flat_map(|ctor| ctor.split(pcx, None))
24482452
.map(|c| {
2449-
is_useful_specialized(pcx, v, c, witness_preference, hir_id, is_under_guard)
2453+
is_useful_specialized(
2454+
pcx,
2455+
v,
2456+
&c,
2457+
witness_preference,
2458+
hir_id,
2459+
is_under_guard,
2460+
is_top_level,
2461+
)
24502462
})
24512463
.find(|result| result.is_useful())
24522464
.unwrap_or(NotUseful)
24532465
} else {
2454-
let ctor_wild_subpatterns = Fields::empty();
2455-
let matrix = matrix.specialize_constructor(pcx, &constructor, &ctor_wild_subpatterns);
2456-
// Unwrap is ok: v can always be specialized with its own constructor.
2457-
let v =
2458-
v.specialize_constructor(pcx, &constructor, &ctor_wild_subpatterns, true).unwrap();
2459-
let usefulness =
2460-
is_useful(cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false);
2461-
2462-
usefulness.apply_wildcard(pcx, missing_ctors)
2466+
// Some constructors are missing, thus we can specialize with the wildcard constructor,
2467+
// which will stand for those constructors that are missing, and behaves like any of
2468+
// them.
2469+
is_useful_specialized(
2470+
pcx,
2471+
v,
2472+
constructor,
2473+
witness_preference,
2474+
hir_id,
2475+
is_under_guard,
2476+
is_top_level,
2477+
)
24632478
}
24642479
};
24652480
debug!("is_useful::returns({:#?}, {:#?}) = {:?}", matrix, v, ret);
@@ -2471,20 +2486,22 @@ crate fn is_useful<'p, 'tcx>(
24712486
fn is_useful_specialized<'p, 'tcx>(
24722487
pcx: PatCtxt<'_, 'p, 'tcx>,
24732488
v: &PatStack<'p, 'tcx>,
2474-
ctor: Constructor<'tcx>,
2489+
ctor: &Constructor<'tcx>,
24752490
witness_preference: WitnessPreference,
24762491
hir_id: HirId,
24772492
is_under_guard: bool,
2493+
is_top_level: bool,
24782494
) -> Usefulness<'tcx> {
24792495
debug!("is_useful_specialized({:#?}, {:#?}, {:?})", v, ctor, pcx.ty);
24802496

24812497
// We cache the result of `Fields::wildcards` because it is used a lot.
2482-
let ctor_wild_subpatterns = Fields::wildcards(pcx, &ctor);
2483-
let matrix = pcx.matrix.specialize_constructor(pcx, &ctor, &ctor_wild_subpatterns);
2484-
v.specialize_constructor(pcx, &ctor, &ctor_wild_subpatterns, true)
2485-
.map(|v| is_useful(pcx.cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false))
2486-
.map(|u| u.apply_constructor(pcx, &ctor, &ctor_wild_subpatterns))
2487-
.unwrap_or(NotUseful)
2498+
let ctor_wild_subpatterns = Fields::wildcards(pcx, ctor);
2499+
let matrix = pcx.matrix.specialize_constructor(pcx, ctor, &ctor_wild_subpatterns);
2500+
// Unwrap is ok: v can always be specialized with its own constructor.
2501+
let v = v.specialize_constructor(pcx, ctor, &ctor_wild_subpatterns, true).unwrap();
2502+
let usefulness =
2503+
is_useful(pcx.cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false);
2504+
usefulness.apply_constructor(pcx, ctor, &ctor_wild_subpatterns, is_top_level)
24882505
}
24892506

24902507
/// Determines the constructor that the given pattern can be specialized to.

0 commit comments

Comments
 (0)