From a5fe176e9715f6e67a3ede3d204ba84b2f92ce7d Mon Sep 17 00:00:00 2001 From: Jakub Wieczorek Date: Fri, 11 Jul 2014 18:54:01 +0200 Subject: [PATCH] Convert a first batch of diagnostics to have error codes --- src/librustc/diagnostics.rs | 96 +++++ src/librustc/driver/session.rs | 3 + src/librustc/middle/check_const.rs | 51 ++- src/librustc/middle/check_match.rs | 55 ++- src/librustc/middle/check_static.rs | 12 +- src/librustc/middle/typeck/check/_match.rs | 76 ++-- src/librustc/middle/typeck/check/method.rs | 53 +-- src/librustc/middle/typeck/check/mod.rs | 426 +++++++++------------ src/libsyntax/diagnostic.rs | 3 + src/libsyntax/diagnostics/macros.rs | 22 ++ src/libsyntax/diagnostics/plugin.rs | 3 +- 11 files changed, 410 insertions(+), 390 deletions(-) diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 0499795f890..5f3bbf48105 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -16,3 +16,99 @@ register_diagnostic!(E0001, r##" This means that perhaps some of the preceeding patterns are too general, this 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 +) diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs index 313b2bd6bf0..135e21e4e01 100644 --- a/src/librustc/driver/session.rs +++ b/src/librustc/driver/session.rs @@ -85,6 +85,9 @@ impl Session { pub fn span_warn(&self, sp: Span, msg: &str) { 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) { self.diagnostic().handler().warn(msg) } diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs index 33bf6ceed4f..283d667f3a8 100644 --- a/src/librustc/middle/check_const.rs +++ b/src/librustc/middle/check_const.rs @@ -87,28 +87,25 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &Expr, is_const: bool) { match e.node { ExprUnary(UnDeref, _) => { } ExprUnary(UnBox, _) | ExprUnary(UnUniq, _) => { - v.tcx.sess.span_err(e.span, - "cannot do allocations in constant expressions"); + span_err!(v.tcx.sess, e.span, E0010, "cannot do allocations in constant expressions"); return; } ExprLit(lit) if ast_util::lit_is_str(lit) => {} ExprBinary(..) | ExprUnary(..) => { let method_call = typeck::MethodCall::expr(e.id); if v.tcx.method_map.borrow().contains_key(&method_call) { - v.tcx.sess.span_err(e.span, "user-defined operators are not \ - allowed in constant expressions"); + span_err!(v.tcx.sess, e.span, E0011, + "user-defined operators are not allowed in constant expressions"); } } ExprLit(_) => (), ExprCast(_, _) => { let ety = ty::expr_ty(v.tcx, e); if !ty::type_is_numeric(ety) && !ty::type_is_unsafe_ptr(ety) { - v.tcx - .sess - .span_err(e.span, - format!("can not cast to `{}` in a constant \ - expression", - ppaux::ty_to_string(v.tcx, ety)).as_slice()) + span_err!(v.tcx.sess, e.span, E0012, + "can not cast to `{}` in a constant expression", + ppaux::ty_to_string(v.tcx, ety) + ); } } ExprPath(ref pth) => { @@ -117,9 +114,8 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &Expr, is_const: bool) { // foo:: in a const. Currently that is only done on // a path in trans::callee that only works in block contexts. if !pth.segments.iter().all(|segment| segment.types.is_empty()) { - v.tcx.sess.span_err(e.span, - "paths in constants may only refer to \ - items without type parameters"); + span_err!(v.tcx.sess, e.span, E0013, + "paths in constants may only refer to items without type parameters"); } match v.tcx.def_map.borrow().find(&e.id) { Some(&DefStatic(..)) | @@ -129,9 +125,8 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &Expr, is_const: bool) { Some(&def) => { debug!("(checking const) found bad def: {:?}", def); - v.tcx.sess.span_err(e.span, - "paths in constants may only refer to \ - constants or functions"); + span_err!(v.tcx.sess, e.span, E0014, + "paths in constants may only refer to constants or functions"); } None => { 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(&DefVariant(..)) => {} // OK. _ => { - v.tcx.sess.span_err(e.span, - "function calls in constants are limited to \ - struct and enum constructors"); + span_err!(v.tcx.sess, e.span, E0015, + "function calls in constants are limited to 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 for stmt in block.stmts.iter() { let block_span_err = |span| - v.tcx.sess.span_err(span, - "blocks in constants are limited to \ - items and tail expressions"); + span_err!(v.tcx.sess, span, E0016, + "blocks in constants are limited to items and tail expressions"); match stmt.node { StmtDecl(ref span, _) => { match span.node { @@ -187,18 +180,18 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &Expr, is_const: bool) { ExprRepeat(..) | ExprStruct(..) => { } ExprAddrOf(..) => { - v.tcx.sess.span_err(e.span, - "references in constants may only refer to \ - immutable values"); + span_err!(v.tcx.sess, e.span, E0017, + "references in constants may only refer to immutable values"); }, 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, - "constant contains unimplemented expression type"); - return; + span_err!(v.tcx.sess, e.span, E0019, + "constant contains unimplemented expression type"); + return; } } } diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index f31c247abd3..832b222ef16 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -142,15 +142,16 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &Expr) { // Finally, check if the whole match expression is exhaustive. // Check for empty enum, because is_useful only works on inhabited types. let pat_ty = node_id_to_type(cx.tcx, scrut.id); - if (*arms).is_empty() { - if !type_is_empty(cx.tcx, pat_ty) { - // We know the type is inhabited, so this must be wrong - cx.tcx.sess.span_err(ex.span, format!("non-exhaustive patterns: \ - type {} is non-empty", - ty_to_string(cx.tcx, pat_ty)).as_slice()); - } - // If the type *is* empty, it's vacuously exhaustive - return; + if arms.is_empty() { + if !type_is_empty(cx.tcx, pat_ty) { + // We know the type is inhabited, so this must be wrong + span_err!(cx.tcx.sess, ex.span, E0002, + "non-exhaustive patterns: type {} is non-empty", + ty_to_string(cx.tcx, pat_ty) + ); + } + // If the type *is* empty, it's vacuously exhaustive + return; } let m: Matrix = Matrix(arms .iter() @@ -186,8 +187,9 @@ fn check_arms(cx: &MatchCheckCtxt, arms: &[Arm]) { walk_pat(&**pat, |p| { if pat_matches_nan(p) { - cx.tcx.sess.span_warn(p.span, "unmatchable NaN in pattern, \ - use the is_nan method in a guard instead"); + span_warn!(cx.tcx.sess, p.span, E0003, + "unmatchable NaN in pattern, use the is_nan method in a guard instead" + ); } true }); @@ -222,9 +224,10 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, m: &Matrix) { [] => wild(), _ => unreachable!() }; - let msg = format!("non-exhaustive patterns: `{0}` not covered", - pat_to_string(&*witness)); - cx.tcx.sess.span_err(sp, msg.as_slice()); + span_err!(cx.tcx.sess, sp, E0004, + "non-exhaustive patterns: `{}` not covered", + pat_to_string(&*witness) + ); } NotUseful => { // 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) { Some(pat) => { - let msg = format!( + span_err!(cx.tcx.sess, loc.pat.span, E0005, "refutable pattern in {} binding: `{}` not covered", name, pat_to_string(&*pat) ); - cx.tcx.sess.span_err(loc.pat.span, msg.as_slice()); }, None => () } @@ -801,11 +803,10 @@ fn check_fn(cx: &mut MatchCheckCtxt, for input in decl.inputs.iter() { match is_refutable(cx, input.pat) { Some(pat) => { - let msg = format!( + span_err!(cx.tcx.sess, input.pat.span, E0006, "refutable pattern in function argument: `{}` not covered", pat_to_string(&*pat) ); - cx.tcx.sess.span_err(input.pat.span, msg.as_slice()); }, None => () } @@ -850,21 +851,13 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt, // x @ Foo(..) is legal, but x @ Foo(y) isn't. if sub.map_or(false, |p| pat_contains_bindings(def_map, &*p)) { - tcx.sess.span_err( - p.span, - "cannot bind by-move with sub-bindings"); + span_err!(cx.tcx.sess, p.span, E0007, "cannot bind by-move with sub-bindings"); } else if has_guard { - tcx.sess.span_err( - p.span, - "cannot bind by-move into a pattern guard"); + span_err!(cx.tcx.sess, p.span, E0008, "cannot bind by-move into a pattern guard"); } else if by_ref_span.is_some() { - tcx.sess.span_err( - p.span, - "cannot bind by-move and by-ref \ - in the same pattern"); - tcx.sess.span_note( - by_ref_span.unwrap(), - "by-ref binding occurs here"); + span_err!(cx.tcx.sess, p.span, E0009, + "cannot bind by-move and by-ref in the same pattern"); + span_note!(cx.tcx.sess, by_ref_span.unwrap(), "by-ref binding occurs here"); } }; diff --git a/src/librustc/middle/check_static.rs b/src/librustc/middle/check_static.rs index 1e948afb701..8985e633ad4 100644 --- a/src/librustc/middle/check_static.rs +++ b/src/librustc/middle/check_static.rs @@ -112,18 +112,18 @@ impl<'a> Visitor for CheckStaticVisitor<'a> { visit::walk_expr(self, e, is_const); } ast::ExprVstore(_, ast::ExprVstoreMutSlice) => { - self.tcx.sess.span_err(e.span, - "static items are not allowed to have mutable slices"); + span_err!(self.tcx.sess, e.span, E0020, + "static items are not allowed to have mutable slices"); }, ast::ExprUnary(ast::UnBox, _) => { - self.tcx.sess.span_err(e.span, - "static items are not allowed to have managed pointers"); + span_err!(self.tcx.sess, e.span, E0021, + "static items are not allowed to have managed pointers"); } ast::ExprBox(..) | ast::ExprUnary(ast::UnUniq, _) | ast::ExprVstore(_, ast::ExprVstoreUniq) => { - self.tcx.sess.span_err(e.span, - "static items are not allowed to have custom pointers"); + span_err!(self.tcx.sess, e.span, E0022, + "static items are not allowed to have custom pointers"); } _ => { let node_ty = ty::node_id_to_type(self.tcx, e.id); diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs index 2232cc49657..170f850328e 100644 --- a/src/librustc/middle/typeck/check/_match.rs +++ b/src/librustc/middle/typeck/check/_match.rs @@ -253,14 +253,10 @@ pub fn check_pat_variant(pcx: &pat_ctxt, pat: &ast::Pat, path: &ast::Path, if arg_len > 0 { // N-ary variant. if arg_len != subpats_len { - let s = format!("this pattern has {} field{}, \ - but the corresponding {} has {} field{}", - subpats_len, - if subpats_len == 1 {""} else {"s"}, - kind_name, - arg_len, - if arg_len == 1 {""} else {"s"}); - tcx.sess.span_err(pat.span, s.as_slice()); + span_err!(tcx.sess, pat.span, E0023, + "this pattern has {} field{}, but the corresponding {} has {} field{}", + subpats_len, if subpats_len == 1 {""} else {"s"}, + kind_name, arg_len, if arg_len == 1 {""} else {"s"}); 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 { - tcx.sess.span_err(pat.span, - format!("this pattern has {} field{}, \ - but the corresponding {} has no fields", - subpats_len, - if subpats_len == 1 {""} else {"s"}, - kind_name).as_slice()); + span_err!(tcx.sess, pat.span, E0024, + "this pattern has {} field{}, but the corresponding {} has no fields", + subpats_len, if subpats_len == 1 {""} else {"s"}, + kind_name); 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 // up its type won't fail check_pat(pcx, &*field.pat, ty::mk_err()); - tcx.sess.span_err(span, - format!("field `{}` bound twice in pattern", - token::get_ident(field.ident)).as_slice()); + span_err!(tcx.sess, span, E0025, + "field `{}` bound twice in pattern", + token::get_ident(field.ident)); } Some(&(index, ref mut used)) => { *used = true; @@ -339,10 +333,10 @@ pub fn check_struct_pat_fields(pcx: &pat_ctxt, // Check the pattern anyway, so that attempts to look // up its type won't fail check_pat(pcx, &*field.pat, ty::mk_err()); - tcx.sess.span_err(span, - format!("struct `{}` does not have a field named `{}`", - ty::item_path_str(tcx, class_id), - token::get_ident(field.ident)).as_slice()); + span_err!(tcx.sess, span, E0026, + "struct `{}` does not have a field named `{}`", + ty::item_path_str(tcx, class_id), + token::get_ident(field.ident)); } } } @@ -353,11 +347,9 @@ pub fn check_struct_pat_fields(pcx: &pat_ctxt, if found_fields.contains(&i) { continue; } - - tcx.sess - .span_err(span, - format!("pattern does not mention field `{}`", - token::get_name(field.name)).as_slice()); + span_err!(tcx.sess, span, E0027, + "pattern does not mention field `{}`", + token::get_name(field.name)); } } } @@ -400,11 +392,9 @@ pub fn check_struct_like_enum_variant_pat(pcx: &pat_ctxt, } Some(&def::DefStruct(..)) | Some(&def::DefVariant(..)) => { let name = pprust::path_to_string(path); - tcx.sess.span_err(span, - format!("mismatched types: expected `{}` but \ - found `{}`", - fcx.infcx().ty_to_string(expected), - name).as_slice()); + span_err!(tcx.sess, span, E0028, + "mismatched types: expected `{}` but found `{}`", + fcx.infcx().ty_to_string(expected), name); } _ => { 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 } 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"); } else { match valid_range_bounds(fcx.ccx, &**begin, &**end) { Some(false) => { - tcx.sess.span_err(begin.span, + span_err!(tcx.sess, begin.span, E0030, "lower range bound must be less than upper"); }, None => { - tcx.sess.span_err(begin.span, + span_err!(tcx.sess, begin.span, E0031, "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::lookup_item_type(tcx, item_did).ty).unwrap(); if struct_did != cid { - tcx.sess - .span_err(path.span, - format!("`{}` does not name the \ - structure `{}`", - pprust::path_to_string(path), - fcx.infcx() - .ty_to_string(expected)).as_slice()) + span_err!(tcx.sess, pat.span, E0032, + "`{}` does not name the structure `{}`", + pprust::path_to_string(path), + fcx.infcx().ty_to_string(expected)); } 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 // "let &x = &SomeTrait" or "let box x = Box", an error. check_pat(pcx, inner, ty::mk_err()); - tcx.sess.span_err( - span, - format!("type `{}` cannot be dereferenced", - fcx.infcx().ty_to_string(expected)).as_slice()); + span_err!(tcx.sess, span, E0033, + "type `{}` cannot be dereferenced", + fcx.infcx().ty_to_string(expected)); fcx.write_error(pat_id); } _ => { diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index a184ecac9de..47878370938 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -1041,8 +1041,7 @@ impl<'a> LookupContext<'a> { } if relevant_candidates.len() > 1 { - self.tcx().sess.span_err( - self.span, + span_err!(self.tcx().sess, self.span, E0034, "multiple applicable methods in scope"); for (idx, candidate) in relevant_candidates.iter().enumerate() { self.report_candidate(idx, &candidate.origin); @@ -1112,13 +1111,11 @@ impl<'a> LookupContext<'a> { if num_supplied_tps == 0u { self.fcx.infcx().next_ty_vars(num_method_tps) } else if num_method_tps == 0u { - tcx.sess.span_err( - self.span, - "this method does not take type parameters"); + span_err!(tcx.sess, self.span, E0035, + "does not take type parameters"); self.fcx.infcx().next_ty_vars(num_method_tps) } else if num_supplied_tps != num_method_tps { - tcx.sess.span_err( - self.span, + span_err!(tcx.sess, self.span, E0036, "incorrect number of type parameters given for this method"); self.fcx.infcx().next_ty_vars(num_method_tps) } else { @@ -1221,10 +1218,8 @@ impl<'a> LookupContext<'a> { match candidate.method_ty.explicit_self { ast::SelfStatic => { // reason (a) above - self.tcx().sess.span_err( - self.span, - "cannot call a method without a receiver \ - through an object"); + span_err!(self.tcx().sess, self.span, E0037, + "cannot call a method without a receiver through an object"); } ast::SelfValue(_) | ast::SelfRegion(..) | ast::SelfUniq(_) => {} @@ -1233,8 +1228,7 @@ impl<'a> LookupContext<'a> { // reason (a) above let check_for_self_ty = |ty| { if ty::type_has_self(ty) { - self.tcx().sess.span_err( - self.span, + span_err!(self.tcx().sess, self.span, E0038, "cannot call a method whose type contains a \ self-type through an object"); true @@ -1256,8 +1250,7 @@ impl<'a> LookupContext<'a> { if candidate.method_ty.generics.has_type_params(subst::FnSpace) { // reason (b) above - self.tcx().sess.span_err( - self.span, + span_err!(self.tcx().sess, self.span, E0039, "cannot call a generic method through an object"); } } @@ -1279,8 +1272,8 @@ impl<'a> LookupContext<'a> { } if bad { - self.tcx().sess.span_err(self.span, - "explicit call to destructor"); + span_err!(self.tcx().sess, self.span, E0040, + "explicit call to destructor"); } } @@ -1425,28 +1418,22 @@ impl<'a> LookupContext<'a> { } else { self.span }; - self.tcx().sess.span_note( - span, - format!("candidate #{} is `{}`", - idx + 1u, - ty::item_path_str(self.tcx(), did)).as_slice()); + span_note!(self.tcx().sess, span, + "candidate #{} is `{}`", + idx + 1u, ty::item_path_str(self.tcx(), did)); } fn report_param_candidate(&self, idx: uint, did: DefId) { - self.tcx().sess.span_note( - self.span, - format!("candidate #{} derives from the bound `{}`", - idx + 1u, - ty::item_path_str(self.tcx(), did)).as_slice()); + span_note!(self.tcx().sess, self.span, + "candidate #{} derives from the bound `{}`", + idx + 1u, ty::item_path_str(self.tcx(), did)); } fn report_trait_candidate(&self, idx: uint, did: DefId) { - self.tcx().sess.span_note( - self.span, - format!("candidate #{} derives from the type of the receiver, \ - which is the trait `{}`", - idx + 1u, - ty::item_path_str(self.tcx(), did)).as_slice()); + span_note!(self.tcx().sess, self.span, + "candidate #{} derives from the type of the receiver, \ + which is the trait `{}`", + idx + 1u, ty::item_path_str(self.tcx(), did)); } fn infcx(&'a self) -> &'a infer::InferCtxt<'a> { diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index cdf434f4099..7a4451c38f4 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -569,11 +569,10 @@ fn check_for_field_shadowing(tcx: &ty::ctxt, for f in fields.iter() { match super_fields.iter().find(|sf| f.name == sf.name) { Some(prev_field) => { - tcx.sess.span_err(span_for_field(tcx, f, id), - format!("field `{}` hides field declared in \ - super-struct", - token::get_name(f.name)).as_slice()); - tcx.sess.span_note(span_for_field(tcx, prev_field, parent_id), + span_err!(tcx.sess, span_for_field(tcx, f, id), E0041, + "field `{}` hides field declared in super-struct", + token::get_name(f.name)); + span_note!(tcx.sess, span_for_field(tcx, prev_field, parent_id), "previously declared here"); }, None => {} @@ -595,16 +594,16 @@ fn check_fields_sized(tcx: &ty::ctxt, if !ty::type_is_sized(tcx, t) { match f.node.kind { ast::NamedField(ident, _) => { - tcx.sess.span_err( - f.span, - format!("type `{}` is dynamically sized. \ - dynamically sized types may only \ - appear as the type of the final \ - field in a struct", - token::get_ident(ident)).as_slice()); + span_err!(tcx.sess, f.span, E0042, + "type `{}` is dynamically sized. \ + dynamically sized types may only \ + appear as the type of the final \ + field in a struct", + token::get_ident(ident)); } 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() { let pty = ty::lookup_item_type(ccx.tcx, local_def(item.id)); 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 { ast::ForeignItemFn(ref fn_decl, _) => { if fn_decl.variadic && m.abi != abi::C { - ccx.tcx.sess.span_err( - item.span, "variadic function must have C calling convention"); + span_err!(ccx.tcx.sess, item.span, E0045, + "variadic function must have C calling convention"); } } _ => {} @@ -826,10 +826,9 @@ fn check_impl_methods_against_trait(ccx: &CrateCtxt, } if !missing_methods.is_empty() { - tcx.sess.span_err( - impl_span, - format!("not all trait methods implemented, missing: {}", - missing_methods.connect(", ")).as_slice()); + span_err!(tcx.sess, impl_span, E0046, + "not all trait methods implemented, missing: {}", + missing_methods.connect(", ")); } } @@ -865,23 +864,17 @@ fn compare_impl_method(tcx: &ty::ctxt, match (&trait_m.explicit_self, &impl_m.explicit_self) { (&ast::SelfStatic, &ast::SelfStatic) => {} (&ast::SelfStatic, _) => { - tcx.sess.span_err( - impl_m_span, - format!("method `{}` has a `{}` declaration in the impl, \ - but not in the trait", - token::get_ident(trait_m.ident), - pprust::explicit_self_to_string( - impl_m.explicit_self)).as_slice()); + span_err!(tcx.sess, impl_m_span, E0047, + "method `{}` has a `{}` declaration in the impl, but not in the trait", + token::get_ident(trait_m.ident), + pprust::explicit_self_to_string(impl_m.explicit_self)); return; } (_, &ast::SelfStatic) => { - tcx.sess.span_err( - impl_m_span, - format!("method `{}` has a `{}` declaration in the trait, \ - but not in the impl", - token::get_ident(trait_m.ident), - pprust::explicit_self_to_string( - trait_m.explicit_self)).as_slice()); + span_err!(tcx.sess, impl_m_span, E0048, + "method `{}` has a `{}` declaration in the trait, but not in the impl", + token::get_ident(trait_m.ident), + pprust::explicit_self_to_string(trait_m.explicit_self)); return; } _ => { @@ -892,28 +885,26 @@ fn compare_impl_method(tcx: &ty::ctxt, 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); if num_impl_m_type_params != num_trait_m_type_params { - tcx.sess.span_err( - impl_m_span, - format!("method `{}` has {} type parameter{} \ - but its trait declaration has {} type parameter{}", - token::get_ident(trait_m.ident), - num_impl_m_type_params, - if num_impl_m_type_params == 1 {""} else {"s"}, - num_trait_m_type_params, - if num_trait_m_type_params == 1 {""} else {"s"}).as_slice()); + span_err!(tcx.sess, impl_m_span, E0049, + "method `{}` has {} type parameter{} \ + but its trait declaration has {} type parameter{}", + token::get_ident(trait_m.ident), + num_impl_m_type_params, + if num_impl_m_type_params == 1 {""} else {"s"}, + num_trait_m_type_params, + if num_trait_m_type_params == 1 {""} else {"s"}); return; } if impl_m.fty.sig.inputs.len() != trait_m.fty.sig.inputs.len() { - tcx.sess.span_err( - impl_m_span, - format!("method `{}` has {} parameter{} \ - but the declaration in trait `{}` has {}", - token::get_ident(trait_m.ident), - impl_m.fty.sig.inputs.len(), - if impl_m.fty.sig.inputs.len() == 1 {""} else {"s"}, - ty::item_path_str(tcx, trait_m.def_id), - trait_m.fty.sig.inputs.len()).as_slice()); + span_err!(tcx.sess, impl_m_span, E0050, + "method `{}` has {} parameter{} \ + but the declaration in trait `{}` has {}", + token::get_ident(trait_m.ident), + impl_m.fty.sig.inputs.len(), + if impl_m.fty.sig.inputs.len() == 1 {""} else {"s"}, + ty::item_path_str(tcx, trait_m.def_id), + trait_m.fty.sig.inputs.len()); return; } @@ -1002,16 +993,13 @@ fn compare_impl_method(tcx: &ty::ctxt, impl_param_def.bounds.builtin_bounds - trait_param_def.bounds.builtin_bounds; if !extra_bounds.is_empty() { - tcx.sess.span_err( - impl_m_span, - format!("in method `{}`, \ - type parameter {} requires `{}`, \ - which is not required by \ - the corresponding type parameter \ - in the trait declaration", - token::get_ident(trait_m.ident), - i, - extra_bounds.user_string(tcx)).as_slice()); + span_err!(tcx.sess, impl_m_span, E0051, + "in method `{}`, type parameter {} requires `{}`, \ + which is not required by the corresponding type parameter \ + in the trait declaration", + token::get_ident(trait_m.ident), + i, + extra_bounds.user_string(tcx)); return; } @@ -1043,17 +1031,12 @@ fn compare_impl_method(tcx: &ty::ctxt, } if !ok { - tcx.sess.span_err(impl_m_span, - format!("in method `{}`, type parameter {} \ - requires bound `{}`, which is not \ - required by the corresponding \ - type parameter in the trait \ - declaration", - token::get_ident(trait_m.ident), - i, - ppaux::trait_ref_to_string( - tcx, - &*impl_trait_bound)).as_slice()) + span_err!(tcx.sess, impl_m_span, E0052, + "in method `{}`, type parameter {} requires bound `{}`, which is not \ + required by the corresponding type parameter in the trait declaration", + token::get_ident(trait_m.ident), + i, + ppaux::trait_ref_to_string(tcx, &*impl_trait_bound)); } } } @@ -1071,11 +1054,10 @@ fn compare_impl_method(tcx: &ty::ctxt, impl_fty, trait_fty) { Ok(()) => {} Err(ref terr) => { - tcx.sess.span_err( - impl_m_span, - format!("method `{}` has an incompatible type for trait: {}", - token::get_ident(trait_m.ident), - ty::type_err_to_str(tcx, terr)).as_slice()); + span_err!(tcx.sess, impl_m_span, E0053, + "method `{}` has an incompatible type for trait: {}", + token::get_ident(trait_m.ident), + ty::type_err_to_str(tcx, terr)); ty::note_and_explain_type_err(tcx, terr); } } @@ -1162,10 +1144,8 @@ fn check_cast(fcx: &FnCtxt, }, t_e, None); } } else if ty::get(t_1).sty == ty::ty_bool { - fcx.tcx() - .sess - .span_err(span, - "cannot cast as `bool`, compare with zero instead"); + span_err!(fcx.tcx().sess, span, E0054, + "cannot cast as `bool`, compare with zero instead"); } else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) { fn types_compatible(fcx: &FnCtxt, sp: Span, t1: ty::t, t2: ty::t) -> bool { @@ -1533,9 +1513,9 @@ pub fn autoderef(fcx: &FnCtxt, sp: Span, base_ty: ty::t, } // We've reached the recursion limit, error gracefully. - fcx.tcx().sess.span_err(sp, - format!("reached the recursion limit while auto-dereferencing {}", - base_ty.repr(fcx.tcx())).as_slice()); + span_err!(fcx.tcx().sess, sp, E0055, + "reached the recursion limit while auto-dereferencing {}", + base_ty.repr(fcx.tcx())); (ty::mk_err(), 0, None) } @@ -1581,11 +1561,11 @@ fn try_overloaded_call(fcx: &FnCtxt, write_call(fcx, call_expression, output_type); if !fcx.tcx().sess.features.overloaded_calls.get() { - fcx.tcx().sess.span_err(call_expression.span, - "overloaded calls are experimental"); - fcx.tcx().sess.span_note(call_expression.span, - "add `#[feature(overloaded_calls)]` to \ - the crate attributes to enable"); + span_err!(fcx.tcx().sess, call_expression.span, E0056, + "overloaded calls are experimental"); + span_note!(fcx.tcx().sess, call_expression.span, + "add `#[feature(overloaded_calls)]` to \ + the crate attributes to enable"); } return true @@ -1783,14 +1763,12 @@ fn check_argument_types(fcx: &FnCtxt, match ty::get(tuple_type).sty { ty::ty_tup(ref arg_types) => { if arg_types.len() != args.len() { - let msg = format!( - "this function takes {} parameter{} \ - but {} parameter{} supplied", - arg_types.len(), - if arg_types.len() == 1 {""} else {"s"}, - args.len(), - if args.len() == 1 {" was"} else {"s were"}); - tcx.sess.span_err(sp, msg.as_slice()); + span_err!(tcx.sess, sp, E0057, + "this function takes {} parameter{} but {} parameter{} supplied", + arg_types.len(), + if arg_types.len() == 1 {""} else {"s"}, + args.len(), + if args.len() == 1 {" was"} else {"s were"}); err_args(args.len()) } else { (*arg_types).clone() @@ -1798,21 +1776,17 @@ fn check_argument_types(fcx: &FnCtxt, } ty::ty_nil => { if args.len() != 0 { - let msg = format!( - "this function takes 0 parameters \ - but {} parameter{} supplied", - args.len(), - if args.len() == 1 {" was"} else {"s were"}); - tcx.sess.span_err(sp, msg.as_slice()); + span_err!(tcx.sess, sp, E0058, + "this function takes 0 parameters but {} parameter{} supplied", + args.len(), + if args.len() == 1 {" was"} else {"s were"}); } Vec::new() } _ => { - tcx.sess - .span_err(sp, - "cannot use call notation; the first type \ - parameter for the function trait is neither a \ - tuple nor unit"); + span_err!(tcx.sess, sp, E0059, + "cannot use call notation; the first type parameter \ + for the function trait is neither a tuple nor unit"); err_args(supplied_arg_count) } } @@ -1822,29 +1796,22 @@ fn check_argument_types(fcx: &FnCtxt, if supplied_arg_count >= expected_arg_count { fn_inputs.iter().map(|a| *a).collect() } else { - let msg = format!( + span_err!(tcx.sess, sp, E0060, "this function takes at least {} parameter{} \ but {} parameter{} supplied", - expected_arg_count, - if expected_arg_count == 1 {""} else {"s"}, - supplied_arg_count, - if supplied_arg_count == 1 {" was"} else {"s were"}); - - tcx.sess.span_err(sp, msg.as_slice()); - + expected_arg_count, + if expected_arg_count == 1 {""} else {"s"}, + supplied_arg_count, + if supplied_arg_count == 1 {" was"} else {"s were"}); err_args(supplied_arg_count) } } else { - let msg = format!( - "this function takes {} parameter{} \ - but {} parameter{} supplied", - expected_arg_count, - if expected_arg_count == 1 {""} else {"s"}, - supplied_arg_count, - if supplied_arg_count == 1 {" was"} else {"s were"}); - - tcx.sess.span_err(sp, msg.as_slice()); - + span_err!(tcx.sess, sp, E0061, + "this function takes {} parameter{} but {} parameter{} supplied", + expected_arg_count, + if expected_arg_count == 1 {""} else {"s"}, + supplied_arg_count, + if supplied_arg_count == 1 {" was"} else {"s were"}); err_args(supplied_arg_count) }; @@ -2730,11 +2697,9 @@ fn check_expr_with_unifier(fcx: &FnCtxt, error_happened = true; } Some((_, true)) => { - tcx.sess.span_err( - field.ident.span, - format!("field `{}` specified more than once", - token::get_ident(field.ident - .node)).as_slice()); + span_err!(fcx.tcx().sess, field.ident.span, E0062, + "field `{}` specified more than once", + token::get_ident(field.ident.node)); error_happened = true; } Some((field_id, false)) => { @@ -2772,11 +2737,10 @@ fn check_expr_with_unifier(fcx: &FnCtxt, } } - tcx.sess.span_err(span, - format!( - "missing field{}: {fields}", - if missing_fields.len() == 1 {""} else {"s"}, - fields = missing_fields.connect(", ")).as_slice()); + span_err!(tcx.sess, span, E0063, + "missing field{}: {}", + if missing_fields.len() == 1 {""} else {"s"}, + missing_fields.connect(", ")); } } @@ -2938,12 +2902,14 @@ fn check_expr_with_unifier(fcx: &FnCtxt, } } ast::ExprLit(_) => { - let error = if vst == ast::ExprVstoreSlice { - "`&\"string\"` has been removed; use `\"string\"` instead" + if vst == ast::ExprVstoreSlice { + span_err!(tcx.sess, expr.span, E0064, + "`&\"string\"` has been removed; use `\"string\"` instead"); } else { - "`box \"string\"` has been removed; use `\"string\".to_string()` instead" - }; - tcx.sess.span_err(expr.span, error); + span_err!(tcx.sess, expr.span, E0065, + "`box \"string\"` has been removed; use \ + `\"string\".to_string()` instead"); + } ty::mk_err() } _ => tcx.sess.span_bug(expr.span, "vstore modifier on non-sequence"), @@ -2977,9 +2943,8 @@ fn check_expr_with_unifier(fcx: &FnCtxt, } if !checked { - tcx.sess.span_err(expr.span, - "only the managed heap and exchange heap are \ - currently supported"); + span_err!(tcx.sess, expr.span, E0066, + "only the managed heap and exchange heap are currently supported"); fcx.write_ty(id, ty::mk_err()); } } @@ -3011,7 +2976,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt, let tcx = fcx.tcx(); 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 @@ -3077,7 +3042,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt, }; if is_newtype { // This is an obsolete struct deref - tcx.sess.span_err(expr.span, + span_err!(tcx.sess, expr.span, E0068, "single-field tuple-structs can \ no longer be dereferenced"); } else { @@ -3181,8 +3146,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt, ret_ty, ty::mk_nil()) { Ok(_) => { /* fall through */ } Err(_) => { - tcx.sess.span_err( - expr.span, + span_err!(tcx.sess, expr.span, E0069, "`return;` in function returning non-nil"); } }, @@ -3201,7 +3165,8 @@ fn check_expr_with_unifier(fcx: &FnCtxt, let tcx = fcx.tcx(); 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); @@ -3390,11 +3355,9 @@ fn check_expr_with_unifier(fcx: &FnCtxt, base_expr); } _ => { - tcx.sess - .span_err(path.span, - format!("`{}` does not name a structure", - pprust::path_to_string( - path)).as_slice()) + span_err!(tcx.sess, path.span, E0071, + "`{}` does not name a structure", + pprust::path_to_string(path)); } } } @@ -3766,10 +3729,10 @@ pub fn check_representable(tcx: &ty::ctxt, // caught by case 1. match ty::is_type_representable(tcx, sp, rty) { ty::SelfRecursive => { - tcx.sess.span_err( - sp, format!("illegal recursive {} type; \ - wrap the inner value in a box to make it representable", - designation).as_slice()); + span_err!(tcx.sess, sp, E0072, + "illegal recursive {} type; \ + wrap the inner value in a box to make it representable", + designation); return false } ty::Representable | ty::ContainsRecursive => (), @@ -3794,12 +3757,10 @@ pub fn check_instantiable(tcx: &ty::ctxt, -> bool { let item_ty = ty::node_id_to_type(tcx, item_id); if !ty::is_instantiable(tcx, item_ty) { - tcx.sess - .span_err(sp, - format!("this type cannot be instantiated without an \ - instance of itself; consider using \ - `Option<{}>`", - ppaux::ty_to_string(tcx, item_ty)).as_slice()); + span_err!(tcx.sess, sp, E0073, + "this type cannot be instantiated without an \ + instance of itself; consider using `Option<{}>`", + ppaux::ty_to_string(tcx, item_ty)); false } else { true @@ -3809,25 +3770,25 @@ pub fn check_instantiable(tcx: &ty::ctxt, pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) { let t = ty::node_id_to_type(tcx, id); 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; } match ty::get(t).sty { ty::ty_struct(did, ref substs) => { let fields = ty::lookup_struct_fields(tcx, did); 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; } let e = ty::lookup_field_type(tcx, did, fields.get(0).id, substs); if !fields.iter().all( |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; } if !ty::type_is_machine(e) { - tcx.sess.span_err(sp, "SIMD vector element type should be \ - machine type"); + span_err!(tcx.sess, sp, E0077, + "SIMD vector element type should be machine type"); return; } } @@ -3852,16 +3813,10 @@ pub fn check_enum_variants_sized(ccx: &CrateCtxt, // A struct value with an unsized final field is itself // unsized and we must track this in the type system. if !ty::type_is_sized(ccx.tcx, *t) { - ccx.tcx - .sess - .span_err( - args.get(i).ty.span, - 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()); + span_err!(ccx.tcx.sess, args.get(i).ty.span, E0078, + "type `{}` is dynamically sized. dynamically sized types may only \ + appear as the final type in a variant", + ppaux::ty_to_string(ccx.tcx, *t)); } } }, @@ -3947,14 +3902,12 @@ pub fn check_enum_variants(ccx: &CrateCtxt, 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(_) => { - 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) => { - ccx.tcx - .sess - .span_err(e.span, - format!("expected constant: {}", - *err).as_slice()); + span_err!(ccx.tcx.sess, e.span, E0080, + "expected constant: {}", *err); } } }, @@ -3963,16 +3916,18 @@ pub fn check_enum_variants(ccx: &CrateCtxt, // Check for duplicate discriminant values if disr_vals.contains(¤t_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 match hint { attr::ReprAny | attr::ReprExtern => (), attr::ReprInt(sp, ity) => { if !disr_in_range(ccx, ity, current_disr_val) { - ccx.tcx.sess.span_err(v.span, - "discriminant value outside specified type"); - ccx.tcx.sess.span_note(sp, "discriminant type specified here"); + span_err!(ccx.tcx.sess, v.span, E0082, + "discriminant value outside specified type"); + span_note!(ccx.tcx.sess, sp, + "discriminant type specified here"); } } } @@ -3990,12 +3945,13 @@ pub fn check_enum_variants(ccx: &CrateCtxt, let hint = ty::lookup_repr_hint(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id }); if hint != attr::ReprAny && vs.len() <= 1 { - let msg = if vs.len() == 1 { - "unsupported representation for univariant enum" + if vs.len() == 1 { + span_err!(ccx.tcx.sess, sp, E0083, + "unsupported representation for univariant enum"); } 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); @@ -4241,15 +4197,13 @@ pub fn instantiate_path(fcx: &FnCtxt, segment: &ast::PathSegment) { for typ in segment.types.iter() { - fcx.tcx().sess.span_err( - typ.span, + span_err!(fcx.tcx().sess, typ.span, E0085, "type parameters may not appear here"); break; } for lifetime in segment.lifetimes.iter() { - fcx.tcx().sess.span_err( - lifetime.span, + span_err!(fcx.tcx().sess, lifetime.span, E0086, "lifetime parameters may not appear here"); break; } @@ -4288,14 +4242,11 @@ pub fn instantiate_path(fcx: &FnCtxt, if i < type_count { substs.types.push(space, t); } else if i == type_count { - fcx.tcx().sess.span_err( - typ.span, - format!( - "too many type parameters provided: \ - expected at most {} parameter(s) \ - but found {} parameter(s)", - type_count, - segment.types.len()).as_slice()); + span_err!(fcx.tcx().sess, typ.span, E0087, + "too many type parameters provided: \ + expected at most {} parameter(s) \ + but found {} parameter(s)", + type_count, segment.types.len()); substs.types.truncate(space, 0); } } @@ -4309,13 +4260,11 @@ pub fn instantiate_path(fcx: &FnCtxt, if i < region_count { substs.mut_regions().push(space, r); } else if i == region_count { - fcx.tcx().sess.span_err( - lifetime.span, - format!( - "too many lifetime parameters provided: \ - expected {} parameter(s) but found {} parameter(s)", - region_count, - segment.lifetimes.len()).as_slice()); + span_err!(fcx.tcx().sess, lifetime.span, E0088, + "too many lifetime parameters provided: \ + expected {} parameter(s) but found {} parameter(s)", + region_count, + segment.lifetimes.len()); substs.mut_regions().truncate(space, 0); } } @@ -4360,14 +4309,10 @@ pub fn instantiate_path(fcx: &FnCtxt, if provided_len < required_len { let qualifier = if desired.len() != required_len { "at least " } else { "" }; - fcx.tcx().sess.span_err( - span, - format!("too few type parameters provided: \ - expected {}{} parameter(s) \ - but found {} parameter(s)", - qualifier, - required_len, - provided_len).as_slice()); + span_err!(fcx.tcx().sess, span, E0089, + "too few type parameters provided: expected {}{} parameter(s) \ + but found {} parameter(s)", + qualifier, required_len, provided_len); substs.types.replace(space, Vec::from_elem(desired.len(), ty::mk_err())); return; @@ -4418,14 +4363,10 @@ pub fn instantiate_path(fcx: &FnCtxt, // Otherwise, too few were provided. Report an error and then // use inference variables. - fcx.tcx().sess.span_err( - span, - format!( - "too few lifetime parameters provided: \ - expected {} parameter(s) \ - but found {} parameter(s)", - desired.len(), - provided_len).as_slice()); + span_err!(fcx.tcx().sess, span, E0090, + "too few lifetime parameters provided: expected {} parameter(s) \ + but found {} parameter(s)", + desired.len(), provided_len); substs.mut_regions().replace( space, @@ -4547,10 +4488,9 @@ pub fn check_bounds_are_used(ccx: &CrateCtxt, for (i, b) in tps_used.iter().enumerate() { if !*b { - ccx.tcx.sess.span_err( - span, - format!("type parameter `{}` is unused", - token::get_ident(tps.get(i).ident)).as_slice()); + span_err!(ccx.tcx.sess, span, E0091, + "type parameter `{}` is unused", + token::get_ident(tps.get(i).ident)); } } } @@ -4586,10 +4526,8 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) { (0, Vec::new(), ty::mk_nil()) } op => { - tcx.sess.span_err(it.span, - format!("unrecognized atomic operation \ - function: `{}`", - op).as_slice()); + span_err!(tcx.sess, it.span, E0092, + "unrecognized atomic operation function: `{}`", op); return; } } @@ -4813,9 +4751,8 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) { ty::mk_tup(tcx, vec!(ty::mk_u64(), ty::mk_bool()))), ref other => { - tcx.sess.span_err(it.span, - format!("unrecognized intrinsic function: `{}`", - *other).as_slice()); + span_err!(tcx.sess, it.span, E0093, + "unrecognized intrinsic function: `{}`", *other); return; } } @@ -4833,11 +4770,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_n_tps = i_ty.generics.types.len(subst::FnSpace); if i_n_tps != n_tps { - tcx.sess.span_err(it.span, - format!("intrinsic has wrong number of type \ - parameters: found {}, expected {}", - i_n_tps, - n_tps).as_slice()); + span_err!(tcx.sess, it.span, E0094, + "intrinsic has wrong number of type \ + parameters: found {}, expected {}", + i_n_tps, n_tps); } else { require_same_types(tcx, None, diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 9bb5eae2ed2..0b26a641f8d 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -98,6 +98,9 @@ impl SpanHandler { pub fn span_warn(&self, sp: Span, msg: &str) { 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) { self.handler.emit(Some((&self.cm, sp)), msg, Note); } diff --git a/src/libsyntax/diagnostics/macros.rs b/src/libsyntax/diagnostics/macros.rs index b0260e1180f..b4af7205c42 100644 --- a/src/libsyntax/diagnostics/macros.rs +++ b/src/libsyntax/diagnostics/macros.rs @@ -49,3 +49,25 @@ macro_rules! span_err( ($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))* + ) +) diff --git a/src/libsyntax/diagnostics/plugin.rs b/src/libsyntax/diagnostics/plugin.rs index 6582d2e44c8..209296989fa 100644 --- a/src/libsyntax/diagnostics/plugin.rs +++ b/src/libsyntax/diagnostics/plugin.rs @@ -54,7 +54,8 @@ pub fn expand_diagnostic_used(ecx: &mut ExtCtxt, span: Span, with_registered_diagnostics(|diagnostics| { if !diagnostics.contains_key(&code.name) { 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()); } ()