about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/compiletest/runtest.rs12
-rw-r--r--src/librustc/lib.rs1
-rw-r--r--src/librustc/session/mod.rs55
3 files changed, 66 insertions, 2 deletions
diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs
index 5de93c52029..5579479c5e5 100644
--- a/src/compiletest/runtest.rs
+++ b/src/compiletest/runtest.rs
@@ -966,6 +966,16 @@ fn check_expected_errors(expected_errors: Vec<errors::ExpectedError> ,
         line.starts_with( prefix )
     }
 
+    // A multi-line error will have followup lines which will always
+    // start with one of these strings.
+    fn continuation( line: &str) -> bool {
+        line.starts_with(" expected") ||
+        line.starts_with("    found") ||
+        //                1234
+        // Should have 4 spaces: see issue 18946
+        line.starts_with("(")
+    }
+
     // Scan and extract our error/warning messages,
     // which look like:
     //    filename:line1:col1: line2:col2: *error:* msg
@@ -981,7 +991,7 @@ fn check_expected_errors(expected_errors: Vec<errors::ExpectedError> ,
                        ee.kind,
                        ee.msg,
                        line);
-                if prefix_matches(line, prefixes[i].as_slice()) &&
+                if (prefix_matches(line, prefixes[i].as_slice()) || continuation(line)) &&
                     line.contains(ee.kind.as_slice()) &&
                     line.contains(ee.msg.as_slice()) {
                     found_flags[i] = true;
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index fb7c5296d02..eb6c49f6ad0 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -35,6 +35,7 @@ extern crate flate;
 extern crate getopts;
 extern crate graphviz;
 extern crate libc;
+extern crate regex;
 extern crate rustc_llvm;
 extern crate rustc_back;
 extern crate serialize;
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index 26d5a9daf89..27acc39c778 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -15,6 +15,8 @@ use metadata::filesearch;
 use session::search_paths::PathKind;
 use util::nodemap::NodeMap;
 
+use regex::Regex;
+
 use syntax::ast::NodeId;
 use syntax::codemap::Span;
 use syntax::diagnostic::{self, Emitter};
@@ -71,7 +73,58 @@ impl Session {
         self.diagnostic().handler().fatal(msg)
     }
     pub fn span_err(&self, sp: Span, msg: &str) {
-        self.diagnostic().span_err(sp, msg)
+        // Conditions for enabling multi-line errors:
+        if !msg.contains("mismatched types") &&
+           !msg.contains("type mismatch resolving") &&
+           !msg.contains("if and else have incompatible types") &&
+           !msg.contains("if may be missing an else clause") &&
+           !msg.contains("match arms have incompatible types") &&
+           !msg.contains("structure constructor specifies a structure of type") {
+            return self.diagnostic().span_err(sp, msg);
+        }
+
+        let first  = Regex::new(r"[( ]expected").unwrap();
+        let second = Regex::new(r" found").unwrap();
+        let third  = Regex::new(
+                     r"\((values differ|lifetime|cyclic type of infinite size)").unwrap();
+
+        let mut new_msg = String::new();
+        let mut head = 0u;
+
+        // Insert `\n` before expected and found.
+        for (pos1, pos2) in first.find_iter(msg).zip(
+                            second.find_iter(msg)) {
+            new_msg = new_msg +
+            // A `(` may be preceded by a space and it should be trimmed
+                      msg[head..pos1.0].trim_right() + // prefix
+                      "\n" +                           // insert before first
+                      &msg[pos1.0..pos1.1] +           // insert what first matched
+                      &msg[pos1.1..pos2.0] +           // between matches
+                      "\n   " +                        // insert before second
+            //           123
+            // `expected` is 3 char longer than `found`. To align the types, `found` gets
+            // 3 spaces prepended.
+                      &msg[pos2.0..pos2.1];            // insert what second matched
+
+            head = pos2.1;
+        }
+
+        let mut tail = &msg[head..];
+        // Insert `\n` before any remaining messages which match.
+        for pos in third.find_iter(tail).take(1) {
+            // The end of the message may just be wrapped in `()` without `expected`/`found`.
+            // Push this also to a new line and add the final tail after.
+            new_msg = new_msg +
+            // `(` is usually preceded by a space and should be trimmed.
+                      tail[..pos.0].trim_right() + // prefix
+                      "\n" +                       // insert before paren
+                      &tail[pos.0..];              // append the tail
+
+            tail = "";
+        }
+
+        new_msg.push_str(tail);
+        self.diagnostic().span_err(sp, &new_msg[])
     }
     pub fn span_err_with_code(&self, sp: Span, msg: &str, code: &str) {
         self.diagnostic().span_err_with_code(sp, msg, code)