Skip to content

Add new RUSTC_BOOTSTRAP=-2 mode for testing stable compiler behavior in UI tests - #163664

Open
Kobzol wants to merge 5 commits into
rust-lang:mainfrom
Kobzol:bootstrap-but-this-time-for-real-2
Open

Kobzol wants to merge 5 commits into
rust-lang:mainfrom
Kobzol:bootstrap-but-this-time-for-real-2

Conversation

@Kobzol

@Kobzol Kobzol commented Oct 2, 2026 •

Copy link
Copy Markdown
Member

Right now, it is not possible to test how the compiler behaves on the stable toolchain in UI tests. Even though #132993 added a mechanism to emulate stable rustc on the nightly channel, using the RUSTC_BOOTSTRAP=-1 environment variable, this mechanism is not currently usable within compiletest and UI tests directly, because compiletest unconditionally passes several unstable -Z flags that are load-bearing for the testing infra itself to work (notably -Zui-testing and friends).

That is quite annoying, because we do in fact want to test stable behavior in a couple of tests, but today we have to write those as run-make tests (latest example: https://rust-lang.zulipchat.com/#narrow/channel/131828-t-compiler/topic/Testing.20stable.20vs.20nightly.20behavior.20in.20UI.20tests/with/628206707), even if the tested situation is very simple. Those are harder to read, write and maintain than UI tests and they do not support blessing outputs as well as UI tests. Recently, I at least added #163444 as a way of centralizing the logic of testing a stable rustc in a run-make test, but that does not really help with the fact that we still have to use run-make tests for it, even when a normal UI test would do.

For #162848, I would also like to have a way of passing -Zthreads=1 to all run-make tests, even if they are testing stable rustc, but that's not easily possible, because those tests are using RUSTC_BOOTSTRAP=-1.

This PR proposes to add a new mode to RUSTC_BOOTSTRAP, with the value of -21. This can be used to emulate the behavior of stable rustc, while still allowing passing unstable -Z flags (and -Zunstable-options) to the compiler.

The stability check in the compiler is thus now separated into two questions:

  • Are we an unstable/nightly build?
  • Can we accept unstable compiler flags?

The latter is checked only at a few places, so the necessary change to the compiler is rather small (IMO).

To demonstrate how this would be used, I also implemented a new directive into compiletest in this PR, act-as-stable. That can be used in a UI test to emulate stable rustc. Some tests before used only-stable to "achieve" this, which is very misleading, because it doesn't work at all 😆, due to compiletest unconditionally passing RUSTC_BOOTSTRAP=1 to all executed tests. act-as-stable fixes that.

The last two commits demonstrate how we could replace run-make tests that tested different output on stable/nightly with UI tests.

I suppose that this mode might be interesting for other people outside of rust-lang/rust, but if you don't want that, I can gate it behind -Zui-testing.

r? jieyouxu

Footnotes

  1. Note that RUSTC_BOOTSTRAP=<crate-identifier> is a thing, so we cannot that easily name the values for this flag with strings that from valid Rust identifiers. Which is why I just chose -2. ↩

@rustbot

rustbot commented Oct 2, 2026

Copy link
Copy Markdown
Collaborator

compiletest directives have been modified. Please add or update docs for the
new or modified directive in src/doc/rustc-dev-guide/.

The rustc-dev-guide subtree was changed. If your future PRs only touch the subtree, consider submitting them directly to rust-lang/rustc-dev-guide, which is where the document is primarily maintained (and has faster CI).

cc @BoxyUwU, @tshepang

Some changes occurred in src/tools/compiletest

cc @jieyouxu

@rustbot rustbot added A-compiletest Area: The compiletest test runner A-run-make Area: port run-make Makefiles to rmake.rs A-rustc-dev-guide Area: rustc-dev-guide A-testsuite Area: The testsuite used to check the correctness of rustc S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Oct 2, 2026
@rust-log-analyzer

This comment has been minimized.

@bjorn3

bjorn3 commented Oct 2, 2026

Copy link
Copy Markdown
Member

You can probably remove

rm -r tests/run-make/missing-unstable-trait-bound # This disables support for unstable features, but running cg_clif needs some unstable features
rm -r tests/run-make/const-trait-stable-toolchain # same
rm -r tests/run-make/print-request-help-stable-unstable # same
rm -r tests/run-make/issue-149402-suggest-unresolve # same
rm -r tests/run-make/const-destruct-stable-toolchain # same
rm -r tests/run-make/unstable-target-feature # same

@rust-log-analyzer

This comment has been minimized.

@rust-bors

This comment has been minimized.

@Kobzol
Kobzol force-pushed the bootstrap-but-this-time-for-real-2 branch from 9565273 to a36b6f8 Compare October 4, 2026 11:59
@rustbot

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@Kobzol
Kobzol force-pushed the bootstrap-but-this-time-for-real-2 branch from a36b6f8 to 8e072e8 Compare October 4, 2026 17:58
@rust-bors

This comment has been minimized.

@Kobzol
Kobzol force-pushed the bootstrap-but-this-time-for-real-2 branch from 8e072e8 to 0c3b3be Compare October 12, 2026 06:54
@rustbot

rustbot commented Oct 12, 2026

Copy link
Copy Markdown
Collaborator

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@petrochenkov petrochenkov self-assigned this Oct 12, 2026

@jieyouxu jieyouxu left a comment •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

General idea makes sense to me. Some discussions

View changes since this review

/// Specifically, we need it when we want to test how rustc behaves on the stable channel,
/// but at the same time we need to be able to pass it some unstable `-Z` compiler flags
/// required for the testing infrastructure itself to work.
ActAsStableForTesting,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like this name isn't very intuitive -- if we can use unstable compiler flags then we are not acting as stable. I would directly call this AllowUnstableCompilerFlagsOnly as opposed to ActAsStableForTesting. WDYT?

In the sense that, we actually have three aspects:

  1. Release channel: stable/beta vs nightly
  2. Can unstable language features be used
  3. Can unstable compiler flags be used

Ditto on the comment below

Comment on lines +38 to +43
// `RUSTC_BOOTSTRAP=-2` simulates the stable toolchain, while allowing unstable compiler flags
// to be passed.
std::assert_matches!(
UnstableFeatures::from_environment_value(None, Ok("-2".to_string())),
UnstableFeatures::ActAsStableForTesting
);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder, technically I think we can call this -allow-unstable-compiler-flags right, doesn't have to be 2? Because sure --crate-name accepts a wide range of identifiers but -<whatever> is not a valid crate name.

Comment on lines +27 to +28
To test stable-only behavior, use the `act-as-stable` directive, which will set `RUSTC_BOOTSTRAP=-2`
for you.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should also mention allow using unstable compiler flags but not unstable features

/// a best-effort approximation for diagnostics. Add new directives to this list when needed.
pub(crate) const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
// tidy-alphabetical-start
"act-as-stable",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I don't love the name, because it's actually more like //@ well-actually-we-allow-unstable-compiler-flags-but-not-language-features. But obviously that's a despairingly long name...

There's candidates like

  • //@ pretend-stable (which is really the same meaning as act-as-stable)
  • //@ stable-features-only, but that loses the "pretend" intent

Maybe //@ act-as-stable is fine.

};

if !edition.is_stable() && !nightly_options::is_unstable_enabled(matches) {
if !edition.is_stable() && !nightly_options::unstable_options_enabled(matches) {

@jieyouxu jieyouxu Oct 12, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: grepping shows that there's still a reference to unstable_options_enabled around 516

View changes since the review

Comment on lines +67 to +72
handler(ACT_AS_STABLE, |_config, ln, props| {
if ln.name == ACT_AS_STABLE {
// Simulate the stable toolchain, but allow unstable -Z flags passed by compiletest
props.rustc_env.push(("RUSTC_BOOTSTRAP".to_string(), "-2".to_string()));
}
}),

@jieyouxu jieyouxu Oct 12, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we reject using this outside of ui mode as well?

(NB: I know we need to improve how we handle which directives are rejected/accepted under which conditions, but not in this PR.)

View changes since the review

let print_help = || {
// Only show unstable options in --help if we accept unstable options.
let unstable_enabled = nightly_options::is_unstable_enabled(&matches);
let unstable_enabled = nightly_options::unstable_options_enabled(&matches);

@petrochenkov petrochenkov Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is actually changing the help output, I wouldn't expect the "act-as-stable" mode to do that.

FWIW, I like the "less principled escape hatch" alternative better.
Accepting all unstable flags deviates too much from acting as stable, and we don't actually need all unstable flags for UI testing, only like 2-3 of them.

View changes since the review

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, if we are able to limit it to only for-testing ones, that seems generally better.

@petrochenkov petrochenkov removed their assignment Oct 13, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-compiletest Area: The compiletest test runner A-run-make Area: port run-make Makefiles to rmake.rs A-rustc-dev-guide Area: rustc-dev-guide A-testsuite Area: The testsuite used to check the correctness of rustc S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants