Turn on new errors, json mode. Remove duplicate unicode test
This commit is contained in:
parent
42903d9a8f
commit
fad4f32c31
18 changed files with 29 additions and 595 deletions
|
@ -94,7 +94,7 @@ use syntax::ast;
|
||||||
use syntax::parse::token;
|
use syntax::parse::token;
|
||||||
use syntax::ptr::P;
|
use syntax::ptr::P;
|
||||||
use syntax_pos::{self, Pos, Span};
|
use syntax_pos::{self, Pos, Span};
|
||||||
use errors::{DiagnosticBuilder, check_old_school};
|
use errors::DiagnosticBuilder;
|
||||||
|
|
||||||
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||||
pub fn note_and_explain_region(self,
|
pub fn note_and_explain_region(self,
|
||||||
|
@ -541,25 +541,19 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
let span = origin.span();
|
let span = origin.span();
|
||||||
|
|
||||||
let mut is_simple_error = false;
|
|
||||||
|
|
||||||
if let Some((expected, found)) = expected_found {
|
if let Some((expected, found)) = expected_found {
|
||||||
is_simple_error = if let &TypeError::Sorts(ref values) = terr {
|
let is_simple_error = if let &TypeError::Sorts(ref values) = terr {
|
||||||
values.expected.is_primitive() && values.found.is_primitive()
|
values.expected.is_primitive() && values.found.is_primitive()
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
|
|
||||||
if !is_simple_error || check_old_school() {
|
if !is_simple_error {
|
||||||
diag.note_expected_found(&"type", &expected, &found);
|
diag.note_expected_found(&"type", &expected, &found);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !is_simple_error && check_old_school() {
|
diag.span_label(span, &terr);
|
||||||
diag.span_note(span, &format!("{}", terr));
|
|
||||||
} else {
|
|
||||||
diag.span_label(span, &terr);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.note_error_origin(diag, &origin);
|
self.note_error_origin(diag, &origin);
|
||||||
self.check_and_note_conflicting_crates(diag, terr, span);
|
self.check_and_note_conflicting_crates(diag, terr, span);
|
||||||
|
|
|
@ -1055,7 +1055,7 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
|
||||||
"NAME=PATH"),
|
"NAME=PATH"),
|
||||||
opt::opt_s("", "sysroot", "Override the system root", "PATH"),
|
opt::opt_s("", "sysroot", "Override the system root", "PATH"),
|
||||||
opt::multi_ubnr("Z", "", "Set internal debugging options", "FLAG"),
|
opt::multi_ubnr("Z", "", "Set internal debugging options", "FLAG"),
|
||||||
opt::opt_ubnr("", "error-format",
|
opt::opt_s("", "error-format",
|
||||||
"How errors and other messages are produced",
|
"How errors and other messages are produced",
|
||||||
"human|json"),
|
"human|json"),
|
||||||
opt::opt_s("", "color", "Configure coloring of output:
|
opt::opt_s("", "color", "Configure coloring of output:
|
||||||
|
|
|
@ -23,7 +23,6 @@ use mir::transform as mir_pass;
|
||||||
use syntax::ast::{NodeId, Name};
|
use syntax::ast::{NodeId, Name};
|
||||||
use errors::{self, DiagnosticBuilder};
|
use errors::{self, DiagnosticBuilder};
|
||||||
use errors::emitter::{Emitter, EmitterWriter};
|
use errors::emitter::{Emitter, EmitterWriter};
|
||||||
use errors::snippet::FormatMode;
|
|
||||||
use syntax::json::JsonEmitter;
|
use syntax::json::JsonEmitter;
|
||||||
use syntax::feature_gate;
|
use syntax::feature_gate;
|
||||||
use syntax::parse;
|
use syntax::parse;
|
||||||
|
@ -369,9 +368,7 @@ pub fn build_session_with_codemap(sopts: config::Options,
|
||||||
let emitter: Box<Emitter> = match sopts.error_format {
|
let emitter: Box<Emitter> = match sopts.error_format {
|
||||||
config::ErrorOutputType::HumanReadable(color_config) => {
|
config::ErrorOutputType::HumanReadable(color_config) => {
|
||||||
Box::new(EmitterWriter::stderr(color_config,
|
Box::new(EmitterWriter::stderr(color_config,
|
||||||
Some(registry),
|
Some(codemap.clone())))
|
||||||
Some(codemap.clone()),
|
|
||||||
errors::snippet::FormatMode::EnvironmentSelected))
|
|
||||||
}
|
}
|
||||||
config::ErrorOutputType::Json => {
|
config::ErrorOutputType::Json => {
|
||||||
Box::new(JsonEmitter::stderr(Some(registry), codemap.clone()))
|
Box::new(JsonEmitter::stderr(Some(registry), codemap.clone()))
|
||||||
|
@ -509,9 +506,7 @@ pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
|
||||||
let emitter: Box<Emitter> = match output {
|
let emitter: Box<Emitter> = match output {
|
||||||
config::ErrorOutputType::HumanReadable(color_config) => {
|
config::ErrorOutputType::HumanReadable(color_config) => {
|
||||||
Box::new(EmitterWriter::stderr(color_config,
|
Box::new(EmitterWriter::stderr(color_config,
|
||||||
None,
|
None))
|
||||||
None,
|
|
||||||
FormatMode::EnvironmentSelected))
|
|
||||||
}
|
}
|
||||||
config::ErrorOutputType::Json => Box::new(JsonEmitter::basic()),
|
config::ErrorOutputType::Json => Box::new(JsonEmitter::basic()),
|
||||||
};
|
};
|
||||||
|
@ -524,9 +519,7 @@ pub fn early_warn(output: config::ErrorOutputType, msg: &str) {
|
||||||
let emitter: Box<Emitter> = match output {
|
let emitter: Box<Emitter> = match output {
|
||||||
config::ErrorOutputType::HumanReadable(color_config) => {
|
config::ErrorOutputType::HumanReadable(color_config) => {
|
||||||
Box::new(EmitterWriter::stderr(color_config,
|
Box::new(EmitterWriter::stderr(color_config,
|
||||||
None,
|
None))
|
||||||
None,
|
|
||||||
FormatMode::EnvironmentSelected))
|
|
||||||
}
|
}
|
||||||
config::ErrorOutputType::Json => Box::new(JsonEmitter::basic()),
|
config::ErrorOutputType::Json => Box::new(JsonEmitter::basic()),
|
||||||
};
|
};
|
||||||
|
|
|
@ -44,7 +44,7 @@ use std::cmp::Ordering;
|
||||||
use std::collections::hash_map::Entry::Vacant;
|
use std::collections::hash_map::Entry::Vacant;
|
||||||
|
|
||||||
use rustc_const_math::*;
|
use rustc_const_math::*;
|
||||||
use rustc_errors::{DiagnosticBuilder, check_old_school};
|
use rustc_errors::DiagnosticBuilder;
|
||||||
|
|
||||||
macro_rules! math {
|
macro_rules! math {
|
||||||
($e:expr, $op:expr) => {
|
($e:expr, $op:expr) => {
|
||||||
|
@ -378,11 +378,7 @@ pub fn note_const_eval_err<'a, 'tcx>(
|
||||||
{
|
{
|
||||||
match err.description() {
|
match err.description() {
|
||||||
ConstEvalErrDescription::Simple(message) => {
|
ConstEvalErrDescription::Simple(message) => {
|
||||||
if check_old_school() {
|
diag.span_label(err.span, &message);
|
||||||
diag.note(&message);
|
|
||||||
} else {
|
|
||||||
diag.span_label(err.span, &message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -100,7 +100,6 @@ use syntax::feature_gate::{GatedCfg, UnstableFeatures};
|
||||||
use syntax::parse::{self, PResult};
|
use syntax::parse::{self, PResult};
|
||||||
use syntax_pos::MultiSpan;
|
use syntax_pos::MultiSpan;
|
||||||
use errors::emitter::Emitter;
|
use errors::emitter::Emitter;
|
||||||
use errors::snippet::FormatMode;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub mod test;
|
pub mod test;
|
||||||
|
@ -141,9 +140,7 @@ pub fn run(args: Vec<String>) -> isize {
|
||||||
None => {
|
None => {
|
||||||
let emitter =
|
let emitter =
|
||||||
errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto,
|
errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto,
|
||||||
None,
|
None);
|
||||||
None,
|
|
||||||
FormatMode::EnvironmentSelected);
|
|
||||||
let handler = errors::Handler::with_emitter(true, false, Box::new(emitter));
|
let handler = errors::Handler::with_emitter(true, false, Box::new(emitter));
|
||||||
handler.emit(&MultiSpan::new(),
|
handler.emit(&MultiSpan::new(),
|
||||||
&abort_msg(err_count),
|
&abort_msg(err_count),
|
||||||
|
@ -381,10 +378,7 @@ fn check_cfg(sopts: &config::Options,
|
||||||
output: ErrorOutputType) {
|
output: ErrorOutputType) {
|
||||||
let emitter: Box<Emitter> = match output {
|
let emitter: Box<Emitter> = match output {
|
||||||
config::ErrorOutputType::HumanReadable(color_config) => {
|
config::ErrorOutputType::HumanReadable(color_config) => {
|
||||||
Box::new(errors::emitter::EmitterWriter::stderr(color_config,
|
Box::new(errors::emitter::EmitterWriter::stderr(color_config, None))
|
||||||
None,
|
|
||||||
None,
|
|
||||||
FormatMode::EnvironmentSelected))
|
|
||||||
}
|
}
|
||||||
config::ErrorOutputType::Json => Box::new(json::JsonEmitter::basic()),
|
config::ErrorOutputType::Json => Box::new(json::JsonEmitter::basic()),
|
||||||
};
|
};
|
||||||
|
@ -1050,10 +1044,7 @@ pub fn monitor<F: FnOnce() + Send + 'static>(f: F) {
|
||||||
// Thread panicked without emitting a fatal diagnostic
|
// Thread panicked without emitting a fatal diagnostic
|
||||||
if !value.is::<errors::FatalError>() {
|
if !value.is::<errors::FatalError>() {
|
||||||
let emitter =
|
let emitter =
|
||||||
Box::new(errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto,
|
Box::new(errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto, None));
|
||||||
None,
|
|
||||||
None,
|
|
||||||
FormatMode::EnvironmentSelected));
|
|
||||||
let handler = errors::Handler::with_emitter(true, false, emitter);
|
let handler = errors::Handler::with_emitter(true, false, emitter);
|
||||||
|
|
||||||
// a .span_bug or .bug call has already printed what
|
// a .span_bug or .bug call has already printed what
|
||||||
|
|
|
@ -10,16 +10,13 @@
|
||||||
|
|
||||||
use self::Destination::*;
|
use self::Destination::*;
|
||||||
|
|
||||||
use syntax_pos::{COMMAND_LINE_SP, DUMMY_SP, FileMap, Span, MultiSpan, LineInfo, CharPos};
|
use syntax_pos::{COMMAND_LINE_SP, DUMMY_SP, FileMap, Span, MultiSpan, CharPos};
|
||||||
use registry;
|
|
||||||
|
|
||||||
use check_old_school;
|
|
||||||
use {Level, CodeSuggestion, DiagnosticBuilder, CodeMapper};
|
use {Level, CodeSuggestion, DiagnosticBuilder, CodeMapper};
|
||||||
use RenderSpan::*;
|
use RenderSpan::*;
|
||||||
use snippet::{StyledString, Style, FormatMode, Annotation, Line};
|
use snippet::{StyledString, Style, Annotation, Line};
|
||||||
use styled_buffer::StyledBuffer;
|
use styled_buffer::StyledBuffer;
|
||||||
|
|
||||||
use std::cmp;
|
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
@ -33,18 +30,7 @@ pub trait Emitter {
|
||||||
|
|
||||||
impl Emitter for EmitterWriter {
|
impl Emitter for EmitterWriter {
|
||||||
fn emit(&mut self, db: &DiagnosticBuilder) {
|
fn emit(&mut self, db: &DiagnosticBuilder) {
|
||||||
// Pick old school mode either from env or let the test dictate the format
|
self.emit_messages_default(db);
|
||||||
let old_school = match self.format_mode {
|
|
||||||
FormatMode::NewErrorFormat => false,
|
|
||||||
FormatMode::OriginalErrorFormat => true,
|
|
||||||
FormatMode::EnvironmentSelected => check_old_school()
|
|
||||||
};
|
|
||||||
|
|
||||||
if old_school {
|
|
||||||
self.emit_messages_old_school(db);
|
|
||||||
} else {
|
|
||||||
self.emit_messages_default(db);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,11 +56,7 @@ impl ColorConfig {
|
||||||
|
|
||||||
pub struct EmitterWriter {
|
pub struct EmitterWriter {
|
||||||
dst: Destination,
|
dst: Destination,
|
||||||
registry: Option<registry::Registry>,
|
|
||||||
cm: Option<Rc<CodeMapper>>,
|
cm: Option<Rc<CodeMapper>>,
|
||||||
|
|
||||||
// For now, allow an old-school mode while we transition
|
|
||||||
format_mode: FormatMode
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FileWithAnnotatedLines {
|
struct FileWithAnnotatedLines {
|
||||||
|
@ -99,33 +81,23 @@ macro_rules! println_maybe_styled {
|
||||||
|
|
||||||
impl EmitterWriter {
|
impl EmitterWriter {
|
||||||
pub fn stderr(color_config: ColorConfig,
|
pub fn stderr(color_config: ColorConfig,
|
||||||
registry: Option<registry::Registry>,
|
code_map: Option<Rc<CodeMapper>>)
|
||||||
code_map: Option<Rc<CodeMapper>>,
|
|
||||||
format_mode: FormatMode)
|
|
||||||
-> EmitterWriter {
|
-> EmitterWriter {
|
||||||
if color_config.use_color() {
|
if color_config.use_color() {
|
||||||
let dst = Destination::from_stderr();
|
let dst = Destination::from_stderr();
|
||||||
EmitterWriter { dst: dst,
|
EmitterWriter { dst: dst,
|
||||||
registry: registry,
|
cm: code_map}
|
||||||
cm: code_map,
|
|
||||||
format_mode: format_mode.clone() }
|
|
||||||
} else {
|
} else {
|
||||||
EmitterWriter { dst: Raw(Box::new(io::stderr())),
|
EmitterWriter { dst: Raw(Box::new(io::stderr())),
|
||||||
registry: registry,
|
cm: code_map}
|
||||||
cm: code_map,
|
|
||||||
format_mode: format_mode.clone() }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(dst: Box<Write + Send>,
|
pub fn new(dst: Box<Write + Send>,
|
||||||
registry: Option<registry::Registry>,
|
code_map: Option<Rc<CodeMapper>>)
|
||||||
code_map: Option<Rc<CodeMapper>>,
|
|
||||||
format_mode: FormatMode)
|
|
||||||
-> EmitterWriter {
|
-> EmitterWriter {
|
||||||
EmitterWriter { dst: Raw(dst),
|
EmitterWriter { dst: Raw(dst),
|
||||||
registry: registry,
|
cm: code_map}
|
||||||
cm: code_map,
|
|
||||||
format_mode: format_mode.clone() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn preprocess_annotations(&self, msp: &MultiSpan) -> Vec<FileWithAnnotatedLines> {
|
fn preprocess_annotations(&self, msp: &MultiSpan) -> Vec<FileWithAnnotatedLines> {
|
||||||
|
@ -668,240 +640,6 @@ impl EmitterWriter {
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn emit_message_old_school(&mut self,
|
|
||||||
msp: &MultiSpan,
|
|
||||||
msg: &str,
|
|
||||||
code: &Option<String>,
|
|
||||||
level: &Level,
|
|
||||||
show_snippet: bool)
|
|
||||||
-> io::Result<()> {
|
|
||||||
let mut buffer = StyledBuffer::new();
|
|
||||||
|
|
||||||
let loc = match msp.primary_span() {
|
|
||||||
Some(COMMAND_LINE_SP) | Some(DUMMY_SP) => "".to_string(),
|
|
||||||
Some(ps) => if let Some(ref cm) = self.cm {
|
|
||||||
cm.span_to_string(ps)
|
|
||||||
} else {
|
|
||||||
"".to_string()
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
"".to_string()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if loc != "" {
|
|
||||||
buffer.append(0, &loc, Style::NoStyle);
|
|
||||||
buffer.append(0, " ", Style::NoStyle);
|
|
||||||
}
|
|
||||||
buffer.append(0, &level.to_string(), Style::Level(level.clone()));
|
|
||||||
buffer.append(0, ": ", Style::HeaderMsg);
|
|
||||||
buffer.append(0, msg, Style::HeaderMsg);
|
|
||||||
buffer.append(0, " ", Style::NoStyle);
|
|
||||||
match code {
|
|
||||||
&Some(ref code) => {
|
|
||||||
buffer.append(0, "[", Style::ErrorCode);
|
|
||||||
buffer.append(0, &code, Style::ErrorCode);
|
|
||||||
buffer.append(0, "]", Style::ErrorCode);
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !show_snippet {
|
|
||||||
emit_to_destination(&buffer.render(), level, &mut self.dst)?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Watch out for various nasty special spans; don't try to
|
|
||||||
// print any filename or anything for those.
|
|
||||||
match msp.primary_span() {
|
|
||||||
Some(COMMAND_LINE_SP) | Some(DUMMY_SP) => {
|
|
||||||
emit_to_destination(&buffer.render(), level, &mut self.dst)?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
_ => { }
|
|
||||||
}
|
|
||||||
|
|
||||||
let annotated_files = self.preprocess_annotations(msp);
|
|
||||||
|
|
||||||
if let (Some(ref cm), Some(ann_file), Some(ref primary_span)) =
|
|
||||||
(self.cm.as_ref(), annotated_files.first(), msp.primary_span().as_ref()) {
|
|
||||||
|
|
||||||
// Next, print the source line and its squiggle
|
|
||||||
// for old school mode, we will render them to the buffer, then insert the file loc
|
|
||||||
// (or space the same amount) in front of the line and the squiggle
|
|
||||||
let source_string = ann_file.file.get_line(ann_file.lines[0].line_index - 1)
|
|
||||||
.unwrap_or("");
|
|
||||||
|
|
||||||
let line_offset = buffer.num_lines();
|
|
||||||
|
|
||||||
let lo = cm.lookup_char_pos(primary_span.lo);
|
|
||||||
//Before each secondary line in old skool-mode, print the label
|
|
||||||
//as an old-style note
|
|
||||||
let file_pos = format!("{}:{} ", lo.file.name.clone(), lo.line);
|
|
||||||
let file_pos_len = file_pos.len();
|
|
||||||
|
|
||||||
// First create the source line we will highlight.
|
|
||||||
buffer.puts(line_offset, 0, &file_pos, Style::FileNameStyle);
|
|
||||||
buffer.puts(line_offset, file_pos_len, &source_string, Style::Quotation);
|
|
||||||
// Sort the annotations by (start, end col)
|
|
||||||
let annotations = ann_file.lines[0].annotations.clone();
|
|
||||||
|
|
||||||
// Next, create the highlight line.
|
|
||||||
for annotation in &annotations {
|
|
||||||
for p in annotation.start_col..annotation.end_col {
|
|
||||||
if p == annotation.start_col {
|
|
||||||
buffer.putc(line_offset + 1,
|
|
||||||
file_pos_len + p,
|
|
||||||
'^',
|
|
||||||
if annotation.is_primary {
|
|
||||||
Style::UnderlinePrimary
|
|
||||||
} else {
|
|
||||||
Style::OldSchoolNote
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
buffer.putc(line_offset + 1,
|
|
||||||
file_pos_len + p,
|
|
||||||
'~',
|
|
||||||
if annotation.is_primary {
|
|
||||||
Style::UnderlinePrimary
|
|
||||||
} else {
|
|
||||||
Style::OldSchoolNote
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(ref primary_span) = msp.primary_span().as_ref() {
|
|
||||||
self.render_macro_backtrace_old_school(primary_span, &mut buffer)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
match code {
|
|
||||||
&Some(ref code) if self.registry.as_ref()
|
|
||||||
.and_then(|registry| registry.find_description(code))
|
|
||||||
.is_some() => {
|
|
||||||
let msg = "run `rustc --explain ".to_string() + &code.to_string() +
|
|
||||||
"` to see a detailed explanation";
|
|
||||||
|
|
||||||
let line_offset = buffer.num_lines();
|
|
||||||
buffer.append(line_offset, &loc, Style::NoStyle);
|
|
||||||
buffer.append(line_offset, " ", Style::NoStyle);
|
|
||||||
buffer.append(line_offset, &Level::Help.to_string(), Style::Level(Level::Help));
|
|
||||||
buffer.append(line_offset, ": ", Style::HeaderMsg);
|
|
||||||
buffer.append(line_offset, &msg, Style::HeaderMsg);
|
|
||||||
}
|
|
||||||
_ => ()
|
|
||||||
}
|
|
||||||
|
|
||||||
// final step: take our styled buffer, render it, then output it
|
|
||||||
emit_to_destination(&buffer.render(), level, &mut self.dst)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
fn emit_suggestion_old_school(&mut self,
|
|
||||||
suggestion: &CodeSuggestion,
|
|
||||||
level: &Level,
|
|
||||||
msg: &str)
|
|
||||||
-> io::Result<()> {
|
|
||||||
use std::borrow::Borrow;
|
|
||||||
|
|
||||||
let primary_span = suggestion.msp.primary_span().unwrap();
|
|
||||||
if let Some(ref cm) = self.cm {
|
|
||||||
let mut buffer = StyledBuffer::new();
|
|
||||||
|
|
||||||
let loc = cm.span_to_string(primary_span);
|
|
||||||
|
|
||||||
if loc != "" {
|
|
||||||
buffer.append(0, &loc, Style::NoStyle);
|
|
||||||
buffer.append(0, " ", Style::NoStyle);
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer.append(0, &level.to_string(), Style::Level(level.clone()));
|
|
||||||
buffer.append(0, ": ", Style::HeaderMsg);
|
|
||||||
buffer.append(0, msg, Style::HeaderMsg);
|
|
||||||
|
|
||||||
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();
|
|
||||||
let mut row_num = 1;
|
|
||||||
for line in lines.by_ref().take(MAX_HIGHLIGHT_LINES) {
|
|
||||||
buffer.append(row_num, &fm.name, Style::FileNameStyle);
|
|
||||||
for _ in 0..max_digits+2 {
|
|
||||||
buffer.append(row_num, &" ", Style::NoStyle);
|
|
||||||
}
|
|
||||||
buffer.append(row_num, line, Style::NoStyle);
|
|
||||||
row_num += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we elided some lines, add an ellipsis
|
|
||||||
if let Some(_) = lines.next() {
|
|
||||||
buffer.append(row_num, "...", Style::NoStyle);
|
|
||||||
}
|
|
||||||
emit_to_destination(&buffer.render(), level, &mut self.dst)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn emit_messages_old_school(&mut self, db: &DiagnosticBuilder) {
|
|
||||||
match self.emit_message_old_school(&db.span,
|
|
||||||
&db.message,
|
|
||||||
&db.code,
|
|
||||||
&db.level,
|
|
||||||
true) {
|
|
||||||
Ok(()) => {
|
|
||||||
for child in &db.children {
|
|
||||||
let (span, show_snippet) = if child.span.primary_spans().is_empty() {
|
|
||||||
(db.span.clone(), false)
|
|
||||||
} else {
|
|
||||||
(child.span.clone(), true)
|
|
||||||
};
|
|
||||||
|
|
||||||
match child.render_span {
|
|
||||||
Some(FullSpan(_)) => {
|
|
||||||
match self.emit_message_old_school(&span,
|
|
||||||
&child.message,
|
|
||||||
&None,
|
|
||||||
&child.level,
|
|
||||||
show_snippet) {
|
|
||||||
Err(e) => panic!("failed to emit error: {}", e),
|
|
||||||
_ => ()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Some(Suggestion(ref cs)) => {
|
|
||||||
match self.emit_suggestion_old_school(cs,
|
|
||||||
&child.level,
|
|
||||||
&child.message) {
|
|
||||||
Err(e) => panic!("failed to emit error: {}", e),
|
|
||||||
_ => ()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
match self.emit_message_old_school(&span,
|
|
||||||
&child.message,
|
|
||||||
&None,
|
|
||||||
&child.level,
|
|
||||||
show_snippet) {
|
|
||||||
Err(e) => panic!("failed to emit error: {}", e),
|
|
||||||
_ => ()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(e) => panic!("failed to emit error: {}", e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render_macro_backtrace_old_school(&mut self,
|
fn render_macro_backtrace_old_school(&mut self,
|
||||||
sp: &Span,
|
sp: &Span,
|
||||||
buffer: &mut StyledBuffer) -> io::Result<()> {
|
buffer: &mut StyledBuffer) -> io::Result<()> {
|
||||||
|
@ -958,16 +696,6 @@ fn emit_to_destination(rendered_buffer: &Vec<Vec<StyledString>>,
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn line_num_max_digits(line: &LineInfo) -> usize {
|
|
||||||
let mut max_line_num = line.line_index + 1;
|
|
||||||
let mut digits = 0;
|
|
||||||
while max_line_num > 0 {
|
|
||||||
max_line_num /= 10;
|
|
||||||
digits += 1;
|
|
||||||
}
|
|
||||||
digits
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
fn stderr_isatty() -> bool {
|
fn stderr_isatty() -> bool {
|
||||||
use libc;
|
use libc;
|
||||||
|
|
|
@ -420,13 +420,11 @@ pub struct Handler {
|
||||||
|
|
||||||
impl Handler {
|
impl Handler {
|
||||||
pub fn with_tty_emitter(color_config: ColorConfig,
|
pub fn with_tty_emitter(color_config: ColorConfig,
|
||||||
registry: Option<registry::Registry>,
|
|
||||||
can_emit_warnings: bool,
|
can_emit_warnings: bool,
|
||||||
treat_err_as_bug: bool,
|
treat_err_as_bug: bool,
|
||||||
cm: Option<Rc<CodeMapper>>)
|
cm: Option<Rc<CodeMapper>>)
|
||||||
-> Handler {
|
-> Handler {
|
||||||
let emitter = Box::new(EmitterWriter::stderr(color_config, registry, cm,
|
let emitter = Box::new(EmitterWriter::stderr(color_config, cm));
|
||||||
snippet::FormatMode::EnvironmentSelected));
|
|
||||||
Handler::with_emitter(can_emit_warnings, treat_err_as_bug, emitter)
|
Handler::with_emitter(can_emit_warnings, treat_err_as_bug, emitter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -750,21 +748,4 @@ pub fn expect<T, M>(diag: &Handler, opt: Option<T>, msg: M) -> T where
|
||||||
Some(t) => t,
|
Some(t) => t,
|
||||||
None => diag.bug(&msg()),
|
None => diag.bug(&msg()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// True if we should use the old-skool error format style. This is
|
|
||||||
/// the default setting until the new errors are deemed stable enough
|
|
||||||
/// for general use.
|
|
||||||
///
|
|
||||||
/// FIXME(#33240)
|
|
||||||
#[cfg(not(test))]
|
|
||||||
pub fn check_old_school() -> bool {
|
|
||||||
use std::env;
|
|
||||||
env::var("RUST_NEW_ERROR_FORMAT").is_err()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// For unit tests, use the new format.
|
|
||||||
#[cfg(test)]
|
|
||||||
pub fn check_old_school() -> bool {
|
|
||||||
false
|
|
||||||
}
|
|
|
@ -15,18 +15,10 @@ use CodeMapper;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use {Level};
|
use {Level};
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub enum FormatMode {
|
|
||||||
NewErrorFormat,
|
|
||||||
OriginalErrorFormat,
|
|
||||||
EnvironmentSelected
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SnippetData {
|
pub struct SnippetData {
|
||||||
codemap: Rc<CodeMapper>,
|
codemap: Rc<CodeMapper>,
|
||||||
files: Vec<FileInfo>,
|
files: Vec<FileInfo>
|
||||||
format_mode: FormatMode,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -41,10 +33,6 @@ pub struct FileInfo {
|
||||||
primary_span: Option<Span>,
|
primary_span: Option<Span>,
|
||||||
|
|
||||||
lines: Vec<Line>,
|
lines: Vec<Line>,
|
||||||
|
|
||||||
/// The type of error format to render. We keep it here so that
|
|
||||||
/// it's easy to configure for both tests and regular usage
|
|
||||||
format_mode: FormatMode,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
|
||||||
|
|
|
@ -128,7 +128,6 @@ pub fn run_core(search_paths: SearchPaths,
|
||||||
|
|
||||||
let codemap = Rc::new(codemap::CodeMap::new());
|
let codemap = Rc::new(codemap::CodeMap::new());
|
||||||
let diagnostic_handler = errors::Handler::with_tty_emitter(ColorConfig::Auto,
|
let diagnostic_handler = errors::Handler::with_tty_emitter(ColorConfig::Auto,
|
||||||
None,
|
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
Some(codemap.clone()));
|
Some(codemap.clone()));
|
||||||
|
|
|
@ -74,7 +74,6 @@ pub fn run(input: &str,
|
||||||
|
|
||||||
let codemap = Rc::new(CodeMap::new());
|
let codemap = Rc::new(CodeMap::new());
|
||||||
let diagnostic_handler = errors::Handler::with_tty_emitter(ColorConfig::Auto,
|
let diagnostic_handler = errors::Handler::with_tty_emitter(ColorConfig::Auto,
|
||||||
None,
|
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
Some(codemap.clone()));
|
Some(codemap.clone()));
|
||||||
|
@ -228,9 +227,7 @@ fn runtest(test: &str, cratename: &str, cfgs: Vec<String>, libs: SearchPaths,
|
||||||
let data = Arc::new(Mutex::new(Vec::new()));
|
let data = Arc::new(Mutex::new(Vec::new()));
|
||||||
let codemap = Rc::new(CodeMap::new());
|
let codemap = Rc::new(CodeMap::new());
|
||||||
let emitter = errors::emitter::EmitterWriter::new(box Sink(data.clone()),
|
let emitter = errors::emitter::EmitterWriter::new(box Sink(data.clone()),
|
||||||
None,
|
Some(codemap.clone()));
|
||||||
Some(codemap.clone()),
|
|
||||||
errors::snippet::FormatMode::EnvironmentSelected);
|
|
||||||
let old = io::set_panic(box Sink(data.clone()));
|
let old = io::set_panic(box Sink(data.clone()));
|
||||||
let _bomb = Bomb(data.clone(), old.unwrap_or(box io::stdout()));
|
let _bomb = Bomb(data.clone(), old.unwrap_or(box io::stdout()));
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,6 @@ impl ParseSess {
|
||||||
pub fn new() -> ParseSess {
|
pub fn new() -> ParseSess {
|
||||||
let cm = Rc::new(CodeMap::new());
|
let cm = Rc::new(CodeMap::new());
|
||||||
let handler = Handler::with_tty_emitter(ColorConfig::Auto,
|
let handler = Handler::with_tty_emitter(ColorConfig::Auto,
|
||||||
None,
|
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
Some(cm.clone()));
|
Some(cm.clone()));
|
||||||
|
|
|
@ -2,4 +2,4 @@
|
||||||
|
|
||||||
all:
|
all:
|
||||||
$(RUSTC) foo.rs --crate-type staticlib
|
$(RUSTC) foo.rs --crate-type staticlib
|
||||||
$(RUSTC) bar.rs 2>&1 | grep "error: found staticlib"
|
$(RUSTC) bar.rs 2>&1 | grep "found staticlib"
|
||||||
|
|
|
@ -27,7 +27,7 @@ all:
|
||||||
mv $(TMPDIR)/$(call RLIB_GLOB,crateA) $(A3)
|
mv $(TMPDIR)/$(call RLIB_GLOB,crateA) $(A3)
|
||||||
# Ensure crateC fails to compile since A1 is "missing" and A2/A3 hashes do not match
|
# Ensure crateC fails to compile since A1 is "missing" and A2/A3 hashes do not match
|
||||||
$(RUSTC) -L $(A2) -L $(A3) crateC.rs >$(LOG) 2>&1 || true
|
$(RUSTC) -L $(A2) -L $(A3) crateC.rs >$(LOG) 2>&1 || true
|
||||||
grep "error: found possibly newer version of crate \`crateA\` which \`crateB\` depends on" $(LOG)
|
grep "found possibly newer version of crate \`crateA\` which \`crateB\` depends on" $(LOG)
|
||||||
grep "note: perhaps that crate needs to be recompiled?" $(LOG)
|
grep "note: perhaps that crate needs to be recompiled?" $(LOG)
|
||||||
grep "note: crate \`crateA\` path #1:" $(LOG)
|
grep "note: crate \`crateA\` path #1:" $(LOG)
|
||||||
grep "note: crate \`crateA\` path #2:" $(LOG)
|
grep "note: crate \`crateA\` path #2:" $(LOG)
|
||||||
|
|
|
@ -6,4 +6,4 @@ all:
|
||||||
$(call REMOVE_RLIBS,crateA)
|
$(call REMOVE_RLIBS,crateA)
|
||||||
# Ensure crateC fails to compile since dependency crateA is missing
|
# Ensure crateC fails to compile since dependency crateA is missing
|
||||||
$(RUSTC) crateC.rs 2>&1 | \
|
$(RUSTC) crateC.rs 2>&1 | \
|
||||||
grep "error: can't find crate for \`crateA\` which \`crateB\` depends on"
|
grep "can't find crate for \`crateA\` which \`crateB\` depends on"
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
-include ../tools.mk
|
|
||||||
|
|
||||||
# This test attempts to run rustc itself from the compiled binary; but
|
|
||||||
# that means that you need to set the LD_LIBRARY_PATH for rustc itself
|
|
||||||
# while running multiple_files, and that won't work for stage1.
|
|
||||||
|
|
||||||
# FIXME ignore windows
|
|
||||||
ifndef IS_WINDOWS
|
|
||||||
ifeq ($(RUST_BUILD_STAGE),1)
|
|
||||||
DOTEST=
|
|
||||||
else
|
|
||||||
DOTEST=dotest
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
all: $(DOTEST)
|
|
||||||
|
|
||||||
dotest:
|
|
||||||
# check that we don't ICE on unicode input, issue #11178
|
|
||||||
$(RUSTC) multiple_files.rs
|
|
||||||
$(call RUN,multiple_files) "$(RUSTC)" "$(TMPDIR)"
|
|
||||||
|
|
||||||
# check that our multibyte-ident spans are (approximately) the
|
|
||||||
# correct length. issue #8706
|
|
||||||
$(RUSTC) span_length.rs
|
|
||||||
$(call RUN,span_length) "$(RUSTC)" "$(TMPDIR)"
|
|
|
@ -1,74 +0,0 @@
|
||||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
|
||||||
// file at the top-level directory of this distribution and at
|
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
||||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
||||||
// option. This file may not be copied, modified, or distributed
|
|
||||||
// except according to those terms.
|
|
||||||
|
|
||||||
#![feature(rand)]
|
|
||||||
|
|
||||||
use std::fs::File;
|
|
||||||
use std::io::prelude::*;
|
|
||||||
use std::path::Path;
|
|
||||||
use std::process::Command;
|
|
||||||
use std::__rand::{thread_rng, Rng};
|
|
||||||
use std::{char, env};
|
|
||||||
|
|
||||||
// creates unicode_input_multiple_files_{main,chars}.rs, where the
|
|
||||||
// former imports the latter. `_chars` just contains an identifier
|
|
||||||
// made up of random characters, because will emit an error message
|
|
||||||
// about the ident being in the wrong place, with a span (and creating
|
|
||||||
// this span used to upset the compiler).
|
|
||||||
|
|
||||||
fn random_char() -> char {
|
|
||||||
let mut rng = thread_rng();
|
|
||||||
// a subset of the XID_start Unicode table (ensuring that the
|
|
||||||
// compiler doesn't fail with an "unrecognised token" error)
|
|
||||||
let (lo, hi): (u32, u32) = match rng.gen_range(1u32, 4u32 + 1) {
|
|
||||||
1 => (0x41, 0x5a),
|
|
||||||
2 => (0xf8, 0x1ba),
|
|
||||||
3 => (0x1401, 0x166c),
|
|
||||||
_ => (0x10400, 0x1044f)
|
|
||||||
};
|
|
||||||
|
|
||||||
char::from_u32(rng.gen_range(lo, hi + 1)).unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let args: Vec<String> = env::args().collect();
|
|
||||||
let rustc = &args[1];
|
|
||||||
let tmpdir = Path::new(&args[2]);
|
|
||||||
|
|
||||||
let main_file = tmpdir.join("unicode_input_multiple_files_main.rs");
|
|
||||||
{
|
|
||||||
let _ = File::create(&main_file).unwrap()
|
|
||||||
.write_all(b"mod unicode_input_multiple_files_chars;").unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
for _ in 0..100 {
|
|
||||||
{
|
|
||||||
let randoms = tmpdir.join("unicode_input_multiple_files_chars.rs");
|
|
||||||
let mut w = File::create(&randoms).unwrap();
|
|
||||||
for _ in 0..30 {
|
|
||||||
write!(&mut w, "{}", random_char()).unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// rustc is passed to us with --out-dir and -L etc., so we
|
|
||||||
// can't exec it directly
|
|
||||||
let result = Command::new("sh")
|
|
||||||
.arg("-c")
|
|
||||||
.arg(&format!("{} {}",
|
|
||||||
rustc,
|
|
||||||
main_file.display()))
|
|
||||||
.output().unwrap();
|
|
||||||
let err = String::from_utf8_lossy(&result.stderr);
|
|
||||||
|
|
||||||
// positive test so that this test will be updated when the
|
|
||||||
// compiler changes.
|
|
||||||
assert!(err.contains("expected item, found"))
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,130 +0,0 @@
|
||||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
|
||||||
// file at the top-level directory of this distribution and at
|
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
||||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
||||||
// option. This file may not be copied, modified, or distributed
|
|
||||||
// except according to those terms.
|
|
||||||
|
|
||||||
#![feature(rand)]
|
|
||||||
|
|
||||||
use std::fs::File;
|
|
||||||
use std::io::prelude::*;
|
|
||||||
use std::iter::repeat;
|
|
||||||
use std::path::Path;
|
|
||||||
use std::process::Command;
|
|
||||||
use std::__rand::{thread_rng, Rng};
|
|
||||||
use std::{char, env};
|
|
||||||
|
|
||||||
pub fn check_old_skool() -> bool {
|
|
||||||
use std::env;
|
|
||||||
env::var("RUST_NEW_ERROR_FORMAT").is_err()
|
|
||||||
}
|
|
||||||
|
|
||||||
// creates a file with `fn main() { <random ident> }` and checks the
|
|
||||||
// compiler emits a span of the appropriate length (for the
|
|
||||||
// "unresolved name" message); currently just using the number of code
|
|
||||||
// points, but should be the number of graphemes (FIXME #7043)
|
|
||||||
|
|
||||||
fn random_char() -> char {
|
|
||||||
let mut rng = thread_rng();
|
|
||||||
// a subset of the XID_start Unicode table (ensuring that the
|
|
||||||
// compiler doesn't fail with an "unrecognised token" error)
|
|
||||||
let (lo, hi): (u32, u32) = match rng.gen_range(1u32, 4u32 + 1) {
|
|
||||||
1 => (0x41, 0x5a),
|
|
||||||
2 => (0xf8, 0x1ba),
|
|
||||||
3 => (0x1401, 0x166c),
|
|
||||||
_ => (0x10400, 0x1044f)
|
|
||||||
};
|
|
||||||
|
|
||||||
char::from_u32(rng.gen_range(lo, hi + 1)).unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let args: Vec<String> = env::args().collect();
|
|
||||||
let rustc = &args[1];
|
|
||||||
let tmpdir = Path::new(&args[2]);
|
|
||||||
let main_file = tmpdir.join("span_main.rs");
|
|
||||||
|
|
||||||
for _ in 0..100 {
|
|
||||||
let n = thread_rng().gen_range(3, 20);
|
|
||||||
|
|
||||||
{
|
|
||||||
let _ = write!(&mut File::create(&main_file).unwrap(),
|
|
||||||
"#![feature(non_ascii_idents)] fn main() {{ {} }}",
|
|
||||||
// random string of length n
|
|
||||||
(0..n).map(|_| random_char()).collect::<String>());
|
|
||||||
}
|
|
||||||
|
|
||||||
// rustc is passed to us with --out-dir and -L etc., so we
|
|
||||||
// can't exec it directly
|
|
||||||
let result = Command::new("sh")
|
|
||||||
.arg("-c")
|
|
||||||
.arg(&format!("{} {}",
|
|
||||||
rustc,
|
|
||||||
main_file.to_str()
|
|
||||||
.unwrap()))
|
|
||||||
.output().unwrap();
|
|
||||||
|
|
||||||
let err = String::from_utf8_lossy(&result.stderr);
|
|
||||||
|
|
||||||
if check_old_skool() {
|
|
||||||
// the span should end the line (e.g no extra ~'s)
|
|
||||||
let expected_span = format!("^{}\n", repeat("~").take(n - 1)
|
|
||||||
.collect::<String>());
|
|
||||||
assert!(err.contains(&expected_span));
|
|
||||||
} else {
|
|
||||||
// the span should end the line (e.g no extra ~'s)
|
|
||||||
let expected_span = format!("^{}\n", repeat("^").take(n - 1)
|
|
||||||
.collect::<String>());
|
|
||||||
assert!(err.contains(&expected_span));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test multi-column characters and tabs
|
|
||||||
{
|
|
||||||
let _ = write!(&mut File::create(&main_file).unwrap(),
|
|
||||||
r#"extern "路濫狼á́́" fn foo() {{}} extern "路濫狼á́" fn bar() {{}}"#);
|
|
||||||
}
|
|
||||||
|
|
||||||
let result = Command::new("sh")
|
|
||||||
.arg("-c")
|
|
||||||
.arg(format!("{} {}",
|
|
||||||
rustc,
|
|
||||||
main_file.display()))
|
|
||||||
.output().unwrap();
|
|
||||||
|
|
||||||
let err = String::from_utf8_lossy(&result.stderr);
|
|
||||||
|
|
||||||
// Test both the length of the snake and the leading spaces up to it
|
|
||||||
|
|
||||||
if check_old_skool() {
|
|
||||||
// Extra characters. Every line is preceded by `filename:lineno <actual code>`
|
|
||||||
let offset = main_file.to_str().unwrap().len() + 3;
|
|
||||||
|
|
||||||
// First snake is 8 ~s long, with 7 preceding spaces (excluding file name/line offset)
|
|
||||||
let expected_span = format!("\n{}^{}\n",
|
|
||||||
repeat(" ").take(offset + 7).collect::<String>(),
|
|
||||||
repeat("~").take(8).collect::<String>());
|
|
||||||
assert!(err.contains(&expected_span));
|
|
||||||
// Second snake is only 7 ~s long, with 36 preceding spaces,
|
|
||||||
// because rustc counts chars() now rather than width(). This
|
|
||||||
// is because width() functions are to be removed from
|
|
||||||
// librustc_unicode
|
|
||||||
let expected_span = format!("\n{}^{}\n",
|
|
||||||
repeat(" ").take(offset + 36).collect::<String>(),
|
|
||||||
repeat("~").take(7).collect::<String>());
|
|
||||||
assert!(err.contains(&expected_span));
|
|
||||||
} else {
|
|
||||||
let expected_span = format!("\n |>{}{}\n",
|
|
||||||
repeat(" ").take(8).collect::<String>(),
|
|
||||||
repeat("^").take(9).collect::<String>());
|
|
||||||
assert!(err.contains(&expected_span));
|
|
||||||
let expected_span = format!("\n |>{}{}\n",
|
|
||||||
repeat(" ").take(37).collect::<String>(),
|
|
||||||
repeat("^").take(8).collect::<String>());
|
|
||||||
assert!(err.contains(&expected_span));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1330,9 +1330,7 @@ actual:\n\
|
||||||
// patterns still match the raw compiler output.
|
// patterns still match the raw compiler output.
|
||||||
if self.props.error_patterns.is_empty() {
|
if self.props.error_patterns.is_empty() {
|
||||||
args.extend(["--error-format",
|
args.extend(["--error-format",
|
||||||
"json",
|
"json"]
|
||||||
"-Z",
|
|
||||||
"unstable-options"]
|
|
||||||
.iter()
|
.iter()
|
||||||
.map(|s| s.to_string()));
|
.map(|s| s.to_string()));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue