Merge pull request #35664 from arielb1/split-literals

prohibit splitting literal patterns
diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs
index a5a9dea..e4a2988 100644
--- a/src/librustc_const_eval/check_match.rs
+++ b/src/librustc_const_eval/check_match.rs
@@ -706,9 +706,12 @@
     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 @@
                 }
             }).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 @@
             }
         }
     } 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 @@
     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 @@
 /// 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(..) =>
diff --git a/src/test/compile-fail/issue-35044.rs b/src/test/compile-fail/issue-35044.rs
new file mode 100644
index 0000000..64b8151
--- /dev/null
+++ b/src/test/compile-fail/issue-35044.rs
@@ -0,0 +1,46 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[derive(Debug, PartialEq)]
+enum Reg {
+    EAX,
+    EBX,
+    ECX,
+    EDX,
+    ESP,
+    EBP,
+    ISP,
+}
+
+fn string_to_reg(_s:&str) -> Reg {
+    match _s.as_ref() {
+        "EAX" => Reg::EAX,
+        "EBX" => Reg::EBX,
+        "ECX" => Reg::ECX,
+        "EDX" => Reg::EDX,
+        "EBP" => Reg::EBP,
+        "ESP" => Reg::ESP,
+        "ISP" => Reg::ISP, //~ NOTE split literal here
+        &_    => panic!("bla bla bla"), //~ ERROR see issue #35044
+    }
+}
+
+fn main() {
+    let vec = vec!["EAX", "EBX", "ECX", "EDX", "ESP", "EBP", "ISP"];
+    let mut iter = vec.iter();
+    println!("{:?}", string_to_reg(""));
+    println!("{:?}", string_to_reg(iter.next().unwrap()));
+    println!("{:?}", string_to_reg(iter.next().unwrap()));
+    println!("{:?}", string_to_reg(iter.next().unwrap()));
+    println!("{:?}", string_to_reg(iter.next().unwrap()));
+    println!("{:?}",  string_to_reg(iter.next().unwrap()));
+    println!("{:?}", string_to_reg(iter.next().unwrap()));
+    println!("{:?}",  string_to_reg(iter.next().unwrap()));
+}