From ebc55879bc6ba359ca35b4f3d23c290ba49b25d3 Mon Sep 17 00:00:00 2001 From: Piotr Czarnecki Date: Wed, 3 Aug 2016 19:12:33 +0200 Subject: [PATCH 1/4] Add a `count` field to `Error` --- src/errors.rs | 4 ++++ src/json.rs | 9 +++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/errors.rs b/src/errors.rs index c3da891..d211a26 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -61,6 +61,10 @@ pub struct Error { /// `None` if not specified or unknown message kind. pub kind: Option, pub msg: String, + /// We can expect a specific number of sub-spans. + /// This count is used only for expected errors. + /// `None` when multiple actual messages on the same line should be treated as one. + pub count: Option, } #[derive(PartialEq, Debug)] diff --git a/src/json.rs b/src/json.rs index 84b7854..fda6c1d 100644 --- a/src/json.rs +++ b/src/json.rs @@ -149,6 +149,7 @@ fn push_expected_errors(expected_errors: &mut Vec, line_num: span.line_start, kind: kind, msg: msg, + count: None, } ); } @@ -160,6 +161,7 @@ fn push_expected_errors(expected_errors: &mut Vec, line_num: span.line_start, kind: None, msg: with_code(span, next_line), + count: None, } ); } @@ -174,7 +176,8 @@ fn push_expected_errors(expected_errors: &mut Vec, Error { line_num: start_line + index, kind: Some(ErrorKind::Suggestion), - msg: line.to_string() + msg: line.to_string(), + count: None, } ); } @@ -196,7 +199,8 @@ fn push_expected_errors(expected_errors: &mut Vec, expected_errors.push(Error { line_num: span.line_start, kind: Some(ErrorKind::Note), - msg: span.label.clone().unwrap() + msg: span.label.clone().unwrap(), + count: None, }); } @@ -215,6 +219,7 @@ fn push_backtrace(expected_errors: &mut Vec, line_num: expansion.span.line_start, kind: Some(ErrorKind::Note), msg: format!("in this expansion of {}", expansion.macro_decl_name), + count: None, } ); } From 2bb7c0852179d52e9cd2228e366ac124e1ec482a Mon Sep 17 00:00:00 2001 From: Piotr Czarnecki Date: Wed, 3 Aug 2016 19:13:26 +0200 Subject: [PATCH 2/4] Parse the expected message count For example '9' in `//~ ERROR*9 foo` --- src/errors.rs | 49 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/src/errors.rs b/src/errors.rs index d211a26..474f0e0 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -128,24 +128,38 @@ fn parse_expected(last_nonfollow_error: Option, (false, line[start + tag.len()..].chars().take_while(|c| *c == '^').count()) }; let kind_start = start + tag.len() + adjusts + (follow as usize); - let (kind, msg); - match - line[kind_start..].split_whitespace() - .next() - .expect("Encountered unexpected empty comment") - .parse::() - { + let (kind, msg, count); + let kind_str = line[kind_start..].trim_left() + .chars() + .take_while(|c| !c.is_whitespace() && *c != '*') + .collect::(); + match kind_str.parse::() { Ok(k) => { - // If we find `//~ ERROR foo` or something like that: + // If we find `//~ ERROR foo` or `//~ ERROR*9 foo` something like that: kind = Some(k); - let letters = line[kind_start..].chars(); - msg = letters.skip_while(|c| c.is_whitespace()) - .skip_while(|c| !c.is_whitespace()) - .collect::(); + let rest = line[kind_start..].trim_left() + .chars() + .skip_while(|c| !c.is_whitespace() && *c != '*') + .collect::(); + if rest.starts_with('*') { + // We found `//~ ERROR*9 foo` + let count_str = rest.chars().skip(1) + .take_while(|c| c.is_digit(10)) + .collect::(); + count = Some(count_str.parse::().expect("Incorrect message count")); + msg = rest.chars().skip(1) + .skip_while(|c| c.is_digit(10)) + .collect::(); + } else { + // We found `//~ ERROR foo` + count = None; + msg = rest; + } } Err(_) => { // Otherwise we found `//~ foo`: kind = None; + count = None; let letters = line[kind_start..].chars(); msg = letters.skip_while(|c| c.is_whitespace()) .collect::(); @@ -167,7 +181,12 @@ fn parse_expected(last_nonfollow_error: Option, debug!("line={} tag={:?} which={:?} kind={:?} msg={:?}", line_num, tag, which, kind, msg); - Some((which, Error { line_num: line_num, - kind: kind, - msg: msg, })) + Some((which, + Error { + line_num: line_num, + kind: kind, + msg: msg, + count: count, + } + )) } From a8acc4356a93072b5c30a29279a78d55b2feeded Mon Sep 17 00:00:00 2001 From: Piotr Czarnecki Date: Wed, 3 Aug 2016 19:19:19 +0200 Subject: [PATCH 3/4] Check errors using the expected message count. Duplicate actual errors are allowed by default. Errors with multispans are considered as duplicated for each sub-span. This is a [breaking-change] to compiletest's behavior. --- src/runtest.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/runtest.rs b/src/runtest.rs index 42edbd4..9827b7f 100644 --- a/src/runtest.rs +++ b/src/runtest.rs @@ -1015,13 +1015,14 @@ actual:\n\ let mut unexpected = 0; let mut not_found = 0; let mut found = vec![false; expected_errors.len()]; + let mut counts_expected = expected_errors.iter().map(|ee| ee.count).collect::>(); for actual_error in &actual_errors { let opt_index = expected_errors .iter() .enumerate() .position(|(index, expected_error)| { - !found[index] && + counts_expected[index] != Some(0) && actual_error.line_num == expected_error.line_num && (expected_error.kind.is_none() || actual_error.kind == expected_error.kind) && @@ -1031,8 +1032,11 @@ actual:\n\ match opt_index { Some(index) => { // found a match, everybody is happy - assert!(!found[index]); found[index] = true; + if let &mut Some(ref mut count) = &mut counts_expected[index] { + assert!(*count != 0); + *count -= 1; + } } None => { @@ -1053,7 +1057,8 @@ actual:\n\ // anything not yet found is a problem for (index, expected_error) in expected_errors.iter().enumerate() { - if !found[index] { + let count_is_good = counts_expected[index] == None || counts_expected[index] == Some(0); + if !found[index] || !count_is_good { self.error( &format!("{}:{}: expected {} not found: {}", file_name, From f27684b987264a94a9dd1f9da412b7ea3f7688f7 Mon Sep 17 00:00:00 2001 From: Piotr Czarnecki Date: Wed, 3 Aug 2016 19:30:03 +0200 Subject: [PATCH 4/4] Update a test --- test-project/tests/compile-fail/multiple-errors.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/test-project/tests/compile-fail/multiple-errors.rs b/test-project/tests/compile-fail/multiple-errors.rs index ce11277..8748741 100644 --- a/test-project/tests/compile-fail/multiple-errors.rs +++ b/test-project/tests/compile-fail/multiple-errors.rs @@ -1,5 +1,9 @@ -fn main() { - let x: (u64, bool) = (true, 42u64); +fn foo() { + let x: (u64, bool, bool) = (true, 42u64, 666u64); //~^ ERROR mismatched types - //~^^ ERROR mismatched types +} + +fn bar() { + let x: (u64, bool) = (true, 42u64); + //~^ ERROR*2 mismatched types }