Turn on new errors, json mode. Remove duplicate unicode test

This commit is contained in:
Jonathan Turner 2016-08-05 15:58:31 -07:00
parent 42903d9a8f
commit fad4f32c31
18 changed files with 29 additions and 595 deletions

View File

@ -94,7 +94,7 @@ use syntax::ast;
use syntax::parse::token;
use syntax::ptr::P;
use syntax_pos::{self, Pos, Span};
use errors::{DiagnosticBuilder, check_old_school};
use errors::DiagnosticBuilder;
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
pub fn note_and_explain_region(self,
@ -541,25 +541,19 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
let span = origin.span();
let mut is_simple_error = false;
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()
} else {
false
};
if !is_simple_error || check_old_school() {
if !is_simple_error {
diag.note_expected_found(&"type", &expected, &found);
}
}
if !is_simple_error && check_old_school() {
diag.span_note(span, &format!("{}", terr));
} else {
diag.span_label(span, &terr);
}
diag.span_label(span, &terr);
self.note_error_origin(diag, &origin);
self.check_and_note_conflicting_crates(diag, terr, span);

View File

@ -1055,7 +1055,7 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
"NAME=PATH"),
opt::opt_s("", "sysroot", "Override the system root", "PATH"),
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",
"human|json"),
opt::opt_s("", "color", "Configure coloring of output:

View File

@ -23,7 +23,6 @@ use mir::transform as mir_pass;
use syntax::ast::{NodeId, Name};
use errors::{self, DiagnosticBuilder};
use errors::emitter::{Emitter, EmitterWriter};
use errors::snippet::FormatMode;
use syntax::json::JsonEmitter;
use syntax::feature_gate;
use syntax::parse;
@ -369,9 +368,7 @@ pub fn build_session_with_codemap(sopts: config::Options,
let emitter: Box<Emitter> = match sopts.error_format {
config::ErrorOutputType::HumanReadable(color_config) => {
Box::new(EmitterWriter::stderr(color_config,
Some(registry),
Some(codemap.clone()),
errors::snippet::FormatMode::EnvironmentSelected))
Some(codemap.clone())))
}
config::ErrorOutputType::Json => {
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 {
config::ErrorOutputType::HumanReadable(color_config) => {
Box::new(EmitterWriter::stderr(color_config,
None,
None,
FormatMode::EnvironmentSelected))
None))
}
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 {
config::ErrorOutputType::HumanReadable(color_config) => {
Box::new(EmitterWriter::stderr(color_config,
None,
None,
FormatMode::EnvironmentSelected))
None))
}
config::ErrorOutputType::Json => Box::new(JsonEmitter::basic()),
};

View File

@ -44,7 +44,7 @@ use std::cmp::Ordering;
use std::collections::hash_map::Entry::Vacant;
use rustc_const_math::*;
use rustc_errors::{DiagnosticBuilder, check_old_school};
use rustc_errors::DiagnosticBuilder;
macro_rules! math {
($e:expr, $op:expr) => {
@ -378,11 +378,7 @@ pub fn note_const_eval_err<'a, 'tcx>(
{
match err.description() {
ConstEvalErrDescription::Simple(message) => {
if check_old_school() {
diag.note(&message);
} else {
diag.span_label(err.span, &message);
}
diag.span_label(err.span, &message);
}
}

View File

@ -100,7 +100,6 @@ 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;
@ -141,9 +140,7 @@ pub fn run(args: Vec<String>) -> isize {
None => {
let emitter =
errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto,
None,
None,
FormatMode::EnvironmentSelected);
None);
let handler = errors::Handler::with_emitter(true, false, Box::new(emitter));
handler.emit(&MultiSpan::new(),
&abort_msg(err_count),
@ -381,10 +378,7 @@ fn check_cfg(sopts: &config::Options,
output: ErrorOutputType) {
let emitter: Box<Emitter> = match output {
config::ErrorOutputType::HumanReadable(color_config) => {
Box::new(errors::emitter::EmitterWriter::stderr(color_config,
None,
None,
FormatMode::EnvironmentSelected))
Box::new(errors::emitter::EmitterWriter::stderr(color_config, None))
}
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
if !value.is::<errors::FatalError>() {
let emitter =
Box::new(errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto,
None,
None,
FormatMode::EnvironmentSelected));
Box::new(errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto, None));
let handler = errors::Handler::with_emitter(true, false, emitter);
// a .span_bug or .bug call has already printed what

View File

@ -10,16 +10,13 @@
use self::Destination::*;
use syntax_pos::{COMMAND_LINE_SP, DUMMY_SP, FileMap, Span, MultiSpan, LineInfo, CharPos};
use registry;
use syntax_pos::{COMMAND_LINE_SP, DUMMY_SP, FileMap, Span, MultiSpan, CharPos};
use check_old_school;
use {Level, CodeSuggestion, DiagnosticBuilder, CodeMapper};
use RenderSpan::*;
use snippet::{StyledString, Style, FormatMode, Annotation, Line};
use snippet::{StyledString, Style, Annotation, Line};
use styled_buffer::StyledBuffer;
use std::cmp;
use std::io::prelude::*;
use std::io;
use std::rc::Rc;
@ -33,18 +30,7 @@ pub trait Emitter {
impl Emitter for EmitterWriter {
fn emit(&mut self, db: &DiagnosticBuilder) {
// Pick old school mode either from env or let the test dictate the format
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);
}
self.emit_messages_default(db);
}
}
@ -70,11 +56,7 @@ impl ColorConfig {
pub struct EmitterWriter {
dst: Destination,
registry: Option<registry::Registry>,
cm: Option<Rc<CodeMapper>>,
// For now, allow an old-school mode while we transition
format_mode: FormatMode
}
struct FileWithAnnotatedLines {
@ -99,33 +81,23 @@ macro_rules! println_maybe_styled {
impl EmitterWriter {
pub fn stderr(color_config: ColorConfig,
registry: Option<registry::Registry>,
code_map: Option<Rc<CodeMapper>>,
format_mode: FormatMode)
code_map: Option<Rc<CodeMapper>>)
-> EmitterWriter {
if color_config.use_color() {
let dst = Destination::from_stderr();
EmitterWriter { dst: dst,
registry: registry,
cm: code_map,
format_mode: format_mode.clone() }
cm: code_map}
} else {
EmitterWriter { dst: Raw(Box::new(io::stderr())),
registry: registry,
cm: code_map,
format_mode: format_mode.clone() }
cm: code_map}
}
}
pub fn new(dst: Box<Write + Send>,
registry: Option<registry::Registry>,
code_map: Option<Rc<CodeMapper>>,
format_mode: FormatMode)
code_map: Option<Rc<CodeMapper>>)
-> EmitterWriter {
EmitterWriter { dst: Raw(dst),
registry: registry,
cm: code_map,
format_mode: format_mode.clone() }
cm: code_map}
}
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,
sp: &Span,
buffer: &mut StyledBuffer) -> io::Result<()> {
@ -958,16 +696,6 @@ fn emit_to_destination(rendered_buffer: &Vec<Vec<StyledString>>,
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)]
fn stderr_isatty() -> bool {
use libc;

View File

@ -420,13 +420,11 @@ pub struct Handler {
impl Handler {
pub fn with_tty_emitter(color_config: ColorConfig,
registry: Option<registry::Registry>,
can_emit_warnings: bool,
treat_err_as_bug: bool,
cm: Option<Rc<CodeMapper>>)
-> Handler {
let emitter = Box::new(EmitterWriter::stderr(color_config, registry, cm,
snippet::FormatMode::EnvironmentSelected));
let emitter = Box::new(EmitterWriter::stderr(color_config, cm));
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,
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
}
}

View File

@ -15,18 +15,10 @@ use CodeMapper;
use std::rc::Rc;
use {Level};
#[derive(Clone)]
pub enum FormatMode {
NewErrorFormat,
OriginalErrorFormat,
EnvironmentSelected
}
#[derive(Clone)]
pub struct SnippetData {
codemap: Rc<CodeMapper>,
files: Vec<FileInfo>,
format_mode: FormatMode,
files: Vec<FileInfo>
}
#[derive(Clone)]
@ -41,10 +33,6 @@ pub struct FileInfo {
primary_span: Option<Span>,
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)]

View File

@ -128,7 +128,6 @@ pub fn run_core(search_paths: SearchPaths,
let codemap = Rc::new(codemap::CodeMap::new());
let diagnostic_handler = errors::Handler::with_tty_emitter(ColorConfig::Auto,
None,
true,
false,
Some(codemap.clone()));

View File

@ -74,7 +74,6 @@ pub fn run(input: &str,
let codemap = Rc::new(CodeMap::new());
let diagnostic_handler = errors::Handler::with_tty_emitter(ColorConfig::Auto,
None,
true,
false,
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 codemap = Rc::new(CodeMap::new());
let emitter = errors::emitter::EmitterWriter::new(box Sink(data.clone()),
None,
Some(codemap.clone()),
errors::snippet::FormatMode::EnvironmentSelected);
Some(codemap.clone()));
let old = io::set_panic(box Sink(data.clone()));
let _bomb = Bomb(data.clone(), old.unwrap_or(box io::stdout()));

View File

@ -51,7 +51,6 @@ impl ParseSess {
pub fn new() -> ParseSess {
let cm = Rc::new(CodeMap::new());
let handler = Handler::with_tty_emitter(ColorConfig::Auto,
None,
true,
false,
Some(cm.clone()));

View File

@ -2,4 +2,4 @@
all:
$(RUSTC) foo.rs --crate-type staticlib
$(RUSTC) bar.rs 2>&1 | grep "error: found staticlib"
$(RUSTC) bar.rs 2>&1 | grep "found staticlib"

View File

@ -27,7 +27,7 @@ all:
mv $(TMPDIR)/$(call RLIB_GLOB,crateA) $(A3)
# 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
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: crate \`crateA\` path #1:" $(LOG)
grep "note: crate \`crateA\` path #2:" $(LOG)

View File

@ -6,4 +6,4 @@ all:
$(call REMOVE_RLIBS,crateA)
# Ensure crateC fails to compile since dependency crateA is missing
$(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"

View File

@ -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)"

View File

@ -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"))
}
}

View File

@ -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));
}
}

View File

@ -1330,9 +1330,7 @@ actual:\n\
// patterns still match the raw compiler output.
if self.props.error_patterns.is_empty() {
args.extend(["--error-format",
"json",
"-Z",
"unstable-options"]
"json"]
.iter()
.map(|s| s.to_string()));
}