Skip to content

Commit 4ed9500

Browse files
committed
Auto merge of #41245 - estebank:multiline-trim, r=nikomatsakis
Reduce visual clutter of multiline start when possible When a span starts on a line with nothing but whitespace to the left, and there are no other annotations in that line, simplify the visual representation of the span. Go from: ```rust error[E0072]: recursive type `A` has infinite size --> file2.rs:1:1 | 1 | struct A { | _^ starting here... 2 | | a: A, 3 | | } | |_^ ...ending here: recursive type has infinite size | ``` To: ```rust error[E0072]: recursive type `A` has infinite size --> file2.rs:1:1 | 1 | / struct A { 2 | | a: A, 3 | | } | |_^ recursive type has infinite size ``` Re: #38246. r? @nikomatsakis CC @jonathandturner
2 parents 535ee6c + cc07c35 commit 4ed9500

26 files changed

+200
-179
lines changed

src/librustc_errors/emitter.rs

+54-13
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,41 @@ impl EmitterWriter {
263263

264264
draw_col_separator(buffer, line_offset, width_offset - 2);
265265

266+
// Special case when there's only one annotation involved, it is the start of a multiline
267+
// span and there's no text at the beginning of the code line. Instead of doing the whole
268+
// graph:
269+
//
270+
// 2 | fn foo() {
271+
// | _^
272+
// 3 | |
273+
// 4 | | }
274+
// | |_^ test
275+
//
276+
// we simplify the output to:
277+
//
278+
// 2 | / fn foo() {
279+
// 3 | |
280+
// 4 | | }
281+
// | |_^ test
282+
if line.annotations.len() == 1 {
283+
if let Some(ref ann) = line.annotations.get(0) {
284+
if let AnnotationType::MultilineStart(depth) = ann.annotation_type {
285+
if source_string[0..ann.start_col].trim() == "" {
286+
let style = if ann.is_primary {
287+
Style::UnderlinePrimary
288+
} else {
289+
Style::UnderlineSecondary
290+
};
291+
buffer.putc(line_offset,
292+
width_offset + depth - 1,
293+
'/',
294+
style);
295+
return vec![(depth, style)];
296+
}
297+
}
298+
}
299+
}
300+
266301
// We want to display like this:
267302
//
268303
// vec.push(vec.pop().unwrap());
@@ -355,10 +390,8 @@ impl EmitterWriter {
355390
for (i, annotation) in annotations.iter().enumerate() {
356391
for (j, next) in annotations.iter().enumerate() {
357392
if overlaps(next, annotation, 0) // This label overlaps with another one and both
358-
&& !annotation.is_line() // take space (they have text and are not
359-
&& !next.is_line() // multiline lines).
360-
&& annotation.has_label()
361-
&& j > i
393+
&& annotation.has_label() // take space (they have text and are not
394+
&& j > i // multiline lines).
362395
&& p == 0 // We're currently on the first line, move the label one line down
363396
{
364397
// This annotation needs a new line in the output.
@@ -374,7 +407,7 @@ impl EmitterWriter {
374407
} else {
375408
0
376409
};
377-
if overlaps(next, annotation, l) // Do not allow two labels to be in the same
410+
if (overlaps(next, annotation, l) // Do not allow two labels to be in the same
378411
// line if they overlap including padding, to
379412
// avoid situations like:
380413
//
@@ -383,11 +416,18 @@ impl EmitterWriter {
383416
// | |
384417
// fn_spanx_span
385418
//
386-
&& !annotation.is_line() // Do not add a new line if this annotation
387-
&& !next.is_line() // or the next are vertical line placeholders.
388419
&& annotation.has_label() // Both labels must have some text, otherwise
389-
&& next.has_label() // they are not overlapping.
420+
&& next.has_label()) // they are not overlapping.
421+
// Do not add a new line if this annotation
422+
// or the next are vertical line placeholders.
423+
|| (annotation.takes_space() // If either this or the next annotation is
424+
&& next.has_label()) // multiline start/end, move it to a new line
425+
|| (annotation.has_label() // so as not to overlap the orizontal lines.
426+
&& next.takes_space())
427+
|| (annotation.takes_space()
428+
&& next.takes_space())
390429
{
430+
// This annotation needs a new line in the output.
391431
p += 1;
392432
break;
393433
}
@@ -397,6 +437,7 @@ impl EmitterWriter {
397437
line_len = p;
398438
}
399439
}
440+
400441
if line_len != 0 {
401442
line_len += 1;
402443
}
@@ -480,7 +521,7 @@ impl EmitterWriter {
480521
};
481522
let pos = pos + 1;
482523

483-
if pos > 1 && annotation.has_label() {
524+
if pos > 1 && (annotation.has_label() || annotation.takes_space()) {
484525
for p in line_offset + 1..line_offset + pos + 1 {
485526
buffer.putc(p,
486527
code_offset + annotation.start_col,
@@ -514,12 +555,12 @@ impl EmitterWriter {
514555
// After this we will have:
515556
//
516557
// 2 | fn foo() {
517-
// | __________ starting here...
558+
// | __________
518559
// | |
519560
// | something about `foo`
520561
// 3 |
521562
// 4 | }
522-
// | _ ...ending here: test
563+
// | _ test
523564
for &(pos, annotation) in &annotations_position {
524565
let style = if annotation.is_primary {
525566
Style::LabelPrimary
@@ -557,12 +598,12 @@ impl EmitterWriter {
557598
// After this we will have:
558599
//
559600
// 2 | fn foo() {
560-
// | ____-_____^ starting here...
601+
// | ____-_____^
561602
// | |
562603
// | something about `foo`
563604
// 3 |
564605
// 4 | }
565-
// | _^ ...ending here: test
606+
// | _^ test
566607
for &(_, annotation) in &annotations_position {
567608
let (underline, style) = if annotation.is_primary {
568609
('^', Style::UnderlinePrimary)

src/librustc_errors/snippet.rs

+14-8
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ impl MultilineAnnotation {
6363
start_col: self.start_col,
6464
end_col: self.start_col + 1,
6565
is_primary: self.is_primary,
66-
label: Some("starting here...".to_owned()),
66+
label: None,
6767
annotation_type: AnnotationType::MultilineStart(self.depth)
6868
}
6969
}
@@ -73,10 +73,7 @@ impl MultilineAnnotation {
7373
start_col: self.end_col - 1,
7474
end_col: self.end_col,
7575
is_primary: self.is_primary,
76-
label: match self.label {
77-
Some(ref label) => Some(format!("...ending here: {}", label)),
78-
None => Some("...ending here".to_owned()),
79-
},
76+
label: self.label.clone(),
8077
annotation_type: AnnotationType::MultilineEnd(self.depth)
8178
}
8279
}
@@ -106,9 +103,9 @@ pub enum AnnotationType {
106103
// Each of these corresponds to one part of the following diagram:
107104
//
108105
// x | foo(1 + bar(x,
109-
// | _________^ starting here... < MultilineStart
110-
// x | | y), < MultilineLine
111-
// | |______________^ ...ending here: label < MultilineEnd
106+
// | _________^ < MultilineStart
107+
// x | | y), < MultilineLine
108+
// | |______________^ label < MultilineEnd
112109
// x | z);
113110
/// Annotation marking the first character of a fully shown multiline span
114111
MultilineStart(usize),
@@ -189,6 +186,15 @@ impl Annotation {
189186
false
190187
}
191188
}
189+
190+
pub fn takes_space(&self) -> bool {
191+
// Multiline annotations always have to keep vertical space.
192+
match self.annotation_type {
193+
AnnotationType::MultilineStart(_) |
194+
AnnotationType::MultilineEnd(_) => true,
195+
_ => false,
196+
}
197+
}
192198
}
193199

194200
#[derive(Debug)]

0 commit comments

Comments
 (0)