@@ -12,7 +12,7 @@ use self::Destination::*;
12
12
13
13
use syntax_pos:: { COMMAND_LINE_SP , DUMMY_SP , FileMap , Span , MultiSpan , CharPos } ;
14
14
15
- use { Level , CodeSuggestion , DiagnosticBuilder , CodeMapper } ;
15
+ use { Level , CodeSuggestion , DiagnosticBuilder , SubDiagnostic , CodeMapper } ;
16
16
use RenderSpan :: * ;
17
17
use snippet:: { StyledString , Style , Annotation , Line } ;
18
18
use styled_buffer:: StyledBuffer ;
@@ -30,7 +30,10 @@ pub trait Emitter {
30
30
31
31
impl Emitter for EmitterWriter {
32
32
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) ;
34
37
}
35
38
}
36
39
@@ -381,19 +384,69 @@ impl EmitterWriter {
381
384
max
382
385
}
383
386
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 {
385
388
let mut max = 0 ;
386
389
387
- let primary = self . get_multispan_max_line_num ( & db . span ) ;
390
+ let primary = self . get_multispan_max_line_num ( span) ;
388
391
max = if primary > max { primary } else { max } ;
389
392
390
- for sub in & db . children {
393
+ for sub in children {
391
394
let sub_result = self . get_multispan_max_line_num ( & sub. span ) ;
392
395
max = if sub_result > max { primary } else { max } ;
393
396
}
394
397
max
395
398
}
396
399
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
+
397
450
fn emit_message_default ( & mut self ,
398
451
msp : & MultiSpan ,
399
452
msg : & str ,
@@ -578,26 +631,31 @@ impl EmitterWriter {
578
631
}
579
632
Ok ( ( ) )
580
633
}
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) ;
583
641
let max_line_num_len = max_line_num. to_string ( ) . len ( ) ;
584
642
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,
589
647
max_line_num_len,
590
648
false ) {
591
649
Ok ( ( ) ) => {
592
- if !db . children . is_empty ( ) {
650
+ if !children. is_empty ( ) {
593
651
let mut buffer = StyledBuffer :: new ( ) ;
594
652
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 ) {
596
654
Ok ( ( ) ) => ( ) ,
597
655
Err ( e) => panic ! ( "failed to emit error: {}" , e)
598
656
}
599
657
}
600
- for child in & db . children {
658
+ for child in children {
601
659
match child. render_span {
602
660
Some ( FullSpan ( ref msp) ) => {
603
661
match self . emit_message_default ( msp,
0 commit comments