From 0c0365d33f2acd067156d366fd4b0c250efe7240 Mon Sep 17 00:00:00 2001 From: Jakub Bukaj Date: Thu, 23 Oct 2014 22:35:19 +0200 Subject: [PATCH 1/7] Improve the readability of diagnostics that involve unresolved type variables Diagnostics such as the following ``` mismatched types: expected `core::result::Result`, found `core::option::Option<>` :6 let a: Result = None; ^~~~ mismatched types: expected `&mut `, found `uint` :7 f(42u); ^~~ ``` tend to be fairly unappealing to new users. While specific type var IDs are valuable in diagnostics that deal with more than one such variable, in practice many messages only mention one. In those cases, leaving out the specific number makes the messages slightly less terrifying. In addition, type variables have been changed to use the type hole syntax `_` in diagnostics. With a variable ID, they're printed as `_#id` (e.g. `_#1`). In cases where the ID is left out, it's simply `_`. Integer and float variables have an additional suffix after the number, e.g. `_#1i` or `_#3f`. --- src/librustc/middle/ty.rs | 27 +-- src/librustc/middle/typeck/infer/combine.rs | 10 + .../middle/typeck/infer/error_reporting.rs | 42 +++- src/librustc/middle/typeck/infer/mod.rs | 65 ++--- src/librustc/util/ppaux.rs | 229 ++++++++++-------- 5 files changed, 210 insertions(+), 163 deletions(-) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index edb67f7fddf8b..3ec1106ff20e0 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -1032,10 +1032,8 @@ pub enum type_err { terr_ref_mutability, terr_vec_mutability, terr_tuple_size(expected_found), + terr_fixed_array_size(expected_found), terr_ty_param_size(expected_found), - terr_record_size(expected_found), - terr_record_mutability, - terr_record_fields(expected_found), terr_arg_count, terr_regions_does_not_outlive(Region, Region), terr_regions_not_same(Region, Region), @@ -3790,8 +3788,8 @@ pub fn ty_sort_string(cx: &ctxt, t: t) -> String { ty_enum(id, _) => format!("enum {}", item_path_str(cx, id)), ty_uniq(_) => "box".to_string(), - ty_vec(_, Some(_)) => "array".to_string(), - ty_vec(_, None) => "unsized array".to_string(), + ty_vec(_, Some(n)) => format!("array of {} elements", n), + ty_vec(_, None) => "slice".to_string(), ty_ptr(_) => "*-ptr".to_string(), ty_rptr(_, _) => "&-ptr".to_string(), ty_bare_fn(_) => "extern fn".to_string(), @@ -3874,27 +3872,18 @@ pub fn type_err_to_str(cx: &ctxt, err: &type_err) -> String { values.expected, values.found) } - terr_tuple_size(values) => { - format!("expected a tuple with {} elements, \ + terr_fixed_array_size(values) => { + format!("expected an array with a fixed size of {} elements, \ found one with {} elements", values.expected, values.found) } - terr_record_size(values) => { - format!("expected a record with {} fields, \ - found one with {} fields", + terr_tuple_size(values) => { + format!("expected a tuple with {} elements, \ + found one with {} elements", values.expected, values.found) } - terr_record_mutability => { - "record elements differ in mutability".to_string() - } - terr_record_fields(values) => { - format!("expected a record with field `{}`, found one \ - with field `{}`", - token::get_ident(values.expected), - token::get_ident(values.found)) - } terr_arg_count => { "incorrect number of function parameters".to_string() } diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs index de9379a3aa763..e51eb331cdc37 100644 --- a/src/librustc/middle/typeck/infer/combine.rs +++ b/src/librustc/middle/typeck/infer/combine.rs @@ -515,6 +515,16 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C, a: ty::t, b: ty::t) -> cres { + this.tys(a_t, b_t).and_then(|t| { + if sz_a == sz_b { + Ok(ty::mk_vec(tcx, t, Some(sz_a))) + } else { + Err(ty::terr_fixed_array_size(expected_found(this, sz_a, sz_b))) + } + }) + } + (&ty::ty_vec(a_t, sz_a), &ty::ty_vec(b_t, sz_b)) => { this.tys(a_t, b_t).and_then(|t| { if sz_a == sz_b { diff --git a/src/librustc/middle/typeck/infer/error_reporting.rs b/src/librustc/middle/typeck/infer/error_reporting.rs index 426c6836778e2..0f000e93fc01a 100644 --- a/src/librustc/middle/typeck/infer/error_reporting.rs +++ b/src/librustc/middle/typeck/infer/error_reporting.rs @@ -62,6 +62,7 @@ time of error detection. use std::collections::HashSet; use middle::def; use middle::subst; +use middle::ty_fold::{mod, TypeFoldable}; use middle::ty; use middle::ty::{Region, ReFree}; use middle::typeck::infer; @@ -111,7 +112,7 @@ pub trait ErrorReporting { fn values_str(&self, values: &ValuePairs) -> Option; - fn expected_found_str( + fn expected_found_str( &self, exp_found: &ty::expected_found) -> Option; @@ -396,16 +397,12 @@ impl<'a, 'tcx> ErrorReporting for InferCtxt<'a, 'tcx> { * or None if this is a derived error. */ match *values { - infer::Types(ref exp_found) => { - self.expected_found_str(exp_found) - } - infer::TraitRefs(ref exp_found) => { - self.expected_found_str(exp_found) - } + infer::Types(ref exp_found) => self.expected_found_str(exp_found), + infer::TraitRefs(ref exp_found) => self.expected_found_str(exp_found) } } - fn expected_found_str( + fn expected_found_str( &self, exp_found: &ty::expected_found) -> Option @@ -420,9 +417,14 @@ impl<'a, 'tcx> ErrorReporting for InferCtxt<'a, 'tcx> { return None; } + // Only include variable IDs in the diagnostics if there are at least two + // present across both types/traits. + let should_print_var_ids = expected.remaining_type_variables(self.tcx) + .union(&found.remaining_type_variables(self.tcx)).count() > 1; + Some(format!("expected `{}`, found `{}`", - expected.user_string(self.tcx), - found.user_string(self.tcx))) + expected.user_string_with_var_ids(self.tcx, should_print_var_ids), + found.user_string_with_var_ids(self.tcx, should_print_var_ids))) } fn report_param_bound_failure(&self, @@ -1654,6 +1656,7 @@ impl<'a, 'tcx> ErrorReportingHelpers for InferCtxt<'a, 'tcx> { pub trait Resolvable { fn resolve(&self, infcx: &InferCtxt) -> Self; fn contains_error(&self) -> bool; + fn remaining_type_variables(&self, tcx: &ty::ctxt) -> HashSet; } impl Resolvable for ty::t { @@ -1663,6 +1666,22 @@ impl Resolvable for ty::t { fn contains_error(&self) -> bool { ty::type_is_error(*self) } + fn remaining_type_variables(&self, tcx: &ty::ctxt) -> HashSet { + let mut vars = HashSet::new(); + { + let mut folder = ty_fold::BottomUpFolder { + tcx: tcx, + fldop: |t| { + if let ty::ty_infer(var) = ty::get(t).sty { + vars.insert(var); + } + t + } + }; + self.fold_with(&mut folder); + } + vars + } } impl Resolvable for Rc { @@ -1672,6 +1691,9 @@ impl Resolvable for Rc { fn contains_error(&self) -> bool { ty::trait_ref_contains_error(&**self) } + fn remaining_type_variables(&self, _: &ty::ctxt) -> HashSet { + HashSet::new() + } } fn lifetimes_in_scope(tcx: &ty::ctxt, diff --git a/src/librustc/middle/typeck/infer/mod.rs b/src/librustc/middle/typeck/infer/mod.rs index d2a77f906b535..227a9b1bdcc88 100644 --- a/src/librustc/middle/typeck/infer/mod.rs +++ b/src/librustc/middle/typeck/infer/mod.rs @@ -36,7 +36,8 @@ use syntax::ast; use syntax::codemap; use syntax::codemap::Span; use util::common::indent; -use util::ppaux::{bound_region_to_string, ty_to_string, trait_ref_to_string, Repr}; +use util::ppaux::{bound_region_to_string, ty_to_string}; +use util::ppaux::{trait_ref_to_string, Repr}; use self::coercion::Coerce; use self::combine::{Combine, CombineFields}; @@ -900,32 +901,25 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { err: Option<&ty::type_err>) { debug!("hi! expected_ty = {}, actual_ty = {}", expected_ty, actual_ty); - let error_str = err.map_or("".to_string(), |t_err| { - format!(" ({})", ty::type_err_to_str(self.tcx, t_err)) - }); let resolved_expected = expected_ty.map(|e_ty| { self.resolve_type_vars_if_possible(e_ty) }); - if !resolved_expected.map_or(false, |e| { ty::type_is_error(e) }) { - match resolved_expected { - None => { - self.tcx - .sess - .span_err(sp, - format!("{}{}", - mk_msg(None, actual_ty), - error_str).as_slice()) - } - Some(e) => { - self.tcx.sess.span_err(sp, - format!("{}{}", - mk_msg(Some(self.ty_to_string(e)), actual_ty), - error_str).as_slice()); + + match resolved_expected { + Some(t) if ty::type_is_error(t) => (), + _ => { + let error_str = err.map_or("".to_string(), |t_err| { + format!(" ({})", ty::type_err_to_str(self.tcx, t_err)) + }); + + self.tcx.sess.span_err(sp, format!("{}{}", + mk_msg(resolved_expected.map(|t| self.ty_to_string(t)), actual_ty), + error_str).as_slice()); + + for err in err.iter() { + ty::note_and_explain_type_err(self.tcx, *err) } } - for err in err.iter() { - ty::note_and_explain_type_err(self.tcx, *err) - } } } @@ -945,25 +939,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } pub fn report_mismatched_types(&self, - sp: Span, - e: ty::t, - a: ty::t, + span: Span, + expected: ty::t, + actual: ty::t, err: &ty::type_err) { - let resolved_expected = - self.resolve_type_vars_if_possible(e); - let mk_msg = match ty::get(resolved_expected).sty { - // Don't report an error if expected is ty_err - ty::ty_err => return, - _ => { - // if I leave out : String, it infers &str and complains - |actual: String| { - format!("mismatched types: expected `{}`, found `{}`", - self.ty_to_string(resolved_expected), - actual) - } - } + let trace = TypeTrace { + origin: Misc(span), + values: Types(ty::expected_found { + expected: expected, + found: actual + }) }; - self.type_error_message(sp, mk_msg, a, Some(err)); + self.report_and_explain_type_error(trace, err); } pub fn replace_late_bound_regions_with_fresh_regions(&self, diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 296158dd4a868..572f2c9abf223 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -43,6 +43,9 @@ pub trait Repr { /// Produces a string suitable for showing to the user. pub trait UserString { fn user_string(&self, tcx: &ctxt) -> String; + fn user_string_with_var_ids(&self, tcx: &ctxt, _: bool) -> String { + self.user_string(tcx) + } } pub fn note_and_explain_region(cx: &ctxt, @@ -228,8 +231,14 @@ pub fn mutability_to_string(m: ast::Mutability) -> String { } } +pub fn mt_to_string_with_var_ids(cx: &ctxt, m: &mt, print_var_ids: bool) -> String { + format!("{}{}", + mutability_to_string(m.mutbl), + ty_to_string_with_var_ids(cx, m.ty, print_var_ids)) +} + pub fn mt_to_string(cx: &ctxt, m: &mt) -> String { - format!("{}{}", mutability_to_string(m.mutbl), ty_to_string(cx, m.ty)) + mt_to_string_with_var_ids(cx, m, false) } pub fn trait_store_to_string(cx: &ctxt, s: ty::TraitStore) -> String { @@ -256,14 +265,17 @@ pub fn trait_ref_to_string(cx: &ctxt, trait_ref: &ty::TraitRef) -> String { } pub fn ty_to_string(cx: &ctxt, typ: t) -> String { - fn fn_input_to_string(cx: &ctxt, input: ty::t) -> String { - ty_to_string(cx, input).to_string() - } + ty_to_string_with_var_ids(cx, typ, true) +} + +pub fn ty_to_string_with_var_ids(cx: &ctxt, typ: t, mut print_var_ids: bool) -> String { + print_var_ids = print_var_ids || cx.sess.verbose(); fn bare_fn_to_string(cx: &ctxt, fn_style: ast::FnStyle, abi: abi::Abi, ident: Option, - sig: &ty::FnSig) + sig: &ty::FnSig, + print_var_ids: bool) -> String { let mut s = String::new(); match fn_style { @@ -288,12 +300,12 @@ pub fn ty_to_string(cx: &ctxt, typ: t) -> String { _ => { } } - push_sig_to_string(cx, &mut s, '(', ')', sig, ""); + push_sig_to_string(cx, &mut s, '(', ')', sig, "", print_var_ids); s } - fn closure_to_string(cx: &ctxt, cty: &ty::ClosureTy) -> String { + fn closure_to_string(cx: &ctxt, cty: &ty::ClosureTy, print_var_ids: bool) -> String { let mut s = String::new(); match cty.store { @@ -318,7 +330,7 @@ pub fn ty_to_string(cx: &ctxt, typ: t) -> String { assert_eq!(cty.onceness, ast::Once); s.push_str("proc"); push_sig_to_string(cx, &mut s, '(', ')', &cty.sig, - bounds_str.as_slice()); + bounds_str.as_slice(), print_var_ids); } ty::RegionTraitStore(..) => { match cty.onceness { @@ -326,7 +338,7 @@ pub fn ty_to_string(cx: &ctxt, typ: t) -> String { ast::Once => s.push_str("once ") } push_sig_to_string(cx, &mut s, '|', '|', &cty.sig, - bounds_str.as_slice()); + bounds_str.as_slice(), print_var_ids); } } @@ -338,9 +350,13 @@ pub fn ty_to_string(cx: &ctxt, typ: t) -> String { bra: char, ket: char, sig: &ty::FnSig, - bounds: &str) { + bounds: &str, + print_var_ids: bool) { s.push(bra); - let strs: Vec = sig.inputs.iter().map(|a| fn_input_to_string(cx, *a)).collect(); + let strs = sig.inputs + .iter() + .map(|a| ty_to_string_with_var_ids(cx, *a, print_var_ids)) + .collect::>(); s.push_str(strs.connect(", ").as_slice()); if sig.variadic { s.push_str(", ..."); @@ -355,8 +371,8 @@ pub fn ty_to_string(cx: &ctxt, typ: t) -> String { match sig.output { ty::FnConverging(t) => { if !ty::type_is_nil(t) { - s.push_str(" -> "); - s.push_str(ty_to_string(cx, t).as_slice()); + s.push_str(" -> "); + s.push_str(ty_to_string_with_var_ids(cx, t, print_var_ids).as_slice()); } } ty::FnDiverging => { @@ -365,82 +381,98 @@ pub fn ty_to_string(cx: &ctxt, typ: t) -> String { } } - // if there is an id, print that instead of the structural type: - /*for def_id in ty::type_def_id(typ).iter() { - // note that this typedef cannot have type parameters - return ty::item_path_str(cx, *def_id); - }*/ + fn infer_ty_to_string(ty: ty::InferTy, print_var_ids: bool) -> String { + match ty { + ty::TyVar(ty::TyVid { index: vid }) + | ty::IntVar(ty::IntVid { index: vid }) + | ty::FloatVar(ty::FloatVid { index: vid }) => { + match ty { + ty::TyVar(_) if print_var_ids => format!("_#{}", vid), + ty::TyVar(_) => "_".to_string(), + ty::IntVar(_) => format!("_#{}i", vid), + ty::FloatVar(_) => format!("_#{}f", vid), + _ => unreachable!() + } + } + ty::SkolemizedTy(v) => format!("SkolemizedTy({})", v), + ty::SkolemizedIntTy(v) => format!("SkolemizedIntTy({})", v), + } + } // pretty print the structural type representation: - return match ty::get(typ).sty { - ty_nil => "()".to_string(), - ty_bool => "bool".to_string(), - ty_char => "char".to_string(), - ty_int(t) => ast_util::int_ty_to_string(t, None).to_string(), - ty_uint(t) => ast_util::uint_ty_to_string(t, None).to_string(), - ty_float(t) => ast_util::float_ty_to_string(t).to_string(), - ty_uniq(typ) => format!("Box<{}>", ty_to_string(cx, typ)), - ty_ptr(ref tm) => { - format!("*{} {}", match tm.mutbl { - ast::MutMutable => "mut", - ast::MutImmutable => "const", - }, ty_to_string(cx, tm.ty)) - } - ty_rptr(r, ref tm) => { - let mut buf = region_ptr_to_string(cx, r); - buf.push_str(mt_to_string(cx, tm).as_slice()); - buf - } - ty_open(typ) => format!("opened<{}>", ty_to_string(cx, typ)), - ty_tup(ref elems) => { - let strs: Vec = elems.iter().map(|elem| ty_to_string(cx, *elem)).collect(); - format!("({})", strs.connect(",")) - } - ty_closure(ref f) => { - closure_to_string(cx, &**f) - } - ty_bare_fn(ref f) => { - bare_fn_to_string(cx, f.fn_style, f.abi, None, &f.sig) - } - ty_infer(infer_ty) => infer_ty.to_string(), - ty_err => "[type error]".to_string(), - ty_param(ref param_ty) => { - param_ty.repr(cx) - } - ty_enum(did, ref substs) | ty_struct(did, ref substs) => { - let base = ty::item_path_str(cx, did); - let generics = ty::lookup_item_type(cx, did).generics; - parameterized(cx, base.as_slice(), substs, &generics) - } - ty_trait(box ty::TyTrait { - def_id: did, ref substs, ref bounds - }) => { - let base = ty::item_path_str(cx, did); - let trait_def = ty::lookup_trait_def(cx, did); - let ty = parameterized(cx, base.as_slice(), - substs, &trait_def.generics); - let bound_str = bounds.user_string(cx); - let bound_sep = if bound_str.is_empty() { "" } else { "+" }; - format!("{}{}{}", - ty, - bound_sep, - bound_str) - } - ty_str => "str".to_string(), - ty_unboxed_closure(ref did, _, ref substs) => { - let unboxed_closures = cx.unboxed_closures.borrow(); - unboxed_closures.find(did).map(|cl| { - closure_to_string(cx, &cl.closure_type.subst(cx, substs)) - }).unwrap_or_else(|| "closure".to_string()) - } - ty_vec(t, sz) => { - match sz { - Some(n) => { - format!("[{}, ..{}]", ty_to_string(cx, t), n) - } - None => format!("[{}]", ty_to_string(cx, t)), - } - } + match ty::get(typ).sty { + ty_nil => "()".to_string(), + ty_bool => "bool".to_string(), + ty_char => "char".to_string(), + ty_int(t) => ast_util::int_ty_to_string(t, None).to_string(), + ty_uint(t) => ast_util::uint_ty_to_string(t, None).to_string(), + ty_float(t) => ast_util::float_ty_to_string(t).to_string(), + ty_uniq(typ) => format!("Box<{}>", ty_to_string_with_var_ids(cx, typ, print_var_ids)), + ty_ptr(ref tm) => { + format!("*{} {}", match tm.mutbl { + ast::MutMutable => "mut", + ast::MutImmutable => "const", + }, ty_to_string(cx, tm.ty)) + } + ty_rptr(r, ref tm) => { + let mut buf = region_ptr_to_string(cx, r); + buf.push_str(mt_to_string_with_var_ids(cx, tm, print_var_ids).as_slice()); + buf + } + ty_open(typ) => + format!("opened<{}>", ty_to_string_with_var_ids(cx, typ, print_var_ids)), + ty_tup(ref elems) => { + let strs = elems + .iter() + .map(|elem| ty_to_string_with_var_ids(cx, *elem, print_var_ids)) + .collect::>(); + match strs.as_slice() { + [ref string] => format!("({},)", string), + strs => format!("({})", strs.connect(", ")) + } + } + ty_closure(ref f) => { + closure_to_string(cx, &**f, print_var_ids) + } + ty_bare_fn(ref f) => { + bare_fn_to_string(cx, f.fn_style, f.abi, None, &f.sig, print_var_ids) + } + ty_infer(infer_ty) => infer_ty_to_string(infer_ty, print_var_ids), + ty_err => "[type error]".to_string(), + ty_param(ref param_ty) => param_ty.repr(cx), + ty_enum(did, ref substs) | ty_struct(did, ref substs) => { + let base = ty::item_path_str(cx, did); + let generics = ty::lookup_item_type(cx, did).generics; + parameterized(cx, base.as_slice(), substs, &generics, print_var_ids) + } + ty_trait(box ty::TyTrait { + def_id: did, ref substs, ref bounds + }) => { + let base = ty::item_path_str(cx, did); + let trait_def = ty::lookup_trait_def(cx, did); + let ty = parameterized(cx, base.as_slice(), + substs, &trait_def.generics, print_var_ids); + let bound_str = bounds.user_string(cx); + let bound_sep = if bound_str.is_empty() { "" } else { "+" }; + format!("{}{}{}", + ty, + bound_sep, + bound_str) + } + ty_str => "str".to_string(), + ty_unboxed_closure(ref did, _, ref substs) => { + let unboxed_closures = cx.unboxed_closures.borrow(); + unboxed_closures.find(did).map(|cl| { + closure_to_string(cx, &cl.closure_type.subst(cx, substs), print_var_ids) + }).unwrap_or_else(|| "closure".to_string()) + } + ty_vec(t, sz) => { + let inner_str = ty_to_string_with_var_ids(cx, t, print_var_ids); + match sz { + Some(n) => format!("[{}, ..{}]", inner_str, n), + None => format!("[{}]", inner_str), + } + } } } @@ -460,7 +492,8 @@ pub fn explicit_self_category_to_str(category: &ty::ExplicitSelfCategory) pub fn parameterized(cx: &ctxt, base: &str, substs: &subst::Substs, - generics: &ty::Generics) + generics: &ty::Generics, + print_var_ids: bool) -> String { let mut strs = Vec::new(); @@ -470,15 +503,15 @@ pub fn parameterized(cx: &ctxt, subst::NonerasedRegions(ref regions) => { for &r in regions.iter() { let s = region_to_string(cx, "", false, r); - if !s.is_empty() { - strs.push(s) - } else { + if s.is_empty() { // This happens when the value of the region // parameter is not easily serialized. This may be // because the user omitted it in the first place, // or because it refers to some block in the code, // etc. I'm not sure how best to serialize this. strs.push(format!("'_")); + } else { + strs.push(s) } } } @@ -499,7 +532,7 @@ pub fn parameterized(cx: &ctxt, }; for t in tps[..tps.len() - num_defaults].iter() { - strs.push(ty_to_string(cx, *t)) + strs.push(ty_to_string_with_var_ids(cx, *t, print_var_ids)) } if cx.sess.verbose() { @@ -515,7 +548,7 @@ pub fn parameterized(cx: &ctxt, } if strs.len() > 0u { - format!("{}<{}>", base, strs.connect(",")) + format!("{}<{}>", base, strs.connect(", ")) } else { format!("{}", base) } @@ -710,7 +743,7 @@ impl Repr for ty::TraitRef { let trait_def = ty::lookup_trait_def(tcx, self.def_id); format!("<{} as {}>", self.substs.self_ty().repr(tcx), - parameterized(tcx, base.as_slice(), &self.substs, &trait_def.generics)) + parameterized(tcx, base.as_slice(), &self.substs, &trait_def.generics, false)) } } @@ -1095,9 +1128,12 @@ impl UserString for ty::BuiltinBounds { impl UserString for ty::TraitRef { fn user_string(&self, tcx: &ctxt) -> String { + self.user_string_with_var_ids(tcx, false) + } + fn user_string_with_var_ids(&self, tcx: &ctxt, print_var_ids: bool) -> String { let base = ty::item_path_str(tcx, self.def_id); let trait_def = ty::lookup_trait_def(tcx, self.def_id); - parameterized(tcx, base.as_slice(), &self.substs, &trait_def.generics) + parameterized(tcx, base.as_slice(), &self.substs, &trait_def.generics, print_var_ids) } } @@ -1105,6 +1141,9 @@ impl UserString for ty::t { fn user_string(&self, tcx: &ctxt) -> String { ty_to_string(tcx, *self) } + fn user_string_with_var_ids(&self, tcx: &ctxt, print_var_ids: bool) -> String { + ty_to_string_with_var_ids(tcx, *self, print_var_ids) + } } impl UserString for ast::Ident { From 66fbe4c22c9743aff642f06549ce5f503668f722 Mon Sep 17 00:00:00 2001 From: Jakub Bukaj Date: Thu, 23 Oct 2014 22:48:32 +0200 Subject: [PATCH 2/7] Update tests with the new diagnostic tweaks --- src/test/compile-fail/array-not-vector.rs | 4 ++-- .../explicit-self-lifetime-mismatch.rs | 8 ++++---- .../generic-type-params-name-repr.rs | 6 +++--- src/test/compile-fail/issue-13482.rs | 4 ++-- src/test/compile-fail/issue-16338.rs | 2 +- src/test/compile-fail/issue-16401.rs | 2 +- src/test/compile-fail/issue-3680.rs | 4 ++-- src/test/compile-fail/issue-4201.rs | 2 +- src/test/compile-fail/issue-4968.rs | 2 +- src/test/compile-fail/issue-5100.rs | 20 +++++++++---------- src/test/compile-fail/issue-5500.rs | 2 +- src/test/compile-fail/issue-7092.rs | 2 +- src/test/compile-fail/issue-7867.rs | 6 +++--- src/test/compile-fail/map-types.rs | 2 +- src/test/compile-fail/match-vec-mismatch-2.rs | 2 +- src/test/compile-fail/repeat_count.rs | 2 +- .../slightly-nice-generic-literal-messages.rs | 2 +- src/test/compile-fail/suppressed-error.rs | 2 +- src/test/compile-fail/tuple-arity-mismatch.rs | 3 +++ .../compile-fail/tuple-index-out-of-bounds.rs | 2 +- .../typeck_type_placeholder_mismatch.rs | 4 ++-- 21 files changed, 43 insertions(+), 40 deletions(-) diff --git a/src/test/compile-fail/array-not-vector.rs b/src/test/compile-fail/array-not-vector.rs index 79d4ada41e8e8..7edb4b8754a1f 100644 --- a/src/test/compile-fail/array-not-vector.rs +++ b/src/test/compile-fail/array-not-vector.rs @@ -9,8 +9,8 @@ // except according to those terms. fn main() { - let _x: int = [1i, 2, 3]; //~ ERROR expected int, found array + let _x: int = [1i, 2, 3]; //~ ERROR expected int, found array of 3 elements let x: &[int] = &[1, 2, 3]; - let _y: &int = x; //~ ERROR expected int, found unsized array + let _y: &int = x; //~ ERROR expected int, found slice } diff --git a/src/test/compile-fail/explicit-self-lifetime-mismatch.rs b/src/test/compile-fail/explicit-self-lifetime-mismatch.rs index b5346a1c5d1f7..d1ae535d83097 100644 --- a/src/test/compile-fail/explicit-self-lifetime-mismatch.rs +++ b/src/test/compile-fail/explicit-self-lifetime-mismatch.rs @@ -16,10 +16,10 @@ struct Foo<'a,'b> { impl<'a,'b> Foo<'a,'b> { // The number of errors is related to the way invariance works. fn bar(self: Foo<'b,'a>) {} - //~^ ERROR mismatched types: expected `Foo<'a,'b>`, found `Foo<'b,'a>` - //~^^ ERROR mismatched types: expected `Foo<'a,'b>`, found `Foo<'b,'a>` - //~^^^ ERROR mismatched types: expected `Foo<'b,'a>`, found `Foo<'a,'b>` - //~^^^^ ERROR mismatched types: expected `Foo<'b,'a>`, found `Foo<'a,'b>` + //~^ ERROR mismatched types: expected `Foo<'a, 'b>`, found `Foo<'b, 'a>` + //~^^ ERROR mismatched types: expected `Foo<'a, 'b>`, found `Foo<'b, 'a>` + //~^^^ ERROR mismatched types: expected `Foo<'b, 'a>`, found `Foo<'a, 'b>` + //~^^^^ ERROR mismatched types: expected `Foo<'b, 'a>`, found `Foo<'a, 'b>` } fn main() {} diff --git a/src/test/compile-fail/generic-type-params-name-repr.rs b/src/test/compile-fail/generic-type-params-name-repr.rs index 87c865ab618b7..1c14644ec186d 100644 --- a/src/test/compile-fail/generic-type-params-name-repr.rs +++ b/src/test/compile-fail/generic-type-params-name-repr.rs @@ -29,13 +29,13 @@ fn main() { // Including cases where the default is using previous type params. let _: HashMap = (); - //~^ ERROR mismatched types: expected `HashMap`, found `()` + //~^ ERROR mismatched types: expected `HashMap`, found `()` let _: HashMap> = (); - //~^ ERROR mismatched types: expected `HashMap`, found `()` + //~^ ERROR mismatched types: expected `HashMap`, found `()` // But not when there's a different type in between. let _: Foo = (); - //~^ ERROR mismatched types: expected `Foo`, found `()` + //~^ ERROR mismatched types: expected `Foo`, found `()` // And don't print <> at all when there's just defaults. let _: Foo = (); diff --git a/src/test/compile-fail/issue-13482.rs b/src/test/compile-fail/issue-13482.rs index 43c7f45e15a55..0139a2ff7108d 100644 --- a/src/test/compile-fail/issue-13482.rs +++ b/src/test/compile-fail/issue-13482.rs @@ -12,8 +12,8 @@ fn main() { let x = [1,2]; let y = match x { [] => None, -//~^ ERROR mismatched types: expected `[, ..2]`, found `[, ..0]` -// (expected array, found array) +//~^ ERROR types: expected `[_#0i, ..2]`, found `[_#7, ..0]` +// (expected array of 2 elements, found array of 0 elements) [a,_] => Some(a) }; } diff --git a/src/test/compile-fail/issue-16338.rs b/src/test/compile-fail/issue-16338.rs index 537fc5aaa5503..f62bccb22f359 100644 --- a/src/test/compile-fail/issue-16338.rs +++ b/src/test/compile-fail/issue-16338.rs @@ -12,7 +12,7 @@ use std::raw::Slice; fn main() { let Slice { data: data, len: len } = "foo"; - //~^ ERROR mismatched types: expected `&str`, found `core::raw::Slice<>` + //~^ ERROR mismatched types: expected `&str`, found `core::raw::Slice<_>` // (expected &-ptr, found struct core::raw::Slice) } diff --git a/src/test/compile-fail/issue-16401.rs b/src/test/compile-fail/issue-16401.rs index deb2f5912b652..4890cc52c0005 100644 --- a/src/test/compile-fail/issue-16401.rs +++ b/src/test/compile-fail/issue-16401.rs @@ -13,7 +13,7 @@ use std::raw::Slice; fn main() { match () { Slice { data: data, len: len } => (), - //~^ ERROR mismatched types: expected `()`, found `core::raw::Slice<>` + //~^ ERROR mismatched types: expected `()`, found `core::raw::Slice<_>` // (expected (), found struct core::raw::Slice) _ => unreachable!() } diff --git a/src/test/compile-fail/issue-3680.rs b/src/test/compile-fail/issue-3680.rs index 96a93c205feb7..a23f76bd15b26 100644 --- a/src/test/compile-fail/issue-3680.rs +++ b/src/test/compile-fail/issue-3680.rs @@ -11,7 +11,7 @@ fn main() { match None { Err(_) => () - //~^ ERROR mismatched types: expected `core::option::Option<>` - // , found `core::result::Result<,>` + //~^ ERROR mismatched types: expected `core::option::Option<_#1>` + // , found `core::result::Result<_#2, _#3>` } } diff --git a/src/test/compile-fail/issue-4201.rs b/src/test/compile-fail/issue-4201.rs index 4b2be9e58acdc..69bcfc019c096 100644 --- a/src/test/compile-fail/issue-4201.rs +++ b/src/test/compile-fail/issue-4201.rs @@ -12,7 +12,7 @@ fn main() { let a = if true { 0 } else if false { -//~^ ERROR if may be missing an else clause: expected `()`, found `` +//~^ ERROR if may be missing an else clause: expected `()`, found `_#1i` 1 }; } diff --git a/src/test/compile-fail/issue-4968.rs b/src/test/compile-fail/issue-4968.rs index a181215f4184d..8311d6fd563c4 100644 --- a/src/test/compile-fail/issue-4968.rs +++ b/src/test/compile-fail/issue-4968.rs @@ -13,6 +13,6 @@ const A: (int,int) = (4,2); fn main() { match 42 { A => () } - //~^ ERROR mismatched types: expected ``, found `(int,int)` + //~^ ERROR mismatched types: expected `_#0i`, found `(int, int)` // (expected integral variable, found tuple) } diff --git a/src/test/compile-fail/issue-5100.rs b/src/test/compile-fail/issue-5100.rs index 3ddb713528c55..be7bd248614ce 100644 --- a/src/test/compile-fail/issue-5100.rs +++ b/src/test/compile-fail/issue-5100.rs @@ -13,32 +13,32 @@ enum A { B, C } fn main() { match (true, false) { B => (), - //~^ ERROR mismatched types: expected `(bool,bool)`, found `A` - // (expected tuple, found enum A) +//~^ ERROR mismatched types: expected `(bool, bool)`, found `A` (expected tuple, found enum A) _ => () } match (true, false) { (true, false, false) => () - //~^ ERROR mismatched types: expected `(bool,bool)`, - // found `(,,)` - // (expected a tuple with 2 elements, found one with 3 elements) +//~^ ERROR mismatched types: expected `(bool, bool)`, found `(_#9, _#10, _#11)` + } + + match (true, false) { + (true, false, false) => () +//~^ ERROR (expected a tuple with 2 elements, found one with 3 elements) } match (true, false) { box (true, false) => () - //~^ ERROR mismatched types: expected `(bool,bool)`, found `Box<>` - // (expected tuple, found box) +//~^ ERROR mismatched types: expected `(bool, bool)`, found `Box<_>` (expected tuple, found box) } match (true, false) { &(true, false) => () - //~^ ERROR mismatched types: expected `(bool,bool)`, found `&` - // (expected tuple, found &-ptr) +//~^ ERROR mismatched types: expected `(bool, bool)`, found `&_` (expected tuple, found &-ptr) } - let v = [('a', 'b') //~ ERROR expected function, found `(char,char)` + let v = [('a', 'b') //~ ERROR expected function, found `(char, char)` ('c', 'd'), ('e', 'f')]; diff --git a/src/test/compile-fail/issue-5500.rs b/src/test/compile-fail/issue-5500.rs index 86ff29a52b034..56867349065a5 100644 --- a/src/test/compile-fail/issue-5500.rs +++ b/src/test/compile-fail/issue-5500.rs @@ -10,5 +10,5 @@ fn main() { &panic!() - //~^ ERROR mismatched types: expected `()`, found `&` (expected (), found &-ptr) + //~^ ERROR mismatched types: expected `()`, found `&_` (expected (), found &-ptr) } diff --git a/src/test/compile-fail/issue-7092.rs b/src/test/compile-fail/issue-7092.rs index cc7e8052920b2..116639f49459f 100644 --- a/src/test/compile-fail/issue-7092.rs +++ b/src/test/compile-fail/issue-7092.rs @@ -14,7 +14,7 @@ enum Whatever { fn foo(x: Whatever) { match x { Some(field) => -//~^ ERROR: mismatched types: expected `Whatever`, found `core::option::Option<>` +//~^ ERROR: mismatched types: expected `Whatever`, found `core::option::Option<_>` field.access(), //~ ERROR the type of this value must be known in this context } } diff --git a/src/test/compile-fail/issue-7867.rs b/src/test/compile-fail/issue-7867.rs index 0ab551642a0c4..f3915634cc127 100644 --- a/src/test/compile-fail/issue-7867.rs +++ b/src/test/compile-fail/issue-7867.rs @@ -14,14 +14,14 @@ mod foo { pub fn bar() {} } fn main() { match (true, false) { - B => (), //~ ERROR expected `(bool,bool)`, found `A` (expected tuple, found enum A) + B => (), //~ ERROR expected `(bool, bool)`, found `A` (expected tuple, found enum A) _ => () } match &Some(42i) { Some(x) => (), //~ ERROR expected `&core::option::Option`, - // found `core::option::Option<>` + // found `core::option::Option<_>` None => () //~ ERROR expected `&core::option::Option`, - // found `core::option::Option<>` + // found `core::option::Option<_>` } } diff --git a/src/test/compile-fail/map-types.rs b/src/test/compile-fail/map-types.rs index cbe391324794f..6f032c5b1f089 100644 --- a/src/test/compile-fail/map-types.rs +++ b/src/test/compile-fail/map-types.rs @@ -18,5 +18,5 @@ fn main() { let x: Box> = box HashMap::new(); let x: Box> = x; let y: Box> = box x; - //~^ ERROR the trait `collections::Map` is not implemented + //~^ ERROR the trait `collections::Map` is not implemented } diff --git a/src/test/compile-fail/match-vec-mismatch-2.rs b/src/test/compile-fail/match-vec-mismatch-2.rs index 6d37eb8a63645..6bb049f3ca5e8 100644 --- a/src/test/compile-fail/match-vec-mismatch-2.rs +++ b/src/test/compile-fail/match-vec-mismatch-2.rs @@ -11,6 +11,6 @@ fn main() { match () { [()] => { } -//~^ ERROR mismatched types: expected `()`, found `&[]` (expected (), found &-ptr) +//~^ ERROR mismatched types: expected `()`, found `&[_]` (expected (), found &-ptr) } } diff --git a/src/test/compile-fail/repeat_count.rs b/src/test/compile-fail/repeat_count.rs index 8a28819a7365a..6a1603fbfcbff 100644 --- a/src/test/compile-fail/repeat_count.rs +++ b/src/test/compile-fail/repeat_count.rs @@ -18,7 +18,7 @@ fn main() { let c = [0, ..true]; //~ ERROR expected positive integer for repeat count, found boolean //~^ ERROR: expected `uint`, found `bool` let d = [0, ..0.5]; //~ ERROR expected positive integer for repeat count, found float - //~^ ERROR: expected `uint`, found `` + //~^ ERROR: expected `uint`, found `_#0f` let e = [0, .."foo"]; //~ ERROR expected positive integer for repeat count, found string //~^ ERROR: expected `uint`, found `&'static str` let f = [0, ..-4]; diff --git a/src/test/compile-fail/slightly-nice-generic-literal-messages.rs b/src/test/compile-fail/slightly-nice-generic-literal-messages.rs index aebe78b18e047..02ebbb134f0ee 100644 --- a/src/test/compile-fail/slightly-nice-generic-literal-messages.rs +++ b/src/test/compile-fail/slightly-nice-generic-literal-messages.rs @@ -13,7 +13,7 @@ struct Foo(T); fn main() { match Foo(1.1) { 1 => {} - //~^ ERROR expected `Foo<,>`, found `` + //~^ ERROR expected `Foo<_#0f, _#2>`, found `_#0i` } } diff --git a/src/test/compile-fail/suppressed-error.rs b/src/test/compile-fail/suppressed-error.rs index 54d6fa5bdd395..bd9f2c3632846 100644 --- a/src/test/compile-fail/suppressed-error.rs +++ b/src/test/compile-fail/suppressed-error.rs @@ -10,6 +10,6 @@ fn main() { let (x, y) = (); -//~^ ERROR types: expected `()`, found `(,)` (expected (), found tuple) +//~^ ERROR expected `()`, found `(_#3, _#4)` (expected (), found tuple) return x; } diff --git a/src/test/compile-fail/tuple-arity-mismatch.rs b/src/test/compile-fail/tuple-arity-mismatch.rs index 1500a3cbe52db..d0c2faed4b29d 100644 --- a/src/test/compile-fail/tuple-arity-mismatch.rs +++ b/src/test/compile-fail/tuple-arity-mismatch.rs @@ -15,4 +15,7 @@ fn first((value, _): (int, f64)) -> int { value } fn main() { let y = first ((1,2.0,3)); //~^ ERROR expected a tuple with 2 elements, found one with 3 elements + + let y = first ((1,)); + //~^ ERROR expected `(int, f64)`, found `(int,)` } diff --git a/src/test/compile-fail/tuple-index-out-of-bounds.rs b/src/test/compile-fail/tuple-index-out-of-bounds.rs index d16f950a5d4bd..f9bf2746794ac 100644 --- a/src/test/compile-fail/tuple-index-out-of-bounds.rs +++ b/src/test/compile-fail/tuple-index-out-of-bounds.rs @@ -22,5 +22,5 @@ fn main() { tuple.0; tuple.1; tuple.2; - //~^ ERROR attempted out-of-bounds tuple index `2` on type `(int,int)` + //~^ ERROR attempted out-of-bounds tuple index `2` on type `(int, int)` } diff --git a/src/test/compile-fail/typeck_type_placeholder_mismatch.rs b/src/test/compile-fail/typeck_type_placeholder_mismatch.rs index 29d32b1053910..aa7b551afc56a 100644 --- a/src/test/compile-fail/typeck_type_placeholder_mismatch.rs +++ b/src/test/compile-fail/typeck_type_placeholder_mismatch.rs @@ -19,11 +19,11 @@ pub fn main() { fn test1() { let x: Foo<_> = Bar::; - //~^ ERROR mismatched types: expected `Foo<>`, found `Bar` + //~^ ERROR mismatched types: expected `Foo<_>`, found `Bar` let y: Foo = x; } fn test2() { let x: Foo<_> = Bar::; - //~^ ERROR mismatched types: expected `Foo<>`, found `Bar` + //~^ ERROR mismatched types: expected `Foo<_>`, found `Bar` } From 1b79303f4996d76e75588705e3ddb64031009564 Mon Sep 17 00:00:00 2001 From: Jakub Bukaj Date: Wed, 29 Oct 2014 18:59:04 +0100 Subject: [PATCH 3/7] Address review comments --- src/librustc/middle/ty.rs | 12 ++++++--- .../middle/typeck/infer/error_reporting.rs | 27 ++++++++++--------- src/librustc/util/ppaux.rs | 6 ++--- 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 3ec1106ff20e0..ff949a93e01b1 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -3912,9 +3912,15 @@ pub fn type_err_to_str(cx: &ctxt, err: &type_err) -> String { trait_store_to_string(cx, (*values).found)) } terr_sorts(values) => { - format!("expected {}, found {}", - ty_sort_string(cx, values.expected), - ty_sort_string(cx, values.found)) + // A naive approach to making sure that we're not reporting silly errors such as: + // (expected closure, found closure). + let expected_str = ty_sort_string(cx, values.expected); + let found_str = ty_sort_string(cx, values.found); + if expected_str == found_str { + format!("expected {}, found a different {}", expected_str, found_str) + } else { + format!("expected {}, found {}", expected_str, found_str) + } } terr_traits(values) => { format!("expected trait `{}`, found trait `{}`", diff --git a/src/librustc/middle/typeck/infer/error_reporting.rs b/src/librustc/middle/typeck/infer/error_reporting.rs index 0f000e93fc01a..e6c158ef9af2b 100644 --- a/src/librustc/middle/typeck/infer/error_reporting.rs +++ b/src/librustc/middle/typeck/infer/error_reporting.rs @@ -112,7 +112,7 @@ pub trait ErrorReporting { fn values_str(&self, values: &ValuePairs) -> Option; - fn expected_found_str( + fn expected_found_str( &self, exp_found: &ty::expected_found) -> Option; @@ -402,7 +402,7 @@ impl<'a, 'tcx> ErrorReporting for InferCtxt<'a, 'tcx> { } } - fn expected_found_str( + fn expected_found_str( &self, exp_found: &ty::expected_found) -> Option @@ -1656,16 +1656,13 @@ impl<'a, 'tcx> ErrorReportingHelpers for InferCtxt<'a, 'tcx> { pub trait Resolvable { fn resolve(&self, infcx: &InferCtxt) -> Self; fn contains_error(&self) -> bool; +} + +pub trait HasRemainingTypeVariables { fn remaining_type_variables(&self, tcx: &ty::ctxt) -> HashSet; } -impl Resolvable for ty::t { - fn resolve(&self, infcx: &InferCtxt) -> ty::t { - infcx.resolve_type_vars_if_possible(*self) - } - fn contains_error(&self) -> bool { - ty::type_is_error(*self) - } +impl HasRemainingTypeVariables for T { fn remaining_type_variables(&self, tcx: &ty::ctxt) -> HashSet { let mut vars = HashSet::new(); { @@ -1684,6 +1681,15 @@ impl Resolvable for ty::t { } } +impl Resolvable for ty::t { + fn resolve(&self, infcx: &InferCtxt) -> ty::t { + infcx.resolve_type_vars_if_possible(*self) + } + fn contains_error(&self) -> bool { + ty::type_is_error(*self) + } +} + impl Resolvable for Rc { fn resolve(&self, infcx: &InferCtxt) -> Rc { Rc::new(infcx.resolve_type_vars_in_trait_ref_if_possible(&**self)) @@ -1691,9 +1697,6 @@ impl Resolvable for Rc { fn contains_error(&self) -> bool { ty::trait_ref_contains_error(&**self) } - fn remaining_type_variables(&self, _: &ty::ctxt) -> HashSet { - HashSet::new() - } } fn lifetimes_in_scope(tcx: &ty::ctxt, diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 572f2c9abf223..eb37f68154da2 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -383,9 +383,9 @@ pub fn ty_to_string_with_var_ids(cx: &ctxt, typ: t, mut print_var_ids: bool) -> fn infer_ty_to_string(ty: ty::InferTy, print_var_ids: bool) -> String { match ty { - ty::TyVar(ty::TyVid { index: vid }) - | ty::IntVar(ty::IntVid { index: vid }) - | ty::FloatVar(ty::FloatVid { index: vid }) => { + ty::TyVar(ty::TyVid { index: vid }) | + ty::IntVar(ty::IntVid { index: vid }) | + ty::FloatVar(ty::FloatVid { index: vid }) => { match ty { ty::TyVar(_) if print_var_ids => format!("_#{}", vid), ty::TyVar(_) => "_".to_string(), From 3db13f4892bc06ee038aef01dc9e5daf0451a561 Mon Sep 17 00:00:00 2001 From: Jakub Bukaj Date: Wed, 29 Oct 2014 21:20:06 +0100 Subject: [PATCH 4/7] Always drop var IDs from type variables modulo -Z verbose, per PR discussion --- .../middle/typeck/infer/error_reporting.rs | 37 +------ src/librustc/util/ppaux.rs | 96 +++++++------------ src/test/compile-fail/issue-13482-2.rs | 21 ++++ src/test/compile-fail/issue-13482.rs | 2 +- src/test/compile-fail/issue-3680.rs | 4 +- src/test/compile-fail/issue-4201.rs | 2 +- src/test/compile-fail/issue-4968.rs | 2 +- src/test/compile-fail/issue-5100.rs | 2 +- src/test/compile-fail/repeat_count.rs | 2 +- .../slightly-nice-generic-literal-messages.rs | 2 +- src/test/compile-fail/suppressed-error.rs | 2 +- 11 files changed, 71 insertions(+), 101 deletions(-) create mode 100644 src/test/compile-fail/issue-13482-2.rs diff --git a/src/librustc/middle/typeck/infer/error_reporting.rs b/src/librustc/middle/typeck/infer/error_reporting.rs index e6c158ef9af2b..3baa9a7a5f964 100644 --- a/src/librustc/middle/typeck/infer/error_reporting.rs +++ b/src/librustc/middle/typeck/infer/error_reporting.rs @@ -62,7 +62,6 @@ time of error detection. use std::collections::HashSet; use middle::def; use middle::subst; -use middle::ty_fold::{mod, TypeFoldable}; use middle::ty; use middle::ty::{Region, ReFree}; use middle::typeck::infer; @@ -112,7 +111,7 @@ pub trait ErrorReporting { fn values_str(&self, values: &ValuePairs) -> Option; - fn expected_found_str( + fn expected_found_str( &self, exp_found: &ty::expected_found) -> Option; @@ -402,7 +401,7 @@ impl<'a, 'tcx> ErrorReporting for InferCtxt<'a, 'tcx> { } } - fn expected_found_str( + fn expected_found_str( &self, exp_found: &ty::expected_found) -> Option @@ -417,14 +416,9 @@ impl<'a, 'tcx> ErrorReporting for InferCtxt<'a, 'tcx> { return None; } - // Only include variable IDs in the diagnostics if there are at least two - // present across both types/traits. - let should_print_var_ids = expected.remaining_type_variables(self.tcx) - .union(&found.remaining_type_variables(self.tcx)).count() > 1; - Some(format!("expected `{}`, found `{}`", - expected.user_string_with_var_ids(self.tcx, should_print_var_ids), - found.user_string_with_var_ids(self.tcx, should_print_var_ids))) + expected.user_string(self.tcx), + found.user_string(self.tcx))) } fn report_param_bound_failure(&self, @@ -1658,29 +1652,6 @@ pub trait Resolvable { fn contains_error(&self) -> bool; } -pub trait HasRemainingTypeVariables { - fn remaining_type_variables(&self, tcx: &ty::ctxt) -> HashSet; -} - -impl HasRemainingTypeVariables for T { - fn remaining_type_variables(&self, tcx: &ty::ctxt) -> HashSet { - let mut vars = HashSet::new(); - { - let mut folder = ty_fold::BottomUpFolder { - tcx: tcx, - fldop: |t| { - if let ty::ty_infer(var) = ty::get(t).sty { - vars.insert(var); - } - t - } - }; - self.fold_with(&mut folder); - } - vars - } -} - impl Resolvable for ty::t { fn resolve(&self, infcx: &InferCtxt) -> ty::t { infcx.resolve_type_vars_if_possible(*self) diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index eb37f68154da2..633a350ddb2a4 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -43,9 +43,6 @@ pub trait Repr { /// Produces a string suitable for showing to the user. pub trait UserString { fn user_string(&self, tcx: &ctxt) -> String; - fn user_string_with_var_ids(&self, tcx: &ctxt, _: bool) -> String { - self.user_string(tcx) - } } pub fn note_and_explain_region(cx: &ctxt, @@ -231,14 +228,10 @@ pub fn mutability_to_string(m: ast::Mutability) -> String { } } -pub fn mt_to_string_with_var_ids(cx: &ctxt, m: &mt, print_var_ids: bool) -> String { +pub fn mt_to_string(cx: &ctxt, m: &mt) -> String { format!("{}{}", mutability_to_string(m.mutbl), - ty_to_string_with_var_ids(cx, m.ty, print_var_ids)) -} - -pub fn mt_to_string(cx: &ctxt, m: &mt) -> String { - mt_to_string_with_var_ids(cx, m, false) + ty_to_string(cx, m.ty)) } pub fn trait_store_to_string(cx: &ctxt, s: ty::TraitStore) -> String { @@ -265,17 +258,11 @@ pub fn trait_ref_to_string(cx: &ctxt, trait_ref: &ty::TraitRef) -> String { } pub fn ty_to_string(cx: &ctxt, typ: t) -> String { - ty_to_string_with_var_ids(cx, typ, true) -} - -pub fn ty_to_string_with_var_ids(cx: &ctxt, typ: t, mut print_var_ids: bool) -> String { - print_var_ids = print_var_ids || cx.sess.verbose(); fn bare_fn_to_string(cx: &ctxt, fn_style: ast::FnStyle, abi: abi::Abi, ident: Option, - sig: &ty::FnSig, - print_var_ids: bool) + sig: &ty::FnSig) -> String { let mut s = String::new(); match fn_style { @@ -300,12 +287,12 @@ pub fn ty_to_string_with_var_ids(cx: &ctxt, typ: t, mut print_var_ids: bool) -> _ => { } } - push_sig_to_string(cx, &mut s, '(', ')', sig, "", print_var_ids); + push_sig_to_string(cx, &mut s, '(', ')', sig, ""); s } - fn closure_to_string(cx: &ctxt, cty: &ty::ClosureTy, print_var_ids: bool) -> String { + fn closure_to_string(cx: &ctxt, cty: &ty::ClosureTy) -> String { let mut s = String::new(); match cty.store { @@ -330,7 +317,7 @@ pub fn ty_to_string_with_var_ids(cx: &ctxt, typ: t, mut print_var_ids: bool) -> assert_eq!(cty.onceness, ast::Once); s.push_str("proc"); push_sig_to_string(cx, &mut s, '(', ')', &cty.sig, - bounds_str.as_slice(), print_var_ids); + bounds_str.as_slice()); } ty::RegionTraitStore(..) => { match cty.onceness { @@ -338,7 +325,7 @@ pub fn ty_to_string_with_var_ids(cx: &ctxt, typ: t, mut print_var_ids: bool) -> ast::Once => s.push_str("once ") } push_sig_to_string(cx, &mut s, '|', '|', &cty.sig, - bounds_str.as_slice(), print_var_ids); + bounds_str.as_slice()); } } @@ -350,12 +337,11 @@ pub fn ty_to_string_with_var_ids(cx: &ctxt, typ: t, mut print_var_ids: bool) -> bra: char, ket: char, sig: &ty::FnSig, - bounds: &str, - print_var_ids: bool) { + bounds: &str) { s.push(bra); let strs = sig.inputs .iter() - .map(|a| ty_to_string_with_var_ids(cx, *a, print_var_ids)) + .map(|a| ty_to_string(cx, *a)) .collect::>(); s.push_str(strs.connect(", ").as_slice()); if sig.variadic { @@ -372,7 +358,7 @@ pub fn ty_to_string_with_var_ids(cx: &ctxt, typ: t, mut print_var_ids: bool) -> ty::FnConverging(t) => { if !ty::type_is_nil(t) { s.push_str(" -> "); - s.push_str(ty_to_string_with_var_ids(cx, t, print_var_ids).as_slice()); + s.push_str(ty_to_string(cx, t).as_slice()); } } ty::FnDiverging => { @@ -381,21 +367,20 @@ pub fn ty_to_string_with_var_ids(cx: &ctxt, typ: t, mut print_var_ids: bool) -> } } - fn infer_ty_to_string(ty: ty::InferTy, print_var_ids: bool) -> String { + fn infer_ty_to_string(cx: &ctxt, ty: ty::InferTy) -> String { + let print_var_ids = cx.sess.verbose(); match ty { - ty::TyVar(ty::TyVid { index: vid }) | - ty::IntVar(ty::IntVid { index: vid }) | - ty::FloatVar(ty::FloatVid { index: vid }) => { - match ty { - ty::TyVar(_) if print_var_ids => format!("_#{}", vid), - ty::TyVar(_) => "_".to_string(), - ty::IntVar(_) => format!("_#{}i", vid), - ty::FloatVar(_) => format!("_#{}f", vid), - _ => unreachable!() - } - } + ty::TyVar(ty::TyVid { index: vid }) if print_var_ids => + format!("_#{}", vid), + ty::IntVar(ty::IntVid { index: vid }) if print_var_ids => + format!("_#{}i", vid), + ty::FloatVar(ty::FloatVid { index: vid }) if print_var_ids => + format!("_#{}f", vid), + ty::TyVar(_) => "_".to_string(), + ty::IntVar(_) => "_#i".to_string(), + ty::FloatVar(_) => "_#f".to_string(), ty::SkolemizedTy(v) => format!("SkolemizedTy({})", v), - ty::SkolemizedIntTy(v) => format!("SkolemizedIntTy({})", v), + ty::SkolemizedIntTy(v) => format!("SkolemizedIntTy({})", v) } } @@ -407,7 +392,7 @@ pub fn ty_to_string_with_var_ids(cx: &ctxt, typ: t, mut print_var_ids: bool) -> ty_int(t) => ast_util::int_ty_to_string(t, None).to_string(), ty_uint(t) => ast_util::uint_ty_to_string(t, None).to_string(), ty_float(t) => ast_util::float_ty_to_string(t).to_string(), - ty_uniq(typ) => format!("Box<{}>", ty_to_string_with_var_ids(cx, typ, print_var_ids)), + ty_uniq(typ) => format!("Box<{}>", ty_to_string(cx, typ)), ty_ptr(ref tm) => { format!("*{} {}", match tm.mutbl { ast::MutMutable => "mut", @@ -416,15 +401,15 @@ pub fn ty_to_string_with_var_ids(cx: &ctxt, typ: t, mut print_var_ids: bool) -> } ty_rptr(r, ref tm) => { let mut buf = region_ptr_to_string(cx, r); - buf.push_str(mt_to_string_with_var_ids(cx, tm, print_var_ids).as_slice()); + buf.push_str(mt_to_string(cx, tm).as_slice()); buf } ty_open(typ) => - format!("opened<{}>", ty_to_string_with_var_ids(cx, typ, print_var_ids)), + format!("opened<{}>", ty_to_string(cx, typ)), ty_tup(ref elems) => { let strs = elems .iter() - .map(|elem| ty_to_string_with_var_ids(cx, *elem, print_var_ids)) + .map(|elem| ty_to_string(cx, *elem)) .collect::>(); match strs.as_slice() { [ref string] => format!("({},)", string), @@ -432,18 +417,18 @@ pub fn ty_to_string_with_var_ids(cx: &ctxt, typ: t, mut print_var_ids: bool) -> } } ty_closure(ref f) => { - closure_to_string(cx, &**f, print_var_ids) + closure_to_string(cx, &**f) } ty_bare_fn(ref f) => { - bare_fn_to_string(cx, f.fn_style, f.abi, None, &f.sig, print_var_ids) + bare_fn_to_string(cx, f.fn_style, f.abi, None, &f.sig) } - ty_infer(infer_ty) => infer_ty_to_string(infer_ty, print_var_ids), + ty_infer(infer_ty) => infer_ty_to_string(cx, infer_ty), ty_err => "[type error]".to_string(), ty_param(ref param_ty) => param_ty.repr(cx), ty_enum(did, ref substs) | ty_struct(did, ref substs) => { let base = ty::item_path_str(cx, did); let generics = ty::lookup_item_type(cx, did).generics; - parameterized(cx, base.as_slice(), substs, &generics, print_var_ids) + parameterized(cx, base.as_slice(), substs, &generics) } ty_trait(box ty::TyTrait { def_id: did, ref substs, ref bounds @@ -451,7 +436,7 @@ pub fn ty_to_string_with_var_ids(cx: &ctxt, typ: t, mut print_var_ids: bool) -> let base = ty::item_path_str(cx, did); let trait_def = ty::lookup_trait_def(cx, did); let ty = parameterized(cx, base.as_slice(), - substs, &trait_def.generics, print_var_ids); + substs, &trait_def.generics); let bound_str = bounds.user_string(cx); let bound_sep = if bound_str.is_empty() { "" } else { "+" }; format!("{}{}{}", @@ -463,11 +448,11 @@ pub fn ty_to_string_with_var_ids(cx: &ctxt, typ: t, mut print_var_ids: bool) -> ty_unboxed_closure(ref did, _, ref substs) => { let unboxed_closures = cx.unboxed_closures.borrow(); unboxed_closures.find(did).map(|cl| { - closure_to_string(cx, &cl.closure_type.subst(cx, substs), print_var_ids) + closure_to_string(cx, &cl.closure_type.subst(cx, substs)) }).unwrap_or_else(|| "closure".to_string()) } ty_vec(t, sz) => { - let inner_str = ty_to_string_with_var_ids(cx, t, print_var_ids); + let inner_str = ty_to_string(cx, t); match sz { Some(n) => format!("[{}, ..{}]", inner_str, n), None => format!("[{}]", inner_str), @@ -492,8 +477,7 @@ pub fn explicit_self_category_to_str(category: &ty::ExplicitSelfCategory) pub fn parameterized(cx: &ctxt, base: &str, substs: &subst::Substs, - generics: &ty::Generics, - print_var_ids: bool) + generics: &ty::Generics) -> String { let mut strs = Vec::new(); @@ -532,7 +516,7 @@ pub fn parameterized(cx: &ctxt, }; for t in tps[..tps.len() - num_defaults].iter() { - strs.push(ty_to_string_with_var_ids(cx, *t, print_var_ids)) + strs.push(ty_to_string(cx, *t)) } if cx.sess.verbose() { @@ -743,7 +727,7 @@ impl Repr for ty::TraitRef { let trait_def = ty::lookup_trait_def(tcx, self.def_id); format!("<{} as {}>", self.substs.self_ty().repr(tcx), - parameterized(tcx, base.as_slice(), &self.substs, &trait_def.generics, false)) + parameterized(tcx, base.as_slice(), &self.substs, &trait_def.generics)) } } @@ -1128,12 +1112,9 @@ impl UserString for ty::BuiltinBounds { impl UserString for ty::TraitRef { fn user_string(&self, tcx: &ctxt) -> String { - self.user_string_with_var_ids(tcx, false) - } - fn user_string_with_var_ids(&self, tcx: &ctxt, print_var_ids: bool) -> String { let base = ty::item_path_str(tcx, self.def_id); let trait_def = ty::lookup_trait_def(tcx, self.def_id); - parameterized(tcx, base.as_slice(), &self.substs, &trait_def.generics, print_var_ids) + parameterized(tcx, base.as_slice(), &self.substs, &trait_def.generics) } } @@ -1141,9 +1122,6 @@ impl UserString for ty::t { fn user_string(&self, tcx: &ctxt) -> String { ty_to_string(tcx, *self) } - fn user_string_with_var_ids(&self, tcx: &ctxt, print_var_ids: bool) -> String { - ty_to_string_with_var_ids(tcx, *self, print_var_ids) - } } impl UserString for ast::Ident { diff --git a/src/test/compile-fail/issue-13482-2.rs b/src/test/compile-fail/issue-13482-2.rs new file mode 100644 index 0000000000000..6746b90e32d2e --- /dev/null +++ b/src/test/compile-fail/issue-13482-2.rs @@ -0,0 +1,21 @@ +// Copyright 2014 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. + +// compile-flags:-Z verbose + +fn main() { + let x = [1,2]; + let y = match x { + [] => None, + //~^ ERROR types: expected `[_#0i, ..2]`, found `[_#7, ..0]` + // (expected array of 2 elements, found array of 0 elements) + [a,_] => Some(a) + }; +} diff --git a/src/test/compile-fail/issue-13482.rs b/src/test/compile-fail/issue-13482.rs index 0139a2ff7108d..e0b1f8845e236 100644 --- a/src/test/compile-fail/issue-13482.rs +++ b/src/test/compile-fail/issue-13482.rs @@ -12,7 +12,7 @@ fn main() { let x = [1,2]; let y = match x { [] => None, -//~^ ERROR types: expected `[_#0i, ..2]`, found `[_#7, ..0]` +//~^ ERROR types: expected `[_#i, ..2]`, found `[_, ..0]` // (expected array of 2 elements, found array of 0 elements) [a,_] => Some(a) }; diff --git a/src/test/compile-fail/issue-3680.rs b/src/test/compile-fail/issue-3680.rs index a23f76bd15b26..f018a02a945a9 100644 --- a/src/test/compile-fail/issue-3680.rs +++ b/src/test/compile-fail/issue-3680.rs @@ -11,7 +11,7 @@ fn main() { match None { Err(_) => () - //~^ ERROR mismatched types: expected `core::option::Option<_#1>` - // , found `core::result::Result<_#2, _#3>` + //~^ ERROR mismatched types: expected `core::option::Option<_>` + // , found `core::result::Result<_, _>` } } diff --git a/src/test/compile-fail/issue-4201.rs b/src/test/compile-fail/issue-4201.rs index 69bcfc019c096..5899fa43a4821 100644 --- a/src/test/compile-fail/issue-4201.rs +++ b/src/test/compile-fail/issue-4201.rs @@ -12,7 +12,7 @@ fn main() { let a = if true { 0 } else if false { -//~^ ERROR if may be missing an else clause: expected `()`, found `_#1i` +//~^ ERROR if may be missing an else clause: expected `()`, found `_#i` 1 }; } diff --git a/src/test/compile-fail/issue-4968.rs b/src/test/compile-fail/issue-4968.rs index 8311d6fd563c4..54fd9d492bfcb 100644 --- a/src/test/compile-fail/issue-4968.rs +++ b/src/test/compile-fail/issue-4968.rs @@ -13,6 +13,6 @@ const A: (int,int) = (4,2); fn main() { match 42 { A => () } - //~^ ERROR mismatched types: expected `_#0i`, found `(int, int)` + //~^ ERROR mismatched types: expected `_#i`, found `(int, int)` // (expected integral variable, found tuple) } diff --git a/src/test/compile-fail/issue-5100.rs b/src/test/compile-fail/issue-5100.rs index be7bd248614ce..ddd82af01a71e 100644 --- a/src/test/compile-fail/issue-5100.rs +++ b/src/test/compile-fail/issue-5100.rs @@ -19,7 +19,7 @@ fn main() { match (true, false) { (true, false, false) => () -//~^ ERROR mismatched types: expected `(bool, bool)`, found `(_#9, _#10, _#11)` +//~^ ERROR mismatched types: expected `(bool, bool)`, found `(_, _, _)` } match (true, false) { diff --git a/src/test/compile-fail/repeat_count.rs b/src/test/compile-fail/repeat_count.rs index 6a1603fbfcbff..0d4dab9916dcf 100644 --- a/src/test/compile-fail/repeat_count.rs +++ b/src/test/compile-fail/repeat_count.rs @@ -18,7 +18,7 @@ fn main() { let c = [0, ..true]; //~ ERROR expected positive integer for repeat count, found boolean //~^ ERROR: expected `uint`, found `bool` let d = [0, ..0.5]; //~ ERROR expected positive integer for repeat count, found float - //~^ ERROR: expected `uint`, found `_#0f` + //~^ ERROR: expected `uint`, found `_#f` let e = [0, .."foo"]; //~ ERROR expected positive integer for repeat count, found string //~^ ERROR: expected `uint`, found `&'static str` let f = [0, ..-4]; diff --git a/src/test/compile-fail/slightly-nice-generic-literal-messages.rs b/src/test/compile-fail/slightly-nice-generic-literal-messages.rs index 02ebbb134f0ee..3ac3988bad2bd 100644 --- a/src/test/compile-fail/slightly-nice-generic-literal-messages.rs +++ b/src/test/compile-fail/slightly-nice-generic-literal-messages.rs @@ -13,7 +13,7 @@ struct Foo(T); fn main() { match Foo(1.1) { 1 => {} - //~^ ERROR expected `Foo<_#0f, _#2>`, found `_#0i` + //~^ ERROR expected `Foo<_#f, _>`, found `_#i` } } diff --git a/src/test/compile-fail/suppressed-error.rs b/src/test/compile-fail/suppressed-error.rs index bd9f2c3632846..27f50be528c56 100644 --- a/src/test/compile-fail/suppressed-error.rs +++ b/src/test/compile-fail/suppressed-error.rs @@ -10,6 +10,6 @@ fn main() { let (x, y) = (); -//~^ ERROR expected `()`, found `(_#3, _#4)` (expected (), found tuple) +//~^ ERROR expected `()`, found `(_, _)` (expected (), found tuple) return x; } From 3cbc3f4802b9dd8125f2605cf4dab7a18839c4e8 Mon Sep 17 00:00:00 2001 From: Jakub Bukaj Date: Thu, 30 Oct 2014 21:16:52 +0100 Subject: [PATCH 5/7] Add a test for failure to unify type parameters --- src/test/compile-fail/type-parameter-names.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/test/compile-fail/type-parameter-names.rs b/src/test/compile-fail/type-parameter-names.rs index e1a29afa737c8..42691fa522903 100644 --- a/src/test/compile-fail/type-parameter-names.rs +++ b/src/test/compile-fail/type-parameter-names.rs @@ -11,6 +11,9 @@ // Test that we print out the names of type parameters correctly in // our error messages. -fn foo(x: Foo) -> Bar { x } //~ ERROR expected `Bar`, found `Foo` +fn foo(x: Foo) -> Bar { + x +//~^ ERROR expected `Bar`, found `Foo` (expected type parameter, found a different type parameter) +} fn main() {} From cac995444b69cb1453bc2be1fd5de27f110c0e01 Mon Sep 17 00:00:00 2001 From: Jakub Bukaj Date: Thu, 30 Oct 2014 21:29:13 +0100 Subject: [PATCH 6/7] Add a test for errors unifying an integer variable with a float variable --- .../integral-variable-unification-error.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/test/compile-fail/integral-variable-unification-error.rs diff --git a/src/test/compile-fail/integral-variable-unification-error.rs b/src/test/compile-fail/integral-variable-unification-error.rs new file mode 100644 index 0000000000000..fbbe4cf8dbc4b --- /dev/null +++ b/src/test/compile-fail/integral-variable-unification-error.rs @@ -0,0 +1,15 @@ +// Copyright 2014 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 mut x = 2; + x = 5.0; +//~^ ERROR expected `_`, found `_` (expected integral variable, found floating-point variable) +} From a2624fc90891b8265550229e38bc255e61a9d335 Mon Sep 17 00:00:00 2001 From: Jakub Bukaj Date: Thu, 30 Oct 2014 21:17:06 +0100 Subject: [PATCH 7/7] Use the `_` representation for integral variables as well --- src/librustc/util/ppaux.rs | 5 ++--- src/test/compile-fail/issue-13482.rs | 2 +- src/test/compile-fail/issue-4201.rs | 2 +- src/test/compile-fail/issue-4968.rs | 2 +- src/test/compile-fail/repeat_count.rs | 2 +- .../compile-fail/slightly-nice-generic-literal-messages.rs | 2 +- 6 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 633a350ddb2a4..8befba00fd2fe 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -376,9 +376,8 @@ pub fn ty_to_string(cx: &ctxt, typ: t) -> String { format!("_#{}i", vid), ty::FloatVar(ty::FloatVid { index: vid }) if print_var_ids => format!("_#{}f", vid), - ty::TyVar(_) => "_".to_string(), - ty::IntVar(_) => "_#i".to_string(), - ty::FloatVar(_) => "_#f".to_string(), + ty::TyVar(_) | ty::IntVar(_) | ty::FloatVar(_) => + "_".to_string(), ty::SkolemizedTy(v) => format!("SkolemizedTy({})", v), ty::SkolemizedIntTy(v) => format!("SkolemizedIntTy({})", v) } diff --git a/src/test/compile-fail/issue-13482.rs b/src/test/compile-fail/issue-13482.rs index e0b1f8845e236..18070ed53b04a 100644 --- a/src/test/compile-fail/issue-13482.rs +++ b/src/test/compile-fail/issue-13482.rs @@ -12,7 +12,7 @@ fn main() { let x = [1,2]; let y = match x { [] => None, -//~^ ERROR types: expected `[_#i, ..2]`, found `[_, ..0]` +//~^ ERROR types: expected `[_, ..2]`, found `[_, ..0]` // (expected array of 2 elements, found array of 0 elements) [a,_] => Some(a) }; diff --git a/src/test/compile-fail/issue-4201.rs b/src/test/compile-fail/issue-4201.rs index 5899fa43a4821..0391c73d90a6c 100644 --- a/src/test/compile-fail/issue-4201.rs +++ b/src/test/compile-fail/issue-4201.rs @@ -12,7 +12,7 @@ fn main() { let a = if true { 0 } else if false { -//~^ ERROR if may be missing an else clause: expected `()`, found `_#i` +//~^ ERROR if may be missing an else clause: expected `()`, found `_` 1 }; } diff --git a/src/test/compile-fail/issue-4968.rs b/src/test/compile-fail/issue-4968.rs index 54fd9d492bfcb..cf1f1f5908954 100644 --- a/src/test/compile-fail/issue-4968.rs +++ b/src/test/compile-fail/issue-4968.rs @@ -13,6 +13,6 @@ const A: (int,int) = (4,2); fn main() { match 42 { A => () } - //~^ ERROR mismatched types: expected `_#i`, found `(int, int)` + //~^ ERROR mismatched types: expected `_`, found `(int, int)` // (expected integral variable, found tuple) } diff --git a/src/test/compile-fail/repeat_count.rs b/src/test/compile-fail/repeat_count.rs index 0d4dab9916dcf..be79a7a915b88 100644 --- a/src/test/compile-fail/repeat_count.rs +++ b/src/test/compile-fail/repeat_count.rs @@ -18,7 +18,7 @@ fn main() { let c = [0, ..true]; //~ ERROR expected positive integer for repeat count, found boolean //~^ ERROR: expected `uint`, found `bool` let d = [0, ..0.5]; //~ ERROR expected positive integer for repeat count, found float - //~^ ERROR: expected `uint`, found `_#f` + //~^ ERROR: expected `uint`, found `_` let e = [0, .."foo"]; //~ ERROR expected positive integer for repeat count, found string //~^ ERROR: expected `uint`, found `&'static str` let f = [0, ..-4]; diff --git a/src/test/compile-fail/slightly-nice-generic-literal-messages.rs b/src/test/compile-fail/slightly-nice-generic-literal-messages.rs index 3ac3988bad2bd..a655a17c037d2 100644 --- a/src/test/compile-fail/slightly-nice-generic-literal-messages.rs +++ b/src/test/compile-fail/slightly-nice-generic-literal-messages.rs @@ -13,7 +13,7 @@ struct Foo(T); fn main() { match Foo(1.1) { 1 => {} - //~^ ERROR expected `Foo<_#f, _>`, found `_#i` + //~^ ERROR expected `Foo<_, _>`, found `_` } }