@@ -141,25 +141,31 @@ pub fn extract_rendered(output: &str) -> String {
141
141
}
142
142
143
143
pub fn parse_output ( file_name : & str , output : & str , proc_res : & ProcRes ) -> Vec < Error > {
144
- output. lines ( ) . flat_map ( |line| parse_line ( file_name, line, output, proc_res) ) . collect ( )
144
+ let mut expected_errors = vec ! [ ] ;
145
+ for line in output. lines ( ) {
146
+ parse_line ( & mut expected_errors, file_name, line, output, proc_res) ;
147
+ }
148
+ expected_errors
145
149
}
146
150
147
- fn parse_line ( file_name : & str , line : & str , output : & str , proc_res : & ProcRes ) -> Vec < Error > {
151
+ fn parse_line (
152
+ expected_errors : & mut Vec < Error > ,
153
+ file_name : & str ,
154
+ line : & str ,
155
+ output : & str ,
156
+ proc_res : & ProcRes ,
157
+ ) {
148
158
// The compiler sometimes intermingles non-JSON stuff into the
149
159
// output. This hack just skips over such lines. Yuck.
150
160
if line. starts_with ( '{' ) {
151
161
match serde_json:: from_str :: < Diagnostic > ( line) {
152
162
Ok ( diagnostic) => {
153
- let mut expected_errors = vec ! [ ] ;
154
- push_expected_errors ( & mut expected_errors, & diagnostic, & [ ] , file_name) ;
155
- expected_errors
163
+ push_expected_errors ( expected_errors, & diagnostic, & [ ] , file_name, None )
156
164
}
157
165
Err ( error) => {
158
166
// Ignore the future compat report message - this is handled
159
167
// by `extract_rendered`
160
- if serde_json:: from_str :: < FutureIncompatReport > ( line) . is_ok ( ) {
161
- vec ! [ ]
162
- } else {
168
+ if !serde_json:: from_str :: < FutureIncompatReport > ( line) . is_ok ( ) {
163
169
proc_res. fatal (
164
170
Some ( & format ! (
165
171
"failed to decode compiler output as json: \
@@ -171,8 +177,6 @@ fn parse_line(file_name: &str, line: &str, output: &str, proc_res: &ProcRes) ->
171
177
}
172
178
}
173
179
}
174
- } else {
175
- vec ! [ ]
176
180
}
177
181
}
178
182
@@ -181,6 +185,7 @@ fn push_expected_errors(
181
185
diagnostic : & Diagnostic ,
182
186
default_spans : & [ & DiagnosticSpan ] ,
183
187
file_name : & str ,
188
+ prev_parent : Option < usize > ,
184
189
) {
185
190
// In case of macro expansions, we need to get the span of the callsite
186
191
let spans_info_in_this_file: Vec < _ > = diagnostic
@@ -240,6 +245,7 @@ fn push_expected_errors(
240
245
// more structured shortly anyhow.
241
246
let kind = ErrorKind :: from_compiler_str ( & diagnostic. level ) ;
242
247
let mut message_lines = diagnostic. message . lines ( ) ;
248
+ let mut parent = None ;
243
249
if let Some ( first_line) = message_lines. next ( ) {
244
250
let ignore = |s| {
245
251
static RE : OnceLock < Regex > = OnceLock :: new ( ) ;
@@ -250,21 +256,29 @@ fn push_expected_errors(
250
256
} ;
251
257
252
258
if primary_spans. is_empty ( ) && !ignore ( first_line) {
259
+ if parent. is_none ( ) {
260
+ parent = Some ( expected_errors. len ( ) ) ;
261
+ }
253
262
expected_errors. push ( Error {
254
263
line_num : None ,
255
264
kind,
256
265
msg : with_code ( None , first_line) ,
257
266
should_annotate : diagnostic. level != "failure-note" ,
258
267
viral : true ,
268
+ parent : prev_parent,
259
269
} ) ;
260
270
} else {
261
271
for span in primary_spans {
272
+ if parent. is_none ( ) {
273
+ parent = Some ( expected_errors. len ( ) ) ;
274
+ }
262
275
expected_errors. push ( Error {
263
276
line_num : Some ( span. line_start ) ,
264
277
kind,
265
278
msg : with_code ( Some ( span) , first_line) ,
266
279
should_annotate : diagnostic. level != "failure-note" ,
267
280
viral : true ,
281
+ parent : prev_parent,
268
282
} ) ;
269
283
}
270
284
}
@@ -277,6 +291,7 @@ fn push_expected_errors(
277
291
msg : with_code ( None , next_line) ,
278
292
should_annotate : false ,
279
293
viral : true ,
294
+ parent : prev_parent,
280
295
} ) ;
281
296
} else {
282
297
for span in primary_spans {
@@ -286,6 +301,7 @@ fn push_expected_errors(
286
301
msg : with_code ( Some ( span) , next_line) ,
287
302
should_annotate : false ,
288
303
viral : true ,
304
+ parent : prev_parent,
289
305
} ) ;
290
306
}
291
307
}
@@ -301,6 +317,7 @@ fn push_expected_errors(
301
317
msg : line. to_string ( ) ,
302
318
should_annotate : true ,
303
319
viral : true ,
320
+ parent,
304
321
} ) ;
305
322
}
306
323
}
@@ -309,7 +326,7 @@ fn push_expected_errors(
309
326
// Add notes for the backtrace
310
327
for span in primary_spans {
311
328
if let Some ( frame) = & span. expansion {
312
- push_backtrace ( expected_errors, frame, file_name) ;
329
+ push_backtrace ( expected_errors, frame, file_name, parent ) ;
313
330
}
314
331
}
315
332
@@ -321,19 +338,21 @@ fn push_expected_errors(
321
338
msg : span. label . clone ( ) . unwrap ( ) ,
322
339
should_annotate : true ,
323
340
viral : true ,
341
+ parent,
324
342
} ) ;
325
343
}
326
344
327
345
// Flatten out the children.
328
346
for child in & diagnostic. children {
329
- push_expected_errors ( expected_errors, child, primary_spans, file_name) ;
347
+ push_expected_errors ( expected_errors, child, primary_spans, file_name, parent ) ;
330
348
}
331
349
}
332
350
333
351
fn push_backtrace (
334
352
expected_errors : & mut Vec < Error > ,
335
353
expansion : & DiagnosticSpanMacroExpansion ,
336
354
file_name : & str ,
355
+ parent : Option < usize > ,
337
356
) {
338
357
if Path :: new ( & expansion. span . file_name ) == Path :: new ( & file_name) {
339
358
expected_errors. push ( Error {
@@ -342,10 +361,11 @@ fn push_backtrace(
342
361
msg : format ! ( "in this expansion of {}" , expansion. macro_decl_name) ,
343
362
should_annotate : true ,
344
363
viral : true ,
364
+ parent,
345
365
} ) ;
346
366
}
347
367
348
368
if let Some ( previous_expansion) = & expansion. span . expansion {
349
- push_backtrace ( expected_errors, previous_expansion, file_name) ;
369
+ push_backtrace ( expected_errors, previous_expansion, file_name, parent ) ;
350
370
}
351
371
}
0 commit comments