diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index c95652f274e36..2bc4b59962b1b 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -29,6 +29,12 @@ use syntax_pos::symbol::InternedString; // Queries marked with `fatal_cycle` do not need the latter implementation, // as they will raise an fatal error on query cycles instead. rustc_queries! { + Other { + query trigger_delay_span_bug(key: DefId) -> () { + desc { "trigger a delay span bug" } + } + } + Other { /// Records the type of every item. query type_of(key: DefId) -> Ty<'tcx> { diff --git a/src/librustc_codegen_utils/lib.rs b/src/librustc_codegen_utils/lib.rs index 66920342ff6ba..fb2099e71a31a 100644 --- a/src/librustc_codegen_utils/lib.rs +++ b/src/librustc_codegen_utils/lib.rs @@ -19,7 +19,7 @@ extern crate rustc; use rustc::ty::TyCtxt; use rustc::ty::query::Providers; -use rustc::hir::def_id::LOCAL_CRATE; +use rustc::hir::def_id::{LOCAL_CRATE, DefId}; use syntax::symbol::sym; pub mod link; @@ -27,18 +27,50 @@ pub mod codegen_backend; pub mod symbol_names; pub mod symbol_names_test; + +pub fn trigger_delay_span_bug(tcx: TyCtxt<'_>, key: DefId) { + tcx.sess.delay_span_bug( + tcx.def_span(key), + "delayed span bug triggered by #[rustc_error(delay_span_bug_from_inside_query)]" + ); +} + /// check for the #[rustc_error] annotation, which forces an /// error in codegen. This is used to write compile-fail tests /// that actually test that compilation succeeds without /// reporting an error. pub fn check_for_rustc_errors_attr(tcx: TyCtxt<'_>) { if let Some((def_id, _)) = tcx.entry_fn(LOCAL_CRATE) { - if tcx.has_attr(def_id, sym::rustc_error) { - tcx.sess.span_fatal(tcx.def_span(def_id), "compilation successful"); + let attrs = &*tcx.get_attrs(def_id); + for attr in attrs { + if attr.check_name(sym::rustc_error) { + match attr.meta_item_list() { + // check if there is a #[rustc_error(delayed)] + Some(list) => { + if list.iter().any(|list_item| { + list_item.ident().map(|i| i.name) == + Some(sym::delay_span_bug_from_inside_query) + }) { + tcx.ensure().trigger_delay_span_bug(def_id); + } + } + // bare #[rustc_error] + None => { + tcx.sess.span_fatal( + tcx.def_span(def_id), + "fatal error triggered by #[rustc_error]" + ); + } + } + } } } } pub fn provide(providers: &mut Providers<'_>) { crate::symbol_names::provide(providers); + *providers = Providers { + trigger_delay_span_bug, + ..*providers + }; } diff --git a/src/libsyntax/feature_gate/builtin_attrs.rs b/src/libsyntax/feature_gate/builtin_attrs.rs index ab1620b952491..e9eef1c9d6b02 100644 --- a/src/libsyntax/feature_gate/builtin_attrs.rs +++ b/src/libsyntax/feature_gate/builtin_attrs.rs @@ -533,7 +533,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_attr!(TEST, rustc_variance, Normal, template!(Word)), rustc_attr!(TEST, rustc_layout, Normal, template!(List: "field1, field2, ...")), rustc_attr!(TEST, rustc_regions, Normal, template!(Word)), - rustc_attr!(TEST, rustc_error, Whitelisted, template!(Word)), + rustc_attr!( + TEST, rustc_error, Whitelisted, + template!(Word, List: "delay_span_bug_from_inside_query") + ), rustc_attr!(TEST, rustc_dump_user_substs, Whitelisted, template!(Word)), rustc_attr!(TEST, rustc_if_this_changed, Whitelisted, template!(Word, List: "DepNode")), rustc_attr!(TEST, rustc_then_this_would_need, Whitelisted, template!(List: "DepNode")), diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index c37efde9923a7..6ff9ee03e1941 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -234,6 +234,7 @@ symbols! { default_lib_allocator, default_type_parameter_fallback, default_type_params, + delay_span_bug_from_inside_query, deny, deprecated, deref, diff --git a/src/test/incremental/delayed_span_bug.rs b/src/test/incremental/delayed_span_bug.rs new file mode 100644 index 0000000000000..2529e531e30ad --- /dev/null +++ b/src/test/incremental/delayed_span_bug.rs @@ -0,0 +1,8 @@ +// revisions: cfail1 cfail2 +// should-ice +// error-pattern: delayed span bug triggered by #[rustc_error(delay_span_bug_from_inside_query)] + +#![feature(rustc_attrs)] + +#[rustc_error(delay_span_bug_from_inside_query)] +fn main() {} diff --git a/src/test/ui/associated-types/bound-lifetime-constrained.rs b/src/test/ui/associated-types/bound-lifetime-constrained.rs index fb82b3fa66660..4e6754c865dce 100644 --- a/src/test/ui/associated-types/bound-lifetime-constrained.rs +++ b/src/test/ui/associated-types/bound-lifetime-constrained.rs @@ -45,4 +45,4 @@ fn clause2() where T: for<'a> Fn() -> <() as Foo<'a>>::Item { } #[rustc_error] -fn main() { } //[ok]~ ERROR compilation successful +fn main() { } //[ok]~ ERROR fatal error triggered by #[rustc_error] diff --git a/src/test/ui/associated-types/bound-lifetime-in-binding-only.ok.stderr b/src/test/ui/associated-types/bound-lifetime-in-binding-only.ok.stderr index fcdb371a6e599..5ece425196c77 100644 --- a/src/test/ui/associated-types/bound-lifetime-in-binding-only.ok.stderr +++ b/src/test/ui/associated-types/bound-lifetime-in-binding-only.ok.stderr @@ -1,4 +1,4 @@ -error: compilation successful +error: fatal error triggered by #[rustc_error] --> $DIR/bound-lifetime-in-binding-only.rs:71:1 | LL | fn main() { } diff --git a/src/test/ui/associated-types/bound-lifetime-in-binding-only.rs b/src/test/ui/associated-types/bound-lifetime-in-binding-only.rs index 843f5f0619588..e714457ef7b38 100644 --- a/src/test/ui/associated-types/bound-lifetime-in-binding-only.rs +++ b/src/test/ui/associated-types/bound-lifetime-in-binding-only.rs @@ -68,4 +68,4 @@ fn ok3() where for<'a> Parameterized<'a>: Foo { } #[rustc_error] -fn main() { } //[ok]~ ERROR compilation successful +fn main() { } //[ok]~ ERROR fatal error triggered by #[rustc_error] diff --git a/src/test/ui/associated-types/bound-lifetime-in-return-only.ok.stderr b/src/test/ui/associated-types/bound-lifetime-in-return-only.ok.stderr index 504d68e66e23e..8c0980983119b 100644 --- a/src/test/ui/associated-types/bound-lifetime-in-return-only.ok.stderr +++ b/src/test/ui/associated-types/bound-lifetime-in-return-only.ok.stderr @@ -1,4 +1,4 @@ -error: compilation successful +error: fatal error triggered by #[rustc_error] --> $DIR/bound-lifetime-in-return-only.rs:49:1 | LL | fn main() { } diff --git a/src/test/ui/associated-types/bound-lifetime-in-return-only.rs b/src/test/ui/associated-types/bound-lifetime-in-return-only.rs index 9c0dc61494d1f..a60ccb6c4b28d 100644 --- a/src/test/ui/associated-types/bound-lifetime-in-return-only.rs +++ b/src/test/ui/associated-types/bound-lifetime-in-return-only.rs @@ -46,4 +46,4 @@ fn ok2(_: &dyn for<'a,'b> Fn<(&'b Parameterized<'a>,), Output=&'a i32>) { } #[rustc_error] -fn main() { } //[ok]~ ERROR compilation successful +fn main() { } //[ok]~ ERROR fatal error triggered by #[rustc_error] diff --git a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.ok.stderr b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.ok.stderr index 15bbea671c50f..baa8e6f82f646 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.ok.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.ok.stderr @@ -1,4 +1,4 @@ -error: compilation successful +error: fatal error triggered by #[rustc_error] --> $DIR/project-fn-ret-contravariant.rs:50:1 | LL | fn main() { } diff --git a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.oneuse.stderr b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.oneuse.stderr index 15bbea671c50f..baa8e6f82f646 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.oneuse.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.oneuse.stderr @@ -1,4 +1,4 @@ -error: compilation successful +error: fatal error triggered by #[rustc_error] --> $DIR/project-fn-ret-contravariant.rs:50:1 | LL | fn main() { } 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 d953325df2349..ebf52918153c1 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 @@ -48,5 +48,5 @@ fn transmute<'a,'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) { #[rustc_error] fn main() { } -//[ok]~^ ERROR compilation successful -//[oneuse]~^^ ERROR compilation successful +//[ok]~^ ERROR fatal error triggered by #[rustc_error] +//[oneuse]~^^ ERROR fatal error triggered by #[rustc_error] diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.ok.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.ok.stderr index 8110ed40cfe4e..8f445acf2b98c 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.ok.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.ok.stderr @@ -1,4 +1,4 @@ -error: compilation successful +error: fatal error triggered by #[rustc_error] --> $DIR/project-fn-ret-invariant.rs:59:1 | LL | fn main() { } diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs b/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs index 54b6e3642c2ea..23d873212ed1e 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs @@ -57,4 +57,4 @@ fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { #[rustc_error] fn main() { } -//[ok]~^ ERROR compilation successful +//[ok]~^ ERROR fatal error triggered by #[rustc_error] diff --git a/src/test/ui/associated-types/higher-ranked-projection.good.stderr b/src/test/ui/associated-types/higher-ranked-projection.good.stderr index 16fef0510f871..63d88543607f3 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.good.stderr +++ b/src/test/ui/associated-types/higher-ranked-projection.good.stderr @@ -1,4 +1,4 @@ -error: compilation successful +error: fatal error triggered by #[rustc_error] --> $DIR/higher-ranked-projection.rs:24:1 | LL | / fn main() { diff --git a/src/test/ui/associated-types/higher-ranked-projection.rs b/src/test/ui/associated-types/higher-ranked-projection.rs index a2ea6d8f206b6..5315e21b0f5a9 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.rs +++ b/src/test/ui/associated-types/higher-ranked-projection.rs @@ -21,7 +21,7 @@ fn foo(_t: T) {} #[rustc_error] -fn main() { //[good]~ ERROR compilation successful +fn main() { //[good]~ ERROR fatal error triggered by #[rustc_error] foo(()); //[bad]~^ ERROR type mismatch } diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr index 9ec36f4c142e9..6aba6466fada5 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr @@ -1,4 +1,4 @@ -error: compilation successful +error: fatal error triggered by #[rustc_error] --> $DIR/hr-subtype.rs:100:1 | LL | / fn main() { diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr index 9ec36f4c142e9..6aba6466fada5 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr @@ -1,4 +1,4 @@ -error: compilation successful +error: fatal error triggered by #[rustc_error] --> $DIR/hr-subtype.rs:100:1 | LL | / fn main() { diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr index 9ec36f4c142e9..6aba6466fada5 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr @@ -1,4 +1,4 @@ -error: compilation successful +error: fatal error triggered by #[rustc_error] --> $DIR/hr-subtype.rs:100:1 | LL | / fn main() { diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr index 9ec36f4c142e9..6aba6466fada5 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr @@ -1,4 +1,4 @@ -error: compilation successful +error: fatal error triggered by #[rustc_error] --> $DIR/hr-subtype.rs:100:1 | LL | / fn main() { diff --git a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr index 9ec36f4c142e9..6aba6466fada5 100644 --- a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr @@ -1,4 +1,4 @@ -error: compilation successful +error: fatal error triggered by #[rustc_error] --> $DIR/hr-subtype.rs:100:1 | LL | / fn main() { diff --git a/src/test/ui/hr-subtype/hr-subtype.rs b/src/test/ui/hr-subtype/hr-subtype.rs index 2f7c1e6fd8c0d..b31f198bd97bf 100644 --- a/src/test/ui/hr-subtype/hr-subtype.rs +++ b/src/test/ui/hr-subtype/hr-subtype.rs @@ -98,9 +98,9 @@ check! { bound_a_b_ret_a_vs_bound_a_ret_a: (for<'a,'b> fn(&'a u32, &'b u32) -> & #[rustc_error] fn main() { -//[bound_a_vs_bound_a]~^ ERROR compilation successful -//[bound_a_vs_bound_b]~^^ ERROR compilation successful -//[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful -//[bound_co_a_vs_bound_co_b]~^^^^ ERROR compilation successful -//[free_x_vs_free_x]~^^^^^ ERROR compilation successful +//[bound_a_vs_bound_a]~^ ERROR fatal error triggered by #[rustc_error] +//[bound_a_vs_bound_b]~^^ ERROR fatal error triggered by #[rustc_error] +//[bound_inv_a_vs_bound_inv_b]~^^^ ERROR fatal error triggered by #[rustc_error] +//[bound_co_a_vs_bound_co_b]~^^^^ ERROR fatal error triggered by #[rustc_error] +//[free_x_vs_free_x]~^^^^^ ERROR fatal error triggered by #[rustc_error] } diff --git a/src/test/ui/proc-macro/no-macro-use-attr.rs b/src/test/ui/proc-macro/no-macro-use-attr.rs index 15ab431fe754a..a8a8fa4e19a4a 100644 --- a/src/test/ui/proc-macro/no-macro-use-attr.rs +++ b/src/test/ui/proc-macro/no-macro-use-attr.rs @@ -7,4 +7,4 @@ extern crate test_macros; //~^ WARN unused extern crate #[rustc_error] -fn main() {} //~ ERROR compilation successful +fn main() {} //~ ERROR fatal error triggered by #[rustc_error] diff --git a/src/test/ui/proc-macro/no-macro-use-attr.stderr b/src/test/ui/proc-macro/no-macro-use-attr.stderr index 87487bcc7d662..50552ea7dbb68 100644 --- a/src/test/ui/proc-macro/no-macro-use-attr.stderr +++ b/src/test/ui/proc-macro/no-macro-use-attr.stderr @@ -10,7 +10,7 @@ note: lint level defined here LL | #![warn(unused_extern_crates)] | ^^^^^^^^^^^^^^^^^^^^ -error: compilation successful +error: fatal error triggered by #[rustc_error] --> $DIR/no-macro-use-attr.rs:10:1 | LL | fn main() {} diff --git a/src/test/ui/rfc1445/feature-gate.rs b/src/test/ui/rfc1445/feature-gate.rs index 550610c5444e9..b97cc1bb6290c 100644 --- a/src/test/ui/rfc1445/feature-gate.rs +++ b/src/test/ui/rfc1445/feature-gate.rs @@ -18,7 +18,7 @@ struct Foo { const FOO: Foo = Foo { x: 0 }; #[rustc_error] -fn main() { //[with_gate]~ ERROR compilation successful +fn main() { //[with_gate]~ ERROR fatal error triggered by #[rustc_error] let y = Foo { x: 1 }; match y { FOO => { } diff --git a/src/test/ui/rfc1445/feature-gate.with_gate.stderr b/src/test/ui/rfc1445/feature-gate.with_gate.stderr index ca8dc75c5335f..fabbfd5c70bb9 100644 --- a/src/test/ui/rfc1445/feature-gate.with_gate.stderr +++ b/src/test/ui/rfc1445/feature-gate.with_gate.stderr @@ -1,4 +1,4 @@ -error: compilation successful +error: fatal error triggered by #[rustc_error] --> $DIR/feature-gate.rs:21:1 | LL | / fn main() { diff --git a/src/test/ui/rustc-error.rs b/src/test/ui/rustc-error.rs index 0504198032cc3..69d57948fb5e7 100644 --- a/src/test/ui/rustc-error.rs +++ b/src/test/ui/rustc-error.rs @@ -2,5 +2,5 @@ #[rustc_error] fn main() { - //~^ ERROR compilation successful + //~^ ERROR fatal error triggered by #[rustc_error] } diff --git a/src/test/ui/rustc-error.stderr b/src/test/ui/rustc-error.stderr index dcbc0e1feb213..7dfc444929594 100644 --- a/src/test/ui/rustc-error.stderr +++ b/src/test/ui/rustc-error.stderr @@ -1,4 +1,4 @@ -error: compilation successful +error: fatal error triggered by #[rustc_error] --> $DIR/rustc-error.rs:4:1 | LL | / fn main() { diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index df56448dd225d..0212ff45eecb2 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -376,6 +376,8 @@ pub struct TestProps { // If true, `rustfix` will only apply `MachineApplicable` suggestions. pub rustfix_only_machine_applicable: bool, pub assembly_output: Option, + // If true, the test is expected to ICE + pub should_ice: bool, } impl TestProps { @@ -414,6 +416,7 @@ impl TestProps { run_rustfix: false, rustfix_only_machine_applicable: false, assembly_output: None, + should_ice: false, } } @@ -464,6 +467,10 @@ impl TestProps { 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); } @@ -578,6 +585,9 @@ impl TestProps { _ => 1, }; } + if self.should_ice { + self.failure_status = 101; + } for key in &["RUST_TEST_NOCAPTURE", "RUST_TEST_THREADS"] { if let Ok(val) = env::var(key) { @@ -688,6 +698,9 @@ fn iter_header(testfile: &Path, cfg: Option<&str>, it: &mut dyn FnMut(&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") } diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index ea31f37c7a52b..1782074fc9234 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -298,6 +298,12 @@ impl<'test> TestCx<'test> { /// Code executed for each revision in turn (or, if there are no /// revisions, exactly once, with revision == None). fn run_revision(&self) { + if self.props.should_ice { + if self.config.mode != CompileFail && + self.config.mode != Incremental { + self.fatal("cannot use should-ice in a test that is not cfail"); + } + } match self.config.mode { CompileFail => self.run_cfail_test(), RunFail => self.run_rfail_test(), @@ -383,7 +389,7 @@ impl<'test> TestCx<'test> { fn run_cfail_test(&self) { let proc_res = self.compile_test(); self.check_if_test_should_compile(&proc_res); - self.check_no_compiler_crash(&proc_res); + self.check_no_compiler_crash(&proc_res, self.props.should_ice); let output_to_check = self.get_output(&proc_res); let expected_errors = errors::load_errors(&self.testpaths.file, self.revision); @@ -395,6 +401,12 @@ impl<'test> TestCx<'test> { } else { self.check_error_patterns(&output_to_check, &proc_res); } + if self.props.should_ice { + match proc_res.status.code() { + Some(101) => (), + _ => self.fatal("expected ICE"), + } + } self.check_forbid_output(&output_to_check, &proc_res); } @@ -1402,9 +1414,11 @@ impl<'test> TestCx<'test> { } } - fn check_no_compiler_crash(&self, proc_res: &ProcRes) { + fn check_no_compiler_crash(&self, proc_res: &ProcRes, should_ice: bool) { match proc_res.status.code() { - Some(101) => self.fatal_proc_rec("compiler encountered internal error", proc_res), + Some(101) if !should_ice => { + self.fatal_proc_rec("compiler encountered internal error", proc_res) + } None => self.fatal_proc_rec("compiler terminated by signal", proc_res), _ => (), } @@ -2518,7 +2532,7 @@ impl<'test> TestCx<'test> { self.fatal_proc_rec("compilation failed!", &proc_res); } - self.check_no_compiler_crash(&proc_res); + self.check_no_compiler_crash(&proc_res, self.props.should_ice); const PREFIX: &'static str = "MONO_ITEM "; const CGU_MARKER: &'static str = "@@"; @@ -2774,8 +2788,14 @@ impl<'test> TestCx<'test> { } if revision.starts_with("rpass") { + if revision_cx.props.should_ice { + revision_cx.fatal("can only use should-ice in cfail tests"); + } revision_cx.run_rpass_test(); } else if revision.starts_with("rfail") { + if revision_cx.props.should_ice { + revision_cx.fatal("can only use should-ice in cfail tests"); + } revision_cx.run_rfail_test(); } else if revision.starts_with("cfail") { revision_cx.run_cfail_test();