@@ -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