1
Fork 0

auto merge of #15615 : jakub-/rust/diagnostics, r=brson

This commit is contained in:
bors 2014-07-15 21:06:12 +00:00
commit de111e69a8
11 changed files with 410 additions and 390 deletions

View file

@ -16,3 +16,99 @@ register_diagnostic!(E0001, r##"
This means that perhaps some of the preceeding patterns are too general, this This means that perhaps some of the preceeding patterns are too general, this
one is too specific or the ordering is incorrect. one is too specific or the ordering is incorrect.
"##) "##)
register_diagnostics!(
E0002,
E0003,
E0004,
E0005,
E0006,
E0007,
E0008,
E0009,
E0010,
E0011,
E0012,
E0013,
E0014,
E0015,
E0016,
E0017,
E0018,
E0019,
E0020,
E0021,
E0022,
E0023,
E0024,
E0025,
E0026,
E0027,
E0028,
E0029,
E0030,
E0031,
E0032,
E0033,
E0034,
E0035,
E0036,
E0037,
E0038,
E0039,
E0040,
E0041,
E0042,
E0043,
E0044,
E0045,
E0046,
E0047,
E0048,
E0049,
E0050,
E0051,
E0052,
E0053,
E0054,
E0055,
E0056,
E0057,
E0058,
E0059,
E0060,
E0061,
E0062,
E0063,
E0064,
E0065,
E0066,
E0067,
E0068,
E0069,
E0070,
E0071,
E0072,
E0073,
E0074,
E0075,
E0076,
E0077,
E0078,
E0079,
E0080,
E0081,
E0082,
E0083,
E0084,
E0085,
E0086,
E0087,
E0088,
E0089,
E0090,
E0091,
E0092,
E0093,
E0094
)

View file

@ -85,6 +85,9 @@ impl Session {
pub fn span_warn(&self, sp: Span, msg: &str) { pub fn span_warn(&self, sp: Span, msg: &str) {
self.diagnostic().span_warn(sp, msg) self.diagnostic().span_warn(sp, msg)
} }
pub fn span_warn_with_code(&self, sp: Span, msg: &str, code: &str) {
self.diagnostic().span_warn_with_code(sp, msg, code)
}
pub fn warn(&self, msg: &str) { pub fn warn(&self, msg: &str) {
self.diagnostic().handler().warn(msg) self.diagnostic().handler().warn(msg)
} }

View file

@ -87,28 +87,25 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &Expr, is_const: bool) {
match e.node { match e.node {
ExprUnary(UnDeref, _) => { } ExprUnary(UnDeref, _) => { }
ExprUnary(UnBox, _) | ExprUnary(UnUniq, _) => { ExprUnary(UnBox, _) | ExprUnary(UnUniq, _) => {
v.tcx.sess.span_err(e.span, span_err!(v.tcx.sess, e.span, E0010, "cannot do allocations in constant expressions");
"cannot do allocations in constant expressions");
return; return;
} }
ExprLit(lit) if ast_util::lit_is_str(lit) => {} ExprLit(lit) if ast_util::lit_is_str(lit) => {}
ExprBinary(..) | ExprUnary(..) => { ExprBinary(..) | ExprUnary(..) => {
let method_call = typeck::MethodCall::expr(e.id); let method_call = typeck::MethodCall::expr(e.id);
if v.tcx.method_map.borrow().contains_key(&method_call) { if v.tcx.method_map.borrow().contains_key(&method_call) {
v.tcx.sess.span_err(e.span, "user-defined operators are not \ span_err!(v.tcx.sess, e.span, E0011,
allowed in constant expressions"); "user-defined operators are not allowed in constant expressions");
} }
} }
ExprLit(_) => (), ExprLit(_) => (),
ExprCast(_, _) => { ExprCast(_, _) => {
let ety = ty::expr_ty(v.tcx, e); let ety = ty::expr_ty(v.tcx, e);
if !ty::type_is_numeric(ety) && !ty::type_is_unsafe_ptr(ety) { if !ty::type_is_numeric(ety) && !ty::type_is_unsafe_ptr(ety) {
v.tcx span_err!(v.tcx.sess, e.span, E0012,
.sess "can not cast to `{}` in a constant expression",
.span_err(e.span, ppaux::ty_to_string(v.tcx, ety)
format!("can not cast to `{}` in a constant \ );
expression",
ppaux::ty_to_string(v.tcx, ety)).as_slice())
} }
} }
ExprPath(ref pth) => { ExprPath(ref pth) => {
@ -117,9 +114,8 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &Expr, is_const: bool) {
// foo::<bar> in a const. Currently that is only done on // foo::<bar> in a const. Currently that is only done on
// a path in trans::callee that only works in block contexts. // a path in trans::callee that only works in block contexts.
if !pth.segments.iter().all(|segment| segment.types.is_empty()) { if !pth.segments.iter().all(|segment| segment.types.is_empty()) {
v.tcx.sess.span_err(e.span, span_err!(v.tcx.sess, e.span, E0013,
"paths in constants may only refer to \ "paths in constants may only refer to items without type parameters");
items without type parameters");
} }
match v.tcx.def_map.borrow().find(&e.id) { match v.tcx.def_map.borrow().find(&e.id) {
Some(&DefStatic(..)) | Some(&DefStatic(..)) |
@ -129,9 +125,8 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &Expr, is_const: bool) {
Some(&def) => { Some(&def) => {
debug!("(checking const) found bad def: {:?}", def); debug!("(checking const) found bad def: {:?}", def);
v.tcx.sess.span_err(e.span, span_err!(v.tcx.sess, e.span, E0014,
"paths in constants may only refer to \ "paths in constants may only refer to constants or functions");
constants or functions");
} }
None => { None => {
v.tcx.sess.span_bug(e.span, "unbound path in const?!"); v.tcx.sess.span_bug(e.span, "unbound path in const?!");
@ -143,9 +138,8 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &Expr, is_const: bool) {
Some(&DefStruct(..)) => {} // OK. Some(&DefStruct(..)) => {} // OK.
Some(&DefVariant(..)) => {} // OK. Some(&DefVariant(..)) => {} // OK.
_ => { _ => {
v.tcx.sess.span_err(e.span, span_err!(v.tcx.sess, e.span, E0015,
"function calls in constants are limited to \ "function calls in constants are limited to struct and enum constructors");
struct and enum constructors");
} }
} }
} }
@ -153,9 +147,8 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &Expr, is_const: bool) {
// Check all statements in the block // Check all statements in the block
for stmt in block.stmts.iter() { for stmt in block.stmts.iter() {
let block_span_err = |span| let block_span_err = |span|
v.tcx.sess.span_err(span, span_err!(v.tcx.sess, span, E0016,
"blocks in constants are limited to \ "blocks in constants are limited to items and tail expressions");
items and tail expressions");
match stmt.node { match stmt.node {
StmtDecl(ref span, _) => { StmtDecl(ref span, _) => {
match span.node { match span.node {
@ -187,16 +180,16 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &Expr, is_const: bool) {
ExprRepeat(..) | ExprRepeat(..) |
ExprStruct(..) => { } ExprStruct(..) => { }
ExprAddrOf(..) => { ExprAddrOf(..) => {
v.tcx.sess.span_err(e.span, span_err!(v.tcx.sess, e.span, E0017,
"references in constants may only refer to \ "references in constants may only refer to immutable values");
immutable values");
}, },
ExprVstore(_, ExprVstoreUniq) => { ExprVstore(_, ExprVstoreUniq) => {
v.tcx.sess.span_err(e.span, "cannot allocate vectors in constant expressions") span_err!(v.tcx.sess, e.span, E0018,
"cannot allocate vectors in constant expressions");
}, },
_ => { _ => {
v.tcx.sess.span_err(e.span, span_err!(v.tcx.sess, e.span, E0019,
"constant contains unimplemented expression type"); "constant contains unimplemented expression type");
return; return;
} }

View file

@ -142,12 +142,13 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &Expr) {
// Finally, check if the whole match expression is exhaustive. // Finally, check if the whole match expression is exhaustive.
// Check for empty enum, because is_useful only works on inhabited types. // Check for empty enum, because is_useful only works on inhabited types.
let pat_ty = node_id_to_type(cx.tcx, scrut.id); let pat_ty = node_id_to_type(cx.tcx, scrut.id);
if (*arms).is_empty() { if arms.is_empty() {
if !type_is_empty(cx.tcx, pat_ty) { if !type_is_empty(cx.tcx, pat_ty) {
// We know the type is inhabited, so this must be wrong // We know the type is inhabited, so this must be wrong
cx.tcx.sess.span_err(ex.span, format!("non-exhaustive patterns: \ span_err!(cx.tcx.sess, ex.span, E0002,
type {} is non-empty", "non-exhaustive patterns: type {} is non-empty",
ty_to_string(cx.tcx, pat_ty)).as_slice()); ty_to_string(cx.tcx, pat_ty)
);
} }
// If the type *is* empty, it's vacuously exhaustive // If the type *is* empty, it's vacuously exhaustive
return; return;
@ -186,8 +187,9 @@ fn check_arms(cx: &MatchCheckCtxt, arms: &[Arm]) {
walk_pat(&**pat, |p| { walk_pat(&**pat, |p| {
if pat_matches_nan(p) { if pat_matches_nan(p) {
cx.tcx.sess.span_warn(p.span, "unmatchable NaN in pattern, \ span_warn!(cx.tcx.sess, p.span, E0003,
use the is_nan method in a guard instead"); "unmatchable NaN in pattern, use the is_nan method in a guard instead"
);
} }
true true
}); });
@ -222,9 +224,10 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, m: &Matrix) {
[] => wild(), [] => wild(),
_ => unreachable!() _ => unreachable!()
}; };
let msg = format!("non-exhaustive patterns: `{0}` not covered", span_err!(cx.tcx.sess, sp, E0004,
pat_to_string(&*witness)); "non-exhaustive patterns: `{}` not covered",
cx.tcx.sess.span_err(sp, msg.as_slice()); pat_to_string(&*witness)
);
} }
NotUseful => { NotUseful => {
// This is good, wildcard pattern isn't reachable // This is good, wildcard pattern isn't reachable
@ -779,11 +782,10 @@ fn check_local(cx: &mut MatchCheckCtxt, loc: &Local) {
match is_refutable(cx, loc.pat) { match is_refutable(cx, loc.pat) {
Some(pat) => { Some(pat) => {
let msg = format!( span_err!(cx.tcx.sess, loc.pat.span, E0005,
"refutable pattern in {} binding: `{}` not covered", "refutable pattern in {} binding: `{}` not covered",
name, pat_to_string(&*pat) name, pat_to_string(&*pat)
); );
cx.tcx.sess.span_err(loc.pat.span, msg.as_slice());
}, },
None => () None => ()
} }
@ -801,11 +803,10 @@ fn check_fn(cx: &mut MatchCheckCtxt,
for input in decl.inputs.iter() { for input in decl.inputs.iter() {
match is_refutable(cx, input.pat) { match is_refutable(cx, input.pat) {
Some(pat) => { Some(pat) => {
let msg = format!( span_err!(cx.tcx.sess, input.pat.span, E0006,
"refutable pattern in function argument: `{}` not covered", "refutable pattern in function argument: `{}` not covered",
pat_to_string(&*pat) pat_to_string(&*pat)
); );
cx.tcx.sess.span_err(input.pat.span, msg.as_slice());
}, },
None => () None => ()
} }
@ -850,21 +851,13 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
// x @ Foo(..) is legal, but x @ Foo(y) isn't. // x @ Foo(..) is legal, but x @ Foo(y) isn't.
if sub.map_or(false, |p| pat_contains_bindings(def_map, &*p)) { if sub.map_or(false, |p| pat_contains_bindings(def_map, &*p)) {
tcx.sess.span_err( span_err!(cx.tcx.sess, p.span, E0007, "cannot bind by-move with sub-bindings");
p.span,
"cannot bind by-move with sub-bindings");
} else if has_guard { } else if has_guard {
tcx.sess.span_err( span_err!(cx.tcx.sess, p.span, E0008, "cannot bind by-move into a pattern guard");
p.span,
"cannot bind by-move into a pattern guard");
} else if by_ref_span.is_some() { } else if by_ref_span.is_some() {
tcx.sess.span_err( span_err!(cx.tcx.sess, p.span, E0009,
p.span, "cannot bind by-move and by-ref in the same pattern");
"cannot bind by-move and by-ref \ span_note!(cx.tcx.sess, by_ref_span.unwrap(), "by-ref binding occurs here");
in the same pattern");
tcx.sess.span_note(
by_ref_span.unwrap(),
"by-ref binding occurs here");
} }
}; };

View file

@ -112,17 +112,17 @@ impl<'a> Visitor<bool> for CheckStaticVisitor<'a> {
visit::walk_expr(self, e, is_const); visit::walk_expr(self, e, is_const);
} }
ast::ExprVstore(_, ast::ExprVstoreMutSlice) => { ast::ExprVstore(_, ast::ExprVstoreMutSlice) => {
self.tcx.sess.span_err(e.span, span_err!(self.tcx.sess, e.span, E0020,
"static items are not allowed to have mutable slices"); "static items are not allowed to have mutable slices");
}, },
ast::ExprUnary(ast::UnBox, _) => { ast::ExprUnary(ast::UnBox, _) => {
self.tcx.sess.span_err(e.span, span_err!(self.tcx.sess, e.span, E0021,
"static items are not allowed to have managed pointers"); "static items are not allowed to have managed pointers");
} }
ast::ExprBox(..) | ast::ExprBox(..) |
ast::ExprUnary(ast::UnUniq, _) | ast::ExprUnary(ast::UnUniq, _) |
ast::ExprVstore(_, ast::ExprVstoreUniq) => { ast::ExprVstore(_, ast::ExprVstoreUniq) => {
self.tcx.sess.span_err(e.span, span_err!(self.tcx.sess, e.span, E0022,
"static items are not allowed to have custom pointers"); "static items are not allowed to have custom pointers");
} }
_ => { _ => {

View file

@ -253,14 +253,10 @@ pub fn check_pat_variant(pcx: &pat_ctxt, pat: &ast::Pat, path: &ast::Path,
if arg_len > 0 { if arg_len > 0 {
// N-ary variant. // N-ary variant.
if arg_len != subpats_len { if arg_len != subpats_len {
let s = format!("this pattern has {} field{}, \ span_err!(tcx.sess, pat.span, E0023,
but the corresponding {} has {} field{}", "this pattern has {} field{}, but the corresponding {} has {} field{}",
subpats_len, subpats_len, if subpats_len == 1 {""} else {"s"},
if subpats_len == 1 {""} else {"s"}, kind_name, arg_len, if arg_len == 1 {""} else {"s"});
kind_name,
arg_len,
if arg_len == 1 {""} else {"s"});
tcx.sess.span_err(pat.span, s.as_slice());
error_happened = true; error_happened = true;
} }
@ -272,12 +268,10 @@ pub fn check_pat_variant(pcx: &pat_ctxt, pat: &ast::Pat, path: &ast::Path,
} }
} }
} else if subpats_len > 0 { } else if subpats_len > 0 {
tcx.sess.span_err(pat.span, span_err!(tcx.sess, pat.span, E0024,
format!("this pattern has {} field{}, \ "this pattern has {} field{}, but the corresponding {} has no fields",
but the corresponding {} has no fields", subpats_len, if subpats_len == 1 {""} else {"s"},
subpats_len, kind_name);
if subpats_len == 1 {""} else {"s"},
kind_name).as_slice());
error_happened = true; error_happened = true;
} }
@ -321,9 +315,9 @@ pub fn check_struct_pat_fields(pcx: &pat_ctxt,
// Check the pattern anyway, so that attempts to look // Check the pattern anyway, so that attempts to look
// up its type won't fail // up its type won't fail
check_pat(pcx, &*field.pat, ty::mk_err()); check_pat(pcx, &*field.pat, ty::mk_err());
tcx.sess.span_err(span, span_err!(tcx.sess, span, E0025,
format!("field `{}` bound twice in pattern", "field `{}` bound twice in pattern",
token::get_ident(field.ident)).as_slice()); token::get_ident(field.ident));
} }
Some(&(index, ref mut used)) => { Some(&(index, ref mut used)) => {
*used = true; *used = true;
@ -339,10 +333,10 @@ pub fn check_struct_pat_fields(pcx: &pat_ctxt,
// Check the pattern anyway, so that attempts to look // Check the pattern anyway, so that attempts to look
// up its type won't fail // up its type won't fail
check_pat(pcx, &*field.pat, ty::mk_err()); check_pat(pcx, &*field.pat, ty::mk_err());
tcx.sess.span_err(span, span_err!(tcx.sess, span, E0026,
format!("struct `{}` does not have a field named `{}`", "struct `{}` does not have a field named `{}`",
ty::item_path_str(tcx, class_id), ty::item_path_str(tcx, class_id),
token::get_ident(field.ident)).as_slice()); token::get_ident(field.ident));
} }
} }
} }
@ -353,11 +347,9 @@ pub fn check_struct_pat_fields(pcx: &pat_ctxt,
if found_fields.contains(&i) { if found_fields.contains(&i) {
continue; continue;
} }
span_err!(tcx.sess, span, E0027,
tcx.sess "pattern does not mention field `{}`",
.span_err(span, token::get_name(field.name));
format!("pattern does not mention field `{}`",
token::get_name(field.name)).as_slice());
} }
} }
} }
@ -400,11 +392,9 @@ pub fn check_struct_like_enum_variant_pat(pcx: &pat_ctxt,
} }
Some(&def::DefStruct(..)) | Some(&def::DefVariant(..)) => { Some(&def::DefStruct(..)) | Some(&def::DefVariant(..)) => {
let name = pprust::path_to_string(path); let name = pprust::path_to_string(path);
tcx.sess.span_err(span, span_err!(tcx.sess, span, E0028,
format!("mismatched types: expected `{}` but \ "mismatched types: expected `{}` but found `{}`",
found `{}`", fcx.infcx().ty_to_string(expected), name);
fcx.infcx().ty_to_string(expected),
name).as_slice());
} }
_ => { _ => {
tcx.sess.span_bug(span, "resolve didn't write in variant"); tcx.sess.span_bug(span, "resolve didn't write in variant");
@ -441,16 +431,16 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) {
{ {
// no-op // no-op
} else if !ty::type_is_numeric(b_ty) && !ty::type_is_char(b_ty) { } else if !ty::type_is_numeric(b_ty) && !ty::type_is_char(b_ty) {
tcx.sess.span_err(pat.span, span_err!(tcx.sess, begin.span, E0029,
"only char and numeric types are allowed in range"); "only char and numeric types are allowed in range");
} else { } else {
match valid_range_bounds(fcx.ccx, &**begin, &**end) { match valid_range_bounds(fcx.ccx, &**begin, &**end) {
Some(false) => { Some(false) => {
tcx.sess.span_err(begin.span, span_err!(tcx.sess, begin.span, E0030,
"lower range bound must be less than upper"); "lower range bound must be less than upper");
}, },
None => { None => {
tcx.sess.span_err(begin.span, span_err!(tcx.sess, begin.span, E0031,
"mismatched types in range"); "mismatched types in range");
}, },
_ => { }, _ => { },
@ -521,13 +511,10 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) {
ty::ty_to_def_id( ty::ty_to_def_id(
ty::lookup_item_type(tcx, item_did).ty).unwrap(); ty::lookup_item_type(tcx, item_did).ty).unwrap();
if struct_did != cid { if struct_did != cid {
tcx.sess span_err!(tcx.sess, pat.span, E0032,
.span_err(path.span, "`{}` does not name the structure `{}`",
format!("`{}` does not name the \
structure `{}`",
pprust::path_to_string(path), pprust::path_to_string(path),
fcx.infcx() fcx.infcx().ty_to_string(expected));
.ty_to_string(expected)).as_slice())
} }
check_struct_pat(pcx, pat.id, pat.span, expected, path, check_struct_pat(pcx, pat.id, pat.span, expected, path,
@ -744,10 +731,9 @@ fn check_pointer_pat(pcx: &pat_ctxt,
// This is "x = SomeTrait" being reduced from // This is "x = SomeTrait" being reduced from
// "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error. // "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
check_pat(pcx, inner, ty::mk_err()); check_pat(pcx, inner, ty::mk_err());
tcx.sess.span_err( span_err!(tcx.sess, span, E0033,
span, "type `{}` cannot be dereferenced",
format!("type `{}` cannot be dereferenced", fcx.infcx().ty_to_string(expected));
fcx.infcx().ty_to_string(expected)).as_slice());
fcx.write_error(pat_id); fcx.write_error(pat_id);
} }
_ => { _ => {

View file

@ -1041,8 +1041,7 @@ impl<'a> LookupContext<'a> {
} }
if relevant_candidates.len() > 1 { if relevant_candidates.len() > 1 {
self.tcx().sess.span_err( span_err!(self.tcx().sess, self.span, E0034,
self.span,
"multiple applicable methods in scope"); "multiple applicable methods in scope");
for (idx, candidate) in relevant_candidates.iter().enumerate() { for (idx, candidate) in relevant_candidates.iter().enumerate() {
self.report_candidate(idx, &candidate.origin); self.report_candidate(idx, &candidate.origin);
@ -1112,13 +1111,11 @@ impl<'a> LookupContext<'a> {
if num_supplied_tps == 0u { if num_supplied_tps == 0u {
self.fcx.infcx().next_ty_vars(num_method_tps) self.fcx.infcx().next_ty_vars(num_method_tps)
} else if num_method_tps == 0u { } else if num_method_tps == 0u {
tcx.sess.span_err( span_err!(tcx.sess, self.span, E0035,
self.span, "does not take type parameters");
"this method does not take type parameters");
self.fcx.infcx().next_ty_vars(num_method_tps) self.fcx.infcx().next_ty_vars(num_method_tps)
} else if num_supplied_tps != num_method_tps { } else if num_supplied_tps != num_method_tps {
tcx.sess.span_err( span_err!(tcx.sess, self.span, E0036,
self.span,
"incorrect number of type parameters given for this method"); "incorrect number of type parameters given for this method");
self.fcx.infcx().next_ty_vars(num_method_tps) self.fcx.infcx().next_ty_vars(num_method_tps)
} else { } else {
@ -1221,10 +1218,8 @@ impl<'a> LookupContext<'a> {
match candidate.method_ty.explicit_self { match candidate.method_ty.explicit_self {
ast::SelfStatic => { // reason (a) above ast::SelfStatic => { // reason (a) above
self.tcx().sess.span_err( span_err!(self.tcx().sess, self.span, E0037,
self.span, "cannot call a method without a receiver through an object");
"cannot call a method without a receiver \
through an object");
} }
ast::SelfValue(_) | ast::SelfRegion(..) | ast::SelfUniq(_) => {} ast::SelfValue(_) | ast::SelfRegion(..) | ast::SelfUniq(_) => {}
@ -1233,8 +1228,7 @@ impl<'a> LookupContext<'a> {
// reason (a) above // reason (a) above
let check_for_self_ty = |ty| { let check_for_self_ty = |ty| {
if ty::type_has_self(ty) { if ty::type_has_self(ty) {
self.tcx().sess.span_err( span_err!(self.tcx().sess, self.span, E0038,
self.span,
"cannot call a method whose type contains a \ "cannot call a method whose type contains a \
self-type through an object"); self-type through an object");
true true
@ -1256,8 +1250,7 @@ impl<'a> LookupContext<'a> {
if candidate.method_ty.generics.has_type_params(subst::FnSpace) { if candidate.method_ty.generics.has_type_params(subst::FnSpace) {
// reason (b) above // reason (b) above
self.tcx().sess.span_err( span_err!(self.tcx().sess, self.span, E0039,
self.span,
"cannot call a generic method through an object"); "cannot call a generic method through an object");
} }
} }
@ -1279,7 +1272,7 @@ impl<'a> LookupContext<'a> {
} }
if bad { if bad {
self.tcx().sess.span_err(self.span, span_err!(self.tcx().sess, self.span, E0040,
"explicit call to destructor"); "explicit call to destructor");
} }
} }
@ -1425,28 +1418,22 @@ impl<'a> LookupContext<'a> {
} else { } else {
self.span self.span
}; };
self.tcx().sess.span_note( span_note!(self.tcx().sess, span,
span, "candidate #{} is `{}`",
format!("candidate #{} is `{}`", idx + 1u, ty::item_path_str(self.tcx(), did));
idx + 1u,
ty::item_path_str(self.tcx(), did)).as_slice());
} }
fn report_param_candidate(&self, idx: uint, did: DefId) { fn report_param_candidate(&self, idx: uint, did: DefId) {
self.tcx().sess.span_note( span_note!(self.tcx().sess, self.span,
self.span, "candidate #{} derives from the bound `{}`",
format!("candidate #{} derives from the bound `{}`", idx + 1u, ty::item_path_str(self.tcx(), did));
idx + 1u,
ty::item_path_str(self.tcx(), did)).as_slice());
} }
fn report_trait_candidate(&self, idx: uint, did: DefId) { fn report_trait_candidate(&self, idx: uint, did: DefId) {
self.tcx().sess.span_note( span_note!(self.tcx().sess, self.span,
self.span, "candidate #{} derives from the type of the receiver, \
format!("candidate #{} derives from the type of the receiver, \
which is the trait `{}`", which is the trait `{}`",
idx + 1u, idx + 1u, ty::item_path_str(self.tcx(), did));
ty::item_path_str(self.tcx(), did)).as_slice());
} }
fn infcx(&'a self) -> &'a infer::InferCtxt<'a> { fn infcx(&'a self) -> &'a infer::InferCtxt<'a> {

View file

@ -569,11 +569,10 @@ fn check_for_field_shadowing(tcx: &ty::ctxt,
for f in fields.iter() { for f in fields.iter() {
match super_fields.iter().find(|sf| f.name == sf.name) { match super_fields.iter().find(|sf| f.name == sf.name) {
Some(prev_field) => { Some(prev_field) => {
tcx.sess.span_err(span_for_field(tcx, f, id), span_err!(tcx.sess, span_for_field(tcx, f, id), E0041,
format!("field `{}` hides field declared in \ "field `{}` hides field declared in super-struct",
super-struct", token::get_name(f.name));
token::get_name(f.name)).as_slice()); span_note!(tcx.sess, span_for_field(tcx, prev_field, parent_id),
tcx.sess.span_note(span_for_field(tcx, prev_field, parent_id),
"previously declared here"); "previously declared here");
}, },
None => {} None => {}
@ -595,16 +594,16 @@ fn check_fields_sized(tcx: &ty::ctxt,
if !ty::type_is_sized(tcx, t) { if !ty::type_is_sized(tcx, t) {
match f.node.kind { match f.node.kind {
ast::NamedField(ident, _) => { ast::NamedField(ident, _) => {
tcx.sess.span_err( span_err!(tcx.sess, f.span, E0042,
f.span, "type `{}` is dynamically sized. \
format!("type `{}` is dynamically sized. \
dynamically sized types may only \ dynamically sized types may only \
appear as the type of the final \ appear as the type of the final \
field in a struct", field in a struct",
token::get_ident(ident)).as_slice()); token::get_ident(ident));
} }
ast::UnnamedField(_) => { ast::UnnamedField(_) => {
tcx.sess.span_err(f.span, "dynamically sized type in field"); span_err!(tcx.sess, f.span, E0043,
"dynamically sized type in field");
} }
} }
} }
@ -719,14 +718,15 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
for item in m.items.iter() { for item in m.items.iter() {
let pty = ty::lookup_item_type(ccx.tcx, local_def(item.id)); let pty = ty::lookup_item_type(ccx.tcx, local_def(item.id));
if !pty.generics.types.is_empty() { if !pty.generics.types.is_empty() {
ccx.tcx.sess.span_err(item.span, "foreign items may not have type parameters"); span_err!(ccx.tcx.sess, item.span, E0044,
"foreign items may not have type parameters");
} }
match item.node { match item.node {
ast::ForeignItemFn(ref fn_decl, _) => { ast::ForeignItemFn(ref fn_decl, _) => {
if fn_decl.variadic && m.abi != abi::C { if fn_decl.variadic && m.abi != abi::C {
ccx.tcx.sess.span_err( span_err!(ccx.tcx.sess, item.span, E0045,
item.span, "variadic function must have C calling convention"); "variadic function must have C calling convention");
} }
} }
_ => {} _ => {}
@ -828,10 +828,9 @@ fn check_impl_methods_against_trait(ccx: &CrateCtxt,
} }
if !missing_methods.is_empty() { if !missing_methods.is_empty() {
tcx.sess.span_err( span_err!(tcx.sess, impl_span, E0046,
impl_span, "not all trait methods implemented, missing: {}",
format!("not all trait methods implemented, missing: {}", missing_methods.connect(", "));
missing_methods.connect(", ")).as_slice());
} }
} }
@ -867,23 +866,17 @@ fn compare_impl_method(tcx: &ty::ctxt,
match (&trait_m.explicit_self, &impl_m.explicit_self) { match (&trait_m.explicit_self, &impl_m.explicit_self) {
(&ast::SelfStatic, &ast::SelfStatic) => {} (&ast::SelfStatic, &ast::SelfStatic) => {}
(&ast::SelfStatic, _) => { (&ast::SelfStatic, _) => {
tcx.sess.span_err( span_err!(tcx.sess, impl_m_span, E0047,
impl_m_span, "method `{}` has a `{}` declaration in the impl, but not in the trait",
format!("method `{}` has a `{}` declaration in the impl, \
but not in the trait",
token::get_ident(trait_m.ident), token::get_ident(trait_m.ident),
pprust::explicit_self_to_string( pprust::explicit_self_to_string(impl_m.explicit_self));
impl_m.explicit_self)).as_slice());
return; return;
} }
(_, &ast::SelfStatic) => { (_, &ast::SelfStatic) => {
tcx.sess.span_err( span_err!(tcx.sess, impl_m_span, E0048,
impl_m_span, "method `{}` has a `{}` declaration in the trait, but not in the impl",
format!("method `{}` has a `{}` declaration in the trait, \
but not in the impl",
token::get_ident(trait_m.ident), token::get_ident(trait_m.ident),
pprust::explicit_self_to_string( pprust::explicit_self_to_string(trait_m.explicit_self));
trait_m.explicit_self)).as_slice());
return; return;
} }
_ => { _ => {
@ -894,28 +887,26 @@ fn compare_impl_method(tcx: &ty::ctxt,
let num_impl_m_type_params = impl_m.generics.types.len(subst::FnSpace); let num_impl_m_type_params = impl_m.generics.types.len(subst::FnSpace);
let num_trait_m_type_params = trait_m.generics.types.len(subst::FnSpace); let num_trait_m_type_params = trait_m.generics.types.len(subst::FnSpace);
if num_impl_m_type_params != num_trait_m_type_params { if num_impl_m_type_params != num_trait_m_type_params {
tcx.sess.span_err( span_err!(tcx.sess, impl_m_span, E0049,
impl_m_span, "method `{}` has {} type parameter{} \
format!("method `{}` has {} type parameter{} \
but its trait declaration has {} type parameter{}", but its trait declaration has {} type parameter{}",
token::get_ident(trait_m.ident), token::get_ident(trait_m.ident),
num_impl_m_type_params, num_impl_m_type_params,
if num_impl_m_type_params == 1 {""} else {"s"}, if num_impl_m_type_params == 1 {""} else {"s"},
num_trait_m_type_params, num_trait_m_type_params,
if num_trait_m_type_params == 1 {""} else {"s"}).as_slice()); if num_trait_m_type_params == 1 {""} else {"s"});
return; return;
} }
if impl_m.fty.sig.inputs.len() != trait_m.fty.sig.inputs.len() { if impl_m.fty.sig.inputs.len() != trait_m.fty.sig.inputs.len() {
tcx.sess.span_err( span_err!(tcx.sess, impl_m_span, E0050,
impl_m_span, "method `{}` has {} parameter{} \
format!("method `{}` has {} parameter{} \
but the declaration in trait `{}` has {}", but the declaration in trait `{}` has {}",
token::get_ident(trait_m.ident), token::get_ident(trait_m.ident),
impl_m.fty.sig.inputs.len(), impl_m.fty.sig.inputs.len(),
if impl_m.fty.sig.inputs.len() == 1 {""} else {"s"}, if impl_m.fty.sig.inputs.len() == 1 {""} else {"s"},
ty::item_path_str(tcx, trait_m.def_id), ty::item_path_str(tcx, trait_m.def_id),
trait_m.fty.sig.inputs.len()).as_slice()); trait_m.fty.sig.inputs.len());
return; return;
} }
@ -1004,16 +995,13 @@ fn compare_impl_method(tcx: &ty::ctxt,
impl_param_def.bounds.builtin_bounds - impl_param_def.bounds.builtin_bounds -
trait_param_def.bounds.builtin_bounds; trait_param_def.bounds.builtin_bounds;
if !extra_bounds.is_empty() { if !extra_bounds.is_empty() {
tcx.sess.span_err( span_err!(tcx.sess, impl_m_span, E0051,
impl_m_span, "in method `{}`, type parameter {} requires `{}`, \
format!("in method `{}`, \ which is not required by the corresponding type parameter \
type parameter {} requires `{}`, \
which is not required by \
the corresponding type parameter \
in the trait declaration", in the trait declaration",
token::get_ident(trait_m.ident), token::get_ident(trait_m.ident),
i, i,
extra_bounds.user_string(tcx)).as_slice()); extra_bounds.user_string(tcx));
return; return;
} }
@ -1045,17 +1033,12 @@ fn compare_impl_method(tcx: &ty::ctxt,
} }
if !ok { if !ok {
tcx.sess.span_err(impl_m_span, span_err!(tcx.sess, impl_m_span, E0052,
format!("in method `{}`, type parameter {} \ "in method `{}`, type parameter {} requires bound `{}`, which is not \
requires bound `{}`, which is not \ required by the corresponding type parameter in the trait declaration",
required by the corresponding \
type parameter in the trait \
declaration",
token::get_ident(trait_m.ident), token::get_ident(trait_m.ident),
i, i,
ppaux::trait_ref_to_string( ppaux::trait_ref_to_string(tcx, &*impl_trait_bound));
tcx,
&*impl_trait_bound)).as_slice())
} }
} }
} }
@ -1073,11 +1056,10 @@ fn compare_impl_method(tcx: &ty::ctxt,
impl_fty, trait_fty) { impl_fty, trait_fty) {
Ok(()) => {} Ok(()) => {}
Err(ref terr) => { Err(ref terr) => {
tcx.sess.span_err( span_err!(tcx.sess, impl_m_span, E0053,
impl_m_span, "method `{}` has an incompatible type for trait: {}",
format!("method `{}` has an incompatible type for trait: {}",
token::get_ident(trait_m.ident), token::get_ident(trait_m.ident),
ty::type_err_to_str(tcx, terr)).as_slice()); ty::type_err_to_str(tcx, terr));
ty::note_and_explain_type_err(tcx, terr); ty::note_and_explain_type_err(tcx, terr);
} }
} }
@ -1164,9 +1146,7 @@ fn check_cast(fcx: &FnCtxt,
}, t_e, None); }, t_e, None);
} }
} else if ty::get(t_1).sty == ty::ty_bool { } else if ty::get(t_1).sty == ty::ty_bool {
fcx.tcx() span_err!(fcx.tcx().sess, span, E0054,
.sess
.span_err(span,
"cannot cast as `bool`, compare with zero instead"); "cannot cast as `bool`, compare with zero instead");
} else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) { } else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) {
fn types_compatible(fcx: &FnCtxt, sp: Span, fn types_compatible(fcx: &FnCtxt, sp: Span,
@ -1535,9 +1515,9 @@ pub fn autoderef<T>(fcx: &FnCtxt, sp: Span, base_ty: ty::t,
} }
// We've reached the recursion limit, error gracefully. // We've reached the recursion limit, error gracefully.
fcx.tcx().sess.span_err(sp, span_err!(fcx.tcx().sess, sp, E0055,
format!("reached the recursion limit while auto-dereferencing {}", "reached the recursion limit while auto-dereferencing {}",
base_ty.repr(fcx.tcx())).as_slice()); base_ty.repr(fcx.tcx()));
(ty::mk_err(), 0, None) (ty::mk_err(), 0, None)
} }
@ -1583,9 +1563,9 @@ fn try_overloaded_call(fcx: &FnCtxt,
write_call(fcx, call_expression, output_type); write_call(fcx, call_expression, output_type);
if !fcx.tcx().sess.features.overloaded_calls.get() { if !fcx.tcx().sess.features.overloaded_calls.get() {
fcx.tcx().sess.span_err(call_expression.span, span_err!(fcx.tcx().sess, call_expression.span, E0056,
"overloaded calls are experimental"); "overloaded calls are experimental");
fcx.tcx().sess.span_note(call_expression.span, span_note!(fcx.tcx().sess, call_expression.span,
"add `#[feature(overloaded_calls)]` to \ "add `#[feature(overloaded_calls)]` to \
the crate attributes to enable"); the crate attributes to enable");
} }
@ -1785,14 +1765,12 @@ fn check_argument_types(fcx: &FnCtxt,
match ty::get(tuple_type).sty { match ty::get(tuple_type).sty {
ty::ty_tup(ref arg_types) => { ty::ty_tup(ref arg_types) => {
if arg_types.len() != args.len() { if arg_types.len() != args.len() {
let msg = format!( span_err!(tcx.sess, sp, E0057,
"this function takes {} parameter{} \ "this function takes {} parameter{} but {} parameter{} supplied",
but {} parameter{} supplied",
arg_types.len(), arg_types.len(),
if arg_types.len() == 1 {""} else {"s"}, if arg_types.len() == 1 {""} else {"s"},
args.len(), args.len(),
if args.len() == 1 {" was"} else {"s were"}); if args.len() == 1 {" was"} else {"s were"});
tcx.sess.span_err(sp, msg.as_slice());
err_args(args.len()) err_args(args.len())
} else { } else {
(*arg_types).clone() (*arg_types).clone()
@ -1800,21 +1778,17 @@ fn check_argument_types(fcx: &FnCtxt,
} }
ty::ty_nil => { ty::ty_nil => {
if args.len() != 0 { if args.len() != 0 {
let msg = format!( span_err!(tcx.sess, sp, E0058,
"this function takes 0 parameters \ "this function takes 0 parameters but {} parameter{} supplied",
but {} parameter{} supplied",
args.len(), args.len(),
if args.len() == 1 {" was"} else {"s were"}); if args.len() == 1 {" was"} else {"s were"});
tcx.sess.span_err(sp, msg.as_slice());
} }
Vec::new() Vec::new()
} }
_ => { _ => {
tcx.sess span_err!(tcx.sess, sp, E0059,
.span_err(sp, "cannot use call notation; the first type parameter \
"cannot use call notation; the first type \ for the function trait is neither a tuple nor unit");
parameter for the function trait is neither a \
tuple nor unit");
err_args(supplied_arg_count) err_args(supplied_arg_count)
} }
} }
@ -1824,29 +1798,22 @@ fn check_argument_types(fcx: &FnCtxt,
if supplied_arg_count >= expected_arg_count { if supplied_arg_count >= expected_arg_count {
fn_inputs.iter().map(|a| *a).collect() fn_inputs.iter().map(|a| *a).collect()
} else { } else {
let msg = format!( span_err!(tcx.sess, sp, E0060,
"this function takes at least {} parameter{} \ "this function takes at least {} parameter{} \
but {} parameter{} supplied", but {} parameter{} supplied",
expected_arg_count, expected_arg_count,
if expected_arg_count == 1 {""} else {"s"}, if expected_arg_count == 1 {""} else {"s"},
supplied_arg_count, supplied_arg_count,
if supplied_arg_count == 1 {" was"} else {"s were"}); if supplied_arg_count == 1 {" was"} else {"s were"});
tcx.sess.span_err(sp, msg.as_slice());
err_args(supplied_arg_count) err_args(supplied_arg_count)
} }
} else { } else {
let msg = format!( span_err!(tcx.sess, sp, E0061,
"this function takes {} parameter{} \ "this function takes {} parameter{} but {} parameter{} supplied",
but {} parameter{} supplied",
expected_arg_count, expected_arg_count,
if expected_arg_count == 1 {""} else {"s"}, if expected_arg_count == 1 {""} else {"s"},
supplied_arg_count, supplied_arg_count,
if supplied_arg_count == 1 {" was"} else {"s were"}); if supplied_arg_count == 1 {" was"} else {"s were"});
tcx.sess.span_err(sp, msg.as_slice());
err_args(supplied_arg_count) err_args(supplied_arg_count)
}; };
@ -2732,11 +2699,9 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
error_happened = true; error_happened = true;
} }
Some((_, true)) => { Some((_, true)) => {
tcx.sess.span_err( span_err!(fcx.tcx().sess, field.ident.span, E0062,
field.ident.span, "field `{}` specified more than once",
format!("field `{}` specified more than once", token::get_ident(field.ident.node));
token::get_ident(field.ident
.node)).as_slice());
error_happened = true; error_happened = true;
} }
Some((field_id, false)) => { Some((field_id, false)) => {
@ -2774,11 +2739,10 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
} }
} }
tcx.sess.span_err(span, span_err!(tcx.sess, span, E0063,
format!( "missing field{}: {}",
"missing field{}: {fields}",
if missing_fields.len() == 1 {""} else {"s"}, if missing_fields.len() == 1 {""} else {"s"},
fields = missing_fields.connect(", ")).as_slice()); missing_fields.connect(", "));
} }
} }
@ -2940,12 +2904,14 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
} }
} }
ast::ExprLit(_) => { ast::ExprLit(_) => {
let error = if vst == ast::ExprVstoreSlice { if vst == ast::ExprVstoreSlice {
"`&\"string\"` has been removed; use `\"string\"` instead" span_err!(tcx.sess, expr.span, E0064,
"`&\"string\"` has been removed; use `\"string\"` instead");
} else { } else {
"`box \"string\"` has been removed; use `\"string\".to_string()` instead" span_err!(tcx.sess, expr.span, E0065,
}; "`box \"string\"` has been removed; use \
tcx.sess.span_err(expr.span, error); `\"string\".to_string()` instead");
}
ty::mk_err() ty::mk_err()
} }
_ => tcx.sess.span_bug(expr.span, "vstore modifier on non-sequence"), _ => tcx.sess.span_bug(expr.span, "vstore modifier on non-sequence"),
@ -2979,9 +2945,8 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
} }
if !checked { if !checked {
tcx.sess.span_err(expr.span, span_err!(tcx.sess, expr.span, E0066,
"only the managed heap and exchange heap are \ "only the managed heap and exchange heap are currently supported");
currently supported");
fcx.write_ty(id, ty::mk_err()); fcx.write_ty(id, ty::mk_err());
} }
} }
@ -3013,7 +2978,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
let tcx = fcx.tcx(); let tcx = fcx.tcx();
if !ty::expr_is_lval(tcx, &**lhs) { if !ty::expr_is_lval(tcx, &**lhs) {
tcx.sess.span_err(lhs.span, "illegal left-hand side expression"); span_err!(tcx.sess, lhs.span, E0067, "illegal left-hand side expression");
} }
// Overwrite result of check_binop...this preserves existing behavior // Overwrite result of check_binop...this preserves existing behavior
@ -3079,7 +3044,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
}; };
if is_newtype { if is_newtype {
// This is an obsolete struct deref // This is an obsolete struct deref
tcx.sess.span_err(expr.span, span_err!(tcx.sess, expr.span, E0068,
"single-field tuple-structs can \ "single-field tuple-structs can \
no longer be dereferenced"); no longer be dereferenced");
} else { } else {
@ -3183,8 +3148,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
ret_ty, ty::mk_nil()) { ret_ty, ty::mk_nil()) {
Ok(_) => { /* fall through */ } Ok(_) => { /* fall through */ }
Err(_) => { Err(_) => {
tcx.sess.span_err( span_err!(tcx.sess, expr.span, E0069,
expr.span,
"`return;` in function returning non-nil"); "`return;` in function returning non-nil");
} }
}, },
@ -3203,7 +3167,8 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
let tcx = fcx.tcx(); let tcx = fcx.tcx();
if !ty::expr_is_lval(tcx, &**lhs) { if !ty::expr_is_lval(tcx, &**lhs) {
tcx.sess.span_err(lhs.span, "illegal left-hand side expression"); span_err!(tcx.sess, expr.span, E0070,
"illegal left-hand side expression");
} }
let lhs_ty = fcx.expr_ty(&**lhs); let lhs_ty = fcx.expr_ty(&**lhs);
@ -3392,11 +3357,9 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
base_expr); base_expr);
} }
_ => { _ => {
tcx.sess span_err!(tcx.sess, path.span, E0071,
.span_err(path.span, "`{}` does not name a structure",
format!("`{}` does not name a structure", pprust::path_to_string(path));
pprust::path_to_string(
path)).as_slice())
} }
} }
} }
@ -3768,10 +3731,10 @@ pub fn check_representable(tcx: &ty::ctxt,
// caught by case 1. // caught by case 1.
match ty::is_type_representable(tcx, sp, rty) { match ty::is_type_representable(tcx, sp, rty) {
ty::SelfRecursive => { ty::SelfRecursive => {
tcx.sess.span_err( span_err!(tcx.sess, sp, E0072,
sp, format!("illegal recursive {} type; \ "illegal recursive {} type; \
wrap the inner value in a box to make it representable", wrap the inner value in a box to make it representable",
designation).as_slice()); designation);
return false return false
} }
ty::Representable | ty::ContainsRecursive => (), ty::Representable | ty::ContainsRecursive => (),
@ -3796,12 +3759,10 @@ pub fn check_instantiable(tcx: &ty::ctxt,
-> bool { -> bool {
let item_ty = ty::node_id_to_type(tcx, item_id); let item_ty = ty::node_id_to_type(tcx, item_id);
if !ty::is_instantiable(tcx, item_ty) { if !ty::is_instantiable(tcx, item_ty) {
tcx.sess span_err!(tcx.sess, sp, E0073,
.span_err(sp, "this type cannot be instantiated without an \
format!("this type cannot be instantiated without an \ instance of itself; consider using `Option<{}>`",
instance of itself; consider using \ ppaux::ty_to_string(tcx, item_ty));
`Option<{}>`",
ppaux::ty_to_string(tcx, item_ty)).as_slice());
false false
} else { } else {
true true
@ -3811,25 +3772,25 @@ pub fn check_instantiable(tcx: &ty::ctxt,
pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) { pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
let t = ty::node_id_to_type(tcx, id); let t = ty::node_id_to_type(tcx, id);
if ty::type_needs_subst(t) { if ty::type_needs_subst(t) {
tcx.sess.span_err(sp, "SIMD vector cannot be generic"); span_err!(tcx.sess, sp, E0074, "SIMD vector cannot be generic");
return; return;
} }
match ty::get(t).sty { match ty::get(t).sty {
ty::ty_struct(did, ref substs) => { ty::ty_struct(did, ref substs) => {
let fields = ty::lookup_struct_fields(tcx, did); let fields = ty::lookup_struct_fields(tcx, did);
if fields.is_empty() { if fields.is_empty() {
tcx.sess.span_err(sp, "SIMD vector cannot be empty"); span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
return; return;
} }
let e = ty::lookup_field_type(tcx, did, fields.get(0).id, substs); let e = ty::lookup_field_type(tcx, did, fields.get(0).id, substs);
if !fields.iter().all( if !fields.iter().all(
|f| ty::lookup_field_type(tcx, did, f.id, substs) == e) { |f| ty::lookup_field_type(tcx, did, f.id, substs) == e) {
tcx.sess.span_err(sp, "SIMD vector should be homogeneous"); span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous");
return; return;
} }
if !ty::type_is_machine(e) { if !ty::type_is_machine(e) {
tcx.sess.span_err(sp, "SIMD vector element type should be \ span_err!(tcx.sess, sp, E0077,
machine type"); "SIMD vector element type should be machine type");
return; return;
} }
} }
@ -3854,16 +3815,10 @@ pub fn check_enum_variants_sized(ccx: &CrateCtxt,
// A struct value with an unsized final field is itself // A struct value with an unsized final field is itself
// unsized and we must track this in the type system. // unsized and we must track this in the type system.
if !ty::type_is_sized(ccx.tcx, *t) { if !ty::type_is_sized(ccx.tcx, *t) {
ccx.tcx span_err!(ccx.tcx.sess, args.get(i).ty.span, E0078,
.sess "type `{}` is dynamically sized. dynamically sized types may only \
.span_err( appear as the final type in a variant",
args.get(i).ty.span, ppaux::ty_to_string(ccx.tcx, *t));
format!("type `{}` is dynamically sized. \
dynamically sized types may only \
appear as the final type in a \
variant",
ppaux::ty_to_string(ccx.tcx,
*t)).as_slice());
} }
} }
}, },
@ -3949,14 +3904,12 @@ pub fn check_enum_variants(ccx: &CrateCtxt,
Ok(const_eval::const_int(val)) => current_disr_val = val as Disr, Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr, Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
Ok(_) => { Ok(_) => {
ccx.tcx.sess.span_err(e.span, "expected signed integer constant"); span_err!(ccx.tcx.sess, e.span, E0079,
"expected signed integer constant");
} }
Err(ref err) => { Err(ref err) => {
ccx.tcx span_err!(ccx.tcx.sess, e.span, E0080,
.sess "expected constant: {}", *err);
.span_err(e.span,
format!("expected constant: {}",
*err).as_slice());
} }
} }
}, },
@ -3965,16 +3918,18 @@ pub fn check_enum_variants(ccx: &CrateCtxt,
// Check for duplicate discriminant values // Check for duplicate discriminant values
if disr_vals.contains(&current_disr_val) { if disr_vals.contains(&current_disr_val) {
ccx.tcx.sess.span_err(v.span, "discriminant value already exists"); span_err!(ccx.tcx.sess, v.span, E0081,
"discriminant value already exists");
} }
// Check for unrepresentable discriminant values // Check for unrepresentable discriminant values
match hint { match hint {
attr::ReprAny | attr::ReprExtern => (), attr::ReprAny | attr::ReprExtern => (),
attr::ReprInt(sp, ity) => { attr::ReprInt(sp, ity) => {
if !disr_in_range(ccx, ity, current_disr_val) { if !disr_in_range(ccx, ity, current_disr_val) {
ccx.tcx.sess.span_err(v.span, span_err!(ccx.tcx.sess, v.span, E0082,
"discriminant value outside specified type"); "discriminant value outside specified type");
ccx.tcx.sess.span_note(sp, "discriminant type specified here"); span_note!(ccx.tcx.sess, sp,
"discriminant type specified here");
} }
} }
} }
@ -3992,12 +3947,13 @@ pub fn check_enum_variants(ccx: &CrateCtxt,
let hint = ty::lookup_repr_hint(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id }); let hint = ty::lookup_repr_hint(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id });
if hint != attr::ReprAny && vs.len() <= 1 { if hint != attr::ReprAny && vs.len() <= 1 {
let msg = if vs.len() == 1 { if vs.len() == 1 {
"unsupported representation for univariant enum" span_err!(ccx.tcx.sess, sp, E0083,
"unsupported representation for univariant enum");
} else { } else {
"unsupported representation for zero-variant enum" span_err!(ccx.tcx.sess, sp, E0084,
"unsupported representation for zero-variant enum");
}; };
ccx.tcx.sess.span_err(sp, msg)
} }
let variants = do_check(ccx, vs, id, hint); let variants = do_check(ccx, vs, id, hint);
@ -4243,15 +4199,13 @@ pub fn instantiate_path(fcx: &FnCtxt,
segment: &ast::PathSegment) segment: &ast::PathSegment)
{ {
for typ in segment.types.iter() { for typ in segment.types.iter() {
fcx.tcx().sess.span_err( span_err!(fcx.tcx().sess, typ.span, E0085,
typ.span,
"type parameters may not appear here"); "type parameters may not appear here");
break; break;
} }
for lifetime in segment.lifetimes.iter() { for lifetime in segment.lifetimes.iter() {
fcx.tcx().sess.span_err( span_err!(fcx.tcx().sess, lifetime.span, E0086,
lifetime.span,
"lifetime parameters may not appear here"); "lifetime parameters may not appear here");
break; break;
} }
@ -4290,14 +4244,11 @@ pub fn instantiate_path(fcx: &FnCtxt,
if i < type_count { if i < type_count {
substs.types.push(space, t); substs.types.push(space, t);
} else if i == type_count { } else if i == type_count {
fcx.tcx().sess.span_err( span_err!(fcx.tcx().sess, typ.span, E0087,
typ.span,
format!(
"too many type parameters provided: \ "too many type parameters provided: \
expected at most {} parameter(s) \ expected at most {} parameter(s) \
but found {} parameter(s)", but found {} parameter(s)",
type_count, type_count, segment.types.len());
segment.types.len()).as_slice());
substs.types.truncate(space, 0); substs.types.truncate(space, 0);
} }
} }
@ -4311,13 +4262,11 @@ pub fn instantiate_path(fcx: &FnCtxt,
if i < region_count { if i < region_count {
substs.mut_regions().push(space, r); substs.mut_regions().push(space, r);
} else if i == region_count { } else if i == region_count {
fcx.tcx().sess.span_err( span_err!(fcx.tcx().sess, lifetime.span, E0088,
lifetime.span,
format!(
"too many lifetime parameters provided: \ "too many lifetime parameters provided: \
expected {} parameter(s) but found {} parameter(s)", expected {} parameter(s) but found {} parameter(s)",
region_count, region_count,
segment.lifetimes.len()).as_slice()); segment.lifetimes.len());
substs.mut_regions().truncate(space, 0); substs.mut_regions().truncate(space, 0);
} }
} }
@ -4362,14 +4311,10 @@ pub fn instantiate_path(fcx: &FnCtxt,
if provided_len < required_len { if provided_len < required_len {
let qualifier = let qualifier =
if desired.len() != required_len { "at least " } else { "" }; if desired.len() != required_len { "at least " } else { "" };
fcx.tcx().sess.span_err( span_err!(fcx.tcx().sess, span, E0089,
span, "too few type parameters provided: expected {}{} parameter(s) \
format!("too few type parameters provided: \
expected {}{} parameter(s) \
but found {} parameter(s)", but found {} parameter(s)",
qualifier, qualifier, required_len, provided_len);
required_len,
provided_len).as_slice());
substs.types.replace(space, substs.types.replace(space,
Vec::from_elem(desired.len(), ty::mk_err())); Vec::from_elem(desired.len(), ty::mk_err()));
return; return;
@ -4420,14 +4365,10 @@ pub fn instantiate_path(fcx: &FnCtxt,
// Otherwise, too few were provided. Report an error and then // Otherwise, too few were provided. Report an error and then
// use inference variables. // use inference variables.
fcx.tcx().sess.span_err( span_err!(fcx.tcx().sess, span, E0090,
span, "too few lifetime parameters provided: expected {} parameter(s) \
format!(
"too few lifetime parameters provided: \
expected {} parameter(s) \
but found {} parameter(s)", but found {} parameter(s)",
desired.len(), desired.len(), provided_len);
provided_len).as_slice());
substs.mut_regions().replace( substs.mut_regions().replace(
space, space,
@ -4549,10 +4490,9 @@ pub fn check_bounds_are_used(ccx: &CrateCtxt,
for (i, b) in tps_used.iter().enumerate() { for (i, b) in tps_used.iter().enumerate() {
if !*b { if !*b {
ccx.tcx.sess.span_err( span_err!(ccx.tcx.sess, span, E0091,
span, "type parameter `{}` is unused",
format!("type parameter `{}` is unused", token::get_ident(tps.get(i).ident));
token::get_ident(tps.get(i).ident)).as_slice());
} }
} }
} }
@ -4588,10 +4528,8 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
(0, Vec::new(), ty::mk_nil()) (0, Vec::new(), ty::mk_nil())
} }
op => { op => {
tcx.sess.span_err(it.span, span_err!(tcx.sess, it.span, E0092,
format!("unrecognized atomic operation \ "unrecognized atomic operation function: `{}`", op);
function: `{}`",
op).as_slice());
return; return;
} }
} }
@ -4815,9 +4753,8 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
ty::mk_tup(tcx, vec!(ty::mk_u64(), ty::mk_bool()))), ty::mk_tup(tcx, vec!(ty::mk_u64(), ty::mk_bool()))),
ref other => { ref other => {
tcx.sess.span_err(it.span, span_err!(tcx.sess, it.span, E0093,
format!("unrecognized intrinsic function: `{}`", "unrecognized intrinsic function: `{}`", *other);
*other).as_slice());
return; return;
} }
} }
@ -4835,11 +4772,10 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id)); let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
let i_n_tps = i_ty.generics.types.len(subst::FnSpace); let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
if i_n_tps != n_tps { if i_n_tps != n_tps {
tcx.sess.span_err(it.span, span_err!(tcx.sess, it.span, E0094,
format!("intrinsic has wrong number of type \ "intrinsic has wrong number of type \
parameters: found {}, expected {}", parameters: found {}, expected {}",
i_n_tps, i_n_tps, n_tps);
n_tps).as_slice());
} else { } else {
require_same_types(tcx, require_same_types(tcx,
None, None,

View file

@ -98,6 +98,9 @@ impl SpanHandler {
pub fn span_warn(&self, sp: Span, msg: &str) { pub fn span_warn(&self, sp: Span, msg: &str) {
self.handler.emit(Some((&self.cm, sp)), msg, Warning); self.handler.emit(Some((&self.cm, sp)), msg, Warning);
} }
pub fn span_warn_with_code(&self, sp: Span, msg: &str, code: &str) {
self.handler.emit_with_code(Some((&self.cm, sp)), msg, code, Warning);
}
pub fn span_note(&self, sp: Span, msg: &str) { pub fn span_note(&self, sp: Span, msg: &str) {
self.handler.emit(Some((&self.cm, sp)), msg, Note); self.handler.emit(Some((&self.cm, sp)), msg, Note);
} }

View file

@ -49,3 +49,25 @@ macro_rules! span_err(
($session).span_err_with_code($span, format!($($arg),*).as_slice(), stringify!($code)) ($session).span_err_with_code($span, format!($($arg),*).as_slice(), stringify!($code))
}) })
) )
#[macro_export]
macro_rules! span_warn(
($session:expr, $span:expr, $code:ident, $($arg:expr),*) => ({
__diagnostic_used!($code);
($session).span_warn_with_code($span, format!($($arg),*).as_slice(), stringify!($code))
})
)
#[macro_export]
macro_rules! span_note(
($session:expr, $span:expr, $($arg:expr),*) => ({
($session).span_note($span, format!($($arg),*).as_slice())
})
)
#[macro_export]
macro_rules! register_diagnostics(
($($code:tt),*) => (
$(register_diagnostic!($code))*
)
)

View file

@ -54,7 +54,8 @@ pub fn expand_diagnostic_used(ecx: &mut ExtCtxt, span: Span,
with_registered_diagnostics(|diagnostics| { with_registered_diagnostics(|diagnostics| {
if !diagnostics.contains_key(&code.name) { if !diagnostics.contains_key(&code.name) {
ecx.span_err(span, format!( ecx.span_err(span, format!(
"unknown diagnostic code {}", token::get_ident(code).get() "unknown diagnostic code {}; add to librustc/diagnostics.rs",
token::get_ident(code).get()
).as_slice()); ).as_slice());
} }
() ()