From c484c2d1f840a3fd195b951a67745564b51715ad Mon Sep 17 00:00:00 2001
From: Jakub Wieczorek <jakub@jakub.cc>
Date: Tue, 24 Jun 2014 00:12:17 +0200
Subject: [PATCH] Fix #15129

Add support for unit literals to const_eval.
---
 src/librustc/middle/check_match.rs            |  9 ++---
 src/librustc/middle/const_eval.rs             |  6 ++--
 src/librustc/middle/ty.rs                     |  6 ++++
 src/test/compile-fail/issue-15129.rs          | 27 +++++++++++++++
 .../non-exhaustive-pattern-witness.rs         | 11 ++++---
 src/test/compile-fail/repeat_count.rs         |  8 ++++-
 src/test/run-pass/issue-15129.rs              | 33 +++++++++++++++++++
 7 files changed, 89 insertions(+), 11 deletions(-)
 create mode 100644 src/test/compile-fail/issue-15129.rs
 create mode 100644 src/test/run-pass/issue-15129.rs

diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs
index 09a9273dba7..629c7f4dab7 100644
--- a/src/librustc/middle/check_match.rs
+++ b/src/librustc/middle/check_match.rs
@@ -10,7 +10,7 @@
 
 #![allow(non_camel_case_types)]
 
-use middle::const_eval::{compare_const_vals, const_bool, const_float, const_val};
+use middle::const_eval::{compare_const_vals, const_bool, const_float, const_nil, const_val};
 use middle::const_eval::{eval_const_expr, lookup_const_by_id};
 use middle::def::*;
 use middle::pat_util::*;
@@ -203,6 +203,7 @@ enum ctor {
 fn const_val_to_expr(value: &const_val) -> Gc<Expr> {
     let node = match value {
         &const_bool(b) => LitBool(b),
+        &const_nil => LitNil,
         _ => unreachable!()
     };
     box(GC) Expr {
@@ -309,6 +310,9 @@ fn all_constructors(cx: &MatchCheckCtxt, m: &Matrix, left_ty: ty::t) -> Vec<ctor
         ty::ty_bool =>
             [true, false].iter().map(|b| val(const_bool(*b))).collect(),
 
+        ty::ty_nil =>
+            vec!(val(const_nil)),
+
         ty::ty_rptr(_, ty::mt { ty: ty, .. }) => match ty::get(ty).sty {
             ty::ty_vec(_, None) => vec_constructors(m),
             _ => vec!(single)
@@ -326,9 +330,6 @@ fn all_constructors(cx: &MatchCheckCtxt, m: &Matrix, left_ty: ty::t) -> Vec<ctor
         ty::ty_vec(_, Some(n)) =>
             vec!(vec(n)),
 
-        ty::ty_nil if !m.iter().all(|r| is_wild(cx, *r.get(0))) =>
-            vec!(),
-
         _ =>
             vec!(single)
     }
diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs
index 4444cac0043..7567e73b01d 100644
--- a/src/librustc/middle/const_eval.rs
+++ b/src/librustc/middle/const_eval.rs
@@ -299,7 +299,8 @@ pub enum const_val {
     const_uint(u64),
     const_str(InternedString),
     const_binary(Rc<Vec<u8> >),
-    const_bool(bool)
+    const_bool(bool),
+    const_nil
 }
 
 pub fn eval_const_expr(tcx: &ty::ctxt, e: &Expr) -> const_val {
@@ -514,7 +515,7 @@ pub fn lit_to_const(lit: &Lit) -> const_val {
         LitFloat(ref n, _) | LitFloatUnsuffixed(ref n) => {
             const_float(from_str::<f64>(n.get()).unwrap() as f64)
         }
-        LitNil => const_int(0i64),
+        LitNil => const_nil,
         LitBool(b) => const_bool(b)
     }
 }
@@ -530,6 +531,7 @@ pub fn compare_const_vals(a: &const_val, b: &const_val) -> Option<int> {
         (&const_str(ref a), &const_str(ref b)) => compare_vals(a, b),
         (&const_bool(a), &const_bool(b)) => compare_vals(a, b),
         (&const_binary(ref a), &const_binary(ref b)) => compare_vals(a, b),
+        (&const_nil, &const_nil) => compare_vals((), ()),
         _ => None
     }
 }
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index b0e838a442b..689a47f1136 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -4184,6 +4184,12 @@ pub fn eval_repeat_count<T: ExprTyProvider>(tcx: &T, count_expr: &ast::Expr) ->
                                          repeat count but found binary array");
             return 0;
         }
+        const_eval::const_nil => {
+            tcx.ty_ctxt().sess.span_err(count_expr.span,
+                                        "expected positive integer for \
+                                         repeat count but found ()");
+            return 0;
+        }
       },
       Err(..) => {
         tcx.ty_ctxt().sess.span_err(count_expr.span,
diff --git a/src/test/compile-fail/issue-15129.rs b/src/test/compile-fail/issue-15129.rs
new file mode 100644
index 00000000000..83d7096087e
--- /dev/null
+++ b/src/test/compile-fail/issue-15129.rs
@@ -0,0 +1,27 @@
+// Copyright 2014 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.
+
+pub enum T {
+    T1(()),
+    T2(())
+}
+
+pub enum V {
+    V1(int),
+    V2(bool)
+}
+
+fn main() {
+    match (T1(()), V2(true)) {
+    //~^ ERROR non-exhaustive patterns: `(T1(()), V2(_))` not covered
+        (T1(()), V1(i)) => (),
+        (T2(()), V2(b)) => ()
+    }
+}
diff --git a/src/test/compile-fail/non-exhaustive-pattern-witness.rs b/src/test/compile-fail/non-exhaustive-pattern-witness.rs
index d0f51bf2da4..7fba306d868 100644
--- a/src/test/compile-fail/non-exhaustive-pattern-witness.rs
+++ b/src/test/compile-fail/non-exhaustive-pattern-witness.rs
@@ -67,8 +67,11 @@ fn vectors_with_nested_enums() {
     }
 }
 
-fn main() {
-    struct_with_a_nested_enum_and_vector();
-    enum_with_multiple_missing_variants();
-    enum_struct_variant();
+fn missing_nil() {
+    match ((), false) {
+    //~^ ERROR non-exhaustive patterns: `((), false)` not covered
+        ((), true) => ()
+    }
 }
+
+fn main() {}
diff --git a/src/test/compile-fail/repeat_count.rs b/src/test/compile-fail/repeat_count.rs
index 692c51b5b5f..6d8655fd7d4 100644
--- a/src/test/compile-fail/repeat_count.rs
+++ b/src/test/compile-fail/repeat_count.rs
@@ -1,4 +1,4 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -13,4 +13,10 @@
 fn main() {
     let n = 1;
     let a = [0, ..n]; //~ ERROR expected constant integer for repeat count but found variable
+    let b = [0, ..()]; //~ ERROR expected positive integer for repeat count but found ()
+    let c = [0, ..true]; //~ ERROR expected positive integer for repeat count but found boolean
+    let d = [0, ..0.5]; //~ ERROR expected positive integer for repeat count but found float
+    let e = [0, .."foo"]; //~ ERROR expected positive integer for repeat count but found string
+    let f = [0, ..-4];
+    //~^ ERROR expected positive integer for repeat count but found negative integer
 }
diff --git a/src/test/run-pass/issue-15129.rs b/src/test/run-pass/issue-15129.rs
new file mode 100644
index 00000000000..fcc392e3779
--- /dev/null
+++ b/src/test/run-pass/issue-15129.rs
@@ -0,0 +1,33 @@
+// Copyright 2014 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.
+
+pub enum T {
+    T1(()),
+    T2(())
+}
+
+pub enum V {
+    V1(int),
+    V2(bool)
+}
+
+fn foo(x: (T, V)) -> String {
+    match x {
+        (T1(()), V1(i))  => format!("T1(()), V1({})", i),
+        (T2(()), V2(b))  => format!("T2(()), V2({})", b),
+        _ => String::new()
+    }
+}
+
+
+fn main() {
+    assert_eq!(foo((T1(()), V1(99))), "T1(()), V1(99)".to_string());
+    assert_eq!(foo((T2(()), V2(true))), "T2(()), V2(true)".to_string());
+}