Skip to content

Commit 3a7531d

Browse files
committed
internal: sync match checking with rust-lang/rust f31622a50 2021-11-12
1 parent facd630 commit 3a7531d

File tree

3 files changed

+57
-34
lines changed

3 files changed

+57
-34
lines changed

crates/hir_ty/src/diagnostics/expr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ impl ExprValidator {
322322
let report = compute_match_usefulness(&cx, &m_arms, match_expr_ty);
323323

324324
// FIXME Report unreacheble arms
325-
// https://github.com/rust-lang/rust/blob/25c15cdbe/compiler/rustc_mir_build/src/thir/pattern/check_match.rs#L200-L201
325+
// https://github.com/rust-lang/rust/blob/f31622a50/compiler/rustc_mir_build/src/thir/pattern/check_match.rs#L200
326326

327327
let witnesses = report.non_exhaustiveness_witnesses;
328328
// FIXME Report witnesses

crates/hir_ty/src/diagnostics/match_check/deconstruct_pat.rs

+30-23
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,14 @@ impl Constructor {
331331
}
332332
}
333333

334+
pub(super) fn is_unstable_variant(&self, _pcx: PatCtxt<'_, '_>) -> bool {
335+
false //FIXME: implement this
336+
}
337+
338+
pub(super) fn is_doc_hidden_variant(&self, _pcx: PatCtxt<'_, '_>) -> bool {
339+
false //FIXME: implement this
340+
}
341+
334342
fn variant_id_for_adt(&self, adt: hir_def::AdtId) -> VariantId {
335343
match *self {
336344
Variant(id) => id.into(),
@@ -555,32 +563,33 @@ impl SplitWildcard {
555563
// witness.
556564
let is_declared_nonexhaustive = cx.is_foreign_non_exhaustive_enum(pcx.ty);
557565

566+
let is_exhaustive_pat_feature = cx.feature_exhaustive_patterns();
567+
558568
// If `exhaustive_patterns` is disabled and our scrutinee is an empty enum, we treat it
559569
// as though it had an "unknown" constructor to avoid exposing its emptiness. The
560570
// exception is if the pattern is at the top level, because we want empty matches to be
561571
// considered exhaustive.
562572
let is_secretly_empty = enum_data.variants.is_empty()
563-
&& !cx.feature_exhaustive_patterns()
573+
&& !is_exhaustive_pat_feature
564574
&& !pcx.is_top_level;
565575

566-
if is_secretly_empty {
567-
smallvec![NonExhaustive]
568-
} else if is_declared_nonexhaustive {
569-
enum_data
570-
.variants
571-
.iter()
572-
.map(|(local_id, ..)| Variant(EnumVariantId { parent: enum_id, local_id }))
573-
.chain(Some(NonExhaustive))
574-
.collect()
575-
} else if cx.feature_exhaustive_patterns() {
576-
unimplemented!() // see MatchCheckCtx.feature_exhaustive_patterns()
577-
} else {
578-
enum_data
579-
.variants
580-
.iter()
581-
.map(|(local_id, ..)| Variant(EnumVariantId { parent: enum_id, local_id }))
582-
.collect()
576+
let mut ctors: SmallVec<[_; 1]> = enum_data
577+
.variants
578+
.iter()
579+
.filter(|&(_, _v)| {
580+
// If `exhaustive_patterns` is enabled, we exclude variants known to be
581+
// uninhabited.
582+
let is_uninhabited = is_exhaustive_pat_feature
583+
&& unimplemented!("after MatchCheckCtx.feature_exhaustive_patterns()");
584+
!is_uninhabited
585+
})
586+
.map(|(local_id, _)| Variant(EnumVariantId { parent: enum_id, local_id }))
587+
.collect();
588+
589+
if is_secretly_empty || is_declared_nonexhaustive {
590+
ctors.push(NonExhaustive);
583591
}
592+
ctors
584593
}
585594
TyKind::Scalar(Scalar::Char) => unhandled(),
586595
TyKind::Scalar(Scalar::Int(..) | Scalar::Uint(..)) => unhandled(),
@@ -660,9 +669,7 @@ impl SplitWildcard {
660669
Missing {
661670
nonexhaustive_enum_missing_real_variants: self
662671
.iter_missing(pcx)
663-
.filter(|c| !c.is_non_exhaustive())
664-
.next()
665-
.is_some(),
672+
.any(|c| !(c.is_non_exhaustive() || c.is_unstable_variant(pcx))),
666673
}
667674
} else {
668675
Missing { nonexhaustive_enum_missing_real_variants: false }
@@ -819,9 +826,9 @@ impl<'p> Fields<'p> {
819826

820827
/// Values and patterns can be represented as a constructor applied to some fields. This represents
821828
/// a pattern in this form.
822-
/// This also keeps track of whether the pattern has been foundreachable during analysis. For this
829+
/// This also keeps track of whether the pattern has been found reachable during analysis. For this
823830
/// reason we should be careful not to clone patterns for which we care about that. Use
824-
/// `clone_and_forget_reachability` is you're sure.
831+
/// `clone_and_forget_reachability` if you're sure.
825832
pub(crate) struct DeconstructedPat<'p> {
826833
ctor: Constructor,
827834
fields: Fields<'p>,

crates/hir_ty/src/diagnostics/match_check/usefulness.rs

+26-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
//! Based on rust-lang/rust (last sync 68b76a483 2021-10-01)
2-
//! <https://github.com/rust-lang/rust/blob/68b76a483/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs>
1+
//! Based on rust-lang/rust (last sync f31622a50 2021-11-12)
2+
//! <https://github.com/rust-lang/rust/blob/f31622a50/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs>
33
//!
44
//! -----
55
//!
@@ -402,9 +402,7 @@ impl<'p> Matrix<'p> {
402402
/// expands it.
403403
fn push(&mut self, row: PatStack<'p>) {
404404
if !row.is_empty() && row.head().is_or_pat() {
405-
for row in row.expand_or_pat() {
406-
self.patterns.push(row);
407-
}
405+
self.patterns.extend(row.expand_or_pat());
408406
} else {
409407
self.patterns.push(row);
410408
}
@@ -500,15 +498,33 @@ impl<'p> Usefulness<'p> {
500498
} else {
501499
let mut split_wildcard = SplitWildcard::new(pcx);
502500
split_wildcard.split(pcx, matrix.heads().map(DeconstructedPat::ctor));
501+
502+
// This lets us know if we skipped any variants because they are marked
503+
// `doc(hidden)` or they are unstable feature gate (only stdlib types).
504+
let mut hide_variant_show_wild = false;
503505
// Construct for each missing constructor a "wild" version of this
504506
// constructor, that matches everything that can be built with
505507
// it. For example, if `ctor` is a `Constructor::Variant` for
506508
// `Option::Some`, we get the pattern `Some(_)`.
507-
split_wildcard
509+
let mut new: Vec<DeconstructedPat<'_>> = split_wildcard
508510
.iter_missing(pcx)
509-
.cloned()
510-
.map(|missing_ctor| DeconstructedPat::wild_from_ctor(pcx, missing_ctor))
511-
.collect()
511+
.filter_map(|missing_ctor| {
512+
// Check if this variant is marked `doc(hidden)`
513+
if missing_ctor.is_doc_hidden_variant(pcx)
514+
|| missing_ctor.is_unstable_variant(pcx)
515+
{
516+
hide_variant_show_wild = true;
517+
return None;
518+
}
519+
Some(DeconstructedPat::wild_from_ctor(pcx, missing_ctor.clone()))
520+
})
521+
.collect();
522+
523+
if hide_variant_show_wild {
524+
new.push(DeconstructedPat::wildcard(pcx.ty.clone()))
525+
}
526+
527+
new
512528
};
513529

514530
witnesses
@@ -660,7 +676,7 @@ fn is_useful<'p>(
660676
return ret;
661677
}
662678

663-
assert!(rows.iter().all(|r| r.len() == v.len()));
679+
debug_assert!(rows.iter().all(|r| r.len() == v.len()));
664680

665681
let ty = v.head().ty();
666682
let is_non_exhaustive = cx.is_foreign_non_exhaustive_enum(ty);

0 commit comments

Comments
 (0)