From 54d51bc48396b89954a10c936f6797064ccdbc29 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Fri, 15 Nov 2019 21:40:05 -0800 Subject: [PATCH 1/4] Allow multiple cfgs per comment in "revisions:" tests The `//[X]~` syntax filters errors for tests that are run across multiple cfgs with `// revisions:`. This commit extends that syntax to accept `//[X,Y]~`, which will match multiple cfgs to the same error annotation. This is functionally the same as writing two comments, `//[X]~` and `//[Y]~`, but can fit on a single line. --- src/tools/compiletest/src/errors.rs | 89 +++++++++++++++-------------- 1 file changed, 47 insertions(+), 42 deletions(-) diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs index 5b3936ffc1e3b..2524468766f27 100644 --- a/src/tools/compiletest/src/errors.rs +++ b/src/tools/compiletest/src/errors.rs @@ -7,7 +7,9 @@ use std::io::BufReader; use std::path::Path; use std::str::FromStr; +use lazy_static::lazy_static; use log::*; +use regex::Regex; #[derive(Clone, Debug, PartialEq)] pub enum ErrorKind { @@ -85,20 +87,16 @@ pub fn load_errors(testfile: &Path, cfg: Option<&str>) -> Vec { // updating it in the map callback below.) let mut last_nonfollow_error = None; - let tag = match cfg { - Some(rev) => format!("//[{}]~", rev), - None => "//~".to_string(), - }; - rdr.lines() .enumerate() .filter_map(|(line_num, line)| { - parse_expected(last_nonfollow_error, line_num + 1, &line.unwrap(), &tag).map( + parse_expected(last_nonfollow_error, line_num + 1, &line.unwrap(), cfg).map( |(which, error)| { match which { FollowPrevious(_) => {} _ => last_nonfollow_error = Some(error.line_num), } + error }, ) @@ -110,46 +108,53 @@ fn parse_expected( last_nonfollow_error: Option, line_num: usize, line: &str, - tag: &str, + cfg: Option<&str>, ) -> Option<(WhichLine, Error)> { - let start = line.find(tag)?; - let (follow, adjusts) = if line[start + tag.len()..].chars().next().unwrap() == '|' { - (true, 0) - } else { - ( - false, - line[start + tag.len()..] - .chars() - .take_while(|c| *c == '^') - .count(), - ) + // Matches comments like: + // //~ + // //~| + // //~^ + // //~^^^^^ + // //[cfg1]~ + // //[cfg1,cfg2]~^^ + lazy_static! { + static ref RE: Regex = + Regex::new(r"//(?:\[(?P[\w,]+)])?~(?P\||\^*)").unwrap(); + } + + let captures = RE.captures(line)?; + + match (cfg, captures.name("cfgs")) { + // Only error messages that contain our `cfg` betweeen the square brackets apply to us. + (Some(cfg), Some(filter)) if !filter.as_str().split(',').any(|s| s == cfg) + => return None, + (Some(_), Some(_)) => {} + + (None, Some(_)) => panic!("Only tests with revisions should use `//[X]~`"), + + // If an error has no list of revisions, it applies to all revisions. + (Some(_), None) | (None, None) => {} + } + + let (follow, adjusts) = match &captures["adjust"] { + "|" => (true, 0), + circumflexes => (false, circumflexes.len()), }; - let kind_start = start + tag.len() + adjusts + (follow as usize); - let (kind, msg); - match line[kind_start..] + + // Get the part of the comment after the sigil (e.g. `~^^` or ~|). + let (_, mut msg) = line.split_at(captures.get(0).unwrap().end()); + + let first_word = msg .split_whitespace() .next() - .expect("Encountered unexpected empty comment") - .parse::() - { - Ok(k) => { - // If we find `//~ ERROR foo` or 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::(); - } - Err(_) => { - // Otherwise we found `//~ foo`: - kind = None; - let letters = line[kind_start..].chars(); - msg = letters - .skip_while(|c| c.is_whitespace()) - .collect::(); - } + .expect("Encountered unexpected empty comment"); + + // If we find `//~ ERROR foo` or something like that, skip the first word. + let kind = first_word.parse::().ok(); + if let Some(_) = kind { + msg = &msg.trim_start().split_at(first_word.len()).1; } + let msg = msg.trim().to_owned(); let (which, line_num) = if follow { @@ -171,7 +176,7 @@ fn parse_expected( debug!( "line={} tag={:?} which={:?} kind={:?} msg={:?}", - line_num, tag, which, kind, msg + line_num, &captures[0], which, kind, msg ); Some(( which, From 701f6e51b2aab7a761e5c9c81cff476e81eef7e0 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Mon, 18 Nov 2019 10:06:21 -0800 Subject: [PATCH 2/4] Fix broken incremental test This test does not actually emit any warnings, since `#![allow(warnings)]` was specified. `compiletest` was erroneously ignoring `//~` tests and looking only for `//[X]~` ones. As a result of the changes in the previous commit, we now look for `//~` comments in incremental tests and expect them to appear in *all* revisions. --- src/test/incremental/warnings-reemitted.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/test/incremental/warnings-reemitted.rs b/src/test/incremental/warnings-reemitted.rs index a1d11f8aa5bbe..5fc89395827c8 100644 --- a/src/test/incremental/warnings-reemitted.rs +++ b/src/test/incremental/warnings-reemitted.rs @@ -2,9 +2,8 @@ // compile-flags: -Coverflow-checks=on // build-pass (FIXME(62277): could be check-pass?) -#![allow(warnings)] #![warn(const_err)] fn main() { - 255u8 + 1; //~ WARNING this expression will panic at run-time + let _ = 255u8 + 1; //~ WARNING attempt to add with overflow } From ae2293837e4c66deaeeb6a895087cb5c76e935ea Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Mon, 18 Nov 2019 10:43:11 -0800 Subject: [PATCH 3/4] Change some tests to use the shorter comment style --- .../cache/project-fn-ret-contravariant.rs | 4 +--- src/test/ui/error-codes/E0161.rs | 10 ++-------- .../where-clause-inherent-impl-underscore.rs | 3 +-- .../where-clause-trait-impl-region.rs | 3 +-- .../where-clause-trait-impl-underscore.rs | 3 +-- 5 files changed, 6 insertions(+), 17 deletions(-) diff --git a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.rs b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.rs index ebf52918153c1..8c6073e2f7a49 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.rs +++ b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.rs @@ -47,6 +47,4 @@ fn transmute<'a,'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) { } #[rustc_error] -fn main() { } -//[ok]~^ ERROR fatal error triggered by #[rustc_error] -//[oneuse]~^^ ERROR fatal error triggered by #[rustc_error] +fn main() { } //[ok,oneuse]~ ERROR fatal error triggered by #[rustc_error] diff --git a/src/test/ui/error-codes/E0161.rs b/src/test/ui/error-codes/E0161.rs index 2ca17050ae2a4..58217ff74b8d6 100644 --- a/src/test/ui/error-codes/E0161.rs +++ b/src/test/ui/error-codes/E0161.rs @@ -20,14 +20,8 @@ fn foo(x: Box<[i32]>) { box *x; - //[migrate]~^ ERROR E0161 - //[nll]~^^ ERROR E0161 - //[zflags]~^^^ ERROR E0161 - //[edition]~^^^^ ERROR E0161 - //[migrateul]~^^^^^ ERROR E0161 - //[nllul]~^^^^^^ ERROR E0161 - //[zflagsul]~^^^^^^^ ERROR E0161 - //[editionul]~^^^^^^^^ ERROR E0161 + //[migrate,nll,zflags,edition]~^ ERROR E0161 + //[migrateul,nllul,zflagsul,editionul]~^^ ERROR E0161 } fn main() {} diff --git a/src/test/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rs b/src/test/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rs index b50cce335bd8c..38189816da849 100644 --- a/src/test/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rs +++ b/src/test/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rs @@ -11,8 +11,7 @@ struct Foo { impl Foo where T: WithRegion<'_> -//[rust2015]~^ ERROR `'_` cannot be used here -//[rust2018]~^^ ERROR `'_` cannot be used here +//[rust2015,rust2018]~^ ERROR `'_` cannot be used here { } fn main() {} diff --git a/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rs b/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rs index f2d483e66e013..09e5bbd846d6c 100644 --- a/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rs +++ b/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rs @@ -9,8 +9,7 @@ trait Foo { } impl Foo for Vec where T: WithType<&u32> -//[rust2015]~^ ERROR `&` without an explicit lifetime name cannot be used here -//[rust2018]~^^ ERROR `&` without an explicit lifetime name cannot be used here +//[rust2015,rust2018]~^ ERROR `&` without an explicit lifetime name cannot be used here { } fn main() {} diff --git a/src/test/ui/underscore-lifetime/where-clause-trait-impl-underscore.rs b/src/test/ui/underscore-lifetime/where-clause-trait-impl-underscore.rs index 94e4426e822d9..371d2e4ba43ac 100644 --- a/src/test/ui/underscore-lifetime/where-clause-trait-impl-underscore.rs +++ b/src/test/ui/underscore-lifetime/where-clause-trait-impl-underscore.rs @@ -9,8 +9,7 @@ trait Foo { } impl Foo for Vec where T: WithRegion<'_> -//[rust2015]~^ ERROR `'_` cannot be used here -//[rust2018]~^^ ERROR `'_` cannot be used here +//[rust2015,rust2018]~^ ERROR `'_` cannot be used here { } fn main() {} From c537f229009bcec23ac89132fd6f571acbc23c38 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Thu, 21 Nov 2019 14:13:42 -0800 Subject: [PATCH 4/4] Give name to full regex capture --- src/tools/compiletest/src/errors.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs index 2524468766f27..0ec2738181ee2 100644 --- a/src/tools/compiletest/src/errors.rs +++ b/src/tools/compiletest/src/errors.rs @@ -142,7 +142,8 @@ fn parse_expected( }; // Get the part of the comment after the sigil (e.g. `~^^` or ~|). - let (_, mut msg) = line.split_at(captures.get(0).unwrap().end()); + let whole_match = captures.get(0).unwrap(); + let (_, mut msg) = line.split_at(whole_match.end()); let first_word = msg .split_whitespace() @@ -176,7 +177,7 @@ fn parse_expected( debug!( "line={} tag={:?} which={:?} kind={:?} msg={:?}", - line_num, &captures[0], which, kind, msg + line_num, whole_match.as_str(), which, kind, msg ); Some(( which,