Auto merge of #63402 - estebank:strip-margin, r=oli-obk
Strip code to the left and right in diagnostics for long lines Fix #62999.
This commit is contained in:
commit
19a38de68a
26 changed files with 580 additions and 156 deletions
12
Cargo.lock
12
Cargo.lock
|
@ -3232,6 +3232,7 @@ dependencies = [
|
||||||
"rustc_data_structures",
|
"rustc_data_structures",
|
||||||
"serialize",
|
"serialize",
|
||||||
"syntax_pos",
|
"syntax_pos",
|
||||||
|
"term_size",
|
||||||
"termcolor",
|
"termcolor",
|
||||||
"unicode-width",
|
"unicode-width",
|
||||||
]
|
]
|
||||||
|
@ -4107,6 +4108,17 @@ dependencies = [
|
||||||
"winapi 0.3.6",
|
"winapi 0.3.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "term_size"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9e5b9a66db815dcfd2da92db471106457082577c3c278d4138ab3e3b4e189327"
|
||||||
|
dependencies = [
|
||||||
|
"kernel32-sys",
|
||||||
|
"libc",
|
||||||
|
"winapi 0.2.8",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "termcolor"
|
name = "termcolor"
|
||||||
version = "1.0.4"
|
version = "1.0.4"
|
||||||
|
|
|
@ -1292,6 +1292,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
||||||
"show macro backtraces even for non-local macros"),
|
"show macro backtraces even for non-local macros"),
|
||||||
teach: bool = (false, parse_bool, [TRACKED],
|
teach: bool = (false, parse_bool, [TRACKED],
|
||||||
"show extended diagnostic help"),
|
"show extended diagnostic help"),
|
||||||
|
terminal_width: Option<usize> = (None, parse_opt_uint, [UNTRACKED],
|
||||||
|
"set the current terminal width"),
|
||||||
continue_parse_after_error: bool = (false, parse_bool, [TRACKED],
|
continue_parse_after_error: bool = (false, parse_bool, [TRACKED],
|
||||||
"attempt to recover from parse errors (experimental)"),
|
"attempt to recover from parse errors (experimental)"),
|
||||||
dep_tasks: bool = (false, parse_bool, [UNTRACKED],
|
dep_tasks: bool = (false, parse_bool, [UNTRACKED],
|
||||||
|
|
|
@ -1055,6 +1055,7 @@ fn default_emitter(
|
||||||
Some(source_map.clone()),
|
Some(source_map.clone()),
|
||||||
short,
|
short,
|
||||||
sopts.debugging_opts.teach,
|
sopts.debugging_opts.teach,
|
||||||
|
sopts.debugging_opts.terminal_width,
|
||||||
),
|
),
|
||||||
Some(dst) => EmitterWriter::new(
|
Some(dst) => EmitterWriter::new(
|
||||||
dst,
|
dst,
|
||||||
|
@ -1062,6 +1063,7 @@ fn default_emitter(
|
||||||
short,
|
short,
|
||||||
false, // no teach messages when writing to a buffer
|
false, // no teach messages when writing to a buffer
|
||||||
false, // no colors when writing to a buffer
|
false, // no colors when writing to a buffer
|
||||||
|
None, // no terminal width
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
Box::new(emitter.ui_testing(sopts.debugging_opts.ui_testing))
|
Box::new(emitter.ui_testing(sopts.debugging_opts.ui_testing))
|
||||||
|
@ -1375,7 +1377,7 @@ pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
|
||||||
let emitter: Box<dyn Emitter + sync::Send> = match output {
|
let emitter: Box<dyn Emitter + sync::Send> = match output {
|
||||||
config::ErrorOutputType::HumanReadable(kind) => {
|
config::ErrorOutputType::HumanReadable(kind) => {
|
||||||
let (short, color_config) = kind.unzip();
|
let (short, color_config) = kind.unzip();
|
||||||
Box::new(EmitterWriter::stderr(color_config, None, short, false))
|
Box::new(EmitterWriter::stderr(color_config, None, short, false, None))
|
||||||
}
|
}
|
||||||
config::ErrorOutputType::Json { pretty, json_rendered } =>
|
config::ErrorOutputType::Json { pretty, json_rendered } =>
|
||||||
Box::new(JsonEmitter::basic(pretty, json_rendered)),
|
Box::new(JsonEmitter::basic(pretty, json_rendered)),
|
||||||
|
@ -1389,7 +1391,7 @@ pub fn early_warn(output: config::ErrorOutputType, msg: &str) {
|
||||||
let emitter: Box<dyn Emitter + sync::Send> = match output {
|
let emitter: Box<dyn Emitter + sync::Send> = match output {
|
||||||
config::ErrorOutputType::HumanReadable(kind) => {
|
config::ErrorOutputType::HumanReadable(kind) => {
|
||||||
let (short, color_config) = kind.unzip();
|
let (short, color_config) = kind.unzip();
|
||||||
Box::new(EmitterWriter::stderr(color_config, None, short, false))
|
Box::new(EmitterWriter::stderr(color_config, None, short, false, None))
|
||||||
}
|
}
|
||||||
config::ErrorOutputType::Json { pretty, json_rendered } =>
|
config::ErrorOutputType::Json { pretty, json_rendered } =>
|
||||||
Box::new(JsonEmitter::basic(pretty, json_rendered)),
|
Box::new(JsonEmitter::basic(pretty, json_rendered)),
|
||||||
|
|
|
@ -1156,11 +1156,13 @@ pub fn report_ices_to_stderr_if_any<F: FnOnce() -> R, R>(f: F) -> Result<R, Erro
|
||||||
// Thread panicked without emitting a fatal diagnostic
|
// Thread panicked without emitting a fatal diagnostic
|
||||||
eprintln!("");
|
eprintln!("");
|
||||||
|
|
||||||
let emitter =
|
let emitter = Box::new(errors::emitter::EmitterWriter::stderr(
|
||||||
Box::new(errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto,
|
errors::ColorConfig::Auto,
|
||||||
None,
|
None,
|
||||||
false,
|
false,
|
||||||
false));
|
false,
|
||||||
|
None,
|
||||||
|
));
|
||||||
let handler = errors::Handler::with_emitter(true, None, emitter);
|
let handler = errors::Handler::with_emitter(true, None, emitter);
|
||||||
|
|
||||||
// a .span_bug or .bug call has already printed what
|
// a .span_bug or .bug call has already printed what
|
||||||
|
|
|
@ -18,3 +18,4 @@ unicode-width = "0.1.4"
|
||||||
atty = "0.2"
|
atty = "0.2"
|
||||||
termcolor = "1.0"
|
termcolor = "1.0"
|
||||||
annotate-snippets = "0.6.1"
|
annotate-snippets = "0.6.1"
|
||||||
|
term_size = "0.3.1"
|
||||||
|
|
|
@ -24,7 +24,7 @@ use rustc_data_structures::sync::Lrc;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::cmp::{min, Reverse};
|
use std::cmp::{min, max, Reverse};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use termcolor::{StandardStream, ColorChoice, ColorSpec, BufferWriter, Ansi};
|
use termcolor::{StandardStream, ColorChoice, ColorSpec, BufferWriter, Ansi};
|
||||||
use termcolor::{WriteColor, Color, Buffer};
|
use termcolor::{WriteColor, Color, Buffer};
|
||||||
|
@ -51,9 +51,127 @@ impl HumanReadableErrorType {
|
||||||
dst: Box<dyn Write + Send>,
|
dst: Box<dyn Write + Send>,
|
||||||
source_map: Option<Lrc<SourceMapperDyn>>,
|
source_map: Option<Lrc<SourceMapperDyn>>,
|
||||||
teach: bool,
|
teach: bool,
|
||||||
|
terminal_width: Option<usize>,
|
||||||
) -> EmitterWriter {
|
) -> EmitterWriter {
|
||||||
let (short, color_config) = self.unzip();
|
let (short, color_config) = self.unzip();
|
||||||
EmitterWriter::new(dst, source_map, short, teach, color_config.suggests_using_colors())
|
let color = color_config.suggests_using_colors();
|
||||||
|
EmitterWriter::new(dst, source_map, short, teach, color, terminal_width)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
struct Margin {
|
||||||
|
/// The available whitespace in the left that can be consumed when centering.
|
||||||
|
pub whitespace_left: usize,
|
||||||
|
/// The column of the beginning of left-most span.
|
||||||
|
pub span_left: usize,
|
||||||
|
/// The column of the end of right-most span.
|
||||||
|
pub span_right: usize,
|
||||||
|
/// The beginning of the line to be displayed.
|
||||||
|
pub computed_left: usize,
|
||||||
|
/// The end of the line to be displayed.
|
||||||
|
pub computed_right: usize,
|
||||||
|
/// The current width of the terminal. 140 by default and in tests.
|
||||||
|
pub column_width: usize,
|
||||||
|
/// The end column of a span label, including the span. Doesn't account for labels not in the
|
||||||
|
/// same line as the span.
|
||||||
|
pub label_right: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Margin {
|
||||||
|
fn new(
|
||||||
|
whitespace_left: usize,
|
||||||
|
span_left: usize,
|
||||||
|
span_right: usize,
|
||||||
|
label_right: usize,
|
||||||
|
column_width: usize,
|
||||||
|
max_line_len: usize,
|
||||||
|
) -> Self {
|
||||||
|
// The 6 is padding to give a bit of room for `...` when displaying:
|
||||||
|
// ```
|
||||||
|
// error: message
|
||||||
|
// --> file.rs:16:58
|
||||||
|
// |
|
||||||
|
// 16 | ... fn foo(self) -> Self::Bar {
|
||||||
|
// | ^^^^^^^^^
|
||||||
|
// ```
|
||||||
|
|
||||||
|
let mut m = Margin {
|
||||||
|
whitespace_left: if whitespace_left >= 6 { whitespace_left - 6 } else { 0 },
|
||||||
|
span_left: if span_left >= 6 { span_left - 6 } else { 0 },
|
||||||
|
span_right: span_right + 6,
|
||||||
|
computed_left: 0,
|
||||||
|
computed_right: 0,
|
||||||
|
column_width,
|
||||||
|
label_right: label_right + 6,
|
||||||
|
};
|
||||||
|
m.compute(max_line_len);
|
||||||
|
m
|
||||||
|
}
|
||||||
|
|
||||||
|
fn was_cut_left(&self) -> bool {
|
||||||
|
self.computed_left > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn was_cut_right(&self, line_len: usize) -> bool {
|
||||||
|
let right = if self.computed_right == self.span_right ||
|
||||||
|
self.computed_right == self.label_right
|
||||||
|
{
|
||||||
|
// Account for the "..." padding given above. Otherwise we end up with code lines that
|
||||||
|
// do fit but end in "..." as if they were trimmed.
|
||||||
|
self.computed_right - 6
|
||||||
|
} else {
|
||||||
|
self.computed_right
|
||||||
|
};
|
||||||
|
right < line_len && line_len > self.computed_left + self.column_width
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compute(&mut self, max_line_len: usize) {
|
||||||
|
// When there's a lot of whitespace (>20), we want to trim it as it is useless.
|
||||||
|
self.computed_left = if self.whitespace_left > 20 {
|
||||||
|
self.whitespace_left - 16 // We want some padding.
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
// We want to show as much as possible, max_line_len is the right-most boundary for the
|
||||||
|
// relevant code.
|
||||||
|
self.computed_right = max(max_line_len, self.computed_left);
|
||||||
|
|
||||||
|
if self.computed_right - self.computed_left > self.column_width {
|
||||||
|
// Trimming only whitespace isn't enough, let's get craftier.
|
||||||
|
if self.label_right - self.whitespace_left <= self.column_width {
|
||||||
|
// Attempt to fit the code window only trimming whitespace.
|
||||||
|
self.computed_left = self.whitespace_left;
|
||||||
|
self.computed_right = self.computed_left + self.column_width;
|
||||||
|
} else if self.label_right - self.span_left <= self.column_width {
|
||||||
|
// Attempt to fit the code window considering only the spans and labels.
|
||||||
|
let padding_left = (self.column_width - (self.label_right - self.span_left)) / 2;
|
||||||
|
self.computed_left = self.span_left - padding_left;
|
||||||
|
self.computed_right = self.computed_left + self.column_width;
|
||||||
|
} else if self.span_right - self.span_left <= self.column_width {
|
||||||
|
// Attempt to fit the code window considering the spans and labels plus padding.
|
||||||
|
let padding_left = (self.column_width - (self.span_right - self.span_left)) / 5 * 2;
|
||||||
|
self.computed_left = self.span_left - padding_left;
|
||||||
|
self.computed_right = self.computed_left + self.column_width;
|
||||||
|
} else { // Mostly give up but still don't show the full line.
|
||||||
|
self.computed_left = self.span_left;
|
||||||
|
self.computed_right = self.span_right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn left(&self, line_len: usize) -> usize {
|
||||||
|
min(self.computed_left, line_len)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn right(&self, line_len: usize) -> usize {
|
||||||
|
if max(line_len, self.computed_left) - self.computed_left <= self.column_width {
|
||||||
|
line_len
|
||||||
|
} else if self.computed_right > line_len {
|
||||||
|
line_len
|
||||||
|
} else {
|
||||||
|
self.computed_right
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,6 +298,7 @@ pub struct EmitterWriter {
|
||||||
short_message: bool,
|
short_message: bool,
|
||||||
teach: bool,
|
teach: bool,
|
||||||
ui_testing: bool,
|
ui_testing: bool,
|
||||||
|
terminal_width: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -190,11 +309,13 @@ pub struct FileWithAnnotatedLines {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EmitterWriter {
|
impl EmitterWriter {
|
||||||
pub fn stderr(color_config: ColorConfig,
|
pub fn stderr(
|
||||||
source_map: Option<Lrc<SourceMapperDyn>>,
|
color_config: ColorConfig,
|
||||||
short_message: bool,
|
source_map: Option<Lrc<SourceMapperDyn>>,
|
||||||
teach: bool)
|
short_message: bool,
|
||||||
-> EmitterWriter {
|
teach: bool,
|
||||||
|
terminal_width: Option<usize>,
|
||||||
|
) -> EmitterWriter {
|
||||||
let dst = Destination::from_stderr(color_config);
|
let dst = Destination::from_stderr(color_config);
|
||||||
EmitterWriter {
|
EmitterWriter {
|
||||||
dst,
|
dst,
|
||||||
|
@ -202,6 +323,7 @@ impl EmitterWriter {
|
||||||
short_message,
|
short_message,
|
||||||
teach,
|
teach,
|
||||||
ui_testing: false,
|
ui_testing: false,
|
||||||
|
terminal_width,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,6 +333,7 @@ impl EmitterWriter {
|
||||||
short_message: bool,
|
short_message: bool,
|
||||||
teach: bool,
|
teach: bool,
|
||||||
colored: bool,
|
colored: bool,
|
||||||
|
terminal_width: Option<usize>,
|
||||||
) -> EmitterWriter {
|
) -> EmitterWriter {
|
||||||
EmitterWriter {
|
EmitterWriter {
|
||||||
dst: Raw(dst, colored),
|
dst: Raw(dst, colored),
|
||||||
|
@ -218,6 +341,7 @@ impl EmitterWriter {
|
||||||
short_message,
|
short_message,
|
||||||
teach,
|
teach,
|
||||||
ui_testing: false,
|
ui_testing: false,
|
||||||
|
terminal_width,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,12 +358,70 @@ impl EmitterWriter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_source_line(&self,
|
fn draw_line(
|
||||||
buffer: &mut StyledBuffer,
|
&self,
|
||||||
file: Lrc<SourceFile>,
|
buffer: &mut StyledBuffer,
|
||||||
line: &Line,
|
source_string: &str,
|
||||||
width_offset: usize,
|
line_index: usize,
|
||||||
code_offset: usize) -> Vec<(usize, Style)> {
|
line_offset: usize,
|
||||||
|
width_offset: usize,
|
||||||
|
code_offset: usize,
|
||||||
|
margin: Margin,
|
||||||
|
) {
|
||||||
|
let line_len = source_string.len();
|
||||||
|
// Create the source line we will highlight.
|
||||||
|
let left = margin.left(line_len);
|
||||||
|
let right = margin.right(line_len);
|
||||||
|
// On long lines, we strip the source line, accounting for unicode.
|
||||||
|
let mut taken = 0;
|
||||||
|
let code: String = source_string.chars().skip(left).take_while(|ch| {
|
||||||
|
// Make sure that the trimming on the right will fall within the terminal width.
|
||||||
|
// FIXME: `unicode_width` sometimes disagrees with terminals on how wide a `char` is.
|
||||||
|
// For now, just accept that sometimes the code line will be longer than desired.
|
||||||
|
let next = unicode_width::UnicodeWidthChar::width(*ch).unwrap_or(1);
|
||||||
|
if taken + next > right - left {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
taken += next;
|
||||||
|
true
|
||||||
|
}).collect();
|
||||||
|
buffer.puts(line_offset, code_offset, &code, Style::Quotation);
|
||||||
|
if margin.was_cut_left() {
|
||||||
|
// We have stripped some code/whitespace from the beginning, make it clear.
|
||||||
|
buffer.puts(line_offset, code_offset, "...", Style::LineNumber);
|
||||||
|
}
|
||||||
|
if margin.was_cut_right(line_len) {
|
||||||
|
// We have stripped some code after the right-most span end, make it clear we did so.
|
||||||
|
buffer.puts(line_offset, code_offset + taken - 3, "...", Style::LineNumber);
|
||||||
|
}
|
||||||
|
buffer.puts(line_offset, 0, &self.maybe_anonymized(line_index), Style::LineNumber);
|
||||||
|
|
||||||
|
draw_col_separator(buffer, line_offset, width_offset - 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_source_line(
|
||||||
|
&self,
|
||||||
|
buffer: &mut StyledBuffer,
|
||||||
|
file: Lrc<SourceFile>,
|
||||||
|
line: &Line,
|
||||||
|
width_offset: usize,
|
||||||
|
code_offset: usize,
|
||||||
|
margin: Margin,
|
||||||
|
) -> Vec<(usize, Style)> {
|
||||||
|
// Draw:
|
||||||
|
//
|
||||||
|
// LL | ... code ...
|
||||||
|
// | ^^-^ span label
|
||||||
|
// | |
|
||||||
|
// | secondary span label
|
||||||
|
//
|
||||||
|
// ^^ ^ ^^^ ^^^^ ^^^ we don't care about code too far to the right of a span, we trim it
|
||||||
|
// | | | |
|
||||||
|
// | | | actual code found in your source code and the spans we use to mark it
|
||||||
|
// | | when there's too much wasted space to the left, trim it
|
||||||
|
// | vertical divider between the column number and the code
|
||||||
|
// column number
|
||||||
|
|
||||||
if line.line_index == 0 {
|
if line.line_index == 0 {
|
||||||
return Vec::new();
|
return Vec::new();
|
||||||
}
|
}
|
||||||
|
@ -251,14 +433,21 @@ impl EmitterWriter {
|
||||||
|
|
||||||
let line_offset = buffer.num_lines();
|
let line_offset = buffer.num_lines();
|
||||||
|
|
||||||
// First create the source line we will highlight.
|
let left = margin.left(source_string.len()); // Left trim
|
||||||
buffer.puts(line_offset, code_offset, &source_string, Style::Quotation);
|
// Account for unicode characters of width !=0 that were removed.
|
||||||
buffer.puts(line_offset,
|
let left = source_string.chars().take(left).fold(0, |acc, ch| {
|
||||||
0,
|
acc + unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1)
|
||||||
&self.maybe_anonymized(line.line_index),
|
});
|
||||||
Style::LineNumber);
|
|
||||||
|
|
||||||
draw_col_separator(buffer, line_offset, width_offset - 2);
|
self.draw_line(
|
||||||
|
buffer,
|
||||||
|
&source_string,
|
||||||
|
line.line_index,
|
||||||
|
line_offset,
|
||||||
|
width_offset,
|
||||||
|
code_offset,
|
||||||
|
margin,
|
||||||
|
);
|
||||||
|
|
||||||
// Special case when there's only one annotation involved, it is the start of a multiline
|
// Special case when there's only one annotation involved, it is the start of a multiline
|
||||||
// span and there's no text at the beginning of the code line. Instead of doing the whole
|
// span and there's no text at the beginning of the code line. Instead of doing the whole
|
||||||
|
@ -279,18 +468,13 @@ impl EmitterWriter {
|
||||||
if line.annotations.len() == 1 {
|
if line.annotations.len() == 1 {
|
||||||
if let Some(ref ann) = line.annotations.get(0) {
|
if let Some(ref ann) = line.annotations.get(0) {
|
||||||
if let AnnotationType::MultilineStart(depth) = ann.annotation_type {
|
if let AnnotationType::MultilineStart(depth) = ann.annotation_type {
|
||||||
if source_string.chars()
|
if source_string.chars().take(ann.start_col).all(|c| c.is_whitespace()) {
|
||||||
.take(ann.start_col)
|
|
||||||
.all(|c| c.is_whitespace()) {
|
|
||||||
let style = if ann.is_primary {
|
let style = if ann.is_primary {
|
||||||
Style::UnderlinePrimary
|
Style::UnderlinePrimary
|
||||||
} else {
|
} else {
|
||||||
Style::UnderlineSecondary
|
Style::UnderlineSecondary
|
||||||
};
|
};
|
||||||
buffer.putc(line_offset,
|
buffer.putc(line_offset, width_offset + depth - 1, '/', style);
|
||||||
width_offset + depth - 1,
|
|
||||||
'/',
|
|
||||||
style);
|
|
||||||
return vec![(depth, style)];
|
return vec![(depth, style)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -511,19 +695,23 @@ impl EmitterWriter {
|
||||||
match annotation.annotation_type {
|
match annotation.annotation_type {
|
||||||
AnnotationType::MultilineStart(depth) |
|
AnnotationType::MultilineStart(depth) |
|
||||||
AnnotationType::MultilineEnd(depth) => {
|
AnnotationType::MultilineEnd(depth) => {
|
||||||
draw_range(buffer,
|
draw_range(
|
||||||
'_',
|
buffer,
|
||||||
line_offset + pos,
|
'_',
|
||||||
width_offset + depth,
|
line_offset + pos,
|
||||||
code_offset + annotation.start_col,
|
width_offset + depth,
|
||||||
style);
|
code_offset + annotation.start_col - left,
|
||||||
|
style,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
_ if self.teach => {
|
_ if self.teach => {
|
||||||
buffer.set_style_range(line_offset,
|
buffer.set_style_range(
|
||||||
code_offset + annotation.start_col,
|
line_offset,
|
||||||
code_offset + annotation.end_col,
|
code_offset + annotation.start_col - left,
|
||||||
style,
|
code_offset + annotation.end_col - left,
|
||||||
annotation.is_primary);
|
style,
|
||||||
|
annotation.is_primary,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -551,7 +739,7 @@ impl EmitterWriter {
|
||||||
if pos > 1 && (annotation.has_label() || annotation.takes_space()) {
|
if pos > 1 && (annotation.has_label() || annotation.takes_space()) {
|
||||||
for p in line_offset + 1..=line_offset + pos {
|
for p in line_offset + 1..=line_offset + pos {
|
||||||
buffer.putc(p,
|
buffer.putc(p,
|
||||||
code_offset + annotation.start_col,
|
code_offset + annotation.start_col - margin.computed_left,
|
||||||
'|',
|
'|',
|
||||||
style);
|
style);
|
||||||
}
|
}
|
||||||
|
@ -595,15 +783,20 @@ impl EmitterWriter {
|
||||||
Style::LabelSecondary
|
Style::LabelSecondary
|
||||||
};
|
};
|
||||||
let (pos, col) = if pos == 0 {
|
let (pos, col) = if pos == 0 {
|
||||||
(pos + 1, annotation.end_col + 1)
|
(pos + 1, if annotation.end_col + 1 > left {
|
||||||
|
annotation.end_col + 1 - left
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
(pos + 2, annotation.start_col)
|
(pos + 2, if annotation.start_col > left {
|
||||||
|
annotation.start_col - left
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
})
|
||||||
};
|
};
|
||||||
if let Some(ref label) = annotation.label {
|
if let Some(ref label) = annotation.label {
|
||||||
buffer.puts(line_offset + pos,
|
buffer.puts(line_offset + pos, code_offset + col, &label, style);
|
||||||
code_offset + col,
|
|
||||||
&label,
|
|
||||||
style);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -638,10 +831,16 @@ impl EmitterWriter {
|
||||||
('-', Style::UnderlineSecondary)
|
('-', Style::UnderlineSecondary)
|
||||||
};
|
};
|
||||||
for p in annotation.start_col..annotation.end_col {
|
for p in annotation.start_col..annotation.end_col {
|
||||||
buffer.putc(line_offset + 1,
|
buffer.putc(
|
||||||
code_offset + p,
|
line_offset + 1,
|
||||||
underline,
|
if code_offset + p > left {
|
||||||
style);
|
code_offset + p - left
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
},
|
||||||
|
underline,
|
||||||
|
style,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
annotations_position.iter().filter_map(|&(_, annotation)| {
|
annotations_position.iter().filter_map(|&(_, annotation)| {
|
||||||
|
@ -979,22 +1178,30 @@ impl EmitterWriter {
|
||||||
let buffer_msg_line_offset = buffer.num_lines();
|
let buffer_msg_line_offset = buffer.num_lines();
|
||||||
|
|
||||||
buffer.prepend(buffer_msg_line_offset, "--> ", Style::LineNumber);
|
buffer.prepend(buffer_msg_line_offset, "--> ", Style::LineNumber);
|
||||||
buffer.append(buffer_msg_line_offset,
|
buffer.append(
|
||||||
&format!("{}:{}:{}",
|
buffer_msg_line_offset,
|
||||||
loc.file.name,
|
&format!(
|
||||||
sm.doctest_offset_line(&loc.file.name, loc.line),
|
"{}:{}:{}",
|
||||||
loc.col.0 + 1),
|
loc.file.name,
|
||||||
Style::LineAndColumn);
|
sm.doctest_offset_line(&loc.file.name, loc.line),
|
||||||
|
loc.col.0 + 1,
|
||||||
|
),
|
||||||
|
Style::LineAndColumn,
|
||||||
|
);
|
||||||
for _ in 0..max_line_num_len {
|
for _ in 0..max_line_num_len {
|
||||||
buffer.prepend(buffer_msg_line_offset, " ", Style::NoStyle);
|
buffer.prepend(buffer_msg_line_offset, " ", Style::NoStyle);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
buffer.prepend(0,
|
buffer.prepend(
|
||||||
&format!("{}:{}:{}: ",
|
0,
|
||||||
loc.file.name,
|
&format!(
|
||||||
sm.doctest_offset_line(&loc.file.name, loc.line),
|
"{}:{}:{}: ",
|
||||||
loc.col.0 + 1),
|
loc.file.name,
|
||||||
Style::LineAndColumn);
|
sm.doctest_offset_line(&loc.file.name, loc.line),
|
||||||
|
loc.col.0 + 1,
|
||||||
|
),
|
||||||
|
Style::LineAndColumn,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else if !self.short_message {
|
} else if !self.short_message {
|
||||||
// remember where we are in the output buffer for easy reference
|
// remember where we are in the output buffer for easy reference
|
||||||
|
@ -1037,22 +1244,94 @@ impl EmitterWriter {
|
||||||
// Contains the vertical lines' positions for active multiline annotations
|
// Contains the vertical lines' positions for active multiline annotations
|
||||||
let mut multilines = FxHashMap::default();
|
let mut multilines = FxHashMap::default();
|
||||||
|
|
||||||
|
// Get the left-side margin to remove it
|
||||||
|
let mut whitespace_margin = std::usize::MAX;
|
||||||
|
for line_idx in 0..annotated_file.lines.len() {
|
||||||
|
let file = annotated_file.file.clone();
|
||||||
|
let line = &annotated_file.lines[line_idx];
|
||||||
|
if let Some(source_string) = file.get_line(line.line_index - 1) {
|
||||||
|
let leading_whitespace = source_string
|
||||||
|
.chars()
|
||||||
|
.take_while(|c| c.is_whitespace())
|
||||||
|
.count();
|
||||||
|
if source_string.chars().any(|c| !c.is_whitespace()) {
|
||||||
|
whitespace_margin = min(
|
||||||
|
whitespace_margin,
|
||||||
|
leading_whitespace,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if whitespace_margin == std::usize::MAX {
|
||||||
|
whitespace_margin = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Left-most column any visible span points at.
|
||||||
|
let mut span_left_margin = std::usize::MAX;
|
||||||
|
for line in &annotated_file.lines {
|
||||||
|
for ann in &line.annotations {
|
||||||
|
span_left_margin = min(span_left_margin, ann.start_col);
|
||||||
|
span_left_margin = min(span_left_margin, ann.end_col);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if span_left_margin == std::usize::MAX {
|
||||||
|
span_left_margin = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Right-most column any visible span points at.
|
||||||
|
let mut span_right_margin = 0;
|
||||||
|
let mut label_right_margin = 0;
|
||||||
|
let mut max_line_len = 0;
|
||||||
|
for line in &annotated_file.lines {
|
||||||
|
max_line_len = max(max_line_len, annotated_file.file
|
||||||
|
.get_line(line.line_index - 1)
|
||||||
|
.map(|s| s.len())
|
||||||
|
.unwrap_or(0));
|
||||||
|
for ann in &line.annotations {
|
||||||
|
span_right_margin = max(span_right_margin, ann.start_col);
|
||||||
|
span_right_margin = max(span_right_margin, ann.end_col);
|
||||||
|
// FIXME: account for labels not in the same line
|
||||||
|
let label_right = ann.label.as_ref().map(|l| l.len() + 1).unwrap_or(0);
|
||||||
|
label_right_margin = max(label_right_margin, ann.end_col + label_right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let width_offset = 3 + max_line_num_len;
|
||||||
|
let code_offset = if annotated_file.multiline_depth == 0 {
|
||||||
|
width_offset
|
||||||
|
} else {
|
||||||
|
width_offset + annotated_file.multiline_depth + 1
|
||||||
|
};
|
||||||
|
|
||||||
|
let column_width = if let Some(width) = self.terminal_width {
|
||||||
|
width
|
||||||
|
} else if self.ui_testing {
|
||||||
|
140
|
||||||
|
} else {
|
||||||
|
term_size::dimensions().map(|(w, _)| w - code_offset).unwrap_or(140)
|
||||||
|
};
|
||||||
|
|
||||||
|
let margin = Margin::new(
|
||||||
|
whitespace_margin,
|
||||||
|
span_left_margin,
|
||||||
|
span_right_margin,
|
||||||
|
label_right_margin,
|
||||||
|
column_width,
|
||||||
|
max_line_len,
|
||||||
|
);
|
||||||
|
|
||||||
// Next, output the annotate source for this file
|
// Next, output the annotate source for this file
|
||||||
for line_idx in 0..annotated_file.lines.len() {
|
for line_idx in 0..annotated_file.lines.len() {
|
||||||
let previous_buffer_line = buffer.num_lines();
|
let previous_buffer_line = buffer.num_lines();
|
||||||
|
|
||||||
let width_offset = 3 + max_line_num_len;
|
let depths = self.render_source_line(
|
||||||
let code_offset = if annotated_file.multiline_depth == 0 {
|
&mut buffer,
|
||||||
width_offset
|
annotated_file.file.clone(),
|
||||||
} else {
|
&annotated_file.lines[line_idx],
|
||||||
width_offset + annotated_file.multiline_depth + 1
|
width_offset,
|
||||||
};
|
code_offset,
|
||||||
|
margin,
|
||||||
let depths = self.render_source_line(&mut buffer,
|
);
|
||||||
annotated_file.file.clone(),
|
|
||||||
&annotated_file.lines[line_idx],
|
|
||||||
width_offset,
|
|
||||||
code_offset);
|
|
||||||
|
|
||||||
let mut to_add = FxHashMap::default();
|
let mut to_add = FxHashMap::default();
|
||||||
|
|
||||||
|
@ -1099,25 +1378,24 @@ impl EmitterWriter {
|
||||||
|
|
||||||
let last_buffer_line_num = buffer.num_lines();
|
let last_buffer_line_num = buffer.num_lines();
|
||||||
|
|
||||||
buffer.puts(last_buffer_line_num,
|
self.draw_line(
|
||||||
0,
|
&mut buffer,
|
||||||
&self.maybe_anonymized(annotated_file.lines[line_idx + 1]
|
&unannotated_line,
|
||||||
.line_index - 1),
|
annotated_file.lines[line_idx + 1].line_index - 1,
|
||||||
Style::LineNumber);
|
last_buffer_line_num,
|
||||||
draw_col_separator(&mut buffer,
|
width_offset,
|
||||||
last_buffer_line_num,
|
code_offset,
|
||||||
1 + max_line_num_len);
|
margin,
|
||||||
buffer.puts(last_buffer_line_num,
|
);
|
||||||
code_offset,
|
|
||||||
&unannotated_line,
|
|
||||||
Style::Quotation);
|
|
||||||
|
|
||||||
for (depth, style) in &multilines {
|
for (depth, style) in &multilines {
|
||||||
draw_multiline_line(&mut buffer,
|
draw_multiline_line(
|
||||||
last_buffer_line_num,
|
&mut buffer,
|
||||||
width_offset,
|
last_buffer_line_num,
|
||||||
*depth,
|
width_offset,
|
||||||
*style);
|
*depth,
|
||||||
|
*style,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1207,7 +1485,7 @@ impl EmitterWriter {
|
||||||
// ...or trailing spaces. Account for substitutions containing unicode
|
// ...or trailing spaces. Account for substitutions containing unicode
|
||||||
// characters.
|
// characters.
|
||||||
let sub_len = part.snippet.trim().chars().fold(0, |acc, ch| {
|
let sub_len = part.snippet.trim().chars().fold(0, |acc, ch| {
|
||||||
acc + unicode_width::UnicodeWidthChar::width(ch).unwrap_or(0)
|
acc + unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1)
|
||||||
});
|
});
|
||||||
|
|
||||||
let underline_start = (span_start_pos + start) as isize + offset;
|
let underline_start = (span_start_pos + start) as isize + offset;
|
||||||
|
@ -1230,7 +1508,7 @@ impl EmitterWriter {
|
||||||
|
|
||||||
// length of the code after substitution
|
// length of the code after substitution
|
||||||
let full_sub_len = part.snippet.chars().fold(0, |acc, ch| {
|
let full_sub_len = part.snippet.chars().fold(0, |acc, ch| {
|
||||||
acc + unicode_width::UnicodeWidthChar::width(ch).unwrap_or(0) as isize
|
acc + unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1) as isize
|
||||||
});
|
});
|
||||||
|
|
||||||
// length of the code to be substituted
|
// length of the code to be substituted
|
||||||
|
|
|
@ -383,7 +383,7 @@ impl Handler {
|
||||||
cm: Option<Lrc<SourceMapperDyn>>,
|
cm: Option<Lrc<SourceMapperDyn>>,
|
||||||
flags: HandlerFlags)
|
flags: HandlerFlags)
|
||||||
-> Handler {
|
-> Handler {
|
||||||
let emitter = Box::new(EmitterWriter::stderr(color_config, cm, false, false));
|
let emitter = Box::new(EmitterWriter::stderr(color_config, cm, false, false, None));
|
||||||
Handler::with_emitter_and_flags(emitter, flags)
|
Handler::with_emitter_and_flags(emitter, flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -193,6 +193,7 @@ pub fn new_handler(error_format: ErrorOutputType,
|
||||||
source_map.map(|cm| cm as _),
|
source_map.map(|cm| cm as _),
|
||||||
short,
|
short,
|
||||||
sessopts.debugging_opts.teach,
|
sessopts.debugging_opts.teach,
|
||||||
|
sessopts.debugging_opts.terminal_width,
|
||||||
).ui_testing(ui_testing)
|
).ui_testing(ui_testing)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
|
@ -433,7 +433,7 @@ pub fn make_test(s: &str,
|
||||||
// Any errors in parsing should also appear when the doctest is compiled for real, so just
|
// Any errors in parsing should also appear when the doctest is compiled for real, so just
|
||||||
// send all the errors that libsyntax emits directly into a `Sink` instead of stderr.
|
// send all the errors that libsyntax emits directly into a `Sink` instead of stderr.
|
||||||
let cm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
let cm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
||||||
let emitter = EmitterWriter::new(box io::sink(), None, false, false, false);
|
let emitter = EmitterWriter::new(box io::sink(), None, false, false, false, None);
|
||||||
// FIXME(misdreavus): pass `-Z treat-err-as-bug` to the doctest parser
|
// FIXME(misdreavus): pass `-Z treat-err-as-bug` to the doctest parser
|
||||||
let handler = Handler::with_emitter(false, None, box emitter);
|
let handler = Handler::with_emitter(false, None, box emitter);
|
||||||
let sess = ParseSess::with_span_handler(handler, cm);
|
let sess = ParseSess::with_span_handler(handler, cm);
|
||||||
|
|
|
@ -219,7 +219,7 @@ impl Diagnostic {
|
||||||
}
|
}
|
||||||
let buf = BufWriter::default();
|
let buf = BufWriter::default();
|
||||||
let output = buf.clone();
|
let output = buf.clone();
|
||||||
je.json_rendered.new_emitter(Box::new(buf), Some(je.sm.clone()), false)
|
je.json_rendered.new_emitter(Box::new(buf), Some(je.sm.clone()), false, None)
|
||||||
.ui_testing(je.ui_testing).emit_diagnostic(db);
|
.ui_testing(je.ui_testing).emit_diagnostic(db);
|
||||||
let output = Arc::try_unwrap(output.0).unwrap().into_inner().unwrap();
|
let output = Arc::try_unwrap(output.0).unwrap().into_inner().unwrap();
|
||||||
let output = String::from_utf8(output).unwrap();
|
let output = String::from_utf8(output).unwrap();
|
||||||
|
|
|
@ -10,7 +10,14 @@ use errors::{Handler, emitter::EmitterWriter};
|
||||||
use syntax_pos::{BytePos, Span};
|
use syntax_pos::{BytePos, Span};
|
||||||
|
|
||||||
fn mk_sess(sm: Lrc<SourceMap>) -> ParseSess {
|
fn mk_sess(sm: Lrc<SourceMap>) -> ParseSess {
|
||||||
let emitter = EmitterWriter::new(Box::new(io::sink()), Some(sm.clone()), false, false, false);
|
let emitter = EmitterWriter::new(
|
||||||
|
Box::new(io::sink()),
|
||||||
|
Some(sm.clone()),
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
None,
|
||||||
|
);
|
||||||
ParseSess::with_span_handler(Handler::with_emitter(true, None, Box::new(emitter)), sm)
|
ParseSess::with_span_handler(Handler::with_emitter(true, None, Box::new(emitter)), sm)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,10 +35,11 @@ fn t1() {
|
||||||
with_default_globals(|| {
|
with_default_globals(|| {
|
||||||
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
||||||
let sh = mk_sess(sm.clone());
|
let sh = mk_sess(sm.clone());
|
||||||
let mut string_reader = setup(&sm,
|
let mut string_reader = setup(
|
||||||
&sh,
|
&sm,
|
||||||
"/* my source file */ fn main() { println!(\"zebra\"); }\n"
|
&sh,
|
||||||
.to_string());
|
"/* my source file */ fn main() { println!(\"zebra\"); }\n".to_string(),
|
||||||
|
);
|
||||||
assert_eq!(string_reader.next_token(), token::Comment);
|
assert_eq!(string_reader.next_token(), token::Comment);
|
||||||
assert_eq!(string_reader.next_token(), token::Whitespace);
|
assert_eq!(string_reader.next_token(), token::Whitespace);
|
||||||
let tok1 = string_reader.next_token();
|
let tok1 = string_reader.next_token();
|
||||||
|
@ -127,8 +135,10 @@ fn character_a() {
|
||||||
with_default_globals(|| {
|
with_default_globals(|| {
|
||||||
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
||||||
let sh = mk_sess(sm.clone());
|
let sh = mk_sess(sm.clone());
|
||||||
assert_eq!(setup(&sm, &sh, "'a'".to_string()).next_token(),
|
assert_eq!(
|
||||||
mk_lit(token::Char, "a", None));
|
setup(&sm, &sh, "'a'".to_string()).next_token(),
|
||||||
|
mk_lit(token::Char, "a", None),
|
||||||
|
);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,8 +147,10 @@ fn character_space() {
|
||||||
with_default_globals(|| {
|
with_default_globals(|| {
|
||||||
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
||||||
let sh = mk_sess(sm.clone());
|
let sh = mk_sess(sm.clone());
|
||||||
assert_eq!(setup(&sm, &sh, "' '".to_string()).next_token(),
|
assert_eq!(
|
||||||
mk_lit(token::Char, " ", None));
|
setup(&sm, &sh, "' '".to_string()).next_token(),
|
||||||
|
mk_lit(token::Char, " ", None),
|
||||||
|
);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,8 +159,10 @@ fn character_escaped() {
|
||||||
with_default_globals(|| {
|
with_default_globals(|| {
|
||||||
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
||||||
let sh = mk_sess(sm.clone());
|
let sh = mk_sess(sm.clone());
|
||||||
assert_eq!(setup(&sm, &sh, "'\\n'".to_string()).next_token(),
|
assert_eq!(
|
||||||
mk_lit(token::Char, "\\n", None));
|
setup(&sm, &sh, "'\\n'".to_string()).next_token(),
|
||||||
|
mk_lit(token::Char, "\\n", None),
|
||||||
|
);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,8 +171,10 @@ fn lifetime_name() {
|
||||||
with_default_globals(|| {
|
with_default_globals(|| {
|
||||||
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
||||||
let sh = mk_sess(sm.clone());
|
let sh = mk_sess(sm.clone());
|
||||||
assert_eq!(setup(&sm, &sh, "'abc".to_string()).next_token(),
|
assert_eq!(
|
||||||
token::Lifetime(Symbol::intern("'abc")));
|
setup(&sm, &sh, "'abc".to_string()).next_token(),
|
||||||
|
token::Lifetime(Symbol::intern("'abc")),
|
||||||
|
);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,8 +183,10 @@ fn raw_string() {
|
||||||
with_default_globals(|| {
|
with_default_globals(|| {
|
||||||
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
||||||
let sh = mk_sess(sm.clone());
|
let sh = mk_sess(sm.clone());
|
||||||
assert_eq!(setup(&sm, &sh, "r###\"\"#a\\b\x00c\"\"###".to_string()).next_token(),
|
assert_eq!(
|
||||||
mk_lit(token::StrRaw(3), "\"#a\\b\x00c\"", None));
|
setup(&sm, &sh, "r###\"\"#a\\b\x00c\"\"###".to_string()).next_token(),
|
||||||
|
mk_lit(token::StrRaw(3), "\"#a\\b\x00c\"", None),
|
||||||
|
);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,11 +197,15 @@ fn literal_suffixes() {
|
||||||
let sh = mk_sess(sm.clone());
|
let sh = mk_sess(sm.clone());
|
||||||
macro_rules! test {
|
macro_rules! test {
|
||||||
($input: expr, $tok_type: ident, $tok_contents: expr) => {{
|
($input: expr, $tok_type: ident, $tok_contents: expr) => {{
|
||||||
assert_eq!(setup(&sm, &sh, format!("{}suffix", $input)).next_token(),
|
assert_eq!(
|
||||||
mk_lit(token::$tok_type, $tok_contents, Some("suffix")));
|
setup(&sm, &sh, format!("{}suffix", $input)).next_token(),
|
||||||
|
mk_lit(token::$tok_type, $tok_contents, Some("suffix")),
|
||||||
|
);
|
||||||
// with a whitespace separator:
|
// with a whitespace separator:
|
||||||
assert_eq!(setup(&sm, &sh, format!("{} suffix", $input)).next_token(),
|
assert_eq!(
|
||||||
mk_lit(token::$tok_type, $tok_contents, None));
|
setup(&sm, &sh, format!("{} suffix", $input)).next_token(),
|
||||||
|
mk_lit(token::$tok_type, $tok_contents, None),
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,12 +219,18 @@ fn literal_suffixes() {
|
||||||
test!("1.0", Float, "1.0");
|
test!("1.0", Float, "1.0");
|
||||||
test!("1.0e10", Float, "1.0e10");
|
test!("1.0e10", Float, "1.0e10");
|
||||||
|
|
||||||
assert_eq!(setup(&sm, &sh, "2us".to_string()).next_token(),
|
assert_eq!(
|
||||||
mk_lit(token::Integer, "2", Some("us")));
|
setup(&sm, &sh, "2us".to_string()).next_token(),
|
||||||
assert_eq!(setup(&sm, &sh, "r###\"raw\"###suffix".to_string()).next_token(),
|
mk_lit(token::Integer, "2", Some("us")),
|
||||||
mk_lit(token::StrRaw(3), "raw", Some("suffix")));
|
);
|
||||||
assert_eq!(setup(&sm, &sh, "br###\"raw\"###suffix".to_string()).next_token(),
|
assert_eq!(
|
||||||
mk_lit(token::ByteStrRaw(3), "raw", Some("suffix")));
|
setup(&sm, &sh, "r###\"raw\"###suffix".to_string()).next_token(),
|
||||||
|
mk_lit(token::StrRaw(3), "raw", Some("suffix")),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
setup(&sm, &sh, "br###\"raw\"###suffix".to_string()).next_token(),
|
||||||
|
mk_lit(token::ByteStrRaw(3), "raw", Some("suffix")),
|
||||||
|
);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -144,11 +144,14 @@ fn test_harness(file_text: &str, span_labels: Vec<SpanLabel>, expected_output: &
|
||||||
println!("text: {:?}", source_map.span_to_snippet(span));
|
println!("text: {:?}", source_map.span_to_snippet(span));
|
||||||
}
|
}
|
||||||
|
|
||||||
let emitter = EmitterWriter::new(Box::new(Shared { data: output.clone() }),
|
let emitter = EmitterWriter::new(
|
||||||
Some(source_map.clone()),
|
Box::new(Shared { data: output.clone() }),
|
||||||
false,
|
Some(source_map.clone()),
|
||||||
false,
|
false,
|
||||||
false);
|
false,
|
||||||
|
false,
|
||||||
|
None,
|
||||||
|
);
|
||||||
let handler = Handler::with_emitter(true, None, Box::new(emitter));
|
let handler = Handler::with_emitter(true, None, Box::new(emitter));
|
||||||
handler.span_err(msp, "foo");
|
handler.span_err(msp, "foo");
|
||||||
|
|
||||||
|
|
|
@ -37,8 +37,8 @@ LL | asm!("mov sp, $0"::"r"(addr),
|
||||||
error[E0669]: invalid value for constraint in inline assembly
|
error[E0669]: invalid value for constraint in inline assembly
|
||||||
--> $DIR/inline-asm-bad-operand.rs:56:32
|
--> $DIR/inline-asm-bad-operand.rs:56:32
|
||||||
|
|
|
|
||||||
LL | "r"("hello e0669"));
|
LL | ... "r"("hello e0669"));
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 7 previous errors
|
error: aborting due to 7 previous errors
|
||||||
|
|
||||||
|
|
|
@ -67,14 +67,14 @@ LL | deprecated_unstable_text();
|
||||||
warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
|
warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
|
||||||
--> $DIR/lint-stability-deprecated.rs:57:9
|
--> $DIR/lint-stability-deprecated.rs:57:9
|
||||||
|
|
|
|
||||||
LL | Trait::trait_deprecated_unstable_text(&foo);
|
LL | ... Trait::trait_deprecated_unstable_text(&foo);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
|
warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
|
||||||
--> $DIR/lint-stability-deprecated.rs:59:9
|
--> $DIR/lint-stability-deprecated.rs:59:9
|
||||||
|
|
|
|
||||||
LL | <Foo as Trait>::trait_deprecated_unstable_text(&foo);
|
LL | ... <Foo as Trait>::trait_deprecated_unstable_text(&foo);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
warning: use of deprecated item 'lint_stability::DeprecatedStruct': text
|
warning: use of deprecated item 'lint_stability::DeprecatedStruct': text
|
||||||
--> $DIR/lint-stability-deprecated.rs:106:17
|
--> $DIR/lint-stability-deprecated.rs:106:17
|
||||||
|
@ -181,14 +181,14 @@ LL | <Foo as Trait>::trait_deprecated_unstable(&foo);
|
||||||
warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
|
warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
|
||||||
--> $DIR/lint-stability-deprecated.rs:155:9
|
--> $DIR/lint-stability-deprecated.rs:155:9
|
||||||
|
|
|
|
||||||
LL | Trait::trait_deprecated_unstable_text(&foo);
|
LL | ... Trait::trait_deprecated_unstable_text(&foo);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
|
warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
|
||||||
--> $DIR/lint-stability-deprecated.rs:157:9
|
--> $DIR/lint-stability-deprecated.rs:157:9
|
||||||
|
|
|
|
||||||
LL | <Foo as Trait>::trait_deprecated_unstable_text(&foo);
|
LL | ... <Foo as Trait>::trait_deprecated_unstable_text(&foo);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
warning: use of deprecated item 'lint_stability::DeprecatedTrait': text
|
warning: use of deprecated item 'lint_stability::DeprecatedTrait': text
|
||||||
--> $DIR/lint-stability-deprecated.rs:185:10
|
--> $DIR/lint-stability-deprecated.rs:185:10
|
||||||
|
@ -421,20 +421,20 @@ LL | <Foo>::trait_deprecated_unstable(&foo);
|
||||||
warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable_text': text
|
warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable_text': text
|
||||||
--> $DIR/lint-stability-deprecated.rs:53:13
|
--> $DIR/lint-stability-deprecated.rs:53:13
|
||||||
|
|
|
|
||||||
LL | foo.method_deprecated_unstable_text();
|
LL | ... foo.method_deprecated_unstable_text();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable_text': text
|
warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable_text': text
|
||||||
--> $DIR/lint-stability-deprecated.rs:54:9
|
--> $DIR/lint-stability-deprecated.rs:54:9
|
||||||
|
|
|
|
||||||
LL | Foo::method_deprecated_unstable_text(&foo);
|
LL | ... Foo::method_deprecated_unstable_text(&foo);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable_text': text
|
warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable_text': text
|
||||||
--> $DIR/lint-stability-deprecated.rs:55:9
|
--> $DIR/lint-stability-deprecated.rs:55:9
|
||||||
|
|
|
|
||||||
LL | <Foo>::method_deprecated_unstable_text(&foo);
|
LL | ... <Foo>::method_deprecated_unstable_text(&foo);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
|
warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
|
||||||
--> $DIR/lint-stability-deprecated.rs:56:13
|
--> $DIR/lint-stability-deprecated.rs:56:13
|
||||||
|
@ -445,8 +445,8 @@ LL | foo.trait_deprecated_unstable_text();
|
||||||
warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
|
warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
|
||||||
--> $DIR/lint-stability-deprecated.rs:58:9
|
--> $DIR/lint-stability-deprecated.rs:58:9
|
||||||
|
|
|
|
||||||
LL | <Foo>::trait_deprecated_unstable_text(&foo);
|
LL | ... <Foo>::trait_deprecated_unstable_text(&foo);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
warning: use of deprecated item 'lint_stability::DeprecatedStruct::i': text
|
warning: use of deprecated item 'lint_stability::DeprecatedStruct::i': text
|
||||||
--> $DIR/lint-stability-deprecated.rs:107:13
|
--> $DIR/lint-stability-deprecated.rs:107:13
|
||||||
|
@ -505,8 +505,8 @@ LL | foo.trait_deprecated_unstable_text();
|
||||||
warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
|
warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
|
||||||
--> $DIR/lint-stability-deprecated.rs:156:9
|
--> $DIR/lint-stability-deprecated.rs:156:9
|
||||||
|
|
|
|
||||||
LL | <Foo>::trait_deprecated_unstable_text(&foo);
|
LL | ... <Foo>::trait_deprecated_unstable_text(&foo);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
|
warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
|
||||||
--> $DIR/lint-stability-deprecated.rs:173:13
|
--> $DIR/lint-stability-deprecated.rs:173:13
|
||||||
|
|
|
@ -49,14 +49,14 @@ LL | fn fn_types(a: &'a isize,
|
||||||
error[E0261]: use of undeclared lifetime name `'b`
|
error[E0261]: use of undeclared lifetime name `'b`
|
||||||
--> $DIR/regions-name-undeclared.rs:42:36
|
--> $DIR/regions-name-undeclared.rs:42:36
|
||||||
|
|
|
|
||||||
LL | &'b isize,
|
LL | ... &'b isize,
|
||||||
| ^^ undeclared lifetime
|
| ^^ undeclared lifetime
|
||||||
|
|
||||||
error[E0261]: use of undeclared lifetime name `'b`
|
error[E0261]: use of undeclared lifetime name `'b`
|
||||||
--> $DIR/regions-name-undeclared.rs:45:36
|
--> $DIR/regions-name-undeclared.rs:45:36
|
||||||
|
|
|
|
||||||
LL | &'b isize)>,
|
LL | ... &'b isize)>,
|
||||||
| ^^ undeclared lifetime
|
| ^^ undeclared lifetime
|
||||||
|
|
||||||
error[E0261]: use of undeclared lifetime name `'a`
|
error[E0261]: use of undeclared lifetime name `'a`
|
||||||
--> $DIR/regions-name-undeclared.rs:46:17
|
--> $DIR/regions-name-undeclared.rs:46:17
|
||||||
|
|
6
src/test/ui/terminal-width/non-whitespace-trimming-2.rs
Normal file
6
src/test/ui/terminal-width/non-whitespace-trimming-2.rs
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
// ignore-tidy-linelength
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _: usize = 0; let _: usize = 1; let _: usize = 2; let _: usize = 3; let _: usize = 4; let _: usize = 5; let _: usize = 6; let _: usize = 7; let _: usize = 8; let _: usize = 9; let _: usize = 10; let _: usize = 11; let _: usize = 12; let _: usize = 13; let _: usize = 14; let _: usize = 15; let _: () = 42; let _: usize = 0; let _: usize = 1; let _: usize = 2; let _: usize = 3; let _: usize = 4; let _: usize = 5; let _: usize = 6; let _: usize = 7; let _: usize = 8; let _: usize = 9; let _: usize = 10; let _: usize = 11; let _: usize = 12; let _: usize = 13; let _: usize = 14; let _: usize = 15;
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
}
|
12
src/test/ui/terminal-width/non-whitespace-trimming-2.stderr
Normal file
12
src/test/ui/terminal-width/non-whitespace-trimming-2.stderr
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/non-whitespace-trimming-2.rs:4:311
|
||||||
|
|
|
||||||
|
LL | ...; let _: usize = 14; let _: usize = 15; let _: () = 42; let _: usize = 0; let _: usize = 1; let _: usize = 2; let _: usize = 3; let _:...
|
||||||
|
| ^^ expected (), found integer
|
||||||
|
|
|
||||||
|
= note: expected type `()`
|
||||||
|
found type `{integer}`
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
|
@ -0,0 +1,6 @@
|
||||||
|
// ignore-tidy-linelength
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _: &str = "🦀☀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓ ☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷☸☹☺☻☼☽☾☿♀♁♂♃♄♅♆♇♏♔♕♖♗♘♙♚♛♜♝♞♟♠♡♢♣♤♥♦♧♨♩♪♫♬♭♮♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀⚁⚂⚃⚄⚅⚆⚈⚉4🦀☀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷☸☹☺☻☼☽☾☿♀♁♂♃♄♅♆♇♏♔♕♖♗♘♙♚♛♜♝♞♟♠♡♢♣♤♥♦♧♨♩♪♫♬♭♮♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀⚁⚂⚃⚄⚅⚆⚈⚉4🦀🦀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷☸☹☺☻☼☽☾☿♀♁♂♃♄♅♆♇♏♔♕♖♗♘♙♚♛♜♝♞♟♠♡♢♣♤♥♦♧♨♩♪♫♬♭♮♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀⚁⚂⚃⚄⚅⚆⚈⚉4"; let _: () = 42; let _: &str = "🦀☀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓ ☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷☸☹☺☻☼☽☾☿♀♁♂♃♄♅♆♇♏♔♕♖♗♘♙♚♛♜♝♞♟♠♡♢♣♤♥♦♧♨♩♪♫♬♭♮♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀⚁⚂⚃⚄⚅⚆⚈⚉4🦀☀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷☸☹☺☻☼☽☾☿♀♁♂♃♄♅♆♇♏♔♕♖♗♘♙♚♛♜♝♞♟♠♡♢♣♤♥♦♧♨♩♪♫♬♭♮♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀⚁⚂⚃⚄⚅⚆⚈⚉4🦀🦀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷☸☹☺☻☼☽☾☿♀♁♂♃♄♅♆♇♏♔♕♖♗♘♙♚♛♜♝♞♟♠♡♢♣♤♥♦♧♨♩♪♫♬♭♮♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀⚁⚂⚃⚄⚅⚆⚈⚉4";
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/non-whitespace-trimming-unicode.rs:4:415
|
||||||
|
|
|
||||||
|
LL | ...♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀⚁⚂⚃⚄⚅⚆⚈⚉4"; let _: () = 42; let _: &str = "🦀☀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓ ☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷☸☹☺☻☼☽☾☿♀♁♂♃♄♅♆...
|
||||||
|
| ^^ expected (), found integer
|
||||||
|
|
|
||||||
|
= note: expected type `()`
|
||||||
|
found type `{integer}`
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
6
src/test/ui/terminal-width/non-whitespace-trimming.rs
Normal file
6
src/test/ui/terminal-width/non-whitespace-trimming.rs
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
// ignore-tidy-linelength
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = 42; let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = ();
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
}
|
12
src/test/ui/terminal-width/non-whitespace-trimming.stderr
Normal file
12
src/test/ui/terminal-width/non-whitespace-trimming.stderr
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/non-whitespace-trimming.rs:4:241
|
||||||
|
|
|
||||||
|
LL | ...) = (); let _: () = (); let _: () = (); let _: () = 42; let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = ()...
|
||||||
|
| ^^ expected (), found integer
|
||||||
|
|
|
||||||
|
= note: expected type `()`
|
||||||
|
found type `{integer}`
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
8
src/test/ui/terminal-width/whitespace-trimming-2.rs
Normal file
8
src/test/ui/terminal-width/whitespace-trimming-2.rs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
// ignore-tidy-linelength
|
||||||
|
|
||||||
|
fn foo() -> usize {
|
||||||
|
()
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
14
src/test/ui/terminal-width/whitespace-trimming-2.stderr
Normal file
14
src/test/ui/terminal-width/whitespace-trimming-2.stderr
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/whitespace-trimming-2.rs:4:187
|
||||||
|
|
|
||||||
|
LL | ...-> usize {
|
||||||
|
| ----- expected `usize` because of return type
|
||||||
|
LL | ... ()
|
||||||
|
| ^^ expected usize, found ()
|
||||||
|
|
|
||||||
|
= note: expected type `usize`
|
||||||
|
found type `()`
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
6
src/test/ui/terminal-width/whitespace-trimming.rs
Normal file
6
src/test/ui/terminal-width/whitespace-trimming.rs
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
// ignore-tidy-linelength
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _: () = 42;
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
}
|
12
src/test/ui/terminal-width/whitespace-trimming.stderr
Normal file
12
src/test/ui/terminal-width/whitespace-trimming.stderr
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/whitespace-trimming.rs:4:193
|
||||||
|
|
|
||||||
|
LL | ... let _: () = 42;
|
||||||
|
| ^^ expected (), found integer
|
||||||
|
|
|
||||||
|
= note: expected type `()`
|
||||||
|
found type `{integer}`
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
|
@ -162,6 +162,7 @@ const WHITELIST: &[Crate<'_>] = &[
|
||||||
Crate("termcolor"),
|
Crate("termcolor"),
|
||||||
Crate("terminon"),
|
Crate("terminon"),
|
||||||
Crate("termion"),
|
Crate("termion"),
|
||||||
|
Crate("term_size"),
|
||||||
Crate("thread_local"),
|
Crate("thread_local"),
|
||||||
Crate("ucd-util"),
|
Crate("ucd-util"),
|
||||||
Crate("unicode-width"),
|
Crate("unicode-width"),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue