Skip to content

Commit 7a85767

Browse files
committed
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)
2 parents 9329bd6 + 4493cf4 commit 7a85767

File tree

5 files changed

+166
-81
lines changed

5 files changed

+166
-81
lines changed

src/librustc/middle/typeck/check/_match.rs

+104-70
Original file line numberDiff line numberDiff line change
@@ -175,11 +175,18 @@ pub fn check_pat_variant(pcx: &pat_ctxt, pat: @ast::pat, path: @ast::Path,
175175
kind_name = "structure";
176176
}
177177
_ => {
178-
tcx.sess.span_fatal(
179-
pat.span,
180-
fmt!("mismatched types: expected `%s` but found enum or \
181-
structure",
182-
fcx.infcx().ty_to_str(expected)));
178+
let resolved_expected =
179+
fcx.infcx().ty_to_str(fcx.infcx().resolve_type_vars_if_possible(expected));
180+
fcx.infcx().type_error_message_str(pat.span,
181+
|actual| {
182+
fmt!("mismatched types: expected `%s` but found %s",
183+
resolved_expected, actual)},
184+
~"an enum or structure pattern",
185+
None);
186+
fcx.write_error(pat.id);
187+
kind_name = "[error]";
188+
arg_types = (copy subpats).get_or_default(~[]).map(|_|
189+
ty::mk_err());
183190
}
184191
}
185192

@@ -486,74 +493,44 @@ pub fn check_pat(pcx: &pat_ctxt, pat: @ast::pat, expected: ty::t) {
486493
}
487494
ast::pat_tup(ref elts) => {
488495
let s = structure_of(fcx, pat.span, expected);
489-
let ex_elts = match s {
490-
ty::ty_tup(ref elts) => elts,
491-
_ => {
492-
tcx.sess.span_fatal
493-
(pat.span,
494-
fmt!("mismatched types: expected `%s`, found tuple",
495-
fcx.infcx().ty_to_str(expected)));
496-
}
497-
};
498496
let e_count = elts.len();
499-
if e_count != ex_elts.len() {
500-
tcx.sess.span_fatal
501-
(pat.span, fmt!("mismatched types: expected a tuple \
502-
with %u fields, found one with %u \
503-
fields", ex_elts.len(), e_count));
504-
}
505-
let mut i = 0u;
506-
for elts.each |elt| {
507-
check_pat(pcx, *elt, ex_elts[i]);
508-
i += 1u;
497+
match s {
498+
ty::ty_tup(ref ex_elts) if e_count == ex_elts.len() => {
499+
for elts.eachi |i, elt| {
500+
check_pat(pcx, *elt, ex_elts[i]);
501+
}
502+
fcx.write_ty(pat.id, expected);
503+
}
504+
_ => {
505+
for elts.each |elt| {
506+
check_pat(pcx, *elt, ty::mk_err());
507+
}
508+
let actual = ty::mk_tup(tcx, elts.map(|pat_var| {
509+
fcx.node_ty(pat_var.id)
510+
}));
511+
// use terr_tuple_size if both types are tuples
512+
let type_error = match s {
513+
ty::ty_tup(ref ex_elts) =>
514+
ty::terr_tuple_size(ty::expected_found{expected: ex_elts.len(),
515+
found: e_count}),
516+
_ => ty::terr_mismatch
517+
};
518+
fcx.infcx().report_mismatched_types(pat.span,
519+
expected,
520+
actual,
521+
&type_error);
522+
fcx.write_error(pat.id);
523+
}
509524
}
510-
511-
fcx.write_ty(pat.id, expected);
512525
}
513526
ast::pat_box(inner) => {
514-
match structure_of(fcx, pat.span, expected) {
515-
ty::ty_box(e_inner) => {
516-
check_pat(pcx, inner, e_inner.ty);
517-
fcx.write_ty(pat.id, expected);
518-
}
519-
_ => {
520-
tcx.sess.span_fatal(
521-
pat.span,
522-
~"mismatched types: expected `" +
523-
fcx.infcx().ty_to_str(expected) +
524-
~"` found box");
525-
}
526-
}
527+
check_pointer_pat(pcx, Managed, inner, pat.id, pat.span, expected);
527528
}
528529
ast::pat_uniq(inner) => {
529-
match structure_of(fcx, pat.span, expected) {
530-
ty::ty_uniq(e_inner) => {
531-
check_pat(pcx, inner, e_inner.ty);
532-
fcx.write_ty(pat.id, expected);
533-
}
534-
_ => {
535-
tcx.sess.span_fatal(
536-
pat.span,
537-
~"mismatched types: expected `" +
538-
fcx.infcx().ty_to_str(expected) +
539-
~"` found uniq");
540-
}
541-
}
530+
check_pointer_pat(pcx, Owned, inner, pat.id, pat.span, expected);
542531
}
543532
ast::pat_region(inner) => {
544-
match structure_of(fcx, pat.span, expected) {
545-
ty::ty_rptr(_, e_inner) => {
546-
check_pat(pcx, inner, e_inner.ty);
547-
fcx.write_ty(pat.id, expected);
548-
}
549-
_ => {
550-
tcx.sess.span_fatal(
551-
pat.span,
552-
~"mismatched types: expected `" +
553-
fcx.infcx().ty_to_str(expected) +
554-
~"` found borrowed pointer");
555-
}
556-
}
533+
check_pointer_pat(pcx, Borrowed, inner, pat.id, pat.span, expected);
557534
}
558535
ast::pat_vec(ref before, slice, ref after) => {
559536
let default_region_var =
@@ -577,11 +554,25 @@ pub fn check_pat(pcx: &pat_ctxt, pat: @ast::pat, expected: ty::t) {
577554
(mt, default_region_var)
578555
},
579556
_ => {
580-
tcx.sess.span_fatal(
581-
pat.span,
582-
fmt!("mismatched type: expected `%s` but found vector",
583-
fcx.infcx().ty_to_str(expected))
584-
);
557+
for before.each |&elt| {
558+
check_pat(pcx, elt, ty::mk_err());
559+
}
560+
for slice.each |&elt| {
561+
check_pat(pcx, elt, ty::mk_err());
562+
}
563+
for after.each |&elt| {
564+
check_pat(pcx, elt, ty::mk_err());
565+
}
566+
let resolved_expected =
567+
fcx.infcx().ty_to_str(fcx.infcx().resolve_type_vars_if_possible(expected));
568+
fcx.infcx().type_error_message_str(pat.span,
569+
|actual| {
570+
fmt!("mismatched types: expected `%s` but found %s",
571+
resolved_expected, actual)},
572+
~"a vector pattern",
573+
None);
574+
fcx.write_error(pat.id);
575+
return;
585576
}
586577
};
587578
for before.each |elt| {
@@ -605,3 +596,46 @@ pub fn check_pat(pcx: &pat_ctxt, pat: @ast::pat, expected: ty::t) {
605596
}
606597
}
607598
599+
// Helper function to check @, ~ and & patterns
600+
pub fn check_pointer_pat(pcx: &pat_ctxt,
601+
pointer_kind: PointerKind,
602+
inner: @ast::pat,
603+
pat_id: ast::node_id,
604+
span: span,
605+
expected: ty::t) {
606+
let fcx = pcx.fcx;
607+
let check_inner: &fn(ty::mt) = |e_inner| {
608+
check_pat(pcx, inner, e_inner.ty);
609+
fcx.write_ty(pat_id, expected);
610+
};
611+
match structure_of(fcx, span, expected) {
612+
ty::ty_box(e_inner) if pointer_kind == Managed => {
613+
check_inner(e_inner);
614+
}
615+
ty::ty_uniq(e_inner) if pointer_kind == Owned => {
616+
check_inner(e_inner);
617+
}
618+
ty::ty_rptr(_, e_inner) if pointer_kind == Borrowed => {
619+
check_inner(e_inner);
620+
}
621+
_ => {
622+
check_pat(pcx, inner, ty::mk_err());
623+
let resolved_expected =
624+
fcx.infcx().ty_to_str(fcx.infcx().resolve_type_vars_if_possible(expected));
625+
fcx.infcx().type_error_message_str(span, |actual| {
626+
fmt!("mismatched types: expected `%s` but found %s",
627+
resolved_expected, actual)},
628+
fmt!("%s pattern", match pointer_kind {
629+
Managed => "an @-box",
630+
Owned => "a ~-box",
631+
Borrowed => "an &-pointer"
632+
}),
633+
None);
634+
fcx.write_error(pat_id);
635+
}
636+
}
637+
}
638+
639+
#[deriving(Eq)]
640+
enum PointerKind { Managed, Owned, Borrowed }
641+

src/librustc/middle/typeck/infer/mod.rs

+16-9
Original file line numberDiff line numberDiff line change
@@ -749,25 +749,32 @@ pub impl InferCtxt {
749749
}
750750
}
751751

752-
fn type_error_message(@mut self, sp: span, mk_msg: &fn(~str) -> ~str,
753-
actual_ty: ty::t, err: Option<&ty::type_err>) {
754-
let actual_ty = self.resolve_type_vars_if_possible(actual_ty);
755752

756-
// Don't report an error if actual type is ty_err.
757-
if ty::type_is_error(actual_ty) {
758-
return;
759-
}
753+
fn type_error_message_str(@mut self, sp: span, mk_msg: &fn(~str) -> ~str,
754+
actual_ty: ~str, err: Option<&ty::type_err>) {
760755
let error_str = err.map_default(~"", |t_err|
761756
fmt!(" (%s)",
762757
ty::type_err_to_str(self.tcx, *t_err)));
763758
self.tcx.sess.span_err(sp,
764-
fmt!("%s%s", mk_msg(self.ty_to_str(actual_ty)),
765-
error_str));
759+
fmt!("%s%s", mk_msg(actual_ty), error_str));
766760
for err.each |err| {
767761
ty::note_and_explain_type_err(self.tcx, *err)
768762
}
769763
}
770764

765+
fn type_error_message(@mut self, sp: span, mk_msg: &fn(~str) -> ~str,
766+
actual_ty: ty::t, err: Option<&ty::type_err>) {
767+
let actual_ty = self.resolve_type_vars_if_possible(actual_ty);
768+
769+
// Don't report an error if actual type is ty_err.
770+
if ty::type_is_error(actual_ty) {
771+
return;
772+
}
773+
774+
self.type_error_message_str(sp, mk_msg, self.ty_to_str(actual_ty),
775+
err);
776+
}
777+
771778
fn report_mismatched_types(@mut self, sp: span, e: ty::t, a: ty::t,
772779
err: &ty::type_err) {
773780
let resolved_expected =
+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
fn main() {
22
match () {
3-
[()] => { } //~ ERROR mismatched type: expected `()` but found vector
3+
[()] => { } //~ ERROR mismatched types: expected `()` but found a vector pattern
44
}
55
}
+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
fn main() {
22
match ~"foo" {
3-
['f', 'o', .._] => { } //~ ERROR mismatched type: expected `~str` but found vector
3+
['f', 'o', .._] => { } //~ ERROR mismatched types: expected `~str` but found a vector pattern
44
_ => { }
55
}
66
}

src/test/compile-fail/issue-5100.rs

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
enum A { B, C }
12+
13+
fn main() {
14+
match (true, false) {
15+
B => (), //~ ERROR expected `(bool,bool)` but found an enum or structure pattern
16+
_ => ()
17+
}
18+
19+
match (true, false) {
20+
(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)
21+
}
22+
23+
match (true, false) {
24+
@(true, false) => () //~ ERROR mismatched types: expected `(bool,bool)` but found an @-box pattern
25+
}
26+
27+
match (true, false) {
28+
~(true, false) => () //~ ERROR mismatched types: expected `(bool,bool)` but found a ~-box pattern
29+
}
30+
31+
match (true, false) {
32+
&(true, false) => () //~ ERROR mismatched types: expected `(bool,bool)` but found an &-pointer pattern
33+
}
34+
35+
36+
let v = [('a', 'b') //~ ERROR expected function but found `(char,char)`
37+
('c', 'd'),
38+
('e', 'f')];
39+
40+
for v.each |&(x,y)| {} // should be OK
41+
42+
// Make sure none of the errors above were fatal
43+
let x: char = true; //~ ERROR expected `char` but found `bool`
44+
}

0 commit comments

Comments
 (0)