Skip to content

Commit b30022a

Browse files
authored
Auto merge of #37369 - estebank:multiline-span, r=nikomatsakis
Show multiline spans in full if short enough When dealing with multiline spans that span few lines, show the complete span instead of restricting to the first character of the first line. For example, instead of: ``` % ./rustc file2.rs error[E0277]: the trait bound `{integer}: std::ops::Add<()>` is not satisfied --> file2.rs:13:9 | 13 | foo(1 + bar(x, | ^ trait `{integer}: std::ops::Add<()>` not satisfied | ``` show ``` % ./rustc file2.rs error[E0277]: the trait bound `{integer}: std::ops::Add<()>` is not satisfied --> file2.rs:13:9 | 13 | foo(1 + bar(x, | ________^ starting here... 14 | | y), | |_____________^ ...ending here: trait `{integer}: std::ops::Add<()>` not satisfied | ``` The [proposal in internals](https://internals.rust-lang.org/t/proposal-for-multiline-span-comments/4242/6) outlines the reasoning behind this.
2 parents f50dbd5 + b7982bb commit b30022a

15 files changed

+1158
-144
lines changed

src/librustc_errors/emitter.rs

+353-105
Large diffs are not rendered by default.

src/librustc_errors/snippet.rs

+104-3
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,86 @@ pub struct Line {
4141
pub annotations: Vec<Annotation>,
4242
}
4343

44+
45+
#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
46+
pub struct MultilineAnnotation {
47+
pub depth: usize,
48+
pub line_start: usize,
49+
pub line_end: usize,
50+
pub start_col: usize,
51+
pub end_col: usize,
52+
pub is_primary: bool,
53+
pub label: Option<String>,
54+
}
55+
56+
impl MultilineAnnotation {
57+
pub fn increase_depth(&mut self) {
58+
self.depth += 1;
59+
}
60+
61+
pub fn as_start(&self) -> Annotation {
62+
Annotation {
63+
start_col: self.start_col,
64+
end_col: self.start_col + 1,
65+
is_primary: self.is_primary,
66+
label: Some("starting here...".to_owned()),
67+
annotation_type: AnnotationType::MultilineStart(self.depth)
68+
}
69+
}
70+
71+
pub fn as_end(&self) -> Annotation {
72+
Annotation {
73+
start_col: self.end_col - 1,
74+
end_col: self.end_col,
75+
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+
},
80+
annotation_type: AnnotationType::MultilineEnd(self.depth)
81+
}
82+
}
83+
84+
pub fn as_line(&self) -> Annotation {
85+
Annotation {
86+
start_col: 0,
87+
end_col: 0,
88+
is_primary: self.is_primary,
89+
label: None,
90+
annotation_type: AnnotationType::MultilineLine(self.depth)
91+
}
92+
}
93+
}
94+
95+
#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
96+
pub enum AnnotationType {
97+
/// Annotation under a single line of code
98+
Singleline,
99+
100+
/// Annotation under the first character of a multiline span
101+
Minimized,
102+
103+
/// Annotation enclosing the first and last character of a multiline span
104+
Multiline(MultilineAnnotation),
105+
106+
// The Multiline type above is replaced with the following three in order
107+
// to reuse the current label drawing code.
108+
//
109+
// Each of these corresponds to one part of the following diagram:
110+
//
111+
// x | foo(1 + bar(x,
112+
// | _________^ starting here... < MultilineStart
113+
// x | | y), < MultilineLine
114+
// | |______________^ ...ending here: label < MultilineEnd
115+
// x | z);
116+
/// Annotation marking the first character of a fully shown multiline span
117+
MultilineStart(usize),
118+
/// Annotation marking the last character of a fully shown multiline span
119+
MultilineEnd(usize),
120+
/// Line at the left enclosing the lines of a fully shown multiline span
121+
MultilineLine(usize),
122+
}
123+
44124
#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
45125
pub struct Annotation {
46126
/// Start column, 0-based indexing -- counting *characters*, not
@@ -55,11 +135,32 @@ pub struct Annotation {
55135
/// Is this annotation derived from primary span
56136
pub is_primary: bool,
57137

58-
/// Is this a large span minimized down to a smaller span
59-
pub is_minimized: bool,
60-
61138
/// Optional label to display adjacent to the annotation.
62139
pub label: Option<String>,
140+
141+
/// Is this a single line, multiline or multiline span minimized down to a
142+
/// smaller span.
143+
pub annotation_type: AnnotationType,
144+
}
145+
146+
impl Annotation {
147+
pub fn is_minimized(&self) -> bool {
148+
match self.annotation_type {
149+
AnnotationType::Minimized => true,
150+
_ => false,
151+
}
152+
}
153+
154+
pub fn is_multiline(&self) -> bool {
155+
match self.annotation_type {
156+
AnnotationType::Multiline(_) |
157+
AnnotationType::MultilineStart(_) |
158+
AnnotationType::MultilineLine(_) |
159+
AnnotationType::MultilineEnd(_) => true,
160+
_ => false,
161+
}
162+
}
163+
63164
}
64165

65166
#[derive(Debug)]

src/libsyntax/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -145,4 +145,7 @@ pub mod ext {
145145
}
146146
}
147147

148+
#[cfg(test)]
149+
mod test_snippet;
150+
148151
// __build_diagnostic_array! { libsyntax, DIAGNOSTICS }

0 commit comments

Comments
 (0)