Skip to content

rustc: Suppress derived pattern-match-checking errors #6103

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 104 additions & 70 deletions src/librustc/middle/typeck/check/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
}

Expand Down Expand Up @@ -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 =
Expand All @@ -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| {
Expand All @@ -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 }

25 changes: 16 additions & 9 deletions src/librustc/middle/typeck/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down
2 changes: 1 addition & 1 deletion src/test/compile-fail/alt-vec-mismatch-2.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
fn main() {
match () {
[()] => { } //~ ERROR mismatched type: expected `()` but found vector
[()] => { } //~ ERROR mismatched types: expected `()` but found a vector pattern
}
}
2 changes: 1 addition & 1 deletion src/test/compile-fail/alt-vec-mismatch.rs
Original file line number Diff line number Diff line change
@@ -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
_ => { }
}
}
44 changes: 44 additions & 0 deletions src/test/compile-fail/issue-5100.rs
Original file line number Diff line number Diff line change
@@ -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`
}