about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-04-30 17:39:36 -0700
committerbors <bors@rust-lang.org>2013-04-30 17:39:36 -0700
commit7a857673ff76c966ceb061e3794b119e2e498c40 (patch)
treefc892d62bbdcf12076f7c30e8a3c5e50e9979741
parent9329bd669d704fffeed90c1f6703518345e6c2fd (diff)
parent4493cf49cdaeb7aea974b9155a678fb8c9e3e390 (diff)
downloadrust-7a857673ff76c966ceb061e3794b119e2e498c40.tar.gz
rust-7a857673ff76c966ceb061e3794b119e2e498c40.zip
auto merge of #6103 : catamorphism/rust/nonfatal-errors, r=catamorphism
r? @nikomatsakis typeck::check::_match wasn't suppressing derived errors properly.
Fixed it. (This will fix #5100)
-rw-r--r--src/librustc/middle/typeck/check/_match.rs174
-rw-r--r--src/librustc/middle/typeck/infer/mod.rs25
-rw-r--r--src/test/compile-fail/alt-vec-mismatch-2.rs2
-rw-r--r--src/test/compile-fail/alt-vec-mismatch.rs2
-rw-r--r--src/test/compile-fail/issue-5100.rs44
5 files changed, 166 insertions, 81 deletions
diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs
index 7f0066a1aa2..5ff71057121 100644
--- a/src/librustc/middle/typeck/check/_match.rs
+++ b/src/librustc/middle/typeck/check/_match.rs
@@ -175,11 +175,18 @@ pub fn check_pat_variant(pcx: &pat_ctxt, pat: @ast::pat, path: @ast::Path,
             kind_name = "structure";
         }
         _ => {
-            tcx.sess.span_fatal(
-                pat.span,
-                fmt!("mismatched types: expected `%s` but found enum or \
-                      structure",
-                     fcx.infcx().ty_to_str(expected)));
+            let resolved_expected =
+                fcx.infcx().ty_to_str(fcx.infcx().resolve_type_vars_if_possible(expected));
+            fcx.infcx().type_error_message_str(pat.span,
+                                               |actual| {
+                    fmt!("mismatched types: expected `%s` but found %s",
+                         resolved_expected, actual)},
+                    ~"an enum or structure pattern",
+                    None);
+            fcx.write_error(pat.id);
+            kind_name = "[error]";
+            arg_types = (copy subpats).get_or_default(~[]).map(|_|
+                                                               ty::mk_err());
         }
     }
 
@@ -486,74 +493,44 @@ pub fn check_pat(pcx: &pat_ctxt, pat: @ast::pat, expected: ty::t) {
       }
       ast::pat_tup(ref elts) => {
         let s = structure_of(fcx, pat.span, expected);
-        let ex_elts = match s {
-          ty::ty_tup(ref elts) => elts,
-          _ => {
-            tcx.sess.span_fatal
-                (pat.span,
-                 fmt!("mismatched types: expected `%s`, found tuple",
-                      fcx.infcx().ty_to_str(expected)));
-          }
-        };
         let e_count = elts.len();
-        if e_count != ex_elts.len() {
-            tcx.sess.span_fatal
-                (pat.span, fmt!("mismatched types: expected a tuple \
-                      with %u fields, found one with %u \
-                      fields", ex_elts.len(), e_count));
-        }
-        let mut i = 0u;
-        for elts.each |elt| {
-            check_pat(pcx, *elt, ex_elts[i]);
-            i += 1u;
+        match s {
+            ty::ty_tup(ref ex_elts) if e_count == ex_elts.len() => {
+                for elts.eachi |i, elt| {
+                    check_pat(pcx, *elt, ex_elts[i]);
+                }
+                fcx.write_ty(pat.id, expected);
+            }
+            _ => {
+                for elts.each |elt| {
+                    check_pat(pcx, *elt, ty::mk_err());
+                }
+                let actual = ty::mk_tup(tcx, elts.map(|pat_var| {
+                    fcx.node_ty(pat_var.id)
+                }));
+                // use terr_tuple_size if both types are tuples
+                let type_error = match s {
+                    ty::ty_tup(ref ex_elts) =>
+                        ty::terr_tuple_size(ty::expected_found{expected: ex_elts.len(),
+                                                           found: e_count}),
+                    _ => ty::terr_mismatch
+                };
+                fcx.infcx().report_mismatched_types(pat.span,
+                                                    expected,
+                                                    actual,
+                                                    &type_error);
+                fcx.write_error(pat.id);
+            }
         }
-
-        fcx.write_ty(pat.id, expected);
       }
       ast::pat_box(inner) => {
-        match structure_of(fcx, pat.span, expected) {
-          ty::ty_box(e_inner) => {
-            check_pat(pcx, inner, e_inner.ty);
-            fcx.write_ty(pat.id, expected);
-          }
-          _ => {
-            tcx.sess.span_fatal(
-                pat.span,
-                ~"mismatched types: expected `" +
-                fcx.infcx().ty_to_str(expected) +
-                ~"` found box");
-          }
-        }
+          check_pointer_pat(pcx, Managed, inner, pat.id, pat.span, expected);
       }
       ast::pat_uniq(inner) => {
-        match structure_of(fcx, pat.span, expected) {
-          ty::ty_uniq(e_inner) => {
-            check_pat(pcx, inner, e_inner.ty);
-            fcx.write_ty(pat.id, expected);
-          }
-          _ => {
-            tcx.sess.span_fatal(
-                pat.span,
-                ~"mismatched types: expected `" +
-                fcx.infcx().ty_to_str(expected) +
-                ~"` found uniq");
-          }
-        }
+          check_pointer_pat(pcx, Owned, inner, pat.id, pat.span, expected);
       }
       ast::pat_region(inner) => {
-        match structure_of(fcx, pat.span, expected) {
-          ty::ty_rptr(_, e_inner) => {
-            check_pat(pcx, inner, e_inner.ty);
-            fcx.write_ty(pat.id, expected);
-          }
-          _ => {
-            tcx.sess.span_fatal(
-                pat.span,
-                ~"mismatched types: expected `" +
-                fcx.infcx().ty_to_str(expected) +
-                ~"` found borrowed pointer");
-          }
-        }
+          check_pointer_pat(pcx, Borrowed, inner, pat.id, pat.span, expected);
       }
       ast::pat_vec(ref before, slice, ref after) => {
         let default_region_var =
@@ -577,11 +554,25 @@ pub fn check_pat(pcx: &pat_ctxt, pat: @ast::pat, expected: ty::t) {
             (mt, default_region_var)
           },
           _ => {
-            tcx.sess.span_fatal(
-                pat.span,
-                fmt!("mismatched type: expected `%s` but found vector",
-                     fcx.infcx().ty_to_str(expected))
-            );
+              for before.each |&elt| {
+                  check_pat(pcx, elt, ty::mk_err());
+              }
+              for slice.each |&elt| {
+                  check_pat(pcx, elt, ty::mk_err());
+              }
+              for after.each |&elt| {
+                  check_pat(pcx, elt, ty::mk_err());
+              }
+              let resolved_expected =
+                  fcx.infcx().ty_to_str(fcx.infcx().resolve_type_vars_if_possible(expected));
+              fcx.infcx().type_error_message_str(pat.span,
+                  |actual| {
+                      fmt!("mismatched types: expected `%s` but found %s",
+                           resolved_expected, actual)},
+                                                 ~"a vector pattern",
+                                                 None);
+              fcx.write_error(pat.id);
+              return;
           }
         };
         for before.each |elt| {
@@ -605,3 +596,46 @@ pub fn check_pat(pcx: &pat_ctxt, pat: @ast::pat, expected: ty::t) {
     }
 }
 
+// Helper function to check @, ~ and & patterns
+pub fn check_pointer_pat(pcx: &pat_ctxt,
+                         pointer_kind: PointerKind,
+                         inner: @ast::pat,
+                         pat_id: ast::node_id,
+                         span: span,
+                         expected: ty::t) {
+    let fcx = pcx.fcx;
+    let check_inner: &fn(ty::mt) = |e_inner| {
+        check_pat(pcx, inner, e_inner.ty);
+        fcx.write_ty(pat_id, expected);
+    };
+    match structure_of(fcx, span, expected) {
+        ty::ty_box(e_inner) if pointer_kind == Managed => {
+            check_inner(e_inner);
+        }
+        ty::ty_uniq(e_inner) if pointer_kind == Owned => {
+            check_inner(e_inner);
+        }
+        ty::ty_rptr(_, e_inner) if pointer_kind == Borrowed => {
+            check_inner(e_inner);
+        }
+        _ => {
+            check_pat(pcx, inner, ty::mk_err());
+            let resolved_expected =
+                fcx.infcx().ty_to_str(fcx.infcx().resolve_type_vars_if_possible(expected));
+            fcx.infcx().type_error_message_str(span, |actual| {
+                    fmt!("mismatched types: expected `%s` but found %s",
+                         resolved_expected, actual)},
+                                               fmt!("%s pattern", match pointer_kind {
+                                                   Managed => "an @-box",
+                                                   Owned => "a ~-box",
+                                                   Borrowed => "an &-pointer"
+                                               }),
+                    None);
+            fcx.write_error(pat_id);
+          }
+    }
+}
+
+#[deriving(Eq)]
+enum PointerKind { Managed, Owned, Borrowed }
+
diff --git a/src/librustc/middle/typeck/infer/mod.rs b/src/librustc/middle/typeck/infer/mod.rs
index 7b5a93d4cad..8f709e7cd5a 100644
--- a/src/librustc/middle/typeck/infer/mod.rs
+++ b/src/librustc/middle/typeck/infer/mod.rs
@@ -749,25 +749,32 @@ pub impl InferCtxt {
         }
     }
 
-    fn type_error_message(@mut self, sp: span, mk_msg: &fn(~str) -> ~str,
-                          actual_ty: ty::t, err: Option<&ty::type_err>) {
-        let actual_ty = self.resolve_type_vars_if_possible(actual_ty);
 
-        // Don't report an error if actual type is ty_err.
-        if ty::type_is_error(actual_ty) {
-            return;
-        }
+    fn type_error_message_str(@mut self, sp: span, mk_msg: &fn(~str) -> ~str,
+                          actual_ty: ~str, err: Option<&ty::type_err>) {
         let error_str = err.map_default(~"", |t_err|
                          fmt!(" (%s)",
                               ty::type_err_to_str(self.tcx, *t_err)));
         self.tcx.sess.span_err(sp,
-           fmt!("%s%s", mk_msg(self.ty_to_str(actual_ty)),
-                error_str));
+           fmt!("%s%s", mk_msg(actual_ty), error_str));
         for err.each |err| {
             ty::note_and_explain_type_err(self.tcx, *err)
         }
     }
 
+    fn type_error_message(@mut self, sp: span, mk_msg: &fn(~str) -> ~str,
+                          actual_ty: ty::t, err: Option<&ty::type_err>) {
+        let actual_ty = self.resolve_type_vars_if_possible(actual_ty);
+
+        // Don't report an error if actual type is ty_err.
+        if ty::type_is_error(actual_ty) {
+            return;
+        }
+
+        self.type_error_message_str(sp, mk_msg, self.ty_to_str(actual_ty),
+                                    err);
+    }
+
     fn report_mismatched_types(@mut self, sp: span, e: ty::t, a: ty::t,
                                err: &ty::type_err) {
         let resolved_expected =
diff --git a/src/test/compile-fail/alt-vec-mismatch-2.rs b/src/test/compile-fail/alt-vec-mismatch-2.rs
index 9e8fb84951d..6ea0300cf1e 100644
--- a/src/test/compile-fail/alt-vec-mismatch-2.rs
+++ b/src/test/compile-fail/alt-vec-mismatch-2.rs
@@ -1,5 +1,5 @@
 fn main() {
     match () {
-        [()] => { } //~ ERROR mismatched type: expected `()` but found vector
+        [()] => { } //~ ERROR mismatched types: expected `()` but found a vector pattern
     }
 }
diff --git a/src/test/compile-fail/alt-vec-mismatch.rs b/src/test/compile-fail/alt-vec-mismatch.rs
index ef4d92ea491..85ed8761ee9 100644
--- a/src/test/compile-fail/alt-vec-mismatch.rs
+++ b/src/test/compile-fail/alt-vec-mismatch.rs
@@ -1,6 +1,6 @@
 fn main() {
     match ~"foo" {
-        ['f', 'o', .._] => { } //~ ERROR mismatched type: expected `~str` but found vector
+        ['f', 'o', .._] => { } //~ ERROR mismatched types: expected `~str` but found a vector pattern
         _ => { }
     }
 }
diff --git a/src/test/compile-fail/issue-5100.rs b/src/test/compile-fail/issue-5100.rs
new file mode 100644
index 00000000000..dbfdb38f721
--- /dev/null
+++ b/src/test/compile-fail/issue-5100.rs
@@ -0,0 +1,44 @@
+// Copyright 2013 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.
+
+enum A { B, C }
+
+fn main() {
+    match (true, false) {
+        B => (), //~ ERROR expected `(bool,bool)` but found an enum or structure pattern
+        _ => ()
+    }
+
+    match (true, false) {
+        (true, false, false) => () //~ ERROR mismatched types: expected `(bool,bool)` but found `(bool,bool,bool)` (expected a tuple with 2 elements but found one with 3 elements)
+    }
+
+    match (true, false) {
+        @(true, false) => () //~ ERROR mismatched types: expected `(bool,bool)` but found an @-box pattern
+    }
+
+    match (true, false) {
+        ~(true, false) => () //~ ERROR mismatched types: expected `(bool,bool)` but found a ~-box pattern
+    }
+
+    match (true, false) {
+        &(true, false) => () //~ ERROR mismatched types: expected `(bool,bool)` but found an &-pointer pattern
+    }
+
+
+    let v = [('a', 'b')   //~ ERROR expected function but found `(char,char)`
+             ('c', 'd'),
+             ('e', 'f')];
+
+    for v.each |&(x,y)| {} // should be OK
+
+    // Make sure none of the errors above were fatal
+    let x: char = true; //~ ERROR expected `char` but found `bool`
+}