diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 0e516bdc21194..3939f5f5880a9 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -22,7 +22,8 @@ use mir::transform as mir_pass; use syntax::ast::{NodeId, Name}; use errors::{self, DiagnosticBuilder}; -use errors::emitter::{Emitter, BasicEmitter, EmitterWriter}; +use errors::emitter::{Emitter, EmitterWriter}; +use errors::snippet::FormatMode; use syntax::json::JsonEmitter; use syntax::feature_gate; use syntax::parse; @@ -439,7 +440,7 @@ pub fn build_session_with_codemap(sopts: config::Options, config::ErrorOutputType::HumanReadable(color_config) => { Box::new(EmitterWriter::stderr(color_config, Some(registry), - codemap.clone(), + Some(codemap.clone()), errors::snippet::FormatMode::EnvironmentSelected)) } config::ErrorOutputType::Json => { @@ -577,7 +578,10 @@ unsafe fn configure_llvm(sess: &Session) { pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! { let mut emitter: Box = match output { config::ErrorOutputType::HumanReadable(color_config) => { - Box::new(BasicEmitter::stderr(color_config)) + Box::new(EmitterWriter::stderr(color_config, + None, + None, + FormatMode::EnvironmentSelected)) } config::ErrorOutputType::Json => Box::new(JsonEmitter::basic()), }; @@ -588,7 +592,10 @@ pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! { pub fn early_warn(output: config::ErrorOutputType, msg: &str) { let mut emitter: Box = match output { config::ErrorOutputType::HumanReadable(color_config) => { - Box::new(BasicEmitter::stderr(color_config)) + Box::new(EmitterWriter::stderr(color_config, + None, + None, + FormatMode::EnvironmentSelected)) } config::ErrorOutputType::Json => Box::new(JsonEmitter::basic()), }; diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 84e0403192317..695e9062db334 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -100,6 +100,7 @@ use syntax::feature_gate::{GatedCfg, UnstableFeatures}; use syntax::parse::{self, PResult}; use syntax_pos::MultiSpan; use errors::emitter::Emitter; +use errors::snippet::FormatMode; #[cfg(test)] pub mod test; @@ -139,7 +140,10 @@ pub fn run(args: Vec) -> isize { Some(sess) => sess.fatal(&abort_msg(err_count)), None => { let mut emitter = - errors::emitter::BasicEmitter::stderr(errors::ColorConfig::Auto); + errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto, + None, + None, + FormatMode::EnvironmentSelected); emitter.emit(&MultiSpan::new(), &abort_msg(err_count), None, errors::Level::Fatal); exit_on_err(); @@ -375,7 +379,10 @@ fn check_cfg(sopts: &config::Options, output: ErrorOutputType) { let mut emitter: Box = match output { config::ErrorOutputType::HumanReadable(color_config) => { - Box::new(errors::emitter::BasicEmitter::stderr(color_config)) + Box::new(errors::emitter::EmitterWriter::stderr(color_config, + None, + None, + FormatMode::EnvironmentSelected)) } config::ErrorOutputType::Json => Box::new(json::JsonEmitter::basic()), }; @@ -1046,7 +1053,11 @@ pub fn monitor(f: F) { if let Err(value) = thread.unwrap().join() { // Thread panicked without emitting a fatal diagnostic if !value.is::() { - let mut emitter = errors::emitter::BasicEmitter::stderr(errors::ColorConfig::Auto); + let mut emitter = + errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto, + None, + None, + FormatMode::EnvironmentSelected); // a .span_bug or .bug call has already printed what // it wants to print. diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index a7c68e3a87b31..75c35869e9e9d 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -117,42 +117,10 @@ impl ColorConfig { } } -/// A basic emitter for when we don't have access to a codemap or registry. Used -/// for reporting very early errors, etc. -pub struct BasicEmitter { - dst: Destination, -} - -impl CoreEmitter for BasicEmitter { - fn emit_message(&mut self, - _rsp: &RenderSpan, - msg: &str, - code: Option<&str>, - lvl: Level, - _is_header: bool, - _show_snippet: bool) { - // we ignore the span as we have no access to a codemap at this point - if let Err(e) = print_diagnostic(&mut self.dst, "", lvl, msg, code) { - panic!("failed to print diagnostics: {:?}", e); - } - } -} - -impl BasicEmitter { - pub fn stderr(color_config: ColorConfig) -> BasicEmitter { - if color_config.use_color() { - let dst = Destination::from_stderr(); - BasicEmitter { dst: dst } - } else { - BasicEmitter { dst: Raw(Box::new(io::stderr())) } - } - } -} - pub struct EmitterWriter { dst: Destination, registry: Option, - cm: Rc, + cm: Option>, /// Is this the first error emitted thus far? If not, we emit a /// `\n` before the top-level errors. @@ -194,7 +162,7 @@ macro_rules! println_maybe_styled { impl EmitterWriter { pub fn stderr(color_config: ColorConfig, registry: Option, - code_map: Rc, + code_map: Option>, format_mode: FormatMode) -> EmitterWriter { if color_config.use_color() { @@ -215,7 +183,7 @@ impl EmitterWriter { pub fn new(dst: Box, registry: Option, - code_map: Rc, + code_map: Option>, format_mode: FormatMode) -> EmitterWriter { EmitterWriter { dst: Raw(dst), @@ -257,7 +225,11 @@ impl EmitterWriter { if old_school { let loc = match rsp.span().primary_span() { Some(COMMAND_LINE_SP) | Some(DUMMY_SP) => "".to_string(), - Some(ps) => self.cm.span_to_string(ps), + Some(ps) => if let Some(ref cm) = self.cm { + cm.span_to_string(ps) + } else { + "".to_string() + }, None => "".to_string() }; print_diagnostic(&mut self.dst, &loc, lvl, msg, Some(code))? @@ -270,7 +242,11 @@ impl EmitterWriter { if old_school { let loc = match rsp.span().primary_span() { Some(COMMAND_LINE_SP) | Some(DUMMY_SP) => "".to_string(), - Some(ps) => self.cm.span_to_string(ps), + Some(ps) => if let Some(ref cm) = self.cm { + cm.span_to_string(ps) + } else { + "".to_string() + }, None => "".to_string() }; print_diagnostic(&mut self.dst, &loc, lvl, msg, code)? @@ -316,7 +292,11 @@ impl EmitterWriter { .is_some() => { let loc = match rsp.span().primary_span() { Some(COMMAND_LINE_SP) | Some(DUMMY_SP) => "".to_string(), - Some(ps) => self.cm.span_to_string(ps), + Some(ps) => if let Some(ref cm) = self.cm { + cm.span_to_string(ps) + } else { + "".to_string() + }, None => "".to_string() }; let msg = "run `rustc --explain ".to_string() + &code.to_string() + @@ -335,32 +315,34 @@ impl EmitterWriter { use std::borrow::Borrow; let primary_span = suggestion.msp.primary_span().unwrap(); - let lines = self.cm.span_to_lines(primary_span).unwrap(); - assert!(!lines.lines.is_empty()); - - let complete = suggestion.splice_lines(self.cm.borrow()); - let line_count = cmp::min(lines.lines.len(), MAX_HIGHLIGHT_LINES); - let display_lines = &lines.lines[..line_count]; - - let fm = &*lines.file; - // Calculate the widest number to format evenly - let max_digits = line_num_max_digits(display_lines.last().unwrap()); - - // print the suggestion without any line numbers, but leave - // space for them. This helps with lining up with previous - // snippets from the actual error being reported. - let mut lines = complete.lines(); - for line in lines.by_ref().take(MAX_HIGHLIGHT_LINES) { - write!(&mut self.dst, "{0}:{1:2$} {3}\n", - fm.name, "", max_digits, line)?; - } + if let Some(ref cm) = self.cm { + let lines = cm.span_to_lines(primary_span).unwrap(); + + assert!(!lines.lines.is_empty()); + + let complete = suggestion.splice_lines(cm.borrow()); + let line_count = cmp::min(lines.lines.len(), MAX_HIGHLIGHT_LINES); + let display_lines = &lines.lines[..line_count]; + + let fm = &*lines.file; + // Calculate the widest number to format evenly + let max_digits = line_num_max_digits(display_lines.last().unwrap()); + + // print the suggestion without any line numbers, but leave + // space for them. This helps with lining up with previous + // snippets from the actual error being reported. + let mut lines = complete.lines(); + for line in lines.by_ref().take(MAX_HIGHLIGHT_LINES) { + write!(&mut self.dst, "{0}:{1:2$} {3}\n", + fm.name, "", max_digits, line)?; + } - // if we elided some lines, add an ellipsis - if let Some(_) = lines.next() { - write!(&mut self.dst, "{0:1$} {0:2$} ...\n", - "", fm.name.len(), max_digits)?; + // if we elided some lines, add an ellipsis + if let Some(_) = lines.next() { + write!(&mut self.dst, "{0:1$} {0:2$} ...\n", + "", fm.name.len(), max_digits)?; + } } - Ok(()) } @@ -369,20 +351,26 @@ impl EmitterWriter { lvl: Level) -> io::Result<()> { + // Check to see if we have any lines to highlight, exit early if not + match self.cm { + None => return Ok(()), + _ => () + } + let old_school = match self.format_mode { FormatMode::NewErrorFormat => false, FormatMode::OriginalErrorFormat => true, FormatMode::EnvironmentSelected => check_old_skool() }; - let mut snippet_data = SnippetData::new(self.cm.clone(), + let mut snippet_data = SnippetData::new(self.cm.as_ref().unwrap().clone(), msp.primary_span(), self.format_mode.clone()); if old_school { let mut output_vec = vec![]; for span_label in msp.span_labels() { - let mut snippet_data = SnippetData::new(self.cm.clone(), + let mut snippet_data = SnippetData::new(self.cm.as_ref().unwrap().clone(), Some(span_label.span), self.format_mode.clone()); @@ -431,16 +419,18 @@ impl EmitterWriter { fn print_macro_backtrace(&mut self, sp: Span) -> io::Result<()> { - for trace in self.cm.macro_backtrace(sp) { - let mut diag_string = - format!("in this expansion of {}", trace.macro_decl_name); - if let Some(def_site_span) = trace.def_site_span { - diag_string.push_str( - &format!(" (defined in {})", - self.cm.span_to_filename(def_site_span))); + if let Some(ref cm) = self.cm { + for trace in cm.macro_backtrace(sp) { + let mut diag_string = + format!("in this expansion of {}", trace.macro_decl_name); + if let Some(def_site_span) = trace.def_site_span { + diag_string.push_str( + &format!(" (defined in {})", + cm.span_to_filename(def_site_span))); + } + let snippet = cm.span_to_string(trace.call_site); + print_diagnostic(&mut self.dst, &snippet, Note, &diag_string, None)?; } - let snippet = self.cm.span_to_string(trace.call_site); - print_diagnostic(&mut self.dst, &snippet, Note, &diag_string, None)?; } Ok(()) } diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 18fc826f9aa4b..100e79b1954d5 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -423,7 +423,7 @@ impl Handler { registry: Option, can_emit_warnings: bool, treat_err_as_bug: bool, - cm: Rc) + cm: Option>) -> Handler { let emitter = Box::new(EmitterWriter::stderr(color_config, registry, cm, snippet::FormatMode::EnvironmentSelected)); diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 49a3991ecbe0b..fc9ae73f5ce7e 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -131,7 +131,7 @@ pub fn run_core(search_paths: SearchPaths, None, true, false, - codemap.clone()); + Some(codemap.clone())); let dep_graph = DepGraph::new(false); let _ignore = dep_graph.in_ignore(); diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index bb69ba6e568d5..f9d0df9981a1d 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -77,7 +77,7 @@ pub fn run(input: &str, None, true, false, - codemap.clone()); + Some(codemap.clone())); let dep_graph = DepGraph::new(false); let _ignore = dep_graph.in_ignore(); @@ -229,7 +229,7 @@ fn runtest(test: &str, cratename: &str, cfgs: Vec, libs: SearchPaths, let codemap = Rc::new(CodeMap::new()); let emitter = errors::emitter::EmitterWriter::new(box Sink(data.clone()), None, - codemap.clone(), + Some(codemap.clone()), errors::snippet::FormatMode::EnvironmentSelected); let old = io::set_panic(box Sink(data.clone())); let _bomb = Bomb(data.clone(), old.unwrap_or(box io::stdout())); diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 743f96d737e2d..3b93dc0c4d37f 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -1235,7 +1235,7 @@ r"blork2.rs:2:1: 2:12 let cm = Rc::new(CodeMap::new()); let mut ew = EmitterWriter::new(Box::new(Sink(data.clone())), None, - cm.clone(), + Some(cm.clone()), FormatMode::NewErrorFormat); let content = "abcdefg koksi @@ -1321,7 +1321,7 @@ r"blork2.rs:2:1: 2:12 let cm = Rc::new(CodeMap::new()); let mut diag = EmitterWriter::new(Box::new(Sink(data.clone())), None, - cm.clone(), + Some(cm.clone()), FormatMode::NewErrorFormat); let inp = "_____aaaaaa____bbbbbb__cccccdd_"; @@ -1377,7 +1377,7 @@ r"blork2.rs:2:1: 2:12 let cm = Rc::new(CodeMap::new()); let mut diag = EmitterWriter::new(Box::new(Sink(data.clone())), None, - cm.clone(), + Some(cm.clone()), FormatMode::NewErrorFormat); let inp = "aaaaa\n\ diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 77b5c10899a3d..5ea1d6be9fec9 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -1686,7 +1686,7 @@ mod tests { // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. let emitter = errors::emitter::EmitterWriter::new(Box::new(io::sink()), None, - cm, + Some(cm), errors::snippet::FormatMode::EnvironmentSelected); errors::Handler::with_emitter(true, false, Box::new(emitter)) } diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 9502bc48a3e11..6af4d95e888ac 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -50,7 +50,11 @@ pub struct ParseSess { impl ParseSess { pub fn new() -> ParseSess { let cm = Rc::new(CodeMap::new()); - let handler = Handler::with_tty_emitter(ColorConfig::Auto, None, true, false, cm.clone()); + let handler = Handler::with_tty_emitter(ColorConfig::Auto, + None, + true, + false, + Some(cm.clone())); ParseSess::with_span_handler(handler, cm) }