]> git.lizzy.rs Git - rust.git/commitdiff
degrade gracefully with empty spans
authorNiko Matsakis <niko@alum.mit.edu>
Tue, 3 May 2016 10:11:20 +0000 (06:11 -0400)
committerNiko Matsakis <niko@alum.mit.edu>
Tue, 3 May 2016 10:15:39 +0000 (06:15 -0400)
src/libsyntax/errors/snippet/mod.rs
src/libsyntax/errors/snippet/test.rs

index e213f623ab85dac2e40fe4c49536fc0938f74b0e..237e6823e0f8752b6693fd8d90b4887c4479f25b 100644 (file)
@@ -376,11 +376,21 @@ fn push_lines(&mut self,
         // Basically, although this loses information, multi-line spans just
         // never look good.
 
-        let (line, start_col, end_col) = if lines.len() == 1 {
+        let (line, start_col, mut end_col) = if lines.len() == 1 {
             (lines[0].line_index, lines[0].start_col, lines[0].end_col)
         } else {
             (lines[0].line_index, lines[0].start_col, CharPos(lines[0].start_col.0 + 1))
         };
+
+        // Watch out for "empty spans". If we get a span like 6..6, we
+        // want to just display a `^` at 6, so convert that to
+        // 6..7. This is degenerate input, but it's best to degrade
+        // gracefully -- and the parser likes to suply a span like
+        // that for EOF, in particular.
+        if start_col == end_col {
+            end_col.0 += 1;
+        }
+
         let index = self.ensure_source_line(line);
         self.lines[index].push_annotation(start_col,
                                           end_col,
index 569d11199190c42ea28db9ac891b8bacbb5b65ef..5a888b488191ba0ea07b45b8e0f65796b796fc8b 100644 (file)
@@ -519,3 +519,41 @@ fn foo() {
   |>            ----- bar
 "#[1..]);
 }
+
+#[test]
+fn span_empty() {
+    // In one of the unit tests, we found that the parser sometimes
+    // gives empty spans, and in particular it supplied an EOF span
+    // like this one, which points at the very end. We want to
+    // fallback gracefully in this case.
+
+    let file_text = r#"
+fn main() {
+    struct Foo;
+
+    impl !Sync for Foo {}
+
+    unsafe impl Send for &'static Foo {
+    // error: cross-crate traits with a default impl, like `core::marker::Send`,
+    //        can only be implemented for a struct/enum type, not
+    //        `&'static Foo`
+}"#;
+
+
+    let cm = Rc::new(CodeMap::new());
+    let foo = cm.new_filemap_and_lines("foo.rs", file_text);
+
+    let mut rbrace_span = cm.span_substr(&foo, file_text, "}", 1);
+    rbrace_span.lo = rbrace_span.hi;
+
+    let mut snippet = SnippetData::new(cm.clone(), Some(rbrace_span));
+    snippet.push(rbrace_span, false, None);
+    let lines = snippet.render_lines();
+    let text: String = make_string(&lines);
+    println!("r#\"\n{}\"", text);
+    assert_eq!(text, &r#"
+  --> foo.rs:11:2
+11 |> }
+   |>  -
+"#[1..]);
+}