@@ -15,6 +15,8 @@ use metadata::filesearch;
15
15
use session:: search_paths:: PathKind ;
16
16
use util:: nodemap:: NodeMap ;
17
17
18
+ use regex:: Regex ;
19
+
18
20
use syntax:: ast:: NodeId ;
19
21
use syntax:: codemap:: Span ;
20
22
use syntax:: diagnostic:: { self , Emitter } ;
@@ -71,7 +73,58 @@ impl Session {
71
73
self . diagnostic ( ) . handler ( ) . fatal ( msg)
72
74
}
73
75
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[ ] )
75
128
}
76
129
pub fn span_err_with_code ( & self , sp : Span , msg : & str , code : & str ) {
77
130
self . diagnostic ( ) . span_err_with_code ( sp, msg, code)
0 commit comments