diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs index 40c5df7b76832..e27c2ff97dbd2 100644 --- a/src/librustc/middle/typeck/check/_match.rs +++ b/src/librustc/middle/typeck/check/_match.rs @@ -146,13 +146,12 @@ pub fn check_pat_variant(pcx: &pat_ctxt, pat: @ast::pat, path: @ast::Path, kind_name = "variant"; } None => { - 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| { + fcx.infcx().type_error_message_str_with_expected(pat.span, + |expected, actual| { + expected.map_default(~"", |&e| { fmt!("mismatched types: expected `%s` but found %s", - resolved_expected, actual)}, - ~"a structure pattern", + e, actual)})}, + Some(expected), ~"a structure pattern", None); fcx.write_error(pat.id); kind_name = "[error]"; @@ -189,13 +188,12 @@ pub fn check_pat_variant(pcx: &pat_ctxt, pat: @ast::pat, path: @ast::Path, kind_name = "structure"; } _ => { - 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| { + fcx.infcx().type_error_message_str_with_expected(pat.span, + |expected, actual| { + expected.map_default(~"", |&e| { fmt!("mismatched types: expected `%s` but found %s", - resolved_expected, actual)}, - ~"an enum or structure pattern", + e, actual)})}, + Some(expected), ~"an enum or structure pattern", None); fcx.write_error(pat.id); kind_name = "[error]"; @@ -514,9 +512,6 @@ pub fn check_pat(pcx: &pat_ctxt, pat: @ast::pat, expected: ty::t) { 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) => @@ -524,10 +519,10 @@ pub fn check_pat(pcx: &pat_ctxt, pat: @ast::pat, expected: ty::t) { found: e_count}), _ => ty::terr_mismatch }; - fcx.infcx().report_mismatched_types(pat.span, - expected, - actual, - &type_error); + fcx.infcx().type_error_message_str_with_expected(pat.span, |expected, actual| { + expected.map_default(~"", |&e| { + fmt!("mismatched types: expected `%s` but found %s", + e, actual)})}, Some(expected), ~"tuple", Some(&type_error)); fcx.write_error(pat.id); } } @@ -572,14 +567,15 @@ pub fn check_pat(pcx: &pat_ctxt, pat: @ast::pat, expected: ty::t) { 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.infcx().type_error_message_str_with_expected( + pat.span, + |expected, actual| { + expected.map_default(~"", |&e| { + fmt!("mismatched types: expected `%s` but found %s", + e, actual)})}, + Some(expected), + ~"a vector pattern", + None); fcx.write_error(pat.id); return; } @@ -629,17 +625,19 @@ pub fn check_pointer_pat(pcx: &pat_ctxt, } _ => { 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.infcx().type_error_message_str_with_expected( + span, + |expected, actual| { + expected.map_default(~"", |&e| { + fmt!("mismatched types: expected `%s` but found %s", + e, actual)})}, + Some(expected), + fmt!("%s pattern", match pointer_kind { + Managed => "an @-box", + Owned => "a ~-box", + Borrowed => "an &-pointer" + }), + None); fcx.write_error(pat_id); } } diff --git a/src/librustc/middle/typeck/infer/mod.rs b/src/librustc/middle/typeck/infer/mod.rs index 2e784b11c357b..2c42914f4b551 100644 --- a/src/librustc/middle/typeck/infer/mod.rs +++ b/src/librustc/middle/typeck/infer/mod.rs @@ -728,21 +728,45 @@ pub impl InferCtxt { } } + fn type_error_message_str(@mut self, + sp: span, + mk_msg: &fn(Option<~str>, ~str) -> ~str, + actual_ty: ~str, err: Option<&ty::type_err>) { + self.type_error_message_str_with_expected(sp, mk_msg, None, actual_ty, err) + } + + fn type_error_message_str_with_expected(@mut self, + sp: span, + mk_msg: &fn(Option<~str>, ~str) -> ~str, + expected_ty: Option, actual_ty: ~str, + err: Option<&ty::type_err>) { + debug!("hi! expected_ty = %?, actual_ty = %s", expected_ty, actual_ty); - 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(actual_ty), error_str)); - for err.each |err| { - ty::note_and_explain_type_err(self.tcx, *err) + let resolved_expected = expected_ty.map(|&e_ty| + { self.resolve_type_vars_if_possible(e_ty) }); + if !resolved_expected.map_default(false, |&e| { ty::type_is_error(e) }) { + match resolved_expected { + None => self.tcx.sess.span_err(sp, + fmt!("%s%s", mk_msg(None, actual_ty), error_str)), + Some(e) => { + self.tcx.sess.span_err(sp, + fmt!("%s%s", mk_msg(Some(self.ty_to_str(e)), 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>) { + 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. @@ -750,8 +774,7 @@ pub impl InferCtxt { return; } - self.type_error_message_str(sp, mk_msg, self.ty_to_str(actual_ty), - err); + self.type_error_message_str(sp, |_e, a| { mk_msg(a) }, self.ty_to_str(actual_ty), err); } fn report_mismatched_types(@mut self, sp: span, e: ty::t, a: ty::t, diff --git a/src/test/compile-fail/issue-5100.rs b/src/test/compile-fail/issue-5100.rs index dbfdb38f7211f..8cc047230dc97 100644 --- a/src/test/compile-fail/issue-5100.rs +++ b/src/test/compile-fail/issue-5100.rs @@ -17,7 +17,7 @@ fn main() { } 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) + (true, false, false) => () //~ ERROR mismatched types: expected `(bool,bool)` but found tuple (expected a tuple with 2 elements but found one with 3 elements) } match (true, false) { diff --git a/src/test/compile-fail/suppressed-error.rs b/src/test/compile-fail/suppressed-error.rs new file mode 100644 index 0000000000000..b4a72548cfc0d --- /dev/null +++ b/src/test/compile-fail/suppressed-error.rs @@ -0,0 +1,14 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let (x, y) = (); //~ ERROR expected `()` but found tuple (types differ) + return x; +} \ No newline at end of file