Skip to content

Commit dfa5245

Browse files
committed
Rollup merge of rust-lang#33369 - nikomatsakis:graceful-empty-span, r=jntrnr
degrade gracefully with empty spans In rust-lang#32756, we solved the final test failure, but digging more into it the handling of that scenario could be better. The error was caused by an empty span supplied by the parser representing EOF. This patch checks that we cope more gracefully with such spans: r? @jonathandturner
2 parents 8e414e0 + f030b5d commit dfa5245

File tree

2 files changed

+49
-1
lines changed

2 files changed

+49
-1
lines changed

src/libsyntax/errors/snippet/mod.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -376,11 +376,21 @@ impl FileInfo {
376376
// Basically, although this loses information, multi-line spans just
377377
// never look good.
378378

379-
let (line, start_col, end_col) = if lines.len() == 1 {
379+
let (line, start_col, mut end_col) = if lines.len() == 1 {
380380
(lines[0].line_index, lines[0].start_col, lines[0].end_col)
381381
} else {
382382
(lines[0].line_index, lines[0].start_col, CharPos(lines[0].start_col.0 + 1))
383383
};
384+
385+
// Watch out for "empty spans". If we get a span like 6..6, we
386+
// want to just display a `^` at 6, so convert that to
387+
// 6..7. This is degenerate input, but it's best to degrade
388+
// gracefully -- and the parser likes to suply a span like
389+
// that for EOF, in particular.
390+
if start_col == end_col {
391+
end_col.0 += 1;
392+
}
393+
384394
let index = self.ensure_source_line(line);
385395
self.lines[index].push_annotation(start_col,
386396
end_col,

src/libsyntax/errors/snippet/test.rs

+38
Original file line numberDiff line numberDiff line change
@@ -519,3 +519,41 @@ fn span_overlap_label3() {
519519
|> ----- bar
520520
"#[1..]);
521521
}
522+
523+
#[test]
524+
fn span_empty() {
525+
// In one of the unit tests, we found that the parser sometimes
526+
// gives empty spans, and in particular it supplied an EOF span
527+
// like this one, which points at the very end. We want to
528+
// fallback gracefully in this case.
529+
530+
let file_text = r#"
531+
fn main() {
532+
struct Foo;
533+
534+
impl !Sync for Foo {}
535+
536+
unsafe impl Send for &'static Foo {
537+
// error: cross-crate traits with a default impl, like `core::marker::Send`,
538+
// can only be implemented for a struct/enum type, not
539+
// `&'static Foo`
540+
}"#;
541+
542+
543+
let cm = Rc::new(CodeMap::new());
544+
let foo = cm.new_filemap_and_lines("foo.rs", file_text);
545+
546+
let mut rbrace_span = cm.span_substr(&foo, file_text, "}", 1);
547+
rbrace_span.lo = rbrace_span.hi;
548+
549+
let mut snippet = SnippetData::new(cm.clone(), Some(rbrace_span));
550+
snippet.push(rbrace_span, false, None);
551+
let lines = snippet.render_lines();
552+
let text: String = make_string(&lines);
553+
println!("r#\"\n{}\"", text);
554+
assert_eq!(text, &r#"
555+
--> foo.rs:11:2
556+
11 |> }
557+
|> -
558+
"#[1..]);
559+
}

0 commit comments

Comments
 (0)