@@ -15,6 +15,8 @@ use metadata::filesearch;
1515use session:: search_paths:: PathKind ;
1616use util:: nodemap:: NodeMap ;
1717
18+ use regex:: Regex ;
19+
1820use syntax:: ast:: NodeId ;
1921use syntax:: codemap:: Span ;
2022use syntax:: diagnostic:: { self , Emitter } ;
@@ -71,7 +73,58 @@ impl Session {
7173 self . diagnostic ( ) . handler ( ) . fatal ( msg)
7274 }
7375 pub fn span_err ( & self , sp : Span , msg : & str ) {
74- self . diagnostic ( ) . span_err ( sp, msg)
76+ // Conditions for enabling multi-line errors:
77+ if !msg. contains ( "mismatched types" ) &&
78+ !msg. contains ( "type mismatch resolving" ) &&
79+ !msg. contains ( "if and else have incompatible types" ) &&
80+ !msg. contains ( "if may be missing an else clause" ) &&
81+ !msg. contains ( "match arms have incompatible types" ) &&
82+ !msg. contains ( "structure constructor specifies a structure of type" ) {
83+ return self . diagnostic ( ) . span_err ( sp, msg) ;
84+ }
85+
86+ let first = Regex :: new ( r"[( ]expected" ) . unwrap ( ) ;
87+ let second = Regex :: new ( r" found" ) . unwrap ( ) ;
88+ let third = Regex :: new (
89+ r"\((values differ|lifetime|cyclic type of infinite size)" ) . unwrap ( ) ;
90+
91+ let mut new_msg = String :: new ( ) ;
92+ let mut head = 0 u;
93+
94+ // Insert `\n` before expected and found.
95+ for ( pos1, pos2) in first. find_iter ( msg) . zip (
96+ second. find_iter ( msg) ) {
97+ new_msg = new_msg +
98+ // A `(` may be preceded by a space and it should be trimmed
99+ msg[ head..pos1. 0 ] . trim_right ( ) + // prefix
100+ "\n " + // insert before first
101+ & msg[ pos1. 0 ..pos1. 1 ] + // insert what first matched
102+ & msg[ pos1. 1 ..pos2. 0 ] + // between matches
103+ "\n " + // insert before second
104+ // 123
105+ // `expected` is 3 char longer than `found`. To align the types, `found` gets
106+ // 3 spaces prepended.
107+ & msg[ pos2. 0 ..pos2. 1 ] ; // insert what second matched
108+
109+ head = pos2. 1 ;
110+ }
111+
112+ let mut tail = & msg[ head..] ;
113+ // Insert `\n` before any remaining messages which match.
114+ for pos in third. find_iter ( tail) . take ( 1 ) {
115+ // The end of the message may just be wrapped in `()` without `expected`/`found`.
116+ // Push this also to a new line and add the final tail after.
117+ new_msg = new_msg +
118+ // `(` is usually preceded by a space and should be trimmed.
119+ tail[ ..pos. 0 ] . trim_right ( ) + // prefix
120+ "\n " + // insert before paren
121+ & tail[ pos. 0 ..] ; // append the tail
122+
123+ tail = "" ;
124+ }
125+
126+ new_msg. push_str ( tail) ;
127+ self . diagnostic ( ) . span_err ( sp, & new_msg[ ] )
75128 }
76129 pub fn span_err_with_code ( & self , sp : Span , msg : & str , code : & str ) {
77130 self . diagnostic ( ) . span_err_with_code ( sp, msg, code)
0 commit comments