Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor slice pattern usefulness checking #66129

Merged
merged 18 commits into from
Nov 12, 2019
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 33 additions & 21 deletions src/librustc_mir/hair/pattern/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -657,31 +657,43 @@ impl<'tcx> Constructor<'tcx> {
param_env: ty::ParamEnv<'tcx>,
other_ctors: &Vec<Constructor<'tcx>>,
) -> Vec<Constructor<'tcx>> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has got me thinking... would using Cow<[Constructor]> be more efficient if perhaps Single | ... and friends are more common?

(If so, we shouldn't make such changes here, but perhaps in some follow-up.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quite possibly yes. It'd also be not too hard to take self instead of &self, if we want to avoid cloning. I don't know which would be better

let mut refined_ctors = vec![self.clone()];
for other_ctor in other_ctors {
if other_ctor == self {
// If a constructor appears in a `match` arm, we can
// eliminate it straight away.
refined_ctors = vec![]
} else if let Some(interval) = IntRange::from_ctor(tcx, param_env, other_ctor) {
// Refine the required constructors for the type by subtracting
// the range defined by the current constructor pattern.
refined_ctors = interval.subtract_from(tcx, param_env, refined_ctors);
match self {
// Those constructors can only match themselves.
Single | Variant(_) | FixedLenSlice(_) => {
if other_ctors.iter().any(|c| c == self) {
vec![]
} else {
vec![self.clone()]
}
}
ConstantRange(..) | ConstantValue(..) => {
let mut remaining_ctors = vec![self.clone()];
for other_ctor in other_ctors {
if other_ctor == self {
// If a constructor appears in a `match` arm, we can
// eliminate it straight away.
remaining_ctors = vec![]
} else if let Some(interval) = IntRange::from_ctor(tcx, param_env, other_ctor) {
// Refine the required constructors for the type by subtracting
// the range defined by the current constructor pattern.
remaining_ctors = interval.subtract_from(tcx, param_env, remaining_ctors);
}

// If the constructor patterns that have been considered so far
// already cover the entire range of values, then we know the
// constructor is not missing, and we can move on to the next one.
if refined_ctors.is_empty() {
break;
// If the constructor patterns that have been considered so far
// already cover the entire range of values, then we know the
// constructor is not missing, and we can move on to the next one.
if remaining_ctors.is_empty() {
break;
}
}

// If a constructor has not been matched, then it is missing.
// We add `remaining_ctors` instead of `self`, because then we can
// provide more detailed error information about precisely which
// ranges have been omitted.
remaining_ctors
}
}

// If a constructor has not been matched, then it is missing.
// We add `refined_ctors` instead of `self`, because then we can
// provide more detailed error information about precisely which
// ranges have been omitted.
refined_ctors
}

/// This returns one wildcard pattern for each argument to this constructor.
Expand Down