22
33use std:: path:: { Path , PathBuf } ;
44use std:: str:: FromStr ;
5+ use std:: sync:: OnceLock ;
56
7+ use regex:: Regex ;
68use serde:: Deserialize ;
79
810use crate :: errors:: { Error , ErrorKind } ;
@@ -213,36 +215,24 @@ fn push_expected_errors(
213215 // also ensure that `//~ ERROR E123` *always* works. The
214216 // assumption is that these multi-line error messages are on their
215217 // way out anyhow.
216- let with_code = |span : & DiagnosticSpan , text : & str | {
217- match diagnostic. code {
218- Some ( ref code) =>
219- // FIXME(#33000) -- it'd be better to use a dedicated
220- // UI harness than to include the line/col number like
221- // this, but some current tests rely on it.
222- //
223- // Note: Do NOT include the filename. These can easily
224- // cause false matches where the expected message
225- // appears in the filename, and hence the message
226- // changes but the test still passes.
227- {
228- format ! (
229- "{}:{}: {}:{}: {} [{}]" ,
230- span. line_start,
231- span. column_start,
232- span. line_end,
233- span. column_end,
234- text,
235- code. code. clone( )
236- )
237- }
238- None =>
239- // FIXME(#33000) -- it'd be better to use a dedicated UI harness
240- {
241- format ! (
242- "{}:{}: {}:{}: {}" ,
243- span. line_start, span. column_start, span. line_end, span. column_end, text
244- )
218+ let with_code = |span : Option < & DiagnosticSpan > , text : & str | {
219+ // FIXME(#33000) -- it'd be better to use a dedicated
220+ // UI harness than to include the line/col number like
221+ // this, but some current tests rely on it.
222+ //
223+ // Note: Do NOT include the filename. These can easily
224+ // cause false matches where the expected message
225+ // appears in the filename, and hence the message
226+ // changes but the test still passes.
227+ let span_str = match span {
228+ Some ( DiagnosticSpan { line_start, column_start, line_end, column_end, .. } ) => {
229+ format ! ( "{line_start}:{column_start}: {line_end}:{column_end}" )
245230 }
231+ None => format ! ( "?:?: ?:?" ) ,
232+ } ;
233+ match & diagnostic. code {
234+ Some ( code) => format ! ( "{span_str}: {text} [{}]" , code. code) ,
235+ None => format ! ( "{span_str}: {text}" ) ,
246236 }
247237 } ;
248238
@@ -251,19 +241,41 @@ fn push_expected_errors(
251241 // more structured shortly anyhow.
252242 let mut message_lines = diagnostic. message . lines ( ) ;
253243 if let Some ( first_line) = message_lines. next ( ) {
254- for span in primary_spans {
255- let msg = with_code ( span, first_line) ;
244+ let ignore = |s| {
245+ static RE : OnceLock < Regex > = OnceLock :: new ( ) ;
246+ RE . get_or_init ( || {
247+ Regex :: new ( r"aborting due to \d+ previous errors?|\d+ warnings? emitted" ) . unwrap ( )
248+ } )
249+ . is_match ( s)
250+ } ;
251+
252+ if primary_spans. is_empty ( ) && !ignore ( first_line) {
253+ let msg = with_code ( None , first_line) ;
256254 let kind = ErrorKind :: from_str ( & diagnostic. level ) . ok ( ) ;
257- expected_errors. push ( Error { line_num : span. line_start , kind, msg } ) ;
255+ expected_errors. push ( Error { line_num : None , kind, msg } ) ;
256+ } else {
257+ for span in primary_spans {
258+ let msg = with_code ( Some ( span) , first_line) ;
259+ let kind = ErrorKind :: from_str ( & diagnostic. level ) . ok ( ) ;
260+ expected_errors. push ( Error { line_num : Some ( span. line_start ) , kind, msg } ) ;
261+ }
258262 }
259263 }
260264 for next_line in message_lines {
261- for span in primary_spans {
265+ if primary_spans. is_empty ( ) {
262266 expected_errors. push ( Error {
263- line_num : span . line_start ,
267+ line_num : None ,
264268 kind : None ,
265- msg : with_code ( span , next_line) ,
269+ msg : with_code ( None , next_line) ,
266270 } ) ;
271+ } else {
272+ for span in primary_spans {
273+ expected_errors. push ( Error {
274+ line_num : Some ( span. line_start ) ,
275+ kind : None ,
276+ msg : with_code ( Some ( span) , next_line) ,
277+ } ) ;
278+ }
267279 }
268280 }
269281
@@ -272,7 +284,7 @@ fn push_expected_errors(
272284 if let Some ( ref suggested_replacement) = span. suggested_replacement {
273285 for ( index, line) in suggested_replacement. lines ( ) . enumerate ( ) {
274286 expected_errors. push ( Error {
275- line_num : span. line_start + index,
287+ line_num : Some ( span. line_start + index) ,
276288 kind : Some ( ErrorKind :: Suggestion ) ,
277289 msg : line. to_string ( ) ,
278290 } ) ;
@@ -290,7 +302,7 @@ fn push_expected_errors(
290302 // Add notes for any labels that appear in the message.
291303 for span in spans_in_this_file. iter ( ) . filter ( |span| span. label . is_some ( ) ) {
292304 expected_errors. push ( Error {
293- line_num : span. line_start ,
305+ line_num : Some ( span. line_start ) ,
294306 kind : Some ( ErrorKind :: Note ) ,
295307 msg : span. label . clone ( ) . unwrap ( ) ,
296308 } ) ;
@@ -309,7 +321,7 @@ fn push_backtrace(
309321) {
310322 if Path :: new ( & expansion. span . file_name ) == Path :: new ( & file_name) {
311323 expected_errors. push ( Error {
312- line_num : expansion. span . line_start ,
324+ line_num : Some ( expansion. span . line_start ) ,
313325 kind : Some ( ErrorKind :: Note ) ,
314326 msg : format ! ( "in this expansion of {}" , expansion. macro_decl_name) ,
315327 } ) ;
0 commit comments