Skip to content

Commit 57144ff

Browse files
committed
ayy one pass
1 parent 30bc24e commit 57144ff

File tree

4 files changed

+198
-354
lines changed

4 files changed

+198
-354
lines changed

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

+16-112
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@
3737
//! skipping some constructors as long as it doesn't change whether the resulting list of witnesses
3838
//! is empty of not. We use this in the wildcard `_` case.
3939
//!
40-
//! Splitting is implemented in the [`Constructor::split`] function. We don't do splitting for
40+
//! Splitting is implemented in the [`ConstructorSet::split`] function. We don't do splitting for
4141
//! or-patterns; instead we just try the alternatives one-by-one. For details on splitting
42-
//! wildcards, see [`Constructor::split`]; for integer ranges, see
43-
//! [`IntRange::split`]; for slices, see [`Slice::split`].
42+
//! wildcards, see [`ConstructorSet::split`]; for integer ranges, see [`IntRange::split`]; for
43+
//! slices, see [`Slice::split`].
4444
//!
4545
//! ## Opaque patterns
4646
//!
@@ -678,8 +678,8 @@ pub(super) enum Constructor<'tcx> {
678678
/// We use this for variants behind an unstable gate as well as
679679
/// `#[doc(hidden)]` ones.
680680
Hidden,
681-
/// Fake extra constructor for constructors that are not seen in the matrix, as explained in the
682-
/// code for [`Constructor::split`].
681+
/// Fake extra constructor for constructors that are not seen in the matrix, as explained at the
682+
/// top of the file.
683683
Missing,
684684
}
685685

@@ -761,104 +761,12 @@ impl<'tcx> Constructor<'tcx> {
761761
}
762762
}
763763

764-
/// Some constructors (namely `Wildcard`, `IntRange` and `Slice`) actually stand for a set of
765-
/// actual constructors (like variants, integers or fixed-sized slices). When specializing for
766-
/// these constructors, we want to be specialising for the actual underlying constructors.
767-
/// Naively, we would simply return the list of constructors they correspond to. We instead are
768-
/// more clever: if there are constructors that we know will behave the same w.r.t. the current
769-
/// matrix, we keep them grouped. For example, all slices of a sufficiently large length will
770-
/// either be all useful or all non-useful with a given matrix.
771-
///
772-
/// See the branches for details on how the splitting is done.
773-
///
774-
/// This function may discard some irrelevant constructors if this preserves behavior. Eg. for
775-
/// the `_` case, we ignore the constructors already present in the column, unless all of them
776-
/// are.
777-
pub(super) fn split<'a>(
778-
&self,
779-
pcx: &PatCtxt<'_, '_, 'tcx>,
780-
ctors: impl Iterator<Item = &'a Constructor<'tcx>> + Clone,
781-
) -> SmallVec<[Self; 1]>
782-
where
783-
'tcx: 'a,
784-
{
785-
match self {
786-
Wildcard => {
787-
let split_set = ConstructorSet::for_ty(pcx.cx, pcx.ty).split(pcx, ctors);
788-
if !split_set.missing.is_empty() {
789-
// We are splitting a wildcard in order to compute its usefulness. Some constructors are
790-
// not present in the column. The first thing we note is that specializing with any of
791-
// the missing constructors would select exactly the rows with wildcards. Moreover, they
792-
// would all return equivalent results. We can therefore group them all into a
793-
// fictitious `Missing` constructor.
794-
//
795-
// As an important optimization, this function will skip all the present constructors.
796-
// This is correct because specializing with any of the present constructors would
797-
// select a strict superset of the wildcard rows, and thus would only find witnesses
798-
// already found with the `Missing` constructor.
799-
// This does mean that diagnostics are incomplete: in
800-
// ```
801-
// match x {
802-
// Some(true) => {}
803-
// }
804-
// ```
805-
// we report `None` as missing but not `Some(false)`.
806-
//
807-
// When all the constructors are missing we can equivalently return the `Wildcard`
808-
// constructor on its own. The difference between `Wildcard` and `Missing` will then
809-
// only be in diagnostics.
810-
811-
// If some constructors are missing, we typically want to report those constructors,
812-
// e.g.:
813-
// ```
814-
// enum Direction { N, S, E, W }
815-
// let Direction::N = ...;
816-
// ```
817-
// we can report 3 witnesses: `S`, `E`, and `W`.
818-
//
819-
// However, if the user didn't actually specify a constructor
820-
// in this arm, e.g., in
821-
// ```
822-
// let x: (Direction, Direction, bool) = ...;
823-
// let (_, _, false) = x;
824-
// ```
825-
// we don't want to show all 16 possible witnesses `(<direction-1>, <direction-2>,
826-
// true)` - we are satisfied with `(_, _, true)`. So if all constructors are missing we
827-
// prefer to report just a wildcard `_`.
828-
//
829-
// The exception is: if we are at the top-level, for example in an empty match, we
830-
// usually prefer to report the full list of constructors.
831-
let all_missing = split_set.present.is_empty();
832-
let report_when_all_missing =
833-
pcx.is_top_level && !IntRange::is_integral(pcx.ty);
834-
let ctor =
835-
if all_missing && !report_when_all_missing { Wildcard } else { Missing };
836-
smallvec![ctor]
837-
} else {
838-
split_set.present
839-
}
840-
}
841-
// Fast-track if the range is trivial.
842-
IntRange(this_range) if !this_range.is_singleton() => {
843-
let column_ranges = ctors.filter_map(|ctor| ctor.as_int_range()).cloned();
844-
this_range.split(column_ranges).map(|(_, range)| IntRange(range)).collect()
845-
}
846-
Slice(this_slice @ Slice { kind: VarLen(..), .. }) => {
847-
let column_slices = ctors.filter_map(|c| c.as_slice());
848-
this_slice.split(column_slices).map(|(_, slice)| Slice(slice)).collect()
849-
}
850-
// Any other constructor can be used unchanged.
851-
_ => smallvec![self.clone()],
852-
}
853-
}
854-
855764
/// Returns whether `self` is covered by `other`, i.e. whether `self` is a subset of `other`.
856765
/// For the simple cases, this is simply checking for equality. For the "grouped" constructors,
857766
/// this checks for inclusion.
858767
// We inline because this has a single call site in `Matrix::specialize_constructor`.
859768
#[inline]
860769
pub(super) fn is_covered_by<'p>(&self, pcx: &PatCtxt<'_, 'p, 'tcx>, other: &Self) -> bool {
861-
// This must be kept in sync with `is_covered_by_any`.
862770
match (self, other) {
863771
// Wildcards cover anything
864772
(_, Wildcard) => true,
@@ -1244,19 +1152,6 @@ impl ConstructorSet {
12441152

12451153
SplitConstructorSet { present, missing }
12461154
}
1247-
1248-
/// Compute the set of constructors missing from this column.
1249-
/// This is only used for reporting to the user.
1250-
pub(super) fn compute_missing<'a, 'tcx>(
1251-
&self,
1252-
pcx: &PatCtxt<'_, '_, 'tcx>,
1253-
ctors: impl Iterator<Item = &'a Constructor<'tcx>> + Clone,
1254-
) -> Vec<Constructor<'tcx>>
1255-
where
1256-
'tcx: 'a,
1257-
{
1258-
self.split(pcx, ctors).missing
1259-
}
12601155
}
12611156

12621157
/// A value can be decomposed into a constructor applied to some fields. This struct represents
@@ -1697,7 +1592,17 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
16971592
self.reachable.set(true)
16981593
}
16991594
pub(super) fn is_reachable(&self) -> bool {
1700-
self.reachable.get()
1595+
if self.reachable.get() {
1596+
true
1597+
} else if self.is_or_pat() && self.iter_fields().any(|f| f.is_reachable()) {
1598+
// We always expand or patterns in the matrix, so we will never see the actual
1599+
// or-pattern (the one with constructor `Or`) in the column. As such, it will not be
1600+
// marked as reachable itself, only its children will. We recover this information here.
1601+
self.set_reachable();
1602+
true
1603+
} else {
1604+
false
1605+
}
17011606
}
17021607

17031608
/// Report the spans of subpatterns that were not reachable, if any.
@@ -1706,7 +1611,6 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
17061611
self.collect_unreachable_spans(&mut spans);
17071612
spans
17081613
}
1709-
17101614
fn collect_unreachable_spans(&self, spans: &mut Vec<Span>) {
17111615
// We don't look at subpatterns if we already reported the whole pattern as unreachable.
17121616
if !self.is_reachable() {

0 commit comments

Comments
 (0)