Skip to content

Allow ui_test style headers in compiletest #114072

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
9 changes: 9 additions & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,7 @@ dependencies = [
"rustfix",
"serde",
"serde_json",
"test_common",
"tracing",
"tracing-subscriber",
"unified-diff",
Expand Down Expand Up @@ -5053,6 +5054,13 @@ dependencies = [
"std",
]

[[package]]
name = "test_common"
version = "0.0.0"
dependencies = [
"tracing",
]

[[package]]
name = "tester"
version = "0.9.1"
Expand Down Expand Up @@ -5135,6 +5143,7 @@ dependencies = [
"regex",
"semver",
"termcolor",
"test_common",
"walkdir",
]

Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ members = [
"src/tools/clippy",
"src/tools/clippy/clippy_dev",
"src/tools/compiletest",
"src/tools/test_common",
"src/tools/error_index_generator",
"src/tools/linkchecker",
"src/tools/lint-docs",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pushd rust
command -v rg >/dev/null 2>&1 || cargo install ripgrep

rm -r tests/ui/{unsized-locals/,lto/,linkage*} || true
for test in $(rg --files-with-matches "lto|// needs-asm-support" tests/{codegen-units,ui,incremental}); do
for test in $(rg --files-with-matches "lto|//@needs-asm-support" tests/{codegen-units,ui,incremental}); do
rm $test
done

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_error_codes/src/error_codes/E0472.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Inline assembly (`asm!`) is not supported on this target.
Example of erroneous code:

```ignore (cannot-change-target)
// compile-flags: --target sparc64-unknown-linux-gnu
//@compile-flags: --target sparc64-unknown-linux-gnu
#![no_std]

use core::arch::asm;
Expand Down
14 changes: 9 additions & 5 deletions src/tools/compiletest/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,15 @@ unified-diff = "0.2.1"
getopts = "0.2"
miropt-test-tools = { path = "../miropt-test-tools" }
build_helper = { path = "../build_helper" }
test_common = { path = "../test_common" }
tracing = "0.1"
tracing-subscriber = { version = "0.3.3", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] }
tracing-subscriber = { version = "0.3.3", default-features = false, features = [
"fmt",
"env-filter",
"smallvec",
"parking_lot",
"ansi",
] }
regex = "1.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
Expand All @@ -33,7 +40,4 @@ miow = "0.5"

[target.'cfg(windows)'.dependencies.windows]
version = "0.48.0"
features = [
"Win32_Foundation",
"Win32_System_Diagnostics_Debug",
]
features = ["Win32_Foundation", "Win32_System_Diagnostics_Debug"]
125 changes: 77 additions & 48 deletions src/tools/compiletest/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::path::Path;
use std::str::FromStr;

use once_cell::sync::Lazy;
use regex::Regex;
use regex::{Captures, Regex};
use tracing::*;

#[derive(Clone, Debug, PartialEq)]
Expand Down Expand Up @@ -64,13 +64,13 @@ enum WhichLine {
AdjustBackward(usize),
}

/// Looks for either "//~| KIND MESSAGE" or "//~^^... KIND MESSAGE"
/// Looks for either `//~| KIND MESSAGE` or `//~^^... KIND MESSAGE`
/// The former is a "follow" that inherits its target from the preceding line;
/// the latter is an "adjusts" that goes that many lines up.
///
/// Goal is to enable tests both like: //~^^^ ERROR go up three
/// and also //~^ ERROR message one for the preceding line, and
/// //~| ERROR message two for that same line.
/// Goal is to enable tests both like: `//~^^^ ERROR` go up three
/// and also `//~^` ERROR message one for the preceding line, and
/// `//~|` ERROR message two for that same line.
///
/// If cfg is not None (i.e., in an incremental test), then we look
/// for `//[X]~` instead, where `X` is the current `cfg`.
Expand All @@ -90,7 +90,7 @@ pub fn load_errors(testfile: &Path, cfg: Option<&str>) -> Vec<Error> {
rdr.lines()
.enumerate()
.filter_map(|(line_num, line)| {
parse_expected(last_nonfollow_error, line_num + 1, &line.unwrap(), cfg).map(
try_parse_error_comment(last_nonfollow_error, line_num + 1, &line.unwrap(), cfg).map(
|(which, error)| {
match which {
FollowPrevious(_) => {}
Expand All @@ -104,56 +104,92 @@ pub fn load_errors(testfile: &Path, cfg: Option<&str>) -> Vec<Error> {
.collect()
}

fn parse_expected(
/// Parses an error pattern from a line, if a pattern exists on that line.
fn try_parse_error_comment(
last_nonfollow_error: Option<usize>,
line_num: usize,
line: &str,
cfg: Option<&str>,
) -> Option<(WhichLine, Error)> {
// Matches comments like:
// //~
// //~|
// //~^
// //~^^^^^
// //[cfg1]~
// //[cfg1,cfg2]~^^
static RE: Lazy<Regex> =
Lazy::new(|| Regex::new(r"//(?:\[(?P<cfgs>[\w,]+)])?~(?P<adjust>\||\^*)").unwrap());

let captures = RE.captures(line)?;

match (cfg, captures.name("cfgs")) {
// Only error messages that contain our `cfg` between 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 mut line = line.trim_start();

// compiletest style revisions are `[revs]~`
static COMPILETEST_REVISION: Lazy<Regex> =
Lazy::new(|| Regex::new(r"//\[(?P<revs>[\w,]+)\]~").unwrap());

// ui_test style revisions are `~[revs]`
static UI_TEST_REVISION: Lazy<Regex> =
Lazy::new(|| Regex::new(r"//~\[(?P<revs>[\w,]+)\]").unwrap());

let check_valid_rev = |captures: &Captures<'_>| {
let revs = captures.name("revs").unwrap_or_else(|| {
panic!("expected comment {} parsed as compiletest to have a revs group", line)
});
match cfg {
// If the comment has revisions, only emit an expected error if one of the specified
// revisions is the current revision.
Some(current_rev) => {
revs.as_str().split(',').position(|rev| rev == current_rev).is_some()
}
None => {
panic!("Only tests with revisions should use revisioned error patterns //~[rev]")
}
}
};

// Check for the different types of revisions.
// If neither of the revision styles match, it's a normal error pattern which must start with a //~
// Note that error pattern comments may start anywhere within a line, such as on the same line as code.
if let Some(captures) = COMPILETEST_REVISION.captures(line) {
if !check_valid_rev(&captures) {
// Comment doesn't have a revision for the current revision.
return None;
}
// Remove the matched revisions and trailing ~ from the line.
line = &line[captures.get(0).unwrap().end()..];
} else if let Some(captures) = UI_TEST_REVISION.captures(line) {
if !check_valid_rev(&captures) {
// Comment doesn't have a revision for the current revision.
return None;
}
// Remove the matched ~ and revisions from the line.
line = &line[captures.get(0).unwrap().end()..];
} else {
// Errors without revisions start with a //~ so find where that starts
line = line.find("//~").map(|idx| &line[idx + 3..])?;
}

let (follow, adjusts) = match &captures["adjust"] {
"|" => (true, 0),
circumflexes => (false, circumflexes.len()),
};
// At this point, if the comment has revisions, they've been verified to be correct for the
// current checking revision. Those revisions have been stripped if applicable, and the leading
// ~ for non-revisioned comments has been removed.

// Parse adjustments:
// - | = "same line as previous error"
// - ^ = "applies to the previous line" (may be repeated indefinitely)
// Only one type of adjustment may exist per error pattern.

// Get the part of the comment after the sigil (e.g. `~^^` or ~|).
let whole_match = captures.get(0).unwrap();
let (_, mut msg) = line.split_at(whole_match.end());
let (follow, adjusts) = if line.starts_with('|') {
line = &line[1..];
(true, 0)
} else {
let adjust_count = line.chars().take_while(|&c| c == '^').count();
line = &line[adjust_count..];
(false, adjust_count)
};

let first_word = msg.split_whitespace().next().expect("Encountered unexpected empty comment");
line = line.trim_start();
let first_word = line.split_whitespace().next().expect("Encountered unexpected empty comment");

// If we find `//~ ERROR foo` or something like that, skip the first word.
// The `FromStr` impl for ErrorKind accepts a trailing `:` too.
let kind = first_word.parse::<ErrorKind>().ok();
if kind.is_some() {
msg = &msg.trim_start().split_at(first_word.len()).1;
line = &line.trim_start().split_at(first_word.len()).1;
}

let msg = msg.trim().to_owned();
let line = line.trim().to_owned();

let (which, line_num) = if follow {
assert_eq!(adjusts, 0, "use either //~| or //~^, not both.");
let line_num = last_nonfollow_error.expect(
"encountered //~| without \
preceding //~^ line.",
Expand All @@ -165,13 +201,6 @@ fn parse_expected(
(which, line_num)
};

debug!(
"line={} tag={:?} which={:?} kind={:?} msg={:?}",
line_num,
whole_match.as_str(),
which,
kind,
msg
);
Some((which, Error { line_num, kind, msg }))
debug!("line={} which={:?} kind={:?} line={:?}", line_num, which, kind, line);
Some((which, Error { line_num, kind, msg: line }))
}
Loading