From cd0586b75fae3014b304a6aa2f7b1b5f55618990 Mon Sep 17 00:00:00 2001 From: Federico Poli Date: Wed, 27 Jun 2018 15:28:30 +0200 Subject: [PATCH 1/2] Add test to reproduce issue #48 --- test-project/tests/compile-fail/macro.rs | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 test-project/tests/compile-fail/macro.rs diff --git a/test-project/tests/compile-fail/macro.rs b/test-project/tests/compile-fail/macro.rs new file mode 100644 index 0000000..09d40aa --- /dev/null +++ b/test-project/tests/compile-fail/macro.rs @@ -0,0 +1,9 @@ +macro_rules! macro_with_error { + ( ) => { + let x: u64 = true; + }; +} + +fn main() { + macro_with_error!(); //~ ERROR mismatched types +} From 3928289fffe191dd76d5897ece9af44a114d1bec Mon Sep 17 00:00:00 2001 From: Federico Poli Date: Wed, 27 Jun 2018 15:30:13 +0200 Subject: [PATCH 2/2] Use callsite of macro expansions in 'push_expected_errors' (closes issue #48) --- src/json.rs | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/json.rs b/src/json.rs index 0863062..e38672f 100644 --- a/src/json.rs +++ b/src/json.rs @@ -39,6 +39,14 @@ struct DiagnosticSpan { expansion: Option>, } +impl DiagnosticSpan { + /// Return the source span - this is either the supplied span, or the span for + /// the macro callsite that expanded to it. + fn callsite(&self) -> &DiagnosticSpan { + self.expansion.as_ref().map(|origin| origin.span.callsite()).unwrap_or(self) + } +} + #[derive(Deserialize, Clone)] struct DiagnosticSpanMacroExpansion { /// span where macro was applied to generate this code @@ -48,6 +56,7 @@ struct DiagnosticSpanMacroExpansion { macro_decl_name: String, } + #[derive(Deserialize, Clone)] struct DiagnosticCode { /// The code itself. @@ -89,15 +98,22 @@ fn push_expected_errors(expected_errors: &mut Vec, diagnostic: &Diagnostic, default_spans: &[&DiagnosticSpan], file_name: &str) { - let spans_in_this_file: Vec<_> = diagnostic.spans + // In case of macro expansions, we need to get the span of the call site + let spans_info_in_this_file: Vec<_> = diagnostic.spans .iter() - .filter(|span| Path::new(&span.file_name) == Path::new(&file_name)) + .map(|span| (span.is_primary, span.callsite())) + .filter(|(_, span)| Path::new(&span.file_name) == Path::new(&file_name)) .collect(); - let primary_spans: Vec<_> = spans_in_this_file.iter() - .cloned() - .filter(|span| span.is_primary) + let spans_in_this_file: Vec<_> = spans_info_in_this_file.iter() + .map(|(_, span)| span) + .collect(); + + let primary_spans: Vec<_> = spans_info_in_this_file.iter() + .filter(|(is_primary, _)| *is_primary) + .map(|(_, span)| span) .take(1) // sometimes we have more than one showing up in the json; pick first + .cloned() .collect(); let primary_spans = if primary_spans.is_empty() { // subdiagnostics often don't have a span of their own;