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)
This commit is contained in:
bors 2013-04-30 17:39:36 -07:00
commit 7a857673ff
5 changed files with 166 additions and 81 deletions

View file

@ -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));
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);
}
}
let mut i = 0u;
for elts.each |elt| {
check_pat(pcx, *elt, ex_elts[i]);
i += 1u;
}
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 }

View file

@ -749,6 +749,19 @@ pub impl InferCtxt {
}
}
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)
}
}
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);
@ -757,15 +770,9 @@ pub impl InferCtxt {
if ty::type_is_error(actual_ty) {
return;
}
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));
for err.each |err| {
ty::note_and_explain_type_err(self.tcx, *err)
}
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,

View file

@ -1,5 +1,5 @@
fn main() {
match () {
[()] => { } //~ ERROR mismatched type: expected `()` but found vector
[()] => { } //~ ERROR mismatched types: expected `()` but found a vector pattern
}
}

View file

@ -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
_ => { }
}
}

View file

@ -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`
}