Skip to content

Commit

Permalink
rustc: Don't call type_error_message() with ty_err as the expected type
Browse files Browse the repository at this point in the history
In #6319, several people mentioned they ran into a "computing
fictitious type" ICE in trans. This turns out to be because some
of my recent changes to typeck::check::_match resulted in type errors
getting reported with ty_err as the expected type, which meant the errors
were suppressed, and typechecking incorrectly succeeded (since the errors
weren't recorded).

Changed the error messages in these cases not to use an expected type at all,
rather, printing out a string describing the type that was expected (which is
what the code originally did). The result is a bit repetitive and the
proliferation of error-reporting functions in typeck::infer is a bit annoying,
but I thought it was important to fix this now; more cleanup can happen later.
  • Loading branch information
catamorphism committed May 12, 2013
1 parent d546493 commit cdb52c0
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 49 deletions.
74 changes: 36 additions & 38 deletions src/librustc/middle/typeck/check/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]";
Expand Down Expand Up @@ -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]";
Expand Down Expand Up @@ -514,20 +512,17 @@ 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) =>
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.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);
}
}
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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);
}
}
Expand Down
43 changes: 33 additions & 10 deletions src/librustc/middle/typeck/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -728,30 +728,53 @@ 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<ty::t>, 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.
if ty::type_is_error(actual_ty) {
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,
Expand Down
2 changes: 1 addition & 1 deletion src/test/compile-fail/issue-5100.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
14 changes: 14 additions & 0 deletions src/test/compile-fail/suppressed-error.rs
Original file line number Diff line number Diff line change
@@ -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 <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.

fn main() {
let (x, y) = (); //~ ERROR expected `()` but found tuple (types differ)
return x;
}

5 comments on commit cdb52c0

@bors
Copy link
Contributor

@bors bors commented on cdb52c0 May 12, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saw approval from nikomatsakis
at catamorphism@cdb52c0

@bors
Copy link
Contributor

@bors bors commented on cdb52c0 May 12, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging catamorphism/rust/issue-6319 = cdb52c0 into auto

@bors
Copy link
Contributor

@bors bors commented on cdb52c0 May 12, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

catamorphism/rust/issue-6319 = cdb52c0 merged ok, testing candidate = 638b394

@bors
Copy link
Contributor

@bors bors commented on cdb52c0 May 12, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bors
Copy link
Contributor

@bors bors commented on cdb52c0 May 12, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fast-forwarding incoming to auto = 638b394

Please sign in to comment.