Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_driver_impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1303,7 +1303,7 @@ pub fn handle_help(matches: &getopts::Matches, args: &[String]) -> bool {
let chelp_pos = opt_help_pos("C");
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);
let nightly_build = nightly_options::match_is_nightly_build(&matches);
usage(matches.opt_present("verbose"), unstable_enabled, nightly_build);
};
Expand Down
36 changes: 33 additions & 3 deletions compiler/rustc_feature/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,34 @@ pub struct Feature {

#[derive(Clone, Copy, Debug, Hash)]
pub enum UnstableFeatures {
/// Disallow use of unstable features, as on beta/stable channels.
/// Disallow use of unstable features and unstable compiler flags.
///
/// Used by default by beta/stable channels.
Disallow,
/// Allow use of unstable features, as on nightly.
/// Allow use of unstable features and unstable compiler flags.
///
/// Used by default by the nightly channel.
Allow,
/// Allow use of unstable features and unstable compiler flags, even if it is not the default
/// behavior.
///
/// Can be used to make a beta/stable channel act like a nightly channel.
///
/// Errors are bypassed for bootstrapping. This is required any time
/// during the build that feature-related lints are set to warn or above
/// because the build turns on warnings-as-errors and uses lots of unstable
/// features. As a result, this is always required for building Rust itself.
Cheat,
/// Allow the use of *unstable compiler flags*, but disallow the use of
/// *unstable language features*.
/// And in general, try to treat everything except for compiler flags as if we were on stable.
///
/// **This mode is designed only for internal testing of rustc.**
///
/// 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,
}

impl UnstableFeatures {
Expand Down Expand Up @@ -76,17 +95,28 @@ impl UnstableFeatures {
// Hypnotize ourselves so that we think we are a stable compiler and thus don't
// allow any unstable features.
"-1" => return UnstableFeatures::Disallow,
// Act as stable, but still accept unstable compiler flags required by compiletest
"-2" => return UnstableFeatures::ActAsStableForTesting,
_ => {}
}
}

if disable_unstable_features { UnstableFeatures::Disallow } else { UnstableFeatures::Allow }
}

pub fn allow_unstable_compiler_flags(&self) -> bool {
match *self {
UnstableFeatures::Allow
| UnstableFeatures::Cheat
| UnstableFeatures::ActAsStableForTesting => true,
UnstableFeatures::Disallow => false,
}
}

pub fn is_nightly_build(&self) -> bool {
match *self {
UnstableFeatures::Allow | UnstableFeatures::Cheat => true,
UnstableFeatures::Disallow => false,
UnstableFeatures::Disallow | UnstableFeatures::ActAsStableForTesting => false,
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_feature/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,11 @@ fn rustc_bootstrap_parsing() {
// Does not support specifying any crate.
assert!(is_force_stable(Some("x")));
assert!(is_force_stable(Some("x,y,z")));

// `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
);
}
30 changes: 17 additions & 13 deletions compiler/rustc_session/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2395,7 +2395,7 @@ pub fn parse_crate_edition(
}
};

if !edition.is_stable() && !nightly_options::is_unstable_enabled(matches) {
if !edition.is_stable() && !nightly_options::unstable_options_enabled(matches) {
let msg = if !is_nightly {
format!(
"the crate requires edition {edition}, but the latest edition supported by this \
Expand All @@ -2413,10 +2413,10 @@ pub fn parse_crate_edition(
fn check_error_format_stability(
early_dcx: &EarlyDiagCtxt,
unstable_opts: &UnstableOptions,
is_nightly_build: bool,
unstable_flags_enabled: bool,
format: ErrorOutputType,
) {
if unstable_opts.unstable_options || is_nightly_build {
if unstable_opts.unstable_options || unstable_flags_enabled {
return;
}
let format = match format {
Expand Down Expand Up @@ -2771,7 +2771,7 @@ pub fn build_session_options(
check_error_format_stability(
early_dcx,
&unstable_opts,
unstable_features.is_nightly_build(),
unstable_features.allow_unstable_compiler_flags(),
error_format,
);

Expand Down Expand Up @@ -2867,15 +2867,15 @@ pub fn build_session_options(
}
}

let unstable_options_enabled = nightly_options::is_unstable_enabled(matches);
let unstable_options_enabled = nightly_options::unstable_options_enabled(matches);
if !unstable_options_enabled && cg.force_frame_pointers == FramePointer::NonLeaf {
early_dcx.early_fatal(
"`-Cforce-frame-pointers=non-leaf` or `always` also requires `-Zunstable-options` \
and a nightly compiler",
)
}

if !nightly_options::is_unstable_enabled(matches) && !unstable_opts.offload.is_empty() {
if !unstable_options_enabled && !unstable_opts.offload.is_empty() {
early_dcx.early_fatal(
"`-Zoffload=Enable` also requires `-Zunstable-options` and a nightly compiler",
)
Expand Down Expand Up @@ -3178,17 +3178,21 @@ pub mod nightly_options {
use super::{OptionStability, RustcOptGroup};
use crate::EarlyDiagCtxt;

pub fn is_unstable_enabled(matches: &getopts::Matches) -> bool {
match_is_nightly_build(matches)
/// Are we allowed to use -Z compiler flags *and* -Zunstable-options was passed?
pub fn unstable_options_enabled(matches: &getopts::Matches) -> bool {
unstable_compiler_flags_allowed(matches)
&& matches.opt_strs("Z").iter().any(|x| *x == "unstable-options")
}

pub fn match_is_nightly_build(matches: &getopts::Matches) -> bool {
is_nightly_build(matches.opt_str("crate-name").as_deref())
/// Are we allowed to use -Z compiler flags?
pub fn unstable_compiler_flags_allowed(matches: &getopts::Matches) -> bool {
UnstableFeatures::from_environment(matches.opt_str("crate-name").as_deref())
.allow_unstable_compiler_flags()
}

fn is_nightly_build(krate: Option<&str>) -> bool {
UnstableFeatures::from_environment(krate).is_nightly_build()
pub fn match_is_nightly_build(matches: &getopts::Matches) -> bool {
let krate = matches.opt_str("crate-name");
UnstableFeatures::from_environment(krate.as_deref()).is_nightly_build()
}

pub fn check_nightly_options(
Expand All @@ -3197,7 +3201,7 @@ pub mod nightly_options {
flags: &[RustcOptGroup],
) {
let has_z_unstable_option = matches.opt_strs("Z").iter().any(|x| *x == "unstable-options");
let really_allows_unstable_options = match_is_nightly_build(matches);
let really_allows_unstable_options = unstable_compiler_flags_allowed(matches);
let mut nightly_options_on_stable = 0;

for opt in flags.iter() {
Expand Down
37 changes: 19 additions & 18 deletions src/doc/rustc-dev-guide/src/tests/misc.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,24 @@ This is a bootstrap/compiler implementation detail, but it can also be useful fo
compiler, even if it's actually a nightly `rustc`.
This is useful because some behaviors of the compiler (e.g. diagnostics)
can differ depending on whether the compiler is nightly or not.
- `RUSTC_BOOTSTRAP=-2` will force a given `rustc` to pretend it is a stable
compiler, even if it's actually a nightly `rustc`.
However, the compiler will still accept unstable compiler flags.
This is useful for internal testing of the compiler, where we need to pass
unstable flags required by compiletest, but we also want to test the compiler's
behavior on the stable channel.

### UI tests

Note that setting `RUSTC_BOOTSTRAP` in ui tests (e.g. via `//@ rustc-env`) is pointless since ui
Note that setting `RUSTC_BOOTSTRAP=-1` in ui tests (e.g. via `//@ rustc-env`) is pointless since ui
tests inherit the bootstrap env var from bootstrap (so it's set to `1` by default), and since
compiletest itself passes `-Z` flags (so `-1` breaks the test). To test stable-only behavior, you
need to write a `run-make` test instead.

For `run-make`/`run-make-cargo` tests, `//@ rustc-env` is not supported.
You can do something like the following for individual `rustc` invocations.

```rust,ignore
use run_make_support::rustc;

fn main() {
rustc()
// Pretend that I am very stable
.env("RUSTC_BOOTSTRAP", "-1")
//...
.run();
}
```
compiletest itself passes `-Z` flags (so `-1` breaks the test).

To test stable-only behavior, use the `act-as-stable` directive, which will set `RUSTC_BOOTSTRAP=-2`
for you.

### Run-make tests

For `run-make`/`run-make-cargo` tests, `//@ act-as-stable` is not supported.
You can use the `run_make_support::stable_bare_rustc` function to create an instance of the compiler
that acts as the stable channel (this internally uses `RUSTC_BOOTSTRAP=-1`).
2 changes: 1 addition & 1 deletion src/librustdoc/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,7 @@ impl Options {
match (
output_format_s.as_ref().map(|_| output_format),
show_coverage,
nightly_options::is_unstable_enabled(matches),
nightly_options::unstable_options_enabled(matches),
) {
(None | Some(OutputFormat::CoverageJson), true, _) => {}
(_, true, _) => {
Expand Down
1 change: 1 addition & 0 deletions src/tools/compiletest/src/directives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ pub(crate) struct TestProps {
}

mod directives {
pub(crate) const ACT_AS_STABLE: &str = "act-as-stable";
pub(crate) const ERROR_PATTERN: &str = "error-pattern";
pub(crate) const REGEX_ERROR_PATTERN: &str = "regex-error-pattern";
pub(crate) const COMPILE_FLAGS: &str = "compile-flags";
Expand Down
1 change: 1 addition & 0 deletions src/tools/compiletest/src/directives/directive_names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub(crate) static KNOWN_DIRECTIVE_NAMES_SET: LazyLock<HashSet<&str>> =
/// 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",
"add-minicore",
"assembly-output",
"aux-bin",
Expand Down
6 changes: 6 additions & 0 deletions src/tools/compiletest/src/directives/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ fn make_directive_handlers_map() -> HashMap<&'static str, Handler> {
// these handlers, e.g. by getting rid of now-redundant name checks.

let handlers: Vec<NamedHandler> = vec![
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()));
}
}),
handler(ERROR_PATTERN, |config, ln, props| {
config.push_name_value_directive(ln, ERROR_PATTERN, &mut props.error_patterns, |r| r);
}),
Expand Down

This file was deleted.

3 changes: 0 additions & 3 deletions tests/run-make/const-destruct-stable-toolchain/const-drop.rs

This file was deleted.

28 changes: 0 additions & 28 deletions tests/run-make/const-destruct-stable-toolchain/rmake.rs

This file was deleted.

This file was deleted.

33 changes: 0 additions & 33 deletions tests/run-make/print-request-help-stable-unstable/rmake.rs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error[E0554]: `#![feature]` may not be used on the nightly release channel
--> $DIR/rustc_bootstrap.rs:51:1
|
LL | #![feature(rustc_attrs)]
| ^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0554`.
10 changes: 8 additions & 2 deletions tests/ui/bootstrap/rustc_bootstrap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@
//! - `1`: cheat, allow usage of unstable features even if rustc thinks it is a stable compiler.
//! - `x,y,z`: comma-delimited list of crates.
//! - `-1`: force rustc to think it is a stable compiler.
//! - `-2`: force rustc to think it is a stable compiler, while still allowing -Z flags.

// ignore-tidy-linelength

//@ revisions: default_nightly cheat cheat_single_crate cheat_multi_crate force_stable invalid_zero invalid_junk
//@ revisions: default_nightly cheat cheat_single_crate cheat_multi_crate force_stable force_stable_allow_flags invalid_zero invalid_junk
//@ only-nightly
//@ normalize-stderr: "dev release channel" -> "nightly release channel"

//@[default_nightly] unset-rustc-env:RUSTC_BOOTSTRAP
//@[default_nightly] check-pass
Expand Down Expand Up @@ -39,10 +41,14 @@
//@[force_stable] rustc-env:RUSTC_BOOTSTRAP=-1
//@[force_stable] compile-flags: -Z unstable-options

#![crate_type = "lib"]
// Here rustc shouldn't complain about compiletest's -Z flags being passed.
//@[force_stable_allow_flags] rustc-env:RUSTC_BOOTSTRAP=-2
//@[force_stable_allow_flags] compile-flags: -Z unstable-options

#![crate_type = "lib"]
// Note: `rustc_attrs` is a perma-unstable internal feature that is unlikely to change, which is
// used as a proxy to check `RUSTC_BOOTSTRAP` versus stability checking logic.
#![feature(rustc_attrs)]
//[force_stable_allow_flags]~^ ERROR: `#![feature]` may not be used on the

//[force_stable]~? RAW the option `Z` is only accepted on the nightly compiler
12 changes: 12 additions & 0 deletions tests/ui/compile-flags/print-request-help-stable-unstable.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//! Check that unstable print requests are omitted from help if compiler is in stable channel.
//!
//! Issue: <https://github.com/rust-lang/rust/issues/138698>

//@ ignore-backends: gcc
//@ compile-flags: --print xxx
//
//@ revisions: stable nightly
//@[stable] act-as-stable
//@[nightly] only-nightly

//~? ERROR unknown print request: `xxx`
Loading
Loading