about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2019-12-13 23:21:14 +0200
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2020-02-06 21:32:07 +0200
commit8f286dbf27b61afdd96f632d0bc7f4c49fbb7d0f (patch)
treeb8f939ec9c615570d4376b22a215e36d9a114e02
parent442ae7f04026c215a03b155eaaf9cde8bb5cf02a (diff)
downloadrust-8f286dbf27b61afdd96f632d0bc7f4c49fbb7d0f.tar.gz
rust-8f286dbf27b61afdd96f632d0bc7f4c49fbb7d0f.zip
rustc_errors: split macro backtrace rendering from <*macros> hacks.
-rw-r--r--src/librustc_errors/annotate_snippet_emitter_writer.rs2
-rw-r--r--src/librustc_errors/emitter.rs154
-rw-r--r--src/librustc_span/source_map.rs8
3 files changed, 97 insertions, 67 deletions
diff --git a/src/librustc_errors/annotate_snippet_emitter_writer.rs b/src/librustc_errors/annotate_snippet_emitter_writer.rs
index 009ab6ac5b1..65d82f545e8 100644
--- a/src/librustc_errors/annotate_snippet_emitter_writer.rs
+++ b/src/librustc_errors/annotate_snippet_emitter_writer.rs
@@ -32,7 +32,7 @@ impl Emitter for AnnotateSnippetEmitterWriter {
         let mut children = diag.children.clone();
         let (mut primary_span, suggestions) = self.primary_span_formatted(&diag);
 
-        self.fix_multispans_in_std_macros(
+        self.render_multispans_macro_backtrace_and_fix_extern_macros(
             &self.source_map,
             &mut primary_span,
             &mut children,
diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs
index 1fcb36a2a30..d32b8c689dc 100644
--- a/src/librustc_errors/emitter.rs
+++ b/src/librustc_errors/emitter.rs
@@ -280,10 +280,7 @@ pub trait Emitter {
         }
     }
 
-    // This does a small "fix" for multispans by looking to see if it can find any that
-    // point directly at <*macros>. Since these are often difficult to read, this
-    // will change the span to point at the use site.
-    fn fix_multispans_in_std_macros(
+    fn render_multispans_macro_backtrace_and_fix_extern_macros(
         &self,
         source_map: &Option<Lrc<SourceMap>>,
         span: &mut MultiSpan,
@@ -291,61 +288,64 @@ pub trait Emitter {
         level: &Level,
         backtrace: bool,
     ) {
-        let mut spans_updated = self.fix_multispan_in_std_macros(source_map, span, backtrace);
-        for child in children.iter_mut() {
-            spans_updated |=
-                self.fix_multispan_in_std_macros(source_map, &mut child.span, backtrace);
+        self.render_multispans_macro_backtrace(source_map, span, children, backtrace);
+
+        if !backtrace {
+            if self.fix_multispans_in_extern_macros(source_map, span, children) {
+                let msg = if level == &Error {
+                    "this error originates in a macro outside of the current crate \
+                    (in Nightly builds, run with -Z external-macro-backtrace \
+                    for more info)"
+                        .to_string()
+                } else {
+                    "this warning originates in a macro outside of the current crate \
+                    (in Nightly builds, run with -Z external-macro-backtrace \
+                    for more info)"
+                        .to_string()
+                };
+
+                children.push(SubDiagnostic {
+                    level: Level::Note,
+                    message: vec![(msg, Style::NoStyle)],
+                    span: MultiSpan::new(),
+                    render_span: None,
+                });
+            }
         }
-        let msg = if level == &Error {
-            "this error originates in a macro outside of the current crate \
-             (in Nightly builds, run with -Z external-macro-backtrace \
-              for more info)"
-                .to_string()
-        } else {
-            "this warning originates in a macro outside of the current crate \
-             (in Nightly builds, run with -Z external-macro-backtrace \
-              for more info)"
-                .to_string()
-        };
+    }
 
-        if spans_updated {
-            children.push(SubDiagnostic {
-                level: Level::Note,
-                message: vec![(msg, Style::NoStyle)],
-                span: MultiSpan::new(),
-                render_span: None,
-            });
+    fn render_multispans_macro_backtrace(
+        &self,
+        source_map: &Option<Lrc<SourceMap>>,
+        span: &mut MultiSpan,
+        children: &mut Vec<SubDiagnostic>,
+        backtrace: bool,
+    ) {
+        self.render_multispan_macro_backtrace(source_map, span, backtrace);
+        for child in children.iter_mut() {
+            self.render_multispan_macro_backtrace(source_map, &mut child.span, backtrace);
         }
     }
 
-    // This "fixes" MultiSpans that contain Spans that are pointing to locations inside of
-    // <*macros>. Since these locations are often difficult to read, we move these Spans from
-    // <*macros> to their corresponding use site.
-    fn fix_multispan_in_std_macros(
+    fn render_multispan_macro_backtrace(
         &self,
         source_map: &Option<Lrc<SourceMap>>,
         span: &mut MultiSpan,
         always_backtrace: bool,
-    ) -> bool {
+    ) {
         let sm = match source_map {
             Some(ref sm) => sm,
-            None => return false,
+            None => return,
         };
 
-        let mut before_after: Vec<(Span, Span)> = vec![];
         let mut new_labels: Vec<(Span, String)> = vec![];
 
         // First, find all the spans in <*macros> and point instead at their use site
-        for sp in span.primary_spans() {
+        for &sp in span.primary_spans() {
             if sp.is_dummy() {
                 continue;
             }
-            let call_sp = sm.call_span_if_macro(*sp);
-            if call_sp != *sp && !always_backtrace {
-                before_after.push((*sp, call_sp));
-            }
             let macro_backtrace: Vec<_> = sp.macro_backtrace().collect();
-            let backtrace_len = macro_backtrace.len();
             for (i, trace) in macro_backtrace.iter().rev().enumerate() {
                 // Only show macro locations that are local
                 // and display them like a span_note
@@ -358,13 +358,13 @@ pub trait Emitter {
                         format!(
                             "in this expansion of `{}`{}",
                             trace.kind.descr(),
-                            if backtrace_len > 2 {
-                                // if backtrace_len == 1 it'll be pointed
-                                // at by "in this macro invocation"
+                            if macro_backtrace.len() > 2 {
+                                // if macro_backtrace.len() == 1 it'll be
+                                // pointed at by "in this macro invocation"
                                 format!(" (#{})", i + 1)
                             } else {
                                 String::new()
-                            }
+                            },
                         ),
                     ));
                 }
@@ -377,13 +377,13 @@ pub trait Emitter {
                         trace.call_site,
                         format!(
                             "in this macro invocation{}",
-                            if backtrace_len > 2 && always_backtrace {
+                            if macro_backtrace.len() > 2 && always_backtrace {
                                 // only specify order when the macro
                                 // backtrace is multiple levels deep
                                 format!(" (#{})", i + 1)
                             } else {
                                 String::new()
-                            }
+                            },
                         ),
                     ));
                     if !always_backtrace {
@@ -395,20 +395,58 @@ pub trait Emitter {
         for (label_span, label_text) in new_labels {
             span.push_span_label(label_span, label_text);
         }
-        for sp_label in span.span_labels() {
-            if sp_label.span.is_dummy() {
-                continue;
-            }
-            if sm.span_to_filename(sp_label.span.clone()).is_macros() && !always_backtrace {
-                if let Some(use_site) = sp_label.span.macro_backtrace().last() {
-                    before_after.push((sp_label.span, use_site.call_site));
-                }
-            }
+    }
+
+    // This does a small "fix" for multispans by looking to see if it can find any that
+    // point directly at <*macros>. Since these are often difficult to read, this
+    // will change the span to point at the use site.
+    fn fix_multispans_in_extern_macros(
+        &self,
+        source_map: &Option<Lrc<SourceMap>>,
+        span: &mut MultiSpan,
+        children: &mut Vec<SubDiagnostic>,
+    ) -> bool {
+        let mut spans_updated = self.fix_multispan_in_extern_macros(source_map, span);
+        for child in children.iter_mut() {
+            spans_updated |= self.fix_multispan_in_extern_macros(source_map, &mut child.span);
         }
+        spans_updated
+    }
+
+    // This "fixes" MultiSpans that contain Spans that are pointing to locations inside of
+    // <*macros>. Since these locations are often difficult to read, we move these Spans from
+    // <*macros> to their corresponding use site.
+    fn fix_multispan_in_extern_macros(
+        &self,
+        source_map: &Option<Lrc<SourceMap>>,
+        span: &mut MultiSpan,
+    ) -> bool {
+        let sm = match source_map {
+            Some(ref sm) => sm,
+            None => return false,
+        };
+
+        // First, find all the spans in <*macros> and point instead at their use site
+        let replacements: Vec<(Span, Span)> = span
+            .primary_spans()
+            .iter()
+            .copied()
+            .chain(span.span_labels().iter().map(|sp_label| sp_label.span))
+            .filter_map(|sp| {
+                if !sp.is_dummy() && sm.span_to_filename(sp).is_macros() {
+                    let maybe_callsite = sp.source_callsite();
+                    if sp != maybe_callsite {
+                        return Some((sp, maybe_callsite));
+                    }
+                }
+                None
+            })
+            .collect();
+
         // After we have them, make sure we replace these 'bad' def sites with their use sites
-        let spans_updated = !before_after.is_empty();
-        for (before, after) in before_after {
-            span.replace(before, after);
+        let spans_updated = !replacements.is_empty();
+        for (from, to) in replacements {
+            span.replace(from, to);
         }
 
         spans_updated
@@ -424,7 +462,7 @@ impl Emitter for EmitterWriter {
         let mut children = diag.children.clone();
         let (mut primary_span, suggestions) = self.primary_span_formatted(&diag);
 
-        self.fix_multispans_in_std_macros(
+        self.render_multispans_macro_backtrace_and_fix_extern_macros(
             &self.sm,
             &mut primary_span,
             &mut children,
diff --git a/src/librustc_span/source_map.rs b/src/librustc_span/source_map.rs
index c250df43a27..45c4d6dbc6c 100644
--- a/src/librustc_span/source_map.rs
+++ b/src/librustc_span/source_map.rs
@@ -945,14 +945,6 @@ impl SourceMap {
             _ => None,
         })
     }
-    pub fn call_span_if_macro(&self, sp: Span) -> Span {
-        if self.span_to_filename(sp.clone()).is_macros() {
-            if let Some(use_site) = sp.macro_backtrace().last() {
-                return use_site.call_site;
-            }
-        }
-        sp
-    }
 }
 
 #[derive(Clone)]