From b4f483db9afe60a00be74200b5f42d05253432e6 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 9 Jan 2014 23:37:57 -0800 Subject: [PATCH 1/7] rustc: Add the __tt_map_insert and __tt_map_get_expr macros Behind the `__tt_map` feature gate. This feature name starts with a double underscore to emphasize it's a hack, but there's no precedent for naming features this way. --- src/librustc/front/feature_gate.rs | 10 ++- src/libsyntax/ext/base.rs | 13 ++- src/libsyntax/ext/tt_map.rs | 114 ++++++++++++++++++++++++++ src/libsyntax/lib.rs | 1 + src/test/compile-fail/gated-tt_map.rs | 14 ++++ src/test/run-pass/tt_map.rs | 18 ++++ 6 files changed, 165 insertions(+), 5 deletions(-) create mode 100644 src/libsyntax/ext/tt_map.rs create mode 100644 src/test/compile-fail/gated-tt_map.rs create mode 100644 src/test/run-pass/tt_map.rs diff --git a/src/librustc/front/feature_gate.rs b/src/librustc/front/feature_gate.rs index f2e525932ad8b..8f116e7babd2a 100644 --- a/src/librustc/front/feature_gate.rs +++ b/src/librustc/front/feature_gate.rs @@ -51,6 +51,9 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[ ("default_type_params", Active), ("quote", Active), + // This is a syntax extension hack + ("__tt_map", Active), + // These are used to test this portion of the compiler, they don't actually // mean anything ("test_accepted_feature", Accepted), @@ -214,9 +217,10 @@ impl Visitor<()> for Context { else if id == self.sess.ident_of("trace_macros") { self.gate_feature("trace_macros", path.span, "`trace_macros` is not \ stable enough for use and is subject to change"); - } - - else { + } else if id == self.sess.ident_of("__tt_map_insert") || + id == self.sess.ident_of("__tt_map_get_expr") { + self.gate_feature("__tt_map", path.span, "__tt_map_* is a hack"); + } else { for "e in quotes.iter() { if id == self.sess.ident_of(quote) { self.gate_feature("quote", path.span, quote + msg); diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index d22a1d697fcb4..c0660938f989e 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -259,6 +259,12 @@ pub fn syntax_expander_table() -> SyntaxEnv { syntax_expanders.insert(intern(&"trace_macros"), builtin_normal_expander( ext::trace_macros::expand_trace_macros)); + syntax_expanders.insert(intern(&"__tt_map_insert"), + builtin_normal_expander( + ext::tt_map::insert_expr)); + syntax_expanders.insert(intern(&"__tt_map_get_expr"), + builtin_normal_expander( + ext::tt_map::get_expr)); syntax_expanders } @@ -283,7 +289,9 @@ pub struct ExtCtxt<'a> { loader: &'a mut CrateLoader, mod_path: ~[ast::Ident], - trace_mac: bool + trace_mac: bool, + // State for the hacky __tt_map_* extensions + tt_maps: HashMap>, } impl<'a> ExtCtxt<'a> { @@ -295,7 +303,8 @@ impl<'a> ExtCtxt<'a> { backtrace: None, loader: loader, mod_path: ~[], - trace_mac: false + trace_mac: false, + tt_maps: HashMap::new() } } diff --git a/src/libsyntax/ext/tt_map.rs b/src/libsyntax/ext/tt_map.rs new file mode 100644 index 0000000000000..fff0f376481bf --- /dev/null +++ b/src/libsyntax/ext/tt_map.rs @@ -0,0 +1,114 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/* + * The token-tree map syntax extension maintains an arbitrary number + * of named maps from ident to token-tree. Token trees can be stored + * into a map with the `__tt_map_insert!` macro and retrieved as an + * expression with the `__tt_map_get_expr!` macro. + * + * This is a hack used to maintain the tables of constants used by + * the rustc error reporting system. In particular, it allows string + * literals to be reused in multiple places without duplication. + */ + +use ast; +use codemap::Span; +use ext::base::{ExtCtxt, MacResult, MRExpr, MRItem}; +use ext::build::AstBuilder; +use parse::token; +use parse::token::{gensym, get_ident}; +use parse::new_parser_from_tts; +use std::hashmap::HashMap; + +pub fn insert_expr(ecx: &mut ExtCtxt, sp: Span, + tts: &[ast::TokenTree]) -> MacResult { + + if tts.len() != 5 { + ecx.span_fatal(sp, "incorrect number of arguments"); + } + + let idxs = [1, 3]; + for i in idxs.iter() { + match &tts[*i] { + &ast::TTTok(_, token::COMMA) => (), + _ => ecx.span_fatal(sp, "expecting comma") + } + } + + let map_name = tree_2_name(ecx, &tts[0]); + let key_name = tree_2_name(ecx, &tts[2]); + let expr = tts[4].clone(); + + if !ecx.tt_maps.contains_key(&map_name) { + ecx.tt_maps.insert(map_name.clone(), HashMap::new()); + } + + let existed = { + let mut maybe_map = ecx.tt_maps.find_mut(&map_name); + let map = maybe_map.get_mut_ref(); + !map.insert(key_name, expr) + }; + + if existed { + let key_ident = get_ident(key_name); + let key_name = key_ident.get(); + ecx.span_fatal(sp, format!("key {} already exists in map", key_name)); + } + + // This item isn't used + let dummy_ident = ast::Ident::new(gensym("dummy_name")); + let dummy_item = ecx.item_mod(sp, dummy_ident, ~[], ~[], ~[]); + return MRItem(dummy_item); +} + +pub fn get_expr(ecx: &mut ExtCtxt, sp: Span, + tts: &[ast::TokenTree]) -> MacResult { + + if tts.len() != 3 { + ecx.span_fatal(sp, "incorrect number of arguments"); + } + + match &tts[1] { + &ast::TTTok(_, token::COMMA) => (), + _ => ecx.span_fatal(sp, "expecting comma") + } + + let map_name = tree_2_name(ecx, &tts[0]); + let key_name = tree_2_name(ecx, &tts[2]); + + match ecx.tt_maps.find(&map_name) { + Some(map) => { + match map.find(&key_name) { + Some(map_tree) => { + MRExpr(tree_2_expr(ecx, map_tree)) + } + None => { + let key_ident = get_ident(key_name); + let key_name = key_ident.get(); + ecx.span_fatal(sp, format!("key {} does not exist in map", key_name)); + } + } + } + None => { + ecx.span_fatal(sp, "map does not exist"); + } + } +} + +fn tree_2_name(ecx: &ExtCtxt, tts: &ast::TokenTree) -> ast::Name { + let mut p = new_parser_from_tts(ecx.parse_sess(), ecx.cfg.clone(), ~[tts.clone()]); + return p.parse_ident().name; +} + +fn tree_2_expr(ecx: &ExtCtxt, tts: &ast::TokenTree) -> @ast::Expr { + let mut p = new_parser_from_tts(ecx.parse_sess(), ecx.cfg.clone(), ~[tts.clone()]); + return p.parse_expr(); +} diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 613416bed1c14..764239b77e9a9 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -97,6 +97,7 @@ pub mod ext { pub mod concat_idents; pub mod log_syntax; pub mod source_util; + pub mod tt_map; pub mod trace_macros; } diff --git a/src/test/compile-fail/gated-tt_map.rs b/src/test/compile-fail/gated-tt_map.rs new file mode 100644 index 0000000000000..359ba9cf2c4d6 --- /dev/null +++ b/src/test/compile-fail/gated-tt_map.rs @@ -0,0 +1,14 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + __tt_map_insert!(A, B, C); //~ ERROR __tt_map_* is a hack + let _foo = __tt_map_get_expr!(A, B, C); //~ ERROR __tt_map_* is a hack +} diff --git a/src/test/run-pass/tt_map.rs b/src/test/run-pass/tt_map.rs new file mode 100644 index 0000000000000..24137a88be2c2 --- /dev/null +++ b/src/test/run-pass/tt_map.rs @@ -0,0 +1,18 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + + let j = 2; + mod m { __tt_map_insert!(my_tt_map, i, j) } + + let k = __tt_map_get_expr!(my_tt_map, i); + assert!(j == k); +} From dda818b9fd3b48af47b2b3b29c21fe9b539faa3e Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 10 Jan 2014 14:43:36 -0800 Subject: [PATCH 2/7] rustc: Introduce a new diagnostic code registry This provides a way to create stable diagnostic codes, while keeping the overal burden on compiler writers low, and introducing a way to incrementally provide extended documentation of diagnostics. --- src/librustc/diag_db.md | 11 +++++++ src/librustc/diag_db.rs | 21 ++++++++++++ src/librustc/diag_index.rs | 19 +++++++++++ src/librustc/diag_macros.rs | 65 +++++++++++++++++++++++++++++++++++++ src/librustc/lib.rs | 10 ++++++ 5 files changed, 126 insertions(+) create mode 100644 src/librustc/diag_db.md create mode 100644 src/librustc/diag_db.rs create mode 100644 src/librustc/diag_index.rs create mode 100644 src/librustc/diag_macros.rs diff --git a/src/librustc/diag_db.md b/src/librustc/diag_db.md new file mode 100644 index 0000000000000..8f90416e96ac2 --- /dev/null +++ b/src/librustc/diag_db.md @@ -0,0 +1,11 @@ +desc_diag!(A0000, " + +This error occurs when you are testing the new Rust error reporter. + +``` +a systems language +pursuing the trifecta +safe, concurrent, fast +``` + +"), diff --git a/src/librustc/diag_db.rs b/src/librustc/diag_db.rs new file mode 100644 index 0000000000000..bd93c21ac19a4 --- /dev/null +++ b/src/librustc/diag_db.rs @@ -0,0 +1,21 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! The diagnostic database. +//! +//! Extended information about Rust diagnostics is included in the +//! diag_db.md file and can be loaded at runtime with the `load` +//! function. + +#[cfg(not(stage0))] + +pub fn load() -> ~[(&'static str, &'static str, &'static str)] { + ~[include!("diag_db.md")] +} diff --git a/src/librustc/diag_index.rs b/src/librustc/diag_index.rs new file mode 100644 index 0000000000000..62401c6dff515 --- /dev/null +++ b/src/librustc/diag_index.rs @@ -0,0 +1,19 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! The diagnostic registry +//! +//! All diagnostic codes must be registered here. To add a new +//! diagnostic code just go to the end of the file and add a new +//! line with a code that is one greater than the previous. + +#[cfg(not(stage0))]; + +reg_diag!(A0000) diff --git a/src/librustc/diag_macros.rs b/src/librustc/diag_macros.rs new file mode 100644 index 0000000000000..84a2eb67c543a --- /dev/null +++ b/src/librustc/diag_macros.rs @@ -0,0 +1,65 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! The macros for managing the Rust compiler's diagnostic codes. + +#[cfg(not(stage0))]; +#[macro_escape]; + +/// Register a diagnostic code at compile time +/// +/// Registers a diagnostic code at compile time so it can be used later +/// for reporting a diagnostic. All diagnostic codes must be registered once +/// and only once before use (lexically) in `alert_*!` or `desc_diag!` +/// macros. +/// +/// Registration of diagnostics ensures that only known diagnostic codes are +/// used in diagnostic messages and only known diagnostic codes have extended +/// descriptions. It also creates a central place where all existing +/// diagnostic codes (both in use and not) are stored so that it is easy +/// to pick the next available diagnostic code when creating a new one. +macro_rules! reg_diag ( + ($name: tt) => { + __tt_map_insert!(DIAGNOSTIC_REGISTRY, $name, $name) + } +) + +/// Raise a diagnostic at the 'error' level +/// +/// Report a diagnostic, registering its message literal at compile time so that +/// it can be retreived later (at compile time) by the `desc_diag!` macro. +/// +/// This must be called (lexically) before a `desc_diag` on the same diagnostic code. +macro_rules! alert_error ( + ($sess: expr, $name: tt, $msg: tt, $($arg: tt)*) => { { + // Validate that the diagnostic code is registered + let _ = stringify!(__tt_map_get_expr!(DIAGNOSTIC_REGISTRY, $name)); + // Insert the diagnostic message into the DIAGNOSTIC_MSG table + // so that desc_diag can retrieve it later. This also prevents the + // same diagnostic from being raised in two different places. + mod insert { __tt_map_insert!(DIAGNOSTIC_MSG, $name, $msg) } + // Report the diagnostic + let msg = format!($msg, $($arg)*); + let msg = format!("{}: {}", stringify!($name), msg); + $sess.err(msg); + } } +) + +/// Describe a diagnostic code and return info about it at runtime +/// +/// Returns a tuple of strings containing (the diagnostic code, the diagnostic +/// message reported for the code, the extended description of the diagnostic). +/// Repated calls to this macro can be used to provide extended documentation about +/// errors and to build up a database of diagnostic information. +macro_rules! desc_diag ( + ($name: tt, $desc: expr) => { + (stringify!($name), __tt_map_get_expr!(DIAGNOSTIC_MSG, $name), $desc) + } +) diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index edcefdf659402..24851c3815f62 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -58,6 +58,12 @@ use syntax::diagnostic::Emitter; use syntax::diagnostic; use syntax::parse; +// Define the diagnostic macros +pub mod diag_macros; +// The index of all diagnostic codes used by this crate. This must be defined +// lexically before any diagnostics are used. +pub mod diag_index; + pub mod middle { pub mod trans; pub mod ty; @@ -405,3 +411,7 @@ pub fn main_args(args: &[~str]) -> int { monitor(proc() run_compiler(owned_args)); 0 } + +// The database of extended diagnostic descriptions. Must come lexically +// after all uses of diagnostics. See `diag_macros` for why. +pub mod diag_db; From 24cc6bd220ece94b3828e752f1ab2a294b04373e Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 10 Jan 2014 18:33:03 -0800 Subject: [PATCH 3/7] Introduce more diagnostic infrastructure --- src/librustc/diag_db.md | 12 +-- src/librustc/diag_db.rs | 2 - src/librustc/diag_index.rs | 3 +- src/librustc/diag_macros.rs | 65 ------------- src/librustc/lib.rs | 1 + src/libsyntax/diag_db.md | 1 + src/libsyntax/diag_db.rs | 115 +++++++++++++++++++++++ src/libsyntax/diag_index.rs | 9 ++ src/libsyntax/diag_macros.rs | 177 +++++++++++++++++++++++++++++++++++ src/libsyntax/diagnostic.rs | 35 ++++++- src/libsyntax/lib.rs | 10 ++ 11 files changed, 346 insertions(+), 84 deletions(-) delete mode 100644 src/librustc/diag_macros.rs create mode 100644 src/libsyntax/diag_db.md create mode 100644 src/libsyntax/diag_db.rs create mode 100644 src/libsyntax/diag_index.rs create mode 100644 src/libsyntax/diag_macros.rs diff --git a/src/librustc/diag_db.md b/src/librustc/diag_db.md index 8f90416e96ac2..36c13b6da5271 100644 --- a/src/librustc/diag_db.md +++ b/src/librustc/diag_db.md @@ -1,11 +1 @@ -desc_diag!(A0000, " - -This error occurs when you are testing the new Rust error reporter. - -``` -a systems language -pursuing the trifecta -safe, concurrent, fast -``` - -"), +("", "", "") /* placeholder */ \ No newline at end of file diff --git a/src/librustc/diag_db.rs b/src/librustc/diag_db.rs index bd93c21ac19a4..03b73661849d5 100644 --- a/src/librustc/diag_db.rs +++ b/src/librustc/diag_db.rs @@ -14,8 +14,6 @@ //! diag_db.md file and can be loaded at runtime with the `load` //! function. -#[cfg(not(stage0))] - pub fn load() -> ~[(&'static str, &'static str, &'static str)] { ~[include!("diag_db.md")] } diff --git a/src/librustc/diag_index.rs b/src/librustc/diag_index.rs index 62401c6dff515..4e3a08e68b125 100644 --- a/src/librustc/diag_index.rs +++ b/src/librustc/diag_index.rs @@ -14,6 +14,5 @@ //! diagnostic code just go to the end of the file and add a new //! line with a code that is one greater than the previous. -#[cfg(not(stage0))]; - reg_diag!(A0000) +reg_diag!(A0001) diff --git a/src/librustc/diag_macros.rs b/src/librustc/diag_macros.rs deleted file mode 100644 index 84a2eb67c543a..0000000000000 --- a/src/librustc/diag_macros.rs +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! The macros for managing the Rust compiler's diagnostic codes. - -#[cfg(not(stage0))]; -#[macro_escape]; - -/// Register a diagnostic code at compile time -/// -/// Registers a diagnostic code at compile time so it can be used later -/// for reporting a diagnostic. All diagnostic codes must be registered once -/// and only once before use (lexically) in `alert_*!` or `desc_diag!` -/// macros. -/// -/// Registration of diagnostics ensures that only known diagnostic codes are -/// used in diagnostic messages and only known diagnostic codes have extended -/// descriptions. It also creates a central place where all existing -/// diagnostic codes (both in use and not) are stored so that it is easy -/// to pick the next available diagnostic code when creating a new one. -macro_rules! reg_diag ( - ($name: tt) => { - __tt_map_insert!(DIAGNOSTIC_REGISTRY, $name, $name) - } -) - -/// Raise a diagnostic at the 'error' level -/// -/// Report a diagnostic, registering its message literal at compile time so that -/// it can be retreived later (at compile time) by the `desc_diag!` macro. -/// -/// This must be called (lexically) before a `desc_diag` on the same diagnostic code. -macro_rules! alert_error ( - ($sess: expr, $name: tt, $msg: tt, $($arg: tt)*) => { { - // Validate that the diagnostic code is registered - let _ = stringify!(__tt_map_get_expr!(DIAGNOSTIC_REGISTRY, $name)); - // Insert the diagnostic message into the DIAGNOSTIC_MSG table - // so that desc_diag can retrieve it later. This also prevents the - // same diagnostic from being raised in two different places. - mod insert { __tt_map_insert!(DIAGNOSTIC_MSG, $name, $msg) } - // Report the diagnostic - let msg = format!($msg, $($arg)*); - let msg = format!("{}: {}", stringify!($name), msg); - $sess.err(msg); - } } -) - -/// Describe a diagnostic code and return info about it at runtime -/// -/// Returns a tuple of strings containing (the diagnostic code, the diagnostic -/// message reported for the code, the extended description of the diagnostic). -/// Repated calls to this macro can be used to provide extended documentation about -/// errors and to build up a database of diagnostic information. -macro_rules! desc_diag ( - ($name: tt, $desc: expr) => { - (stringify!($name), __tt_map_get_expr!(DIAGNOSTIC_MSG, $name), $desc) - } -) diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 24851c3815f62..d71102fcab93d 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -59,6 +59,7 @@ use syntax::diagnostic; use syntax::parse; // Define the diagnostic macros +#[path = "../libsyntax/diag_macros.rs"] pub mod diag_macros; // The index of all diagnostic codes used by this crate. This must be defined // lexically before any diagnostics are used. diff --git a/src/libsyntax/diag_db.md b/src/libsyntax/diag_db.md new file mode 100644 index 0000000000000..36c13b6da5271 --- /dev/null +++ b/src/libsyntax/diag_db.md @@ -0,0 +1 @@ +("", "", "") /* placeholder */ \ No newline at end of file diff --git a/src/libsyntax/diag_db.rs b/src/libsyntax/diag_db.rs new file mode 100644 index 0000000000000..721fbccbcf29e --- /dev/null +++ b/src/libsyntax/diag_db.rs @@ -0,0 +1,115 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! The diagnostic database. +//! +//! Extended information about Rust diagnostics is included in the +//! diag_db.md file and can be loaded at runtime with the `load` +//! function. + +use std::cell::RefCell; +use std::hashmap::HashMap; + +pub fn load() -> ~[RawInfo] { + ~[include!("diag_db.md")] +} + +pub type RawInfo = (&'static str, &'static str, &'static str); +pub type Initializer = fn() -> ~[RawInfo]; + +#[deriving(Clone)] +pub struct DiagnosticInfo { + code: &'static str, + msg: &'static str, + desc: &'static str +} + +pub struct DiagnosticDb { + state: RefCell +} + +pub enum DiagnosticDbState { + Uninitialized(~[Initializer]), + Initialized(HashMap<&'static str, DiagnosticInfo>) +} + +impl DiagnosticDb { + pub fn new(initializers: ~[Initializer]) -> DiagnosticDb { + DiagnosticDb { + state: RefCell::new(Uninitialized(initializers)) + } + } + + fn get_map(&self, f: |&mut HashMap<&'static str, DiagnosticInfo>| -> T) -> T { + let mut new_map; + { + let mut state = self.state.borrow_mut(); + match *state.get() { + Uninitialized(ref initializers) => { + let mut map = HashMap::new(); + for initr in initializers.iter() { + let raw_info = (*initr)(); + for &(code, msg, desc) in raw_info.iter() { + let info = DiagnosticInfo { code: code, msg: msg, desc: desc }; + map.insert(code, info); + } + } + new_map = Some(map); + } + Initialized(ref mut map) => { + return f(map); + } + } + } + + match new_map { + Some(new_map) => { + self.state.set(Initialized(new_map)); + return self.get_map(f); + } + None => unreachable!() + } + } + + pub fn get_info(&self, code: &str) -> Option { + self.get_map(|map| { + match map.find_equiv(&code) { + Some(&info) => Some(info), + None => None + } + }) + } +} + +impl DiagnosticInfo { + /// Returns a markdown-formatted explanation of the diagnostic + pub fn format(&self) -> ~str { + format!("\\# {}: {}\n\n{}", self.code, self.msg, self.desc.trim()) + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn smoke_test() { + fn load() -> ~[RawInfo] { + ~[("A0000", "message", "description")] + } + + let db = DiagnosticDb::new(~[load]); + let info = db.get_info("A0000"); + let text = info.unwrap().format(); + assert!(text.contains("A0000")); + assert!(text.contains("message")); + assert!(text.contains("description")); + } +} diff --git a/src/libsyntax/diag_index.rs b/src/libsyntax/diag_index.rs new file mode 100644 index 0000000000000..e6c760257380c --- /dev/null +++ b/src/libsyntax/diag_index.rs @@ -0,0 +1,9 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. diff --git a/src/libsyntax/diag_macros.rs b/src/libsyntax/diag_macros.rs new file mode 100644 index 0000000000000..210dcfba0684b --- /dev/null +++ b/src/libsyntax/diag_macros.rs @@ -0,0 +1,177 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! The macros for managing the Rust compiler's diagnostic codes. + +#[macro_escape]; + +/// Register a diagnostic code at compile time +/// +/// Registers a diagnostic code at compile time so it can be used later +/// for reporting a diagnostic. All diagnostic codes must be registered once +/// and only once before use (lexically) in `alert_*!` or `desc_diag!` +/// macros. +/// +/// Registration of diagnostics ensures that only known diagnostic codes are +/// used in diagnostic messages and only known diagnostic codes have extended +/// descriptions. It also creates a central place where all existing +/// diagnostic codes (both in use and not) are stored so that it is easy +/// to pick the next available diagnostic code when creating a new one. +#[cfg(not(stage0))] +macro_rules! reg_diag ( + ($name: tt) => { + __tt_map_insert!(DIAGNOSTIC_REGISTRY, $name, $name) + } +) + +#[cfg(stage0)] +macro_rules! reg_diag ( + ($name: tt) => { + } +) + +#[cfg(not(stage0))] +macro_rules! reg_diag_msg ( + ($name: tt, $msg: tt) => { { + // Validate that the diagnostic code is registered + let _ = stringify!(__tt_map_get_expr!(DIAGNOSTIC_REGISTRY, $name)); + // Insert the diagnostic message into the DIAGNOSTIC_MSG table + // so that desc_diag can retrieve it later. This also prevents the + // same diagnostic from being raised in two different places. + mod insert { __tt_map_insert!(DIAGNOSTIC_MSG, $name, $msg) } + } } +) + +#[cfg(stage0)] +macro_rules! reg_diag_msg ( + ($name: tt, $msg: tt) => { { + } } +) + +macro_rules! report_diag ( + ($f: expr, $name: tt, $msg: expr, $($arg: expr), *) => { { + reg_diag_msg!($name, $msg); + let msg: &str = format!($msg, $($arg), *); + $f(stringify!($name), msg); + } }; + ($f: expr, $name: tt, $msg: expr) => { { + reg_diag_msg!($name, $msg); + $f(stringify!($name), $msg); + } } +) + +macro_rules! report_diag_sp ( + ($f: expr, $sp: expr, $name: tt, $msg: expr, $($arg: expr), *) => { { + reg_diag_msg!($name, $msg); + let msg: &str = format!($msg, $($arg), *); + $f(sp, stringify!($name), msg); + } }; + ($f: expr, $sp: expr, $name: tt, $msg: expr) => { { + reg_diag_msg!($name, $msg); + $f(sp, stringify!($name), $msg); + } } +) + +/// Raise a diagnostic at the 'fatal' level +/// +/// Report a diagnostic, registering its message literal at compile time so that +/// it can be retreived later (at compile time) by the `desc_diag!` macro. +/// +/// This must be called (lexically) before a `desc_diag` on the same diagnostic code. +macro_rules! alert_fatal ( + ($sess: expr, $name: tt, $msg: expr, $($arg: expr), *) => ( + report_diag!(|c, m| $sess.fatal_with_diagnostic_code(c, m), + $name, $msg, $($arg), *); + ); + ($sess: expr, $name: tt, $msg: expr) => ( + report_diag!(|c, m| $sess.fatal_with_diagnostic_code(c, m), + $name, $msg); + ) +) + +/// Raise a diagnostic at the 'error' level +macro_rules! alert_err ( + ($sess: expr, $name: tt, $msg: expr, $($arg: expr), *) => ( + report_diag!(|c, m| $sess.err_with_diagnostic_code(c, m), + $name, $msg, $($arg), *); + ); + ($sess: expr, $name: tt, $msg: expr) => ( + report_diag!(|c, m| $sess.err_with_diagnostic_code(c, m), + $name, $msg); + ) +) + +/// Raise a diagnostic at the 'error' level +macro_rules! alert_warn ( + ($sess: expr, $name: tt, $msg: expr, $($arg: expr), *) => ( + report_diag!(|c, m| $sess.warn_with_diagnostic_code(c, m), + $name, $msg, $($arg), *); + ); + ($sess: expr, $name: tt, $msg: expr) => ( + report_diag!(|c, m| $sess.warn_with_diagnostic_code(c, m), + $name, $msg); + ) +) + +/// Raise a diagnostic at the 'fatal' level +macro_rules! span_fatal ( + ($sess: expr, $sp: expr, $name: tt, $msg: expr, $($arg: expr), *) => ( + report_diag!(|c, m| $sess.span_fatal_with_diagnostic_code($sp, c, m), + $name, $msg, $($arg), *); + ); + ($sess: expr, $sp: expr, $name: tt, $msg: expr) => ( + report_diag!(|c, m| $sess.span_fatal_with_diagnostic_code($sp, c, m), + $name, $msg); + ) +) + +/// Raise a diagnostic at the 'error' level +macro_rules! span_err ( + ($sess: expr, $sp: expr, $name: tt, $msg: expr, $($arg: expr), *) => ( + report_diag!(|c, m| $sess.span_err_with_diagnostic_code($sp, c, m), + $name, $msg, $($arg), *); + ); + ($sess: expr, $sp: expr, $name: tt, $msg: expr) => ( + report_diag!(|c, m| $sess.span_err_with_diagnostic_code($sp, c, m), + $name, $msg); + ) +) + +/// Raise a diagnostic at the 'warning' level +macro_rules! span_warn ( + ($sess: expr, $sp: expr, $name: tt, $msg: expr, $($arg: expr), *) => ( + report_diag!(|c, m| $sess.span_warn_with_diagnostic_code($sp, c, m), + $name, $msg, $($arg), *); + ); + ($sess: expr, $sp: expr, $name: tt, $msg: expr) => ( + report_diag!(|c, m| $sess.span_warn_with_diagnostic_code($sp, c, m), + $name, $msg); + ) +) + +/// Describe a diagnostic code and return info about it at runtime +/// +/// Returns a tuple of strings containing (the diagnostic code, the diagnostic +/// message reported for the code, the extended description of the diagnostic). +/// Repated calls to this macro can be used to provide extended documentation about +/// errors and to build up a database of diagnostic information. +#[cfg(not(stage0))] +macro_rules! desc_diag ( + ($name: tt, $desc: expr) => { + (stringify!($name), __tt_map_get_expr!(DIAGNOSTIC_MSG, $name), $desc) + } +) + +#[cfg(stage0)] +macro_rules! desc_diag ( + ($name: tt, $desc: expr) => { + (stringify!($name), "unknown", $desc) + } +) diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 3f6540570b0ef..f4b0810546095 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -48,13 +48,24 @@ impl SpanHandler { self.handler.emit(Some((&*self.cm, sp)), msg, Fatal); fail!(FatalError); } + pub fn span_fatal_with_diagnostic_code(&self, sp: Span, code: &str, msg: &str) -> ! { + self.handler.emit_with_code(Some((&*self.cm, sp)), code, msg, Fatal); + fail!(); + } pub fn span_err(&self, sp: Span, msg: &str) { self.handler.emit(Some((&*self.cm, sp)), msg, Error); self.handler.bump_err_count(); } + pub fn span_err_with_diagnostic_code(&self, sp: Span, code: &str, msg: &str) { + self.handler.emit_with_code(Some((&*self.cm, sp)), code, msg, Error); + self.handler.bump_err_count(); + } pub fn span_warn(&self, sp: Span, msg: &str) { self.handler.emit(Some((&*self.cm, sp)), msg, Warning); } + pub fn span_warn_with_diagnostic_code(&self, sp: Span, code: &str, msg: &str) { + self.handler.emit_with_code(Some((&*self.cm, sp)), code, msg, Warning); + } pub fn span_note(&self, sp: Span, msg: &str) { self.handler.emit(Some((&*self.cm, sp)), msg, Note); } @@ -82,11 +93,19 @@ pub struct Handler { impl Handler { pub fn fatal(&self, msg: &str) -> ! { - self.emit.emit(None, msg, Fatal); + self.emit(None, msg, Fatal); + fail!(FatalError); + } + pub fn fatal_with_diagnostic_code(&self, code: &str, msg: &str) -> ! { + self.emit_with_code(None, code, msg, Fatal); fail!(FatalError); } pub fn err(&self, msg: &str) { - self.emit.emit(None, msg, Error); + self.emit(None, msg, Error); + self.bump_err_count(); + } + pub fn err_with_diagnostic_code(&self, code: &str, msg: &str) { + self.emit_with_code(None, code, msg, Error); self.bump_err_count(); } pub fn bump_err_count(&self) { @@ -111,10 +130,13 @@ impl Handler { self.fatal(s); } pub fn warn(&self, msg: &str) { - self.emit.emit(None, msg, Warning); + self.emit(None, msg, Warning); + } + pub fn warn_with_diagnostic_code(&self, code: &str, msg: &str) { + self.emit_with_code(None, code, msg, Warning); } pub fn note(&self, msg: &str) { - self.emit.emit(None, msg, Note); + self.emit(None, msg, Note); } pub fn bug(&self, msg: &str) -> ! { self.fatal(ice_msg(msg)); @@ -132,6 +154,11 @@ impl Handler { sp: Span, msg: &str, lvl: Level) { self.emit.custom_emit(cm, sp, msg, lvl); } + pub fn emit_with_code(&self, cmsp: Option<(&codemap::CodeMap, Span)>, + code: &str, msg: &str, lvl: Level) { + let msg = format!("{}: {}", code, msg); + self.emit.emit(cmsp, msg, lvl); + } } pub fn ice_msg(msg: &str) -> ~str { diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 764239b77e9a9..f260b02d0424d 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -37,6 +37,12 @@ extern mod serialize; extern mod term; extern mod collections; +// Define the diagnostic macros +pub mod diag_macros; +// The index of all diagnostic codes used by this crate. This must be defined +// lexically before any diagnostics are used. +pub mod diag_index; + pub mod util { pub mod interner; #[cfg(test)] @@ -101,3 +107,7 @@ pub mod ext { pub mod trace_macros; } + +// The database of extended diagnostic descriptions. Must come lexically +// after all uses of diagnostics. See `diag_macros` for why. +pub mod diag_db; From e5293224618bf8e519d43e8330030c7621b0352c Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 10 Jan 2014 23:42:14 -0800 Subject: [PATCH 4/7] Convert to new diagnostics This pairs almost every error in libsyntax and librustc with an error code, emitting with the macros: * alert_fatal!(cx, code, fmt, args); * alert_err!(cx, code, fmt, args); * alert_warn!(cx, code, fmt, args); * span_fatal!(cx, span, code, fmt, args); * span_err!(cx, span, code, fmt, args); * span_warn!(cx, span, code, fmt, args); * resolve_err!(cx, span, code, fmt, args); These macros call the methods 'fatal_without_diagnostic_code' etc. on any given context. For the most part the old diagnostic methods on the various sessions and handles and contexts have been renamed in a way that is obnoxious to call (use the macros), but the macro ExtCtxt still contains the simple `fatal` methods, etc. for ease of use by out of tree procedural macros. Lint errors are difficult to convert to this system because they don't use string literals for reporting errors, so they don't have their own codes yet. --- src/librustc/back/archive.rs | 10 +- src/librustc/back/link.rs | 53 +-- src/librustc/back/lto.rs | 6 +- src/librustc/diag_index.rs | 364 +++++++++++++++++- src/librustc/driver/driver.rs | 8 +- src/librustc/driver/session.rs | 42 +- src/librustc/front/feature_gate.rs | 10 +- src/librustc/front/test.rs | 6 +- src/librustc/lib.rs | 2 +- src/librustc/metadata/creader.rs | 16 +- src/librustc/metadata/loader.rs | 10 +- src/librustc/middle/borrowck/check_loans.rs | 48 +-- .../borrowck/gather_loans/gather_moves.rs | 14 +- src/librustc/middle/borrowck/mod.rs | 81 ++-- src/librustc/middle/check_const.rs | 34 +- src/librustc/middle/check_loop.rs | 8 +- src/librustc/middle/check_match.rs | 48 +-- src/librustc/middle/const_eval.rs | 10 +- src/librustc/middle/effect.rs | 8 +- src/librustc/middle/entry.rs | 14 +- src/librustc/middle/kind.rs | 56 +-- src/librustc/middle/lang_items.rs | 5 +- src/librustc/middle/lint.rs | 20 +- src/librustc/middle/liveness.rs | 20 +- src/librustc/middle/moves.rs | 6 +- src/librustc/middle/privacy.rs | 45 ++- src/librustc/middle/resolve.rs | 237 ++++++------ src/librustc/middle/resolve_lifetime.rs | 24 +- src/librustc/middle/subst.rs | 27 +- src/librustc/middle/trans/base.rs | 12 +- src/librustc/middle/trans/common.rs | 12 +- src/librustc/middle/trans/consts.rs | 2 +- src/librustc/middle/trans/debuginfo.rs | 15 +- src/librustc/middle/trans/foreign.rs | 20 +- src/librustc/middle/trans/glue.rs | 2 +- src/librustc/middle/trans/intrinsic.rs | 10 +- src/librustc/middle/trans/monomorphize.rs | 4 +- src/librustc/middle/ty.rs | 35 +- src/librustc/middle/typeck/astconv.rs | 100 ++--- src/librustc/middle/typeck/check/_match.rs | 46 +-- src/librustc/middle/typeck/check/method.rs | 30 +- src/librustc/middle/typeck/check/mod.rs | 268 +++++++------ src/librustc/middle/typeck/check/vtable.rs | 52 +-- src/librustc/middle/typeck/check/writeback.rs | 30 +- src/librustc/middle/typeck/coherence.rs | 22 +- src/librustc/middle/typeck/collect.rs | 20 +- .../middle/typeck/infer/error_reporting.rs | 124 +++--- src/librustc/middle/typeck/infer/mod.rs | 8 +- src/librustc/middle/typeck/mod.rs | 15 +- src/librustc/middle/typeck/variance.rs | 3 +- src/libsyntax/attr.rs | 13 +- src/libsyntax/diag_index.rs | 203 ++++++++++ src/libsyntax/diag_macros.rs | 60 +-- src/libsyntax/diagnostic.rs | 18 +- src/libsyntax/ext/asm.rs | 6 +- src/libsyntax/ext/base.rs | 39 +- src/libsyntax/ext/bytes.rs | 12 +- src/libsyntax/ext/concat.rs | 4 +- src/libsyntax/ext/concat_idents.rs | 4 +- src/libsyntax/ext/deriving/default.rs | 3 +- src/libsyntax/ext/deriving/mod.rs | 9 +- src/libsyntax/ext/deriving/primitive.rs | 8 +- src/libsyntax/ext/deriving/rand.rs | 3 +- src/libsyntax/ext/deriving/zero.rs | 3 +- src/libsyntax/ext/env.rs | 6 +- src/libsyntax/ext/expand.rs | 98 ++--- src/libsyntax/ext/fmt.rs | 2 +- src/libsyntax/ext/format.rs | 66 ++-- src/libsyntax/ext/quote.rs | 2 +- src/libsyntax/ext/registrar.rs | 3 +- src/libsyntax/ext/source_util.rs | 6 +- src/libsyntax/ext/trace_macros.rs | 2 +- src/libsyntax/ext/tt/macro_parser.rs | 22 +- src/libsyntax/ext/tt/macro_rules.rs | 44 ++- src/libsyntax/ext/tt/transcribe.rs | 33 +- src/libsyntax/ext/tt_map.rs | 14 +- src/libsyntax/parse/attr.rs | 9 +- src/libsyntax/parse/comments.rs | 2 +- src/libsyntax/parse/lexer.rs | 12 +- src/libsyntax/parse/mod.rs | 6 +- src/libsyntax/parse/obsolete.rs | 2 +- src/libsyntax/parse/parser.rs | 277 ++++++------- 82 files changed, 1880 insertions(+), 1173 deletions(-) diff --git a/src/librustc/back/archive.rs b/src/librustc/back/archive.rs index 18aef17b9eb77..55d93760cc168 100644 --- a/src/librustc/back/archive.rs +++ b/src/librustc/back/archive.rs @@ -55,8 +55,8 @@ fn run_ar(sess: Session, args: &str, cwd: Option<&Path>, Ok(mut prog) => { let o = prog.finish_with_output(); if !o.status.success() { - sess.err(format!("{} {} failed with: {}", ar, args.connect(" "), - o.status)); + alert_err!(sess, A0344, "{} {} failed with: {}", ar, args.connect(" "), + o.status); sess.note(format!("stdout ---\n{}", str::from_utf8(o.output).unwrap())); sess.note(format!("stderr ---\n{}", str::from_utf8(o.error).unwrap())); sess.abort_if_errors(); @@ -64,7 +64,7 @@ fn run_ar(sess: Session, args: &str, cwd: Option<&Path>, o }, Err(e) => { - sess.err(format!("could not exec `{}`: {}", ar, e)); + alert_err!(sess, A0345, "could not exec `{}`: {}", ar, e); sess.abort_if_errors(); fail!("rustc::back::archive::run_ar() should not reach this point"); } @@ -206,8 +206,8 @@ impl Archive { if test.exists() { return test } } } - self.sess.fatal(format!("could not find native static library `{}`, \ - perhaps an -L flag is missing?", name)); + alert_fatal!(self.sess, A0051, "could not find native static library `{}`, \ + perhaps an -L flag is missing?", name); } } diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 531b8bf903457..fee7c26b435f5 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -54,14 +54,15 @@ pub enum OutputType { } pub fn llvm_err(sess: Session, msg: ~str) -> ! { - unsafe { + let msg = unsafe { let cstr = llvm::LLVMRustGetLastError(); if cstr == ptr::null() { - sess.fatal(msg); + msg } else { - sess.fatal(msg + ": " + str::raw::from_c_str(cstr)); + format!("{}: {}", msg, str::raw::from_c_str(cstr)) } - } + }; + alert_fatal!(sess, A0052, "LLVM error: {}", msg); } pub fn WriteOutputFile( @@ -189,7 +190,7 @@ pub mod write { for pass in sess.opts.custom_passes.iter() { pass.with_c_str(|s| { if !llvm::LLVMRustAddPass(mpm, s) { - sess.warn(format!("unknown pass {}, ignoring", *pass)); + alert_warn!(sess, A0335, "unknown pass {}, ignoring", *pass); } }) } @@ -334,14 +335,14 @@ pub mod write { match run::process_output(cc, args) { Ok(prog) => { if !prog.status.success() { - sess.err(format!("linking with `{}` failed: {}", cc, prog.status)); + alert_err!(sess, A0346, "linking with `{}` failed: {}", cc, prog.status); sess.note(format!("{} arguments: '{}'", cc, args.connect("' '"))); sess.note(str::from_utf8_owned(prog.error + prog.output).unwrap()); sess.abort_if_errors(); } }, Err(e) => { - sess.err(format!("could not exec the linker `{}`: {}", cc, e)); + alert_err!(sess, A0347, "could not exec the linker `{}`: {}", cc, e); sess.abort_if_errors(); } } @@ -782,8 +783,8 @@ fn get_system_tool(sess: Session, tool: &str) -> ~str { format!("{}/bin/arm-linux-androideabi-{}", *path, tool_str) } None => { - sess.fatal(format!("need Android NDK path for the '{}' tool \ - (--android-cross-path)", tool)) + alert_fatal!(sess, A0053, "need Android NDK path for the '{}' tool \ + (--android-cross-path)", tool) } }, _ => tool.to_owned(), @@ -794,7 +795,7 @@ fn remove(sess: Session, path: &Path) { match fs::unlink(path) { Ok(..) => {} Err(e) => { - sess.err(format!("failed to remove {}: {}", path.display(), e)); + alert_err!(sess, A0356, "failed to remove {}: {}", path.display(), e); } } } @@ -876,12 +877,14 @@ fn link_binary_output(sess: Session, let obj_is_writeable = is_writeable(&obj_filename); let out_is_writeable = is_writeable(&out_filename); if !out_is_writeable { - sess.fatal(format!("output file {} is not writeable -- check its permissions.", - out_filename.display())); + alert_fatal!(sess, A0054, + "output file {} is not writeable -- check its permissions.", + out_filename.display()); } else if !obj_is_writeable { - sess.fatal(format!("object file {} is not writeable -- check its permissions.", - obj_filename.display())); + alert_fatal!(sess, A0055, + "object file {} is not writeable -- check its permissions.", + obj_filename.display()); } match crate_type { @@ -957,8 +960,8 @@ fn link_rlib(sess: Session, match fs::File::create(&metadata).write(trans.metadata) { Ok(..) => {} Err(e) => { - sess.err(format!("failed to write {}: {}", - metadata.display(), e)); + alert_err!(sess, A0348, "failed to write {}: {}", + metadata.display(), e); sess.abort_if_errors(); } } @@ -1009,7 +1012,7 @@ fn link_staticlib(sess: Session, obj_filename: &Path, out_filename: &Path) { let name = sess.cstore.get_crate_data(cnum).name.clone(); let p = match *path { Some(ref p) => p.clone(), None => { - sess.err(format!("could not find rlib for: `{}`", name)); + alert_err!(sess, A0349, "could not find rlib for: `{}`", name); continue } }; @@ -1021,7 +1024,7 @@ fn link_staticlib(sess: Session, obj_filename: &Path, out_filename: &Path) { cstore::NativeUnknown => "library", cstore::NativeFramework => "framework", }; - sess.warn(format!("unlinked native {}: {}", name, *lib)); + alert_warn!(sess, A0336, "unlinked native {}: {}", name, *lib); } } } @@ -1052,14 +1055,14 @@ fn link_natively(sess: Session, dylib: bool, obj_filename: &Path, match prog { Ok(prog) => { if !prog.status.success() { - sess.err(format!("linking with `{}` failed: {}", cc_prog, prog.status)); + alert_err!(sess, A0350, "linking with `{}` failed: {}", cc_prog, prog.status); sess.note(format!("{} arguments: '{}'", cc_prog, cc_args.connect("' '"))); sess.note(str::from_utf8_owned(prog.error + prog.output).unwrap()); sess.abort_if_errors(); } }, Err(e) => { - sess.err(format!("could not exec the linker `{}`: {}", cc_prog, e)); + alert_err!(sess, A0351, "could not exec the linker `{}`: {}", cc_prog, e); sess.abort_if_errors(); } } @@ -1073,7 +1076,7 @@ fn link_natively(sess: Session, dylib: bool, obj_filename: &Path, [out_filename.as_str().unwrap().to_owned()]) { Ok(..) => {} Err(e) => { - sess.err(format!("failed to run dsymutil: {}", e)); + alert_err!(sess, A0352, "failed to run dsymutil: {}", e); sess.abort_if_errors(); } } @@ -1273,10 +1276,10 @@ fn add_upstream_rust_crates(args: &mut ~[~str], sess: Session, match fs::copy(&cratepath, &dst) { Ok(..) => {} Err(e) => { - sess.err(format!("failed to copy {} to {}: {}", + alert_err!(sess, A0353, "failed to copy {} to {}: {}", cratepath.display(), dst.display(), - e)); + e); sess.abort_if_errors(); } } @@ -1313,8 +1316,8 @@ fn add_upstream_rust_crates(args: &mut ~[~str], sess: Session, let cratepath = match *path { Some(ref p) => p.clone(), None => { - sess.err(format!("could not find dynamic library for: `{}`", - sess.cstore.get_crate_data(cnum).name)); + alert_err!(sess, A0354, "could not find dynamic library for: `{}`", + sess.cstore.get_crate_data(cnum).name); return } }; diff --git a/src/librustc/back/lto.rs b/src/librustc/back/lto.rs index 3c7d804435f2f..3fe1ec88af525 100644 --- a/src/librustc/back/lto.rs +++ b/src/librustc/back/lto.rs @@ -20,7 +20,7 @@ use std::libc; pub fn run(sess: session::Session, llmod: ModuleRef, tm: TargetMachineRef, reachable: &[~str]) { if sess.prefer_dynamic() { - sess.err("cannot prefer dynamic linking when performing LTO"); + alert_err!(sess, A0355, "cannot prefer dynamic linking when performing LTO"); sess.note("only 'staticlib' and 'bin' outputs are supported with LTO"); sess.abort_if_errors(); } @@ -31,7 +31,7 @@ pub fn run(sess: session::Session, llmod: ModuleRef, match *crate_type { session::CrateTypeExecutable | session::CrateTypeStaticlib => {} _ => { - sess.fatal("lto can only be run for executables and \ + alert_fatal!(sess, A0049, "lto can only be run for executables and \ static library outputs"); } } @@ -46,7 +46,7 @@ pub fn run(sess: session::Session, llmod: ModuleRef, let path = match path { Some(p) => p, None => { - sess.fatal(format!("could not find rlib for: `{}`", name)); + alert_fatal!(sess, A0050, "could not find rlib for: `{}`", name); } }; diff --git a/src/librustc/diag_index.rs b/src/librustc/diag_index.rs index 4e3a08e68b125..c4d716bd5f1a4 100644 --- a/src/librustc/diag_index.rs +++ b/src/librustc/diag_index.rs @@ -14,5 +14,365 @@ //! diagnostic code just go to the end of the file and add a new //! line with a code that is one greater than the previous. -reg_diag!(A0000) -reg_diag!(A0001) +all_diag!( + A0000, + A0001, + A0002, + A0003, + A0004, + A0005, + A0006, + A0007, + A0008, + A0009, + A0010, + A0011, + A0012, + A0013, + A0014, + A0015, + A0016, + A0017, + A0018, + A0019, + A0020, + A0021, + A0022, + A0023, + A0024, + A0025, + A0026, + A0027, + A0028, + A0029, + A0030, + A0031, + A0032, + A0033, + A0034, + A0035, + A0036, + A0037, + A0038, + A0039, + A0040, + A0041, + A0042, + A0043, + A0044, + A0045, + A0046, + A0047, + A0048, + A0049, + A0050, + A0051, + A0052, + A0053, + A0054, + A0055, + A0056, + A0057, + A0058, + A0059, + A0060, + A0061, + A0062, + A0063, + A0064, + A0065, + A0066, + A0067, + A0068, + A0069, + A0070, + A0071, + A0072, + A0073, + A0074, + A0075, + A0076, + A0077, + A0078, + A0079, + A0080, + A0081, + A0082, + A0083, + A0084, + A0085, + A0086, + A0087, + A0088, + A0089, + A0090, + A0091, + A0092, + A0093, + A0094, + A0095, + A0096, + A0097, + A0098, + A0099, + A0100, + A0101, + A0102, + A0103, + A0104, + A0105, + A0106, + A0107, + A0108, + A0109, + A0110, + A0111, + A0112, + A0113, + A0114, + A0115, + A0116, + A0117, + A0118, + A0119, + A0120, + A0121, + A0122, + A0123, + A0124, + A0125, + A0126, + A0127, + A0128, + A0129, + A0130, + A0131, + A0132, + A0133, + A0134, + A0135, + A0136, + A0137, + A0138, + A0139, + A0140, + A0141, + A0142, + A0143, + A0144, + A0145, + A0146, + A0147, + A0148, + A0149, + A0150, + A0151, + A0152, + A0153, + A0154, + A0155, + A0156, + A0157, + A0158, + A0159, + A0160, + A0161, + A0162, + A0163, + A0164, + A0165, + A0166, + A0167, + A0168, + A0169, + A0170, + A0171, + A0172, + A0173, + A0174, + A0175, + A0176, + A0177, + A0178, + A0179, + A0180, + A0181, + A0182, + A0183, + A0184, + A0185, + A0186, + A0187, + A0188, + A0189, + A0190, + A0191, + A0192, + A0193, + A0194, + A0195, + A0196, + A0197, + A0198, + A0199, + A0200, + A0201, + A0202, + A0203, + A0204, + A0205, + A0206, + A0207, + A0208, + A0209, + A0210, + A0211, + A0212, + A0213, + A0214, + A0215, + A0216, + A0217, + A0218, + A0219, + A0220, + A0221, + A0222, + A0223, + A0224, + A0225, + A0226, + A0227, + A0228, + A0229, + A0230, + A0231, + A0232, + A0233, + A0234, + A0235, + A0236, + A0237, + A0238, + A0239, + A0240, + A0241, + A0242, + A0243, + A0244, + A0245, + A0246, + A0247, + A0248, + A0249, + A0250, + A0251, + A0252, + A0253, + A0254, + A0255, + A0256, + A0257, + A0258, + A0259, + A0260, + A0261, + A0262, + A0263, + A0264, + A0265, + A0266, + A0267, + A0268, + A0269, + A0270, + A0271, + A0272, + A0273, + A0274, + A0275, + A0276, + A0277, + A0278, + A0279, + A0280, + A0281, + A0282, + A0283, + A0284, + A0285, + A0286, + A0287, + A0288, + A0289, + A0290, + A0291, + A0292, + A0293, + A0294, + A0295, + A0296, + A0297, + A0298, + A0299, + A0300, + A0301, + A0302, + A0303, + A0304, + A0305, + A0306, + A0307, + A0308, + A0309, + A0310, + A0311, + A0312, + A0313, + A0314, + A0315, + A0316, + A0317, + A0318, + A0319, + A0320, + A0321, + A0322, + A0323, + A0324, + A0325, + A0326, + A0327, + A0328, + A0329, + A0330, + A0331, + A0332, + A0333, + A0334, + A0335, + A0336, + A0337, + A0338, + A0339, + A0340, + A0341, + A0342, + A0343, + A0344, + A0345, + A0346, + A0347, + A0348, + A0349, + A0350, + A0351, + A0352, + A0353, + A0354, + A0355, + A0356, + A0357, + + LAST_DIAGNOSTIC // Just here to absorb the previous comma +) diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 0d45d5bdbab43..99974f74fcebf 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -479,7 +479,7 @@ fn write_out_deps(sess: Session, (true, None) => match *input { FileInput(..) => outputs.with_extension("d"), StrInput(..) => { - sess.warn("can not write --dep-info without a filename \ + alert_warn!(sess, A0338, "can not write --dep-info without a filename \ when compiling stdin."); return Ok(()); }, @@ -983,7 +983,7 @@ pub fn parse_pretty(sess: Session, name: &str) -> PpMode { &"expanded,identified" => PpmExpandedIdentified, &"identified" => PpmIdentified, _ => { - sess.fatal("argument to `pretty` must be one of `normal`, \ + alert_fatal!(sess, A0056, "argument to `pretty` must be one of `normal`, \ `expanded`, `typed`, `identified`, \ or `expanded,identified`"); } @@ -1142,14 +1142,14 @@ pub fn build_output_filenames(input: &Input, Some(ref out_file) => { let ofile = if sess.opts.output_types.len() > 1 { - sess.warn("ignoring specified output filename because multiple \ + alert_warn!(sess, A0341, "ignoring specified output filename because multiple \ outputs were requested"); None } else { Some(out_file.clone()) }; if *odir != None { - sess.warn("ignoring --out-dir flag due to -o flag."); + alert_warn!(sess, A0337, "ignoring --out-dir flag due to -o flag."); } OutputFilenames { out_directory: out_file.dir_path(), diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs index dc8598c10d0d0..c17aa1dee94f8 100644 --- a/src/librustc/driver/session.rs +++ b/src/librustc/driver/session.rs @@ -226,17 +226,29 @@ pub struct Session_ { pub type Session = @Session_; impl Session_ { - pub fn span_fatal(&self, sp: Span, msg: &str) -> ! { - self.span_diagnostic.span_fatal(sp, msg) + pub fn span_fatal_without_diagnostic_code(&self, sp: Span, msg: &str) -> ! { + self.span_diagnostic.span_fatal_without_diagnostic_code(sp, msg) } - pub fn fatal(&self, msg: &str) -> ! { - self.span_diagnostic.handler().fatal(msg) + pub fn span_fatal_with_diagnostic_code(&self, sp: Span, code: &str, msg: &str) -> ! { + self.span_diagnostic.span_fatal_with_diagnostic_code(sp, code, msg) } - pub fn span_err(&self, sp: Span, msg: &str) { - self.span_diagnostic.span_err(sp, msg) + pub fn fatal_without_diagnostic_code(&self, msg: &str) -> ! { + self.span_diagnostic.handler().fatal_without_diagnostic_code(msg) } - pub fn err(&self, msg: &str) { - self.span_diagnostic.handler().err(msg) + pub fn fatal_with_diagnostic_code(&self, code: &str, msg: &str) -> ! { + self.span_diagnostic.handler().fatal_with_diagnostic_code(code, msg) + } + pub fn span_err_without_diagnostic_code(&self, sp: Span, msg: &str) { + self.span_diagnostic.span_err_without_diagnostic_code(sp, msg) + } + pub fn span_err_with_diagnostic_code(&self, sp: Span, code: &str, msg: &str) { + self.span_diagnostic.span_err_with_diagnostic_code(sp, code, msg) + } + pub fn err_without_diagnostic_code(&self, msg: &str) { + self.span_diagnostic.handler().err_without_diagnostic_code(msg) + } + pub fn err_with_diagnostic_code(&self, code: &str, msg: &str) { + self.span_diagnostic.handler().err_with_diagnostic_code(code, msg) } pub fn err_count(&self) -> uint { self.span_diagnostic.handler().err_count() @@ -247,11 +259,17 @@ impl Session_ { pub fn abort_if_errors(&self) { self.span_diagnostic.handler().abort_if_errors() } - pub fn span_warn(&self, sp: Span, msg: &str) { - self.span_diagnostic.span_warn(sp, msg) + pub fn span_warn_without_diagnostic_code(&self, sp: Span, msg: &str) { + self.span_diagnostic.span_warn_without_diagnostic_code(sp, msg) + } + pub fn span_warn_with_diagnostic_code(&self, sp: Span, code: &str, msg: &str) { + self.span_diagnostic.span_warn_with_diagnostic_code(sp, code, msg) + } + pub fn warn_without_diagnostic_code(&self, msg: &str) { + self.span_diagnostic.handler().warn_without_diagnostic_code(msg) } - pub fn warn(&self, msg: &str) { - self.span_diagnostic.handler().warn(msg) + pub fn warn_with_diagnostic_code(&self, code: &str, msg: &str) { + self.span_diagnostic.handler().warn_with_diagnostic_code(code, msg) } pub fn span_note(&self, sp: Span, msg: &str) { self.span_diagnostic.span_note(sp, msg) diff --git a/src/librustc/front/feature_gate.rs b/src/librustc/front/feature_gate.rs index 8f116e7babd2a..93cf34e89243c 100644 --- a/src/librustc/front/feature_gate.rs +++ b/src/librustc/front/feature_gate.rs @@ -80,7 +80,7 @@ struct Context { impl Context { fn gate_feature(&self, feature: &str, span: Span, explain: &str) { if !self.has_feature(feature) { - self.sess.span_err(span, explain); + span_err!(self.sess, span, A0318, "{}", explain); self.sess.span_note(span, format!("add \\#[feature({})] to the \ crate attributes to enable", feature)); @@ -283,7 +283,7 @@ pub fn check_crate(sess: Session, crate: &ast::Crate) { match attr.meta_item_list() { None => { - sess.span_err(attr.span, "malformed feature attribute, \ + span_err!(sess, attr.span, A0319, "malformed feature attribute, \ expected #[feature(...)]"); } Some(list) => { @@ -291,7 +291,7 @@ pub fn check_crate(sess: Session, crate: &ast::Crate) { let name = match mi.node { ast::MetaWord(ref word) => (*word).clone(), _ => { - sess.span_err(mi.span, + span_err!(sess, mi.span, A0320, "malformed feature, expected just \ one word"); continue @@ -301,10 +301,10 @@ pub fn check_crate(sess: Session, crate: &ast::Crate) { .find(|& &(n, _)| name.equiv(&n)) { Some(&(name, Active)) => { cx.features.push(name); } Some(&(_, Removed)) => { - sess.span_err(mi.span, "feature has been removed"); + span_err!(sess, mi.span, A0321, "feature has been removed"); } Some(&(_, Accepted)) => { - sess.span_warn(mi.span, "feature has added to rust, \ + span_warn!(sess, mi.span, A0330, "feature has added to rust, \ directive not necessary"); } None => { diff --git a/src/librustc/front/test.rs b/src/librustc/front/test.rs index 2704e828ea463..8bd42e59283c5 100644 --- a/src/librustc/front/test.rs +++ b/src/librustc/front/test.rs @@ -95,7 +95,7 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> { ast::ItemFn(_, purity, _, _, _) if purity == ast::UnsafeFn => { let sess = self.cx.sess; - sess.span_fatal(i.span, + span_fatal!(sess, i.span, A0020, "unsafe functions cannot be used for \ tests"); } @@ -214,8 +214,8 @@ fn is_test_fn(cx: &TestCtxt, i: @ast::Item) -> bool { if has_test_attr && !has_test_signature(i) { let sess = cx.sess; - sess.span_err( - i.span, + span_err!(sess, + i.span, A0317, "functions used as tests must have signature fn() -> ()." ); } diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index d71102fcab93d..43d7d20d0ebef 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -297,7 +297,7 @@ pub fn run_compiler(args: &[~str]) { let crateid = match attr::find_crateid(attrs) { Some(crateid) => crateid, None => { - sess.fatal("No crate_id and --crate-id or \ + alert_fatal!(sess, A0048, "No crate_id and --crate-id or \ --crate-name requested") } }; diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index 9c2c5a5745848..8e785372e3d54 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -101,8 +101,8 @@ fn warn_if_multiple_versions(e: &mut Env, assert!(!matches.is_empty()); if matches.len() != 1u { - diag.handler().warn( - format!("using multiple versions of crate `{}`", name)); + alert_warn!(diag.handler(), A0334, + "using multiple versions of crate `{}`", name); for match_ in matches.iter() { diag.span_note(match_.span, "used here"); loader::note_crateid_attr(diag, &match_.crateid); @@ -231,6 +231,7 @@ fn visit_item(e: &Env, i: &ast::Item) { }) .to_owned_vec(); for m in link_args.iter() { + let span = m.span; match m.meta_item_list() { Some(items) => { let kind = items.iter().find(|k| { @@ -244,13 +245,13 @@ fn visit_item(e: &Env, i: &ast::Item) { k.equiv(&("framework")) { cstore::NativeFramework } else if k.equiv(&("framework")) { - e.sess.span_err(m.span, + span_err!(e.sess, span, A0322, "native frameworks are only available \ on OSX targets"); cstore::NativeUnknown } else { - e.sess.span_err(m.span, - format!("unknown kind: `{}`", k)); + span_err!(e.sess, span, A0323, + "unknown kind: `{}`", k); cstore::NativeUnknown } } @@ -262,14 +263,15 @@ fn visit_item(e: &Env, i: &ast::Item) { let n = match n { Some(n) => n, None => { - e.sess.span_err(m.span, + span_err!(e.sess, span, A0324, "#[link(...)] specified without \ `name = \"foo\"`"); InternedString::new("foo") } }; if n.get().is_empty() { - e.sess.span_err(m.span, "#[link(name = \"\")] given with empty name"); + span_err!(e.sess, span, A0325, + "#[link(name = \"\")] given with empty name"); } else { cstore.add_used_library(n.get().to_owned(), kind); } diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index abcd650ced131..cfbe54d273280 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -71,9 +71,9 @@ impl Context { match self.find_library_crate() { Some(t) => t, None => { - self.sess.span_fatal(self.span, - format!("can't find crate for `{}`", - self.ident)); + span_fatal!(self.sess, self.span, A0021, + "can't find crate for `{}`", + self.ident); } } } @@ -148,8 +148,8 @@ impl Context { 0 => None, 1 => Some(matches[0]), _ => { - self.sess.span_err(self.span, - format!("multiple matching crates for `{}`", crate_name)); + span_err!(self.sess, self.span, A0326, + "multiple matching crates for `{}`", crate_name); self.sess.note("candidates:"); for lib in matches.iter() { match lib.dylib { diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index cfd2c0719b09b..ae5ab950a69e5 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -231,10 +231,9 @@ impl<'a> CheckLoanCtxt<'a> { match (new_loan.mutbl, old_loan.mutbl) { (_, MutableMutability) => { let var = self.bccx.loan_path_to_str(new_loan.loan_path); - self.bccx.span_err( - new_loan.span, - format!("cannot borrow `{}` because it is already \ - borrowed as mutable", var)); + span_err!(self.bccx, new_loan.span, A0012, + "cannot borrow `{}` because it is already \ + borrowed as mutable", var); self.bccx.span_note( old_loan.span, format!("previous borrow of `{0}` as mutable occurs \ @@ -244,13 +243,12 @@ impl<'a> CheckLoanCtxt<'a> { } (_, mutability) => { - self.bccx.span_err( - new_loan.span, - format!("cannot borrow `{}` as {} because \ + span_err!(self.bccx, new_loan.span, A0013, + "cannot borrow `{}` as {} because \ it is already borrowed as {}", - self.bccx.loan_path_to_str(new_loan.loan_path), - self.bccx.mut_to_str(new_loan.mutbl), - self.bccx.mut_to_str(old_loan.mutbl))); + self.bccx.loan_path_to_str(new_loan.loan_path), + self.bccx.mut_to_str(new_loan.mutbl), + self.bccx.mut_to_str(old_loan.mutbl)); let var = self.bccx.loan_path_to_str(new_loan.loan_path); let mut note = format!("previous borrow of `{}` occurs \ @@ -349,11 +347,10 @@ impl<'a> CheckLoanCtxt<'a> { } // Otherwise, just a plain error. - self.bccx.span_err( - expr.span, - format!("cannot assign to {} {}", - cmt.mutbl.to_user_str(), - self.bccx.cmt_to_str(cmt))); + span_err!(self.bccx, expr.span, A0014, + "cannot assign to {} {}", + cmt.mutbl.to_user_str(), + self.bccx.cmt_to_str(cmt)); return; fn mark_variable_as_used_mut(this: &CheckLoanCtxt, @@ -590,10 +587,9 @@ impl<'a> CheckLoanCtxt<'a> { expr: &ast::Expr, loan_path: &LoanPath, loan: &Loan) { - self.bccx.span_err( - expr.span, - format!("cannot assign to `{}` because it is borrowed", - self.bccx.loan_path_to_str(loan_path))); + span_err!(self.bccx, expr.span, A0015, + "cannot assign to `{}` because it is borrowed", + self.bccx.loan_path_to_str(loan_path)); self.bccx.span_note( loan.span, format!("borrow of `{}` occurs here", @@ -618,11 +614,10 @@ impl<'a> CheckLoanCtxt<'a> { match self.analyze_move_out_from(id, move_path) { MoveOk => {} MoveWhileBorrowed(loan_path, loan_span) => { - self.bccx.span_err( - span, - format!("cannot move out of `{}` \ + span_err!(self.bccx, span, A0016, + "cannot move out of `{}` \ because it is borrowed", - self.bccx.loan_path_to_str(move_path))); + self.bccx.loan_path_to_str(move_path)); self.bccx.span_note( loan_span, format!("borrow of `{}` occurs here", @@ -727,11 +722,10 @@ fn check_loans_in_fn<'a>(this: &mut CheckLoanCtxt<'a>, match move_err { MoveOk => {} MoveWhileBorrowed(loan_path, loan_span) => { - this.bccx.span_err( - cap_var.span, - format!("cannot move `{}` into closure \ + span_err!(this.bccx, cap_var.span, A0017, + "cannot move `{}` into closure \ because it is borrowed", - this.bccx.loan_path_to_str(move_path))); + this.bccx.loan_path_to_str(move_path)); this.bccx.span_note( loan_span, format!("borrow of `{}` occurs here", diff --git a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs index 0d9b4b0b171cc..5dab45cebef10 100644 --- a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs +++ b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs @@ -104,10 +104,9 @@ fn check_is_legal_to_move_from(bccx: &BorrowckCtxt, mc::cat_deref(_, _, mc::unsafe_ptr(..)) | mc::cat_stack_upvar(..) | mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Many, .. }) => { - bccx.span_err( - cmt0.span, - format!("cannot move out of {}", - bccx.cmt_to_str(cmt))); + span_err!(bccx, cmt0.span, A0018, + "cannot move out of {}", + bccx.cmt_to_str(cmt)); false } @@ -142,11 +141,10 @@ fn check_is_legal_to_move_from(bccx: &BorrowckCtxt, match ty::get(b.ty).sty { ty::ty_struct(did, _) | ty::ty_enum(did, _) => { if ty::has_dtor(bccx.tcx, did) { - bccx.span_err( - cmt0.span, - format!("cannot move out of type `{}`, \ + span_err!(bccx, cmt0.span, A0019, + "cannot move out of type `{}`, \ which defines the `Drop` trait", - b.ty.user_string(bccx.tcx))); + b.ty.user_string(bccx.tcx)); false } else { check_is_legal_to_move_from(bccx, cmt0, b) diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs index 6a3e2fc63b08f..9e88f808a8612 100644 --- a/src/librustc/middle/borrowck/mod.rs +++ b/src/librustc/middle/borrowck/mod.rs @@ -495,9 +495,7 @@ impl BorrowckCtxt { } pub fn report(&self, err: BckError) { - self.span_err( - err.span, - self.bckerr_to_str(err)); + self.raise_bck_err(err); self.note_and_explain_bckerr(err); } @@ -514,20 +512,18 @@ impl BorrowckCtxt { match move.kind { move_data::Declared => { - self.tcx.sess.span_err( - use_span, - format!("{} of possibly uninitialized value: `{}`", - verb, - self.loan_path_to_str(lp))); + span_err!(self.tcx.sess, use_span, A0006, + "{} of possibly uninitialized value: `{}`", + verb, + self.loan_path_to_str(lp)); } _ => { let partially = if lp == moved_lp {""} else {"partially "}; - self.tcx.sess.span_err( - use_span, - format!("{} of {}moved value: `{}`", - verb, - partially, - self.loan_path_to_str(lp))); + span_err!(self.tcx.sess, use_span, A0007, + "{} of {}moved value: `{}`", + verb, + partially, + self.loan_path_to_str(lp)); } } @@ -599,17 +595,16 @@ impl BorrowckCtxt { lp: &LoanPath, assign: &move_data::Assignment) { - self.tcx.sess.span_err( - span, - format!("re-assignment of immutable variable `{}`", - self.loan_path_to_str(lp))); + span_err!(self.tcx.sess, span, A0008, + "re-assignment of immutable variable `{}`", + self.loan_path_to_str(lp)); self.tcx.sess.span_note( assign.span, format!("prior assignment occurs here")); } - pub fn span_err(&self, s: Span, m: &str) { - self.tcx.sess.span_err(s, m); + pub fn span_err_with_diagnostic_code(&self, s: Span, c: &str, m: &str) { + self.tcx.sess.span_err_with_diagnostic_code(s, c, m); } pub fn span_note(&self, s: Span, m: &str) { @@ -620,26 +615,30 @@ impl BorrowckCtxt { self.tcx.sess.span_end_note(s, m); } - pub fn bckerr_to_str(&self, err: BckError) -> ~str { + pub fn raise_bck_err(&self, err: BckError) { match err.code { err_mutbl(lk) => { - format!("cannot borrow {} {} as {}", - err.cmt.mutbl.to_user_str(), - self.cmt_to_str(err.cmt), - self.mut_to_str(lk)) + span_err!(self.tcx.sess, err.span, A0001, + "cannot borrow {} {} as {}", + err.cmt.mutbl.to_user_str(), + self.cmt_to_str(err.cmt), + self.mut_to_str(lk)); } err_out_of_root_scope(..) => { - format!("cannot root managed value long enough") + span_err!(self.tcx.sess, err.span, A0002, + "cannot root managed value long enough"); } err_out_of_scope(..) => { - format!("borrowed value does not live long enough") + span_err!(self.tcx.sess, err.span, A0003, + "borrowed value does not live long enough"); } err_freeze_aliasable_const => { // Means that the user borrowed a ~T or enum value // residing in &const or @const pointer. Terrible // error message, but then &const and @const are // supposed to be going away. - format!("unsafe borrow of aliasable, const value") + span_err!(self.tcx.sess, err.span, A0004, + "unsafe borrow of aliasable, const value"); } err_borrowed_pointer_too_short(..) => { let descr = match opt_loan_path(err.cmt) { @@ -647,9 +646,10 @@ impl BorrowckCtxt { None => self.cmt_to_str(err.cmt), }; - format!("lifetime of {} is too short to guarantee \ - its contents can be safely reborrowed", - descr) + span_err!(self.tcx.sess, err.span, A0005, + "lifetime of {} is too short to guarantee \ + its contents can be safely reborrowed", + descr); } } } @@ -665,25 +665,24 @@ impl BorrowckCtxt { match cause { mc::AliasableOther => { - self.tcx.sess.span_err( - span, - format!("{} in an aliasable location", prefix)); + span_err!(self.tcx.sess, span, A0009, + "{} in an aliasable location", prefix); } mc::AliasableStatic | mc::AliasableStaticMut => { - self.tcx.sess.span_err( - span, + span_err!(self.tcx.sess, + span, A0357, format!("{} in a static location", prefix)); } mc::AliasableManaged => { - self.tcx.sess.span_err( - span, + span_err!(self.tcx.sess, + span, A0010, format!("{} in a `@` pointer", prefix)); } mc::AliasableBorrowed(_) => { - self.tcx.sess.span_err( - span, - format!("{} in a `&` reference", prefix)); + span_err!(self.tcx.sess, + span, A0011, + "{} in a `&` reference", prefix); } } } diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs index d52ae81328f63..bc2f31dc57751 100644 --- a/src/librustc/middle/check_const.rs +++ b/src/librustc/middle/check_const.rs @@ -114,7 +114,7 @@ pub fn check_expr(v: &mut CheckCrateVisitor, match e.node { ExprUnary(_, UnDeref, _) => { } ExprUnary(_, UnBox, _) | ExprUnary(_, UnUniq, _) => { - sess.span_err(e.span, + span_err!(sess, e.span, A0237, "cannot do allocations in constant expressions"); return; } @@ -122,7 +122,7 @@ pub fn check_expr(v: &mut CheckCrateVisitor, ExprBinary(..) | ExprUnary(..) => { let method_map = method_map.borrow(); if method_map.get().contains_key(&e.id) { - sess.span_err(e.span, "user-defined operators are not \ + span_err!(sess, e.span, A0238, "user-defined operators are not \ allowed in constant expressions"); } } @@ -130,9 +130,10 @@ pub fn check_expr(v: &mut CheckCrateVisitor, ExprCast(_, _) => { let ety = ty::expr_ty(tcx, e); if !ty::type_is_numeric(ety) && !ty::type_is_unsafe_ptr(ety) { - sess.span_err(e.span, ~"can not cast to `" + - ppaux::ty_to_str(tcx, ety) + - "` in a constant expression"); + span_err!(sess, e.span, A0239, + "can not cast to `{}` in a constant expression", + ppaux::ty_to_str(tcx, ety)); + } } ExprPath(ref pth) => { @@ -141,8 +142,8 @@ pub fn check_expr(v: &mut CheckCrateVisitor, // 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()) { - sess.span_err( - e.span, "paths in constants may only refer to \ + span_err!(sess, + e.span, A0240, "paths in constants may only refer to \ items without type parameters"); } let def_map = def_map.borrow(); @@ -154,8 +155,8 @@ pub fn check_expr(v: &mut CheckCrateVisitor, Some(&def) => { debug!("(checking const) found bad def: {:?}", def); - sess.span_err( - e.span, + span_err!(sess, + e.span, A0241, "paths in constants may only refer to \ constants or functions"); } @@ -170,8 +171,8 @@ pub fn check_expr(v: &mut CheckCrateVisitor, Some(&DefStruct(..)) => {} // OK. Some(&DefVariant(..)) => {} // OK. _ => { - sess.span_err( - e.span, + span_err!(sess, + e.span, A0242, "function calls in constants are limited to \ struct and enum constructors"); } @@ -187,17 +188,18 @@ pub fn check_expr(v: &mut CheckCrateVisitor, ExprRepeat(..) | ExprStruct(..) => { } ExprAddrOf(..) => { - sess.span_err( - e.span, + span_err!(sess, + e.span, A0243, "references in constants may only refer to \ immutable values"); }, ExprVstore(_, ExprVstoreUniq) => { - sess.span_err(e.span, "cannot allocate vectors in constant expressions") + span_err!(sess, e.span, A0244, + "cannot allocate vectors in constant expressions") }, _ => { - sess.span_err(e.span, + span_err!(sess, e.span, A0245, "constant contains unimplemented expression type"); return; } @@ -234,7 +236,7 @@ pub fn check_item_recursion(sess: Session, impl<'a> Visitor<()> for CheckItemRecursionVisitor<'a> { fn visit_item(&mut self, it: &Item, _: ()) { if self.idstack.iter().any(|x| x == &(it.id)) { - self.sess.span_fatal(self.root_it.span, "recursive constant"); + span_fatal!(self.sess, self.root_it.span, A0030, "recursive constant"); } self.idstack.push(it.id); visit::walk_item(self, it, ()); diff --git a/src/librustc/middle/check_loop.rs b/src/librustc/middle/check_loop.rs index c1be9ea69eaa3..f6efa4aade17c 100644 --- a/src/librustc/middle/check_loop.rs +++ b/src/librustc/middle/check_loop.rs @@ -57,12 +57,12 @@ impl CheckLoopVisitor { match cx { Loop => {} Closure => { - self.tcx.sess.span_err(span, format!("`{}` inside of a closure", - name)); + span_err!(self.tcx.sess, span, A0260, + "`{}` inside of a closure", name); } Normal => { - self.tcx.sess.span_err(span, format!("`{}` outside of loop", - name)); + span_err!(self.tcx.sess, span, A0261, + "`{}` outside of loop", name); } } } diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index ab9eff3a372c6..60230a3db524f 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -85,9 +85,9 @@ fn check_expr(v: &mut CheckMatchVisitor, 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: \ + span_err!(cx.tcx.sess, ex.span, A0288, "non-exhaustive patterns: \ type {} is non-empty", - ty_to_str(cx.tcx, pat_ty))); + ty_to_str(cx.tcx, pat_ty)); } // If the type *is* empty, it's vacuously exhaustive return; @@ -104,7 +104,7 @@ fn check_expr(v: &mut CheckMatchVisitor, } let arms = arms.iter().filter_map(unguarded_pat).collect::<~[~[@Pat]]>().concat_vec(); if arms.is_empty() { - cx.tcx.sess.span_err(ex.span, "non-exhaustive patterns"); + span_err!(cx.tcx.sess, ex.span, A0289, "non-exhaustive patterns"); } else { check_exhaustive(cx, ex.span, arms); } @@ -139,8 +139,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, A0333, + "unmatchable NaN in pattern, \ + use the is_nan method in a guard instead"); } true }); @@ -148,7 +149,7 @@ fn check_arms(cx: &MatchCheckCtxt, arms: &[Arm]) { let v = ~[*pat]; match is_useful(cx, &seen, v) { not_useful => { - cx.tcx.sess.span_err(pat.span, "unreachable pattern"); + span_err!(cx.tcx.sess, pat.span, A0290, "unreachable pattern"); } _ => () } @@ -205,11 +206,12 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, pats: ~[@Pat]) { } } }; - let msg = ~"non-exhaustive patterns" + match ext { + let more_info = match ext { Some(ref s) => format!(": {} not covered", *s), None => ~"" }; - cx.tcx.sess.span_err(sp, msg); + span_err!(cx.tcx.sess, sp, A0291, + "non-exhaustive patterns{}", more_info); } type matrix = ~[~[@Pat]]; @@ -587,7 +589,7 @@ fn specialize(cx: &MatchCheckCtxt, match compare_const_vals(&e_v, v) { Some(val1) => (val1 == 0), None => { - cx.tcx.sess.span_err(pat_span, + span_err!(cx.tcx.sess, pat_span, A0292, "mismatched types between arms"); false } @@ -601,7 +603,7 @@ fn specialize(cx: &MatchCheckCtxt, (val1 >= 0 && val2 <= 0) } _ => { - cx.tcx.sess.span_err(pat_span, + span_err!(cx.tcx.sess, pat_span, A0293, "mismatched types between ranges"); false } @@ -641,7 +643,7 @@ fn specialize(cx: &MatchCheckCtxt, match compare_const_vals(&e_v, v) { Some(val1) => (val1 == 0), None => { - cx.tcx.sess.span_err(pat_span, + span_err!(cx.tcx.sess, pat_span, A0294, "mismatched types between arms"); false } @@ -652,7 +654,7 @@ fn specialize(cx: &MatchCheckCtxt, match (m1, m2) { (Some(val1), Some(val2)) => (val1 >= 0 && val2 <= 0), _ => { - cx.tcx.sess.span_err(pat_span, + span_err!(cx.tcx.sess, pat_span, A0295, "mismatched types between ranges"); false } @@ -750,7 +752,7 @@ fn specialize(cx: &MatchCheckCtxt, match compare_const_vals(&e_v, v) { Some(val1) => val1 == 0, None => { - cx.tcx.sess.span_err(pat_span, + span_err!(cx.tcx.sess, pat_span, A0296, "mismatched types between arms"); false } @@ -762,7 +764,7 @@ fn specialize(cx: &MatchCheckCtxt, match (m1, m2) { (Some(val1), Some(val2)) => (val1 >= 0 && val2 <= 0), _ => { - cx.tcx.sess.span_err(pat_span, + span_err!(cx.tcx.sess, pat_span, A0297, "mismatched types between ranges"); false } @@ -791,7 +793,7 @@ fn specialize(cx: &MatchCheckCtxt, }, (Some(_), Some(_)) => None, _ => { - cx.tcx.sess.span_err(pat_span, + span_err!(cx.tcx.sess, pat_span, A0298, "mismatched types between ranges"); None } @@ -838,7 +840,7 @@ fn check_local(v: &mut CheckMatchVisitor, s: ()) { visit::walk_local(v, loc, s); if is_refutable(cx, loc.pat) { - cx.tcx.sess.span_err(loc.pat.span, + span_err!(cx.tcx.sess, loc.pat.span, A0299, "refutable pattern in local binding"); } @@ -857,7 +859,7 @@ fn check_fn(v: &mut CheckMatchVisitor, visit::walk_fn(v, kind, decl, body, sp, id, s); for input in decl.inputs.iter() { if is_refutable(cx, input.pat) { - cx.tcx.sess.span_err(input.pat.span, + span_err!(cx.tcx.sess, input.pat.span, A0300, "refutable pattern in function argument"); } } @@ -939,16 +941,16 @@ 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, + span_err!(tcx.sess, + p.span, A0301, "cannot bind by-move with sub-bindings"); } else if has_guard { - tcx.sess.span_err( - p.span, + span_err!(tcx.sess, + p.span, A0302, "cannot bind by-move into a pattern guard"); } else if by_ref_span.is_some() { - tcx.sess.span_err( - p.span, + span_err!(tcx.sess, + p.span, A0303, "cannot bind by-move and by-ref \ in the same pattern"); tcx.sess.span_note( diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index 75874339f3a68..9d5a515a1e86b 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -328,7 +328,8 @@ pub enum const_val { pub fn eval_const_expr(tcx: middle::ty::ctxt, e: &Expr) -> const_val { match eval_const_expr_partial(&tcx, e) { Ok(r) => r, - Err(s) => tcx.sess.span_fatal(e.span, s) + Err(s) => span_fatal!(tcx.sess, e.span, A0029, + "error evaluating constant expression: {}", s) } } @@ -454,9 +455,10 @@ pub fn eval_const_expr_partial(tcx: &T, e: &Expr) // (#5900). Fall back to doing a limited lookup to get past it. let ety = ty::expr_ty_opt(tcx.ty_ctxt(), e) .or_else(|| astconv::ast_ty_to_prim_ty(tcx.ty_ctxt(), target_ty)) - .unwrap_or_else(|| tcx.ty_ctxt().sess.span_fatal( - target_ty.span, - format!("target type not found for const cast") + .unwrap_or_else(|| + span_fatal!(tcx.ty_ctxt().sess, + target_ty.span, A0218, + "target type not found for const cast" )); let base = eval_const_expr_partial(tcx, base); diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index 36dd46388c624..137ec78dd0ada 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -49,9 +49,9 @@ impl EffectCheckVisitor { match self.unsafe_context { SafeContext => { // Report an error. - self.tcx.sess.span_err(span, - format!("{} requires unsafe function or block", - description)) + span_err!(self.tcx.sess, span, A0312, + "{} requires unsafe function or block", + description) } UnsafeBlock(block_id) => { // OK, but record this. @@ -72,7 +72,7 @@ impl EffectCheckVisitor { ppaux::ty_to_str(self.tcx, base_type)); match ty::get(base_type).sty { ty::ty_str(..) => { - self.tcx.sess.span_err(e.span, + span_err!(self.tcx.sess, e.span, A0313, "modification of string types is not allowed"); } _ => {} diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs index 3938a786a3991..e8706b5ae1c75 100644 --- a/src/librustc/middle/entry.rs +++ b/src/librustc/middle/entry.rs @@ -82,8 +82,8 @@ fn find_item(item: &Item, ctxt: &mut EntryContext) { if ctxt.main_fn.is_none() { ctxt.main_fn = Some((item.id, item.span)); } else { - ctxt.session.span_err( - item.span, + span_err!(ctxt.session, + item.span, A0270, "multiple 'main' functions"); } } else { @@ -100,8 +100,8 @@ fn find_item(item: &Item, ctxt: &mut EntryContext) { if ctxt.attr_main_fn.is_none() { ctxt.attr_main_fn = Some((item.id, item.span)); } else { - ctxt.session.span_err( - item.span, + span_err!(ctxt.session, + item.span, A0271, "multiple 'main' functions"); } } @@ -110,8 +110,8 @@ fn find_item(item: &Item, ctxt: &mut EntryContext) { if ctxt.start_fn.is_none() { ctxt.start_fn = Some((item.id, item.span)); } else { - ctxt.session.span_err( - item.span, + span_err!(ctxt.session, + item.span, A0272, "multiple 'start' functions"); } } @@ -135,7 +135,7 @@ fn configure_main(this: &mut EntryContext) { } else { if !this.session.building_library.get() { // No main function - this.session.err("main function not found"); + alert_err!(this.session, A0343, "main function not found"); if !this.non_main_fns.is_empty() { // There were some functions named 'main' though. Try to give the user a hint. this.session.note("the main function must be defined at the crate level \ diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs index 0d6dc6572c36e..5d52f127bf7f7 100644 --- a/src/librustc/middle/kind.rs +++ b/src/librustc/middle/kind.rs @@ -97,7 +97,7 @@ fn check_struct_safe_for_destructor(cx: &mut Context, tps: ~[] }); if !ty::type_is_sendable(cx.tcx, struct_ty) { - cx.tcx.sess.span_err(span, + span_err!(cx.tcx.sess, span, A0276, "cannot implement a destructor on a \ structure that does not satisfy Send"); cx.tcx.sess.span_note(span, @@ -106,7 +106,7 @@ fn check_struct_safe_for_destructor(cx: &mut Context, allow this"); } } else { - cx.tcx.sess.span_err(span, + span_err!(cx.tcx.sess, span, A0277, "cannot implement a destructor on a structure \ with type parameters"); cx.tcx.sess.span_note(span, @@ -134,9 +134,9 @@ fn check_impl_of_trait(cx: &mut Context, it: &Item, trait_ref: &TraitRef, self_t let self_ty: ty::t = ty::node_id_to_type(cx.tcx, it.id); debug!("checking impl with self type {:?}", ty::get(self_ty).sty); check_builtin_bounds(cx, self_ty, trait_def.bounds, |missing| { - cx.tcx.sess.span_err(self_type.span, - format!("the type `{}', which does not fulfill `{}`, cannot implement this \ - trait", ty_to_str(cx.tcx, self_ty), missing.user_string(cx.tcx))); + span_err!(cx.tcx.sess, self_type.span, A0278, + "the type `{}', which does not fulfill `{}`, cannot implement this \ + trait", ty_to_str(cx.tcx, self_ty), missing.user_string(cx.tcx)); cx.tcx.sess.span_note(self_type.span, format!("types implementing this trait must fulfill `{}`", trait_def.bounds.user_string(cx.tcx))); @@ -199,8 +199,8 @@ fn with_appropriate_checker(cx: &Context, } fn check_for_bare(cx: &Context, fv: @freevar_entry) { - cx.tcx.sess.span_err( - fv.span, + span_err!(cx.tcx.sess, + fv.span, A0316, "can't capture dynamic environment in a fn item; \ use the || { ... } closure form instead"); } // same check is done in resolve.rs, but shouldn't be done @@ -402,12 +402,12 @@ pub fn check_typaram_bounds(cx: &Context, ty, type_param_def.bounds.builtin_bounds, |missing| { - cx.tcx.sess.span_err( - sp, - format!("instantiating a type parameter with an incompatible type \ + span_err!(cx.tcx.sess, + sp, A0279, + "instantiating a type parameter with an incompatible type \ `{}`, which does not fulfill `{}`", ty_to_str(cx.tcx, ty), - missing.user_string(cx.tcx))); + missing.user_string(cx.tcx)); }); } @@ -418,14 +418,14 @@ pub fn check_freevar_bounds(cx: &Context, sp: Span, ty: ty::t, // Will be Some if the freevar is implicitly borrowed (stack closure). // Emit a less mysterious error message in this case. match referenced_ty { - Some(rty) => cx.tcx.sess.span_err(sp, - format!("cannot implicitly borrow variable of type `{}` in a bounded \ + Some(rty) => span_err!(cx.tcx.sess, sp, A0280, + "cannot implicitly borrow variable of type `{}` in a bounded \ stack closure (implicit reference does not fulfill `{}`)", - ty_to_str(cx.tcx, rty), missing.user_string(cx.tcx))), - None => cx.tcx.sess.span_err(sp, - format!("cannot capture variable of type `{}`, which does \ + ty_to_str(cx.tcx, rty), missing.user_string(cx.tcx)), + None => span_err!(cx.tcx.sess, sp, A0281, + "cannot capture variable of type `{}`, which does \ not fulfill `{}`, in a bounded closure", - ty_to_str(cx.tcx, ty), missing.user_string(cx.tcx))), + ty_to_str(cx.tcx, ty), missing.user_string(cx.tcx)), } cx.tcx.sess.span_note( sp, @@ -437,11 +437,11 @@ pub fn check_freevar_bounds(cx: &Context, sp: Span, ty: ty::t, pub fn check_trait_cast_bounds(cx: &Context, sp: Span, ty: ty::t, bounds: ty::BuiltinBounds) { check_builtin_bounds(cx, ty, bounds, |missing| { - cx.tcx.sess.span_err(sp, - format!("cannot pack type `{}`, which does not fulfill \ + span_err!(cx.tcx.sess, sp, A0282, + "cannot pack type `{}`, which does not fulfill \ `{}`, as a trait bounded by {}", ty_to_str(cx.tcx, ty), missing.user_string(cx.tcx), - bounds.user_string(cx.tcx))); + bounds.user_string(cx.tcx)); }); } @@ -450,18 +450,18 @@ fn check_copy(cx: &Context, ty: ty::t, sp: Span, reason: &str) { ty_to_str(cx.tcx, ty), ty::type_contents(cx.tcx, ty).to_str()); if ty::type_moves_by_default(cx.tcx, ty) { - cx.tcx.sess.span_err( - sp, format!("copying a value of non-copyable type `{}`", - ty_to_str(cx.tcx, ty))); + span_err!(cx.tcx.sess, + sp, A0283, "copying a value of non-copyable type `{}`", + ty_to_str(cx.tcx, ty)); cx.tcx.sess.span_note(sp, format!("{}", reason)); } } pub fn check_send(cx: &Context, ty: ty::t, sp: Span) -> bool { if !ty::type_is_sendable(cx.tcx, ty) { - cx.tcx.sess.span_err( - sp, format!("value has non-sendable type `{}`", - ty_to_str(cx.tcx, ty))); + span_err!(cx.tcx.sess, + sp, A0284, "value has non-sendable type `{}`", + ty_to_str(cx.tcx, ty)); false } else { true @@ -473,11 +473,11 @@ pub fn check_durable(tcx: ty::ctxt, ty: ty::t, sp: Span) -> bool { if !ty::type_is_static(tcx, ty) { match ty::get(ty).sty { ty::ty_param(..) => { - tcx.sess.span_err(sp, "value may contain references; \ + span_err!(tcx.sess, sp, A0285, "value may contain references; \ add `'static` bound"); } _ => { - tcx.sess.span_err(sp, "value may contain references"); + span_err!(tcx.sess, sp, A0286, "value may contain references"); } } false diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 2b100ffa4c98d..b95fdbff4541b 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -149,8 +149,9 @@ impl LanguageItemCollector { // Check for duplicates. match self.items.items[item_index] { Some(original_def_id) if original_def_id != item_def_id => { - self.session.err(format!("duplicate entry for `{}`", - LanguageItems::item_name(item_index))); + alert_err!(self.session, A0103, + "duplicate entry for `{}`", + LanguageItems::item_name(item_index)); } Some(_) | None => { // OK. diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index 0ebfa8c393c2f..563aca211d995 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -488,8 +488,12 @@ impl<'a> Context<'a> { } }; match level { - warn => { self.tcx.sess.span_warn(span, msg); } - deny | forbid => { self.tcx.sess.span_err(span, msg); } + warn => { + self.tcx.sess.span_warn_without_diagnostic_code(span, msg); + } + deny | forbid => { + self.tcx.sess.span_err_without_diagnostic_code(span, msg); + } allow => fail!(), } @@ -524,10 +528,10 @@ impl<'a> Context<'a> { let lint = lint.lint; let now = self.get_level(lint); if now == forbid && level != forbid { - self.tcx.sess.span_err(meta.span, - format!("{}({}) overruled by outer forbid({})", + span_err!(self.tcx.sess, meta.span, A0273, + "{}({}) overruled by outer forbid({})", level_to_str(level), - lintname, lintname)); + lintname, lintname); } else if now != level { let src = self.get_source(lint); self.lint_stack.push((lint, now, src)); @@ -585,7 +589,7 @@ pub fn each_lint(sess: session::Session, let metas = match meta.node { ast::MetaList(_, ref metas) => metas, _ => { - sess.span_err(meta.span, "malformed lint attribute"); + span_err!(sess, meta.span, A0274, "malformed lint attribute"); continue; } }; @@ -597,7 +601,7 @@ pub fn each_lint(sess: session::Session, } } _ => { - sess.span_err(meta.span, "malformed lint attribute"); + span_err!(sess, meta.span, A0275, "malformed lint attribute"); } } } @@ -986,7 +990,7 @@ fn check_crate_attrs_usage(cx: &Context, attrs: &[ast::Attribute]) { cx.span_lint(AttributeUsage, attr.span, "unknown crate attribute"); } if name.equiv(& &"link") { - cx.tcx.sess.span_err(attr.span, + span_err!(cx.tcx.sess, attr.span, A0315, "obsolete crate `link` attribute"); cx.tcx.sess.note("the link attribute has been superceded by the crate_id \ attribute, which has the format `#[crate_id = \"name#version\"]`"); diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 546d6f2720408..aa30ac62eb9fa 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -1576,8 +1576,8 @@ impl Liveness { // for nil return types, it is ok to not return a value expl. } else if ty::type_is_bot(t_ret) { // for bot return types, not ok. Function should fail. - self.tcx.sess.span_err( - sp, "some control paths may return"); + span_err!(self.tcx.sess, + sp, A0304, "some control paths may return"); } else { let ends_with_stmt = match body.expr { None if body.stmts.len() > 0 => @@ -1600,8 +1600,8 @@ impl Liveness { self.tcx.sess.span_note( span_semicolon, "consider removing this semicolon:"); } - self.tcx.sess.span_err( - sp, "not all control paths return a value"); + span_err!(self.tcx.sess, + sp, A0314, "not all control paths return a value"); } } } @@ -1656,14 +1656,14 @@ impl Liveness { let name = self.ir.variable_name(var); match lnk { FreeVarNode(span) => { - self.tcx.sess.span_err( - span, - format!("capture of {}: `{}`", msg, name)); + span_err!(self.tcx.sess, + span, A0305, + "capture of {}: `{}`", msg, name); } ExprNode(span) => { - self.tcx.sess.span_err( - span, - format!("use of {}: `{}`", msg, name)); + span_err!(self.tcx.sess, + span, A0306, + "use of {}: `{}`", msg, name); } ExitNode | VarDefNode(_) => { self.tcx.sess.span_bug( diff --git a/src/librustc/middle/moves.rs b/src/librustc/middle/moves.rs index d73d7f3d6f1db..18a8439cceb42 100644 --- a/src/librustc/middle/moves.rs +++ b/src/librustc/middle/moves.rs @@ -455,10 +455,10 @@ impl VisitContext { if consume_with { if has_dtor(self.tcx, with_ty) { - self.tcx.sess.span_err(with_expr.span, - format!("cannot move out of type `{}`, \ + span_err!(self.tcx.sess, with_expr.span, A0287, + "cannot move out of type `{}`, \ which defines the `Drop` trait", - with_ty.user_string(self.tcx))); + with_ty.user_string(self.tcx)); } self.consume_expr(*with_expr); } else { diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index ae1b71f5ccad1..3fab1cb1e2920 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -513,15 +513,15 @@ impl<'a> PrivacyVisitor<'a> { source_did: Option, msg: &str) -> bool { match self.def_privacy(to_check) { ExternallyDenied => { - self.tcx.sess.span_err(span, format!("{} is private", msg)) + span_err!(self.tcx.sess, span, A0246, "{} is private", msg) } DisallowedBy(id) => { if id == source_did.unwrap_or(to_check).node { - self.tcx.sess.span_err(span, format!("{} is private", msg)); + span_err!(self.tcx.sess, span, A0247, + "{} is private", msg); return false; } else { - self.tcx.sess.span_err(span, format!("{} is inaccessible", - msg)); + span_err!(self.tcx.sess, span, A0248, "{} is inaccessible", msg); } match self.tcx.items.find(id) { Some(ast_map::NodeItem(item, _)) => { @@ -591,9 +591,9 @@ impl<'a> PrivacyVisitor<'a> { if !is_local(field.id) || !self.private_accessible(field.id.node) { let string = token::get_ident(ident.name); - self.tcx.sess.span_err(span, - format!("field `{}` is private", - string.get())) + span_err!(self.tcx.sess, span, A0249, + "field `{}` is private", + string.get()) } break; } @@ -881,19 +881,22 @@ impl Visitor<()> for SanePrivacyVisitor { match i.vis { ast::Inherited => {} ast::Private => { - self.tcx.sess.span_err(i.span, "unnecessary visibility \ - qualifier"); + span_err!(self.tcx.sess, i.span, A0250, + "unnecessary visibility \ + qualifier"); } ast::Public => { if self.in_fn { - self.tcx.sess.span_err(i.span, "unnecessary `pub`, imports \ - in functions are never \ - reachable"); + span_err!(self.tcx.sess, i.span, A0251, + "unnecessary `pub`, imports \ + in functions are never \ + reachable"); } else { match i.node { ast::ViewItemExternMod(..) => { - self.tcx.sess.span_err(i.span, "`pub` visibility \ - is not allowed"); + span_err!(self.tcx.sess, i.span, A0252, + "`pub` visibility \ + is not allowed"); } _ => {} } @@ -913,7 +916,7 @@ impl SanePrivacyVisitor { let tcx = self.tcx; let check_inherited = |sp: Span, vis: ast::Visibility, note: &str| { if vis != ast::Inherited { - tcx.sess.span_err(sp, "unnecessary visibility qualifier"); + span_err!(tcx.sess, sp, A0253, "unnecessary visibility qualifier"); if note.len() > 0 { tcx.sess.span_note(sp, note); } @@ -921,7 +924,7 @@ impl SanePrivacyVisitor { }; let check_not_priv = |sp: Span, vis: ast::Visibility, note: &str| { if vis == ast::Private { - tcx.sess.span_err(sp, "unnecessary `priv` qualifier"); + span_err!(tcx.sess, sp, A0254, "unnecessary `priv` qualifier"); if note.len() > 0 { tcx.sess.span_note(sp, note); } @@ -937,11 +940,11 @@ impl SanePrivacyVisitor { for f in def.fields.iter() { match f.node.kind { ast::NamedField(_, ast::Public) if public_def => { - tcx.sess.span_err(f.span, "unnecessary `pub` \ + span_err!(tcx.sess, f.span, A0255, "unnecessary `pub` \ visibility"); } ast::NamedField(_, ast::Private) if !public_def => { - tcx.sess.span_err(f.span, "unnecessary `priv` \ + span_err!(tcx.sess, f.span, A0256, "unnecessary `priv` \ visibility"); } ast::NamedField(..) | ast::UnnamedField => {} @@ -983,13 +986,13 @@ impl SanePrivacyVisitor { match v.node.vis { ast::Public => { if item.vis == ast::Public { - tcx.sess.span_err(v.span, "unnecessary `pub` \ + span_err!(tcx.sess, v.span, A0257, "unnecessary `pub` \ visibility"); } } ast::Private => { if item.vis != ast::Public { - tcx.sess.span_err(v.span, "unnecessary `priv` \ + span_err!(tcx.sess, v.span, A0258, "unnecessary `priv` \ visibility"); } } @@ -1034,7 +1037,7 @@ impl SanePrivacyVisitor { let tcx = self.tcx; let check_inherited = |sp: Span, vis: ast::Visibility| { if vis != ast::Inherited { - tcx.sess.span_err(sp, "visibility has no effect inside functions"); + span_err!(tcx.sess, sp, A0259, "visibility has no effect inside functions"); } }; let check_struct = |def: &@ast::StructDef| { diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 19e67bb865dd2..3dd93b647314e 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -33,6 +33,14 @@ use std::uint; use std::hashmap::{HashMap, HashSet}; use std::util; +macro_rules! resolve_err ( + ($this: expr, $span: expr, $code: ident, $($arg: expr), *) => ( { + if $this.emit_errors { + span_err!($this.session, $span, $code, $($arg), *); + } + } ) +) + // Definition mapping pub type DefMap = @RefCell>; @@ -1063,10 +1071,10 @@ impl Resolver { // Return an error here by looking up the namespace that // had the duplicate. let ns = ns.unwrap(); - self.resolve_error(sp, - format!("duplicate definition of {} `{}`", + resolve_err!(self, sp, A0064, + "duplicate definition of {} `{}`", namespace_error_to_str(duplicate_type), - self.session.str_of(name))); + self.session.str_of(name)); { let r = child.span_for_namespace(ns); for sp in r.iter() { @@ -2071,11 +2079,11 @@ impl Resolver { match self.resolve_import_for_module(module, import_directive) { Failed => { // We presumably emitted an error. Continue. - let msg = format!("failed to resolve import `{}`", - self.import_path_to_str( - import_directive.module_path, - *import_directive.subclass)); - self.resolve_error(import_directive.span, msg); + resolve_err!(self, import_directive.span, A0065, + "failed to resolve import `{}`", + self.import_path_to_str( + import_directive.module_path, + *import_directive.subclass)); } Indeterminate => { // Bail out. We'll come around next time. @@ -2441,11 +2449,11 @@ impl Resolver { if import_resolution.value_target.get().is_none() && import_resolution.type_target.get().is_none() { - let msg = format!("unresolved import: there is no \ - `{}` in `{}`", - self.session.str_of(source), - self.module_to_str(containing_module)); - self.resolve_error(directive.span, msg); + resolve_err!(self, directive.span, A0066, + "unresolved import: there is no \ + `{}` in `{}`", + self.session.str_of(source), + self.module_to_str(containing_module)); return Failed; } let used_public = used_reexport || used_public; @@ -2673,15 +2681,16 @@ impl Resolver { hi: span.lo + Pos::from_uint(segment_name.len()), expn_info: span.expn_info, }; - self.resolve_error(span, - format!("unresolved import. maybe \ + resolve_err!(self, span, A0067, + "unresolved import. maybe \ a missing `extern mod \ {}`?", - segment_name)); + segment_name); return Failed; } - self.resolve_error(span, format!("unresolved import: could not find `{}` in \ - `{}`.", segment_name, module_name)); + resolve_err!(self, span, A0068, + "unresolved import: could not find `{}` in \ + `{}`.", segment_name, module_name); return Failed; } Indeterminate => { @@ -2698,12 +2707,12 @@ impl Resolver { match type_def.module_def { None => { // Not a module. - self.resolve_error(span, - format!("not a \ + resolve_err!(self, span, A0069, + "not a \ module `{}`", self.session. str_of( - name))); + name)); return Failed; } Some(module_def) => { @@ -2714,8 +2723,8 @@ impl Resolver { module_def.kind.get()) { (ImportSearch, TraitModuleKind) | (ImportSearch, ImplModuleKind) => { - self.resolve_error( - span, + resolve_err!(self, + span, A0070, "cannot import from a trait \ or type implementation"); return Failed; @@ -2744,10 +2753,10 @@ impl Resolver { } None => { // There are no type bindings at all. - self.resolve_error(span, - format!("not a module `{}`", + resolve_err!(self, span, A0071, + "not a module `{}`", self.session.str_of( - name))); + name)); return Failed; } } @@ -2792,12 +2801,13 @@ impl Resolver { let mpath = self.idents_to_str(module_path); match mpath.rfind(':') { Some(idx) => { - self.resolve_error(span, format!("unresolved import: could not find `{}` \ + resolve_err!(self, span, A0072, + "unresolved import: could not find `{}` \ in `{}`", // idx +- 1 to account for the colons // on either side mpath.slice_from(idx + 1), - mpath.slice_to(idx - 1))); + mpath.slice_to(idx - 1)); }, None => (), }; @@ -2829,7 +2839,7 @@ impl Resolver { module_path[0]); match result { Failed => { - self.resolve_error(span, "unresolved name"); + resolve_err!(self, span, A0073, "unresolved name"); return Failed; } Indeterminate => { @@ -3241,12 +3251,12 @@ impl Resolver { .span_to_snippet(imports.get()[index].span) .unwrap(); if sn.contains("::") { - self.resolve_error(imports.get()[index].span, + resolve_err!(self, imports.get()[index].span, A0074, "unresolved import"); } else { - let err = format!("unresolved import (maybe you meant `{}::*`?)", - sn.slice(0, sn.len())); - self.resolve_error(imports.get()[index].span, err); + resolve_err!(self, imports.get()[index].span, A0075, + "unresolved import (maybe you meant `{}::*`?)", + sn.slice(0, sn.len())); } } @@ -3513,15 +3523,15 @@ impl Resolver { // named function item. This is not allowed, so we // report an error. - self.resolve_error( - span, + resolve_err!(self, + span, A0076, "can't capture dynamic environment in a fn item; \ use the || { ... } closure form instead"); } else { // This was an attempt to use a type parameter outside // its scope. - self.resolve_error(span, + resolve_err!(self, span, A0077, "attempt to use a type \ argument out of scope"); } @@ -3536,15 +3546,15 @@ impl Resolver { // named function item. This is not allowed, so we // report an error. - self.resolve_error( - span, + resolve_err!(self, + span, A0078, "can't capture dynamic environment in a fn item; \ use the || { ... } closure form instead"); } else { // This was an attempt to use a type parameter outside // its scope. - self.resolve_error(span, + resolve_err!(self, span, A0079, "attempt to use a type \ argument out of scope"); } @@ -3554,12 +3564,12 @@ impl Resolver { ConstantItemRibKind => { if is_ty_param { // see #9186 - self.resolve_error(span, + resolve_err!(self, span, A0080, "cannot use an outer type \ parameter in this context"); } else { // Still doesn't deal with upvars - self.resolve_error(span, + resolve_err!(self, span, A0081, "attempt to use a non-constant \ value in a constant"); } @@ -3968,8 +3978,9 @@ impl Resolver { TraitDerivation => "derive" }; - let msg = format!("attempt to {} a nonexistent trait `{}`", usage_str, path_str); - self.resolve_error(trait_reference.path.span, msg); + resolve_err!(self, trait_reference.path.span, A0082, + "attempt to {} a nonexistent trait `{}`", + usage_str, path_str); } Some(def) => { debug!("(resolving trait) found trait def: {:?}", def); @@ -3989,8 +4000,8 @@ impl Resolver { match ident_map.find(&ident) { Some(&prev_field) => { let ident_str = self.session.str_of(ident); - self.resolve_error(field.span, - format!("field `{}` is already declared", ident_str)); + resolve_err!(self, field.span, A0083, + "field `{}` is already declared", ident_str); self.session.span_note(prev_field.span, "previously declared here"); }, @@ -4162,22 +4173,22 @@ impl Resolver { match map_i.find(&key) { None => { let string = token::get_ident(key); - self.resolve_error( - p.span, - format!("variable `{}` from pattern \\#1 is \ + resolve_err!(self, + p.span, A0084, + "variable `{}` from pattern \\#1 is \ not bound in pattern \\#{}", string.get(), - i + 1)); + i + 1); } Some(binding_i) => { if binding_0.binding_mode != binding_i.binding_mode { let string = token::get_ident(key); - self.resolve_error( - binding_i.span, - format!("variable `{}` is bound with different \ + resolve_err!(self, + binding_i.span, A0085, + "variable `{}` is bound with different \ mode in pattern \\#{} than in pattern \\#1", string.get(), - i + 1)); + i + 1); } } } @@ -4186,12 +4197,12 @@ impl Resolver { for (&key, &binding) in map_i.iter() { if !map_0.contains_key(&key) { let string = token::get_ident(key); - self.resolve_error( - binding.span, - format!("variable `{}` from pattern \\#{} is \ + resolve_err!(self, + binding.span, A0086, + "variable `{}` from pattern \\#{} is \ not bound in pattern \\#1", string.get(), - i + 1)); + i + 1); } } } @@ -4278,14 +4289,14 @@ impl Resolver { if path.segments .iter() .any(|s| !s.lifetimes.is_empty()) { - self.session.span_err(path.span, + span_err!(self.session, path.span, A0062, "lifetime parameters \ are not allowed on \ this type") } else if path.segments .iter() .any(|s| s.types.len() > 0) { - self.session.span_err(path.span, + span_err!(self.session, path.span, A0063, "type parameters are \ not allowed on this \ type") @@ -4327,9 +4338,9 @@ impl Resolver { self.record_def(path_id, def); } None => { - let msg = format!("use of undeclared type name `{}`", - self.path_idents_to_str(path)); - self.resolve_error(ty.span, msg); + resolve_err!(self, ty.span, A0087, + "use of undeclared type name `{}`", + self.path_idents_to_str(path)); } } @@ -4396,12 +4407,12 @@ impl Resolver { } FoundStructOrEnumVariant(..) => { let string = token::get_ident(renamed); - self.resolve_error(pattern.span, - format!("declaration of `{}` \ + resolve_err!(self, pattern.span, A0088, + "declaration of `{}` \ shadows an enum \ variant or unit-like \ struct in scope", - string.get())); + string.get()); } FoundConst(def, lp) if mode == RefutableMode => { let string = token::get_ident(renamed); @@ -4416,7 +4427,7 @@ impl Resolver { self.record_def(pattern.id, (def, lp)); } FoundConst(..) => { - self.resolve_error(pattern.span, + resolve_err!(self, pattern.span, A0089, "only irrefutable patterns \ allowed here"); } @@ -4475,11 +4486,11 @@ impl Resolver { // Then this is a duplicate variable // in the same disjunct, which is an // error - self.resolve_error(pattern.span, - format!("identifier `{}` is bound more \ + resolve_err!(self, pattern.span, A0090, + "identifier `{}` is bound more \ than once in the same pattern", path_to_str(path, self.session - .intr()))); + .intr())); } // Not bound in the same pattern: do nothing } @@ -4523,14 +4534,14 @@ impl Resolver { self.record_def(pattern.id, def); } Some(_) => { - self.resolve_error( - path.span, - format!("`{}` is not an enum variant or constant", + resolve_err!(self, + path.span, A0091, + "`{}` is not an enum variant or constant", self.session.str_of( - path.segments.last().unwrap().identifier))) + path.segments.last().unwrap().identifier)) } None => { - self.resolve_error(path.span, + resolve_err!(self, path.span, A0092, "unresolved enum variant"); } } @@ -4553,22 +4564,22 @@ impl Resolver { self.record_def(pattern.id, def); } Some(_) => { - self.resolve_error( - path.span, - format!("`{}` is not an enum variant, struct or const", + resolve_err!(self, + path.span, A0093, + "`{}` is not an enum variant, struct or const", self.session .str_of(path.segments .last().unwrap() - .identifier))); + .identifier)); } None => { - self.resolve_error(path.span, - format!("unresolved enum variant, \ + resolve_err!(self, path.span, A0094, + "unresolved enum variant, \ struct or const `{}`", self.session .str_of(path.segments .last().unwrap() - .identifier))); + .identifier)); } } @@ -4607,9 +4618,9 @@ impl Resolver { result => { debug!("(resolving pattern) didn't find struct \ def: {:?}", result); - let msg = format!("`{}` does not name a structure", - self.path_idents_to_str(path)); - self.resolve_error(path.span, msg); + resolve_err!(self, path.span, A0208, + "`{}` does not name a structure", + self.path_idents_to_str(path)); } } } @@ -4833,9 +4844,9 @@ impl Resolver { path.span, PathSearch) { Failed => { - let msg = format!("use of undeclared module `{}`", - self.idents_to_str(module_path_idents)); - self.resolve_error(path.span, msg); + resolve_err!(self, path.span, A0209, + "use of undeclared module `{}`", + self.idents_to_str(module_path_idents)); return None; } @@ -4902,9 +4913,9 @@ impl Resolver { PathSearch, AllPublic) { Failed => { - let msg = format!("use of undeclared module `::{}`", - self.idents_to_str(module_path_idents)); - self.resolve_error(path.span, msg); + resolve_err!(self, path.span, A0095, + "use of undeclared module `::{}`", + self.idents_to_str(module_path_idents)); return None; } @@ -5018,12 +5029,6 @@ impl Resolver { rs } - fn resolve_error(&mut self, span: Span, s: &str) { - if self.emit_errors { - self.session.span_err(span, s); - } - } - fn find_best_match_for_name(&mut self, name: &str, max_distance: uint) -> Option<~str> { let this = &mut *self; @@ -5093,7 +5098,7 @@ impl Resolver { // out here. match def { (DefMethod(..), _) => { - self.resolve_error(expr.span, + resolve_err!(self, expr.span, A0096, "first-class methods \ are not supported"); self.session.span_note(expr.span, @@ -5116,11 +5121,11 @@ impl Resolver { this.resolve_path(expr.id, path, TypeNS, false)) { Some((DefTy(struct_id), _)) if self.structs.contains(&struct_id) => { - self.resolve_error(expr.span, - format!("`{}` is a structure name, but \ + resolve_err!(self, expr.span, A0097, + "`{}` is a structure name, but \ this expression \ uses it like a function name", - wrong_name)); + wrong_name); self.session.span_note(expr.span, format!("Did you mean to write: \ @@ -5133,15 +5138,15 @@ impl Resolver { // of stupid suggestions match self.find_best_match_for_name(wrong_name, 5) { Some(m) => { - self.resolve_error(expr.span, - format!("unresolved name `{}`. \ + resolve_err!(self, expr.span, A0098, + "unresolved name `{}`. \ Did you mean `{}`?", - wrong_name, m)); + wrong_name, m); } None => { - self.resolve_error(expr.span, - format!("unresolved name `{}`.", - wrong_name)); + resolve_err!(self, expr.span, A0099, + "unresolved name `{}`.", + wrong_name); } } } @@ -5173,9 +5178,9 @@ impl Resolver { result => { debug!("(resolving expression) didn't find struct \ def: {:?}", result); - let msg = format!("`{}` does not name a structure", - self.path_idents_to_str(path)); - self.resolve_error(path.span, msg); + resolve_err!(self, path.span, A0100, + "`{}` does not name a structure", + self.path_idents_to_str(path)); } } @@ -5204,12 +5209,12 @@ impl Resolver { let mut label_ribs = self.label_ribs.borrow_mut(); match self.search_ribs(label_ribs.get(), label, expr.span) { None => - self.resolve_error(expr.span, - format!("use of undeclared label \ + resolve_err!(self, expr.span, A0101, + "use of undeclared label \ `{}`", token::get_ident(label) .get() - .to_str())), + .to_str()), Some(DlDef(def @ DefLabel(_))) => { // FIXME: is AllPublic correct? self.record_def(expr.id, (def, AllPublic)) @@ -5432,10 +5437,10 @@ impl Resolver { match pat_binding_mode { BindByValue(_) => {} BindByRef(..) => { - self.resolve_error( - pat.span, - format!("cannot use `ref` binding mode with {}", - descr)); + resolve_err!(self, + pat.span, A0102, + "cannot use `ref` binding mode with {}", + descr); } } } diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index ab730c1b2e547..fd97dc9df2a64 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -258,10 +258,10 @@ impl LifetimeContext { fn unresolved_lifetime_ref(&self, lifetime_ref: &ast::Lifetime) { - self.sess.span_err( - lifetime_ref.span, - format!("use of undeclared lifetime name `'{}`", - self.sess.str_of(lifetime_ref.ident))); + span_err!(self.sess, + lifetime_ref.span, A0327, + "use of undeclared lifetime name `'{}`", + self.sess.str_of(lifetime_ref.ident)); } fn check_lifetime_names(&self, lifetimes: &OptVec) { @@ -271,10 +271,10 @@ impl LifetimeContext { let special_idents = [special_idents::statik]; for lifetime in lifetimes.iter() { if special_idents.iter().any(|&i| i == lifetime.ident) { - self.sess.span_err( - lifetime.span, - format!("illegal lifetime parameter name: `{}`", - self.sess.str_of(lifetime.ident))); + span_err!(self.sess, + lifetime.span, A0328, + "illegal lifetime parameter name: `{}`", + self.sess.str_of(lifetime.ident)); } } @@ -282,11 +282,11 @@ impl LifetimeContext { let lifetime_j = lifetimes.get(j); if lifetime_i.ident == lifetime_j.ident { - self.sess.span_err( - lifetime_j.span, - format!("lifetime name `'{}` declared twice in \ + span_err!(self.sess, + lifetime_j.span, A0329, + "lifetime name `'{}` declared twice in \ the same scope", - self.sess.str_of(lifetime_j.ident))); + self.sess.str_of(lifetime_j.ident)); } } } diff --git a/src/librustc/middle/subst.rs b/src/librustc/middle/subst.rs index 7176b512c719f..d30bc39b917ad 100644 --- a/src/librustc/middle/subst.rs +++ b/src/librustc/middle/subst.rs @@ -95,11 +95,17 @@ impl<'a> TypeFolder for SubstFolder<'a> { root.repr(self.tcx)), None => ~"" }; - let m = format!("missing type param `{}`{}", - t.repr(self.tcx), root_msg); match self.span { - Some(span) => self.tcx.sess.span_err(span, m), - None => self.tcx.sess.err(m) + Some(span) => { + span_err!(self.tcx.sess, span, A0307, + "missing type param `{}`{}", + t.repr(self.tcx), root_msg); + } + None => { + alert_err!(self.tcx.sess, A0308, + "missing type param `{}`{}", + t.repr(self.tcx), root_msg); + } } ty::mk_err() } @@ -113,10 +119,17 @@ impl<'a> TypeFolder for SubstFolder<'a> { root.repr(self.tcx)), None => ~"" }; - let m = format!("missing `Self` type param{}", root_msg); match self.span { - Some(span) => self.tcx.sess.span_err(span, m), - None => self.tcx.sess.err(m) + Some(span) => { + span_err!(self.tcx.sess, span, A0309, + "missing `Self` type param{}", + root_msg); + } + None => { + alert_err!(self.tcx.sess, A0310, + "missing `Self` type param{}", + root_msg); + } } ty::mk_err() } diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 39e0ca176eb0b..1c6d876e5304f 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -343,8 +343,8 @@ pub fn malloc_raw_dyn<'a>( match li.require(it) { Ok(id) => id, Err(s) => { - bcx.tcx().sess.fatal(format!("allocation of `{}` {}", - bcx.ty_to_str(t), s)); + alert_fatal!(bcx.tcx().sess, A0060, "allocation of `{}` {}", + bcx.ty_to_str(t), s); } } } @@ -1746,7 +1746,7 @@ pub fn trans_item(ccx: @CrateContext, item: &ast::Item) { // because we need to get the value of the bool out of LLVM if attr::contains_name(item.attrs, "static_assert") { if m == ast::MutMutable { - ccx.sess.span_fatal(expr.span, + span_fatal!(ccx.sess, expr.span, A0027, "cannot have static_assert on a mutable \ static"); } @@ -1755,7 +1755,7 @@ pub fn trans_item(ccx: @CrateContext, item: &ast::Item) { let v = const_values.get().get_copy(&item.id); unsafe { if !(llvm::LLVMConstIntGetZExtValue(v) != 0) { - ccx.sess.span_fatal(expr.span, "static assertion failed"); + span_fatal!(ccx.sess, expr.span, A0028, "static assertion failed"); } } } @@ -1901,7 +1901,9 @@ pub fn create_entry_wrapper(ccx: @CrateContext, let (start_fn, args) = if use_start_lang_item { let start_def_id = match ccx.tcx.lang_items.require(StartFnLangItem) { Ok(id) => id, - Err(s) => { ccx.tcx.sess.fatal(s); } + Err(s) => { + alert_fatal!(ccx.tcx.sess, A0207, "missing start lang item: {}", s); + } }; let start_fn = if start_def_id.crate == ast::LOCAL_CRATE { get_item_val(ccx, start_def_id.node) diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 7dbf159265dd1..75d720e37529a 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -383,7 +383,7 @@ impl<'a> FunctionContext<'a> { pub fn warn_not_to_commit(ccx: &mut CrateContext, msg: &str) { if !ccx.do_not_commit_warning_issued.get() { ccx.do_not_commit_warning_issued.set(true); - ccx.sess.warn(msg.to_str() + " -- do not commit like this!"); + alert_warn!(ccx.sess, A0340, "do not commit like this! ({})", msg); } } @@ -992,8 +992,14 @@ pub fn langcall(bcx: &Block, Err(s) => { let msg = format!("{} {}", msg, s); match span { - Some(span) => { bcx.tcx().sess.span_fatal(span, msg); } - None => { bcx.tcx().sess.fatal(msg); } + Some(span) => { + span_fatal!(bcx.tcx().sess, span, A0023, + "lang item call: {}", msg); + } + None => { + alert_fatal!(bcx.tcx().sess, A0024, + "lang item calL: {}", msg); + } } } } diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs index 760c56dd9459a..bc470446e39e8 100644 --- a/src/librustc/middle/trans/consts.rs +++ b/src/librustc/middle/trans/consts.rs @@ -470,7 +470,7 @@ fn const_expr_unadjusted(cx: @CrateContext, e: &ast::Expr, if iv >= len { // FIXME #3170: report this earlier on in the const-eval // pass. Reporting here is a bit late. - cx.sess.span_err(e.span, + span_err!(cx.sess, e.span, A0311, "const index-expr is out of bounds"); } (const_get_elt(cx, arr, [iv as c_uint]), inlineable) diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index d214a192ed8d4..40dfe5252c319 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -872,7 +872,8 @@ fn compile_unit_metadata(cx: &CrateContext) { None => fallback_path(cx), Some(ref abs_path) => { if abs_path.is_relative() { - cx.sess.warn("debuginfo: Invalid path to crate's local root source file!"); + alert_warn!(cx.sess, A0339, + "debuginfo: Invalid path to crate's local root source file!"); fallback_path(cx) } else { match abs_path.path_relative_from(work_dir) { @@ -1403,10 +1404,10 @@ fn describe_enum_variant(cx: &CrateContext, match cx.tcx.items.find(variant_info.id.node) { Some(ast_map::NodeVariant(ref variant, _, _)) => variant.span, ref node => { - cx.sess.span_warn(span, - format!("debuginfo::enum_metadata()::\ + span_warn!(cx.sess, span, A0331, + "debuginfo::enum_metadata()::\ adt_struct_metadata() - Unexpected node \ - type: {:?}. This is a bug.", node)); + type: {:?}. This is a bug.", node); codemap::DUMMY_SP } } @@ -2266,10 +2267,10 @@ fn get_namespace_and_span_for_item(cx: &CrateContext, let definition_span = match cx.tcx.items.find(def_id.node) { Some(ast_map::NodeItem(item, _)) => item.span, ref node => { - cx.sess.span_warn(warning_span, - format!("debuginfo::\ + span_warn!(cx.sess, warning_span, A0332, + "debuginfo::\ get_namespace_and_span_for_item() \ - - Unexpected node type: {:?}", *node)); + - Unexpected node type: {:?}", *node); codemap::DUMMY_SP } }; diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index cb638e99ab723..f1fbb89d22926 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -125,13 +125,13 @@ pub fn register_foreign_item_fn(ccx: @CrateContext, let cc = match llvm_calling_convention(ccx, abis) { Some(cc) => cc, None => { - ccx.sess.span_fatal(foreign_item.span, - format!("ABI `{}` has no suitable ABI \ - for target architecture \ - in module {}", - abis.user_string(ccx.tcx), - ast_map::path_to_str(*path, - ccx.sess.intr()))); + span_fatal!(ccx.sess, foreign_item.span, A0025, + "ABI `{}` has no suitable ABI \ + for target architecture \ + in module {}", + abis.user_string(ccx.tcx), + ast_map::path_to_str(*path, + ccx.sess.intr())); } }; @@ -285,10 +285,10 @@ pub fn trans_native_call<'a>( Some(cc) => cc, None => { // FIXME(#8357) We really ought to report a span here - ccx.sess.fatal( - format!("ABI string `{}` has no suitable ABI \ + alert_fatal!(ccx.sess, A0057, + "ABI string `{}` has no suitable ABI \ for target architecture", - fn_abis.user_string(ccx.tcx))); + fn_abis.user_string(ccx.tcx)); } }; diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index 1b9605a172cb6..bc2aab8e96478 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -212,7 +212,7 @@ fn make_visit_glue<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t) ty::ReStatic) { Ok(pair) => pair, Err(s) => { - bcx.tcx().sess.fatal(s); + alert_fatal!(bcx.tcx().sess, A0061, "error making visit glue: {}", s); } }; let v = PointerCast(bcx, v, type_of(bcx.ccx(), object_ty).ptr_to()); diff --git a/src/librustc/middle/trans/intrinsic.rs b/src/librustc/middle/trans/intrinsic.rs index 653f56c6de313..8c8a6373b3877 100644 --- a/src/librustc/middle/trans/intrinsic.rs +++ b/src/librustc/middle/trans/intrinsic.rs @@ -227,7 +227,7 @@ pub fn trans_intrinsic(ccx: @CrateContext, "acq" => lib::llvm::Acquire, "rel" => lib::llvm::Release, "acqrel" => lib::llvm::AcquireRelease, - _ => ccx.sess.fatal("unknown ordering in atomic intrinsic") + _ => alert_fatal!(ccx.sess, A0058, "unknown ordering in atomic intrinsic") } }; @@ -268,7 +268,7 @@ pub fn trans_intrinsic(ccx: @CrateContext, "min" => lib::llvm::Min, "umax" => lib::llvm::UMax, "umin" => lib::llvm::UMin, - _ => ccx.sess.fatal("unknown atomic operation") + _ => alert_fatal!(ccx.sess, A0059, "unknown atomic operation") }; let old = AtomicRMW(bcx, atom_op, get_param(decl, first_real_arg), @@ -389,8 +389,8 @@ pub fn trans_intrinsic(ccx: @CrateContext, } }; let pluralize = |n| if 1 == n { "" } else { "s" }; - ccx.sess.span_fatal(sp, - format!("transmute called on types with \ + span_fatal!(ccx.sess, sp, A0026, + "transmute called on types with \ different sizes: {} ({} bit{}) to \ {} ({} bit{})", ty_to_str(ccx.tcx, in_type), @@ -398,7 +398,7 @@ pub fn trans_intrinsic(ccx: @CrateContext, pluralize(in_type_size), ty_to_str(ccx.tcx, out_type), out_type_size, - pluralize(out_type_size))); + pluralize(out_type_size)); } if !return_type_is_void(ccx, out_type) { diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs index 61100220ffb47..ca73bd3532994 100644 --- a/src/librustc/middle/trans/monomorphize.rs +++ b/src/librustc/middle/trans/monomorphize.rs @@ -201,8 +201,8 @@ pub fn monomorphic_fn(ccx: @CrateContext, // recursively more than thirty times can probably safely be assumed // to be causing an infinite expansion. if depth > 30 { - ccx.sess.span_fatal( - span, "overly deep expansion of inlined function"); + span_fatal!(ccx.sess, span, A0022, + "overly deep expansion of inlined function"); } monomorphizing.get().insert(fn_id, depth + 1); } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 7b2aee9274a7d..6c48db1bb8d20 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -3382,12 +3382,13 @@ pub fn occurs_check(tcx: ctxt, sp: Span, vid: TyVid, rt: t) { // Maybe this should be span_err -- however, there's an // assertion later on that the type doesn't contain // variables, so in this case we have to be sure to die. - tcx.sess.span_fatal - (sp, ~"type inference failed because I \ - could not find a type\n that's both of the form " - + ::util::ppaux::ty_to_str(tcx, mk_var(tcx, vid)) + - " and of the form " + ::util::ppaux::ty_to_str(tcx, rt) + - " - such a type would have to be infinitely large."); + span_fatal!(tcx.sess, sp, A0342, + "type inference failed because I \ + could not find a type\n that's both of the form {} \" + and of the form {} \" + - such a type would have to be infinitely large.", + ::util::ppaux::ty_to_str(tcx, mk_var(tcx, vid)), + ::util::ppaux::ty_to_str(tcx, rt)); } } @@ -4029,17 +4030,15 @@ pub fn enum_variants(cx: ctxt, id: ast::DefId) -> @~[@VariantInfo] { discriminant = val as Disr } Ok(_) => { - cx.sess - .span_err(e.span, + span_err!(cx.sess, e.span, A0262, "expected signed integer \ constant"); } Err(ref err) => { - cx.sess - .span_err(e.span, - format!("expected \ + span_err!(cx.sess, e.span, A0263, + "expected \ constant: {}", - (*err))); + (*err)); } }, None => {} @@ -4459,7 +4458,7 @@ pub fn eval_repeat_count(tcx: &T, count_expr: &ast::Expr) -> match const_eval::eval_const_expr_partial(tcx, count_expr) { Ok(ref const_val) => match *const_val { const_eval::const_int(count) => if count < 0 { - tcx.ty_ctxt().sess.span_err(count_expr.span, + span_err!(tcx.ty_ctxt().sess, count_expr.span, A0264, "expected positive integer for \ repeat count but found negative integer"); return 0; @@ -4468,32 +4467,32 @@ pub fn eval_repeat_count(tcx: &T, count_expr: &ast::Expr) -> }, const_eval::const_uint(count) => return count as uint, const_eval::const_float(count) => { - tcx.ty_ctxt().sess.span_err(count_expr.span, + span_err!(tcx.ty_ctxt().sess, count_expr.span, A0265, "expected positive integer for \ repeat count but found float"); return count as uint; } const_eval::const_str(_) => { - tcx.ty_ctxt().sess.span_err(count_expr.span, + span_err!(tcx.ty_ctxt().sess, count_expr.span, A0266, "expected positive integer for \ repeat count but found string"); return 0; } const_eval::const_bool(_) => { - tcx.ty_ctxt().sess.span_err(count_expr.span, + span_err!(tcx.ty_ctxt().sess, count_expr.span, A0267, "expected positive integer for \ repeat count but found boolean"); return 0; } const_eval::const_binary(_) => { - tcx.ty_ctxt().sess.span_err(count_expr.span, + span_err!(tcx.ty_ctxt().sess, count_expr.span, A0268, "expected positive integer for \ repeat count but found binary array"); return 0; } }, Err(..) => { - tcx.ty_ctxt().sess.span_err(count_expr.span, + span_err!(tcx.ty_ctxt().sess, count_expr.span, A0269, "expected constant integer for repeat count \ but found variable"); return 0; diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index f80658e8ac20b..e5d15316afea6 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -133,8 +133,8 @@ fn opt_ast_region_to_region( match rscope.anon_regions(default_span, 1) { Err(()) => { debug!("optional region in illegal location"); - this.tcx().sess.span_err( - default_span, "missing lifetime specifier"); + span_err!(this.tcx().sess, + default_span, A0109, "missing lifetime specifier"); ty::ReStatic } @@ -181,12 +181,12 @@ fn ast_path_substs( rscope.anon_regions(path.span, expected_num_region_params); if supplied_num_region_params != 0 || anon_regions.is_err() { - tcx.sess.span_err( - path.span, - format!("wrong number of lifetime parameters: \ + span_err!(tcx.sess, + path.span, A0110, + "wrong number of lifetime parameters: \ expected {} but found {}", expected_num_region_params, - supplied_num_region_params)); + supplied_num_region_params); } match anon_regions { @@ -208,18 +208,18 @@ fn ast_path_substs( } else { "expected" }; - this.tcx().sess.span_fatal(path.span, - format!("wrong number of type arguments: {} {} but found {}", - expected, required_ty_param_count, supplied_ty_param_count)); + span_fatal!(this.tcx().sess, path.span, A0038, + "wrong number of type arguments: {} {} but found {}", + expected, required_ty_param_count, supplied_ty_param_count); } else if supplied_ty_param_count > formal_ty_param_count { let expected = if required_ty_param_count < formal_ty_param_count { "expected at most" } else { "expected" }; - this.tcx().sess.span_fatal(path.span, - format!("wrong number of type arguments: {} {} but found {}", - expected, formal_ty_param_count, supplied_ty_param_count)); + span_fatal!(this.tcx().sess, path.span, A0039, + "wrong number of type arguments: {} {} but found {}", + expected, formal_ty_param_count, supplied_ty_param_count); } if supplied_ty_param_count > required_ty_param_count { @@ -312,16 +312,16 @@ fn check_path_args(tcx: ty::ctxt, flags: uint) { if (flags & NO_TPS) != 0u { if !path.segments.iter().all(|s| s.types.is_empty()) { - tcx.sess.span_err( - path.span, + span_err!(tcx.sess, + path.span, A0111, "type parameters are not allowed on this type"); } } if (flags & NO_REGIONS) != 0u { if !path.segments.last().unwrap().lifetimes.is_empty() { - tcx.sess.span_err( - path.span, + span_err!(tcx.sess, + path.span, A0112, "region parameters are not allowed on this type"); } } @@ -332,9 +332,9 @@ pub fn ast_ty_to_prim_ty(tcx: ty::ctxt, ast_ty: &ast::Ty) -> Option { ast::TyPath(ref path, _, id) => { let def_map = tcx.def_map.borrow(); let a_def = match def_map.get().find(&id) { - None => tcx.sess.span_fatal( - ast_ty.span, format!("unbound path {}", - path_to_str(path, tcx.sess.intr()))), + None => span_fatal!(tcx.sess, + ast_ty.span, A0040, "unbound path {}", + path_to_str(path, tcx.sess.intr())), Some(&d) => d }; match a_def { @@ -361,7 +361,7 @@ pub fn ast_ty_to_prim_ty(tcx: ty::ctxt, ast_ty: &ast::Ty) -> Option { Some(ty::mk_mach_float(ft)) } ast::TyStr => { - tcx.sess.span_err(ast_ty.span, + span_err!(tcx.sess, ast_ty.span, A0113, "bare `str` is not a type"); // return /something/ so they can at least get more errors Some(ty::mk_str(tcx, ty::vstore_uniq)) @@ -400,7 +400,8 @@ pub fn ast_ty_to_ty( fn expect_vstore(&self, tcx: ty::ctxt, span: Span, ty: &str) -> ty::vstore { match *self { Box => { - tcx.sess.span_err(span, format!("managed {} are not supported", ty)); + span_err!(tcx.sess, span, A0114, + "managed {} are not supported", ty); // everything can be ~, so this is a worth substitute ty::vstore_uniq } @@ -454,8 +455,8 @@ pub fn ast_ty_to_ty( ty::RegionTraitStore(r) } _ => { - tcx.sess.span_err( - path.span, + span_err!(tcx.sess, + path.span, A0215, "~trait or &trait are the only supported \ forms of casting-to-trait"); return ty::mk_err(); @@ -486,7 +487,7 @@ pub fn ast_ty_to_ty( match ast_ty_to_ty_cache.get().find(&ast_ty.id) { Some(&ty::atttce_resolved(ty)) => return ty, Some(&ty::atttce_unresolved) => { - tcx.sess.span_fatal(ast_ty.span, + span_fatal!(tcx.sess, ast_ty.span, A0041, "illegal recursive type; insert an enum \ or struct in the cycle, if this is \ desired"); @@ -509,7 +510,7 @@ pub fn ast_ty_to_ty( |tmt| ty::mk_uniq(tcx, tmt.ty)) } ast::TyVec(ty) => { - tcx.sess.span_err(ast_ty.span, "bare `[]` is not a type"); + span_err!(tcx.sess, ast_ty.span, A0115, "bare `[]` is not a type"); // return /something/ so they can at least get more errors ty::mk_vec(tcx, ast_ty_to_mt(this, rscope, ty), ty::vstore_uniq) } @@ -528,7 +529,7 @@ pub fn ast_ty_to_ty( } ast::TyBareFn(ref bf) => { if bf.decl.variadic && !bf.abis.is_c() { - tcx.sess.span_err(ast_ty.span, + span_err!(tcx.sess, ast_ty.span, A0116, "variadic function must have C calling convention"); } ty::mk_bare_fn(tcx, ty_of_bare_fn(this, ast_ty.id, bf.purity, @@ -536,7 +537,7 @@ pub fn ast_ty_to_ty( } ast::TyClosure(ref f) => { if f.sigil == ast::ManagedSigil { - tcx.sess.span_err(ast_ty.span, + span_err!(tcx.sess, ast_ty.span, A0117, "managed closures are not supported"); } @@ -563,9 +564,9 @@ pub fn ast_ty_to_ty( ast::TyPath(ref path, ref bounds, id) => { let def_map = tcx.def_map.borrow(); let a_def = match def_map.get().find(&id) { - None => tcx.sess.span_fatal( - ast_ty.span, format!("unbound path {}", - path_to_str(path, tcx.sess.intr()))), + None => span_fatal!(tcx.sess, + ast_ty.span, A0042, "unbound path {}", + path_to_str(path, tcx.sess.intr())), Some(&d) => d }; // Kind bounds on path types are only supported for traits. @@ -573,18 +574,18 @@ pub fn ast_ty_to_ty( // But don't emit the error if the user meant to do a trait anyway. ast::DefTrait(..) => { }, _ if bounds.is_some() => - tcx.sess.span_err(ast_ty.span, + span_err!(tcx.sess, ast_ty.span, A0118, "kind bounds can only be used on trait types"), _ => { }, } match a_def { ast::DefTrait(_) => { let path_str = path_to_str(path, tcx.sess.intr()); - tcx.sess.span_err( - ast_ty.span, - format!("reference to trait `{}` where a type is expected; \ + span_err!(tcx.sess, + ast_ty.span, A0217, + "reference to trait `{}` where a type is expected; \ try `@{}`, `~{}`, or `&{}`", - path_str, path_str, path_str, path_str)); + path_str, path_str, path_str, path_str); ty::mk_err() } ast::DefTy(did) | ast::DefStruct(did) => { @@ -603,17 +604,17 @@ pub fn ast_ty_to_ty( ty::mk_self(tcx, did) } ast::DefMod(id) => { - tcx.sess.span_fatal(ast_ty.span, - format!("found module name used as a type: {}", + span_fatal!(tcx.sess, ast_ty.span, A0043, + "found module name used as a type: {}", ast_map::node_id_to_str(tcx.items, id.node, - token::get_ident_interner()))); + token::get_ident_interner())); } ast::DefPrimTy(_) => { fail!("DefPrimTy arm missed in previous ast_ty_to_prim_ty call"); } _ => { - tcx.sess.span_fatal(ast_ty.span, - format!("found value name used as a type: {:?}", a_def)); + span_fatal!(tcx.sess, ast_ty.span, A0044, + "found value name used as a type: {:?}", a_def); } } } @@ -628,15 +629,16 @@ pub fn ast_ty_to_ty( ty::mk_vec(tcx, ast_ty_to_mt(this, rscope, ty), ty::vstore_fixed(i as uint)), _ => { - tcx.sess.span_fatal( - ast_ty.span, "expected constant expr for vector length"); + span_fatal!(tcx.sess, + ast_ty.span, A0045, + "expected constant expr for vector length"); } } } Err(ref r) => { - tcx.sess.span_fatal( - ast_ty.span, - format!("expected constant expr for vector length: {}", *r)); + span_fatal!(tcx.sess, + ast_ty.span, A0046, + "expected constant expr for vector length: {}", *r); } } } @@ -848,10 +850,10 @@ fn conv_builtin_bounds(tcx: ty::ctxt, ast_bounds: &Option { } } - tcx.sess.span_fatal( - b.path.span, - format!("only the builtin traits can be used \ - as closure or object bounds")); + span_fatal!(tcx.sess, + b.path.span, A0216, + "only the builtin traits can be used \ + as closure or object bounds"); } ast::RegionTyParamBound => { builtin_bounds.add(ty::BoundStatic); diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs index 97b07186f4e09..d6718a0eddaac 100644 --- a/src/librustc/middle/typeck/check/_match.rs +++ b/src/librustc/middle/typeck/check/_match.rs @@ -241,13 +241,13 @@ 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{}", + span_err!(tcx.sess, pat.span, A0224, + "this pattern has {} field{}, but the corresponding {} has {} field{}", subpats_len, if subpats_len == 1u { ~"" } else { ~"s" }, kind_name, arg_len, if arg_len == 1u { ~"" } else { ~"s" }); - tcx.sess.span_err(pat.span, s); error_happened = true; } @@ -259,12 +259,12 @@ 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 \ + span_err!(tcx.sess, pat.span, A0225, + "this pattern has {} field{}, but the corresponding {} has no \ fields", subpats_len, if subpats_len == 1u { "" } else { "s" }, - kind_name)); + kind_name); error_happened = true; } @@ -306,9 +306,9 @@ pub fn check_struct_pat_fields(pcx: &pat_ctxt, for field in fields.iter() { match field_map.find_mut(&field.ident.name) { Some(&(_, true)) => { - tcx.sess.span_err(span, - format!("field `{}` bound twice in pattern", - tcx.sess.str_of(field.ident))); + span_err!(tcx.sess, span, A0226, + "field `{}` bound twice in pattern", + tcx.sess.str_of(field.ident)); } Some(&(index, ref mut used)) => { *used = true; @@ -325,10 +325,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 `{}`", + span_err!(tcx.sess, span, A0227, + "struct `{}` does not have a field named `{}`", name, - tcx.sess.str_of(field.ident))); + tcx.sess.str_of(field.ident)); } } } @@ -341,9 +341,9 @@ pub fn check_struct_pat_fields(pcx: &pat_ctxt, } let string = token::get_ident(field.name); - tcx.sess.span_err(span, - format!("pattern does not mention field `{}`", - string.get())); + span_err!(tcx.sess, span, A0228, + "pattern does not mention field `{}`", + string.get()); } } } @@ -367,10 +367,10 @@ pub fn check_struct_pat(pcx: &pat_ctxt, pat_id: ast::NodeId, span: Span, } Some(&ast::DefStruct(..)) | Some(&ast::DefVariant(..)) => { let name = pprust::path_to_str(path, tcx.sess.intr()); - tcx.sess.span_err(span, - format!("mismatched types: expected `{}` but found `{}`", + span_err!(tcx.sess, span, A0229, + "mismatched types: expected `{}` but found `{}`", fcx.infcx().ty_to_str(expected), - name)); + name); } _ => { tcx.sess.span_bug(span, "resolve didn't write in struct ID"); @@ -406,11 +406,11 @@ pub fn check_struct_like_enum_variant_pat(pcx: &pat_ctxt, } Some(&ast::DefStruct(..)) | Some(&ast::DefVariant(..)) => { let name = pprust::path_to_str(path, tcx.sess.intr()); - tcx.sess.span_err(span, - format!("mismatched types: expected `{}` but \ + span_err!(tcx.sess, span, A0230, + "mismatched types: expected `{}` but \ found `{}`", fcx.infcx().ty_to_str(expected), - name)); + name); } _ => { tcx.sess.span_bug(span, "resolve didn't write in variant"); @@ -447,15 +447,15 @@ 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, "non-numeric type used in range"); + span_err!(tcx.sess, pat.span, A0231, "non-numeric type used 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, A0232, "lower range bound must be less than upper"); }, None => { - tcx.sess.span_err(begin.span, + span_err!(tcx.sess, begin.span, A0233, "mismatched types in range"); }, _ => { }, diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index f19ca049368d0..2131a9d3224eb 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -870,8 +870,8 @@ impl<'a> LookupContext<'a> { } if relevant_candidates.len() > 1 { - self.tcx().sess.span_err( - self.expr.span, + span_err!(self.tcx().sess, + self.expr.span, A0154, "multiple applicable methods in scope"); for (idx, candidate) in relevant_candidates.iter().enumerate() { self.report_candidate(idx, &candidate.origin); @@ -957,13 +957,13 @@ 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.expr.span, + span_err!(tcx.sess, + self.expr.span, A0155, "this method 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.expr.span, + span_err!(tcx.sess, + self.expr.span, A0156, "incorrect number of type \ parameters given for this method"); self.fcx.infcx().next_ty_vars(num_method_tps) @@ -1122,15 +1122,15 @@ impl<'a> LookupContext<'a> { match candidate.method_ty.explicit_self { ast::SelfStatic => { // reason (a) above - self.tcx().sess.span_err( - self.expr.span, + span_err!(self.tcx().sess, + self.expr.span, A0157, "cannot call a method without a receiver \ through an object"); } ast::SelfValue => { // reason (a) above - self.tcx().sess.span_err( - self.expr.span, + span_err!(self.tcx().sess, + self.expr.span, A0158, "cannot call a method with a by-value receiver \ through an object"); } @@ -1141,8 +1141,8 @@ 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.expr.span, + span_err!(self.tcx().sess, + self.expr.span, A0159, "cannot call a method whose type contains a \ self-type through an object"); true @@ -1163,8 +1163,8 @@ impl<'a> LookupContext<'a> { } if candidate.method_ty.generics.has_type_params() { // reason (b) above - self.tcx().sess.span_err( - self.expr.span, + span_err!(self.tcx().sess, + self.expr.span, A0160, "cannot call a generic method through an object"); } } @@ -1189,7 +1189,7 @@ impl<'a> LookupContext<'a> { } if bad { - self.tcx().sess.span_err(self.expr.span, + span_err!(self.tcx().sess, self.expr.span, A0210, "explicit call to destructor"); } } diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 2332152a5d734..5c89cbdd6239f 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -517,8 +517,9 @@ pub fn check_no_duplicate_fields(tcx: ty::ctxt, let orig_sp = field_names.find(&id).map(|x| *x); match orig_sp { Some(orig_sp) => { - tcx.sess.span_err(sp, format!("duplicate field name {} in record type declaration", - tcx.sess.str_of(id))); + span_err!(tcx.sess, sp, A0161, + "duplicate field name {} in record type declaration", + tcx.sess.str_of(id)); tcx.sess.span_note(orig_sp, "first declaration of this field occurred here"); break; } @@ -627,14 +628,15 @@ pub fn check_item(ccx: @CrateCtxt, it: &ast::Item) { for item in m.items.iter() { let tpt = ty::lookup_item_type(ccx.tcx, local_def(item.id)); if tpt.generics.has_type_params() { - ccx.tcx.sess.span_err(item.span, "foreign items may not have type parameters"); + span_err!(ccx.tcx.sess, item.span, A0162, + "foreign items may not have type parameters"); } match item.node { ast::ForeignItemFn(ref fn_decl, _) => { if fn_decl.variadic && !m.abis.is_c() { - ccx.tcx.sess.span_err( - item.span, "variadic function must have C calling convention"); + span_err!(ccx.tcx.sess, item.span, A0163, + "variadic function must have C calling convention"); } } _ => {} @@ -718,12 +720,12 @@ fn check_impl_methods_against_trait(ccx: @CrateCtxt, &impl_trait_ref.substs); } None => { - tcx.sess.span_err( - impl_method.span, - format!("method `{}` is not a member of trait `{}`", + span_err!(tcx.sess, + impl_method.span, A0164, + "method `{}` is not a member of trait `{}`", tcx.sess.str_of(impl_method_ty.ident), pprust::path_to_str(&ast_trait_ref.path, - tcx.sess.intr()))); + tcx.sess.intr())); } } } @@ -746,10 +748,10 @@ 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(", "))); + span_err!(tcx.sess, + impl_span, A0165, + "not all trait methods implemented, missing: {}", + missing_methods.connect(", ")); } } @@ -788,23 +790,23 @@ 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, \ + span_err!(tcx.sess, + impl_m_span, A0166, + "method `{}` has a `{}` declaration in the impl, \ but not in the trait", tcx.sess.str_of(trait_m.ident), pprust::explicit_self_to_str(&impl_m.explicit_self, - tcx.sess.intr()))); + tcx.sess.intr())); return; } (_, &ast::SelfStatic) => { - tcx.sess.span_err( - impl_m_span, - format!("method `{}` has a `{}` declaration in the trait, \ + span_err!(tcx.sess, + impl_m_span, A0167, + "method `{}` has a `{}` declaration in the trait, \ but not in the impl", tcx.sess.str_of(trait_m.ident), pprust::explicit_self_to_str(&trait_m.explicit_self, - tcx.sess.intr()))); + tcx.sess.intr())); return; } _ => { @@ -815,26 +817,26 @@ fn compare_impl_method(tcx: ty::ctxt, let num_impl_m_type_params = impl_m.generics.type_param_defs().len(); let num_trait_m_type_params = trait_m.generics.type_param_defs().len(); if num_impl_m_type_params != num_trait_m_type_params { - tcx.sess.span_err( - impl_m_span, - format!("method `{}` has {} type parameter(s), but its trait \ + span_err!(tcx.sess, + impl_m_span, A0168, + "method `{}` has {} type parameter(s), but its trait \ declaration has {} type parameter(s)", tcx.sess.str_of(trait_m.ident), num_impl_m_type_params, - num_trait_m_type_params)); + num_trait_m_type_params); 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{} \ + span_err!(tcx.sess, + impl_m_span, A0169, + "method `{}` has {} parameter{} \ but the declaration in trait `{}` has {}", tcx.sess.str_of(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())); + trait_m.fty.sig.inputs.len()); return; } @@ -848,16 +850,16 @@ 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 `{}`, \ + span_err!(tcx.sess, + impl_m_span, A0170, + "in method `{}`, \ type parameter {} requires `{}`, \ which is not required by \ the corresponding type parameter \ in the trait declaration", tcx.sess.str_of(trait_m.ident), i, - extra_bounds.user_string(tcx))); + extra_bounds.user_string(tcx)); return; } @@ -867,15 +869,15 @@ fn compare_impl_method(tcx: ty::ctxt, if impl_param_def.bounds.trait_bounds.len() != trait_param_def.bounds.trait_bounds.len() { - tcx.sess.span_err( - impl_m_span, - format!("in method `{}`, \ + span_err!(tcx.sess, + impl_m_span, A0171, + "in method `{}`, \ type parameter {} has {} trait bound(s), but the \ corresponding type parameter in \ the trait declaration has {} trait bound(s)", tcx.sess.str_of(trait_m.ident), i, impl_param_def.bounds.trait_bounds.len(), - trait_param_def.bounds.trait_bounds.len())); + trait_param_def.bounds.trait_bounds.len()); return; } } @@ -940,11 +942,11 @@ fn compare_impl_method(tcx: ty::ctxt, impl_fty, trait_fty) { result::Ok(()) => {} result::Err(ref terr) => { - tcx.sess.span_err( - impl_m_span, - format!("method `{}` has an incompatible type: {}", + span_err!(tcx.sess, + impl_m_span, A0172, + "method `{}` has an incompatible type: {}", tcx.sess.str_of(trait_m.ident), - ty::type_err_to_str(tcx, terr))); + ty::type_err_to_str(tcx, terr)); ty::note_and_explain_type_err(tcx, terr); } } @@ -1441,18 +1443,16 @@ fn check_type_parameter_positions_in_path(function_context: @FnCtxt, // except the final two elements of the path. for i in range(0, path.segments.len() - 2) { for lifetime in path.segments[i].lifetimes.iter() { - function_context.tcx() - .sess - .span_err(lifetime.span, + span_err!(function_context.tcx().sess, + lifetime.span, A0173, "lifetime parameters may not \ appear here"); break; } for typ in path.segments[i].types.iter() { - function_context.tcx() - .sess - .span_err(typ.span, + span_err!(function_context.tcx().sess, + typ.span, A0174, "type parameters may not appear here"); break; } @@ -1488,13 +1488,12 @@ fn check_type_parameter_positions_in_path(function_context: @FnCtxt, let supplied_region_parameter_count = trait_segment.lifetimes.len(); if trait_region_parameter_count != supplied_region_parameter_count && supplied_region_parameter_count != 0 { - function_context.tcx() - .sess - .span_err(path.span, - format!("expected {} lifetime parameter(s), \ + span_err!(function_context.tcx().sess, + path.span, A0175, + "expected {} lifetime parameter(s), \ found {} lifetime parameter(s)", trait_region_parameter_count, - supplied_region_parameter_count)); + supplied_region_parameter_count); } // Make sure the number of type parameters supplied on the trait @@ -1521,12 +1520,12 @@ fn check_type_parameter_positions_in_path(function_context: @FnCtxt, } else { "needs" }; - function_context.tcx().sess.span_err(path.span, - format!("the {} referenced by this path {} {} type \ + span_err!(function_context.tcx().sess, path.span, A0176, + "the {} referenced by this path {} {} type \ parameter{}, but {} type parameter{} were supplied", name, needs, required_ty_param_count, trait_count_suffix, - supplied_ty_param_count, supplied_count_suffix)) + supplied_ty_param_count, supplied_count_suffix) } else if supplied_ty_param_count > formal_ty_param_count { let trait_count_suffix = if formal_ty_param_count == 1 { "" @@ -1543,12 +1542,12 @@ fn check_type_parameter_positions_in_path(function_context: @FnCtxt, } else { "needs" }; - function_context.tcx().sess.span_err(path.span, - format!("the {} referenced by this path {} {} type \ + span_err!(function_context.tcx().sess, path.span, A0177, + "the {} referenced by this path {} {} type \ parameter{}, but {} type parameter{} were supplied", name, needs, formal_ty_param_count, trait_count_suffix, - supplied_ty_param_count, supplied_count_suffix)) + supplied_ty_param_count, supplied_count_suffix) } } _ => { @@ -1556,17 +1555,15 @@ fn check_type_parameter_positions_in_path(function_context: @FnCtxt, // the penultimate segment of the path. let segment = &path.segments[path.segments.len() - 2]; for lifetime in segment.lifetimes.iter() { - function_context.tcx() - .sess - .span_err(lifetime.span, + span_err!(function_context.tcx().sess, + lifetime.span, A0178, "lifetime parameters may not appear here"); break; } for typ in segment.types.iter() { - function_context.tcx() - .sess - .span_err(typ.span, + span_err!(function_context.tcx().sess, + typ.span, A0179, "type parameters may not appear \ here"); break; @@ -1651,7 +1648,7 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt, if supplied_arg_count >= expected_arg_count { fn_inputs.map(|a| *a) } else { - let msg = format!( + span_err!(tcx.sess, sp, A0180, "this function takes at least {} parameter{} \ but {} parameter{} supplied", expected_arg_count, @@ -1659,7 +1656,6 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt, supplied_arg_count, if supplied_arg_count == 1 {" was"} else {"s were"}); - tcx.sess.span_err(sp, msg); err_args(supplied_arg_count) } @@ -1669,7 +1665,7 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt, ast::ForSugar => " (including the closure passed by \ the `for` keyword)" }; - let msg = format!( + span_err!(tcx.sess, sp, A0181, "this function takes {} parameter{} \ but {} parameter{} supplied{}", expected_arg_count, if expected_arg_count == 1 {""} else {"s"}, @@ -1677,7 +1673,6 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt, if supplied_arg_count == 1 {" was"} else {"s were"}, suffix); - tcx.sess.span_err(sp, msg); err_args(supplied_arg_count) }; @@ -2395,10 +2390,10 @@ pub 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", - tcx.sess.str_of(field.ident.node))); + span_err!(tcx.sess, + field.ident.span, A0182, + "field `{}` specified more than once", + tcx.sess.str_of(field.ident.node)); error_happened = true; } Some((field_id, false)) => { @@ -2436,14 +2431,14 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt, } } - tcx.sess.span_err(span, - format!("missing field{}: {}", + span_err!(tcx.sess, span, A0183, + "missing field{}: {}", if missing_fields.len() == 1 { "" } else { "s" }, - missing_fields.connect(", "))); + missing_fields.connect(", ")); } } @@ -2644,7 +2639,8 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt, .require(GcLangItem) { Ok(id) => id, Err(msg) => { - tcx.sess.span_err(expr.span, msg); + span_err!(tcx.sess, expr.span, A0211, + "{}", msg); ast::DefId { crate: ast::CRATE_NODE_ID, node: ast::DUMMY_NODE_ID, @@ -2674,7 +2670,7 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt, } if !checked { - tcx.sess.span_err(expr.span, + span_err!(tcx.sess, expr.span, A0184, "only the managed heap and exchange heap are \ currently supported") } @@ -2721,7 +2717,7 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt, let tcx = fcx.tcx(); if !ty::expr_is_lval(tcx, fcx.ccx.method_map, lhs) { - tcx.sess.span_err(lhs.span, "illegal left-hand side expression"); + span_err!(tcx.sess, lhs.span, A0185, "illegal left-hand side expression"); } // Overwrite result of check_binop...this preserves existing behavior @@ -2769,8 +2765,8 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt, && fields[0].ident == token::special_idents::unnamed_field } => { // This is an obsolete struct deref - tcx.sess.span_err( - expr.span, + span_err!(tcx.sess, + expr.span, A0186, "single-field tuple-structs can no longer be dereferenced"); } _ => { @@ -2866,8 +2862,8 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt, ret_ty, ty::mk_nil()) { result::Ok(_) => { /* fall through */ } result::Err(_) => { - tcx.sess.span_err( - expr.span, + span_err!(tcx.sess, + expr.span, A0187, "`return;` in function returning non-nil"); } }, @@ -2889,7 +2885,7 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt, let tcx = fcx.tcx(); if !ty::expr_is_lval(tcx, fcx.ccx.method_map, lhs) { - tcx.sess.span_err(lhs.span, "illegal left-hand side expression"); + span_err!(tcx.sess, lhs.span, A0188, "illegal left-hand side expression"); } let lhs_ty = fcx.expr_ty(lhs); @@ -3039,7 +3035,7 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt, }, t_e, None); } } else if ty::get(t1).sty == ty::ty_bool { - fcx.tcx().sess.span_err(expr.span, + span_err!(fcx.tcx().sess, expr.span, A0189, "cannot cast as `bool`, compare with zero instead"); } else if type_is_region_ptr(fcx, expr.span, t_e) && type_is_unsafe_ptr(fcx, expr.span, t_1) { @@ -3458,10 +3454,10 @@ pub fn check_representable(tcx: ty::ctxt, // caught by case 1. match ty::is_type_representable(tcx, rty) { ty::SelfRecursive => { - tcx.sess.span_err( - sp, format!("illegal recursive {} type; \ + span_err!(tcx.sess, sp, A0190, + "illegal recursive {} type; \ wrap the inner value in a box to make it representable", - designation)); + designation); } ty::Representable | ty::ContainsRecursive => (), } @@ -3483,34 +3479,35 @@ pub fn check_instantiable(tcx: ty::ctxt, item_id: ast::NodeId) { 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 \ + span_err!(tcx.sess, sp, A0191, + "this type cannot be instantiated \ without an instance of itself; \ consider using `Option<{}>`", - ppaux::ty_to_str(tcx, item_ty))); + ppaux::ty_to_str(tcx, item_ty)); } } 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, A0192, "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, A0193, "SIMD vector cannot be empty"); return; } let e = ty::lookup_field_type(tcx, did, fields[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, A0194, "SIMD vector should be homogeneous"); return; } if !ty::type_is_machine(e) { - tcx.sess.span_err(sp, "SIMD vector element type should be \ + span_err!(tcx.sess, sp, A0212, "SIMD vector element type should be \ machine type"); return; } @@ -3586,10 +3583,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, A0195, + "expected signed integer constant"); } Err(ref err) => { - ccx.tcx.sess.span_err(e.span, format!("expected constant: {}", (*err))); + span_err!(ccx.tcx.sess, e.span, A0196, + "expected constant: {}", (*err)); } } }, @@ -3598,14 +3597,15 @@ 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, A0197, + "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, + span_err!(ccx.tcx.sess, v.span, A0198, "discriminant value outside specified type"); ccx.tcx.sess.span_note(sp, "discriminant type specified here"); } @@ -3624,8 +3624,9 @@ pub fn check_enum_variants(ccx: @CrateCtxt, let hint = ty::lookup_repr_hint(ccx.tcx, ast::DefId { crate: ast::LOCAL_CRATE, node: id }); if hint != attr::ReprAny && vs.len() <= 1 { - ccx.tcx.sess.span_err(sp, format!("unsupported representation for {}variant enum", - if vs.len() == 1 { "uni" } else { "zero-" })) + span_err!(ccx.tcx.sess, sp, A0199, + "unsupported representation for {}variant enum", + if vs.len() == 1 { "uni" } else { "zero-" }) } let variants = do_check(ccx, vs, id, hint); @@ -3732,11 +3733,11 @@ pub fn instantiate_path(fcx: @FnCtxt, |l| ast_region_to_region(fcx.tcx(), l)) } else { if num_supplied_regions != 0 { - fcx.ccx.tcx.sess.span_err( - span, - format!("expected {} lifetime parameter(s), \ + span_err!(fcx.ccx.tcx.sess, + span, A0200, + "expected {} lifetime parameter(s), \ found {} lifetime parameter(s)", - num_expected_regions, num_supplied_regions)); + num_expected_regions, num_supplied_regions); } opt_vec::from(fcx.infcx().next_region_vars( @@ -3765,8 +3766,8 @@ pub fn instantiate_path(fcx: @FnCtxt, let (tps, regions) = if ty_substs_len == 0 { (fcx.infcx().next_ty_vars(ty_param_count), regions) } else if ty_param_count == 0 { - fcx.ccx.tcx.sess.span_err - (span, "this item does not take type parameters"); + span_err!(fcx.ccx.tcx.sess, span, A0201, + "this item does not take type parameters"); (fcx.infcx().next_ty_vars(ty_param_count), regions) } else if ty_substs_len > user_ty_param_count { let expected = if user_ty_param_req < user_ty_param_count { @@ -3774,10 +3775,9 @@ pub fn instantiate_path(fcx: @FnCtxt, } else { "expected" }; - fcx.ccx.tcx.sess.span_err - (span, - format!("too many type parameters provided: {} {}, found {}", - expected, user_ty_param_count, ty_substs_len)); + span_err!(fcx.ccx.tcx.sess, span, A0202, + "too many type parameters provided: {} {}, found {}", + expected, user_ty_param_count, ty_substs_len); (fcx.infcx().next_ty_vars(ty_param_count), regions) } else if ty_substs_len < user_ty_param_req { let expected = if user_ty_param_req < user_ty_param_count { @@ -3785,10 +3785,9 @@ pub fn instantiate_path(fcx: @FnCtxt, } else { "expected" }; - fcx.ccx.tcx.sess.span_err - (span, - format!("not enough type parameters provided: {} {}, found {}", - expected, user_ty_param_req, ty_substs_len)); + span_err!(fcx.ccx.tcx.sess, span, A0203, + "not enough type parameters provided: {} {}, found {}", + expected, user_ty_param_req, ty_substs_len); (fcx.infcx().next_ty_vars(ty_param_count), regions) } else { if ty_substs_len > user_ty_param_req { @@ -4008,9 +4007,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", - ccx.tcx.sess.str_of(tps.get(i).ident))); + span_err!(ccx.tcx.sess, span, A0213, + "type parameter `{}` is unused", + ccx.tcx.sess.str_of(tps.get(i).ident)); } } } @@ -4060,9 +4059,9 @@ pub fn check_intrinsic_type(ccx: @CrateCtxt, it: &ast::ForeignItem) { (0, ~[], ty::mk_nil()) } op => { - tcx.sess.span_err(it.span, - format!("unrecognized atomic operation function: `{}`", - op)); + span_err!(tcx.sess, it.span, A0204, + "unrecognized atomic operation function: `{}`", + op); return; } } @@ -4091,7 +4090,10 @@ pub fn check_intrinsic_type(ccx: @CrateCtxt, it: &ast::ForeignItem) { "get_tydesc" => { let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) { Ok(t) => t, - Err(s) => { tcx.sess.span_fatal(it.span, s); } + Err(s) => { + span_fatal!(tcx.sess, it.span, A0034, + "error type-checking get_tydesc intrinsic: {}", s); + } }; let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt { ty: tydesc_ty, @@ -4107,18 +4109,27 @@ pub fn check_intrinsic_type(ccx: @CrateCtxt, it: &ast::ForeignItem) { tps: ~[], regions: ty::NonerasedRegions(opt_vec::Empty) }) ), - Err(msg) => { tcx.sess.span_fatal(it.span, msg); } + Err(msg) => { + span_fatal!(tcx.sess, it.span, A0214, + "error type-checking type_id intrinsic: {}", msg); + } } }, "visit_tydesc" => { let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) { Ok(t) => t, - Err(s) => { tcx.sess.span_fatal(it.span, s); } + Err(s) => { + span_fatal!(tcx.sess, it.span, A0035, + "error type-checking visit_tydesc intrinsic: {}", s); + } }; let region = ty::ReLateBound(it.id, ty::BrAnon(0)); let visitor_object_ty = match ty::visitor_object_ty(tcx, region) { Ok((_, vot)) => vot, - Err(s) => { tcx.sess.span_fatal(it.span, s); } + Err(s) => { + span_fatal!(tcx.sess, it.span, A0036, + "error type-checking visit_tydesc intrinsic: {}", s); + } }; let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt { @@ -4299,9 +4310,9 @@ pub fn check_intrinsic_type(ccx: @CrateCtxt, it: &ast::ForeignItem) { ty::mk_tup(tcx, ~[ty::mk_u64(), ty::mk_bool()])), ref other => { - tcx.sess.span_err(it.span, - format!("unrecognized intrinsic function: `{}`", - *other)); + span_err!(tcx.sess, it.span, A0205, + "unrecognized intrinsic function: `{}`", + *other); return; } } @@ -4317,9 +4328,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.type_param_defs().len(); if i_n_tps != n_tps { - tcx.sess.span_err(it.span, format!("intrinsic has wrong number \ + span_err!(tcx.sess, it.span, A0206, + "intrinsic has wrong number \ of type parameters: found {}, \ - expected {}", i_n_tps, n_tps)); + expected {}", i_n_tps, n_tps); } else { require_same_types( tcx, None, false, it.span, i_ty.ty, fty, diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index 64589e64f9837..701166db101bc 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -154,12 +154,12 @@ fn lookup_vtables_for_param(vcx: &VtableContext, match lookup_vtable(vcx, location_info, ty, trait_ref, is_early) { Some(vtable) => param_result.push(vtable), None => { - vcx.tcx().sess.span_fatal( - location_info.span, - format!("failed to find an implementation of \ + span_fatal!(vcx.tcx().sess, + location_info.span, A0032, + "failed to find an implementation of \ trait {} for {}", vcx.infcx.trait_ref_to_str(trait_ref), - vcx.infcx.ty_to_str(ty))); + vcx.infcx.ty_to_str(ty)); } } true @@ -211,12 +211,12 @@ fn relate_trait_refs(vcx: &VtableContext, !ty::trait_ref_contains_error(&r_exp_trait_ref) { let tcx = vcx.tcx(); - tcx.sess.span_err( - location_info.span, - format!("expected {}, but found {} ({})", + span_err!(tcx.sess, + location_info.span, A0124, + "expected {}, but found {} ({})", ppaux::trait_ref_to_str(tcx, &r_exp_trait_ref), ppaux::trait_ref_to_str(tcx, &r_act_trait_ref), - ty::type_err_to_str(tcx, err))); + ty::type_err_to_str(tcx, err)); } } } @@ -468,8 +468,8 @@ fn search_for_vtable(vcx: &VtableContext, 1 => return Some(found[0].clone()), _ => { if !is_early { - vcx.tcx().sess.span_err( - location_info.span, + span_err!(vcx.tcx().sess, + location_info.span, A0125, "multiple applicable methods in scope"); } return Some(found[0].clone()); @@ -508,11 +508,11 @@ fn fixup_ty(vcx: &VtableContext, match resolve_type(vcx.infcx, ty, resolve_and_force_all_but_regions) { Ok(new_type) => Some(new_type), Err(e) if !is_early => { - tcx.sess.span_fatal( - location_info.span, - format!("cannot determine a type \ + span_fatal!(tcx.sess, + location_info.span, A0033, + "cannot determine a type \ for this bounded type parameter: {}", - fixup_err_to_str(e))) + fixup_err_to_str(e)) } Err(_) => { None @@ -585,14 +585,14 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: @FnCtxt, is_early: bool) { (&ty::ty_uniq(..), ty::UniqTraitStore) if !mutability_allowed(ast::MutImmutable, target_mutbl) => { - fcx.tcx().sess.span_err(ex.span, - format!("types differ in mutability")); + span_err!(fcx.tcx().sess, ex.span, A0126, + "types differ in mutability"); } (&ty::ty_rptr(_, mt), ty::RegionTraitStore(..)) if !mutability_allowed(mt.mutbl, target_mutbl) => { - fcx.tcx().sess.span_err(ex.span, - format!("types differ in mutability")); + span_err!(fcx.tcx().sess, ex.span, A0127, + "types differ in mutability"); } (&ty::ty_uniq(..), ty::UniqTraitStore) | @@ -648,19 +648,19 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: @FnCtxt, is_early: bool) { } (_, ty::UniqTraitStore) => { - fcx.ccx.tcx.sess.span_err( - ex.span, - format!("can only cast an ~-pointer \ + span_err!(fcx.ccx.tcx.sess, + ex.span, A0128, + "can only cast an ~-pointer \ to a ~-object, not a {}", - ty::ty_sort_str(fcx.tcx(), ty))); + ty::ty_sort_str(fcx.tcx(), ty)); } (_, ty::RegionTraitStore(_)) => { - fcx.ccx.tcx.sess.span_err( - ex.span, - format!("can only cast an &-pointer \ + span_err!(fcx.ccx.tcx.sess, + ex.span, A0130, + "can only cast an &-pointer \ to an &-object, not a {}", - ty::ty_sort_str(fcx.tcx(), ty))); + ty::ty_sort_str(fcx.tcx(), ty)); } } } diff --git a/src/librustc/middle/typeck/check/writeback.rs b/src/librustc/middle/typeck/check/writeback.rs index 48b1acd3f9b37..a004a29de407d 100644 --- a/src/librustc/middle/typeck/check/writeback.rs +++ b/src/librustc/middle/typeck/check/writeback.rs @@ -40,11 +40,10 @@ fn resolve_type_vars_in_type(fcx: @FnCtxt, sp: Span, typ: ty::t) Ok(new_type) => return Some(new_type), Err(e) => { if !fcx.ccx.tcx.sess.has_errors() { - fcx.ccx.tcx.sess.span_err( - sp, - format!("cannot determine a type \ + span_err!(fcx.ccx.tcx.sess, sp, A0219, + "cannot determine a type \ for this expression: {}", - infer::fixup_err_to_str(e))) + infer::fixup_err_to_str(e)) } return None; } @@ -138,11 +137,10 @@ fn resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId) resolve_all | force_all) { Err(e) => { // This should not, I think, happen: - tcx.sess.span_err( - sp, - format!("cannot resolve bound for closure: \ + span_err!(tcx.sess, sp, A0220, + "cannot resolve bound for closure: \ {}", - infer::fixup_err_to_str(e))); + infer::fixup_err_to_str(e)); } Ok(r1) => { // FIXME(eddyb) #2190 Allow only statically resolved @@ -155,7 +153,7 @@ fn resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId) Some(&ast::DefStaticMethod(..)) | Some(&ast::DefVariant(..)) | Some(&ast::DefStruct(_)) => {} - _ => tcx.sess.span_err(sp, + _ => span_err!(tcx.sess, sp, A0221, "cannot coerce non-statically resolved bare fn") } } @@ -179,11 +177,10 @@ fn resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId) Ok(r1) => r1, Err(e) => { // This should not, I think, happen. - tcx.sess.span_err( - sp, - format!("cannot resolve scope of borrow: \ + span_err!(tcx.sess, sp, A0222, + "cannot resolve scope of borrow: \ {}", - infer::fixup_err_to_str(e))); + infer::fixup_err_to_str(e)); r } } @@ -353,11 +350,10 @@ fn visit_local(l: &ast::Local, wbcx: &mut WbCtxt) { write_ty_to_tcx(wbcx.fcx.ccx.tcx, l.id, lty); } Err(e) => { - wbcx.fcx.ccx.tcx.sess.span_err( - l.span, - format!("cannot determine a type \ + span_err!(wbcx.fcx.ccx.tcx.sess, l.span, A0223, + "cannot determine a type \ for this local variable: {}", - infer::fixup_err_to_str(e))); + infer::fixup_err_to_str(e)); wbcx.success = false; } } diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index 27d52aade93e6..7fb7f5f179f35 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -68,9 +68,9 @@ fn get_base_type(inference_context: &InferCtxt, resolved_type = resulting_type; } _ => { - inference_context.tcx.sess.span_fatal(span, - "the type of this value must be known in order \ - to determine the base type"); + span_fatal!(inference_context.tcx.sess, span, A0047, + "the type of this value must be known in order \ + to determine the base type"); } } @@ -190,7 +190,7 @@ impl<'a> visit::Visitor<()> for PrivilegedScopeVisitor<'a> { if !self.cc.ast_type_is_defined_in_local_crate(ast_ty) { // This is an error. let session = self.cc.crate_context.tcx.sess; - session.span_err(item.span, + span_err!(session, item.span, A0104, "cannot associate methods with a type outside the \ crate the type is defined in; define and implement \ a trait or new type instead"); @@ -211,7 +211,7 @@ impl<'a> visit::Visitor<()> for PrivilegedScopeVisitor<'a> { if trait_def_id.crate != LOCAL_CRATE { let session = self.cc.crate_context.tcx.sess; - session.span_err(item.span, + span_err!(session, item.span, A0105, "cannot provide an extension implementation \ where both trait and type are not defined in this crate"); } @@ -276,7 +276,7 @@ impl CoherenceChecker { self_type.ty) { None => { let session = self.crate_context.tcx.sess; - session.span_err(item.span, + span_err!(session, item.span, A0106, "no base type found for inherent implementation; \ implement a trait or new type instead"); } @@ -448,11 +448,11 @@ impl CoherenceChecker { if self.polytypes_unify(polytype_a.clone(), polytype_b) { let session = self.crate_context.tcx.sess; - session.span_err( - self.span_of_impl(implementation_a), - format!("conflicting implementations for trait `{}`", + span_err!(session, + self.span_of_impl(implementation_a), A0107, + "conflicting implementations for trait `{}`", ty::item_path_str(self.crate_context.tcx, - trait_def_id))); + trait_def_id)); if implementation_b.did.crate == LOCAL_CRATE { session.span_note(self.span_of_impl(implementation_b), "note conflicting implementation here"); @@ -748,7 +748,7 @@ impl CoherenceChecker { { match tcx.items.find(impl_info.did.node) { Some(ast_map::NodeItem(item, _)) => { - tcx.sess.span_err((*item).span, + span_err!(tcx.sess, (*item).span, A0108, "the Drop trait may \ only be implemented \ on structures"); diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index 5e46daad7ee20..fb941858d2967 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -430,7 +430,7 @@ pub fn ensure_supertraits(ccx: &CrateCtxt, if ty_trait_refs.iter().any(|other_trait| other_trait.def_id == trait_ref.def_id) { // This means a trait inherited from the same supertrait more // than once. - tcx.sess.span_err(sp, "duplicate supertrait in trait declaration"); + span_err!(tcx.sess, sp, A0234, "duplicate supertrait in trait declaration"); break; } else { ty_trait_refs.push(trait_ref); @@ -543,10 +543,10 @@ pub fn ensure_no_ty_param_bounds(ccx: &CrateCtxt, thing: &'static str) { for ty_param in generics.ty_params.iter() { if ty_param.bounds.len() > 0 { - ccx.tcx.sess.span_err( - span, - format!("trait bounds are not allowed in {} definitions", - thing)); + span_err!(ccx.tcx.sess, + span, A0235, + "trait bounds are not allowed in {} definitions", + thing); } } } @@ -603,7 +603,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) { // Prevent the builtin kind traits from being manually implemented. if tcx.lang_items.to_builtin_kind(trait_ref.def_id).is_some() { - tcx.sess.span_err(it.span, + span_err!(tcx.sess, it.span, A0236, "cannot provide an explicit implementation \ for a builtin kind"); } @@ -755,11 +755,11 @@ pub fn instantiate_trait_ref(ccx: &CrateCtxt, return trait_ref; } _ => { - ccx.tcx.sess.span_fatal( - ast_trait_ref.path.span, - format!("{} is not a trait", + span_fatal!(ccx.tcx.sess, + ast_trait_ref.path.span, A0031, + "{} is not a trait", path_to_str(&ast_trait_ref.path, - ccx.tcx.sess.intr()))); + ccx.tcx.sess.intr())); } } } diff --git a/src/librustc/middle/typeck/infer/error_reporting.rs b/src/librustc/middle/typeck/infer/error_reporting.rs index 657b75a44ed30..129cc46951a5f 100644 --- a/src/librustc/middle/typeck/infer/error_reporting.rs +++ b/src/librustc/middle/typeck/infer/error_reporting.rs @@ -157,23 +157,51 @@ impl ErrorReporting for InferCtxt { } }; - let message_root_str = match trace.origin { - infer::Misc(_) => "mismatched types", - infer::MethodCompatCheck(_) => "method not compatible with trait", - infer::ExprAssignable(_) => "mismatched types", - infer::RelateTraitRefs(_) => "mismatched traits", - infer::RelateSelfType(_) => "mismatched types", - infer::MatchExpression(_) => "match arms have incompatible types", - infer::IfExpression(_) => "if and else have incompatible types", + match trace.origin { + infer::Misc(_) => { + span_err!(self.tcx.sess, trace.origin.span(), A0131, + "mismatched types: {} ({})", + expected_found_str, + ty::type_err_to_str(self.tcx, terr)); + } + infer::MethodCompatCheck(_) => { + span_err!(self.tcx.sess, trace.origin.span(), A0132, + "method not compatible with trait: {} ({})", + expected_found_str, + ty::type_err_to_str(self.tcx, terr)); + } + infer::ExprAssignable(_) => { + span_err!(self.tcx.sess, trace.origin.span(), A0133, + "mismatched types: {} ({})", + expected_found_str, + ty::type_err_to_str(self.tcx, terr)); + } + infer::RelateTraitRefs(_) => { + span_err!(self.tcx.sess, trace.origin.span(), A0134, + "mismatched traits: {} ({})", + expected_found_str, + ty::type_err_to_str(self.tcx, terr)); + } + infer::RelateSelfType(_) => { + span_err!(self.tcx.sess, trace.origin.span(), A0135, + "mismatched types: {} ({})", + expected_found_str, + ty::type_err_to_str(self.tcx, terr)); + } + infer::MatchExpression(_) => { + span_err!(self.tcx.sess, trace.origin.span(), A0136, + "match arms have incompatible types: {} ({})", + expected_found_str, + ty::type_err_to_str(self.tcx, terr)); + } + infer::IfExpression(_) => { + span_err!(self.tcx.sess, trace.origin.span(), A0137, + "if and else have incompatible types: {} ({})", + expected_found_str, + ty::type_err_to_str(self.tcx, terr)); + } }; - self.tcx.sess.span_err( - trace.origin.span(), - format!("{}: {} ({})", - message_root_str, - expected_found_str, - ty::type_err_to_str(self.tcx, terr))); - ty::note_and_explain_type_err(self.tcx, terr); } @@ -222,8 +250,8 @@ impl ErrorReporting for InferCtxt { self.report_and_explain_type_error(trace, &terr); } infer::Reborrow(span) => { - self.tcx.sess.span_err( - span, + span_err!(self.tcx.sess, + span, A0138, "lifetime of reference outlines \ lifetime of borrowed content..."); note_and_explain_region( @@ -238,8 +266,8 @@ impl ErrorReporting for InferCtxt { ""); } infer::InfStackClosure(span) => { - self.tcx.sess.span_err( - span, + span_err!(self.tcx.sess, + span, A0139, "closure outlives stack frame"); note_and_explain_region( self.tcx, @@ -253,8 +281,8 @@ impl ErrorReporting for InferCtxt { ""); } infer::InvokeClosure(span) => { - self.tcx.sess.span_err( - span, + span_err!(self.tcx.sess, + span, A0140, "cannot invoke closure outside of its lifetime"); note_and_explain_region( self.tcx, @@ -263,8 +291,8 @@ impl ErrorReporting for InferCtxt { ""); } infer::DerefPointer(span) => { - self.tcx.sess.span_err( - span, + span_err!(self.tcx.sess, + span, A0141, "dereference of reference outside its lifetime"); note_and_explain_region( self.tcx, @@ -273,8 +301,8 @@ impl ErrorReporting for InferCtxt { ""); } infer::FreeVariable(span) => { - self.tcx.sess.span_err( - span, + span_err!(self.tcx.sess, + span, A0142, "captured variable does not outlive the enclosing closure"); note_and_explain_region( self.tcx, @@ -288,9 +316,9 @@ impl ErrorReporting for InferCtxt { ""); } infer::IndexSlice(span) => { - self.tcx.sess.span_err( - span, - format!("index of slice outside its lifetime")); + span_err!(self.tcx.sess, + span, A0143, + "index of slice outside its lifetime"); note_and_explain_region( self.tcx, "the slice is only valid for ", @@ -298,8 +326,8 @@ impl ErrorReporting for InferCtxt { ""); } infer::RelateObjectBound(span) => { - self.tcx.sess.span_err( - span, + span_err!(self.tcx.sess, + span, A0144, "lifetime of the source pointer does not outlive \ lifetime bound of the object type"); note_and_explain_region( @@ -314,8 +342,8 @@ impl ErrorReporting for InferCtxt { ""); } infer::CallRcvr(span) => { - self.tcx.sess.span_err( - span, + span_err!(self.tcx.sess, + span, A0145, "lifetime of method receiver does not outlive \ the method call"); note_and_explain_region( @@ -325,8 +353,8 @@ impl ErrorReporting for InferCtxt { ""); } infer::CallArg(span) => { - self.tcx.sess.span_err( - span, + span_err!(self.tcx.sess, + span, A0146, "lifetime of function argument does not outlive \ the function call"); note_and_explain_region( @@ -336,8 +364,8 @@ impl ErrorReporting for InferCtxt { ""); } infer::CallReturn(span) => { - self.tcx.sess.span_err( - span, + span_err!(self.tcx.sess, + span, A0147, "lifetime of return value does not outlive \ the function call"); note_and_explain_region( @@ -347,8 +375,8 @@ impl ErrorReporting for InferCtxt { ""); } infer::AddrOf(span) => { - self.tcx.sess.span_err( - span, + span_err!(self.tcx.sess, + span, A0148, "reference is not valid \ at the time of borrow"); note_and_explain_region( @@ -358,8 +386,8 @@ impl ErrorReporting for InferCtxt { ""); } infer::AutoBorrow(span) => { - self.tcx.sess.span_err( - span, + span_err!(self.tcx.sess, + span, A0149, "automatically reference is not valid \ at the time of borrow"); note_and_explain_region( @@ -369,8 +397,8 @@ impl ErrorReporting for InferCtxt { ""); } infer::BindingTypeIsNotValidAtDecl(span) => { - self.tcx.sess.span_err( - span, + span_err!(self.tcx.sess, + span, A0150, "lifetime of variable does not enclose its declaration"); note_and_explain_region( self.tcx, @@ -379,8 +407,8 @@ impl ErrorReporting for InferCtxt { ""); } infer::ReferenceOutlivesReferent(ty, span) => { - self.tcx.sess.span_err( - span, + span_err!(self.tcx.sess, + span, A0151, format!("in type `{}`, pointer has a longer lifetime than \ the data it references", ty.user_string(self.tcx))); @@ -475,11 +503,11 @@ impl ErrorReportingHelpers for InferCtxt { } }; - self.tcx.sess.span_err( - var_origin.span(), - format!("cannot infer an appropriate lifetime{} \ + span_err!(self.tcx.sess, + var_origin.span(), A0152, + "cannot infer an appropriate lifetime{} \ due to conflicting requirements", - var_description)); + var_description); } fn note_region_origin(&self, origin: SubregionOrigin) { diff --git a/src/librustc/middle/typeck/infer/mod.rs b/src/librustc/middle/typeck/infer/mod.rs index 496170c3e47e0..83be9d218b1f6 100644 --- a/src/librustc/middle/typeck/infer/mod.rs +++ b/src/librustc/middle/typeck/infer/mod.rs @@ -754,11 +754,11 @@ impl InferCtxt { }); if !resolved_expected.map_or(false, |e| { ty::type_is_error(e) }) { match resolved_expected { - None => self.tcx.sess.span_err(sp, - format!("{}{}", mk_msg(None, actual_ty), error_str)), + None => span_err!(self.tcx.sess, sp, A0122, + "{}{}", mk_msg(None, actual_ty), error_str), Some(e) => { - self.tcx.sess.span_err(sp, - format!("{}{}", mk_msg(Some(self.ty_to_str(e)), actual_ty), error_str)); + span_err!(self.tcx.sess, sp, A0123, + "{}{}", mk_msg(Some(self.ty_to_str(e)), actual_ty), error_str); } } for err in err.iter() { diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs index b6ad8cc6c43b8..25fe5ef5ca0d5 100644 --- a/src/librustc/middle/typeck/mod.rs +++ b/src/librustc/middle/typeck/mod.rs @@ -259,7 +259,7 @@ pub fn lookup_def_tcx(tcx: ty::ctxt, sp: Span, id: ast::NodeId) -> ast::Def { match def_map.get().find(&id) { Some(&x) => x, _ => { - tcx.sess.span_fatal(sp, "internal error looking up a definition") + span_fatal!(tcx.sess, sp, A0037, "internal error looking up a definition") } } } @@ -298,8 +298,9 @@ pub fn require_same_types(tcx: ty::ctxt, match result { Ok(_) => true, Err(ref terr) => { - tcx.sess.span_err(span, msg() + ": " + - ty::type_err_to_str(tcx, terr)); + span_err!(tcx.sess, span, A0119, + "same types required: {}: {}", + msg(), ty::type_err_to_str(tcx, terr)); ty::note_and_explain_type_err(tcx, terr); false } @@ -342,8 +343,8 @@ fn check_main_fn_ty(ccx: &CrateCtxt, match it.node { ast::ItemFn(_, _, _, ref ps, _) if ps.is_parameterized() => { - tcx.sess.span_err( - main_span, + span_err!(tcx.sess, + main_span, A0120, "main function is not allowed to have type parameters"); return; } @@ -387,8 +388,8 @@ fn check_start_fn_ty(ccx: &CrateCtxt, match it.node { ast::ItemFn(_,_,_,ref ps,_) if ps.is_parameterized() => { - tcx.sess.span_err( - start_span, + span_err!(tcx.sess, + start_span, A0121, "start function is not allowed to have type parameters"); return; } diff --git a/src/librustc/middle/typeck/variance.rs b/src/librustc/middle/typeck/variance.rs index e29add4bc95c1..f6a54611a9da4 100644 --- a/src/librustc/middle/typeck/variance.rs +++ b/src/librustc/middle/typeck/variance.rs @@ -941,7 +941,8 @@ impl<'a> SolveContext<'a> { // attribute and report an error with various results if found. if ty::has_attr(tcx, item_def_id, "rustc_variance") { let found = item_variances.repr(tcx); - tcx.sess.span_err(ast_map::node_span(tcx.items, item_id), found); + span_err!(tcx.sess, ast_map::node_span(tcx.items, item_id), A0153, + "rustc_variance: {}", found); } let mut item_variance_map = tcx.item_variance_map.borrow_mut(); diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 78e9d3bd46f8c..672ea9996dcda 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -379,8 +379,8 @@ pub fn require_unique_names(diagnostic: @SpanHandler, metas: &[@MetaItem]) { let name = meta.name(); if !set.insert(name.clone()) { - diagnostic.span_fatal(meta.span, - format!("duplicate meta item `{}`", name)); + span_fatal!(diagnostic, meta.span, C0013, + "duplicate meta item `{}`", name) } } } @@ -413,8 +413,8 @@ pub fn find_repr_attr(diagnostic: @SpanHandler, attr: @ast::MetaItem, acc: ReprA Some(ity) => ReprInt(item.span, ity), None => { // Not a word we recognize - diagnostic.span_err(item.span, - "unrecognized representation hint"); + span_err!(diagnostic, item.span, C0014, + "unrecognized representation hint"); ReprAny } } @@ -423,13 +423,14 @@ pub fn find_repr_attr(diagnostic: @SpanHandler, attr: @ast::MetaItem, acc: ReprA if acc == ReprAny { acc = hint; } else if acc != hint { - diagnostic.span_warn(item.span, + span_warn!(diagnostic, item.span, C0085, "conflicting representation hint ignored") } } } // Not a word: - _ => diagnostic.span_err(item.span, "unrecognized representation hint") + _ => span_err!(diagnostic, item.span, C0015, + "unrecognized representation hint") } } } diff --git a/src/libsyntax/diag_index.rs b/src/libsyntax/diag_index.rs index e6c760257380c..0cc4f50850789 100644 --- a/src/libsyntax/diag_index.rs +++ b/src/libsyntax/diag_index.rs @@ -7,3 +7,206 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. + +//! The diagnostic registry +//! +//! All diagnostic codes must be registered here. To add a new +//! diagnostic code just go to the end of the file and add a new +//! line with a code that is one greater than the previous. + +all_diag!( + // B errors are used only by ext/ + + B0000, + B0001, + B0002, + B0003, + B0004, + B0005, + B0006, + B0007, + B0008, + B0009, + B0010, + B0011, + B0012, + B0013, + B0014, + B0015, + B0016, + B0017, + B0018, + B0019, + B0020, + B0021, + B0022, + B0023, + B0024, + B0025, + B0026, + B0027, + B0028, + B0029, + B0030, + B0031, + B0032, + B0033, + B0034, + B0035, + B0036, + B0037, + B0038, + B0039, + B0041, + B0042, + B0043, + B0044, + B0045, + B0046, + B0047, + B0048, + B0049, + B0050, + B0051, + B0052, + B0053, + B0054, + B0055, + B0056, + B0057, + B0058, + B0059, + B0060, + B0061, + B0062, + B0063, + B0064, + B0065, + B0066, + B0067, + B0068, + B0069, + B0070, + B0071, + B0072, + B0073, + B0074, + B0075, + B0076, + B0077, + B0078, + B0079, + B0080, + B0081, + B0082, + B0083, + B0084, + B0085, + B0086, + B0087, + B0088, + B0089, + B0090, + B0091, + B0092, + B0093, + B0094, + B0095, + B0096, + B0097, + B0098, + B0099, + B0100, + + // C errors are everything else + + C0000, + C0001, + C0002, + C0003, + C0004, + C0005, + C0006, + C0007, + C0008, + C0009, + C0010, + C0011, + C0012, + C0013, + C0014, + C0015, + C0016, + C0017, + C0018, + C0019, + C0020, + C0021, + C0022, + C0023, + C0024, + C0025, + C0026, + C0027, + C0028, + C0029, + C0030, + C0031, + C0032, + C0033, + C0034, + C0035, + C0036, + C0037, + C0038, + C0039, + C0040, + C0041, + C0042, + C0043, + C0044, + C0045, + C0046, + C0047, + C0048, + C0049, + C0050, + C0051, + C0052, + C0053, + C0054, + C0055, + C0056, + C0057, + C0058, + C0059, + C0060, + C0061, + C0062, + C0063, + C0064, + C0065, + C0066, + C0067, + C0068, + C0069, + C0070, + C0071, + C0072, + C0073, + C0074, + C0075, + C0076, + C0077, + C0078, + C0079, + C0080, + C0081, + C0082, + C0083, + C0084, + C0085, + C0086, + + LAST_DIAGNOSTIC // Just here to absorb the previous comma +) diff --git a/src/libsyntax/diag_macros.rs b/src/libsyntax/diag_macros.rs index 210dcfba0684b..d85c9a364cb61 100644 --- a/src/libsyntax/diag_macros.rs +++ b/src/libsyntax/diag_macros.rs @@ -37,6 +37,12 @@ macro_rules! reg_diag ( } ) +macro_rules! all_diag { + ($($name: tt),+) => { + $(reg_diag!($name))+ + } +} + #[cfg(not(stage0))] macro_rules! reg_diag_msg ( ($name: tt, $msg: tt) => { { @@ -59,23 +65,13 @@ macro_rules! report_diag ( ($f: expr, $name: tt, $msg: expr, $($arg: expr), *) => { { reg_diag_msg!($name, $msg); let msg: &str = format!($msg, $($arg), *); - $f(stringify!($name), msg); + let f: |&str, &str| -> () = $f; + f(stringify!($name), msg); } }; ($f: expr, $name: tt, $msg: expr) => { { reg_diag_msg!($name, $msg); - $f(stringify!($name), $msg); - } } -) - -macro_rules! report_diag_sp ( - ($f: expr, $sp: expr, $name: tt, $msg: expr, $($arg: expr), *) => { { - reg_diag_msg!($name, $msg); - let msg: &str = format!($msg, $($arg), *); - $f(sp, stringify!($name), msg); - } }; - ($f: expr, $sp: expr, $name: tt, $msg: expr) => { { - reg_diag_msg!($name, $msg); - $f(sp, stringify!($name), $msg); + let f: |&str, &str| -> () = $f; + f(stringify!($name), $msg); } } ) @@ -86,25 +82,27 @@ macro_rules! report_diag_sp ( /// /// This must be called (lexically) before a `desc_diag` on the same diagnostic code. macro_rules! alert_fatal ( - ($sess: expr, $name: tt, $msg: expr, $($arg: expr), *) => ( + ($sess: expr, $name: tt, $msg: expr, $($arg: expr), *) => ( { report_diag!(|c, m| $sess.fatal_with_diagnostic_code(c, m), $name, $msg, $($arg), *); - ); - ($sess: expr, $name: tt, $msg: expr) => ( + fail!() + } ); + ($sess: expr, $name: tt, $msg: expr) => ( { report_diag!(|c, m| $sess.fatal_with_diagnostic_code(c, m), $name, $msg); - ) + fail!() + } ) ) /// Raise a diagnostic at the 'error' level macro_rules! alert_err ( ($sess: expr, $name: tt, $msg: expr, $($arg: expr), *) => ( report_diag!(|c, m| $sess.err_with_diagnostic_code(c, m), - $name, $msg, $($arg), *); + $name, $msg, $($arg), *) ); ($sess: expr, $name: tt, $msg: expr) => ( report_diag!(|c, m| $sess.err_with_diagnostic_code(c, m), - $name, $msg); + $name, $msg) ) ) @@ -112,35 +110,37 @@ macro_rules! alert_err ( macro_rules! alert_warn ( ($sess: expr, $name: tt, $msg: expr, $($arg: expr), *) => ( report_diag!(|c, m| $sess.warn_with_diagnostic_code(c, m), - $name, $msg, $($arg), *); + $name, $msg, $($arg), *) ); ($sess: expr, $name: tt, $msg: expr) => ( report_diag!(|c, m| $sess.warn_with_diagnostic_code(c, m), - $name, $msg); + $name, $msg) ) ) /// Raise a diagnostic at the 'fatal' level macro_rules! span_fatal ( - ($sess: expr, $sp: expr, $name: tt, $msg: expr, $($arg: expr), *) => ( + ($sess: expr, $sp: expr, $name: tt, $msg: expr, $($arg: expr), *) => ( { report_diag!(|c, m| $sess.span_fatal_with_diagnostic_code($sp, c, m), $name, $msg, $($arg), *); - ); - ($sess: expr, $sp: expr, $name: tt, $msg: expr) => ( + fail!() + } ); + ($sess: expr, $sp: expr, $name: tt, $msg: expr) => ( { report_diag!(|c, m| $sess.span_fatal_with_diagnostic_code($sp, c, m), $name, $msg); - ) + fail!() + } ) ) /// Raise a diagnostic at the 'error' level macro_rules! span_err ( ($sess: expr, $sp: expr, $name: tt, $msg: expr, $($arg: expr), *) => ( report_diag!(|c, m| $sess.span_err_with_diagnostic_code($sp, c, m), - $name, $msg, $($arg), *); + $name, $msg, $($arg), *) ); ($sess: expr, $sp: expr, $name: tt, $msg: expr) => ( report_diag!(|c, m| $sess.span_err_with_diagnostic_code($sp, c, m), - $name, $msg); + $name, $msg) ) ) @@ -148,11 +148,11 @@ macro_rules! span_err ( macro_rules! span_warn ( ($sess: expr, $sp: expr, $name: tt, $msg: expr, $($arg: expr), *) => ( report_diag!(|c, m| $sess.span_warn_with_diagnostic_code($sp, c, m), - $name, $msg, $($arg), *); + $name, $msg, $($arg), *) ); ($sess: expr, $sp: expr, $name: tt, $msg: expr) => ( report_diag!(|c, m| $sess.span_warn_with_diagnostic_code($sp, c, m), - $name, $msg); + $name, $msg) ) ) diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index f4b0810546095..9dd5bd0a7c2a3 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -44,7 +44,7 @@ pub struct SpanHandler { } impl SpanHandler { - pub fn span_fatal(&self, sp: Span, msg: &str) -> ! { + pub fn span_fatal_without_diagnostic_code(&self, sp: Span, msg: &str) -> ! { self.handler.emit(Some((&*self.cm, sp)), msg, Fatal); fail!(FatalError); } @@ -52,7 +52,7 @@ impl SpanHandler { self.handler.emit_with_code(Some((&*self.cm, sp)), code, msg, Fatal); fail!(); } - pub fn span_err(&self, sp: Span, msg: &str) { + pub fn span_err_without_diagnostic_code(&self, sp: Span, msg: &str) { self.handler.emit(Some((&*self.cm, sp)), msg, Error); self.handler.bump_err_count(); } @@ -60,7 +60,7 @@ impl SpanHandler { self.handler.emit_with_code(Some((&*self.cm, sp)), code, msg, Error); self.handler.bump_err_count(); } - pub fn span_warn(&self, sp: Span, msg: &str) { + pub fn span_warn_without_diagnostic_code(&self, sp: Span, msg: &str) { self.handler.emit(Some((&*self.cm, sp)), msg, Warning); } pub fn span_warn_with_diagnostic_code(&self, sp: Span, code: &str, msg: &str) { @@ -73,7 +73,7 @@ impl SpanHandler { self.handler.custom_emit(&*self.cm, sp, msg, Note); } pub fn span_bug(&self, sp: Span, msg: &str) -> ! { - self.span_fatal(sp, ice_msg(msg)); + self.span_fatal_without_diagnostic_code(sp, ice_msg(msg)); } pub fn span_unimpl(&self, sp: Span, msg: &str) -> ! { self.span_bug(sp, ~"unimplemented " + msg); @@ -92,7 +92,7 @@ pub struct Handler { } impl Handler { - pub fn fatal(&self, msg: &str) -> ! { + pub fn fatal_without_diagnostic_code(&self, msg: &str) -> ! { self.emit(None, msg, Fatal); fail!(FatalError); } @@ -100,7 +100,7 @@ impl Handler { self.emit_with_code(None, code, msg, Fatal); fail!(FatalError); } - pub fn err(&self, msg: &str) { + pub fn err_without_diagnostic_code(&self, msg: &str) { self.emit(None, msg, Error); self.bump_err_count(); } @@ -127,9 +127,9 @@ impl Handler { self.err_count.get()); } } - self.fatal(s); + self.fatal_without_diagnostic_code(s); } - pub fn warn(&self, msg: &str) { + pub fn warn_without_diagnostic_code(&self, msg: &str) { self.emit(None, msg, Warning); } pub fn warn_with_diagnostic_code(&self, code: &str, msg: &str) { @@ -139,7 +139,7 @@ impl Handler { self.emit(None, msg, Note); } pub fn bug(&self, msg: &str) -> ! { - self.fatal(ice_msg(msg)); + self.fatal_without_diagnostic_code(ice_msg(msg)); } pub fn unimpl(&self, msg: &str) -> ! { self.bug(~"unimplemented " + msg); diff --git a/src/libsyntax/ext/asm.rs b/src/libsyntax/ext/asm.rs index 1a3ebf3ce5d1c..d820d25072418 100644 --- a/src/libsyntax/ext/asm.rs +++ b/src/libsyntax/ext/asm.rs @@ -84,7 +84,7 @@ pub fn expand_asm(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) cx.span_unimpl(p.last_span, "'+' (read+write) output operand constraint modifier"); } else if !constraint.get().starts_with("=") { - cx.span_err(p.last_span, "output operand constraint lacks '='"); + span_err!(cx, p.last_span, B0053, "output operand constraint lacks '='"); } p.expect(&token::LPAREN); @@ -106,9 +106,9 @@ pub fn expand_asm(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) let (constraint, _str_style) = p.parse_str(); if constraint.get().starts_with("=") { - cx.span_err(p.last_span, "input operand constraint contains '='"); + span_err!(cx, p.last_span, B0054, "input operand constraint contains '='"); } else if constraint.get().starts_with("+") { - cx.span_err(p.last_span, "input operand constraint contains '+'"); + span_err!(cx, p.last_span, B0055, "input operand constraint contains '+'"); } p.expect(&token::LPAREN); diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index c0660938f989e..33b9fe2236298 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -355,6 +355,7 @@ impl<'a> ExtCtxt<'a> { _ => self.bug("tried to pop without a push") } } + /// Emit `msg` attached to `sp`, and stop compilation immediately. /// /// `span_err` should be strongly prefered where-ever possible: @@ -366,23 +367,34 @@ impl<'a> ExtCtxt<'a> { /// in most cases one can construct a dummy expression/item to /// substitute; we never hit resolve/type-checking so the dummy /// value doesn't have to match anything) + pub fn span_fatal_with_diagnostic_code(&self, sp: Span, code: &str, msg: &str) -> ! { + self.print_backtrace(); + self.parse_sess.span_diagnostic.span_fatal_with_diagnostic_code(sp, code, msg); + } pub fn span_fatal(&self, sp: Span, msg: &str) -> ! { self.print_backtrace(); - self.parse_sess.span_diagnostic.span_fatal(sp, msg); + self.parse_sess.span_diagnostic.span_fatal_without_diagnostic_code(sp, msg); } - /// Emit `msg` attached to `sp`, without immediately stopping /// compilation. /// /// Compilation will be stopped in the near future (at the end of /// the macro expansion phase). + pub fn span_err_with_diagnostic_code(&self, sp: Span, code: &str, msg: &str) { + self.print_backtrace(); + self.parse_sess.span_diagnostic.span_err_with_diagnostic_code(sp, code, msg); + } pub fn span_err(&self, sp: Span, msg: &str) { self.print_backtrace(); - self.parse_sess.span_diagnostic.span_err(sp, msg); + self.parse_sess.span_diagnostic.span_err_without_diagnostic_code(sp, msg); + } + pub fn span_warn_with_diagnostic_code(&self, sp: Span, code: &str, msg: &str) { + self.print_backtrace(); + self.parse_sess.span_diagnostic.span_warn_with_diagnostic_code(sp, code, msg); } pub fn span_warn(&self, sp: Span, msg: &str) { self.print_backtrace(); - self.parse_sess.span_diagnostic.span_warn(sp, msg); + self.parse_sess.span_diagnostic.span_warn_without_diagnostic_code(sp, msg); } pub fn span_unimpl(&self, sp: Span, msg: &str) -> ! { self.print_backtrace(); @@ -416,13 +428,20 @@ impl<'a> ExtCtxt<'a> { /// merely emits a non-fatal error and returns None. pub fn expr_to_str(cx: &ExtCtxt, expr: @ast::Expr, err_msg: &str) -> Option<(InternedString, ast::StrStyle)> { + let err_span; match expr.node { ast::ExprLit(l) => match l.node { ast::LitStr(ref s, style) => return Some(((*s).clone(), style)), - _ => cx.span_err(l.span, err_msg) + _ => err_span = Some(l.span) }, - _ => cx.span_err(expr.span, err_msg) + _ => err_span = Some(expr.span) } + + match err_span { + Some(sp) => span_err!(cx, sp, B0018, "expr_to_str: {}", err_msg), + None => () + } + None } @@ -436,7 +455,7 @@ pub fn check_zero_tts(cx: &ExtCtxt, tts: &[ast::TokenTree], name: &str) { if tts.len() != 0 { - cx.span_err(sp, format!("{} takes no arguments", name)); + span_err!(cx, sp, B0019, "{} takes no arguments", name); } } @@ -448,7 +467,7 @@ pub fn get_single_str_from_tts(cx: &ExtCtxt, name: &str) -> Option<~str> { if tts.len() != 1 { - cx.span_err(sp, format!("{} takes 1 argument.", name)); + span_err!(cx, sp, B0020, "{} takes 1 argument.", name); } else { match tts[0] { ast::TTTok(_, token::LIT_STR(ident)) @@ -456,7 +475,7 @@ pub fn get_single_str_from_tts(cx: &ExtCtxt, let interned_str = token::get_ident(ident.name); return Some(interned_str.get().to_str()) } - _ => cx.span_err(sp, format!("{} requires a string.", name)), + _ => span_err!(cx, sp, B0043, "{} requires a string.", name), } } None @@ -473,7 +492,7 @@ pub fn get_exprs_from_tts(cx: &ExtCtxt, let mut es = ~[]; while p.token != token::EOF { if es.len() != 0 && !p.eat(&token::COMMA) { - cx.span_err(sp, "expected token: `,`"); + span_err!(cx, sp, B0022, "expected token: `,`"); return None; } es.push(p.parse_expr()); diff --git a/src/libsyntax/ext/bytes.rs b/src/libsyntax/ext/bytes.rs index 39bb870b969a0..18668935bd975 100644 --- a/src/libsyntax/ext/bytes.rs +++ b/src/libsyntax/ext/bytes.rs @@ -40,7 +40,7 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> // u8 literal, push to vector expression ast::LitUint(v, ast::TyU8) => { if v > 0xFF { - cx.span_err(expr.span, "too large u8 literal in bytes!") + span_err!(cx, expr.span, B0056, "too large u8 literal in bytes!") } else { bytes.push(cx.expr_u8(expr.span, v as u8)); } @@ -49,9 +49,9 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> // integer literal, push to vector expression ast::LitIntUnsuffixed(v) => { if v > 0xFF { - cx.span_err(expr.span, "too large integer literal in bytes!") + span_err!(cx, expr.span, B0057, "too large integer literal in bytes!") } else if v < 0 { - cx.span_err(expr.span, "negative integer literal in bytes!") + span_err!(cx, expr.span, B0058, "negative integer literal in bytes!") } else { bytes.push(cx.expr_u8(expr.span, v as u8)); } @@ -62,14 +62,14 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> if char::from_u32(v).unwrap().is_ascii() { bytes.push(cx.expr_u8(expr.span, v as u8)); } else { - cx.span_err(expr.span, "non-ascii char literal in bytes!") + span_err!(cx, expr.span, B0059, "non-ascii char literal in bytes!") } } - _ => cx.span_err(expr.span, "unsupported literal in bytes!") + _ => span_err!(cx, expr.span, B0060, "unsupported literal in bytes!") }, - _ => cx.span_err(expr.span, "non-literal in bytes!") + _ => span_err!(cx, expr.span, B0061, "non-literal in bytes!") } } diff --git a/src/libsyntax/ext/concat.rs b/src/libsyntax/ext/concat.rs index c13f9bf92af02..14b73f1ea40a4 100644 --- a/src/libsyntax/ext/concat.rs +++ b/src/libsyntax/ext/concat.rs @@ -48,12 +48,12 @@ pub fn expand_syntax_ext(cx: &mut base::ExtCtxt, accumulator.push_str(format!("{}", b)); } ast::LitBinary(..) => { - cx.span_err(e.span, "cannot concatenate a binary literal"); + span_err!(cx, e.span, B0066, "cannot concatenate a binary literal"); } } } _ => { - cx.span_err(e.span, "expected a literal"); + span_err!(cx, e.span, B0067, "expected a literal"); } } } diff --git a/src/libsyntax/ext/concat_idents.rs b/src/libsyntax/ext/concat_idents.rs index e0d53add6489f..da60cfbba3820 100644 --- a/src/libsyntax/ext/concat_idents.rs +++ b/src/libsyntax/ext/concat_idents.rs @@ -24,7 +24,7 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) match *e { ast::TTTok(_, token::COMMA) => (), _ => { - cx.span_err(sp, "concat_idents! expecting comma."); + span_err!(cx, sp, B0094, "concat_idents! expecting comma."); return MacResult::dummy_expr(); } } @@ -35,7 +35,7 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) res_str.push_str(interned_str.get()) } _ => { - cx.span_err(sp, "concat_idents! requires ident args."); + span_err!(cx, sp, B0095, "concat_idents! requires ident args."); return MacResult::dummy_expr(); } } diff --git a/src/libsyntax/ext/deriving/default.rs b/src/libsyntax/ext/deriving/default.rs index 7b87152b7115a..6cc9a99828cdf 100644 --- a/src/libsyntax/ext/deriving/default.rs +++ b/src/libsyntax/ext/deriving/default.rs @@ -69,7 +69,8 @@ fn default_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructur } } StaticEnum(..) => { - cx.span_err(trait_span, "`Default` cannot be derived for enums, only structs"); + span_err!(cx, trait_span, B0044, + "`Default` cannot be derived for enums, only structs"); // let compilation continue cx.expr_uint(trait_span, 0) } diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index 01e31fc5724d2..6d957007b0dad 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -52,11 +52,11 @@ pub fn expand_meta_deriving(cx: &mut ExtCtxt, -> ~[@Item] { match mitem.node { MetaNameValue(_, ref l) => { - cx.span_err(l.span, "unexpected value in `deriving`"); + span_err!(cx, l.span, B0046, "unexpected value in `deriving`"); in_items } MetaWord(_) | MetaList(_, []) => { - cx.span_warn(mitem.span, "empty trait list in `deriving`"); + span_warn!(cx, mitem.span, B0047, "empty trait list in `deriving`"); in_items } MetaList(_, ref titems) => { @@ -92,8 +92,9 @@ pub fn expand_meta_deriving(cx: &mut ExtCtxt, "FromPrimitive" => expand!(primitive::expand_deriving_from_primitive), ref tname => { - cx.span_err(titem.span, format!("unknown \ - `deriving` trait: `{}`", *tname)); + span_err!(cx, titem.span, B0048, + "unknown \ + `deriving` trait: `{}`", *tname); in_items } } diff --git a/src/libsyntax/ext/deriving/primitive.rs b/src/libsyntax/ext/deriving/primitive.rs index 1b356667b6b31..052c9f01102fb 100644 --- a/src/libsyntax/ext/deriving/primitive.rs +++ b/src/libsyntax/ext/deriving/primitive.rs @@ -72,12 +72,12 @@ fn cs_from(name: &str, cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure match *substr.fields { StaticStruct(..) => { - cx.span_err(trait_span, "`FromPrimitive` cannot be derived for structs"); + span_err!(cx, trait_span, B0049, "`FromPrimitive` cannot be derived for structs"); return cx.expr_fail(trait_span, InternedString::new("")); } StaticEnum(enum_def, _) => { if enum_def.variants.is_empty() { - cx.span_err(trait_span, + span_err!(cx, trait_span, B0050, "`FromPrimitive` cannot be derived for enums with no variants"); return cx.expr_fail(trait_span, InternedString::new("")); } @@ -88,7 +88,7 @@ fn cs_from(name: &str, cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure match variant.node.kind { ast::TupleVariantKind(ref args) => { if !args.is_empty() { - cx.span_err(trait_span, + span_err!(cx, trait_span, B0051, "`FromPrimitive` cannot be derived for \ enum variants with arguments"); return cx.expr_fail(trait_span, @@ -115,7 +115,7 @@ fn cs_from(name: &str, cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure arms.push(arm); } ast::StructVariantKind(_) => { - cx.span_err(trait_span, + span_err!(cx, trait_span, B0052, "`FromPrimitive` cannot be derived for enums \ with struct variants"); return cx.expr_fail(trait_span, diff --git a/src/libsyntax/ext/deriving/rand.rs b/src/libsyntax/ext/deriving/rand.rs index a40317286c960..f6d5a4a8d12d1 100644 --- a/src/libsyntax/ext/deriving/rand.rs +++ b/src/libsyntax/ext/deriving/rand.rs @@ -72,7 +72,8 @@ fn rand_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) } StaticEnum(_, ref variants) => { if variants.is_empty() { - cx.span_err(trait_span, "`Rand` cannot be derived for enums with no variants"); + span_err!(cx, trait_span, B0025, + "`Rand` cannot be derived for enums with no variants"); // let compilation continue return cx.expr_uint(trait_span, 0); } diff --git a/src/libsyntax/ext/deriving/zero.rs b/src/libsyntax/ext/deriving/zero.rs index ca5c1543d88dc..6990fc0f92ba9 100644 --- a/src/libsyntax/ext/deriving/zero.rs +++ b/src/libsyntax/ext/deriving/zero.rs @@ -85,7 +85,8 @@ fn zero_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) } } StaticEnum(..) => { - cx.span_err(trait_span, "`Zero` cannot be derived for enums, only structs"); + span_err!(cx, trait_span, B0045, + "`Zero` cannot be derived for enums, only structs"); // let compilation continue cx.expr_uint(trait_span, 0) } diff --git a/src/libsyntax/ext/env.rs b/src/libsyntax/ext/env.rs index c23a1ce1e28d5..225f8566800c6 100644 --- a/src/libsyntax/ext/env.rs +++ b/src/libsyntax/ext/env.rs @@ -41,7 +41,7 @@ pub fn expand_env(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> base::MacResult { let exprs = match get_exprs_from_tts(cx, sp, tts) { Some([]) => { - cx.span_err(sp, "env! takes 1 or 2 arguments"); + span_err!(cx, sp, B0063, "env! takes 1 or 2 arguments"); return MacResult::dummy_expr(); } None => return MacResult::dummy_expr(), @@ -65,14 +65,14 @@ pub fn expand_env(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) } } _ => { - cx.span_err(sp, "env! takes 1 or 2 arguments"); + span_err!(cx, sp, B0064, "env! takes 1 or 2 arguments"); return MacResult::dummy_expr(); } }; let e = match os::getenv(var.get()) { None => { - cx.span_err(sp, msg.get()); + span_err!(cx, sp, B0065, "env: {}", msg.get()); cx.expr_uint(sp, 0) } Some(s) => cx.expr_str(sp, token::intern_and_get_ident(s)) diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index cfad88e24820a..0ac84e52241ff 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -46,10 +46,9 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr { // Token-tree macros: MacInvocTT(ref pth, ref tts, _) => { if pth.segments.len() > 1u { - fld.cx.span_err( - pth.span, - format!("expected macro name without module \ - separators")); + span_err!(fld.cx, pth.span, B0029, + "expected macro name without module \ + separators"); // let compilation continue return e; } @@ -58,10 +57,10 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr { // leaving explicit deref here to highlight unbox op: let marked_after = match fld.extsbox.find(&extname.name) { None => { - fld.cx.span_err( - pth.span, - format!("macro undefined: '{}'", - extnamestr.get())); + span_err!(fld.cx, + pth.span, B0030, + "macro undefined: '{}'", + extnamestr.get()); // let compilation continue return e; @@ -91,13 +90,10 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr { MRExpr(e) => e, MRAny(any_macro) => any_macro.make_expr(), _ => { - fld.cx.span_err( - pth.span, - format!( - "non-expr macro in expr pos: {}", - extnamestr.get() - ) - ); + span_err!(fld.cx, + pth.span, B0031, + "non-expr macro in expr pos: {}", + extnamestr.get()); return e; } }; @@ -106,11 +102,10 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr { mark_expr(expanded,fm) } _ => { - fld.cx.span_err( - pth.span, - format!("'{}' is not a tt-style macro", - extnamestr.get()) - ); + span_err!(fld.cx, + pth.span, B0032, + "'{}' is not a tt-style macro", + extnamestr.get()); return e; } }; @@ -301,9 +296,9 @@ pub fn expand_item_mac(it: @ast::Item, fld: &mut MacroExpander) let fm = fresh_mark(); let expanded = match fld.extsbox.find(&extname.name) { None => { - fld.cx.span_err(pth.span, - format!("macro undefined: '{}!'", - extnamestr.get())); + span_err!(fld.cx, pth.span, B0033, + "macro undefined: '{}!'", + extnamestr.get()); // let compilation continue return SmallVector::zero(); } @@ -311,11 +306,11 @@ pub fn expand_item_mac(it: @ast::Item, fld: &mut MacroExpander) Some(&NormalTT(ref expander, span)) => { if it.ident.name != parse::token::special_idents::invalid.name { let string = token::get_ident(it.ident.name); - fld.cx.span_err(pth.span, - format!("macro {}! expects no ident argument, \ - given '{}'", - extnamestr.get(), - string.get())); + span_err!(fld.cx, pth.span, B0034, + "macro {}! expects no ident argument, \ + given '{}'", + extnamestr.get(), + string.get()); return SmallVector::zero(); } fld.cx.bt_push(ExpnInfo { @@ -332,9 +327,9 @@ pub fn expand_item_mac(it: @ast::Item, fld: &mut MacroExpander) } Some(&IdentTT(ref expander, span)) => { if it.ident.name == parse::token::special_idents::invalid.name { - fld.cx.span_err(pth.span, - format!("macro {}! expects an ident argument", - extnamestr.get())); + span_err!(fld.cx, pth.span, B0035, + "macro {}! expects an ident argument", + extnamestr.get()); return SmallVector::zero(); } fld.cx.bt_push(ExpnInfo { @@ -350,9 +345,9 @@ pub fn expand_item_mac(it: @ast::Item, fld: &mut MacroExpander) expander.expand(fld.cx, it.span, it.ident, marked_tts) } _ => { - fld.cx.span_err(it.span, - format!("{}! is not legal in item position", - extnamestr.get())); + span_err!(fld.cx, it.span, B0036, + "{}! is not legal in item position", + extnamestr.get()); return SmallVector::zero(); } }; @@ -364,9 +359,9 @@ pub fn expand_item_mac(it: @ast::Item, fld: &mut MacroExpander) .collect() } MRExpr(_) => { - fld.cx.span_err(pth.span, - format!("expr macro in item position: {}", - extnamestr.get())); + span_err!(fld.cx, pth.span, B0037, + "expr macro in item position: {}", + extnamestr.get()); return SmallVector::zero(); } MRAny(any_macro) => { @@ -447,14 +442,18 @@ fn load_extern_macros(crate: &ast::ViewItem, fld: &mut MacroExpander) { // this is fatal: there are almost certainly macros we need // inside this crate, so continue would spew "macro undefined" // errors - Err(err) => fld.cx.span_fatal(crate.span, err) + Err(err) => { + span_fatal!(fld.cx, crate.span, B0000, + "error opening crate for external macros: {}", err) + } }; unsafe { let registrar: MacroCrateRegistrationFun = match lib.symbol(registrar) { Ok(registrar) => registrar, // again fatal if we can't register macros - Err(err) => fld.cx.span_fatal(crate.span, err) + Err(err) => span_fatal!(fld.cx, crate.span, B0001, + "error finding registrar sybol: {}", err) }; registrar(|name, extension| { let extension = match extension { @@ -484,15 +483,17 @@ pub fn expand_stmt(s: &Stmt, fld: &mut MacroExpander) -> SmallVector<@Stmt> { _ => return expand_non_macro_stmt(s, fld) }; if pth.segments.len() > 1u { - fld.cx.span_err(pth.span, "expected macro name without module separators"); + span_err!(fld.cx, pth.span, B0038, + "expected macro name without module separators"); return SmallVector::zero(); } let extname = &pth.segments[0].identifier; let extnamestr = token::get_ident(extname.name); let marked_after = match fld.extsbox.find(&extname.name) { None => { - fld.cx.span_err(pth.span, format!("macro undefined: '{}'", - extnamestr.get())); + span_err!(fld.cx, pth.span, B0039, + "macro undefined: '{}'", + extnamestr.get()); return SmallVector::zero(); } @@ -524,9 +525,9 @@ pub fn expand_stmt(s: &Stmt, fld: &mut MacroExpander) -> SmallVector<@Stmt> { } MRAny(any_macro) => any_macro.make_stmt(), _ => { - fld.cx.span_err(pth.span, - format!("non-stmt macro in stmt pos: {}", - extnamestr.get())); + span_err!(fld.cx, pth.span, B0040, + "non-stmt macro in stmt pos: {}", + extnamestr.get()); return SmallVector::zero(); } }; @@ -535,8 +536,9 @@ pub fn expand_stmt(s: &Stmt, fld: &mut MacroExpander) -> SmallVector<@Stmt> { } _ => { - fld.cx.span_err(pth.span, format!("'{}' is not a tt-style macro", - extnamestr.get())); + span_err!(fld.cx, pth.span, B0041, + "'{}' is not a tt-style macro", + extnamestr.get()); return SmallVector::zero(); } }; @@ -544,7 +546,7 @@ pub fn expand_stmt(s: &Stmt, fld: &mut MacroExpander) -> SmallVector<@Stmt> { // Keep going, outside-in. let fully_expanded = fld.fold_stmt(marked_after); if fully_expanded.is_empty() { - fld.cx.span_err(pth.span, "macro didn't expand to a statement"); + span_err!(fld.cx, pth.span, B0042, "macro didn't expand to a statement"); return SmallVector::zero(); } fld.cx.bt_pop(); diff --git a/src/libsyntax/ext/fmt.rs b/src/libsyntax/ext/fmt.rs index 411bf921dd298..24bfa70e43ee2 100644 --- a/src/libsyntax/ext/fmt.rs +++ b/src/libsyntax/ext/fmt.rs @@ -17,7 +17,7 @@ use ext::build::AstBuilder; pub fn expand_syntax_ext(ecx: &mut base::ExtCtxt, sp: Span, _tts: &[ast::TokenTree]) -> base::MacResult { - ecx.span_err(sp, "`fmt!` is deprecated, use `format!` instead"); + span_err!(ecx, sp, B0062, "`fmt!` is deprecated, use `format!` instead"); ecx.parse_sess.span_diagnostic.span_note(sp, "see http://static.rust-lang.org/doc/master/std/fmt/index.html \ for documentation"); diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs index 4bc3b804c7ff7..18395c5d9a5a5 100644 --- a/src/libsyntax/ext/format.rs +++ b/src/libsyntax/ext/format.rs @@ -141,7 +141,7 @@ impl<'a> Context<'a> { parse::String(..) => {} parse::CurrentArgument => { if self.nest_level == 0 { - self.ecx.span_err(self.fmtsp, + span_err!(self.ecx, self.fmtsp, B0077, "`#` reference used with nothing to \ reference back to"); } @@ -204,8 +204,9 @@ impl<'a> Context<'a> { fn check_positional_ok(&mut self) -> bool { if self.nest_level != 0 { - self.ecx.span_err(self.fmtsp, "cannot use implicit positional \ - arguments nested inside methods"); + span_err!(self.ecx, self.fmtsp, B0078, + "cannot use implicit positional \ + arguments nested inside methods"); false } else { true @@ -222,14 +223,14 @@ impl<'a> Context<'a> { if !seen_cases.insert(arm.selector) { match arm.selector { parse::Keyword(name) => { - self.ecx.span_err(self.fmtsp, - format!("duplicate selector \ - `{:?}`", name)); + span_err!(self.ecx, self.fmtsp, B0079, + "duplicate selector \ + `{:?}`", name); } parse::Literal(idx) => { - self.ecx.span_err(self.fmtsp, - format!("duplicate selector \ - `={}`", idx)); + span_err!(self.ecx, self.fmtsp, B0080, + "duplicate selector \ + `={}`", idx); } } } @@ -242,11 +243,11 @@ impl<'a> Context<'a> { let mut seen_cases = HashSet::new(); for arm in arms.iter() { if !seen_cases.insert(arm.selector) { - self.ecx.span_err(self.fmtsp, - format!("duplicate selector `{}`", - arm.selector)); + span_err!(self.ecx, self.fmtsp, B0081, + "duplicate selector `{}`", + arm.selector); } else if arm.selector == "" { - self.ecx.span_err(self.fmtsp, + span_err!(self.ecx, self.fmtsp, B0082, "empty selector in `select`"); } self.verify_pieces(arm.result); @@ -261,9 +262,9 @@ impl<'a> Context<'a> { match arg { Exact(arg) => { if arg < 0 || self.args.len() <= arg { - let msg = format!("invalid reference to argument `{}` (there \ - are {} arguments)", arg, self.args.len()); - self.ecx.span_err(self.fmtsp, msg); + span_err!(self.ecx, self.fmtsp, B0083, + "invalid reference to argument `{}` (there \ + are {} arguments)", arg, self.args.len()); return; } { @@ -282,8 +283,8 @@ impl<'a> Context<'a> { let span = match self.names.find(&name) { Some(e) => e.span, None => { - let msg = format!("there is no argument named `{}`", name); - self.ecx.span_err(self.fmtsp, msg); + span_err!(self.ecx, self.fmtsp, B0084, + "there is no argument named `{}`", name); return; } }; @@ -322,26 +323,26 @@ impl<'a> Context<'a> { } match (cur, ty) { (&Known(ref cur), &Known(ref ty)) => { - self.ecx.span_err(sp, - format!("argument redeclared with type `{}` when \ + span_err!(self.ecx, sp, B0085, + "argument redeclared with type `{}` when \ it was previously `{}`", *ty, - *cur)); + *cur); } (&Known(ref cur), _) => { - self.ecx.span_err(sp, - format!("argument used to format with `{}` was \ + span_err!(self.ecx, sp, B0086, + "argument used to format with `{}` was \ attempted to not be used for formatting", - *cur)); + *cur); } (_, &Known(ref ty)) => { - self.ecx.span_err(sp, - format!("argument previously used as a format \ + span_err!(self.ecx, sp, B0087, + "argument previously used as a format \ argument attempted to be used as `{}`", - *ty)); + *ty); } (_, _) => { - self.ecx.span_err(sp, "argument declared with multiple formats"); + span_err!(self.ecx, sp, B0088, "argument declared with multiple formats"); } } } @@ -726,8 +727,9 @@ impl<'a> Context<'a> { "x" => "secret_lower_hex", "X" => "secret_upper_hex", _ => { - self.ecx.span_err(sp, format!("unknown format trait `{}`", - *tyname)); + span_err!(self.ecx, sp, B0089, + "unknown format trait `{}`", + *tyname); "dummy" } } @@ -827,12 +829,12 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span, // Make sure that all arguments were used and all arguments have types. for (i, ty) in cx.arg_types.iter().enumerate() { if ty.is_none() { - cx.ecx.span_err(cx.args[i].span, "argument never used"); + span_err!(cx.ecx, cx.args[i].span, B0092, "argument never used"); } } for (name, e) in cx.names.iter() { if !cx.name_types.contains_key(name) { - cx.ecx.span_err(e.span, "named argument never used"); + span_err!(cx.ecx, e.span, B0093, "named argument never used"); } } diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index e98322099040e..55890c42788e4 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -589,7 +589,7 @@ fn expand_tts(cx: &ExtCtxt, sp: Span, tts: &[ast::TokenTree]) let cx_expr = p.parse_expr(); if !p.eat(&token::COMMA) { - p.fatal("expected token `,`"); + alert_fatal!(p, C0082, "expected token `,`"); } let tts = p.parse_all_token_trees(); diff --git a/src/libsyntax/ext/registrar.rs b/src/libsyntax/ext/registrar.rs index e831e8fbb10d9..f97a1e9690f75 100644 --- a/src/libsyntax/ext/registrar.rs +++ b/src/libsyntax/ext/registrar.rs @@ -49,7 +49,8 @@ pub fn find_macro_registrar(diagnostic: @diagnostic::SpanHandler, }) }, _ => { - diagnostic.handler().err("multiple macro registration functions found"); + alert_err!(diagnostic.handler(), B0100, + "multiple macro registration functions found"); for &(_, span) in ctx.registrars.iter() { diagnostic.span_note(span, "one is here"); } diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs index 52010b39a5446..668861f366798 100644 --- a/src/libsyntax/ext/source_util.rs +++ b/src/libsyntax/ext/source_util.rs @@ -110,7 +110,7 @@ pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) let file = res_rel_file(cx, sp, &Path::new(file)); let bytes = match File::open(&file).read_to_end() { Err(e) => { - cx.span_err(sp, format!("couldn't read {}: {}", file.display(), e)); + span_err!(cx, sp, B0068, "couldn't read {}: {}", file.display(), e); return MacResult::dummy_expr(); } Ok(bytes) => bytes, @@ -126,7 +126,7 @@ pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) base::MRExpr(cx.expr_str(sp, interned)) } None => { - cx.span_err(sp, format!("{} wasn't a utf-8 file", file.display())); + span_err!(cx, sp, B0069, "{} wasn't a utf-8 file", file.display()); return MacResult::dummy_expr(); } } @@ -142,7 +142,7 @@ pub fn expand_include_bin(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) let file = res_rel_file(cx, sp, &Path::new(file)); match File::open(&file).read_to_end() { Err(e) => { - cx.span_err(sp, format!("couldn't read {}: {}", file.display(), e)); + span_err!(cx, sp, B0070, "couldn't read {}: {}", file.display(), e); return MacResult::dummy_expr(); } Ok(bytes) => { diff --git a/src/libsyntax/ext/trace_macros.rs b/src/libsyntax/ext/trace_macros.rs index 4189ea6a967a8..1f47568c774da 100644 --- a/src/libsyntax/ext/trace_macros.rs +++ b/src/libsyntax/ext/trace_macros.rs @@ -32,7 +32,7 @@ pub fn expand_trace_macros(cx: &mut ExtCtxt, } else if rust_parser.is_keyword(keywords::False) { cx.set_trace_macros(false); } else { - cx.span_err(sp, "trace_macros! only accepts `true` or `false`"); + span_err!(cx, sp, B0023, "trace_macros! only accepts `true` or `false`"); return base::MacResult::dummy_expr(); } diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index 92bc204e2c18c..a75c4039077a3 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -184,8 +184,8 @@ pub fn nameize(p_s: @ParseSess, ms: &[Matcher], res: &[@NamedMatch]) } => { if ret_val.contains_key(bind_name) { let string = token::get_ident(bind_name.name); - p_s.span_diagnostic - .span_fatal(sp, "duplicated bind name: " + string.get()) + span_fatal!(p_s.span_diagnostic, sp, B0017, + "duplicated bind name: {}", string.get()) } ret_val.insert(*bind_name, res[idx]); } @@ -202,18 +202,6 @@ pub enum ParseResult { Error(codemap::Span, ~str) } -pub fn parse_or_else(sess: @ParseSess, - cfg: ast::CrateConfig, - rdr: R, - ms: ~[Matcher]) - -> HashMap { - match parse(sess, cfg, rdr, ms) { - Success(m) => m, - Failure(sp, str) => sess.span_diagnostic.span_fatal(sp, str), - Error(sp, str) => sess.span_diagnostic.span_fatal(sp, str) - } -} - // perform a token equality check, ignoring syntax context (that is, an unhygienic comparison) pub fn token_name_eq(t1 : &Token, t2 : &Token) -> bool { match (t1,t2) { @@ -415,7 +403,7 @@ pub fn parse_nt(p: &mut Parser, name: &str) -> Nonterminal { match name { "item" => match p.parse_item(~[]) { Some(i) => token::NtItem(i), - None => p.fatal("expected an item keyword") + None => alert_fatal!(p, C0079, "expected an item keyword") }, "block" => token::NtBlock(p.parse_block()), "stmt" => token::NtStmt(p.parse_stmt(~[])), @@ -427,7 +415,7 @@ pub fn parse_nt(p: &mut Parser, name: &str) -> Nonterminal { token::IDENT(sn,b) => { p.bump(); token::NtIdent(~sn,b) } _ => { let token_str = token::to_str(get_ident_interner(), &p.token); - p.fatal(~"expected ident, found " + token_str) + alert_fatal!(p, C0080, "expected ident, found {}", token_str) } }, "path" => { @@ -441,6 +429,6 @@ pub fn parse_nt(p: &mut Parser, name: &str) -> Nonterminal { res } "matchers" => token::NtMatchers(p.parse_matchers()), - _ => p.fatal(~"unsupported builtin nonterminal parser: " + name) + _ => alert_fatal!(p, C0081, "unsupported builtin nonterminal parser: {}", name) } } diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index e196bdccfe34b..08e84e93d8223 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -17,8 +17,8 @@ use ext::base::{NormalTT, MacroExpander}; use ext::base; use ext::tt::macro_parser::{Success, Error, Failure}; use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal}; -use ext::tt::macro_parser::{parse, parse_or_else}; -use parse::lexer::new_tt_reader; +use ext::tt::macro_parser::{parse}; +use parse::lexer::{new_tt_reader, Reader}; use parse::parser::Parser; use parse::attr::ParserAttr; use parse::token::{get_ident_interner, special_idents, gensym_ident}; @@ -26,6 +26,7 @@ use parse::token::{FAT_ARROW, SEMI, NtMatchers, NtTT, EOF}; use parse::token; use print; use std::cell::RefCell; +use std::hashmap::HashMap; use util::small_vector::SmallVector; struct ParserAnyMacro { @@ -46,11 +47,10 @@ impl ParserAnyMacro { } if parser.get().token != EOF { let token_str = parser.get().this_token_to_str(); - let msg = format!("macro expansion ignores token `{}` and any \ - following", - token_str); let span = parser.get().span; - parser.get().span_err(span, msg); + span_err!(parser.get(), span, B0024, + "macro expansion ignores token `{}` and any following", + token_str); } } } @@ -122,7 +122,7 @@ fn generic_extension(cx: &ExtCtxt, // Which arm's failure should we report? (the one furthest along) let mut best_fail_spot = DUMMY_SP; - let mut best_fail_msg = ~"internal error: ran no matchers"; + let mut best_fail_msg = ~"ran no matchers"; let s_d = cx.parse_sess().span_diagnostic; @@ -141,8 +141,8 @@ fn generic_extension(cx: &ExtCtxt, TTDelim(ref tts) => { (*tts).slice(1u,(*tts).len()-1u).to_owned() } - _ => cx.span_fatal( - sp, "macro rhs must be delimited") + _ => span_fatal!(cx, sp, B0007, + "macro rhs must be delimited") } }, _ => cx.span_bug(sp, "bad thing in rhs") @@ -161,13 +161,33 @@ fn generic_extension(cx: &ExtCtxt, best_fail_spot = sp; best_fail_msg = (*msg).clone(); }, - Error(sp, ref msg) => cx.span_fatal(sp, (*msg)) + Error(sp, ref msg) => raise_macro_parse_err(cx, sp, *msg) } } _ => cx.bug("non-matcher found in parsed lhses") } } - cx.span_fatal(best_fail_spot, best_fail_msg); + raise_macro_parse_failure(cx, best_fail_spot, best_fail_msg); +} + +pub fn parse_or_else(cx: &ExtCtxt, + cfg: ast::CrateConfig, + rdr: R, + ms: &[Matcher]) + -> HashMap { + match parse(cx.parse_sess(), cfg, rdr, ms) { + Success(m) => m, + Failure(sp, str) => raise_macro_parse_failure(cx, sp, str), + Error(sp, str) => raise_macro_parse_err(cx, sp, str) + } +} + +pub fn raise_macro_parse_err(cx: &ExtCtxt, sp: Span, msg: &str) -> ! { + span_fatal!(cx, sp, B0008, "error parsing macro: {}", msg) +} + +pub fn raise_macro_parse_failure(cx: &ExtCtxt, sp: Span, msg: &str) -> ! { + span_fatal!(cx, sp, B0009, "macro parse failed: {}", msg) } // this procedure performs the expansion of the @@ -208,7 +228,7 @@ pub fn add_new_extension(cx: &mut ExtCtxt, let arg_reader = new_tt_reader(cx.parse_sess().span_diagnostic, None, arg.clone()); - let argument_map = parse_or_else(cx.parse_sess(), + let argument_map = parse_or_else(cx, cx.cfg(), arg_reader, argument_gram); diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index fccbc57f12c0f..42ffa7e2114a7 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -123,9 +123,9 @@ fn lookup_cur_matched(r: &TtReader, name: Ident) -> @NamedMatch { Some(s) => lookup_cur_matched_by_matched(r, s), None => { let name_string = token::get_ident(name.name); - r.sp_diag.span_fatal(r.cur_span.get(), - format!("unknown macro variable `{}`", - name_string.get())); + span_fatal!(r.sp_diag, r.cur_span.get(), B0010, + "unknown macro variable `{}`", + name_string.get()); } } } @@ -255,23 +255,23 @@ pub fn tt_next_token(r: &TtReader) -> TokenAndSpan { let t = TTSeq(sp, tts, sep.clone(), zerok); match lockstep_iter_size(&t, r) { LisUnconstrained => { - r.sp_diag.span_fatal( - sp, /* blame macro writer */ - "attempted to repeat an expression \ - containing no syntax \ - variables matched as repeating at this depth"); + span_fatal!(r.sp_diag, sp, B0011, + /* blame macro writer */ + "attempted to repeat an expression \ + containing no syntax \ + variables matched as repeating at this depth") } LisContradiction(ref msg) => { /* FIXME #2887 blame macro invoker instead*/ - r.sp_diag.span_fatal(sp, (*msg)); + span_fatal!(r.sp_diag, sp, B0012, + "list contradiction: {}", (*msg)) } LisConstraint(len, _) => { if len == 0 { if !zerok { - r.sp_diag.span_fatal(sp, /* FIXME #2887 blame invoker - */ - "this must repeat at least \ - once"); + /* FIXME #2887 blame invokerb */ + span_fatal!(r.sp_diag, sp, B0013, + "this must repeat at least once") } r.stack.get().idx.set(r.stack.get().idx.get() + 1u); @@ -315,10 +315,11 @@ pub fn tt_next_token(r: &TtReader) -> TokenAndSpan { } MatchedSeq(..) => { let string = token::get_ident(ident.name); - r.sp_diag.span_fatal( + span_fatal!(r.sp_diag, r.cur_span.get(), /* blame the macro writer */ - format!("variable '{}' is still repeating at this depth", - string.get())); + B0014, + "variable '{}' is still repeating at this depth", + string.get()); } } } diff --git a/src/libsyntax/ext/tt_map.rs b/src/libsyntax/ext/tt_map.rs index fff0f376481bf..07736b34f7b4c 100644 --- a/src/libsyntax/ext/tt_map.rs +++ b/src/libsyntax/ext/tt_map.rs @@ -32,14 +32,14 @@ pub fn insert_expr(ecx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> MacResult { if tts.len() != 5 { - ecx.span_fatal(sp, "incorrect number of arguments"); + span_fatal!(ecx, sp, B0002, "incorrect number of arguments") } let idxs = [1, 3]; for i in idxs.iter() { match &tts[*i] { &ast::TTTok(_, token::COMMA) => (), - _ => ecx.span_fatal(sp, "expecting comma") + _ => span_fatal!(ecx, sp, B0003, "expecting comma") } } @@ -60,7 +60,7 @@ pub fn insert_expr(ecx: &mut ExtCtxt, sp: Span, if existed { let key_ident = get_ident(key_name); let key_name = key_ident.get(); - ecx.span_fatal(sp, format!("key {} already exists in map", key_name)); + span_fatal!(ecx, sp, B0004, "key {} already exists in map", key_name); } // This item isn't used @@ -73,12 +73,12 @@ pub fn get_expr(ecx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> MacResult { if tts.len() != 3 { - ecx.span_fatal(sp, "incorrect number of arguments"); + span_fatal!(ecx, sp, B0005, "incorrect number of arguments") } match &tts[1] { &ast::TTTok(_, token::COMMA) => (), - _ => ecx.span_fatal(sp, "expecting comma") + _ => span_fatal!(ecx, sp, B0006, "expecting comma") } let map_name = tree_2_name(ecx, &tts[0]); @@ -93,12 +93,12 @@ pub fn get_expr(ecx: &mut ExtCtxt, sp: Span, None => { let key_ident = get_ident(key_name); let key_name = key_ident.get(); - ecx.span_fatal(sp, format!("key {} does not exist in map", key_name)); + span_fatal!(ecx, sp, B0015, "key {} does not exist in map", key_name); } } } None => { - ecx.span_fatal(sp, "map does not exist"); + span_fatal!(ecx, sp, B0016, "map does not exist") } } } diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index c9bea78d02db5..1ed1396af31ea 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -50,7 +50,7 @@ impl ParserAttr for Parser { self.span.hi ); if attr.node.style != ast::AttrOuter { - self.fatal("expected outer comment"); + alert_fatal!(self, C0076, "expected outer comment"); } attrs.push(attr); self.bump(); @@ -85,8 +85,8 @@ impl ParserAttr for Parser { } _ => { let token_str = self.this_token_to_str(); - self.fatal(format!("expected `\\#` but found `{}`", - token_str)); + alert_fatal!(self, C0078, "expected `\\#` but found `{}`", + token_str) } }; let style = if permit_inner && self.token == token::SEMI { @@ -167,8 +167,7 @@ impl ParserAttr for Parser { match lit.node { ast::LitStr(..) => {} _ => { - self.span_err( - lit.span, + span_err!(self, lit.span, C0017, "non-string literals are not allowed in meta-items"); } } diff --git a/src/libsyntax/parse/comments.rs b/src/libsyntax/parse/comments.rs index 138f9d7164067..45f531c0148c0 100644 --- a/src/libsyntax/parse/comments.rs +++ b/src/libsyntax/parse/comments.rs @@ -279,7 +279,7 @@ fn read_block_comment(rdr: &StringReader, while level > 0 { debug!("=== block comment level {}", level); if is_eof(rdr) { - rdr.fatal(~"unterminated block comment"); + alert_fatal!(rdr, C0075, "unterminated block comment"); } if rdr.curr_is('\n') { trim_whitespace_prefix_and_push_line(&mut lines, curr_line, diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs index f6ebfbfcc3b2e..21cca7f19f5ea 100644 --- a/src/libsyntax/parse/lexer.rs +++ b/src/libsyntax/parse/lexer.rs @@ -26,7 +26,7 @@ pub use ext::tt::transcribe::{TtReader, new_tt_reader}; pub trait Reader { fn is_eof(&self) -> bool; fn next_token(&self) -> TokenAndSpan; - fn fatal(&self, ~str) -> !; + fn fatal_with_diagnostic_code(&self, code: &str, msg: &str) -> !; fn span_diag(&self) -> @SpanHandler; fn peek(&self) -> TokenAndSpan; fn dup(&self) -> ~Reader:; @@ -119,8 +119,8 @@ impl Reader for StringReader { string_advance_token(self); ret_val } - fn fatal(&self, m: ~str) -> ! { - self.span_diagnostic.span_fatal(self.peek_span.get(), m) + fn fatal_with_diagnostic_code(&self, code: &str, msg: &str) -> ! { + self.span_diagnostic.span_fatal_with_diagnostic_code(self.peek_span.get(), code, msg) } fn span_diag(&self) -> @SpanHandler { self.span_diagnostic } fn peek(&self) -> TokenAndSpan { @@ -143,8 +143,8 @@ impl Reader for TtReader { debug!("TtReader: r={:?}", r); return r; } - fn fatal(&self, m: ~str) -> ! { - self.sp_diag.span_fatal(self.cur_span.get(), m); + fn fatal_with_diagnostic_code(&self, code: &str, msg: &str) -> ! { + self.sp_diag.span_fatal_with_diagnostic_code(self.cur_span.get(), code, msg); } fn span_diag(&self) -> @SpanHandler { self.sp_diag } fn peek(&self) -> TokenAndSpan { @@ -163,7 +163,7 @@ fn fatal_span(rdr: &StringReader, m: ~str) -> ! { rdr.peek_span.set(codemap::mk_sp(from_pos, to_pos)); - rdr.fatal(m); + alert_fatal!(rdr, C0074, "lexical error: {}", m); } // report a lexical error spanning [`from_pos`, `to_pos`), appending an diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 6ddb4bbc11fb7..0ee39aee84160 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -227,8 +227,10 @@ pub fn file_to_filemap(sess: @ParseSess, path: &Path, spanopt: Option) -> @FileMap { let err = |msg: &str| { match spanopt { - Some(sp) => sess.span_diagnostic.span_fatal(sp, msg), - None => sess.span_diagnostic.handler().fatal(msg), + Some(sp) => span_fatal!(sess.span_diagnostic, sp, C0012, + "error creating file map: {}", msg), + None => alert_fatal!(sess.span_diagnostic.handler(), C0086, + "error creating file map: {}", msg), } }; let bytes = match File::open(path).read_to_end() { diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index 091fbf82b0d5b..08f866d523cf3 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -176,7 +176,7 @@ impl ParserObsoleteMethods for Parser { kind: ObsoleteSyntax, kind_str: &str, desc: &str) { - self.span_err(sp, format!("obsolete syntax: {}", kind_str)); + span_err!(self, sp, C0016, "obsolete syntax: {}", kind_str); if !self.obsolete_set.contains(&kind) { self.sess.span_diagnostic.handler().note(format!("{}", desc)); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index fd8b945a177ff..c9396f7d88b6d 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -369,13 +369,13 @@ impl Parser { pub fn unexpected_last(&mut self, t: &token::Token) -> ! { let token_str = Parser::token_to_str(t); - self.span_fatal(self.last_span, format!("unexpected token: `{}`", - token_str)); + span_fatal!(self, self.last_span, B0096, + "unexpected token: `{}`", token_str) } pub fn unexpected(&mut self) -> ! { let this_token = self.this_token_to_str(); - self.fatal(format!("unexpected token: `{}`", this_token)); + alert_fatal!(self, C0040, "unexpected token: `{}`", this_token) } // expect and consume the token t. Signal an error if @@ -386,9 +386,10 @@ impl Parser { } else { let token_str = Parser::token_to_str(t); let this_token_str = self.this_token_to_str(); - self.fatal(format!("expected `{}` but found `{}`", - token_str, - this_token_str)) + alert_fatal!(self, C0041, + "expected `{}` but found `{}`", + token_str, + this_token_str) } } @@ -412,13 +413,13 @@ impl Parser { let expected = vec::append(edible.to_owned(), inedible); let expect = tokens_to_str(expected); let actual = self.this_token_to_str(); - self.fatal( - if expected.len() != 1 { - format!("expected one of `{}` but found `{}`", expect, actual) - } else { - format!("expected `{}` but found `{}`", expect, actual) - } - ) + if expected.len() != 1 { + alert_fatal!(self, C0042, + "expected one of `{}` but found `{}`", expect, actual) + } else { + alert_fatal!(self, C0043, + "expected `{}` but found `{}`", expect, actual) + } } } @@ -430,7 +431,7 @@ impl Parser { && expected.iter().all(|t| *t != token::LBRACE) && self.look_ahead(1, |t| *t == token::RBRACE) { // matched; signal non-fatal error and recover. - self.span_err(self.span, + span_err!(self, self.span, C0018, "unit-like struct construction is written with no trailing `{ }`"); self.eat(&token::LBRACE); self.eat(&token::RBRACE); @@ -490,7 +491,7 @@ impl Parser { } _ => { let token_str = self.this_token_to_str(); - self.fatal(format!( "expected ident, found `{}`", token_str)) + alert_fatal!(self, C0044, "expected ident, found `{}`", token_str) } } } @@ -534,9 +535,9 @@ impl Parser { let id_ident = kw.to_ident(); let id_interned_str = token::get_ident(id_ident.name); let token_str = self.this_token_to_str(); - self.fatal(format!("expected `{}`, found `{}`", + alert_fatal!(self, C0045, "expected `{}`, found `{}`", id_interned_str.get(), - token_str)) + token_str) } } @@ -544,8 +545,8 @@ impl Parser { pub fn check_strict_keywords(&mut self) { if token::is_strict_keyword(&self.token) { let token_str = self.this_token_to_str(); - self.span_err(self.span, - format!("found `{}` in ident position", token_str)); + span_err!(self, self.span, C0019, + "found `{}` in ident position", token_str); } } @@ -553,7 +554,7 @@ impl Parser { pub fn check_reserved_keywords(&mut self) { if token::is_reserved_keyword(&self.token) { let token_str = self.this_token_to_str(); - self.fatal(format!("`{}` is a reserved keyword", token_str)) + alert_fatal!(self, C0073, "`{}` is a reserved keyword", token_str) } } @@ -570,9 +571,10 @@ impl Parser { let token_str = self.this_token_to_str(); let found_token = Parser::token_to_str(&token::BINOP(token::OR)); - self.fatal(format!("expected `{}`, found `{}`", - found_token, - token_str)) + alert_fatal!(self, C0046, + "expected `{}`, found `{}`", + found_token, + token_str) } } } @@ -611,9 +613,9 @@ impl Parser { _ => { let gt_str = Parser::token_to_str(&token::GT); let this_token_str = self.this_token_to_str(); - self.fatal(format!("expected `{}`, found `{}`", + alert_fatal!(self, C0047, "expected `{}`, found `{}`", gt_str, - this_token_str)) + this_token_str) } } } @@ -781,11 +783,11 @@ impl Parser { } f(&self.buffer[(self.buffer_start + dist - 1) & 3].tok) } - pub fn fatal(&mut self, m: &str) -> ! { - self.sess.span_diagnostic.span_fatal(self.span, m) + pub fn fatal_with_diagnostic_code(&mut self, code: &str, m: &str) -> ! { + self.sess.span_diagnostic.span_fatal_with_diagnostic_code(self.span, code, m) } - pub fn span_fatal(&mut self, sp: Span, m: &str) -> ! { - self.sess.span_diagnostic.span_fatal(sp, m) + pub fn span_fatal_with_diagnostic_code(&mut self, sp: Span, code: &str, m: &str) -> ! { + self.sess.span_diagnostic.span_fatal_with_diagnostic_code(sp, code, m) } pub fn span_note(&mut self, sp: Span, m: &str) { self.sess.span_diagnostic.span_note(sp, m) @@ -793,11 +795,11 @@ impl Parser { pub fn bug(&mut self, m: &str) -> ! { self.sess.span_diagnostic.span_bug(self.span, m) } - pub fn warn(&mut self, m: &str) { - self.sess.span_diagnostic.span_warn(self.span, m) + pub fn span_warn_with_diagnostic_code(&mut self, code: &str, m: &str) { + self.sess.span_diagnostic.span_warn_with_diagnostic_code(self.span, code, m) } - pub fn span_err(&mut self, sp: Span, m: &str) { - self.sess.span_diagnostic.span_err(sp, m) + pub fn span_err_with_diagnostic_code(&mut self, sp: Span, code: &str, msg: &str) { + self.sess.span_diagnostic.span_err_with_diagnostic_code(sp, code, msg); } pub fn abort_if_errors(&mut self) { self.sess.span_diagnostic.handler().abort_if_errors(); @@ -937,7 +939,7 @@ impl Parser { // Re-parse the region here. What a hack. if region.is_some() { - self.span_err(self.last_span, + span_err!(self, self.last_span, C0020, "lifetime declarations must precede \ the lifetime associated with a \ closure"); @@ -1100,8 +1102,8 @@ impl Parser { _ => { let token_str = p.this_token_to_str(); - p.fatal(format!("expected `;` or `\\{` but found `{}`", - token_str)) + alert_fatal!(p, C0048, "expected `;` or `\\{` but found `{}`", + token_str) } } }) @@ -1262,8 +1264,7 @@ impl Parser { } = self.parse_path(LifetimeAndTypesAndBounds); TyPath(path, bounds, ast::DUMMY_NODE_ID) } else { - let msg = format!("expected type, found token {:?}", self.token); - self.fatal(msg); + alert_fatal!(self, C0049, "expected type, found token {:?}", self.token) }; let sp = mk_sp(lo, self.last_span.hi); @@ -1553,7 +1554,7 @@ impl Parser { if bound_set.is_some() { if i != last_segment_index { - self.span_err(span, + span_err!(self, span, C0021, "type parameter bounds are allowed only \ before the last segment in a path") } @@ -1601,7 +1602,7 @@ impl Parser { }; } _ => { - self.fatal(format!("expected a lifetime name")); + alert_fatal!(self, C0050, "expected a lifetime name"); } } } @@ -1634,10 +1635,10 @@ impl Parser { token::GT => { return res; } token::BINOP(token::SHR) => { return res; } _ => { - let msg = format!("expected `,` or `>` after lifetime \ - name, got: {:?}", - self.token); - self.fatal(msg); + alert_fatal!(self, C0051, + "expected `,` or `>` after lifetime \ + name, got: {:?}", + self.token) } } } @@ -1815,7 +1816,7 @@ impl Parser { } else if self.eat_keyword(keywords::Loop) { return self.parse_loop_expr(Some(lifetime)) } else { - self.fatal("expected `for` or `loop` after a label") + alert_fatal!(self, C0052, "expected `for` or `loop` after a label") } } else if self.eat_keyword(keywords::Loop) { return self.parse_loop_expr(None); @@ -1903,7 +1904,7 @@ impl Parser { self.bump(); match self.token { token::LPAREN | token::LBRACE => {} - _ => self.fatal("expected open delimiter") + _ => alert_fatal!(self, C0053, "expected open delimiter") }; let ket = token::flip_delimiter(&self.token); @@ -2064,7 +2065,7 @@ impl Parser { let separator = self.bump_and_get(); match parse_zerok(self) { Some(zerok) => (Some(separator), zerok), - None => self.fatal("expected `*` or `+`") + None => alert_fatal!(self, C0054, "expected `*` or `+`") } } @@ -2094,8 +2095,8 @@ impl Parser { Some(&sp) => p.span_note(sp, "unclosed delimiter"), }; let token_str = p.this_token_to_str(); - p.fatal(format!("incorrect close delimiter: `{}`", - token_str)) + alert_fatal!(p, C0055, "incorrect close delimiter: `{}`", + token_str) }, /* we ought to allow different depths of unquotation */ token::DOLLAR if p.quote_depth > 0u => { @@ -2133,11 +2134,12 @@ impl Parser { token::EOF => { let open_braces = self.open_braces.clone(); for sp in open_braces.iter() { + // FIXME: lower case error msgs self.span_note(*sp, "Did you mean to close this delimiter?"); } // There shouldn't really be a span, but it's easier for the test runner // if we give it one - self.fatal("this file contains an un-closed delimiter "); + alert_fatal!(self, C0056, "this file contains an un-closed delimiter "); } token::LPAREN | token::LBRACE | token::LBRACKET => { let close_delim = token::flip_delimiter(&self.token); @@ -2183,7 +2185,7 @@ impl Parser { self.bump(); self.parse_matcher_subseq_upto(name_idx, &other_delimiter) } - _ => self.fatal("expected open delimiter") + _ => alert_fatal!(self, C0057, "expected open delimiter") } } @@ -2219,7 +2221,7 @@ impl Parser { let ms = self.parse_matcher_subseq_upto(name_idx, &token::RPAREN); if ms.len() == 0u { - self.fatal("repetition body must be nonempty"); + alert_fatal!(self, C0058, "repetition body must be nonempty") } let (sep, zerok) = self.parse_sep_and_zerok(); MatchSeq(ms, sep, zerok, name_idx_lo, name_idx.get()) @@ -2572,7 +2574,7 @@ impl Parser { } else { // This is an obsolete 'continue' expression if opt_ident.is_some() { - self.span_err(self.last_span, + span_err!(self, self.last_span, C0022, "a label may not be used with a `loop` expression"); } @@ -2715,8 +2717,8 @@ impl Parser { ast::Pat { node: PatIdent(_, _, _), .. } => { slice = Some(subpat); } - ast::Pat { span, .. } => self.span_fatal( - span, "expected an identifier or nothing" + ast::Pat { span, .. } => span_fatal!(self, span, B0097, + "expected an identifier or nothing" ) } } @@ -2755,8 +2757,8 @@ impl Parser { self.bump(); if self.token != token::RBRACE { let token_str = self.this_token_to_str(); - self.fatal(format!("expected `\\}`, found `{}`", - token_str)) + alert_fatal!(self, C0059, "expected `\\}`, found `{}`", + token_str) } etc = true; break; @@ -2780,7 +2782,7 @@ impl Parser { match bind_type { BindByRef(..) | BindByValue(MutMutable) => { let token_str = self.this_token_to_str(); - self.fatal(format!("unexpected `{}`", token_str)) + alert_fatal!(self, C0060, "unexpected `{}`", token_str) } _ => {} } @@ -3069,8 +3071,8 @@ impl Parser { binding_mode: ast::BindingMode) -> ast::Pat_ { if !is_plain_ident(&self.token) { - self.span_fatal(self.last_span, - "expected identifier, found path"); + span_fatal!(self, self.last_span, B0098, + "expected identifier, found path") } // why a path here, and not just an identifier? let name = self.parse_path(NoTypesAllowed).path; @@ -3087,9 +3089,9 @@ impl Parser { // binding mode then we do not end up here, because the lookahead // will direct us over to parse_enum_variant() if self.token == token::LPAREN { - self.span_fatal( - self.last_span, - "expected identifier, found enum pattern"); + span_fatal!(self, + self.last_span, B0099, + "expected identifier, found enum pattern") } PatIdent(binding_mode, name, sub) @@ -3132,7 +3134,7 @@ impl Parser { attrs: ~[Attribute]) -> StructField { let lo = self.span.lo; if !is_plain_ident(&self.token) { - self.fatal("expected ident"); + alert_fatal!(self, C0061, "expected ident") } let name = self.parse_ident(); self.expect(&token::COLON); @@ -3153,7 +3155,7 @@ impl Parser { fn check_expected_item(p: &mut Parser, found_attrs: bool) { // If we have attributes then we should have an item if found_attrs { - p.span_err(p.last_span, "expected item after attributes"); + span_err!(p, p.last_span, C0023, "expected item after attributes"); } } @@ -3223,11 +3225,11 @@ impl Parser { return @spanned(lo, hi, StmtDecl(decl, ast::DUMMY_NODE_ID)); } IoviViewItem(vi) => { - self.span_fatal(vi.span, - "view items must be declared at the top of the block"); + span_fatal!(self, vi.span, C0011, + "view items must be declared at the top of the block") } IoviForeignItem(_) => { - self.fatal("foreign items are not allowed here"); + alert_fatal!(self, C0062, "foreign items are not allowed here") } IoviNone(_) => { /* fallthrough */ } } @@ -3313,7 +3315,8 @@ impl Parser { match self.token { token::SEMI => { if !attributes_box.is_empty() { - self.span_err(self.last_span, "expected item after attributes"); + span_err!(self, self.last_span, C0024, + "expected item after attributes"); attributes_box = ~[]; } self.bump(); // empty @@ -3391,7 +3394,8 @@ impl Parser { } if !attributes_box.is_empty() { - self.span_err(self.last_span, "expected item after attributes"); + span_err!(self, self.last_span, C0025, + "expected item after attributes"); } let hi = self.span.hi; @@ -3427,7 +3431,7 @@ impl Parser { if lifetime_interned_string.equiv(&("static")) { result.push(RegionTyParamBound); } else { - self.span_err(self.span, + span_err!(self, self.span, C0026, "`'static` is the only permissible region bound here"); } self.bump(); @@ -3481,7 +3485,7 @@ impl Parser { if ty_param.default.is_some() { seen_default = true; } else if seen_default { - p.span_err(p.last_span, + span_err!(p, p.last_span, C0084, "type parameters with a default must be trailing"); } ty_param @@ -3513,12 +3517,12 @@ impl Parser { p.bump(); if allow_variadic { if p.token != token::RPAREN { - p.span_fatal(p.span, - "`...` must be last in argument list for variadic function"); + span_fatal!(p, p.span, C0001, + "`...` must be last in argument list for variadic function") } } else { - p.span_fatal(p.span, - "only foreign functions are allowed to be variadic"); + span_fatal!(p, p.span, C0002, + "only foreign functions are allowed to be variadic") } None } else { @@ -3538,7 +3542,7 @@ impl Parser { }; if variadic && args.is_empty() { - self.span_err(sp, + span_err!(self, sp, C0027, "variadic function must be declared with at least one named argument"); } @@ -3571,7 +3575,7 @@ impl Parser { fn expect_self_ident(&mut self) { if !self.is_self_ident() { let token_str = self.this_token_to_str(); - self.fatal(format!("expected `self` but found `{}`", token_str)) + alert_fatal!(self, C0063, "expected `self` but found `{}`", token_str) } self.bump(); } @@ -3659,7 +3663,8 @@ impl Parser { self.parse_mutability() } else { MutImmutable }; if self.is_self_ident() { - self.span_err(self.span, "cannot pass self by unsafe pointer"); + span_err!(self, self.span, C0038, + "cannot pass self by unsafe pointer"); self.bump(); } SelfValue @@ -3702,8 +3707,8 @@ impl Parser { } _ => { let token_str = self.this_token_to_str(); - self.fatal(format!("expected `,` or `)`, found `{}`", - token_str)) + alert_fatal!(self, C0064, "expected `,` or `)`, found `{}`", + token_str) } } } else { @@ -3895,12 +3900,12 @@ impl Parser { }) } TyPath(..) => { - self.span_err(ty.span, - "bounded traits are only valid in type position"); + span_err!(self, ty.span, C0028, + "bounded traits are only valid in type position"); None } _ => { - self.span_err(ty.span, "not a trait"); + span_err!(self, ty.span, C0029, "not a trait"); None } }; @@ -3957,8 +3962,9 @@ impl Parser { } if fields.len() == 0 { let string = get_ident_interner().get(class_name.name); - self.fatal(format!("unit-like struct definition should be written as `struct {};`", - string.as_slice())); + alert_fatal!(self, C0065, + "unit-like struct definition should be written as `struct {};`", + string.as_slice()); } self.bump(); } else if self.token == token::LPAREN { @@ -3986,9 +3992,10 @@ impl Parser { fields = ~[]; } else { let token_str = self.this_token_to_str(); - self.fatal(format!("expected `\\{`, `(`, or `;` after struct \ - name but found `{}`", - token_str)) + alert_fatal!(self, C0066, + "expected `\\{`, `(`, or `;` after struct \ + name but found `{}`", + token_str) } let _ = ast::DUMMY_NODE_ID; // FIXME: Workaround for crazy bug. @@ -4014,9 +4021,9 @@ impl Parser { token::RBRACE => {} _ => { let token_str = self.this_token_to_str(); - self.span_fatal(self.span, - format!("expected `,`, or `\\}` but found `{}`", - token_str)) + span_fatal!(self, self.span, C0003, + "expected `,`, or `\\}` but found `{}`", + token_str) } } a_var @@ -4077,21 +4084,22 @@ impl Parser { true /* macros allowed */) { IoviItem(item) => items.push(item), IoviViewItem(view_item) => { - self.span_fatal(view_item.span, + span_fatal!(self, view_item.span, C0004, "view items must be declared at the top of \ - the module"); + the module") } _ => { let token_str = self.this_token_to_str(); - self.fatal(format!("expected item but found `{}`", - token_str)) + alert_fatal!(self, C0067, + "expected item but found `{}`", + token_str) } } } if first && attrs_remaining_len > 0u { // We parsed attributes for the first item but didn't find it - self.span_err(self.last_span, "expected item after attributes"); + span_err!(self, self.last_span, C0030, "expected item after attributes"); } ast::Mod { view_items: view_items, items: items } @@ -4168,12 +4176,13 @@ impl Parser { (true, false) => default_path, (false, true) => secondary_path, (false, false) => { - self.span_fatal(id_sp, format!("file not found for module `{}`", mod_name)); + span_fatal!(self, id_sp, C0005, + "file not found for module `{}`", mod_name) } (true, true) => { - self.span_fatal(id_sp, - format!("file for module `{}` found at both {} and {}", - mod_name, default_path_str, secondary_path_str)); + span_fatal!(self, id_sp, C0006, + "file for module `{}` found at both {} and {}", + mod_name, default_path_str, secondary_path_str) } } } @@ -4197,14 +4206,14 @@ impl Parser { .position(|p| *p == path); match maybe_i { Some(i) => { - let mut err = ~"circular modules: "; + let mut err = ~""; let len = included_mod_stack.get().len(); for p in included_mod_stack.get().slice(i, len).iter() { err.push_str(p.display().as_maybe_owned().as_slice()); err.push_str(" -> "); } err.push_str(path.display().as_maybe_owned().as_slice()); - self.span_fatal(id_sp, err); + span_fatal!(self, id_sp, C0039, "circular modules: {}", err); } None => () } @@ -4297,7 +4306,7 @@ impl Parser { foreign_items: foreign_items } = self.parse_foreign_items(first_item_attrs, true); if ! attrs_remaining.is_empty() { - self.span_err(self.last_span, + span_err!(self, self.last_span, C0031, "expected item after attributes"); } assert!(self.token == token::RBRACE); @@ -4322,9 +4331,9 @@ impl Parser { self.expect_keyword(keywords::Mod); } else if self.token != token::LBRACE { let token_str = self.this_token_to_str(); - self.span_fatal(self.span, - format!("expected `\\{` or `mod` but found `{}`", - token_str)) + span_fatal!(self, self.span, C0007, + "expected `\\{` or `mod` but found `{}`", + token_str) } let (named, maybe_path, ident) = match self.token { @@ -4340,10 +4349,10 @@ impl Parser { _ => { if must_be_named_mod { let token_str = self.this_token_to_str(); - self.span_fatal(self.span, - format!("expected foreign module name but \ - found `{}`", - token_str)) + span_fatal!(self, self.span, C0008, + "expected foreign module name but \ + found `{}`", + token_str) } (false, None, @@ -4374,7 +4383,7 @@ impl Parser { } if opt_abis.is_some() { - self.span_err(self.span, "an ABI may not be specified here"); + span_err!(self, self.span, C0032, "an ABI may not be specified here"); } @@ -4477,8 +4486,9 @@ impl Parser { } self.expect(&token::RBRACE); if have_disr && !all_nullary { - self.fatal("discriminator values can only be used with a c-like \ - enum"); + alert_fatal!(self, C0068, + "discriminator values can only be used with a c-like \ + enum") } ast::EnumDef { variants: variants } @@ -4519,23 +4529,23 @@ impl Parser { match abi::lookup(word) { Some(abi) => { if abis.contains(abi) { - self.span_err( - self.span, - format!("ABI `{}` appears twice", - word)); + span_err!(self, + self.span, C0033, + "ABI `{}` appears twice", + word); } else { abis.add(abi); } } None => { - self.span_err( - self.span, - format!("illegal ABI: \ + span_err!(self, + self.span, C0034, + "illegal ABI: \ expected one of [{}], \ found `{}`", - abi::all_names().connect(", "), - word)); + abi::all_names().connect(", "), + word); } } } @@ -4776,7 +4786,7 @@ impl Parser { seq_sep_none(), |p| p.parse_token_tree()) } - _ => self.fatal("expected open delimiter") + _ => alert_fatal!(self, C0069, "expected open delimiter") }; // single-variant-enum... : let m = ast::MacInvocTT(pth, tts, EMPTY_CTXT); @@ -4795,14 +4805,14 @@ impl Parser { // FAILURE TO PARSE ITEM if visibility != Inherited { - let mut s = ~"unmatched visibility `"; + let mut s = ~"`"; if visibility == Public { s.push_str("pub") } else { s.push_str("priv") } s.push_char('`'); - self.span_fatal(self.last_span, s); + span_fatal!(self, self.last_span, C0009, "unmatched visibility {}", s) } return IoviNone(attrs); } @@ -4811,9 +4821,9 @@ impl Parser { match self.parse_item_or_view_item(attrs, true) { IoviNone(_) => None, IoviViewItem(_) => - self.fatal("view items are not allowed here"), + alert_fatal!(self, C0070, "view items are not allowed here"), IoviForeignItem(_) => - self.fatal("foreign items are not allowed here"), + alert_fatal!(self, C0071, "foreign items are not allowed here"), IoviItem(item) => Some(item) } } @@ -4998,7 +5008,7 @@ impl Parser { extern_mod_allowed = false; } ViewItemExternMod(..) if !extern_mod_allowed => { - self.span_err(view_item.span, + span_err!(self, view_item.span, C0035, "\"extern mod\" declarations are not allowed here"); } ViewItemExternMod(..) => {} @@ -5026,7 +5036,7 @@ impl Parser { } IoviViewItem(view_item) => { attrs = self.parse_outer_attributes(); - self.span_err(view_item.span, + span_err!(self, view_item.span, C0036, "`use` and `extern mod` declarations must precede items"); } IoviItem(item) => { @@ -5066,12 +5076,13 @@ impl Parser { }, IoviViewItem(view_item) => { // I think this can't occur: - self.span_err(view_item.span, + span_err!(self, view_item.span, C0037, "`use` and `extern mod` declarations must precede items"); } IoviItem(item) => { // FIXME #5668: this will occur for a macro invocation: - self.span_fatal(item.span, "macros cannot expand to foreign items"); + span_fatal!(self, item.span, C0010, + "macros cannot expand to foreign items") } IoviForeignItem(foreign_item) => { foreign_items.push(foreign_item); @@ -5123,7 +5134,7 @@ impl Parser { pub fn parse_str(&mut self) -> (InternedString, StrStyle) { match self.parse_optional_str() { Some(s) => { s } - _ => self.fatal("expected string literal") + _ => alert_fatal!(self, C0072, "expected string literal") } } } From d9c7a8c6e4d8c36ebc47829024acb3188d9dc91d Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sat, 11 Jan 2014 20:48:32 -0800 Subject: [PATCH 5/7] rustc: Add UI for extended diagnostics When diagnostics with codes are emitted they appear in magenta brackets, like `[A0002]`. After failure a note is emitted indicating whether any errors had extended documentation and suggesting the `--explain help` flag. --- src/librustc/diag_db.md | 6 +- src/librustc/diag_db.rs | 10 ++- src/librustc/driver/driver.rs | 9 ++- src/librustc/lib.rs | 20 +++++- src/librustc/middle/astencode.rs | 3 +- src/librustc/middle/typeck/infer/test.rs | 3 +- src/librustdoc/core.rs | 5 +- src/librustdoc/test.rs | 9 +-- src/libsyntax/diag_db.rs | 37 ++++++++++- src/libsyntax/diagnostic.rs | 79 ++++++++++++++++++------ src/libsyntax/ext/expand.rs | 7 ++- src/libsyntax/parse/lexer.rs | 4 +- src/libsyntax/parse/mod.rs | 5 +- src/libsyntax/util/parser_testing.rs | 5 +- 14 files changed, 159 insertions(+), 43 deletions(-) diff --git a/src/librustc/diag_db.md b/src/librustc/diag_db.md index 36c13b6da5271..16afe333b0f96 100644 --- a/src/librustc/diag_db.md +++ b/src/librustc/diag_db.md @@ -1 +1,5 @@ -("", "", "") /* placeholder */ \ No newline at end of file +desc_diag!(A0003, " + +Your borrowed pointer doesn't live long enough, dude. + +"), \ No newline at end of file diff --git a/src/librustc/diag_db.rs b/src/librustc/diag_db.rs index 03b73661849d5..a3c20178c74ae 100644 --- a/src/librustc/diag_db.rs +++ b/src/librustc/diag_db.rs @@ -14,6 +14,14 @@ //! diag_db.md file and can be loaded at runtime with the `load` //! function. -pub fn load() -> ~[(&'static str, &'static str, &'static str)] { +use syntax::diag_db::DiagnosticDb; + +/// Load the database of extended diagnostic descriptions +pub fn load() -> DiagnosticDb { + DiagnosticDb::new(~[load_raw, ::syntax::diag_db::load_raw]) +} + +pub fn load_raw() -> ~[(&'static str, &'static str, &'static str)] { ~[include!("diag_db.md")] } + diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 99974f74fcebf..0fdf658e0082e 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -11,6 +11,7 @@ use back::link; use back::{arm, x86, x86_64, mips}; +use diag_db; use driver::session::{Aggressive, CrateTypeExecutable}; use driver::session::{Session, Session_, No, Less, Default}; use driver::session; @@ -140,7 +141,7 @@ pub fn build_configuration(sess: Session) -> fn parse_cfgspecs(cfgspecs: ~[~str]) -> ast::CrateConfig { cfgspecs.move_iter().map(|s| { - let sess = parse::new_parse_sess(); + let sess = parse::new_parse_sess(diag_db::load()); parse::parse_meta_from_source_str("cfgspec".to_str(), s, ~[], sess) }).collect::() } @@ -925,7 +926,7 @@ pub fn build_session(sopts: @session::Options, -> Session { let codemap = @codemap::CodeMap::new(); let diagnostic_handler = - diagnostic::mk_handler(); + diagnostic::mk_handler(diag_db::load()); let span_diagnostic_handler = diagnostic::mk_span_handler(diagnostic_handler, codemap); @@ -1032,6 +1033,8 @@ pub fn optgroups() -> ~[getopts::OptGroup] { in ", "DIR"), optflag("", "parse-only", "Parse only; do not compile, assemble, or link"), + optopt("", "explain", + "Provide a detailed explanation of an error message", "ERRCODE"), optflagopt("", "pretty", "Pretty-print the input instead of compiling; valid types are: normal (un-annotated source), @@ -1161,7 +1164,7 @@ pub fn build_output_filenames(input: &Input, } pub fn early_error(msg: &str) -> ! { - diagnostic::DefaultEmitter.emit(None, msg, diagnostic::Fatal); + diagnostic::DefaultEmitter.emit(None, msg, diagnostic::Fatal, None); fail!(diagnostic::FatalError); } diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 43d7d20d0ebef..9cff3515f5658 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -57,6 +57,7 @@ use syntax::attr; use syntax::diagnostic::Emitter; use syntax::diagnostic; use syntax::parse; +use syntax::diag_db::{explain_diagnostic, explain_diag_help}; // Define the diagnostic macros #[path = "../libsyntax/diag_macros.rs"] @@ -221,6 +222,21 @@ pub fn run_compiler(args: &[~str]) { return; } + match matches.opt_str("explain") { + Some(ref code) if code == &~"help" => { + explain_diag_help(); + return; + }, + Some(code) => { + if !explain_diagnostic(&diag_db::load(), code) { + d::early_error(format!("no extended information about code {}", code)); + } + return; + } + None => () + } + + // Display the available lint options if "-W help" or only "-W" is given. let lint_flags = vec::append(matches.opt_strs("W"), matches.opt_strs("warn")); if lint_flags.iter().any(|x| x == &~"help") { @@ -379,7 +395,7 @@ pub fn monitor(f: proc()) { diagnostic::DefaultEmitter.emit( None, diagnostic::ice_msg("unexpected failure"), - diagnostic::Error); + diagnostic::Error, None); let xs = [ ~"the compiler hit an unexpected failure path. \ @@ -388,7 +404,7 @@ pub fn monitor(f: proc()) { for note in xs.iter() { diagnostic::DefaultEmitter.emit(None, *note, - diagnostic::Note) + diagnostic::Note, None) } println!("{}", r.read_to_str()); diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index d59ec370e07b5..96f283689b6f5 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -1444,7 +1444,8 @@ impl fake_ext_ctxt for @parse::ParseSess { #[cfg(test)] fn mk_ctxt() -> @parse::ParseSess { - parse::new_parse_sess() + use diag_db; + parse::new_parse_sess(diag_db::load()) } #[cfg(test)] diff --git a/src/librustc/middle/typeck/infer/test.rs b/src/librustc/middle/typeck/infer/test.rs index 517fe232b0345..06cae2385d4da 100644 --- a/src/librustc/middle/typeck/infer/test.rs +++ b/src/librustc/middle/typeck/infer/test.rs @@ -16,6 +16,7 @@ Note: This module is only compiled when doing unit testing. */ +use diag_db; use driver::diagnostic; use driver::driver::{optgroups, build_session_options, build_session}; use driver::driver::{str_input, build_configuration}; @@ -58,7 +59,7 @@ fn setup_env(test_name: &str, source_string: &str) -> Env { let region_map = HashMap(); let lang_items = LanguageItems::new(); - let parse_sess = parse::new_parse_sess(None); + let parse_sess = parse::new_parse_sess(None, diag_db::load()); let crate = parse_crate_from_source_str( test_name.to_str(), @source_string.to_str(), cfg, parse_sess); diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 9ac0e1acec53c..f38dedba2ce7e 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -12,6 +12,7 @@ use rustc; use rustc::{driver, middle}; use rustc::metadata::creader::Loader; use rustc::middle::privacy; +use rustc::diag_db; use syntax::ast; use syntax::parse::token; @@ -47,7 +48,7 @@ fn get_ast_and_resolve(cpath: &Path, phase_2_configure_and_expand, phase_3_run_analysis_passes}; - let parsesess = parse::new_parse_sess(); + let parsesess = parse::new_parse_sess(diag_db::load()); let input = FileInput(cpath.clone()); let sessopts = @driver::session::Options { @@ -59,7 +60,7 @@ fn get_ast_and_resolve(cpath: &Path, }; - let diagnostic_handler = syntax::diagnostic::mk_handler(); + let diagnostic_handler = syntax::diagnostic::mk_handler(diag_db::load()); let span_diagnostic_handler = syntax::diagnostic::mk_span_handler(diagnostic_handler, parsesess.cm); diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 58c89d6aa4a7c..e180ca73a8037 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -22,6 +22,7 @@ use rustc::driver::driver; use rustc::driver::session; use rustc::metadata::creader::Loader; use getopts; +use rustc::diag_db; use syntax::diagnostic; use syntax::parse; @@ -34,7 +35,7 @@ use passes; use visit_ast::RustdocVisitor; pub fn run(input: &str, matches: &getopts::Matches) -> int { - let parsesess = parse::new_parse_sess(); + let parsesess = parse::new_parse_sess(diag_db::load()); let input_path = Path::new(input); let input = driver::FileInput(input_path.clone()); let libs = matches.opt_strs("L").map(|s| Path::new(s.as_slice())); @@ -49,7 +50,7 @@ pub fn run(input: &str, matches: &getopts::Matches) -> int { }; - let diagnostic_handler = diagnostic::mk_handler(); + let diagnostic_handler = diagnostic::mk_handler(diag_db::load()); let span_diagnostic_handler = diagnostic::mk_span_handler(diagnostic_handler, parsesess.cm); @@ -97,7 +98,7 @@ pub fn run(input: &str, matches: &getopts::Matches) -> int { fn runtest(test: &str, cratename: &str, libs: HashSet) { let test = maketest(test, cratename); - let parsesess = parse::new_parse_sess(); + let parsesess = parse::new_parse_sess(diag_db::load()); let input = driver::StrInput(test); let sessopts = @session::Options { @@ -110,7 +111,7 @@ fn runtest(test: &str, cratename: &str, libs: HashSet) { .. (*session::basic_options()).clone() }; - let diagnostic_handler = diagnostic::mk_handler(); + let diagnostic_handler = diagnostic::mk_handler(diag_db::load()); let span_diagnostic_handler = diagnostic::mk_span_handler(diagnostic_handler, parsesess.cm); diff --git a/src/libsyntax/diag_db.rs b/src/libsyntax/diag_db.rs index 721fbccbcf29e..411a6e9bc22ad 100644 --- a/src/libsyntax/diag_db.rs +++ b/src/libsyntax/diag_db.rs @@ -17,7 +17,12 @@ use std::cell::RefCell; use std::hashmap::HashMap; -pub fn load() -> ~[RawInfo] { +/// Load the database of extended diagnostic descriptions +pub fn load() -> DiagnosticDb { + DiagnosticDb::new(~[load_raw]) +} + +pub fn load_raw() -> ~[RawInfo] { ~[include!("diag_db.md")] } @@ -95,6 +100,36 @@ impl DiagnosticInfo { } } +/// Print extended information about a single diagnostic code to the console. +/// Returns false if the DB contains no information about the code. +pub fn explain_diagnostic(db: &DiagnosticDb, code: &str) -> bool { + match db.get_info(code) { + Some(info) => { + println!("\n{}\n", info.format()) + true + } + None => false + } +} + +pub fn explain_diag_help() { + println!("\nRust includes extended documentation about some compiler errors\n\ + that explain in greater depth what the errors means, present examples,\n\ + and suggestions for how to fix them.\n\ + \n\ + Each Rust error message has a corresponding code. When emitted by\n\ + rustc the code will be included in square brackets, like `[A0001]`. If\n\ + the error has additional documentation the code will be appended with\n\ + an asterisk, as in `[A0002*]`.\n\ + \n\ + To view the extended documentation, run `rustc --explain A0002`, replacing\n\ + 'A0002' with your error code.\n\ + \n\ + The extent and quality of extended error documentation depends on user\n\ + contributions. To learn how to improve Rust's error documentation visit\n\ + http://github.com/mozilla/rust/wiki/Note-extended-diagnostics.\n"); +} + #[cfg(test)] mod test { use super::*; diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 9dd5bd0a7c2a3..45876335dbd32 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -10,6 +10,7 @@ use codemap::{Pos, Span}; use codemap; +use diag_db::DiagnosticDb; use std::cell::Cell; use std::io; @@ -25,7 +26,7 @@ static MAX_LINES: uint = 6u; pub trait Emitter { fn emit(&self, cmsp: Option<(&codemap::CodeMap, Span)>, - msg: &str, lvl: Level); + msg: &str, lvl: Level, code: Option<&str>); fn custom_emit(&self, cm: &codemap::CodeMap, sp: Span, msg: &str, lvl: Level); } @@ -89,15 +90,20 @@ impl SpanHandler { pub struct Handler { err_count: Cell, emit: DefaultEmitter, + diag_db: DiagnosticDb, + /// Indicates that we've emitted a diagnostic with extended info + saw_extended_info: Cell, } impl Handler { pub fn fatal_without_diagnostic_code(&self, msg: &str) -> ! { self.emit(None, msg, Fatal); + self.emit_extended_info_explainer(); fail!(FatalError); } pub fn fatal_with_diagnostic_code(&self, code: &str, msg: &str) -> ! { self.emit_with_code(None, code, msg, Fatal); + self.emit_extended_info_explainer(); fail!(FatalError); } pub fn err_without_diagnostic_code(&self, msg: &str) { @@ -145,10 +151,10 @@ impl Handler { self.bug(~"unimplemented " + msg); } pub fn emit(&self, - cmsp: Option<(&codemap::CodeMap, Span)>, - msg: &str, - lvl: Level) { - self.emit.emit(cmsp, msg, lvl); + cmsp: Option<(&codemap::CodeMap, Span)>, + msg: &str, + lvl: Level) { + self.emit.emit(cmsp, msg, lvl, None); } pub fn custom_emit(&self, cm: &codemap::CodeMap, sp: Span, msg: &str, lvl: Level) { @@ -156,8 +162,29 @@ impl Handler { } pub fn emit_with_code(&self, cmsp: Option<(&codemap::CodeMap, Span)>, code: &str, msg: &str, lvl: Level) { - let msg = format!("{}: {}", code, msg); - self.emit.emit(cmsp, msg, lvl); + if !self.have_extended_info_for_code(code) { + self.emit.emit(cmsp, msg, lvl, Some(code)); + } else { + // Indicate with a '*' that there is extra info to be had + // with this error code. + let code = format!("{}*", code); + let code: &str = code; + self.emit.emit(cmsp, msg, lvl, Some(code)); + } + } + + fn have_extended_info_for_code(&self, code: &str) -> bool { + self.diag_db.get_info(code).is_some() + } + + fn emit_extended_info_explainer(&self) { + if self.saw_extended_info.get() { + self.note( + "some of these errors have extended explanations (see `rustc --explain help`)") + } else { + self.note( + "none of these errors have extended explanations (see `rustc --explain help`)") + } } } @@ -174,10 +201,12 @@ pub fn mk_span_handler(handler: @Handler, cm: @codemap::CodeMap) } } -pub fn mk_handler() -> @Handler { +pub fn mk_handler(db: DiagnosticDb) -> @Handler { @Handler { err_count: Cell::new(0), emit: DefaultEmitter, + diag_db: db, + saw_extended_info: Cell::new(false) } } @@ -254,7 +283,7 @@ fn print_maybe_styled(msg: &str, color: term::attr::Attr) -> io::IoResult<()> { } } -fn print_diagnostic(topic: &str, lvl: Level, msg: &str) -> io::IoResult<()> { +fn print_diagnostic(topic: &str, lvl: Level, msg: &str, code: Option<&str>) -> io::IoResult<()> { if !topic.is_empty() { let mut stderr = io::stderr(); if_ok!(write!(&mut stderr as &mut io::Writer, "{} ", topic)); @@ -262,7 +291,18 @@ fn print_diagnostic(topic: &str, lvl: Level, msg: &str) -> io::IoResult<()> { if_ok!(print_maybe_styled(format!("{}: ", lvl.to_str()), term::attr::ForegroundColor(lvl.color()))); - if_ok!(print_maybe_styled(format!("{}\n", msg), term::attr::Bold)); + if_ok!(print_maybe_styled(format!("{}", msg), term::attr::Bold)); + match code { + Some(code) => { + let style = term::attr::ForegroundColor(term::color::BRIGHT_MAGENTA); + if_ok!(print_maybe_styled(format!(" [{}]", code), style)); + } + None => () + } + { + let mut stderr = io::stderr(); + if_ok!(write!(&mut stderr as &mut io::Writer, "\n")); + } Ok(()) } @@ -272,10 +312,11 @@ impl Emitter for DefaultEmitter { fn emit(&self, cmsp: Option<(&codemap::CodeMap, Span)>, msg: &str, - lvl: Level) { + lvl: Level, + code: Option<&str>) { let error = match cmsp { - Some((cm, sp)) => emit(cm, sp, msg, lvl, false), - None => print_diagnostic("", lvl, msg), + Some((cm, sp)) => emit(cm, sp, msg, lvl, code, false), + None => print_diagnostic("", lvl, msg, code), }; match error { @@ -286,7 +327,7 @@ impl Emitter for DefaultEmitter { fn custom_emit(&self, cm: &codemap::CodeMap, sp: Span, msg: &str, lvl: Level) { - match emit(cm, sp, msg, lvl, true) { + match emit(cm, sp, msg, lvl, None, true) { Ok(()) => {} Err(e) => fail!("failed to print diagnostics: {}", e), } @@ -294,7 +335,7 @@ impl Emitter for DefaultEmitter { } fn emit(cm: &codemap::CodeMap, sp: Span, - msg: &str, lvl: Level, custom: bool) -> io::IoResult<()> { + msg: &str, lvl: Level, code: Option<&str>, custom: bool) -> io::IoResult<()> { let ss = cm.span_to_str(sp); let lines = cm.span_to_lines(sp); if custom { @@ -303,10 +344,10 @@ fn emit(cm: &codemap::CodeMap, sp: Span, // the span) let span_end = Span { lo: sp.hi, hi: sp.hi, expn_info: sp.expn_info}; let ses = cm.span_to_str(span_end); - if_ok!(print_diagnostic(ses, lvl, msg)); + if_ok!(print_diagnostic(ses, lvl, msg, code)); if_ok!(custom_highlight_lines(cm, sp, lvl, lines)); } else { - if_ok!(print_diagnostic(ss, lvl, msg)); + if_ok!(print_diagnostic(ss, lvl, msg, code)); if_ok!(highlight_lines(cm, sp, lvl, lines)); } print_macro_backtrace(cm, sp) @@ -427,9 +468,9 @@ fn print_macro_backtrace(cm: &codemap::CodeMap, sp: Span) -> io::IoResult<()> { }; if_ok!(print_diagnostic(ss, Note, format!("in expansion of {}{}{}", pre, - ei.callee.name, post))); + ei.callee.name, post), None)); let ss = cm.span_to_str(ei.call_site); - if_ok!(print_diagnostic(ss, Note, "expansion site")); + if_ok!(print_diagnostic(ss, Note, "expansion site", None)); if_ok!(print_macro_backtrace(cm, ei.call_site)); } Ok(()) diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 0ac84e52241ff..5a5279e4242da 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -904,6 +904,7 @@ mod test { use util::parser_testing::{string_to_pat, strs_to_idents}; use visit; use visit::Visitor; + use diag_db; // a visitor that extracts the paths // from a given thingy and puts them in a mutable @@ -964,7 +965,7 @@ mod test { #[test] fn macros_cant_escape_fns_test () { let src = ~"fn bogus() {macro_rules! z (() => (3+4))}\ fn inty() -> int { z!() }"; - let sess = parse::new_parse_sess(); + let sess = parse::new_parse_sess(diag_db::load()); let crate_ast = parse::parse_crate_from_source_str( ~"", src, @@ -979,7 +980,7 @@ mod test { #[test] fn macros_cant_escape_mods_test () { let src = ~"mod foo {macro_rules! z (() => (3+4))}\ fn inty() -> int { z!() }"; - let sess = parse::new_parse_sess(); + let sess = parse::new_parse_sess(diag_db::load()); let crate_ast = parse::parse_crate_from_source_str( ~"", src, @@ -993,7 +994,7 @@ mod test { #[test] fn macros_can_escape_flattened_mods_test () { let src = ~"#[macro_escape] mod foo {macro_rules! z (() => (3+4))}\ fn inty() -> int { z!() }"; - let sess = parse::new_parse_sess(); + let sess = parse::new_parse_sess(diag_db::load()); let crate_ast = parse::parse_crate_from_source_str( ~"", src, diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs index 21cca7f19f5ea..4d43507fd7fb0 100644 --- a/src/libsyntax/parse/lexer.rs +++ b/src/libsyntax/parse/lexer.rs @@ -1003,6 +1003,7 @@ mod test { use codemap::{BytePos, CodeMap, Span}; use diagnostic; + use diag_db; use parse::token; use parse::token::{str_to_ident}; @@ -1015,7 +1016,8 @@ mod test { fn setup(teststr: ~str) -> Env { let cm = CodeMap::new(); let fm = cm.new_filemap(~"zebra.rs", teststr); - let span_handler = diagnostic::mk_span_handler(diagnostic::mk_handler(), @cm); + let span_handler = + diagnostic::mk_span_handler(diagnostic::mk_handler(diag_db::load()), @cm); Env { string_reader: new_string_reader(span_handler,fm) } diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 0ee39aee84160..2a5f655ce3da7 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -17,6 +17,7 @@ use codemap; use diagnostic::{SpanHandler, mk_span_handler, mk_handler}; use parse::attr::ParserAttr; use parse::parser::Parser; +use diag_db::DiagnosticDb; use std::cell::RefCell; use std::io::File; @@ -45,11 +46,11 @@ pub struct ParseSess { included_mod_stack: RefCell<~[Path]>, } -pub fn new_parse_sess() -> @ParseSess { +pub fn new_parse_sess(db: DiagnosticDb) -> @ParseSess { let cm = @CodeMap::new(); @ParseSess { cm: cm, - span_diagnostic: mk_span_handler(mk_handler(), cm), + span_diagnostic: mk_span_handler(mk_handler(db), cm), included_mod_stack: RefCell::new(~[]), } } diff --git a/src/libsyntax/util/parser_testing.rs b/src/libsyntax/util/parser_testing.rs index 8c7ad028a8ee0..7edac54c62ca4 100644 --- a/src/libsyntax/util/parser_testing.rs +++ b/src/libsyntax/util/parser_testing.rs @@ -14,11 +14,12 @@ use parse::{ParseSess,string_to_filemap,filemap_to_tts}; use parse::{new_parser_from_source_str}; use parse::parser::Parser; use parse::token; +use diag_db; // map a string to tts, using a made-up filename: return both the TokenTree's // and the ParseSess pub fn string_to_tts_and_sess (source_str : ~str) -> (~[ast::TokenTree], @ParseSess) { - let ps = new_parse_sess(); + let ps = new_parse_sess(diag_db::load()); (filemap_to_tts(ps,string_to_filemap(ps,source_str,~"bogofile")),ps) } @@ -29,7 +30,7 @@ pub fn string_to_tts(source_str : ~str) -> ~[ast::TokenTree] { } pub fn string_to_parser_and_sess(source_str: ~str) -> (Parser,@ParseSess) { - let ps = new_parse_sess(); + let ps = new_parse_sess(diag_db::load()); (new_parser_from_source_str(ps,~[],~"bogofile",source_str),ps) } From febb7f87e2a103710f1ded7add8e986ee7e58133 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 9 Feb 2014 14:01:49 -0800 Subject: [PATCH 6/7] Slightly improve the format of the diagnostic database. --- src/librustc/diag_db.md | 5 ----- src/librustc/diag_db.rs | 2 +- src/librustc/diag_db_data.rs | 25 +++++++++++++++++++++++++ src/libsyntax/diag_db.md | 1 - src/libsyntax/diag_db.rs | 2 +- src/libsyntax/diag_db_data.rs | 25 +++++++++++++++++++++++++ src/libsyntax/diag_macros.rs | 6 ++++++ 7 files changed, 58 insertions(+), 8 deletions(-) delete mode 100644 src/librustc/diag_db.md create mode 100644 src/librustc/diag_db_data.rs delete mode 100644 src/libsyntax/diag_db.md create mode 100644 src/libsyntax/diag_db_data.rs diff --git a/src/librustc/diag_db.md b/src/librustc/diag_db.md deleted file mode 100644 index 16afe333b0f96..0000000000000 --- a/src/librustc/diag_db.md +++ /dev/null @@ -1,5 +0,0 @@ -desc_diag!(A0003, " - -Your borrowed pointer doesn't live long enough, dude. - -"), \ No newline at end of file diff --git a/src/librustc/diag_db.rs b/src/librustc/diag_db.rs index a3c20178c74ae..82dac1cbf7e50 100644 --- a/src/librustc/diag_db.rs +++ b/src/librustc/diag_db.rs @@ -22,6 +22,6 @@ pub fn load() -> DiagnosticDb { } pub fn load_raw() -> ~[(&'static str, &'static str, &'static str)] { - ~[include!("diag_db.md")] + include!("diag_db_data.rs") } diff --git a/src/librustc/diag_db_data.rs b/src/librustc/diag_db_data.rs new file mode 100644 index 0000000000000..0bc183f5f202e --- /dev/null +++ b/src/librustc/diag_db_data.rs @@ -0,0 +1,25 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +diag_db!( + +(A0001, " + +Placeholder. + +"), + +(A0002, " + +Placeholder. + +") + +) diff --git a/src/libsyntax/diag_db.md b/src/libsyntax/diag_db.md deleted file mode 100644 index 36c13b6da5271..0000000000000 --- a/src/libsyntax/diag_db.md +++ /dev/null @@ -1 +0,0 @@ -("", "", "") /* placeholder */ \ No newline at end of file diff --git a/src/libsyntax/diag_db.rs b/src/libsyntax/diag_db.rs index 411a6e9bc22ad..2608c908828d8 100644 --- a/src/libsyntax/diag_db.rs +++ b/src/libsyntax/diag_db.rs @@ -23,7 +23,7 @@ pub fn load() -> DiagnosticDb { } pub fn load_raw() -> ~[RawInfo] { - ~[include!("diag_db.md")] + include!("diag_db_data.rs") } pub type RawInfo = (&'static str, &'static str, &'static str); diff --git a/src/libsyntax/diag_db_data.rs b/src/libsyntax/diag_db_data.rs new file mode 100644 index 0000000000000..5afd9bfbf02c8 --- /dev/null +++ b/src/libsyntax/diag_db_data.rs @@ -0,0 +1,25 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +diag_db!( + +(C0001, " + +Placeholder. + +"), + +(C0002, " + +Placeholder. + +") + +) diff --git a/src/libsyntax/diag_macros.rs b/src/libsyntax/diag_macros.rs index d85c9a364cb61..3b55abe0a35c0 100644 --- a/src/libsyntax/diag_macros.rs +++ b/src/libsyntax/diag_macros.rs @@ -175,3 +175,9 @@ macro_rules! desc_diag ( (stringify!($name), "unknown", $desc) } ) + +macro_rules! diag_db ( + ($(($name: tt, $desc: expr)),*) => {~[ + $(desc_diag!($name, $desc)),* + ]} +) From e610e6e3013525c3e8727aecef8ce1629832cde0 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Tue, 11 Feb 2014 18:56:09 -0800 Subject: [PATCH 7/7] Address review feedback --- src/librustc/front/feature_gate.rs | 2 +- src/librustc/metadata/creader.rs | 4 ++-- src/librustc/middle/borrowck/mod.rs | 4 ++-- src/librustc/middle/kind.rs | 2 +- src/librustc/middle/resolve.rs | 4 ++-- src/librustc/middle/typeck/infer/error_reporting.rs | 4 ++-- src/libsyntax/diag_db.rs | 11 +++-------- src/libsyntax/diag_macros.rs | 9 ++------- src/libsyntax/ext/format.rs | 2 +- src/libsyntax/parse/parser.rs | 2 +- src/test/run-pass/tt_map.rs | 4 +++- 11 files changed, 20 insertions(+), 28 deletions(-) diff --git a/src/librustc/front/feature_gate.rs b/src/librustc/front/feature_gate.rs index 93cf34e89243c..4bc898fcc5fdd 100644 --- a/src/librustc/front/feature_gate.rs +++ b/src/librustc/front/feature_gate.rs @@ -284,7 +284,7 @@ pub fn check_crate(sess: Session, crate: &ast::Crate) { match attr.meta_item_list() { None => { span_err!(sess, attr.span, A0319, "malformed feature attribute, \ - expected #[feature(...)]"); + expected \\#[feature(...)]"); } Some(list) => { for &mi in list.iter() { diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index 8e785372e3d54..d4e3f4cc0baee 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -264,14 +264,14 @@ fn visit_item(e: &Env, i: &ast::Item) { Some(n) => n, None => { span_err!(e.sess, span, A0324, - "#[link(...)] specified without \ + "\\#[link(...)] specified without \ `name = \"foo\"`"); InternedString::new("foo") } }; if n.get().is_empty() { span_err!(e.sess, span, A0325, - "#[link(name = \"\")] given with empty name"); + "\\#[link(name = \"\")] given with empty name"); } else { cstore.add_used_library(n.get().to_owned(), kind); } diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs index 9e88f808a8612..0b92fe08483fa 100644 --- a/src/librustc/middle/borrowck/mod.rs +++ b/src/librustc/middle/borrowck/mod.rs @@ -672,12 +672,12 @@ impl BorrowckCtxt { mc::AliasableStaticMut => { span_err!(self.tcx.sess, span, A0357, - format!("{} in a static location", prefix)); + "{} in a static location", prefix); } mc::AliasableManaged => { span_err!(self.tcx.sess, span, A0010, - format!("{} in a `@` pointer", prefix)); + "{} in a `@` pointer", prefix); } mc::AliasableBorrowed(_) => { span_err!(self.tcx.sess, diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs index 5d52f127bf7f7..1a97b8bda031c 100644 --- a/src/librustc/middle/kind.rs +++ b/src/librustc/middle/kind.rs @@ -202,7 +202,7 @@ fn with_appropriate_checker(cx: &Context, span_err!(cx.tcx.sess, fv.span, A0316, "can't capture dynamic environment in a fn item; \ - use the || { ... } closure form instead"); + use the || \\{ ... \\} closure form instead"); } // same check is done in resolve.rs, but shouldn't be done let fty = ty::node_id_to_type(cx.tcx, id); diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 3dd93b647314e..01029dbbff79f 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -3526,7 +3526,7 @@ impl Resolver { resolve_err!(self, span, A0076, "can't capture dynamic environment in a fn item; \ - use the || { ... } closure form instead"); + use the || \\{ ... \\} closure form instead"); } else { // This was an attempt to use a type parameter outside // its scope. @@ -3549,7 +3549,7 @@ impl Resolver { resolve_err!(self, span, A0078, "can't capture dynamic environment in a fn item; \ - use the || { ... } closure form instead"); + use the || \\{ ... \\} closure form instead"); } else { // This was an attempt to use a type parameter outside // its scope. diff --git a/src/librustc/middle/typeck/infer/error_reporting.rs b/src/librustc/middle/typeck/infer/error_reporting.rs index 129cc46951a5f..5ec8be32a4b6f 100644 --- a/src/librustc/middle/typeck/infer/error_reporting.rs +++ b/src/librustc/middle/typeck/infer/error_reporting.rs @@ -409,9 +409,9 @@ impl ErrorReporting for InferCtxt { infer::ReferenceOutlivesReferent(ty, span) => { span_err!(self.tcx.sess, span, A0151, - format!("in type `{}`, pointer has a longer lifetime than \ + "in type `{}`, pointer has a longer lifetime than \ the data it references", - ty.user_string(self.tcx))); + ty.user_string(self.tcx)); note_and_explain_region( self.tcx, "the pointer is valid for ", diff --git a/src/libsyntax/diag_db.rs b/src/libsyntax/diag_db.rs index 2608c908828d8..48e71550ac4db 100644 --- a/src/libsyntax/diag_db.rs +++ b/src/libsyntax/diag_db.rs @@ -66,7 +66,7 @@ impl DiagnosticDb { map.insert(code, info); } } - new_map = Some(map); + new_map = map; } Initialized(ref mut map) => { return f(map); @@ -74,13 +74,8 @@ impl DiagnosticDb { } } - match new_map { - Some(new_map) => { - self.state.set(Initialized(new_map)); - return self.get_map(f); - } - None => unreachable!() - } + self.state.set(Initialized(new_map)); + return self.get_map(f); } pub fn get_info(&self, code: &str) -> Option { diff --git a/src/libsyntax/diag_macros.rs b/src/libsyntax/diag_macros.rs index 3b55abe0a35c0..44d3cb43691d5 100644 --- a/src/libsyntax/diag_macros.rs +++ b/src/libsyntax/diag_macros.rs @@ -62,16 +62,11 @@ macro_rules! reg_diag_msg ( ) macro_rules! report_diag ( - ($f: expr, $name: tt, $msg: expr, $($arg: expr), *) => { { + ($f: expr, $name: tt, $msg:expr $($arg: tt)*) => { { reg_diag_msg!($name, $msg); - let msg: &str = format!($msg, $($arg), *); + let msg: &str = format!($msg $($arg)*); let f: |&str, &str| -> () = $f; f(stringify!($name), msg); - } }; - ($f: expr, $name: tt, $msg: expr) => { { - reg_diag_msg!($name, $msg); - let f: |&str, &str| -> () = $f; - f(stringify!($name), $msg); } } ) diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs index 18395c5d9a5a5..372e1e11e3ae0 100644 --- a/src/libsyntax/ext/format.rs +++ b/src/libsyntax/ext/format.rs @@ -142,7 +142,7 @@ impl<'a> Context<'a> { parse::CurrentArgument => { if self.nest_level == 0 { span_err!(self.ecx, self.fmtsp, B0077, - "`#` reference used with nothing to \ + "`\\#` reference used with nothing to \ reference back to"); } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index c9396f7d88b6d..7cf8a9823b417 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -432,7 +432,7 @@ impl Parser { && self.look_ahead(1, |t| *t == token::RBRACE) { // matched; signal non-fatal error and recover. span_err!(self, self.span, C0018, - "unit-like struct construction is written with no trailing `{ }`"); + "unit-like struct construction is written with no trailing `\\{ \\}`"); self.eat(&token::LBRACE); self.eat(&token::RBRACE); true diff --git a/src/test/run-pass/tt_map.rs b/src/test/run-pass/tt_map.rs index 24137a88be2c2..0d59346012b0a 100644 --- a/src/test/run-pass/tt_map.rs +++ b/src/test/run-pass/tt_map.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn main() { +#[feature(__tt_map)]; + +pub fn main() { let j = 2; mod m { __tt_map_insert!(my_tt_map, i, j) }