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,
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);
"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:
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;
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()))
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()),
};
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()),
};
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) => {
{
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);
}
}
use syntax::parse::{self, PResult};
use syntax_pos::MultiSpan;
use errors::emitter::Emitter;
-use errors::snippet::FormatMode;
#[cfg(test)]
pub mod test;
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),
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()),
};
// 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
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;
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);
}
}
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 {
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> {
_ => ()
}
}
- 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<()> {
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;
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)
}
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
-}
+}
\ No newline at end of file
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)]
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)]
let codemap = Rc::new(codemap::CodeMap::new());
let diagnostic_handler = errors::Handler::with_tty_emitter(ColorConfig::Auto,
- None,
true,
false,
Some(codemap.clone()));
let codemap = Rc::new(CodeMap::new());
let diagnostic_handler = errors::Handler::with_tty_emitter(ColorConfig::Auto,
- None,
true,
false,
Some(codemap.clone()));
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()));
pub fn new() -> ParseSess {
let cm = Rc::new(CodeMap::new());
let handler = Handler::with_tty_emitter(ColorConfig::Auto,
- None,
true,
false,
Some(cm.clone()));
all:
$(RUSTC) foo.rs --crate-type staticlib
- $(RUSTC) bar.rs 2>&1 | grep "error: found staticlib"
+ $(RUSTC) bar.rs 2>&1 | grep "found staticlib"
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)
$(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"
+++ /dev/null
--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)"
+++ /dev/null
-// 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"))
- }
-}
+++ /dev/null
-// 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));
- }
-}
// 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()));
}