summaryrefslogtreecommitdiff
path: root/src/librustc_const_eval/check_match.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/librustc_const_eval/check_match.rs')
-rw-r--r--src/librustc_const_eval/check_match.rs40
1 files changed, 39 insertions, 1 deletions
diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs
index a5a9dea61ad..e4a2988492d 100644
--- a/src/librustc_const_eval/check_match.rs
+++ b/src/librustc_const_eval/check_match.rs
@@ -706,9 +706,12 @@ fn is_useful<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>,
debug!("is_useful - pat_constructors = {:?} left_ty = {:?}", constructors,
left_ty);
if constructors.is_empty() {
+ // v[0] is a wildcard pattern - `pat_constructors` should really be returning
+ // an Option.
let constructors = missing_constructors(cx, matrix, left_ty, max_slice_length);
debug!("is_useful - missing_constructors = {:?}", constructors);
if constructors.is_empty() {
+ // all constructors are covered - must check them all.
all_constructors(cx, left_ty, max_slice_length).into_iter().map(|c| {
match is_useful_specialized(cx, matrix, v, c.clone(), left_ty, witness) {
UsefulWithWitness(pats) => UsefulWithWitness({
@@ -727,6 +730,7 @@ fn is_useful<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>,
}
}).find(|result| result != &NotUseful).unwrap_or(NotUseful)
} else {
+ // some constructor is only covered by wildcards - pick it.
let matrix = rows.iter().filter_map(|r| {
match raw_pat(r[0].0).node {
PatKind::Binding(..) | PatKind::Wild => Some(r[1..].to_vec()),
@@ -747,12 +751,41 @@ fn is_useful<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>,
}
}
} else {
+ // `v` is not a wildcard
constructors.into_iter().map(|c|
is_useful_specialized(cx, matrix, v, c.clone(), left_ty, witness)
).find(|result| result != &NotUseful).unwrap_or(NotUseful)
}
}
+fn check_for_ref_splitting<'s, 'a, 'tcx, I>(cx: &MatchCheckCtxt<'a, 'tcx>, data: I)
+ where I: Iterator<Item=(&'s Pat, Option<Ty<'tcx>>)>
+{
+ let mut ref_pattern = None;
+ let mut lit_pattern = None;
+
+ for (pat, _ty) in data {
+ match pat.node {
+ PatKind::Lit(..) => {
+ lit_pattern = Some(pat);
+ }
+ PatKind::Ref(..) => {
+ ref_pattern = Some(pat);
+ }
+ _ => {}
+ };
+ if let (Some(lit_pattern), Some(ref_pattern)) = (lit_pattern, ref_pattern) {
+ cx.tcx.sess.struct_span_err(
+ ref_pattern.span,
+ &format!("as a temporary restriction, literal patterns can't be split \
+ - see issue #35044")
+ ).span_note(lit_pattern.span, &format!("split literal here"))
+ .emit();
+ cx.tcx.sess.abort_if_errors();
+ }
+ }
+}
+
fn is_useful_specialized<'a, 'tcx>(
cx: &MatchCheckCtxt<'a, 'tcx>,
&Matrix(ref m): &Matrix<'a, 'tcx>,
@@ -762,6 +795,10 @@ fn is_useful_specialized<'a, 'tcx>(
witness: WitnessPreference) -> Usefulness
{
let arity = constructor_arity(cx, &ctor, lty);
+ check_for_ref_splitting(
+ cx,
+ m.iter().map(|r| r[0]).chain(Some(v[0]))
+ );
let matrix = Matrix(m.iter().filter_map(|r| {
specialize(cx, &r[..], &ctor, 0, arity)
}).collect());
@@ -781,7 +818,8 @@ fn is_useful_specialized<'a, 'tcx>(
/// On the other hand, a wild pattern and an identifier pattern cannot be
/// specialized in any way.
fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
- left_ty: Ty, max_slice_length: usize) -> Vec<Constructor> {
+ left_ty: Ty, max_slice_length: usize)
+ -> Vec<Constructor> {
let pat = raw_pat(p);
match pat.node {
PatKind::Struct(..) | PatKind::TupleStruct(..) | PatKind::Path(..) =>