diff options
| author | Federico Poli <federpoli@gmail.com> | 2018-07-19 14:15:43 +0200 |
|---|---|---|
| committer | Federico Poli <federpoli@gmail.com> | 2018-07-23 14:31:06 +0200 |
| commit | 8ec9d7242c3352fbc617d907bec3632215811356 (patch) | |
| tree | fecf6df248e2ba6dea669b97a4e080dc1e3fb0e0 /src/tools | |
| parent | 3900bf8ae3aafdd3ab13a0e6400d47bc5cb2e121 (diff) | |
| download | rust-8ec9d7242c3352fbc617d907bec3632215811356.tar.gz rust-8ec9d7242c3352fbc617d907bec3632215811356.zip | |
Match errors using the callsite of macro expansions
Diffstat (limited to 'src/tools')
| -rw-r--r-- | src/tools/compiletest/src/json.rs | 32 | ||||
| -rw-r--r-- | src/tools/compiletest/src/runtest.rs | 6 |
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 { |
