Rollup merge of #93953 - jackh726:known_bug, r=Mark-Simulacrum
Add the `known-bug` test directive, use it, and do some cleanup cc rust-lang/compiler-team#476 Now tests can be annotated with `known-bug`, which should indicate that the test *should* pass (or at least that the current output is a bug). Adding it relaxes the requirement to add error annotations to the test (though it is still allowed). In the future, this could be extended with further relaxations - with the goal to make adding these tests need minimal effort. I've used this attribute for the GAT tests added in #93757. Finally, I've also cleaned up `header.rs` in compiletest a bit, by extracting out a bit of common logic. I've also split out some of the directives into their own consts. This removes a lot of very similar functions from `Config` and makes `TestProps::load_from` read nicer. I've split these into separate commits, so I in theory could split these into separate PRs if they're controversial, but I think they're pretty straightforward. r? ``@Mark-Simulacrum``
This commit is contained in:
commit
620b0c5122
22 changed files with 219 additions and 249 deletions
|
|
@ -1,4 +1,5 @@
|
|||
// check-fail
|
||||
// known-bug
|
||||
|
||||
// This should pass, but it requires `Sized` to be coinductive.
|
||||
|
||||
|
|
@ -11,7 +12,6 @@ trait Allocator {
|
|||
enum LinkedList<A: Allocator> {
|
||||
Head,
|
||||
Next(A::Allocated<Self>)
|
||||
//~^ overflow
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error[E0275]: overflow evaluating the requirement `LinkedList<A>: Sized`
|
||||
--> $DIR/issue-80626.rs:13:10
|
||||
--> $DIR/issue-80626.rs:14:10
|
||||
|
|
||||
LL | Next(A::Allocated<Self>)
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
// check-fail
|
||||
// known-bug
|
||||
|
||||
// This should pass, but seems to run into a TAIT issue.
|
||||
|
||||
|
|
@ -20,7 +21,6 @@ trait Yay<AdditionalValue> {
|
|||
|
||||
impl<'a> Yay<&'a ()> for () {
|
||||
type InnerStream<'s> = impl Stream<Item = i32> + 's;
|
||||
//~^ the type
|
||||
fn foo<'s>() -> Self::InnerStream<'s> { todo!() }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
error[E0477]: the type `impl Stream<Item = i32>` does not fulfill the required lifetime
|
||||
--> $DIR/issue-86218.rs:22:28
|
||||
--> $DIR/issue-86218.rs:23:28
|
||||
|
|
||||
LL | type InnerStream<'s> = impl Stream<Item = i32> + 's;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: type must outlive the lifetime `'s` as defined here as required by this binding
|
||||
--> $DIR/issue-86218.rs:22:22
|
||||
--> $DIR/issue-86218.rs:23:22
|
||||
|
|
||||
LL | type InnerStream<'s> = impl Stream<Item = i32> + 's;
|
||||
| ^^
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
// check-fail
|
||||
// known-bug
|
||||
|
||||
// This should pass, but we need an extension of implied bounds (probably).
|
||||
|
||||
|
|
@ -23,7 +24,7 @@ struct Foo<T>(T);
|
|||
#[derive(Debug)]
|
||||
struct FooRef<'a, U>(&'a [U]);
|
||||
|
||||
impl<'b, T, U> AsRef2 for Foo<T> //~ the type parameter
|
||||
impl<'b, T, U> AsRef2 for Foo<T>
|
||||
where
|
||||
// * `for<'b, 'c> T: AsRef2<Output<'b> = &'c [U]>>` does not work
|
||||
//
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
|
||||
--> $DIR/issue-87735.rs:26:13
|
||||
--> $DIR/issue-87735.rs:27:13
|
||||
|
|
||||
LL | impl<'b, T, U> AsRef2 for Foo<T>
|
||||
| ^ unconstrained type parameter
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
// check-fail
|
||||
// known-bug
|
||||
|
||||
// This should pass, but unnormalized input args aren't treated as implied.
|
||||
|
||||
|
|
@ -14,7 +15,7 @@ struct Foo;
|
|||
impl MyTrait for Foo {
|
||||
type Assoc<'a, 'b> where 'b: 'a = u32;
|
||||
|
||||
fn do_sth(_: u32) {} //~ lifetime bound
|
||||
fn do_sth(_: u32) {}
|
||||
// fn do_sth(_: Self::Assoc<'static, 'static>) {}
|
||||
// fn do_sth(_: Self::Assoc<'_, '_>) {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
error[E0478]: lifetime bound not satisfied
|
||||
--> $DIR/issue-87748.rs:17:5
|
||||
--> $DIR/issue-87748.rs:18:5
|
||||
|
|
||||
LL | fn do_sth(_: u32) {}
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: lifetime parameter instantiated with the anonymous lifetime #2 defined here
|
||||
--> $DIR/issue-87748.rs:17:5
|
||||
--> $DIR/issue-87748.rs:18:5
|
||||
|
|
||||
LL | fn do_sth(_: u32) {}
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
note: but lifetime parameter must outlive the anonymous lifetime #1 defined here
|
||||
--> $DIR/issue-87748.rs:17:5
|
||||
--> $DIR/issue-87748.rs:18:5
|
||||
|
|
||||
LL | fn do_sth(_: u32) {}
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
// check-fail
|
||||
// known-bug
|
||||
|
||||
// This should pass.
|
||||
|
||||
|
|
@ -15,7 +16,6 @@ struct Bar;
|
|||
|
||||
impl Foo for Bar {
|
||||
type Ass = Bar;
|
||||
//~^ overflow
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error[E0275]: overflow evaluating the requirement `<Bar as Foo>::Ass == _`
|
||||
--> $DIR/issue-87755.rs:17:16
|
||||
--> $DIR/issue-87755.rs:18:16
|
||||
|
|
||||
LL | type Ass = Bar;
|
||||
| ^^^
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
// check-fail
|
||||
// known-bug
|
||||
|
||||
// This should pass, but using a type alias vs a reference directly
|
||||
// changes late-bound -> early-bound.
|
||||
|
|
@ -18,7 +19,7 @@ impl Scanner for IdScanner {
|
|||
type Input<'a> = &'a str;
|
||||
type Token<'a> = &'a str;
|
||||
|
||||
fn scan<'a>(&mut self, s : &'a str) -> &'a str { //~ lifetime parameters
|
||||
fn scan<'a>(&mut self, s : &'a str) -> &'a str {
|
||||
s
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error[E0195]: lifetime parameters or bounds on method `scan` do not match the trait declaration
|
||||
--> $DIR/issue-87803.rs:21:12
|
||||
--> $DIR/issue-87803.rs:22:12
|
||||
|
|
||||
LL | fn scan<'a>(&mut self, i : Self::Input<'a>) -> Self::Token<'a>;
|
||||
| ---- lifetimes in impl do not match this method in trait
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
// check-fail
|
||||
// known-bug
|
||||
|
||||
// This should pass, but has a missed normalization due to HRTB.
|
||||
|
||||
|
|
@ -25,7 +26,6 @@ fn do_something<I: Iterable>(i: I, mut f: impl for<'a> Fn(&mut I::Iterator<'a>))
|
|||
fn main() {
|
||||
do_something(SomeImplementation(), |_| ());
|
||||
do_something(SomeImplementation(), test);
|
||||
//~^ type mismatch
|
||||
}
|
||||
|
||||
fn test<'a, I: Iterable>(_: &mut I::Iterator<'a>) {}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error[E0631]: type mismatch in function arguments
|
||||
--> $DIR/issue-88382.rs:27:40
|
||||
--> $DIR/issue-88382.rs:28:40
|
||||
|
|
||||
LL | do_something(SomeImplementation(), test);
|
||||
| ------------ ^^^^ expected signature of `for<'a> fn(&mut <SomeImplementation as Iterable>::Iterator<'a>) -> _`
|
||||
|
|
@ -10,7 +10,7 @@ LL | fn test<'a, I: Iterable>(_: &mut I::Iterator<'a>) {}
|
|||
| ------------------------------------------------- found signature of `for<'r> fn(&'r mut std::iter::Empty<usize>) -> _`
|
||||
|
|
||||
note: required by a bound in `do_something`
|
||||
--> $DIR/issue-88382.rs:21:56
|
||||
--> $DIR/issue-88382.rs:22:56
|
||||
|
|
||||
LL | fn do_something<I: Iterable>(i: I, mut f: impl for<'a> Fn(&mut I::Iterator<'a>)) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `do_something`
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
// check-fail
|
||||
// known-bug
|
||||
|
||||
// This should pass, but has a missed normalization due to HRTB.
|
||||
|
||||
|
|
@ -27,5 +28,4 @@ impl Trait for Foo {
|
|||
|
||||
fn main() {
|
||||
test(Foo);
|
||||
//~^ the trait bound
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
error[E0277]: the trait bound `for<'a> <_ as Trait>::Assoc<'a>: Marker` is not satisfied
|
||||
--> $DIR/issue-88460.rs:29:5
|
||||
--> $DIR/issue-88460.rs:30:5
|
||||
|
|
||||
LL | test(Foo);
|
||||
| ^^^^ the trait `for<'a> Marker` is not implemented for `<_ as Trait>::Assoc<'a>`
|
||||
|
|
||||
note: required by a bound in `test`
|
||||
--> $DIR/issue-88460.rs:16:27
|
||||
--> $DIR/issue-88460.rs:17:27
|
||||
|
|
||||
LL | fn test<T>(value: T)
|
||||
| ---- required by a bound in this
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
// check-fail
|
||||
// known-bug
|
||||
|
||||
// This should pass, but requires more logic.
|
||||
|
||||
|
|
@ -23,7 +24,7 @@ struct TestB<Q, F>
|
|||
f: F,
|
||||
}
|
||||
|
||||
impl<'q, Q, I, F> A for TestB<Q, F> //~ the type parameter
|
||||
impl<'q, Q, I, F> A for TestB<Q, F>
|
||||
where
|
||||
Q: A<I<'q> = &'q I>,
|
||||
F: Fn(I),
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error[E0207]: the type parameter `I` is not constrained by the impl trait, self type, or predicates
|
||||
--> $DIR/issue-88526.rs:26:13
|
||||
--> $DIR/issue-88526.rs:27:13
|
||||
|
|
||||
LL | impl<'q, Q, I, F> A for TestB<Q, F>
|
||||
| ^ unconstrained type parameter
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
// check-fail
|
||||
// edition:2021
|
||||
// known-bug
|
||||
|
||||
// This should pass, but seems to run into a TAIT bug.
|
||||
|
||||
|
|
@ -31,11 +32,11 @@ trait X {
|
|||
struct Y;
|
||||
|
||||
impl X for Y {
|
||||
type LineStream<'a, Repr> = impl Stream<Item = Repr>; //~ could not find
|
||||
type LineStream<'a, Repr> = impl Stream<Item = Repr>;
|
||||
|
||||
type LineStreamFut<'a, Repr> = impl Future<Output = Self::LineStream<'a, Repr>> ;
|
||||
|
||||
fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> { //~ type mismatch
|
||||
fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {
|
||||
async {empty()}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error[E0271]: type mismatch resolving `<impl Future<Output = [async output]> as Future>::Output == impl Stream<Item = Repr>`
|
||||
--> $DIR/issue-89008.rs:38:43
|
||||
--> $DIR/issue-89008.rs:39:43
|
||||
|
|
||||
LL | type LineStream<'a, Repr> = impl Stream<Item = Repr>;
|
||||
| ------------------------ the expected opaque type
|
||||
|
|
@ -11,7 +11,7 @@ LL | fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {
|
|||
found struct `Empty<_>`
|
||||
|
||||
error: could not find defining uses
|
||||
--> $DIR/issue-89008.rs:34:33
|
||||
--> $DIR/issue-89008.rs:35:33
|
||||
|
|
||||
LL | type LineStream<'a, Repr> = impl Stream<Item = Repr>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
|
|||
|
|
@ -41,12 +41,15 @@ impl EarlyProps {
|
|||
pub fn from_reader<R: Read>(config: &Config, testfile: &Path, rdr: R) -> Self {
|
||||
let mut props = EarlyProps::default();
|
||||
iter_header(testfile, rdr, &mut |_, ln| {
|
||||
if let Some(s) = config.parse_aux_build(ln) {
|
||||
props.aux.push(s);
|
||||
}
|
||||
if let Some(ac) = config.parse_aux_crate(ln) {
|
||||
props.aux_crate.push(ac);
|
||||
}
|
||||
config.push_name_value_directive(ln, directives::AUX_BUILD, &mut props.aux, |r| {
|
||||
r.trim().to_string()
|
||||
});
|
||||
config.push_name_value_directive(
|
||||
ln,
|
||||
directives::AUX_CRATE,
|
||||
&mut props.aux_crate,
|
||||
Config::parse_aux_crate,
|
||||
);
|
||||
config.parse_and_update_revisions(ln, &mut props.revisions);
|
||||
});
|
||||
return props;
|
||||
|
|
@ -126,6 +129,12 @@ pub struct TestProps {
|
|||
// empty before the test starts. Incremental mode tests will reuse the
|
||||
// incremental directory between passes in the same test.
|
||||
pub incremental: bool,
|
||||
// If `true`, this test is a known bug.
|
||||
//
|
||||
// When set, some requirements are relaxed. Currently, this only means no
|
||||
// error annotations are needed, but this may be updated in the future to
|
||||
// include other relaxations.
|
||||
pub known_bug: bool,
|
||||
// How far should the test proceed while still passing.
|
||||
pass_mode: Option<PassMode>,
|
||||
// Ignore `--pass` overrides from the command line for this test.
|
||||
|
|
@ -150,6 +159,38 @@ pub struct TestProps {
|
|||
pub stderr_per_bitwidth: bool,
|
||||
}
|
||||
|
||||
mod directives {
|
||||
pub const ERROR_PATTERN: &'static str = "error-pattern";
|
||||
pub const COMPILE_FLAGS: &'static str = "compile-flags";
|
||||
pub const RUN_FLAGS: &'static str = "run-flags";
|
||||
pub const SHOULD_ICE: &'static str = "should-ice";
|
||||
pub const BUILD_AUX_DOCS: &'static str = "build-aux-docs";
|
||||
pub const FORCE_HOST: &'static str = "force-host";
|
||||
pub const CHECK_STDOUT: &'static str = "check-stdout";
|
||||
pub const CHECK_RUN_RESULTS: &'static str = "check-run-results";
|
||||
pub const DONT_CHECK_COMPILER_STDOUT: &'static str = "dont-check-compiler-stdout";
|
||||
pub const DONT_CHECK_COMPILER_STDERR: &'static str = "dont-check-compiler-stderr";
|
||||
pub const NO_PREFER_DYNAMIC: &'static str = "no-prefer-dynamic";
|
||||
pub const PRETTY_EXPANDED: &'static str = "pretty-expanded";
|
||||
pub const PRETTY_MODE: &'static str = "pretty-mode";
|
||||
pub const PRETTY_COMPARE_ONLY: &'static str = "pretty-compare-only";
|
||||
pub const AUX_BUILD: &'static str = "aux-build";
|
||||
pub const AUX_CRATE: &'static str = "aux-crate";
|
||||
pub const EXEC_ENV: &'static str = "exec-env";
|
||||
pub const RUSTC_ENV: &'static str = "rustc-env";
|
||||
pub const UNSET_RUSTC_ENV: &'static str = "unset-rustc-env";
|
||||
pub const FORBID_OUTPUT: &'static str = "forbid-output";
|
||||
pub const CHECK_TEST_LINE_NUMBERS_MATCH: &'static str = "check-test-line-numbers-match";
|
||||
pub const IGNORE_PASS: &'static str = "ignore-pass";
|
||||
pub const FAILURE_STATUS: &'static str = "failure-status";
|
||||
pub const RUN_RUSTFIX: &'static str = "run-rustfix";
|
||||
pub const RUSTFIX_ONLY_MACHINE_APPLICABLE: &'static str = "rustfix-only-machine-applicable";
|
||||
pub const ASSEMBLY_OUTPUT: &'static str = "assembly-output";
|
||||
pub const STDERR_PER_BITWIDTH: &'static str = "stderr-per-bitwidth";
|
||||
pub const INCREMENTAL: &'static str = "incremental";
|
||||
pub const KNOWN_BUG: &'static str = "known-bug";
|
||||
}
|
||||
|
||||
impl TestProps {
|
||||
pub fn new() -> Self {
|
||||
TestProps {
|
||||
|
|
@ -176,6 +217,7 @@ impl TestProps {
|
|||
forbid_output: vec![],
|
||||
incremental_dir: None,
|
||||
incremental: false,
|
||||
known_bug: false,
|
||||
pass_mode: None,
|
||||
fail_mode: None,
|
||||
ignore_pass: false,
|
||||
|
|
@ -228,11 +270,16 @@ impl TestProps {
|
|||
return;
|
||||
}
|
||||
|
||||
if let Some(ep) = config.parse_error_pattern(ln) {
|
||||
self.error_patterns.push(ep);
|
||||
}
|
||||
use directives::*;
|
||||
|
||||
if let Some(flags) = config.parse_compile_flags(ln) {
|
||||
config.push_name_value_directive(
|
||||
ln,
|
||||
ERROR_PATTERN,
|
||||
&mut self.error_patterns,
|
||||
|r| r,
|
||||
);
|
||||
|
||||
if let Some(flags) = config.parse_name_value_directive(ln, COMPILE_FLAGS) {
|
||||
self.compile_flags.extend(flags.split_whitespace().map(|s| s.to_owned()));
|
||||
}
|
||||
|
||||
|
|
@ -243,93 +290,73 @@ impl TestProps {
|
|||
|
||||
config.parse_and_update_revisions(ln, &mut self.revisions);
|
||||
|
||||
if self.run_flags.is_none() {
|
||||
self.run_flags = config.parse_run_flags(ln);
|
||||
}
|
||||
config.set_name_value_directive(ln, RUN_FLAGS, &mut self.run_flags, |r| r);
|
||||
|
||||
if self.pp_exact.is_none() {
|
||||
self.pp_exact = config.parse_pp_exact(ln, testfile);
|
||||
}
|
||||
|
||||
if !self.should_ice {
|
||||
self.should_ice = config.parse_should_ice(ln);
|
||||
}
|
||||
config.set_name_directive(ln, SHOULD_ICE, &mut self.should_ice);
|
||||
config.set_name_directive(ln, BUILD_AUX_DOCS, &mut self.build_aux_docs);
|
||||
config.set_name_directive(ln, FORCE_HOST, &mut self.force_host);
|
||||
config.set_name_directive(ln, CHECK_STDOUT, &mut self.check_stdout);
|
||||
config.set_name_directive(ln, CHECK_RUN_RESULTS, &mut self.check_run_results);
|
||||
config.set_name_directive(
|
||||
ln,
|
||||
DONT_CHECK_COMPILER_STDOUT,
|
||||
&mut self.dont_check_compiler_stdout,
|
||||
);
|
||||
config.set_name_directive(
|
||||
ln,
|
||||
DONT_CHECK_COMPILER_STDERR,
|
||||
&mut self.dont_check_compiler_stderr,
|
||||
);
|
||||
config.set_name_directive(ln, NO_PREFER_DYNAMIC, &mut self.no_prefer_dynamic);
|
||||
config.set_name_directive(ln, PRETTY_EXPANDED, &mut self.pretty_expanded);
|
||||
|
||||
if !self.build_aux_docs {
|
||||
self.build_aux_docs = config.parse_build_aux_docs(ln);
|
||||
}
|
||||
|
||||
if !self.force_host {
|
||||
self.force_host = config.parse_force_host(ln);
|
||||
}
|
||||
|
||||
if !self.check_stdout {
|
||||
self.check_stdout = config.parse_check_stdout(ln);
|
||||
}
|
||||
|
||||
if !self.check_run_results {
|
||||
self.check_run_results = config.parse_check_run_results(ln);
|
||||
}
|
||||
|
||||
if !self.dont_check_compiler_stdout {
|
||||
self.dont_check_compiler_stdout = config.parse_dont_check_compiler_stdout(ln);
|
||||
}
|
||||
|
||||
if !self.dont_check_compiler_stderr {
|
||||
self.dont_check_compiler_stderr = config.parse_dont_check_compiler_stderr(ln);
|
||||
}
|
||||
|
||||
if !self.no_prefer_dynamic {
|
||||
self.no_prefer_dynamic = config.parse_no_prefer_dynamic(ln);
|
||||
}
|
||||
|
||||
if !self.pretty_expanded {
|
||||
self.pretty_expanded = config.parse_pretty_expanded(ln);
|
||||
}
|
||||
|
||||
if let Some(m) = config.parse_pretty_mode(ln) {
|
||||
if let Some(m) = config.parse_name_value_directive(ln, PRETTY_MODE) {
|
||||
self.pretty_mode = m;
|
||||
}
|
||||
|
||||
if !self.pretty_compare_only {
|
||||
self.pretty_compare_only = config.parse_pretty_compare_only(ln);
|
||||
}
|
||||
|
||||
if let Some(ab) = config.parse_aux_build(ln) {
|
||||
self.aux_builds.push(ab);
|
||||
}
|
||||
|
||||
if let Some(ac) = config.parse_aux_crate(ln) {
|
||||
self.aux_crates.push(ac);
|
||||
}
|
||||
|
||||
if let Some(ee) = config.parse_env(ln, "exec-env") {
|
||||
self.exec_env.push(ee);
|
||||
}
|
||||
|
||||
if let Some(ee) = config.parse_env(ln, "rustc-env") {
|
||||
self.rustc_env.push(ee);
|
||||
}
|
||||
|
||||
if let Some(ev) = config.parse_name_value_directive(ln, "unset-rustc-env") {
|
||||
self.unset_rustc_env.push(ev);
|
||||
}
|
||||
|
||||
if let Some(of) = config.parse_forbid_output(ln) {
|
||||
self.forbid_output.push(of);
|
||||
}
|
||||
|
||||
if !self.check_test_line_numbers_match {
|
||||
self.check_test_line_numbers_match =
|
||||
config.parse_check_test_line_numbers_match(ln);
|
||||
}
|
||||
config.set_name_directive(ln, PRETTY_COMPARE_ONLY, &mut self.pretty_compare_only);
|
||||
config.push_name_value_directive(ln, AUX_BUILD, &mut self.aux_builds, |r| {
|
||||
r.trim().to_string()
|
||||
});
|
||||
config.push_name_value_directive(
|
||||
ln,
|
||||
AUX_CRATE,
|
||||
&mut self.aux_crates,
|
||||
Config::parse_aux_crate,
|
||||
);
|
||||
config.push_name_value_directive(
|
||||
ln,
|
||||
EXEC_ENV,
|
||||
&mut self.exec_env,
|
||||
Config::parse_env,
|
||||
);
|
||||
config.push_name_value_directive(
|
||||
ln,
|
||||
RUSTC_ENV,
|
||||
&mut self.rustc_env,
|
||||
Config::parse_env,
|
||||
);
|
||||
config.push_name_value_directive(
|
||||
ln,
|
||||
UNSET_RUSTC_ENV,
|
||||
&mut self.unset_rustc_env,
|
||||
|r| r,
|
||||
);
|
||||
config.push_name_value_directive(ln, FORBID_OUTPUT, &mut self.forbid_output, |r| r);
|
||||
config.set_name_directive(
|
||||
ln,
|
||||
CHECK_TEST_LINE_NUMBERS_MATCH,
|
||||
&mut self.check_test_line_numbers_match,
|
||||
);
|
||||
|
||||
self.update_pass_mode(ln, cfg, config);
|
||||
self.update_fail_mode(ln, config);
|
||||
|
||||
if !self.ignore_pass {
|
||||
self.ignore_pass = config.parse_ignore_pass(ln);
|
||||
}
|
||||
config.set_name_directive(ln, IGNORE_PASS, &mut self.ignore_pass);
|
||||
|
||||
if let Some(rule) = config.parse_custom_normalization(ln, "normalize-stdout") {
|
||||
self.normalize_stdout.push(rule);
|
||||
|
|
@ -338,30 +365,28 @@ impl TestProps {
|
|||
self.normalize_stderr.push(rule);
|
||||
}
|
||||
|
||||
if let Some(code) = config.parse_failure_status(ln) {
|
||||
if let Some(code) = config
|
||||
.parse_name_value_directive(ln, FAILURE_STATUS)
|
||||
.and_then(|code| code.trim().parse::<i32>().ok())
|
||||
{
|
||||
self.failure_status = code;
|
||||
}
|
||||
|
||||
if !self.run_rustfix {
|
||||
self.run_rustfix = config.parse_run_rustfix(ln);
|
||||
}
|
||||
|
||||
if !self.rustfix_only_machine_applicable {
|
||||
self.rustfix_only_machine_applicable =
|
||||
config.parse_rustfix_only_machine_applicable(ln);
|
||||
}
|
||||
|
||||
if self.assembly_output.is_none() {
|
||||
self.assembly_output = config.parse_assembly_output(ln);
|
||||
}
|
||||
|
||||
if !self.stderr_per_bitwidth {
|
||||
self.stderr_per_bitwidth = config.parse_stderr_per_bitwidth(ln);
|
||||
}
|
||||
|
||||
if !self.incremental {
|
||||
self.incremental = config.parse_incremental(ln);
|
||||
}
|
||||
config.set_name_directive(ln, RUN_RUSTFIX, &mut self.run_rustfix);
|
||||
config.set_name_directive(
|
||||
ln,
|
||||
RUSTFIX_ONLY_MACHINE_APPLICABLE,
|
||||
&mut self.rustfix_only_machine_applicable,
|
||||
);
|
||||
config.set_name_value_directive(
|
||||
ln,
|
||||
ASSEMBLY_OUTPUT,
|
||||
&mut self.assembly_output,
|
||||
|r| r.trim().to_string(),
|
||||
);
|
||||
config.set_name_directive(ln, STDERR_PER_BITWIDTH, &mut self.stderr_per_bitwidth);
|
||||
config.set_name_directive(ln, INCREMENTAL, &mut self.incremental);
|
||||
config.set_name_directive(ln, KNOWN_BUG, &mut self.known_bug);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -503,33 +528,12 @@ fn iter_header<R: Read>(testfile: &Path, rdr: R, it: &mut dyn FnMut(Option<&str>
|
|||
}
|
||||
|
||||
impl Config {
|
||||
fn parse_should_ice(&self, line: &str) -> bool {
|
||||
self.parse_name_directive(line, "should-ice")
|
||||
}
|
||||
fn parse_error_pattern(&self, line: &str) -> Option<String> {
|
||||
self.parse_name_value_directive(line, "error-pattern")
|
||||
}
|
||||
|
||||
fn parse_forbid_output(&self, line: &str) -> Option<String> {
|
||||
self.parse_name_value_directive(line, "forbid-output")
|
||||
}
|
||||
|
||||
fn parse_aux_build(&self, line: &str) -> Option<String> {
|
||||
self.parse_name_value_directive(line, "aux-build").map(|r| r.trim().to_string())
|
||||
}
|
||||
|
||||
fn parse_aux_crate(&self, line: &str) -> Option<(String, String)> {
|
||||
self.parse_name_value_directive(line, "aux-crate").map(|r| {
|
||||
let mut parts = r.trim().splitn(2, '=');
|
||||
(
|
||||
parts.next().expect("missing aux-crate name (e.g. log=log.rs)").to_string(),
|
||||
parts.next().expect("missing aux-crate value (e.g. log=log.rs)").to_string(),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_compile_flags(&self, line: &str) -> Option<String> {
|
||||
self.parse_name_value_directive(line, "compile-flags")
|
||||
fn parse_aux_crate(r: String) -> (String, String) {
|
||||
let mut parts = r.trim().splitn(2, '=');
|
||||
(
|
||||
parts.next().expect("missing aux-crate name (e.g. log=log.rs)").to_string(),
|
||||
parts.next().expect("missing aux-crate value (e.g. log=log.rs)").to_string(),
|
||||
)
|
||||
}
|
||||
|
||||
fn parse_and_update_revisions(&self, line: &str, existing: &mut Vec<String>) {
|
||||
|
|
@ -544,87 +548,18 @@ impl Config {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_run_flags(&self, line: &str) -> Option<String> {
|
||||
self.parse_name_value_directive(line, "run-flags")
|
||||
}
|
||||
fn parse_env(nv: String) -> (String, String) {
|
||||
// nv is either FOO or FOO=BAR
|
||||
let mut strs: Vec<String> = nv.splitn(2, '=').map(str::to_owned).collect();
|
||||
|
||||
fn parse_force_host(&self, line: &str) -> bool {
|
||||
self.parse_name_directive(line, "force-host")
|
||||
}
|
||||
|
||||
fn parse_build_aux_docs(&self, line: &str) -> bool {
|
||||
self.parse_name_directive(line, "build-aux-docs")
|
||||
}
|
||||
|
||||
fn parse_check_stdout(&self, line: &str) -> bool {
|
||||
self.parse_name_directive(line, "check-stdout")
|
||||
}
|
||||
|
||||
fn parse_check_run_results(&self, line: &str) -> bool {
|
||||
self.parse_name_directive(line, "check-run-results")
|
||||
}
|
||||
|
||||
fn parse_dont_check_compiler_stdout(&self, line: &str) -> bool {
|
||||
self.parse_name_directive(line, "dont-check-compiler-stdout")
|
||||
}
|
||||
|
||||
fn parse_dont_check_compiler_stderr(&self, line: &str) -> bool {
|
||||
self.parse_name_directive(line, "dont-check-compiler-stderr")
|
||||
}
|
||||
|
||||
fn parse_no_prefer_dynamic(&self, line: &str) -> bool {
|
||||
self.parse_name_directive(line, "no-prefer-dynamic")
|
||||
}
|
||||
|
||||
fn parse_pretty_expanded(&self, line: &str) -> bool {
|
||||
self.parse_name_directive(line, "pretty-expanded")
|
||||
}
|
||||
|
||||
fn parse_pretty_mode(&self, line: &str) -> Option<String> {
|
||||
self.parse_name_value_directive(line, "pretty-mode")
|
||||
}
|
||||
|
||||
fn parse_pretty_compare_only(&self, line: &str) -> bool {
|
||||
self.parse_name_directive(line, "pretty-compare-only")
|
||||
}
|
||||
|
||||
fn parse_failure_status(&self, line: &str) -> Option<i32> {
|
||||
match self.parse_name_value_directive(line, "failure-status") {
|
||||
Some(code) => code.trim().parse::<i32>().ok(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_check_test_line_numbers_match(&self, line: &str) -> bool {
|
||||
self.parse_name_directive(line, "check-test-line-numbers-match")
|
||||
}
|
||||
|
||||
fn parse_ignore_pass(&self, line: &str) -> bool {
|
||||
self.parse_name_directive(line, "ignore-pass")
|
||||
}
|
||||
|
||||
fn parse_stderr_per_bitwidth(&self, line: &str) -> bool {
|
||||
self.parse_name_directive(line, "stderr-per-bitwidth")
|
||||
}
|
||||
|
||||
fn parse_assembly_output(&self, line: &str) -> Option<String> {
|
||||
self.parse_name_value_directive(line, "assembly-output").map(|r| r.trim().to_string())
|
||||
}
|
||||
|
||||
fn parse_env(&self, line: &str, name: &str) -> Option<(String, String)> {
|
||||
self.parse_name_value_directive(line, name).map(|nv| {
|
||||
// nv is either FOO or FOO=BAR
|
||||
let mut strs: Vec<String> = nv.splitn(2, '=').map(str::to_owned).collect();
|
||||
|
||||
match strs.len() {
|
||||
1 => (strs.pop().unwrap(), String::new()),
|
||||
2 => {
|
||||
let end = strs.pop().unwrap();
|
||||
(strs.pop().unwrap(), end)
|
||||
}
|
||||
n => panic!("Expected 1 or 2 strings, not {}", n),
|
||||
match strs.len() {
|
||||
1 => (strs.pop().unwrap(), String::new()),
|
||||
2 => {
|
||||
let end = strs.pop().unwrap();
|
||||
(strs.pop().unwrap(), end)
|
||||
}
|
||||
})
|
||||
n => panic!("Expected 1 or 2 strings, not {}", n),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_pp_exact(&self, line: &str, testfile: &Path) -> Option<PathBuf> {
|
||||
|
|
@ -736,20 +671,38 @@ impl Config {
|
|||
None
|
||||
}
|
||||
|
||||
fn parse_run_rustfix(&self, line: &str) -> bool {
|
||||
self.parse_name_directive(line, "run-rustfix")
|
||||
}
|
||||
|
||||
fn parse_rustfix_only_machine_applicable(&self, line: &str) -> bool {
|
||||
self.parse_name_directive(line, "rustfix-only-machine-applicable")
|
||||
}
|
||||
|
||||
fn parse_edition(&self, line: &str) -> Option<String> {
|
||||
self.parse_name_value_directive(line, "edition")
|
||||
}
|
||||
|
||||
fn parse_incremental(&self, line: &str) -> bool {
|
||||
self.parse_name_directive(line, "incremental")
|
||||
fn set_name_directive(&self, line: &str, directive: &str, value: &mut bool) {
|
||||
if !*value {
|
||||
*value = self.parse_name_directive(line, directive)
|
||||
}
|
||||
}
|
||||
|
||||
fn set_name_value_directive<T>(
|
||||
&self,
|
||||
line: &str,
|
||||
directive: &str,
|
||||
value: &mut Option<T>,
|
||||
parse: impl FnOnce(String) -> T,
|
||||
) {
|
||||
if value.is_none() {
|
||||
*value = self.parse_name_value_directive(line, directive).map(parse);
|
||||
}
|
||||
}
|
||||
|
||||
fn push_name_value_directive<T>(
|
||||
&self,
|
||||
line: &str,
|
||||
directive: &str,
|
||||
values: &mut Vec<T>,
|
||||
parse: impl FnOnce(String) -> T,
|
||||
) {
|
||||
if let Some(value) = self.parse_name_value_directive(line, directive).map(parse) {
|
||||
values.push(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -903,7 +856,8 @@ pub fn make_test_description<R: Read>(
|
|||
ignore |= !has_memtag && config.parse_name_directive(ln, "needs-sanitizer-memtag");
|
||||
ignore |= config.target_panic == PanicStrategy::Abort
|
||||
&& config.parse_name_directive(ln, "needs-unwind");
|
||||
ignore |= config.target == "wasm32-unknown-unknown" && config.parse_check_run_results(ln);
|
||||
ignore |= config.target == "wasm32-unknown-unknown"
|
||||
&& config.parse_name_directive(ln, directives::CHECK_RUN_RESULTS);
|
||||
ignore |= config.debugger == Some(Debugger::Cdb) && ignore_cdb(config, ln);
|
||||
ignore |= config.debugger == Some(Debugger::Gdb) && ignore_gdb(config, ln);
|
||||
ignore |= config.debugger == Some(Debugger::Lldb) && ignore_lldb(config, ln);
|
||||
|
|
|
|||
|
|
@ -1274,6 +1274,16 @@ impl<'test> TestCx<'test> {
|
|||
self.fatal_proc_rec("process did not return an error status", proc_res);
|
||||
}
|
||||
|
||||
if self.props.known_bug {
|
||||
if !expected_errors.is_empty() {
|
||||
self.fatal_proc_rec(
|
||||
"`known_bug` tests should not have an expected errors",
|
||||
proc_res,
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 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();
|
||||
|
|
@ -1310,6 +1320,7 @@ impl<'test> TestCx<'test> {
|
|||
}
|
||||
|
||||
None => {
|
||||
// If the test is a known bug, don't require that the error is annotated
|
||||
if self.is_unexpected_compiler_message(actual_error, expect_help, expect_note) {
|
||||
self.error(&format!(
|
||||
"{}:{}: unexpected {}: '{}'",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue