Skip to content

Commit b7fa9f1

Browse files
committed
Factor out constructor subtraction
1 parent 92101b7 commit b7fa9f1

File tree

1 file changed

+36
-27
lines changed

1 file changed

+36
-27
lines changed

src/librustc_mir/hair/pattern/_match.rs

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,41 @@ impl<'tcx> Constructor<'tcx> {
646646
}
647647
}
648648

649+
// Returns the set of constructors covered by `self` but not by
650+
// anything in `other_ctors`.
651+
fn subtract_ctors(
652+
&self,
653+
tcx: TyCtxt<'tcx>,
654+
param_env: ty::ParamEnv<'tcx>,
655+
other_ctors: &Vec<Constructor<'tcx>>,
656+
) -> Vec<Constructor<'tcx>> {
657+
let mut refined_ctors = vec![self.clone()];
658+
for other_ctor in other_ctors {
659+
if other_ctor == self {
660+
// If a constructor appears in a `match` arm, we can
661+
// eliminate it straight away.
662+
refined_ctors = vec![]
663+
} else if let Some(interval) = IntRange::from_ctor(tcx, param_env, other_ctor) {
664+
// Refine the required constructors for the type by subtracting
665+
// the range defined by the current constructor pattern.
666+
refined_ctors = interval.subtract_from(tcx, param_env, refined_ctors);
667+
}
668+
669+
// If the constructor patterns that have been considered so far
670+
// already cover the entire range of values, then we know the
671+
// constructor is not missing, and we can move on to the next one.
672+
if refined_ctors.is_empty() {
673+
break;
674+
}
675+
}
676+
677+
// If a constructor has not been matched, then it is missing.
678+
// We add `refined_ctors` instead of `self`, because then we can
679+
// provide more detailed error information about precisely which
680+
// ranges have been omitted.
681+
refined_ctors
682+
}
683+
649684
/// This returns one wildcard pattern for each argument to this constructor.
650685
fn wildcard_subpatterns<'a>(
651686
&self,
@@ -1313,33 +1348,7 @@ impl<'tcx> MissingConstructors<'tcx> {
13131348
/// Iterate over all_ctors \ used_ctors
13141349
fn iter<'a>(&'a self) -> impl Iterator<Item = Constructor<'tcx>> + Captures<'a> {
13151350
self.all_ctors.iter().flat_map(move |req_ctor| {
1316-
let mut refined_ctors = vec![req_ctor.clone()];
1317-
for used_ctor in &self.used_ctors {
1318-
if used_ctor == req_ctor {
1319-
// If a constructor appears in a `match` arm, we can
1320-
// eliminate it straight away.
1321-
refined_ctors = vec![]
1322-
} else if let Some(interval) =
1323-
IntRange::from_ctor(self.tcx, self.param_env, used_ctor)
1324-
{
1325-
// Refine the required constructors for the type by subtracting
1326-
// the range defined by the current constructor pattern.
1327-
refined_ctors = interval.subtract_from(self.tcx, self.param_env, refined_ctors);
1328-
}
1329-
1330-
// If the constructor patterns that have been considered so far
1331-
// already cover the entire range of values, then we know the
1332-
// constructor is not missing, and we can move on to the next one.
1333-
if refined_ctors.is_empty() {
1334-
break;
1335-
}
1336-
}
1337-
1338-
// If a constructor has not been matched, then it is missing.
1339-
// We add `refined_ctors` instead of `req_ctor`, because then we can
1340-
// provide more detailed error information about precisely which
1341-
// ranges have been omitted.
1342-
refined_ctors
1351+
req_ctor.subtract_ctors(self.tcx, self.param_env, &self.used_ctors)
13431352
})
13441353
}
13451354
}

0 commit comments

Comments
 (0)