Remove rfail support from incremental tests

Incremental revisions beginning with `rfail` would cause the incremental test
runner to build the test program, expecting success, and then run the test
program, expecting failure.

Expecting incremental tests to fail at runtime is of questionable utility,
because in almost all cases an equivalent test program can be made to succeed
at runtime instead.

Removing `rfail` support is a small step towards cleaning up compiletest's
incremental test runner, and its overall handling of pass/fail expectations.

There was one existing regression test using `rfail` revisions:
`tests/incremental/issue-80691-bad-eval-cache.rs`. The test code is complex,
and reverting the fix in RUST-83220 does not actually cause the test to fail,
suggesting that it is no longer a useful regression test. This commit therefore
deletes that test.
This commit is contained in:
Zalathar
2026-04-03 20:37:45 +11:00
parent 2972b5e59f
commit a5181d2fd6
4 changed files with 7 additions and 222 deletions
@@ -158,9 +158,9 @@ then runs the compiler for each revision, reusing the incremental results from p
The revisions should start with:
* `rpass` — the test should compile and run successfully
* `rfail` — the test should compile successfully, but the executable should fail to run
* `cfail` — the test should fail to compile
* `cpass` — the test should compile successully
* `rpass` — the test should compile and run successfully
To make the revisions unique, you should add a suffix like `rpass1` and `rpass2`.
+2 -5
View File
@@ -333,15 +333,12 @@ fn should_compile_successfully(&self, pm: Option<PassMode>) -> bool {
TestMode::Incremental => {
let revision =
self.revision.expect("incremental tests require a list of revisions");
if revision.starts_with("cpass")
|| revision.starts_with("rpass")
|| revision.starts_with("rfail")
{
if revision.starts_with("cpass") || revision.starts_with("rpass") {
true
} else if revision.starts_with("cfail") {
pm.is_some()
} else {
panic!("revision name must begin with cpass, rpass, rfail, or cfail");
panic!("revision name must begin with `cfail`, `cpass`, or `rpass`");
}
}
mode => panic!("unimplemented for mode {:?}", mode),
@@ -5,17 +5,16 @@ impl TestCx<'_> {
pub(super) fn run_incremental_test(&self) {
// Basic plan for a test incremental/foo/bar.rs:
// - load list of revisions rpass1, cfail2, rpass3
// - each should begin with `cpass`, `rpass`, `cfail`, or `rfail`
// - each should begin with `cfail`, `cpass`, or `rpass`
// - if `cpass`, expect compilation to succeed, don't execute
// - if `rpass`, expect compilation and execution to succeed
// - if `cfail`, expect compilation to fail
// - if `rfail`, expect compilation to succeed and execution to fail
// - create a directory build/foo/bar.incremental
// - compile foo/bar.rs with -C incremental=.../foo/bar.incremental and -C rpass1
// - because name of revision starts with "rpass", expect success
// - compile foo/bar.rs with -C incremental=.../foo/bar.incremental and -C cfail2
// - because name of revision starts with "cfail", expect an error
// - load expected errors as usual, but filter for those that end in `[rfail2]`
// - load expected errors as usual, but filter for those with `[cfail2]`
// - compile foo/bar.rs with -C incremental=.../foo/bar.incremental and -C rpass3
// - because name of revision starts with "rpass", expect success
// - execute build/foo/bar.exe and save output
@@ -43,15 +42,10 @@ pub(super) fn run_incremental_test(&self) {
self.fatal("can only use should-ice in cfail tests");
}
self.run_rpass_test();
} else if revision.starts_with("rfail") {
if self.props.should_ice {
self.fatal("can only use should-ice in cfail tests");
}
self.run_rfail_test();
} else if revision.starts_with("cfail") {
self.run_cfail_test();
} else {
self.fatal("revision name must begin with cpass, rpass, rfail, or cfail");
self.fatal("revision name must begin with `cfail`, `cpass`, or `rpass`");
}
}
@@ -111,24 +105,4 @@ fn run_cfail_test(&self) {
self.check_forbid_output(&output_to_check, &proc_res);
}
fn run_rfail_test(&self) {
let pm = self.pass_mode();
let should_run = self.run_if_enabled();
let proc_res = self.compile_test(should_run, self.should_emit_metadata(pm));
if !proc_res.status.success() {
self.fatal_proc_rec("compilation failed!", &proc_res);
}
if let WillExecute::Disabled = should_run {
return;
}
let proc_res = self.exec_compiled_test();
let output_to_check = self.get_output(&proc_res);
self.check_correct_failure_status(&proc_res);
self.check_all_error_patterns(&output_to_check, &proc_res);
}
}
@@ -1,186 +0,0 @@
//@ revisions: rfail1 rfail2
//@ failure-status: 101
//@ error-pattern: not implemented
//@ needs-unwind -Cpanic=abort causes abort instead of exit(101)
//@ ignore-backends: gcc
pub trait Interner {
type InternedVariableKinds;
}
trait RustIrDatabase<I: Interner> {
fn associated_ty_data(&self) -> AssociatedTyDatum<I>;
fn impl_datum(&self) -> ImplDatum<I>;
}
trait Fold<I: Interner> {
type Result;
}
impl<T, I: Interner> Fold<I> for Binders<T>
where
T: HasInterner<Interner = I> + Fold<I>,
<T as Fold<I>>::Result: HasInterner<Interner = I>,
I: Interner,
{
type Result = Binders<T::Result>;
}
impl<I: Interner> Fold<I> for WhereClause<I> {
type Result = Binders<WhereClause<I>>;
}
trait HasInterner {
type Interner: Interner;
}
impl<T: HasInterner> HasInterner for Vec<T> {
type Interner = T::Interner;
}
impl<T: HasInterner + ?Sized> HasInterner for &T {
type Interner = T::Interner;
}
pub struct VariableKind<I: Interner> {
_marker: std::marker::PhantomData<I>,
}
struct VariableKinds<I: Interner> {
_interned: I::InternedVariableKinds,
}
struct WhereClause<I: Interner> {
_marker: std::marker::PhantomData<I>,
}
impl<I: Interner> HasInterner for WhereClause<I> {
type Interner = I;
}
struct Binders<T> {
_marker: std::marker::PhantomData<T>,
}
impl<T: HasInterner> HasInterner for Binders<T> {
type Interner = T::Interner;
}
impl<T> Binders<&T> {
fn cloned(self) -> Binders<T> {
unimplemented!()
}
}
impl<T: HasInterner> Binders<T> {
fn map_ref<'a, U, OP>(&'a self, _op: OP) -> Binders<U>
where
OP: FnOnce(&'a T) -> U,
U: HasInterner<Interner = T::Interner>,
{
unimplemented!()
}
}
impl<T, I: Interner> Binders<T>
where
T: Fold<I> + HasInterner<Interner = I>,
I: Interner,
{
fn substitute(self) -> T::Result {
unimplemented!()
}
}
impl<V, U> IntoIterator for Binders<V>
where
V: HasInterner + IntoIterator<Item = U>,
U: HasInterner<Interner = V::Interner>,
{
type Item = Binders<U>;
type IntoIter = BindersIntoIterator<V>;
fn into_iter(self) -> Self::IntoIter {
unimplemented!()
}
}
struct BindersIntoIterator<V: HasInterner> {
_binders: VariableKinds<V::Interner>,
}
impl<V> Iterator for BindersIntoIterator<V>
where
V: HasInterner + IntoIterator,
<V as IntoIterator>::Item: HasInterner<Interner = V::Interner>,
{
type Item = Binders<<V as IntoIterator>::Item>;
fn next(&mut self) -> Option<Self::Item> {
unimplemented!()
}
}
struct ImplDatum<I: Interner> {
binders: Binders<ImplDatumBound<I>>,
}
struct ImplDatumBound<I: Interner> {
where_clauses: Vec<Binders<WhereClause<I>>>,
}
impl<I: Interner> HasInterner for ImplDatumBound<I> {
type Interner = I;
}
struct AssociatedTyDatum<I: Interner> {
binders: Binders<AssociatedTyDatumBound<I>>,
}
struct AssociatedTyDatumBound<I: Interner> {
where_clauses: Vec<Binders<WhereClause<I>>>,
}
impl<I: Interner> HasInterner for AssociatedTyDatumBound<I> {
type Interner = I;
}
struct ClauseBuilder<'me, I: Interner> {
db: &'me dyn RustIrDatabase<I>,
}
impl<'me, I: Interner> ClauseBuilder<'me, I> {
fn new() -> Self {
unimplemented!()
}
fn push_clause(&mut self, _conditions: impl Iterator<Item = Binders<Binders<WhereClause<I>>>>) {
unimplemented!()
}
}
pub(crate) struct Forest<I: Interner> {
_marker: std::marker::PhantomData<I>,
}
impl<I: Interner> Forest<I> {
fn iter_answers<'f>(&'f self) {
let builder = &mut ClauseBuilder::<I>::new();
let impl_datum = builder.db.impl_datum();
let impl_where_clauses = impl_datum
.binders
.map_ref(|b| &b.where_clauses)
.into_iter()
.map(|wc| wc.cloned().substitute());
let associated_ty = builder.db.associated_ty_data();
let assoc_ty_where_clauses = associated_ty
.binders
.map_ref(|b| &b.where_clauses)
.into_iter()
.map(|wc| wc.cloned().substitute());
builder.push_clause(impl_where_clauses.chain(assoc_ty_where_clauses));
}
}
pub struct SLGSolver {
pub(crate) forest: Forest<ChalkIr>,
}
impl SLGSolver {
fn new() -> Self {
unimplemented!()
}
fn solve_multiple(&self) {
let _answers = self.forest.iter_answers();
}
}
pub struct ChalkIr;
impl Interner for ChalkIr {
type InternedVariableKinds = Vec<VariableKind<ChalkIr>>;
}
fn main() {
let solver = SLGSolver::new();
solver.solve_multiple();
}