@@ -141,25 +141,31 @@ pub fn extract_rendered(output: &str) -> String {
141141}
142142
143143pub 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
145149}
146150
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+ ) {
148158 // The compiler sometimes intermingles non-JSON stuff into the
149159 // output. This hack just skips over such lines. Yuck.
150160 if line. starts_with ( '{' ) {
151161 match serde_json:: from_str :: < Diagnostic > ( line) {
152162 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 )
156164 }
157165 Err ( error) => {
158166 // Ignore the future compat report message - this is handled
159167 // 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 ( ) {
163169 proc_res. fatal (
164170 Some ( & format ! (
165171 "failed to decode compiler output as json: \
@@ -171,8 +177,6 @@ fn parse_line(file_name: &str, line: &str, output: &str, proc_res: &ProcRes) ->
171177 }
172178 }
173179 }
174- } else {
175- vec ! [ ]
176180 }
177181}
178182
@@ -181,6 +185,7 @@ fn push_expected_errors(
181185 diagnostic : & Diagnostic ,
182186 default_spans : & [ & DiagnosticSpan ] ,
183187 file_name : & str ,
188+ prev_parent : Option < usize > ,
184189) {
185190 // In case of macro expansions, we need to get the span of the callsite
186191 let spans_info_in_this_file: Vec < _ > = diagnostic
@@ -240,6 +245,7 @@ fn push_expected_errors(
240245 // more structured shortly anyhow.
241246 let kind = ErrorKind :: from_compiler_str ( & diagnostic. level ) ;
242247 let mut message_lines = diagnostic. message . lines ( ) ;
248+ let mut parent = None ;
243249 if let Some ( first_line) = message_lines. next ( ) {
244250 let ignore = |s| {
245251 static RE : OnceLock < Regex > = OnceLock :: new ( ) ;
@@ -250,21 +256,29 @@ fn push_expected_errors(
250256 } ;
251257
252258 if primary_spans. is_empty ( ) && !ignore ( first_line) {
259+ if parent. is_none ( ) {
260+ parent = Some ( expected_errors. len ( ) ) ;
261+ }
253262 expected_errors. push ( Error {
254263 line_num : None ,
255264 kind,
256265 msg : with_code ( None , first_line) ,
257266 should_annotate : diagnostic. level != "failure-note" ,
258267 viral : true ,
268+ parent : prev_parent,
259269 } ) ;
260270 } else {
261271 for span in primary_spans {
272+ if parent. is_none ( ) {
273+ parent = Some ( expected_errors. len ( ) ) ;
274+ }
262275 expected_errors. push ( Error {
263276 line_num : Some ( span. line_start ) ,
264277 kind,
265278 msg : with_code ( Some ( span) , first_line) ,
266279 should_annotate : diagnostic. level != "failure-note" ,
267280 viral : true ,
281+ parent : prev_parent,
268282 } ) ;
269283 }
270284 }
@@ -277,6 +291,7 @@ fn push_expected_errors(
277291 msg : with_code ( None , next_line) ,
278292 should_annotate : false ,
279293 viral : true ,
294+ parent : prev_parent,
280295 } ) ;
281296 } else {
282297 for span in primary_spans {
@@ -286,6 +301,7 @@ fn push_expected_errors(
286301 msg : with_code ( Some ( span) , next_line) ,
287302 should_annotate : false ,
288303 viral : true ,
304+ parent : prev_parent,
289305 } ) ;
290306 }
291307 }
@@ -301,6 +317,7 @@ fn push_expected_errors(
301317 msg : line. to_string ( ) ,
302318 should_annotate : true ,
303319 viral : true ,
320+ parent,
304321 } ) ;
305322 }
306323 }
@@ -309,7 +326,7 @@ fn push_expected_errors(
309326 // Add notes for the backtrace
310327 for span in primary_spans {
311328 if let Some ( frame) = & span. expansion {
312- push_backtrace ( expected_errors, frame, file_name) ;
329+ push_backtrace ( expected_errors, frame, file_name, parent ) ;
313330 }
314331 }
315332
@@ -321,19 +338,21 @@ fn push_expected_errors(
321338 msg : span. label . clone ( ) . unwrap ( ) ,
322339 should_annotate : true ,
323340 viral : true ,
341+ parent,
324342 } ) ;
325343 }
326344
327345 // Flatten out the children.
328346 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 ) ;
330348 }
331349}
332350
333351fn push_backtrace (
334352 expected_errors : & mut Vec < Error > ,
335353 expansion : & DiagnosticSpanMacroExpansion ,
336354 file_name : & str ,
355+ parent : Option < usize > ,
337356) {
338357 if Path :: new ( & expansion. span . file_name ) == Path :: new ( & file_name) {
339358 expected_errors. push ( Error {
@@ -342,10 +361,11 @@ fn push_backtrace(
342361 msg : format ! ( "in this expansion of {}" , expansion. macro_decl_name) ,
343362 should_annotate : true ,
344363 viral : true ,
364+ parent,
345365 } ) ;
346366 }
347367
348368 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 ) ;
350370 }
351371}
0 commit comments