From cdb52c02015805beac9dc7931880a482409e7162 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Sat, 11 May 2013 17:51:00 -0700 Subject: [PATCH] rustc: Don't call type_error_message() with ty_err as the expected type 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. --- src/librustc/middle/typeck/check/_match.rs | 74 +++++++++++----------- src/librustc/middle/typeck/infer/mod.rs | 43 ++++++++++--- src/test/compile-fail/issue-5100.rs | 2 +- src/test/compile-fail/suppressed-error.rs | 14 ++++ 4 files changed, 84 insertions(+), 49 deletions(-) create mode 100644 src/test/compile-fail/suppressed-error.rs diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs index 40c5df7b768..e27c2ff97db 100644 --- a/src/librustc/middle/typeck/check/_match.rs +++ b/src/librustc/middle/typeck/check/_match.rs @@ -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]"; @@ -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]"; @@ -514,9 +512,6 @@ 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) => @@ -524,10 +519,10 @@ pub fn check_pat(pcx: &pat_ctxt, pat: @ast::pat, expected: ty::t) { 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); } } @@ -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; } @@ -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); } } diff --git a/src/librustc/middle/typeck/infer/mod.rs b/src/librustc/middle/typeck/infer/mod.rs index 2e784b11c35..2c42914f4b5 100644 --- a/src/librustc/middle/typeck/infer/mod.rs +++ b/src/librustc/middle/typeck/infer/mod.rs @@ -728,21 +728,45 @@ 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, 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. @@ -750,8 +774,7 @@ pub impl InferCtxt { 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, diff --git a/src/test/compile-fail/issue-5100.rs b/src/test/compile-fail/issue-5100.rs index dbfdb38f721..8cc047230dc 100644 --- a/src/test/compile-fail/issue-5100.rs +++ b/src/test/compile-fail/issue-5100.rs @@ -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) { diff --git a/src/test/compile-fail/suppressed-error.rs b/src/test/compile-fail/suppressed-error.rs new file mode 100644 index 00000000000..b4a72548cfc --- /dev/null +++ b/src/test/compile-fail/suppressed-error.rs @@ -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 or the MIT license +// , 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; +} \ No newline at end of file