about summary refs log tree commit diff
path: root/src/tools
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-07-23 21:44:37 +0000
committerbors <bors@rust-lang.org>2018-07-23 21:44:37 +0000
commit6a1c0637ce44aeea6c60527f4c0e7fb33f2bcd0d (patch)
tree25e3c072744828f6dbfceb3a09c0328176e5afbb /src/tools
parent00204c2f52ec0280bda17de347c79f88e9c6b479 (diff)
parent8ec9d7242c3352fbc617d907bec3632215811356 (diff)
downloadrust-6a1c0637ce44aeea6c60527f4c0e7fb33f2bcd0d.tar.gz
rust-6a1c0637ce44aeea6c60527f4c0e7fb33f2bcd0d.zip
Auto merge of #52175 - fpoli:testsuite-callsite-span, r=petrochenkov
Match errors using the callsite of macro expansions

Fix for issue #51848
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/compiletest/src/json.rs32
-rw-r--r--src/tools/compiletest/src/runtest.rs6
2 files changed, 32 insertions, 6 deletions
diff --git a/src/tools/compiletest/src/json.rs b/src/tools/compiletest/src/json.rs
index 165f2914ae2..201a661726e 100644
--- a/src/tools/compiletest/src/json.rs
+++ b/src/tools/compiletest/src/json.rs
@@ -40,6 +40,21 @@ struct DiagnosticSpan {
     expansion: Option<Box<DiagnosticSpanMacroExpansion>>,
 }
 
+impl DiagnosticSpan {
+    /// Returns the deepest source span in the macro call stack with a given file name.
+    /// This is either the supplied span, or the span for some macro callsite that expanded to it.
+    fn first_callsite_in_file(&self, file_name: &str) -> &DiagnosticSpan {
+        if self.file_name == file_name {
+            self
+        } else {
+            self.expansion
+                .as_ref()
+                .map(|origin| origin.span.first_callsite_in_file(file_name))
+                .unwrap_or(self)
+        }
+    }
+}
+
 #[derive(Deserialize, Clone)]
 struct DiagnosticSpanMacroExpansion {
     /// span where macro was applied to generate this code
@@ -115,16 +130,23 @@ fn push_expected_errors(
     default_spans: &[&DiagnosticSpan],
     file_name: &str,
 ) {
-    let spans_in_this_file: Vec<_> = diagnostic
+    // In case of macro expansions, we need to get the span of the callsite
+    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.first_callsite_in_file(file_name)))
+        .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;
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index fcc47436225..ad86844cec3 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1194,6 +1194,10 @@ impl<'test> TestCx<'test> {
             self.fatal_proc_rec("process did not return an error status", proc_res);
         }
 
+        // On Windows, keep all '\' path separators to match the paths reported in the JSON output
+        // from the compiler
+        let os_file_name = self.testpaths.file.display().to_string();
+
         // on windows, translate all '\' path separators to '/'
         let file_name = format!("{}", self.testpaths.file.display()).replace(r"\", "/");
 
@@ -1209,7 +1213,7 @@ impl<'test> TestCx<'test> {
             .any(|ee| ee.kind == Some(ErrorKind::Note));
 
         // Parse the JSON output from the compiler and extract out the messages.
-        let actual_errors = json::parse_output(&file_name, &proc_res.stderr, proc_res);
+        let actual_errors = json::parse_output(&os_file_name, &proc_res.stderr, proc_res);
         let mut unexpected = Vec::new();
         let mut found = vec![false; expected_errors.len()];
         for actual_error in &actual_errors {