Skip to content

Commit 6439eae

Browse files
committed
allow several ui_test headers in compiletest
1 parent 03a5725 commit 6439eae

File tree

18 files changed

+894
-406
lines changed

18 files changed

+894
-406
lines changed

Cargo.lock

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,7 @@ dependencies = [
668668
"rustfix",
669669
"serde",
670670
"serde_json",
671+
"test_common",
671672
"tracing",
672673
"tracing-subscriber",
673674
"unified-diff",
@@ -5053,6 +5054,13 @@ dependencies = [
50535054
"std",
50545055
]
50555056

5057+
[[package]]
5058+
name = "test_common"
5059+
version = "0.0.0"
5060+
dependencies = [
5061+
"tracing",
5062+
]
5063+
50565064
[[package]]
50575065
name = "tester"
50585066
version = "0.9.1"
@@ -5135,6 +5143,7 @@ dependencies = [
51355143
"regex",
51365144
"semver",
51375145
"termcolor",
5146+
"test_common",
51385147
"walkdir",
51395148
]
51405149

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ members = [
1010
"src/tools/clippy",
1111
"src/tools/clippy/clippy_dev",
1212
"src/tools/compiletest",
13+
"src/tools/test_common",
1314
"src/tools/error_index_generator",
1415
"src/tools/linkchecker",
1516
"src/tools/lint-docs",

compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ pushd rust
1111
command -v rg >/dev/null 2>&1 || cargo install ripgrep
1212

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

compiler/rustc_error_codes/src/error_codes/E0472.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Inline assembly (`asm!`) is not supported on this target.
33
Example of erroneous code:
44

55
```ignore (cannot-change-target)
6-
// compile-flags: --target sparc64-unknown-linux-gnu
6+
//@compile-flags: --target sparc64-unknown-linux-gnu
77
#![no_std]
88
99
use core::arch::asm;

library/core/tests/pin_macro.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// edition:2021
1+
//@edition:2021
22
use core::{
33
marker::PhantomPinned,
44
mem::{drop as stuff, transmute},

src/tools/compiletest/Cargo.toml

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,15 @@ unified-diff = "0.2.1"
1313
getopts = "0.2"
1414
miropt-test-tools = { path = "../miropt-test-tools" }
1515
build_helper = { path = "../build_helper" }
16+
test_common = { path = "../test_common" }
1617
tracing = "0.1"
17-
tracing-subscriber = { version = "0.3.3", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] }
18+
tracing-subscriber = { version = "0.3.3", default-features = false, features = [
19+
"fmt",
20+
"env-filter",
21+
"smallvec",
22+
"parking_lot",
23+
"ansi",
24+
] }
1825
regex = "1.0"
1926
serde = { version = "1.0", features = ["derive"] }
2027
serde_json = "1.0"
@@ -33,7 +40,4 @@ miow = "0.5"
3340

3441
[target.'cfg(windows)'.dependencies.windows]
3542
version = "0.48.0"
36-
features = [
37-
"Win32_Foundation",
38-
"Win32_System_Diagnostics_Debug",
39-
]
43+
features = ["Win32_Foundation", "Win32_System_Diagnostics_Debug"]

src/tools/compiletest/src/errors.rs

Lines changed: 77 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::path::Path;
88
use std::str::FromStr;
99

1010
use once_cell::sync::Lazy;
11-
use regex::Regex;
11+
use regex::{Captures, Regex};
1212
use tracing::*;
1313

1414
#[derive(Clone, Debug, PartialEq)]
@@ -64,13 +64,13 @@ enum WhichLine {
6464
AdjustBackward(usize),
6565
}
6666

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

107-
fn parse_expected(
107+
/// Parses an error pattern from a line, if a pattern exists on that line.
108+
fn try_parse_error_comment(
108109
last_nonfollow_error: Option<usize>,
109110
line_num: usize,
110111
line: &str,
111112
cfg: Option<&str>,
112113
) -> Option<(WhichLine, Error)> {
113-
// Matches comments like:
114-
// //~
115-
// //~|
116-
// //~^
117-
// //~^^^^^
118-
// //[cfg1]~
119-
// //[cfg1,cfg2]~^^
120-
static RE: Lazy<Regex> =
121-
Lazy::new(|| Regex::new(r"//(?:\[(?P<cfgs>[\w,]+)])?~(?P<adjust>\||\^*)").unwrap());
122-
123-
let captures = RE.captures(line)?;
124-
125-
match (cfg, captures.name("cfgs")) {
126-
// Only error messages that contain our `cfg` between the square brackets apply to us.
127-
(Some(cfg), Some(filter)) if !filter.as_str().split(',').any(|s| s == cfg) => return None,
128-
(Some(_), Some(_)) => {}
129-
130-
(None, Some(_)) => panic!("Only tests with revisions should use `//[X]~`"),
131-
132-
// If an error has no list of revisions, it applies to all revisions.
133-
(Some(_), None) | (None, None) => {}
114+
let mut line = line.trim_start();
115+
116+
// compiletest style revisions are `[revs]~`
117+
static COMPILETEST_REVISION: Lazy<Regex> =
118+
Lazy::new(|| Regex::new(r"//\[(?P<revs>[\w,]+)\]~").unwrap());
119+
120+
// compiletest style revisions are `~[revs]`
121+
static UI_TEST_REVISION: Lazy<Regex> =
122+
Lazy::new(|| Regex::new(r"//~\[(?P<revs>[\w,]+)\]").unwrap());
123+
124+
let check_valid_rev = |captures: &Captures<'_>| {
125+
let revs = captures.name("revs").unwrap_or_else(|| {
126+
panic!("expected comment {} parsed as compiletest to have a revs group", line)
127+
});
128+
match cfg {
129+
// If the comment has revisions, only emit an expected error if one of the specified
130+
// revisions is the current revision.
131+
Some(current_rev) => {
132+
revs.as_str().split(',').position(|rev| rev == current_rev).is_some()
133+
}
134+
None => {
135+
panic!("Only tests with revisions should use revisioned error patterns //~[rev]")
136+
}
137+
}
138+
};
139+
140+
// Check for the different types of revisions.
141+
// If neither of the revision styles match, it's a normal error pattern which must start with a //~
142+
// Note that error pattern comments may start anywhere within a line, such as on the same line as code.
143+
if let Some(captures) = COMPILETEST_REVISION.captures(line) {
144+
if !check_valid_rev(&captures) {
145+
// Comment doesn't have a revision for the current revision.
146+
return None;
147+
}
148+
// Remove the matched revisions and trailing ~ from the line.
149+
line = &line[captures.get(0).unwrap().end()..];
150+
} else if let Some(captures) = UI_TEST_REVISION.captures(line) {
151+
if !check_valid_rev(&captures) {
152+
// Comment doesn't have a revision for the current revision.
153+
return None;
154+
}
155+
// Remove the matched ~ and revisions from the line.
156+
line = &line[captures.get(0).unwrap().end()..];
157+
} else {
158+
// Errors without revisions start with a //~ so find where that starts
159+
line = line.find("//~").map(|idx| &line[idx + 3..])?;
134160
}
135161

136-
let (follow, adjusts) = match &captures["adjust"] {
137-
"|" => (true, 0),
138-
circumflexes => (false, circumflexes.len()),
139-
};
162+
// At this point, if the comment has revisions, they've been verified to be correct for the
163+
// current checking revision. Those revisions have been stripped if applicable, and the leading
164+
// ~ for non-revisioned comments has been removed.
165+
166+
// Parse adjustments:
167+
// - | = "same line as previous error"
168+
// - ^ = "applies to the previous line" (may be repeated indefinitely)
169+
// Only one type of adjustment may exist per error pattern.
140170

141-
// Get the part of the comment after the sigil (e.g. `~^^` or ~|).
142-
let whole_match = captures.get(0).unwrap();
143-
let (_, mut msg) = line.split_at(whole_match.end());
171+
let (follow, adjusts) = if line.starts_with('|') {
172+
line = &line[1..];
173+
(true, 0)
174+
} else {
175+
let adjust_count = line.chars().take_while(|&c| c == '^').count();
176+
line = &line[adjust_count..];
177+
(false, adjust_count)
178+
};
144179

145-
let first_word = msg.split_whitespace().next().expect("Encountered unexpected empty comment");
180+
line = line.trim_start();
181+
let first_word = line.split_whitespace().next().expect("Encountered unexpected empty comment");
146182

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

153-
let msg = msg.trim().to_owned();
190+
let line = line.trim().to_owned();
154191

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

168-
debug!(
169-
"line={} tag={:?} which={:?} kind={:?} msg={:?}",
170-
line_num,
171-
whole_match.as_str(),
172-
which,
173-
kind,
174-
msg
175-
);
176-
Some((which, Error { line_num, kind, msg }))
204+
debug!("line={} which={:?} kind={:?} line={:?}", line_num, which, kind, line);
205+
Some((which, Error { line_num, kind, msg: line }))
177206
}

0 commit comments

Comments
 (0)