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_db.rs b/src/librustc/diag_db.rs new file mode 100644 index 0000000000000..82dac1cbf7e50 --- /dev/null +++ b/src/librustc/diag_db.rs @@ -0,0 +1,27 @@ +// 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 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_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/librustc/diag_index.rs b/src/librustc/diag_index.rs new file mode 100644 index 0000000000000..c4d716bd5f1a4 --- /dev/null +++ b/src/librustc/diag_index.rs @@ -0,0 +1,378 @@ +// 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. + +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..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::() } @@ -479,7 +480,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(()); }, @@ -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); @@ -983,7 +984,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`"); } @@ -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), @@ -1142,14 +1145,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(), @@ -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/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 f2e525932ad8b..4bc898fcc5fdd 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), @@ -77,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)); @@ -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); @@ -279,15 +283,15 @@ pub fn check_crate(sess: Session, crate: &ast::Crate) { match attr.meta_item_list() { None => { - sess.span_err(attr.span, "malformed feature attribute, \ - expected #[feature(...)]"); + span_err!(sess, attr.span, A0319, "malformed feature attribute, \ + expected \\#[feature(...)]"); } Some(list) => { for &mi in list.iter() { 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 @@ -297,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 edcefdf659402..9cff3515f5658 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -57,6 +57,14 @@ 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"] +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; @@ -214,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") { @@ -290,7 +313,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") } }; @@ -372,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. \ @@ -381,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()); @@ -405,3 +428,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; diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index 9c2c5a5745848..d4e3f4cc0baee 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, - "#[link(...)] specified without \ + 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/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/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..0b92fe08483fa 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, - format!("{} in a static location", prefix)); + span_err!(self.tcx.sess, + span, A0357, + "{} in a static location", prefix); } mc::AliasableManaged => { - self.tcx.sess.span_err( - span, - format!("{} in a `@` pointer", prefix)); + span_err!(self.tcx.sess, + span, A0010, + "{} 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..1a97b8bda031c 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,10 +199,10 @@ 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"); + 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); @@ -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..01029dbbff79f 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"); + 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"); + 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..5ec8be32a4b6f 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,11 +407,11 @@ impl ErrorReporting for InferCtxt { ""); } infer::ReferenceOutlivesReferent(ty, span) => { - self.tcx.sess.span_err( - span, - format!("in type `{}`, pointer has a longer lifetime than \ + span_err!(self.tcx.sess, + span, A0151, + "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 ", @@ -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/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/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/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/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_db.rs b/src/libsyntax/diag_db.rs new file mode 100644 index 0000000000000..48e71550ac4db --- /dev/null +++ b/src/libsyntax/diag_db.rs @@ -0,0 +1,145 @@ +// 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; + +/// Load the database of extended diagnostic descriptions +pub fn load() -> DiagnosticDb { + DiagnosticDb::new(~[load_raw]) +} + +pub fn load_raw() -> ~[RawInfo] { + include!("diag_db_data.rs") +} + +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 = map; + } + Initialized(ref mut map) => { + return f(map); + } + } + } + + self.state.set(Initialized(new_map)); + return self.get_map(f); + } + + 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()) + } +} + +/// 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::*; + + #[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_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_index.rs b/src/libsyntax/diag_index.rs new file mode 100644 index 0000000000000..0cc4f50850789 --- /dev/null +++ b/src/libsyntax/diag_index.rs @@ -0,0 +1,212 @@ +// 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. + +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 new file mode 100644 index 0000000000000..44d3cb43691d5 --- /dev/null +++ b/src/libsyntax/diag_macros.rs @@ -0,0 +1,178 @@ +// 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) => { + } +) + +macro_rules! all_diag { + ($($name: tt),+) => { + $(reg_diag!($name))+ + } +} + +#[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: tt)*) => { { + reg_diag_msg!($name, $msg); + let msg: &str = format!($msg $($arg)*); + let f: |&str, &str| -> () = $f; + f(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), *); + 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), *) + ); + ($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), *); + 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), *) + ); + ($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) + } +) + +macro_rules! diag_db ( + ($(($name: tt, $desc: expr)),*) => {~[ + $(desc_diag!($name, $desc)),* + ]} +) diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 3f6540570b0ef..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); } @@ -44,17 +45,28 @@ 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); } - pub fn span_err(&self, sp: Span, msg: &str) { + 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_without_diagnostic_code(&self, sp: Span, msg: &str) { self.handler.emit(Some((&*self.cm, sp)), msg, Error); self.handler.bump_err_count(); } - pub fn span_warn(&self, sp: Span, msg: &str) { + 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_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) { + 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); } @@ -62,7 +74,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); @@ -78,15 +90,28 @@ 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(&self, msg: &str) -> ! { - self.emit.emit(None, msg, Fatal); + 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(&self, msg: &str) { - self.emit.emit(None, msg, Error); + pub fn err_without_diagnostic_code(&self, msg: &str) { + 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) { @@ -108,30 +133,59 @@ impl Handler { self.err_count.get()); } } - self.fatal(s); + self.fatal_without_diagnostic_code(s); + } + pub fn warn_without_diagnostic_code(&self, msg: &str) { + self.emit(None, msg, Warning); } - pub fn warn(&self, msg: &str) { - self.emit.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)); + self.fatal_without_diagnostic_code(ice_msg(msg)); } pub fn unimpl(&self, msg: &str) -> ! { 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) { 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) { + 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`)") + } + } } pub fn ice_msg(msg: &str) -> ~str { @@ -147,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) } } @@ -227,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)); @@ -235,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(()) } @@ -245,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 { @@ -259,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), } @@ -267,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 { @@ -276,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) @@ -400,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/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 d22a1d697fcb4..33b9fe2236298 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() } } @@ -346,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: @@ -357,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(); @@ -407,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 } @@ -427,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); } } @@ -439,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)) @@ -447,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 @@ -464,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..5a5279e4242da 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(); @@ -902,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 @@ -962,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, @@ -977,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, @@ -991,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/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..372e1e11e3ae0 100644 --- a/src/libsyntax/ext/format.rs +++ b/src/libsyntax/ext/format.rs @@ -141,8 +141,8 @@ impl<'a> Context<'a> { parse::String(..) => {} parse::CurrentArgument => { if self.nest_level == 0 { - self.ecx.span_err(self.fmtsp, - "`#` reference used with nothing to \ + 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 new file mode 100644 index 0000000000000..07736b34f7b4c --- /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 { + 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) => (), + _ => span_fatal!(ecx, sp, B0003, "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(); + span_fatal!(ecx, sp, B0004, "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 { + span_fatal!(ecx, sp, B0005, "incorrect number of arguments") + } + + match &tts[1] { + &ast::TTTok(_, token::COMMA) => (), + _ => span_fatal!(ecx, sp, B0006, "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(); + span_fatal!(ecx, sp, B0015, "key {} does not exist in map", key_name); + } + } + } + None => { + span_fatal!(ecx, sp, B0016, "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..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)] @@ -97,6 +103,11 @@ pub mod ext { pub mod concat_idents; pub mod log_syntax; pub mod source_util; + pub mod tt_map; 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; 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..4d43507fd7fb0 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 @@ -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 6ddb4bbc11fb7..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(~[]), } } @@ -227,8 +228,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..7cf8a9823b417 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,8 +431,8 @@ 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, - "unit-like struct construction is written with no trailing `{ }`"); + span_err!(self, self.span, C0018, + "unit-like struct construction is written with no trailing `\\{ \\}`"); self.eat(&token::LBRACE); self.eat(&token::RBRACE); true @@ -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") } } } 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) } 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..0d59346012b0a --- /dev/null +++ b/src/test/run-pass/tt_map.rs @@ -0,0 +1,20 @@ +// 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. + +#[feature(__tt_map)]; + +pub 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); +}