rustc: Suppress derived pattern-match-checking errors
typeck::check::_match wasn't suppressing derived errors properly. Fixed it.
This commit is contained in:
parent
9f03d45c56
commit
edc11a9f09
3 changed files with 164 additions and 79 deletions
|
@ -175,11 +175,18 @@ pub fn check_pat_variant(pcx: &pat_ctxt, pat: @ast::pat, path: @ast::Path,
|
||||||
kind_name = "structure";
|
kind_name = "structure";
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
tcx.sess.span_fatal(
|
let resolved_expected =
|
||||||
pat.span,
|
fcx.infcx().ty_to_str(fcx.infcx().resolve_type_vars_if_possible(expected));
|
||||||
fmt!("mismatched types: expected `%s` but found enum or \
|
fcx.infcx().type_error_message_str(pat.span,
|
||||||
structure",
|
|actual| {
|
||||||
fcx.infcx().ty_to_str(expected)));
|
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) => {
|
ast::pat_tup(ref elts) => {
|
||||||
let s = structure_of(fcx, pat.span, expected);
|
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();
|
let e_count = elts.len();
|
||||||
if e_count != ex_elts.len() {
|
match s {
|
||||||
tcx.sess.span_fatal
|
ty::ty_tup(ref ex_elts) if e_count == ex_elts.len() => {
|
||||||
(pat.span, fmt!("mismatched types: expected a tuple \
|
for elts.eachi |i, elt| {
|
||||||
with %u fields, found one with %u \
|
check_pat(pcx, *elt, ex_elts[i]);
|
||||||
fields", ex_elts.len(), e_count));
|
}
|
||||||
|
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) => {
|
ast::pat_box(inner) => {
|
||||||
match structure_of(fcx, pat.span, expected) {
|
check_pointer_pat(pcx, At, inner, pat.id, 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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ast::pat_uniq(inner) => {
|
ast::pat_uniq(inner) => {
|
||||||
match structure_of(fcx, pat.span, expected) {
|
check_pointer_pat(pcx, Uniq, inner, pat.id, 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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ast::pat_region(inner) => {
|
ast::pat_region(inner) => {
|
||||||
match structure_of(fcx, pat.span, expected) {
|
check_pointer_pat(pcx, Borrowed, inner, pat.id, 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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ast::pat_vec(ref before, slice, ref after) => {
|
ast::pat_vec(ref before, slice, ref after) => {
|
||||||
let default_region_var =
|
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)
|
(mt, default_region_var)
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
tcx.sess.span_fatal(
|
for before.each |&elt| {
|
||||||
pat.span,
|
check_pat(pcx, elt, ty::mk_err());
|
||||||
fmt!("mismatched type: expected `%s` but found vector",
|
}
|
||||||
fcx.infcx().ty_to_str(expected))
|
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| {
|
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 == At => {
|
||||||
|
check_inner(e_inner);
|
||||||
|
}
|
||||||
|
ty::ty_uniq(e_inner) if pointer_kind == Uniq => {
|
||||||
|
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!("an %s pattern", match pointer_kind {
|
||||||
|
At => "@-box",
|
||||||
|
Uniq => "~-box",
|
||||||
|
Borrowed => "&-pointer"
|
||||||
|
}),
|
||||||
|
None);
|
||||||
|
fcx.write_error(pat_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[deriving(Eq)]
|
||||||
|
enum PointerKind { At, Uniq, Borrowed }
|
||||||
|
|
||||||
|
|
|
@ -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,
|
fn type_error_message(@mut self, sp: span, mk_msg: &fn(~str) -> ~str,
|
||||||
actual_ty: ty::t, err: Option<&ty::type_err>) {
|
actual_ty: ty::t, err: Option<&ty::type_err>) {
|
||||||
let actual_ty = self.resolve_type_vars_if_possible(actual_ty);
|
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) {
|
if ty::type_is_error(actual_ty) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let error_str = err.map_default(~"", |t_err|
|
|
||||||
fmt!(" (%s)",
|
self.type_error_message_str(sp, mk_msg, self.ty_to_str(actual_ty),
|
||||||
ty::type_err_to_str(self.tcx, *t_err)));
|
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn report_mismatched_types(@mut self, sp: span, e: ty::t, a: ty::t,
|
fn report_mismatched_types(@mut self, sp: span, e: ty::t, a: ty::t,
|
||||||
|
|
44
src/test/compile-fail/issue-5100.rs
Normal file
44
src/test/compile-fail/issue-5100.rs
Normal 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`
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue