diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 49c8be28292..f9e23e96fa8 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -343,8 +343,9 @@ fn fix_multispan_in_std_macros( if call_sp != *sp && !always_backtrace { before_after.push((*sp, call_sp)); } - let backtrace_len = sp.macro_backtrace().len(); - for (i, trace) in sp.macro_backtrace().iter().rev().enumerate() { + 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 if trace.def_site.is_dummy() { @@ -398,8 +399,7 @@ fn fix_multispan_in_std_macros( continue; } if sm.span_to_filename(sp_label.span.clone()).is_macros() && !always_backtrace { - let v = sp_label.span.macro_backtrace(); - if let Some(use_site) = v.last() { + if let Some(use_site) = sp_label.span.macro_backtrace().last() { before_after.push((sp_label.span.clone(), use_site.call_site.clone())); } } diff --git a/src/librustc_errors/json.rs b/src/librustc_errors/json.rs index 21be9527b6c..3ddf9b09893 100644 --- a/src/librustc_errors/json.rs +++ b/src/librustc_errors/json.rs @@ -309,7 +309,7 @@ fn from_span_etc( // backtrace ourselves, but the `macro_backtrace` helper makes // some decision, such as dropping some frames, and I don't // want to duplicate that logic here. - let backtrace = span.macro_backtrace().into_iter(); + let backtrace = span.macro_backtrace(); DiagnosticSpan::from_span_full(span, is_primary, label, suggestion, backtrace, je) } @@ -318,7 +318,7 @@ fn from_span_full( is_primary: bool, label: Option, suggestion: Option<(&String, Applicability)>, - mut backtrace: vec::IntoIter, + mut backtrace: impl Iterator, je: &JsonEmitter, ) -> DiagnosticSpan { let start = je.sm.lookup_char_pos(span.lo()); diff --git a/src/librustc_span/lib.rs b/src/librustc_span/lib.rs index 3f23eb15829..413bd77daae 100644 --- a/src/librustc_span/lib.rs +++ b/src/librustc_span/lib.rs @@ -445,23 +445,26 @@ pub fn allows_unsafe(&self) -> bool { self.ctxt().outer_expn_data().allow_internal_unsafe } - pub fn macro_backtrace(mut self) -> Vec { + pub fn macro_backtrace(mut self) -> impl Iterator { let mut prev_span = DUMMY_SP; - let mut result = vec![]; - loop { - let expn_data = self.ctxt().outer_expn_data(); - if expn_data.is_root() { - break; - } - // Don't print recursive invocations. - if !expn_data.call_site.source_equal(&prev_span) { - result.push(expn_data.clone()); - } + std::iter::from_fn(move || { + loop { + let expn_data = self.ctxt().outer_expn_data(); + if expn_data.is_root() { + return None; + } - prev_span = self; - self = expn_data.call_site; - } - result + let is_recursive = expn_data.call_site.source_equal(&prev_span); + + prev_span = self; + self = expn_data.call_site; + + // Don't print recursive invocations. + if !is_recursive { + return Some(expn_data); + } + } + }) } /// Returns a `Span` that would enclose both `self` and `end`. diff --git a/src/librustc_span/source_map.rs b/src/librustc_span/source_map.rs index e0b93b9ce25..c250df43a27 100644 --- a/src/librustc_span/source_map.rs +++ b/src/librustc_span/source_map.rs @@ -947,8 +947,7 @@ pub fn ensure_source_file_source_present(&self, source_file: Lrc) -> } pub fn call_span_if_macro(&self, sp: Span) -> Span { if self.span_to_filename(sp.clone()).is_macros() { - let v = sp.macro_backtrace(); - if let Some(use_site) = v.last() { + if let Some(use_site) = sp.macro_backtrace().last() { return use_site.call_site; } }