Limit the use of PlaceCtxt
This commit is contained in:
parent
0b2579a1b6
commit
cb0e8c508c
6 changed files with 42 additions and 52 deletions
|
@ -163,7 +163,6 @@ use self::MaybeInfiniteInt::*;
|
||||||
use self::SliceKind::*;
|
use self::SliceKind::*;
|
||||||
|
|
||||||
use crate::index;
|
use crate::index;
|
||||||
use crate::usefulness::PlaceCtxt;
|
|
||||||
use crate::TypeCx;
|
use crate::TypeCx;
|
||||||
|
|
||||||
/// Whether we have seen a constructor in the column or not.
|
/// Whether we have seen a constructor in the column or not.
|
||||||
|
@ -818,8 +817,8 @@ impl<Cx: TypeCx> Constructor<Cx> {
|
||||||
|
|
||||||
/// The number of fields for this constructor. This must be kept in sync with
|
/// The number of fields for this constructor. This must be kept in sync with
|
||||||
/// `Fields::wildcards`.
|
/// `Fields::wildcards`.
|
||||||
pub(crate) fn arity(&self, pcx: &PlaceCtxt<'_, Cx>) -> usize {
|
pub(crate) fn arity(&self, cx: &Cx, ty: &Cx::Ty) -> usize {
|
||||||
pcx.ctor_arity(self)
|
cx.ctor_arity(self, ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether `self` is covered by `other`, i.e. whether `self` is a subset of `other`.
|
/// Returns whether `self` is covered by `other`, i.e. whether `self` is a subset of `other`.
|
||||||
|
@ -827,12 +826,11 @@ impl<Cx: TypeCx> Constructor<Cx> {
|
||||||
/// this checks for inclusion.
|
/// this checks for inclusion.
|
||||||
// We inline because this has a single call site in `Matrix::specialize_constructor`.
|
// We inline because this has a single call site in `Matrix::specialize_constructor`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn is_covered_by(&self, pcx: &PlaceCtxt<'_, Cx>, other: &Self) -> bool {
|
pub(crate) fn is_covered_by(&self, cx: &Cx, other: &Self) -> bool {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(Wildcard, _) => pcx
|
(Wildcard, _) => {
|
||||||
.mcx
|
cx.bug(format_args!("Constructor splitting should not have returned `Wildcard`"))
|
||||||
.tycx
|
}
|
||||||
.bug(format_args!("Constructor splitting should not have returned `Wildcard`")),
|
|
||||||
// Wildcards cover anything
|
// Wildcards cover anything
|
||||||
(_, Wildcard) => true,
|
(_, Wildcard) => true,
|
||||||
// Only a wildcard pattern can match these special constructors.
|
// Only a wildcard pattern can match these special constructors.
|
||||||
|
@ -873,7 +871,7 @@ impl<Cx: TypeCx> Constructor<Cx> {
|
||||||
(Opaque(self_id), Opaque(other_id)) => self_id == other_id,
|
(Opaque(self_id), Opaque(other_id)) => self_id == other_id,
|
||||||
(Opaque(..), _) | (_, Opaque(..)) => false,
|
(Opaque(..), _) | (_, Opaque(..)) => false,
|
||||||
|
|
||||||
_ => pcx.mcx.tycx.bug(format_args!(
|
_ => cx.bug(format_args!(
|
||||||
"trying to compare incompatible constructors {self:?} and {other:?}"
|
"trying to compare incompatible constructors {self:?} and {other:?}"
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
|
|
|
@ -183,7 +183,7 @@ pub fn analyze_match<'p, 'tcx>(
|
||||||
// `if let`s. Only run if the match is exhaustive otherwise the error is redundant.
|
// `if let`s. Only run if the match is exhaustive otherwise the error is redundant.
|
||||||
if tycx.refutable && report.non_exhaustiveness_witnesses.is_empty() {
|
if tycx.refutable && report.non_exhaustiveness_witnesses.is_empty() {
|
||||||
let pat_column = PatternColumn::new(arms);
|
let pat_column = PatternColumn::new(arms);
|
||||||
lint_nonexhaustive_missing_variants(cx, arms, &pat_column, scrut_ty)?;
|
lint_nonexhaustive_missing_variants(tycx, arms, &pat_column, scrut_ty)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(report)
|
Ok(report)
|
||||||
|
|
|
@ -4,8 +4,7 @@ use rustc_span::ErrorGuaranteed;
|
||||||
use crate::constructor::{Constructor, SplitConstructorSet};
|
use crate::constructor::{Constructor, SplitConstructorSet};
|
||||||
use crate::errors::{NonExhaustiveOmittedPattern, NonExhaustiveOmittedPatternLintOnArm, Uncovered};
|
use crate::errors::{NonExhaustiveOmittedPattern, NonExhaustiveOmittedPatternLintOnArm, Uncovered};
|
||||||
use crate::pat::{DeconstructedPat, PatOrWild};
|
use crate::pat::{DeconstructedPat, PatOrWild};
|
||||||
use crate::rustc::{MatchCtxt, RevealedTy, RustcMatchCheckCtxt, WitnessPat};
|
use crate::rustc::{RevealedTy, RustcMatchCheckCtxt, WitnessPat};
|
||||||
use crate::usefulness::PlaceCtxt;
|
|
||||||
use crate::{MatchArm, TypeCx};
|
use crate::{MatchArm, TypeCx};
|
||||||
|
|
||||||
/// A column of patterns in the matrix, where a column is the intuitive notion of "subpatterns that
|
/// A column of patterns in the matrix, where a column is the intuitive notion of "subpatterns that
|
||||||
|
@ -50,9 +49,9 @@ impl<'p, Cx: TypeCx> PatternColumn<'p, Cx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Do constructor splitting on the constructors of the column.
|
/// Do constructor splitting on the constructors of the column.
|
||||||
fn analyze_ctors(&self, pcx: &PlaceCtxt<'_, Cx>) -> Result<SplitConstructorSet<Cx>, Cx::Error> {
|
fn analyze_ctors(&self, cx: &Cx, ty: &Cx::Ty) -> Result<SplitConstructorSet<Cx>, Cx::Error> {
|
||||||
let column_ctors = self.patterns.iter().map(|p| p.ctor());
|
let column_ctors = self.patterns.iter().map(|p| p.ctor());
|
||||||
let ctors_for_ty = &pcx.ctors_for_ty()?;
|
let ctors_for_ty = cx.ctors_for_ty(ty)?;
|
||||||
Ok(ctors_for_ty.split(column_ctors))
|
Ok(ctors_for_ty.split(column_ctors))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,10 +62,11 @@ impl<'p, Cx: TypeCx> PatternColumn<'p, Cx> {
|
||||||
/// which may change the lengths.
|
/// which may change the lengths.
|
||||||
fn specialize(
|
fn specialize(
|
||||||
&self,
|
&self,
|
||||||
pcx: &PlaceCtxt<'_, Cx>,
|
cx: &Cx,
|
||||||
|
ty: &Cx::Ty,
|
||||||
ctor: &Constructor<Cx>,
|
ctor: &Constructor<Cx>,
|
||||||
) -> Vec<PatternColumn<'p, Cx>> {
|
) -> Vec<PatternColumn<'p, Cx>> {
|
||||||
let arity = ctor.arity(pcx);
|
let arity = ctor.arity(cx, ty);
|
||||||
if arity == 0 {
|
if arity == 0 {
|
||||||
return Vec::new();
|
return Vec::new();
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,7 @@ impl<'p, Cx: TypeCx> PatternColumn<'p, Cx> {
|
||||||
let mut specialized_columns: Vec<_> =
|
let mut specialized_columns: Vec<_> =
|
||||||
(0..arity).map(|_| Self { patterns: Vec::new() }).collect();
|
(0..arity).map(|_| Self { patterns: Vec::new() }).collect();
|
||||||
let relevant_patterns =
|
let relevant_patterns =
|
||||||
self.patterns.iter().filter(|pat| ctor.is_covered_by(pcx, pat.ctor()));
|
self.patterns.iter().filter(|pat| ctor.is_covered_by(cx, pat.ctor()));
|
||||||
for pat in relevant_patterns {
|
for pat in relevant_patterns {
|
||||||
let specialized = pat.specialize(ctor, arity);
|
let specialized = pat.specialize(ctor, arity);
|
||||||
for (subpat, column) in specialized.into_iter().zip(&mut specialized_columns) {
|
for (subpat, column) in specialized.into_iter().zip(&mut specialized_columns) {
|
||||||
|
@ -92,15 +92,14 @@ impl<'p, Cx: TypeCx> PatternColumn<'p, Cx> {
|
||||||
/// in a given column.
|
/// in a given column.
|
||||||
#[instrument(level = "debug", skip(cx), ret)]
|
#[instrument(level = "debug", skip(cx), ret)]
|
||||||
fn collect_nonexhaustive_missing_variants<'a, 'p, 'tcx>(
|
fn collect_nonexhaustive_missing_variants<'a, 'p, 'tcx>(
|
||||||
cx: MatchCtxt<'a, 'p, 'tcx>,
|
cx: &RustcMatchCheckCtxt<'p, 'tcx>,
|
||||||
column: &PatternColumn<'p, RustcMatchCheckCtxt<'p, 'tcx>>,
|
column: &PatternColumn<'p, RustcMatchCheckCtxt<'p, 'tcx>>,
|
||||||
) -> Result<Vec<WitnessPat<'p, 'tcx>>, ErrorGuaranteed> {
|
) -> Result<Vec<WitnessPat<'p, 'tcx>>, ErrorGuaranteed> {
|
||||||
let Some(&ty) = column.head_ty() else {
|
let Some(&ty) = column.head_ty() else {
|
||||||
return Ok(Vec::new());
|
return Ok(Vec::new());
|
||||||
};
|
};
|
||||||
let pcx = &PlaceCtxt::new_dummy(cx, &ty);
|
|
||||||
|
|
||||||
let set = column.analyze_ctors(pcx)?;
|
let set = column.analyze_ctors(cx, &ty)?;
|
||||||
if set.present.is_empty() {
|
if set.present.is_empty() {
|
||||||
// We can't consistently handle the case where no constructors are present (since this would
|
// We can't consistently handle the case where no constructors are present (since this would
|
||||||
// require digging deep through any type in case there's a non_exhaustive enum somewhere),
|
// require digging deep through any type in case there's a non_exhaustive enum somewhere),
|
||||||
|
@ -109,20 +108,20 @@ fn collect_nonexhaustive_missing_variants<'a, 'p, 'tcx>(
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut witnesses = Vec::new();
|
let mut witnesses = Vec::new();
|
||||||
if cx.tycx.is_foreign_non_exhaustive_enum(ty) {
|
if cx.is_foreign_non_exhaustive_enum(ty) {
|
||||||
witnesses.extend(
|
witnesses.extend(
|
||||||
set.missing
|
set.missing
|
||||||
.into_iter()
|
.into_iter()
|
||||||
// This will list missing visible variants.
|
// This will list missing visible variants.
|
||||||
.filter(|c| !matches!(c, Constructor::Hidden | Constructor::NonExhaustive))
|
.filter(|c| !matches!(c, Constructor::Hidden | Constructor::NonExhaustive))
|
||||||
.map(|missing_ctor| WitnessPat::wild_from_ctor(pcx, missing_ctor)),
|
.map(|missing_ctor| WitnessPat::wild_from_ctor(cx, missing_ctor, ty)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recurse into the fields.
|
// Recurse into the fields.
|
||||||
for ctor in set.present {
|
for ctor in set.present {
|
||||||
let specialized_columns = column.specialize(pcx, &ctor);
|
let specialized_columns = column.specialize(cx, &ty, &ctor);
|
||||||
let wild_pat = WitnessPat::wild_from_ctor(pcx, ctor);
|
let wild_pat = WitnessPat::wild_from_ctor(cx, ctor, ty);
|
||||||
for (i, col_i) in specialized_columns.iter().enumerate() {
|
for (i, col_i) in specialized_columns.iter().enumerate() {
|
||||||
// Compute witnesses for each column.
|
// Compute witnesses for each column.
|
||||||
let wits_for_col_i = collect_nonexhaustive_missing_variants(cx, col_i)?;
|
let wits_for_col_i = collect_nonexhaustive_missing_variants(cx, col_i)?;
|
||||||
|
@ -138,18 +137,17 @@ fn collect_nonexhaustive_missing_variants<'a, 'p, 'tcx>(
|
||||||
Ok(witnesses)
|
Ok(witnesses)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn lint_nonexhaustive_missing_variants<'a, 'p, 'tcx>(
|
pub(crate) fn lint_nonexhaustive_missing_variants<'p, 'tcx>(
|
||||||
cx: MatchCtxt<'a, 'p, 'tcx>,
|
rcx: &RustcMatchCheckCtxt<'p, 'tcx>,
|
||||||
arms: &[MatchArm<'p, RustcMatchCheckCtxt<'p, 'tcx>>],
|
arms: &[MatchArm<'p, RustcMatchCheckCtxt<'p, 'tcx>>],
|
||||||
pat_column: &PatternColumn<'p, RustcMatchCheckCtxt<'p, 'tcx>>,
|
pat_column: &PatternColumn<'p, RustcMatchCheckCtxt<'p, 'tcx>>,
|
||||||
scrut_ty: RevealedTy<'tcx>,
|
scrut_ty: RevealedTy<'tcx>,
|
||||||
) -> Result<(), ErrorGuaranteed> {
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
let rcx: &RustcMatchCheckCtxt<'_, '_> = cx.tycx;
|
|
||||||
if !matches!(
|
if !matches!(
|
||||||
rcx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, rcx.match_lint_level).0,
|
rcx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, rcx.match_lint_level).0,
|
||||||
rustc_session::lint::Level::Allow
|
rustc_session::lint::Level::Allow
|
||||||
) {
|
) {
|
||||||
let witnesses = collect_nonexhaustive_missing_variants(cx, pat_column)?;
|
let witnesses = collect_nonexhaustive_missing_variants(rcx, pat_column)?;
|
||||||
if !witnesses.is_empty() {
|
if !witnesses.is_empty() {
|
||||||
// Report that a match of a `non_exhaustive` enum marked with `non_exhaustive_omitted_patterns`
|
// Report that a match of a `non_exhaustive` enum marked with `non_exhaustive_omitted_patterns`
|
||||||
// is not exhaustive enough.
|
// is not exhaustive enough.
|
||||||
|
|
|
@ -6,7 +6,6 @@ use std::fmt;
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
|
|
||||||
use crate::constructor::{Constructor, Slice, SliceKind};
|
use crate::constructor::{Constructor, Slice, SliceKind};
|
||||||
use crate::usefulness::PlaceCtxt;
|
|
||||||
use crate::{Captures, TypeCx};
|
use crate::{Captures, TypeCx};
|
||||||
|
|
||||||
use self::Constructor::*;
|
use self::Constructor::*;
|
||||||
|
@ -331,9 +330,9 @@ impl<Cx: TypeCx> WitnessPat<Cx> {
|
||||||
/// Construct a pattern that matches everything that starts with this constructor.
|
/// Construct a pattern that matches everything that starts with this constructor.
|
||||||
/// For example, if `ctor` is a `Constructor::Variant` for `Option::Some`, we get the pattern
|
/// For example, if `ctor` is a `Constructor::Variant` for `Option::Some`, we get the pattern
|
||||||
/// `Some(_)`.
|
/// `Some(_)`.
|
||||||
pub(crate) fn wild_from_ctor(pcx: &PlaceCtxt<'_, Cx>, ctor: Constructor<Cx>) -> Self {
|
pub(crate) fn wild_from_ctor(cx: &Cx, ctor: Constructor<Cx>, ty: Cx::Ty) -> Self {
|
||||||
let fields = pcx.ctor_sub_tys(&ctor).map(|ty| Self::wildcard(ty)).collect();
|
let fields = cx.ctor_sub_tys(&ctor, &ty).map(|ty| Self::wildcard(ty)).collect();
|
||||||
Self::new(ctor, fields, pcx.ty.clone())
|
Self::new(ctor, fields, ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ctor(&self) -> &Constructor<Cx> {
|
pub fn ctor(&self) -> &Constructor<Cx> {
|
||||||
|
|
|
@ -30,7 +30,6 @@ pub type ConstructorSet<'p, 'tcx> =
|
||||||
pub type DeconstructedPat<'p, 'tcx> =
|
pub type DeconstructedPat<'p, 'tcx> =
|
||||||
crate::pat::DeconstructedPat<'p, RustcMatchCheckCtxt<'p, 'tcx>>;
|
crate::pat::DeconstructedPat<'p, RustcMatchCheckCtxt<'p, 'tcx>>;
|
||||||
pub type MatchArm<'p, 'tcx> = crate::MatchArm<'p, RustcMatchCheckCtxt<'p, 'tcx>>;
|
pub type MatchArm<'p, 'tcx> = crate::MatchArm<'p, RustcMatchCheckCtxt<'p, 'tcx>>;
|
||||||
pub type MatchCtxt<'a, 'p, 'tcx> = crate::MatchCtxt<'a, RustcMatchCheckCtxt<'p, 'tcx>>;
|
|
||||||
pub type Usefulness<'p, 'tcx> = crate::usefulness::Usefulness<'p, RustcMatchCheckCtxt<'p, 'tcx>>;
|
pub type Usefulness<'p, 'tcx> = crate::usefulness::Usefulness<'p, RustcMatchCheckCtxt<'p, 'tcx>>;
|
||||||
pub type UsefulnessReport<'p, 'tcx> =
|
pub type UsefulnessReport<'p, 'tcx> =
|
||||||
crate::usefulness::UsefulnessReport<'p, RustcMatchCheckCtxt<'p, 'tcx>>;
|
crate::usefulness::UsefulnessReport<'p, RustcMatchCheckCtxt<'p, 'tcx>>;
|
||||||
|
|
|
@ -731,20 +731,19 @@ pub fn ensure_sufficient_stack<R>(f: impl FnOnce() -> R) -> R {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Context that provides information local to a place under investigation.
|
/// Context that provides information local to a place under investigation.
|
||||||
pub(crate) struct PlaceCtxt<'a, Cx: TypeCx> {
|
struct PlaceCtxt<'a, Cx: TypeCx> {
|
||||||
pub(crate) mcx: MatchCtxt<'a, Cx>,
|
mcx: MatchCtxt<'a, Cx>,
|
||||||
/// Type of the place under investigation.
|
/// Type of the place under investigation.
|
||||||
pub(crate) ty: &'a Cx::Ty,
|
ty: &'a Cx::Ty,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, Cx: TypeCx> Copy for PlaceCtxt<'a, Cx> {}
|
||||||
impl<'a, Cx: TypeCx> Clone for PlaceCtxt<'a, Cx> {
|
impl<'a, Cx: TypeCx> Clone for PlaceCtxt<'a, Cx> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
Self { mcx: self.mcx, ty: self.ty }
|
Self { mcx: self.mcx, ty: self.ty }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Cx: TypeCx> Copy for PlaceCtxt<'a, Cx> {}
|
|
||||||
|
|
||||||
impl<'a, Cx: TypeCx> fmt::Debug for PlaceCtxt<'a, Cx> {
|
impl<'a, Cx: TypeCx> fmt::Debug for PlaceCtxt<'a, Cx> {
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
fmt.debug_struct("PlaceCtxt").field("ty", self.ty).finish()
|
fmt.debug_struct("PlaceCtxt").field("ty", self.ty).finish()
|
||||||
|
@ -752,24 +751,21 @@ impl<'a, Cx: TypeCx> fmt::Debug for PlaceCtxt<'a, Cx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Cx: TypeCx> PlaceCtxt<'a, Cx> {
|
impl<'a, Cx: TypeCx> PlaceCtxt<'a, Cx> {
|
||||||
/// A `PlaceCtxt` when code other than `is_useful` needs one.
|
fn ctor_arity(&self, ctor: &Constructor<Cx>) -> usize {
|
||||||
#[cfg_attr(not(feature = "rustc"), allow(dead_code))]
|
|
||||||
pub(crate) fn new_dummy(mcx: MatchCtxt<'a, Cx>, ty: &'a Cx::Ty) -> Self {
|
|
||||||
PlaceCtxt { mcx, ty }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn ctor_arity(&self, ctor: &Constructor<Cx>) -> usize {
|
|
||||||
self.mcx.tycx.ctor_arity(ctor, self.ty)
|
self.mcx.tycx.ctor_arity(ctor, self.ty)
|
||||||
}
|
}
|
||||||
pub(crate) fn ctor_sub_tys(
|
fn ctor_sub_tys(
|
||||||
&'a self,
|
&'a self,
|
||||||
ctor: &'a Constructor<Cx>,
|
ctor: &'a Constructor<Cx>,
|
||||||
) -> impl Iterator<Item = Cx::Ty> + ExactSizeIterator + Captures<'a> {
|
) -> impl Iterator<Item = Cx::Ty> + ExactSizeIterator + Captures<'a> {
|
||||||
self.mcx.tycx.ctor_sub_tys(ctor, self.ty)
|
self.mcx.tycx.ctor_sub_tys(ctor, self.ty)
|
||||||
}
|
}
|
||||||
pub(crate) fn ctors_for_ty(&self) -> Result<ConstructorSet<Cx>, Cx::Error> {
|
fn ctors_for_ty(&self) -> Result<ConstructorSet<Cx>, Cx::Error> {
|
||||||
self.mcx.tycx.ctors_for_ty(self.ty)
|
self.mcx.tycx.ctors_for_ty(self.ty)
|
||||||
}
|
}
|
||||||
|
fn wild_from_ctor(&self, ctor: Constructor<Cx>) -> WitnessPat<Cx> {
|
||||||
|
WitnessPat::wild_from_ctor(self.mcx.tycx, ctor, self.ty.clone())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Serves two purposes:
|
/// Serves two purposes:
|
||||||
|
@ -1089,7 +1085,7 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> {
|
||||||
wildcard_row_is_relevant: self.wildcard_row_is_relevant && ctor_is_relevant,
|
wildcard_row_is_relevant: self.wildcard_row_is_relevant && ctor_is_relevant,
|
||||||
};
|
};
|
||||||
for (i, row) in self.rows().enumerate() {
|
for (i, row) in self.rows().enumerate() {
|
||||||
if ctor.is_covered_by(pcx, row.head().ctor()) {
|
if ctor.is_covered_by(pcx.mcx.tycx, row.head().ctor()) {
|
||||||
let new_row = row.pop_head_constructor(ctor, arity, ctor_is_relevant, i);
|
let new_row = row.pop_head_constructor(ctor, arity, ctor_is_relevant, i);
|
||||||
matrix.expand_and_push(new_row);
|
matrix.expand_and_push(new_row);
|
||||||
}
|
}
|
||||||
|
@ -1240,7 +1236,7 @@ impl<Cx: TypeCx> WitnessStack<Cx> {
|
||||||
/// ```
|
/// ```
|
||||||
fn apply_constructor(&mut self, pcx: &PlaceCtxt<'_, Cx>, ctor: &Constructor<Cx>) {
|
fn apply_constructor(&mut self, pcx: &PlaceCtxt<'_, Cx>, ctor: &Constructor<Cx>) {
|
||||||
let len = self.0.len();
|
let len = self.0.len();
|
||||||
let arity = ctor.arity(pcx);
|
let arity = pcx.ctor_arity(ctor);
|
||||||
let fields = self.0.drain((len - arity)..).rev().collect();
|
let fields = self.0.drain((len - arity)..).rev().collect();
|
||||||
let pat = WitnessPat::new(ctor.clone(), fields, pcx.ty.clone());
|
let pat = WitnessPat::new(ctor.clone(), fields, pcx.ty.clone());
|
||||||
self.0.push(pat);
|
self.0.push(pat);
|
||||||
|
@ -1315,20 +1311,20 @@ impl<Cx: TypeCx> WitnessMatrix<Cx> {
|
||||||
*self = Self::empty();
|
*self = Self::empty();
|
||||||
} else if !report_individual_missing_ctors {
|
} else if !report_individual_missing_ctors {
|
||||||
// Report `_` as missing.
|
// Report `_` as missing.
|
||||||
let pat = WitnessPat::wild_from_ctor(pcx, Constructor::Wildcard);
|
let pat = pcx.wild_from_ctor(Constructor::Wildcard);
|
||||||
self.push_pattern(pat);
|
self.push_pattern(pat);
|
||||||
} else if missing_ctors.iter().any(|c| c.is_non_exhaustive()) {
|
} else if missing_ctors.iter().any(|c| c.is_non_exhaustive()) {
|
||||||
// We need to report a `_` anyway, so listing other constructors would be redundant.
|
// We need to report a `_` anyway, so listing other constructors would be redundant.
|
||||||
// `NonExhaustive` is displayed as `_` just like `Wildcard`, but it will be picked
|
// `NonExhaustive` is displayed as `_` just like `Wildcard`, but it will be picked
|
||||||
// up by diagnostics to add a note about why `_` is required here.
|
// up by diagnostics to add a note about why `_` is required here.
|
||||||
let pat = WitnessPat::wild_from_ctor(pcx, Constructor::NonExhaustive);
|
let pat = pcx.wild_from_ctor(Constructor::NonExhaustive);
|
||||||
self.push_pattern(pat);
|
self.push_pattern(pat);
|
||||||
} else {
|
} else {
|
||||||
// For each missing constructor `c`, we add a `c(_, _, _)` witness appropriately
|
// For each missing constructor `c`, we add a `c(_, _, _)` witness appropriately
|
||||||
// filled with wildcards.
|
// filled with wildcards.
|
||||||
let mut ret = Self::empty();
|
let mut ret = Self::empty();
|
||||||
for ctor in missing_ctors {
|
for ctor in missing_ctors {
|
||||||
let pat = WitnessPat::wild_from_ctor(pcx, ctor.clone());
|
let pat = pcx.wild_from_ctor(ctor.clone());
|
||||||
// Clone `self` and add `c(_, _, _)` to each of its witnesses.
|
// Clone `self` and add `c(_, _, _)` to each of its witnesses.
|
||||||
let mut wit_matrix = self.clone();
|
let mut wit_matrix = self.clone();
|
||||||
wit_matrix.push_pattern(pat);
|
wit_matrix.push_pattern(pat);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue