mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 11:07:42 +00:00
Reimplement Usefulness::merge
in terms of a binop
This commit is contained in:
parent
5547105f6b
commit
f4f20c0663
@ -696,9 +696,9 @@ impl<'tcx> Usefulness<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// When trying several branches and each returns a `Usefulness`, we need to combine the
|
/// Combine usefulnesses from two branches. This is an associative operation and `NotUseful` is
|
||||||
/// results together.
|
/// a unit.
|
||||||
fn merge(usefulnesses: impl Iterator<Item = Self>) -> Self {
|
fn extend(&mut self, other: Self) {
|
||||||
// If we have detected some unreachable sub-branches, we only want to keep them when they
|
// If we have detected some unreachable sub-branches, we only want to keep them when they
|
||||||
// were unreachable in _all_ branches. Eg. in the following, the last `true` is unreachable
|
// were unreachable in _all_ branches. Eg. in the following, the last `true` is unreachable
|
||||||
// in the second branch of the first or-pattern, but not otherwise. Therefore we don't want
|
// in the second branch of the first or-pattern, but not otherwise. Therefore we don't want
|
||||||
@ -709,54 +709,39 @@ impl<'tcx> Usefulness<'tcx> {
|
|||||||
// (false | true, false | true) => {}
|
// (false | true, false | true) => {}
|
||||||
// }
|
// }
|
||||||
// ```
|
// ```
|
||||||
// Here however we _do_ want to lint that the last `false` is unreachable. So we don't want
|
// Here however we _do_ want to lint that the last `false` is unreachable. In order to
|
||||||
// to intersect the spans that come directly from the or-pattern, since each branch of the
|
// handle that correctly, each branch of an or-pattern marks the other branches as
|
||||||
// or-pattern brings a new disjoint pattern.
|
// unreachable (see `unsplit_or_pat`). That way, intersecting the results will correctly
|
||||||
|
// identify unreachable sub-patterns.
|
||||||
// ```
|
// ```
|
||||||
// match None {
|
// match None {
|
||||||
// Some(false) => {}
|
// Some(false) => {}
|
||||||
// None | Some(true | false) => {}
|
// None | Some(true | false) => {}
|
||||||
// }
|
// }
|
||||||
// ```
|
// ```
|
||||||
|
match (&mut *self, other) {
|
||||||
|
(Useful(s), Useful(o)) => s.intersection_mut(&o),
|
||||||
|
(UsefulWithWitness(s), UsefulWithWitness(o)) => s.extend(o),
|
||||||
|
(_, NotUseful) => {}
|
||||||
|
(NotUseful, other) => *self = other,
|
||||||
|
(UsefulWithWitness(_), Useful(_)) | (Useful(_), UsefulWithWitness(_)) => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Is `None` when no branch was useful. Will often be `Some(Spanset::new())` because the
|
/// When trying several branches and each returns a `Usefulness`, we need to combine the
|
||||||
// sets are only non-empty in the presence of or-patterns.
|
/// results together.
|
||||||
let mut unreachables: Option<SpanSet> = None;
|
fn merge(usefulnesses: impl Iterator<Item = Self>) -> Self {
|
||||||
// Witnesses of usefulness, if any.
|
let mut ret = NotUseful;
|
||||||
let mut witnesses = Vec::new();
|
|
||||||
|
|
||||||
for u in usefulnesses {
|
for u in usefulnesses {
|
||||||
match u {
|
ret.extend(u);
|
||||||
Useful(spans) if spans.is_empty() => {
|
if let Useful(spans) = &ret {
|
||||||
|
if spans.is_empty() {
|
||||||
// Once we reach the empty set, more intersections won't change the result.
|
// Once we reach the empty set, more intersections won't change the result.
|
||||||
return Useful(SpanSet::new());
|
return ret;
|
||||||
}
|
|
||||||
Useful(spans) => {
|
|
||||||
if let Some(unreachables) = &mut unreachables {
|
|
||||||
if !unreachables.is_empty() {
|
|
||||||
unreachables.intersection_mut(&spans);
|
|
||||||
}
|
|
||||||
if unreachables.is_empty() {
|
|
||||||
return Useful(SpanSet::new());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
unreachables = Some(spans);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
NotUseful => {}
|
|
||||||
UsefulWithWitness(wits) => {
|
|
||||||
witnesses.extend(wits);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ret
|
||||||
if !witnesses.is_empty() {
|
|
||||||
UsefulWithWitness(witnesses)
|
|
||||||
} else if let Some(unreachables) = unreachables {
|
|
||||||
Useful(unreachables)
|
|
||||||
} else {
|
|
||||||
NotUseful
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// After calculating the usefulness for a branch of an or-pattern, call this to make this
|
/// After calculating the usefulness for a branch of an or-pattern, call this to make this
|
||||||
|
Loading…
Reference in New Issue
Block a user