mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 12:54:58 +00:00
internal: sync match checking with rust-lang/rust f31622a50 2021-11-12
This commit is contained in:
parent
deb05930ef
commit
1280961b51
3 changed files with 57 additions and 34 deletions
|
@ -335,7 +335,7 @@ impl ExprValidator {
|
||||||
let report = compute_match_usefulness(&cx, &m_arms, match_expr_ty);
|
let report = compute_match_usefulness(&cx, &m_arms, match_expr_ty);
|
||||||
|
|
||||||
// FIXME Report unreacheble arms
|
// FIXME Report unreacheble arms
|
||||||
// https://github.com/rust-lang/rust/blob/25c15cdbe/compiler/rustc_mir_build/src/thir/pattern/check_match.rs#L200-L201
|
// https://github.com/rust-lang/rust/blob/f31622a50/compiler/rustc_mir_build/src/thir/pattern/check_match.rs#L200
|
||||||
|
|
||||||
let witnesses = report.non_exhaustiveness_witnesses;
|
let witnesses = report.non_exhaustiveness_witnesses;
|
||||||
// FIXME Report witnesses
|
// FIXME Report witnesses
|
||||||
|
|
|
@ -332,6 +332,14 @@ impl Constructor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) fn is_unstable_variant(&self, _pcx: PatCtxt<'_, '_>) -> bool {
|
||||||
|
false //FIXME: implement this
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn is_doc_hidden_variant(&self, _pcx: PatCtxt<'_, '_>) -> bool {
|
||||||
|
false //FIXME: implement this
|
||||||
|
}
|
||||||
|
|
||||||
fn variant_id_for_adt(&self, adt: hir_def::AdtId) -> VariantId {
|
fn variant_id_for_adt(&self, adt: hir_def::AdtId) -> VariantId {
|
||||||
match *self {
|
match *self {
|
||||||
Variant(id) => id.into(),
|
Variant(id) => id.into(),
|
||||||
|
@ -556,32 +564,33 @@ impl SplitWildcard {
|
||||||
// witness.
|
// witness.
|
||||||
let is_declared_nonexhaustive = cx.is_foreign_non_exhaustive_enum(pcx.ty);
|
let is_declared_nonexhaustive = cx.is_foreign_non_exhaustive_enum(pcx.ty);
|
||||||
|
|
||||||
|
let is_exhaustive_pat_feature = cx.feature_exhaustive_patterns();
|
||||||
|
|
||||||
// If `exhaustive_patterns` is disabled and our scrutinee is an empty enum, we treat it
|
// If `exhaustive_patterns` is disabled and our scrutinee is an empty enum, we treat it
|
||||||
// as though it had an "unknown" constructor to avoid exposing its emptiness. The
|
// as though it had an "unknown" constructor to avoid exposing its emptiness. The
|
||||||
// exception is if the pattern is at the top level, because we want empty matches to be
|
// exception is if the pattern is at the top level, because we want empty matches to be
|
||||||
// considered exhaustive.
|
// considered exhaustive.
|
||||||
let is_secretly_empty = enum_data.variants.is_empty()
|
let is_secretly_empty = enum_data.variants.is_empty()
|
||||||
&& !cx.feature_exhaustive_patterns()
|
&& !is_exhaustive_pat_feature
|
||||||
&& !pcx.is_top_level;
|
&& !pcx.is_top_level;
|
||||||
|
|
||||||
if is_secretly_empty {
|
let mut ctors: SmallVec<[_; 1]> = enum_data
|
||||||
smallvec![NonExhaustive]
|
.variants
|
||||||
} else if is_declared_nonexhaustive {
|
.iter()
|
||||||
enum_data
|
.filter(|&(_, _v)| {
|
||||||
.variants
|
// If `exhaustive_patterns` is enabled, we exclude variants known to be
|
||||||
.iter()
|
// uninhabited.
|
||||||
.map(|(local_id, ..)| Variant(EnumVariantId { parent: enum_id, local_id }))
|
let is_uninhabited = is_exhaustive_pat_feature
|
||||||
.chain(Some(NonExhaustive))
|
&& unimplemented!("after MatchCheckCtx.feature_exhaustive_patterns()");
|
||||||
.collect()
|
!is_uninhabited
|
||||||
} else if cx.feature_exhaustive_patterns() {
|
})
|
||||||
unimplemented!() // see MatchCheckCtx.feature_exhaustive_patterns()
|
.map(|(local_id, _)| Variant(EnumVariantId { parent: enum_id, local_id }))
|
||||||
} else {
|
.collect();
|
||||||
enum_data
|
|
||||||
.variants
|
if is_secretly_empty || is_declared_nonexhaustive {
|
||||||
.iter()
|
ctors.push(NonExhaustive);
|
||||||
.map(|(local_id, ..)| Variant(EnumVariantId { parent: enum_id, local_id }))
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
|
ctors
|
||||||
}
|
}
|
||||||
TyKind::Scalar(Scalar::Char) => unhandled(),
|
TyKind::Scalar(Scalar::Char) => unhandled(),
|
||||||
TyKind::Scalar(Scalar::Int(..) | Scalar::Uint(..)) => unhandled(),
|
TyKind::Scalar(Scalar::Int(..) | Scalar::Uint(..)) => unhandled(),
|
||||||
|
@ -661,9 +670,7 @@ impl SplitWildcard {
|
||||||
Missing {
|
Missing {
|
||||||
nonexhaustive_enum_missing_real_variants: self
|
nonexhaustive_enum_missing_real_variants: self
|
||||||
.iter_missing(pcx)
|
.iter_missing(pcx)
|
||||||
.filter(|c| !c.is_non_exhaustive())
|
.any(|c| !(c.is_non_exhaustive() || c.is_unstable_variant(pcx))),
|
||||||
.next()
|
|
||||||
.is_some(),
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Missing { nonexhaustive_enum_missing_real_variants: false }
|
Missing { nonexhaustive_enum_missing_real_variants: false }
|
||||||
|
@ -820,9 +827,9 @@ impl<'p> Fields<'p> {
|
||||||
|
|
||||||
/// Values and patterns can be represented as a constructor applied to some fields. This represents
|
/// Values and patterns can be represented as a constructor applied to some fields. This represents
|
||||||
/// a pattern in this form.
|
/// a pattern in this form.
|
||||||
/// This also keeps track of whether the pattern has been foundreachable during analysis. For this
|
/// This also keeps track of whether the pattern has been found reachable during analysis. For this
|
||||||
/// reason we should be careful not to clone patterns for which we care about that. Use
|
/// reason we should be careful not to clone patterns for which we care about that. Use
|
||||||
/// `clone_and_forget_reachability` is you're sure.
|
/// `clone_and_forget_reachability` if you're sure.
|
||||||
pub(crate) struct DeconstructedPat<'p> {
|
pub(crate) struct DeconstructedPat<'p> {
|
||||||
ctor: Constructor,
|
ctor: Constructor,
|
||||||
fields: Fields<'p>,
|
fields: Fields<'p>,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//! Based on rust-lang/rust (last sync 68b76a483 2021-10-01)
|
//! Based on rust-lang/rust (last sync f31622a50 2021-11-12)
|
||||||
//! <https://github.com/rust-lang/rust/blob/68b76a483/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs>
|
//! <https://github.com/rust-lang/rust/blob/f31622a50/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs>
|
||||||
//!
|
//!
|
||||||
//! -----
|
//! -----
|
||||||
//!
|
//!
|
||||||
|
@ -402,9 +402,7 @@ impl<'p> Matrix<'p> {
|
||||||
/// expands it.
|
/// expands it.
|
||||||
fn push(&mut self, row: PatStack<'p>) {
|
fn push(&mut self, row: PatStack<'p>) {
|
||||||
if !row.is_empty() && row.head().is_or_pat() {
|
if !row.is_empty() && row.head().is_or_pat() {
|
||||||
for row in row.expand_or_pat() {
|
self.patterns.extend(row.expand_or_pat());
|
||||||
self.patterns.push(row);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
self.patterns.push(row);
|
self.patterns.push(row);
|
||||||
}
|
}
|
||||||
|
@ -500,15 +498,33 @@ impl<'p> Usefulness<'p> {
|
||||||
} else {
|
} else {
|
||||||
let mut split_wildcard = SplitWildcard::new(pcx);
|
let mut split_wildcard = SplitWildcard::new(pcx);
|
||||||
split_wildcard.split(pcx, matrix.heads().map(DeconstructedPat::ctor));
|
split_wildcard.split(pcx, matrix.heads().map(DeconstructedPat::ctor));
|
||||||
|
|
||||||
|
// This lets us know if we skipped any variants because they are marked
|
||||||
|
// `doc(hidden)` or they are unstable feature gate (only stdlib types).
|
||||||
|
let mut hide_variant_show_wild = false;
|
||||||
// Construct for each missing constructor a "wild" version of this
|
// Construct for each missing constructor a "wild" version of this
|
||||||
// constructor, that matches everything that can be built with
|
// constructor, that matches everything that can be built with
|
||||||
// it. For example, if `ctor` is a `Constructor::Variant` for
|
// it. For example, if `ctor` is a `Constructor::Variant` for
|
||||||
// `Option::Some`, we get the pattern `Some(_)`.
|
// `Option::Some`, we get the pattern `Some(_)`.
|
||||||
split_wildcard
|
let mut new: Vec<DeconstructedPat<'_>> = split_wildcard
|
||||||
.iter_missing(pcx)
|
.iter_missing(pcx)
|
||||||
.cloned()
|
.filter_map(|missing_ctor| {
|
||||||
.map(|missing_ctor| DeconstructedPat::wild_from_ctor(pcx, missing_ctor))
|
// Check if this variant is marked `doc(hidden)`
|
||||||
.collect()
|
if missing_ctor.is_doc_hidden_variant(pcx)
|
||||||
|
|| missing_ctor.is_unstable_variant(pcx)
|
||||||
|
{
|
||||||
|
hide_variant_show_wild = true;
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Some(DeconstructedPat::wild_from_ctor(pcx, missing_ctor.clone()))
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
if hide_variant_show_wild {
|
||||||
|
new.push(DeconstructedPat::wildcard(pcx.ty.clone()))
|
||||||
|
}
|
||||||
|
|
||||||
|
new
|
||||||
};
|
};
|
||||||
|
|
||||||
witnesses
|
witnesses
|
||||||
|
@ -660,7 +676,7 @@ fn is_useful<'p>(
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert!(rows.iter().all(|r| r.len() == v.len()));
|
debug_assert!(rows.iter().all(|r| r.len() == v.len()));
|
||||||
|
|
||||||
let ty = v.head().ty();
|
let ty = v.head().ty();
|
||||||
let is_non_exhaustive = cx.is_foreign_non_exhaustive_enum(ty);
|
let is_non_exhaustive = cx.is_foreign_non_exhaustive_enum(ty);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue