@@ -12,7 +12,7 @@ use self::Destination::*;
1212
1313use syntax_pos:: { COMMAND_LINE_SP , DUMMY_SP , FileMap , Span , MultiSpan , CharPos } ;
1414
15- use { Level , CodeSuggestion , DiagnosticBuilder , CodeMapper } ;
15+ use { Level , CodeSuggestion , DiagnosticBuilder , SubDiagnostic , CodeMapper } ;
1616use RenderSpan :: * ;
1717use snippet:: { StyledString , Style , Annotation , Line } ;
1818use styled_buffer:: StyledBuffer ;
@@ -30,7 +30,10 @@ pub trait Emitter {
3030
3131impl Emitter for EmitterWriter {
3232 fn emit ( & mut self , db : & DiagnosticBuilder ) {
33- self . emit_messages_default ( db) ;
33+ let mut primary_span = db. span . clone ( ) ;
34+ let mut children = db. children . clone ( ) ;
35+ self . fix_multispans_in_std_macros ( & mut primary_span, & mut children) ;
36+ self . emit_messages_default ( & db. level , & db. message , & db. code , & primary_span, & children) ;
3437 }
3538}
3639
@@ -381,19 +384,69 @@ impl EmitterWriter {
381384 max
382385 }
383386
384- fn get_max_line_num ( & mut self , db : & DiagnosticBuilder ) -> usize {
387+ fn get_max_line_num ( & mut self , span : & MultiSpan , children : & Vec < SubDiagnostic > ) -> usize {
385388 let mut max = 0 ;
386389
387- let primary = self . get_multispan_max_line_num ( & db . span ) ;
390+ let primary = self . get_multispan_max_line_num ( span) ;
388391 max = if primary > max { primary } else { max } ;
389392
390- for sub in & db . children {
393+ for sub in children {
391394 let sub_result = self . get_multispan_max_line_num ( & sub. span ) ;
392395 max = if sub_result > max { primary } else { max } ;
393396 }
394397 max
395398 }
396399
400+ fn fix_multispan_in_std_macros ( & mut self , span : & mut MultiSpan ) -> bool {
401+ let mut spans_updated = false ;
402+
403+ if let Some ( ref cm) = self . cm {
404+ let mut before_after: Vec < ( Span , Span ) > = vec ! [ ] ;
405+
406+ // First, find all the spans in <std macros> and point instead at their use site
407+ for sp in span. primary_spans ( ) {
408+ if cm. span_to_filename ( sp. clone ( ) ) == "<std macros>" {
409+ let v = cm. macro_backtrace ( sp. clone ( ) ) ;
410+ if let Some ( use_site) = v. last ( ) {
411+ before_after. push ( ( sp. clone ( ) , use_site. call_site . clone ( ) ) ) ;
412+ } ;
413+ }
414+ }
415+ for sp_label in span. span_labels ( ) {
416+ if cm. span_to_filename ( sp_label. span . clone ( ) ) == "<std macros>" {
417+ let v = cm. macro_backtrace ( sp_label. span . clone ( ) ) ;
418+ if let Some ( use_site) = v. last ( ) {
419+ before_after. push ( ( sp_label. span . clone ( ) , use_site. call_site . clone ( ) ) ) ;
420+ } ;
421+ }
422+ }
423+ // After we have them, make sure we replace these 'bad' def sites with their use sites
424+ for ( before, after) in before_after {
425+ span. replace ( before, after) ;
426+ spans_updated = true ;
427+ }
428+ }
429+
430+ spans_updated
431+ }
432+
433+ fn fix_multispans_in_std_macros ( & mut self ,
434+ span : & mut MultiSpan ,
435+ children : & mut Vec < SubDiagnostic > ) {
436+ let mut spans_updated = self . fix_multispan_in_std_macros ( span) ;
437+ for i in 0 ..children. len ( ) {
438+ spans_updated |= self . fix_multispan_in_std_macros ( & mut children[ i] . span ) ;
439+ }
440+ if spans_updated {
441+ children. push ( SubDiagnostic {
442+ level : Level :: Note ,
443+ message : "this error originates in a macro from the standard library" . to_string ( ) ,
444+ span : MultiSpan :: new ( ) ,
445+ render_span : None
446+ } ) ;
447+ }
448+ }
449+
397450 fn emit_message_default ( & mut self ,
398451 msp : & MultiSpan ,
399452 msg : & str ,
@@ -578,26 +631,31 @@ impl EmitterWriter {
578631 }
579632 Ok ( ( ) )
580633 }
581- fn emit_messages_default ( & mut self , db : & DiagnosticBuilder ) {
582- let max_line_num = self . get_max_line_num ( db) ;
634+ fn emit_messages_default ( & mut self ,
635+ level : & Level ,
636+ message : & String ,
637+ code : & Option < String > ,
638+ span : & MultiSpan ,
639+ children : & Vec < SubDiagnostic > ) {
640+ let max_line_num = self . get_max_line_num ( span, children) ;
583641 let max_line_num_len = max_line_num. to_string ( ) . len ( ) ;
584642
585- match self . emit_message_default ( & db . span ,
586- & db . message ,
587- & db . code ,
588- & db . level ,
643+ match self . emit_message_default ( span,
644+ message,
645+ code,
646+ level,
589647 max_line_num_len,
590648 false ) {
591649 Ok ( ( ) ) => {
592- if !db . children . is_empty ( ) {
650+ if !children. is_empty ( ) {
593651 let mut buffer = StyledBuffer :: new ( ) ;
594652 draw_col_separator_no_space ( & mut buffer, 0 , max_line_num_len + 1 ) ;
595- match emit_to_destination ( & buffer. render ( ) , & db . level , & mut self . dst ) {
653+ match emit_to_destination ( & buffer. render ( ) , level, & mut self . dst ) {
596654 Ok ( ( ) ) => ( ) ,
597655 Err ( e) => panic ! ( "failed to emit error: {}" , e)
598656 }
599657 }
600- for child in & db . children {
658+ for child in children {
601659 match child. render_span {
602660 Some ( FullSpan ( ref msp) ) => {
603661 match self . emit_message_default ( msp,
0 commit comments