diff --git a/src/test/ui/generic-associated-types/bugs/issue-80626.rs b/src/test/ui/generic-associated-types/bugs/issue-80626.rs index aea8aaf4bb393..a637da6cf6fa7 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-80626.rs +++ b/src/test/ui/generic-associated-types/bugs/issue-80626.rs @@ -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 { Head, Next(A::Allocated) - //~^ overflow } fn main() {} diff --git a/src/test/ui/generic-associated-types/bugs/issue-80626.stderr b/src/test/ui/generic-associated-types/bugs/issue-80626.stderr index e18af9c257f7f..8b0cc78e99949 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-80626.stderr +++ b/src/test/ui/generic-associated-types/bugs/issue-80626.stderr @@ -1,5 +1,5 @@ error[E0275]: overflow evaluating the requirement `LinkedList: Sized` - --> $DIR/issue-80626.rs:13:10 + --> $DIR/issue-80626.rs:14:10 | LL | Next(A::Allocated) | ^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/generic-associated-types/bugs/issue-86218.rs b/src/test/ui/generic-associated-types/bugs/issue-86218.rs index 3f8776a363770..68cd0fd7efce0 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-86218.rs +++ b/src/test/ui/generic-associated-types/bugs/issue-86218.rs @@ -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 { impl<'a> Yay<&'a ()> for () { type InnerStream<'s> = impl Stream + 's; - //~^ the type fn foo<'s>() -> Self::InnerStream<'s> { todo!() } } diff --git a/src/test/ui/generic-associated-types/bugs/issue-86218.stderr b/src/test/ui/generic-associated-types/bugs/issue-86218.stderr index 9f4efc0addb73..98a5f4254bb1b 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-86218.stderr +++ b/src/test/ui/generic-associated-types/bugs/issue-86218.stderr @@ -1,11 +1,11 @@ error[E0477]: the type `impl Stream` does not fulfill the required lifetime - --> $DIR/issue-86218.rs:22:28 + --> $DIR/issue-86218.rs:23:28 | LL | type InnerStream<'s> = impl Stream + '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 + 's; | ^^ diff --git a/src/test/ui/generic-associated-types/bugs/issue-87735.rs b/src/test/ui/generic-associated-types/bugs/issue-87735.rs index 5f7a42a740df6..6d6063f8085ba 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-87735.rs +++ b/src/test/ui/generic-associated-types/bugs/issue-87735.rs @@ -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); #[derive(Debug)] struct FooRef<'a, U>(&'a [U]); -impl<'b, T, U> AsRef2 for Foo //~ the type parameter +impl<'b, T, U> AsRef2 for Foo where // * `for<'b, 'c> T: AsRef2 = &'c [U]>>` does not work // diff --git a/src/test/ui/generic-associated-types/bugs/issue-87735.stderr b/src/test/ui/generic-associated-types/bugs/issue-87735.stderr index 31b3a9619b6af..0a18b5f0cbdaa 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-87735.stderr +++ b/src/test/ui/generic-associated-types/bugs/issue-87735.stderr @@ -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 | ^ unconstrained type parameter diff --git a/src/test/ui/generic-associated-types/bugs/issue-87748.rs b/src/test/ui/generic-associated-types/bugs/issue-87748.rs index 4dbaf429ead26..ffcfd62cbb3be 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-87748.rs +++ b/src/test/ui/generic-associated-types/bugs/issue-87748.rs @@ -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<'_, '_>) {} } diff --git a/src/test/ui/generic-associated-types/bugs/issue-87748.stderr b/src/test/ui/generic-associated-types/bugs/issue-87748.stderr index c38d447859233..60bb48efbc895 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-87748.stderr +++ b/src/test/ui/generic-associated-types/bugs/issue-87748.stderr @@ -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) {} | ^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/generic-associated-types/bugs/issue-87755.rs b/src/test/ui/generic-associated-types/bugs/issue-87755.rs index 1cd3534ba77a0..31cea12a3e241 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-87755.rs +++ b/src/test/ui/generic-associated-types/bugs/issue-87755.rs @@ -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() {} diff --git a/src/test/ui/generic-associated-types/bugs/issue-87755.stderr b/src/test/ui/generic-associated-types/bugs/issue-87755.stderr index d2dc991a2b640..5d1aff0117c13 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-87755.stderr +++ b/src/test/ui/generic-associated-types/bugs/issue-87755.stderr @@ -1,5 +1,5 @@ error[E0275]: overflow evaluating the requirement `::Ass == _` - --> $DIR/issue-87755.rs:17:16 + --> $DIR/issue-87755.rs:18:16 | LL | type Ass = Bar; | ^^^ diff --git a/src/test/ui/generic-associated-types/bugs/issue-87803.rs b/src/test/ui/generic-associated-types/bugs/issue-87803.rs index 3d2ff38ab049e..57a4b028d93ea 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-87803.rs +++ b/src/test/ui/generic-associated-types/bugs/issue-87803.rs @@ -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 } } diff --git a/src/test/ui/generic-associated-types/bugs/issue-87803.stderr b/src/test/ui/generic-associated-types/bugs/issue-87803.stderr index 759c0440d07ba..c81c051d32a89 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-87803.stderr +++ b/src/test/ui/generic-associated-types/bugs/issue-87803.stderr @@ -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 diff --git a/src/test/ui/generic-associated-types/bugs/issue-88382.rs b/src/test/ui/generic-associated-types/bugs/issue-88382.rs index f4633ca516999..c9f342405278a 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-88382.rs +++ b/src/test/ui/generic-associated-types/bugs/issue-88382.rs @@ -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: 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>) {} diff --git a/src/test/ui/generic-associated-types/bugs/issue-88382.stderr b/src/test/ui/generic-associated-types/bugs/issue-88382.stderr index 05bc58cbba4e6..d06c3ec8de75e 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-88382.stderr +++ b/src/test/ui/generic-associated-types/bugs/issue-88382.stderr @@ -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 ::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) -> _` | 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: I, mut f: impl for<'a> Fn(&mut I::Iterator<'a>)) { | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `do_something` diff --git a/src/test/ui/generic-associated-types/bugs/issue-88460.rs b/src/test/ui/generic-associated-types/bugs/issue-88460.rs index 7e62790cc50c3..b31d012d2fc41 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-88460.rs +++ b/src/test/ui/generic-associated-types/bugs/issue-88460.rs @@ -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 } diff --git a/src/test/ui/generic-associated-types/bugs/issue-88460.stderr b/src/test/ui/generic-associated-types/bugs/issue-88460.stderr index 604658da7d2c2..0b83e9da1ab7a 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-88460.stderr +++ b/src/test/ui/generic-associated-types/bugs/issue-88460.stderr @@ -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(value: T) | ---- required by a bound in this diff --git a/src/test/ui/generic-associated-types/bugs/issue-88526.rs b/src/test/ui/generic-associated-types/bugs/issue-88526.rs index 90568fcb40125..c72a450b9261c 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-88526.rs +++ b/src/test/ui/generic-associated-types/bugs/issue-88526.rs @@ -1,4 +1,5 @@ // check-fail +// known-bug // This should pass, but requires more logic. @@ -23,7 +24,7 @@ struct TestB f: F, } -impl<'q, Q, I, F> A for TestB //~ the type parameter +impl<'q, Q, I, F> A for TestB where Q: A = &'q I>, F: Fn(I), diff --git a/src/test/ui/generic-associated-types/bugs/issue-88526.stderr b/src/test/ui/generic-associated-types/bugs/issue-88526.stderr index ccc5ae0b621a1..127c889bf715e 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-88526.stderr +++ b/src/test/ui/generic-associated-types/bugs/issue-88526.stderr @@ -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 | ^ unconstrained type parameter diff --git a/src/test/ui/generic-associated-types/bugs/issue-89008.rs b/src/test/ui/generic-associated-types/bugs/issue-89008.rs index 5d850849fd21c..1581b7105a867 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-89008.rs +++ b/src/test/ui/generic-associated-types/bugs/issue-89008.rs @@ -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; //~ could not find + type LineStream<'a, Repr> = impl Stream; type LineStreamFut<'a, Repr> = impl Future> ; - 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()} } } diff --git a/src/test/ui/generic-associated-types/bugs/issue-89008.stderr b/src/test/ui/generic-associated-types/bugs/issue-89008.stderr index 48745fe0fbd96..c2687ca540153 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-89008.stderr +++ b/src/test/ui/generic-associated-types/bugs/issue-89008.stderr @@ -1,5 +1,5 @@ error[E0271]: type mismatch resolving ` as Future>::Output == impl Stream` - --> $DIR/issue-89008.rs:38:43 + --> $DIR/issue-89008.rs:39:43 | LL | type LineStream<'a, Repr> = impl Stream; | ------------------------ 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; | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 60c94eff47a0d..887d27fd6dca4 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -41,12 +41,15 @@ impl EarlyProps { pub fn from_reader(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, // 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); - } - - 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) { + 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 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::().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(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 { - self.parse_name_value_directive(line, "error-pattern") - } - - fn parse_forbid_output(&self, line: &str) -> Option { - self.parse_name_value_directive(line, "forbid-output") - } - - fn parse_aux_build(&self, line: &str) -> Option { - 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 { - 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) { @@ -544,87 +548,18 @@ impl Config { } } - fn parse_run_flags(&self, line: &str) -> Option { - self.parse_name_value_directive(line, "run-flags") - } - - 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 { - 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 { - match self.parse_name_value_directive(line, "failure-status") { - Some(code) => code.trim().parse::().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 { - 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 = nv.splitn(2, '=').map(str::to_owned).collect(); + fn parse_env(nv: String) -> (String, String) { + // nv is either FOO or FOO=BAR + let mut strs: Vec = 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 { @@ -736,20 +671,38 @@ impl Config { None } - fn parse_run_rustfix(&self, line: &str) -> bool { - self.parse_name_directive(line, "run-rustfix") + fn parse_edition(&self, line: &str) -> Option { + self.parse_name_value_directive(line, "edition") } - fn parse_rustfix_only_machine_applicable(&self, line: &str) -> bool { - self.parse_name_directive(line, "rustfix-only-machine-applicable") + fn set_name_directive(&self, line: &str, directive: &str, value: &mut bool) { + if !*value { + *value = self.parse_name_directive(line, directive) + } } - fn parse_edition(&self, line: &str) -> Option { - self.parse_name_value_directive(line, "edition") + fn set_name_value_directive( + &self, + line: &str, + directive: &str, + value: &mut Option, + parse: impl FnOnce(String) -> T, + ) { + if value.is_none() { + *value = self.parse_name_value_directive(line, directive).map(parse); + } } - fn parse_incremental(&self, line: &str) -> bool { - self.parse_name_directive(line, "incremental") + fn push_name_value_directive( + &self, + line: &str, + directive: &str, + values: &mut Vec, + 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( 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); diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index f6ddac3a65e06..7fe7db0801b47 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -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 {}: '{}'",