Skip to content

Commit 9b9cce2

Browse files
author
Jakub Wieczorek
committed
Add scaffolding for assigning alpha-numeric codes to rustc diagnostics
1 parent 7ab9bfa commit 9b9cce2

25 files changed

+466
-84
lines changed

src/librustc/diagnostics.rs

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
register_diagnostic!(E0001, r##"
12+
This error suggests that the expression arm corresponding to the noted pattern
13+
will never be reached as for all possible values of the expression being matched,
14+
one of the preceeding patterns will match.
15+
16+
This means that perhaps some of the preceeding patterns are too general, this
17+
one is too specific or the ordering is incorrect.
18+
"##)

src/librustc/driver/config.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,7 @@ pub fn optgroups() -> Vec<getopts::OptGroup> {
532532
optopt("", "opt-level", "Optimize with possible levels 0-3", "LEVEL"),
533533
optopt( "", "out-dir", "Write output to compiler-chosen filename in <dir>", "DIR"),
534534
optflag("", "parse-only", "Parse only; do not compile, assemble, or link"),
535+
optopt("", "explain", "Provide a detailed explanation of an error message", "OPT"),
535536
optflagopt("", "pretty",
536537
"Pretty-print the input instead of compiling;
537538
valid types are: `normal` (un-annotated source),
@@ -807,6 +808,7 @@ mod test {
807808
use getopts::getopts;
808809
use syntax::attr;
809810
use syntax::attr::AttrMetaMethods;
811+
use syntax::diagnostics;
810812

811813
// When the user supplies --test we should implicitly supply --cfg test
812814
#[test]
@@ -816,8 +818,9 @@ mod test {
816818
Ok(m) => m,
817819
Err(f) => fail!("test_switch_implies_cfg_test: {}", f)
818820
};
821+
let registry = diagnostics::registry::Registry::new([]);
819822
let sessopts = build_session_options(matches);
820-
let sess = build_session(sessopts, None);
823+
let sess = build_session(sessopts, None, registry);
821824
let cfg = build_configuration(&sess);
822825
assert!((attr::contains_name(cfg.as_slice(), "test")));
823826
}
@@ -834,8 +837,9 @@ mod test {
834837
fail!("test_switch_implies_cfg_test_unless_cfg_test: {}", f)
835838
}
836839
};
840+
let registry = diagnostics::registry::Registry::new([]);
837841
let sessopts = build_session_options(matches);
838-
let sess = build_session(sessopts, None);
842+
let sess = build_session(sessopts, None, registry);
839843
let cfg = build_configuration(&sess);
840844
let mut test_items = cfg.iter().filter(|m| m.name().equiv(&("test")));
841845
assert!(test_items.next().is_some());

src/librustc/driver/driver.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use driver::{PpmFlowGraph, PpmExpanded, PpmExpandedIdentified, PpmTyped};
1616
use driver::{PpmIdentified};
1717
use front;
1818
use lib::llvm::{ContextRef, ModuleRef};
19+
use lint;
1920
use metadata::common::LinkMeta;
2021
use metadata::creader;
2122
use middle::cfg;
@@ -26,7 +27,7 @@ use middle;
2627
use plugin::load::Plugins;
2728
use plugin::registry::Registry;
2829
use plugin;
29-
use lint;
30+
3031
use util::common::time;
3132
use util::ppaux;
3233
use util::nodemap::{NodeSet};
@@ -41,6 +42,7 @@ use std::io::MemReader;
4142
use syntax::ast;
4243
use syntax::attr;
4344
use syntax::attr::{AttrMetaMethods};
45+
use syntax::diagnostics;
4446
use syntax::parse;
4547
use syntax::parse::token;
4648
use syntax::print::{pp, pprust};
@@ -213,6 +215,15 @@ pub fn phase_2_configure_and_expand(sess: &Session,
213215
let mut registry = Registry::new(&krate);
214216

215217
time(time_passes, "plugin registration", (), |_| {
218+
if sess.features.rustc_diagnostic_macros.get() {
219+
registry.register_macro("__diagnostic_used",
220+
diagnostics::plugin::expand_diagnostic_used);
221+
registry.register_macro("__register_diagnostic",
222+
diagnostics::plugin::expand_register_diagnostic);
223+
registry.register_macro("__build_diagnostic_array",
224+
diagnostics::plugin::expand_build_diagnostic_array);
225+
}
226+
216227
for &registrar in registrars.iter() {
217228
registrar(&mut registry);
218229
}

src/librustc/driver/mod.rs

+27-8
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use std::task::TaskBuilder;
2626
use syntax::ast;
2727
use syntax::parse;
2828
use syntax::diagnostic::Emitter;
29+
use syntax::diagnostics;
2930

3031
use getopts;
3132

@@ -49,8 +50,24 @@ fn run_compiler(args: &[String]) {
4950
Some(matches) => matches,
5051
None => return
5152
};
52-
let sopts = config::build_session_options(&matches);
5353

54+
let descriptions = diagnostics::registry::Registry::new(super::DIAGNOSTICS);
55+
match matches.opt_str("explain") {
56+
Some(ref code) => {
57+
match descriptions.find_description(code.as_slice()) {
58+
Some(ref description) => {
59+
println!("{}", description);
60+
}
61+
None => {
62+
early_error(format!("no extended information for {}", code).as_slice());
63+
}
64+
}
65+
return;
66+
},
67+
None => ()
68+
}
69+
70+
let sopts = config::build_session_options(&matches);
5471
let (input, input_file_path) = match matches.free.len() {
5572
0u => {
5673
if sopts.describe_lints {
@@ -75,7 +92,7 @@ fn run_compiler(args: &[String]) {
7592
_ => early_error("multiple input filenames provided")
7693
};
7794

78-
let sess = build_session(sopts, input_file_path);
95+
let sess = build_session(sopts, input_file_path, descriptions);
7996
let cfg = config::build_configuration(&sess);
8097
let odir = matches.opt_str("out-dir").map(|o| Path::new(o));
8198
let ofile = matches.opt_str("o").map(|o| Path::new(o));
@@ -383,14 +400,14 @@ fn parse_crate_attrs(sess: &Session, input: &Input) ->
383400
}
384401

385402
pub fn early_error(msg: &str) -> ! {
386-
let mut emitter = diagnostic::EmitterWriter::stderr(diagnostic::Auto);
387-
emitter.emit(None, msg, diagnostic::Fatal);
403+
let mut emitter = diagnostic::EmitterWriter::stderr(diagnostic::Auto, None);
404+
emitter.emit(None, msg, None, diagnostic::Fatal);
388405
fail!(diagnostic::FatalError);
389406
}
390407

391408
pub fn early_warn(msg: &str) {
392-
let mut emitter = diagnostic::EmitterWriter::stderr(diagnostic::Auto);
393-
emitter.emit(None, msg, diagnostic::Warning);
409+
let mut emitter = diagnostic::EmitterWriter::stderr(diagnostic::Auto, None);
410+
emitter.emit(None, msg, None, diagnostic::Warning);
394411
}
395412

396413
pub fn list_metadata(sess: &Session, path: &Path,
@@ -429,14 +446,15 @@ fn monitor(f: proc():Send) {
429446
Err(value) => {
430447
// Task failed without emitting a fatal diagnostic
431448
if !value.is::<diagnostic::FatalError>() {
432-
let mut emitter = diagnostic::EmitterWriter::stderr(diagnostic::Auto);
449+
let mut emitter = diagnostic::EmitterWriter::stderr(diagnostic::Auto, None);
433450

434451
// a .span_bug or .bug call has already printed what
435452
// it wants to print.
436453
if !value.is::<diagnostic::ExplicitBug>() {
437454
emitter.emit(
438455
None,
439456
"unexpected failure",
457+
None,
440458
diagnostic::Bug);
441459
}
442460

@@ -447,7 +465,7 @@ fn monitor(f: proc():Send) {
447465
"run with `RUST_BACKTRACE=1` for a backtrace".to_string(),
448466
];
449467
for note in xs.iter() {
450-
emitter.emit(None, note.as_slice(), diagnostic::Note)
468+
emitter.emit(None, note.as_slice(), None, diagnostic::Note)
451469
}
452470

453471
match r.read_to_string() {
@@ -457,6 +475,7 @@ fn monitor(f: proc():Send) {
457475
format!("failed to read internal \
458476
stderr: {}",
459477
e).as_slice(),
478+
None,
460479
diagnostic::Error)
461480
}
462481
}

src/librustc/driver/session.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use util::nodemap::NodeMap;
2020
use syntax::ast::NodeId;
2121
use syntax::codemap::Span;
2222
use syntax::diagnostic;
23+
use syntax::diagnostics;
2324
use syntax::parse;
2425
use syntax::parse::token;
2526
use syntax::parse::ParseSess;
@@ -65,6 +66,9 @@ impl Session {
6566
pub fn span_err(&self, sp: Span, msg: &str) {
6667
self.diagnostic().span_err(sp, msg)
6768
}
69+
pub fn span_err_with_code(&self, sp: Span, msg: &str, code: &str) {
70+
self.diagnostic().span_err_with_code(sp, msg, code)
71+
}
6872
pub fn err(&self, msg: &str) {
6973
self.diagnostic().handler().err(msg)
7074
}
@@ -197,11 +201,12 @@ impl Session {
197201
}
198202

199203
pub fn build_session(sopts: config::Options,
200-
local_crate_source_file: Option<Path>)
204+
local_crate_source_file: Option<Path>,
205+
registry: diagnostics::registry::Registry)
201206
-> Session {
202207
let codemap = codemap::CodeMap::new();
203208
let diagnostic_handler =
204-
diagnostic::default_handler(sopts.color);
209+
diagnostic::default_handler(sopts.color, Some(registry));
205210
let span_diagnostic_handler =
206211
diagnostic::mk_span_handler(diagnostic_handler, codemap);
207212

src/librustc/front/feature_gate.rs

+5
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[
6666

6767
("quad_precision_float", Removed),
6868

69+
("rustc_diagnostic_macros", Active),
70+
6971
// A temporary feature gate used to enable parser extensions needed
7072
// to bootstrap fix for #5723.
7173
("issue_5723_bootstrap", Active),
@@ -93,6 +95,7 @@ pub struct Features {
9395
pub default_type_params: Cell<bool>,
9496
pub issue_5723_bootstrap: Cell<bool>,
9597
pub overloaded_calls: Cell<bool>,
98+
pub rustc_diagnostic_macros: Cell<bool>
9699
}
97100

98101
impl Features {
@@ -101,6 +104,7 @@ impl Features {
101104
default_type_params: Cell::new(false),
102105
issue_5723_bootstrap: Cell::new(false),
103106
overloaded_calls: Cell::new(false),
107+
rustc_diagnostic_macros: Cell::new(false)
104108
}
105109
}
106110
}
@@ -425,4 +429,5 @@ pub fn check_crate(sess: &Session, krate: &ast::Crate) {
425429
sess.features.default_type_params.set(cx.has_feature("default_type_params"));
426430
sess.features.issue_5723_bootstrap.set(cx.has_feature("issue_5723_bootstrap"));
427431
sess.features.overloaded_calls.set(cx.has_feature("overloaded_calls"));
432+
sess.features.rustc_diagnostic_macros.set(cx.has_feature("rustc_diagnostic_macros"));
428433
}

src/librustc/lib.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,21 @@ This API is completely unstable and subject to change.
3232
#![feature(macro_rules, globs, struct_variant, managed_boxes, quote)]
3333
#![feature(default_type_params, phase, unsafe_destructor)]
3434

35+
#![allow(unknown_features)] // NOTE: Remove after next snapshot
36+
#![feature(rustc_diagnostic_macros)]
37+
3538
extern crate arena;
3639
extern crate debug;
3740
extern crate flate;
3841
extern crate getopts;
3942
extern crate graphviz;
4043
extern crate libc;
4144
extern crate serialize;
42-
extern crate syntax;
4345
extern crate time;
4446
#[phase(plugin, link)] extern crate log;
47+
#[phase(plugin, link)] extern crate syntax;
48+
49+
mod diagnostics;
4550

4651
pub mod middle {
4752
pub mod def;
@@ -127,6 +132,8 @@ pub mod lib {
127132
pub mod llvmdeps;
128133
}
129134

135+
__build_diagnostic_array!(DIAGNOSTICS)
136+
130137
// A private module so that macro-expanded idents like
131138
// `::rustc::lint::Lint` will also work in `rustc` itself.
132139
//

src/librustc/middle/check_match.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ fn check_arms(cx: &MatchCheckCtxt, arms: &[Arm]) {
194194

195195
let v = vec!(*pat);
196196
match is_useful(cx, &seen, v.as_slice(), LeaveOutWitness) {
197-
NotUseful => cx.tcx.sess.span_err(pat.span, "unreachable pattern"),
197+
NotUseful => span_err!(cx.tcx.sess, pat.span, E0001, "unreachable pattern"),
198198
Useful => (),
199199
UsefulWithWitness(_) => unreachable!()
200200
}

src/librustc/middle/typeck/infer/test.rs

+1
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ impl Emitter for ExpectErrorEmitter {
7878
fn emit(&mut self,
7979
_cmsp: Option<(&codemap::CodeMap, Span)>,
8080
msg: &str,
81+
_: Option<&str>,
8182
lvl: Level)
8283
{
8384
remove_message(self, msg, lvl);

src/librustdoc/core.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ fn get_ast_and_resolve(cpath: &Path, libs: HashSet<Path>, cfgs: Vec<String>)
101101

102102

103103
let codemap = syntax::codemap::CodeMap::new();
104-
let diagnostic_handler = syntax::diagnostic::default_handler(syntax::diagnostic::Auto);
104+
let diagnostic_handler = syntax::diagnostic::default_handler(syntax::diagnostic::Auto, None);
105105
let span_diagnostic_handler =
106106
syntax::diagnostic::mk_span_handler(diagnostic_handler, codemap);
107107

src/librustdoc/test.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ pub fn run(input: &str,
5454

5555

5656
let codemap = CodeMap::new();
57-
let diagnostic_handler = diagnostic::default_handler(diagnostic::Auto);
57+
let diagnostic_handler = diagnostic::default_handler(diagnostic::Auto, None);
5858
let span_diagnostic_handler =
5959
diagnostic::mk_span_handler(diagnostic_handler, codemap);
6060

@@ -150,7 +150,7 @@ fn runtest(test: &str, cratename: &str, libs: HashSet<Path>, should_fail: bool,
150150
};
151151
io::util::copy(&mut p, &mut err).unwrap();
152152
});
153-
let emitter = diagnostic::EmitterWriter::new(box w2);
153+
let emitter = diagnostic::EmitterWriter::new(box w2, None);
154154

155155
// Compile the code
156156
let codemap = CodeMap::new();

0 commit comments

Comments
 (0)