Skip to content

Commit 876b266

Browse files
committed
Make multiline errors work with codes
1 parent 9a4401f commit 876b266

File tree

1 file changed

+63
-52
lines changed

1 file changed

+63
-52
lines changed

src/librustc/session/mod.rs

+63-52
Original file line numberDiff line numberDiff line change
@@ -76,61 +76,16 @@ impl Session {
7676
self.diagnostic().handler().fatal(msg)
7777
}
7878
pub fn span_err(&self, sp: Span, msg: &str) {
79-
// Conditions for enabling multi-line errors:
80-
if !msg.contains("mismatched types") &&
81-
!msg.contains("type mismatch resolving") &&
82-
!msg.contains("if and else have incompatible types") &&
83-
!msg.contains("if may be missing an else clause") &&
84-
!msg.contains("match arms have incompatible types") &&
85-
!msg.contains("structure constructor specifies a structure of type") {
86-
return self.diagnostic().span_err(sp, msg);
79+
match split_msg_into_multilines(msg) {
80+
Some(msg) => self.diagnostic().span_err(sp, &msg[]),
81+
None => self.diagnostic().span_err(sp, msg)
8782
}
88-
89-
let first = Regex::new(r"[( ]expected").unwrap();
90-
let second = Regex::new(r" found").unwrap();
91-
let third = Regex::new(
92-
r"\((values differ|lifetime|cyclic type of infinite size)").unwrap();
93-
94-
let mut new_msg = String::new();
95-
let mut head = 0u;
96-
97-
// Insert `\n` before expected and found.
98-
for (pos1, pos2) in first.find_iter(msg).zip(
99-
second.find_iter(msg)) {
100-
new_msg = new_msg +
101-
// A `(` may be preceded by a space and it should be trimmed
102-
msg[head..pos1.0].trim_right() + // prefix
103-
"\n" + // insert before first
104-
&msg[pos1.0..pos1.1] + // insert what first matched
105-
&msg[pos1.1..pos2.0] + // between matches
106-
"\n " + // insert before second
107-
// 123
108-
// `expected` is 3 char longer than `found`. To align the types, `found` gets
109-
// 3 spaces prepended.
110-
&msg[pos2.0..pos2.1]; // insert what second matched
111-
112-
head = pos2.1;
113-
}
114-
115-
let mut tail = &msg[head..];
116-
// Insert `\n` before any remaining messages which match.
117-
for pos in third.find_iter(tail).take(1) {
118-
// The end of the message may just be wrapped in `()` without `expected`/`found`.
119-
// Push this also to a new line and add the final tail after.
120-
new_msg = new_msg +
121-
// `(` is usually preceded by a space and should be trimmed.
122-
tail[..pos.0].trim_right() + // prefix
123-
"\n" + // insert before paren
124-
&tail[pos.0..]; // append the tail
125-
126-
tail = "";
127-
}
128-
129-
new_msg.push_str(tail);
130-
self.diagnostic().span_err(sp, &new_msg[])
13183
}
13284
pub fn span_err_with_code(&self, sp: Span, msg: &str, code: &str) {
133-
self.diagnostic().span_err_with_code(sp, msg, code)
85+
match split_msg_into_multilines(msg) {
86+
Some(msg) => self.diagnostic().span_err_with_code(sp, &msg[], code),
87+
None => self.diagnostic().span_err_with_code(sp, msg, code)
88+
}
13489
}
13590
pub fn err(&self, msg: &str) {
13691
self.diagnostic().handler().err(msg)
@@ -288,6 +243,62 @@ impl Session {
288243
}
289244
}
290245

246+
fn split_msg_into_multilines(msg: &str) -> Option<String> {
247+
// Conditions for enabling multi-line errors:
248+
if !msg.contains("mismatched types") &&
249+
!msg.contains("type mismatch resolving") &&
250+
!msg.contains("if and else have incompatible types") &&
251+
!msg.contains("if may be missing an else clause") &&
252+
!msg.contains("match arms have incompatible types") &&
253+
!msg.contains("structure constructor specifies a structure of type") {
254+
return None
255+
}
256+
257+
let first = Regex::new(r"[( ]expected").unwrap();
258+
let second = Regex::new(r" found").unwrap();
259+
let third = Regex::new(
260+
r"\((values differ|lifetime|cyclic type of infinite size)").unwrap();
261+
262+
let mut new_msg = String::new();
263+
let mut head = 0u;
264+
265+
// Insert `\n` before expected and found.
266+
for (pos1, pos2) in first.find_iter(msg).zip(
267+
second.find_iter(msg)) {
268+
new_msg = new_msg +
269+
// A `(` may be preceded by a space and it should be trimmed
270+
msg[head..pos1.0].trim_right() + // prefix
271+
"\n" + // insert before first
272+
&msg[pos1.0..pos1.1] + // insert what first matched
273+
&msg[pos1.1..pos2.0] + // between matches
274+
"\n " + // insert before second
275+
// 123
276+
// `expected` is 3 char longer than `found`. To align the types, `found` gets
277+
// 3 spaces prepended.
278+
&msg[pos2.0..pos2.1]; // insert what second matched
279+
280+
head = pos2.1;
281+
}
282+
283+
let mut tail = &msg[head..];
284+
// Insert `\n` before any remaining messages which match.
285+
for pos in third.find_iter(tail).take(1) {
286+
// The end of the message may just be wrapped in `()` without `expected`/`found`.
287+
// Push this also to a new line and add the final tail after.
288+
new_msg = new_msg +
289+
// `(` is usually preceded by a space and should be trimmed.
290+
tail[..pos.0].trim_right() + // prefix
291+
"\n" + // insert before paren
292+
&tail[pos.0..]; // append the tail
293+
294+
tail = "";
295+
}
296+
297+
new_msg.push_str(tail);
298+
299+
return Some(new_msg)
300+
}
301+
291302
pub fn build_session(sopts: config::Options,
292303
local_crate_source_file: Option<Path>,
293304
registry: diagnostics::registry::Registry)

0 commit comments

Comments
 (0)