Skip to content

Commit 9c7e7cc

Browse files
committed
Exhaustively specify names and stability of --print values
1 parent c81d22d commit 9c7e7cc

File tree

3 files changed

+129
-63
lines changed

3 files changed

+129
-63
lines changed

compiler/rustc_session/src/config/print_request.rs

Lines changed: 100 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! Code for dealing with `--print` requests.
22
3+
use std::fmt;
34
use std::sync::LazyLock;
45

56
use rustc_data_structures::fx::FxHashSet;
@@ -8,35 +9,7 @@ use crate::EarlyDiagCtxt;
89
use crate::config::{
910
CodegenOptions, OutFileName, UnstableOptions, nightly_options, split_out_file_name,
1011
};
11-
12-
const PRINT_KINDS: &[(&str, PrintKind)] = &[
13-
// tidy-alphabetical-start
14-
("all-target-specs-json", PrintKind::AllTargetSpecsJson),
15-
("calling-conventions", PrintKind::CallingConventions),
16-
("cfg", PrintKind::Cfg),
17-
("check-cfg", PrintKind::CheckCfg),
18-
("code-models", PrintKind::CodeModels),
19-
("crate-name", PrintKind::CrateName),
20-
("crate-root-lint-levels", PrintKind::CrateRootLintLevels),
21-
("deployment-target", PrintKind::DeploymentTarget),
22-
("file-names", PrintKind::FileNames),
23-
("host-tuple", PrintKind::HostTuple),
24-
("link-args", PrintKind::LinkArgs),
25-
("native-static-libs", PrintKind::NativeStaticLibs),
26-
("relocation-models", PrintKind::RelocationModels),
27-
("split-debuginfo", PrintKind::SplitDebuginfo),
28-
("stack-protector-strategies", PrintKind::StackProtectorStrategies),
29-
("supported-crate-types", PrintKind::SupportedCrateTypes),
30-
("sysroot", PrintKind::Sysroot),
31-
("target-cpus", PrintKind::TargetCPUs),
32-
("target-features", PrintKind::TargetFeatures),
33-
("target-libdir", PrintKind::TargetLibdir),
34-
("target-list", PrintKind::TargetList),
35-
("target-spec-json", PrintKind::TargetSpecJson),
36-
("target-spec-json-schema", PrintKind::TargetSpecJsonSchema),
37-
("tls-models", PrintKind::TlsModels),
38-
// tidy-alphabetical-end
39-
];
12+
use crate::macros::AllVariants;
4013

4114
#[derive(Clone, PartialEq, Debug)]
4215
pub struct PrintRequest {
@@ -45,6 +18,7 @@ pub struct PrintRequest {
4518
}
4619

4720
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
21+
#[derive(AllVariants)]
4822
pub enum PrintKind {
4923
// tidy-alphabetical-start
5024
AllTargetSpecsJson,
@@ -74,11 +48,94 @@ pub enum PrintKind {
7448
// tidy-alphabetical-end
7549
}
7650

51+
impl PrintKind {
52+
/// FIXME: rust-analyzer doesn't support `#![feature(macro_derive)]` yet
53+
/// (<https://github.com/rust-lang/rust-analyzer/issues/21043>), which breaks autocomplete.
54+
/// Work around that by aliasing the trait constant to a regular constant.
55+
const ALL_VARIANTS: &[Self] = <Self as AllVariants>::ALL_VARIANTS;
56+
57+
fn name(self) -> &'static str {
58+
use PrintKind::*;
59+
match self {
60+
// tidy-alphabetical-start
61+
AllTargetSpecsJson => "all-target-specs-json",
62+
CallingConventions => "calling-conventions",
63+
Cfg => "cfg",
64+
CheckCfg => "check-cfg",
65+
CodeModels => "code-models",
66+
CrateName => "crate-name",
67+
CrateRootLintLevels => "crate-root-lint-levels",
68+
DeploymentTarget => "deployment-target",
69+
FileNames => "file-names",
70+
HostTuple => "host-tuple",
71+
LinkArgs => "link-args",
72+
NativeStaticLibs => "native-static-libs",
73+
RelocationModels => "relocation-models",
74+
SplitDebuginfo => "split-debuginfo",
75+
StackProtectorStrategies => "stack-protector-strategies",
76+
SupportedCrateTypes => "supported-crate-types",
77+
Sysroot => "sysroot",
78+
TargetCPUs => "target-cpus",
79+
TargetFeatures => "target-features",
80+
TargetLibdir => "target-libdir",
81+
TargetList => "target-list",
82+
TargetSpecJson => "target-spec-json",
83+
TargetSpecJsonSchema => "target-spec-json-schema",
84+
TlsModels => "tls-models",
85+
// tidy-alphabetical-end
86+
}
87+
}
88+
89+
fn is_stable(self) -> bool {
90+
use PrintKind::*;
91+
match self {
92+
// Stable values:
93+
CallingConventions
94+
| Cfg
95+
| CodeModels
96+
| CrateName
97+
| DeploymentTarget
98+
| FileNames
99+
| HostTuple
100+
| LinkArgs
101+
| NativeStaticLibs
102+
| RelocationModels
103+
| SplitDebuginfo
104+
| StackProtectorStrategies
105+
| Sysroot
106+
| TargetCPUs
107+
| TargetFeatures
108+
| TargetLibdir
109+
| TargetList
110+
| TlsModels => true,
111+
112+
// Unstable values:
113+
AllTargetSpecsJson => false,
114+
CheckCfg => false,
115+
CrateRootLintLevels => false,
116+
SupportedCrateTypes => false,
117+
TargetSpecJson => false,
118+
TargetSpecJsonSchema => false,
119+
}
120+
}
121+
122+
fn from_str(s: &str) -> Option<Self> {
123+
Self::ALL_VARIANTS.iter().find(|kind| kind.name() == s).copied()
124+
}
125+
}
126+
127+
impl fmt::Display for PrintKind {
128+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
129+
self.name().fmt(f)
130+
}
131+
}
132+
77133
pub(crate) static PRINT_HELP: LazyLock<String> = LazyLock::new(|| {
134+
let print_kinds =
135+
PrintKind::ALL_VARIANTS.iter().map(|kind| kind.name()).collect::<Vec<_>>().join("|");
78136
format!(
79137
"Compiler information to print on stdout (or to a file)\n\
80-
INFO may be one of <{}>.",
81-
PRINT_KINDS.iter().map(|(name, _)| format!("{name}")).collect::<Vec<_>>().join("|")
138+
INFO may be one of <{print_kinds}>.",
82139
)
83140
});
84141

@@ -107,11 +164,9 @@ pub(crate) fn collect_print_requests(
107164
prints.extend(matches.opt_strs("print").into_iter().map(|req| {
108165
let (req, out) = split_out_file_name(&req);
109166

110-
let kind = if let Some((print_name, print_kind)) =
111-
PRINT_KINDS.iter().find(|&&(name, _)| name == req)
112-
{
113-
check_print_request_stability(early_dcx, unstable_opts, (print_name, *print_kind));
114-
*print_kind
167+
let kind = if let Some(print_kind) = PrintKind::from_str(req) {
168+
check_print_request_stability(early_dcx, unstable_opts, print_kind);
169+
print_kind
115170
} else {
116171
let is_nightly = nightly_options::match_is_nightly_build(matches);
117172
emit_unknown_print_request_help(early_dcx, req, is_nightly)
@@ -136,41 +191,23 @@ pub(crate) fn collect_print_requests(
136191
fn check_print_request_stability(
137192
early_dcx: &EarlyDiagCtxt,
138193
unstable_opts: &UnstableOptions,
139-
(print_name, print_kind): (&str, PrintKind),
194+
print_kind: PrintKind,
140195
) {
141-
if !is_print_request_stable(print_kind) && !unstable_opts.unstable_options {
196+
if !print_kind.is_stable() && !unstable_opts.unstable_options {
142197
early_dcx.early_fatal(format!(
143-
"the `-Z unstable-options` flag must also be passed to enable the `{print_name}` \
144-
print option"
198+
"the `-Z unstable-options` flag must also be passed to enable the `{print_kind}` print option"
145199
));
146200
}
147201
}
148202

149-
fn is_print_request_stable(print_kind: PrintKind) -> bool {
150-
match print_kind {
151-
PrintKind::AllTargetSpecsJson
152-
| PrintKind::CheckCfg
153-
| PrintKind::CrateRootLintLevels
154-
| PrintKind::SupportedCrateTypes
155-
| PrintKind::TargetSpecJson
156-
| PrintKind::TargetSpecJsonSchema => false,
157-
_ => true,
158-
}
159-
}
160-
161203
fn emit_unknown_print_request_help(early_dcx: &EarlyDiagCtxt, req: &str, is_nightly: bool) -> ! {
162-
let prints = PRINT_KINDS
204+
let prints = PrintKind::ALL_VARIANTS
163205
.iter()
164-
.filter_map(|(name, kind)| {
165-
// If we're not on nightly, we don't want to print unstable options
166-
if !is_nightly && !is_print_request_stable(*kind) {
167-
None
168-
} else {
169-
Some(format!("`{name}`"))
170-
}
171-
})
172-
.collect::<Vec<_>>();
173-
let prints = prints.join(", ");
206+
// If we're not on nightly, we don't want to print unstable options
207+
.filter(|kind| is_nightly || kind.is_stable())
208+
.map(|kind| format!("`{kind}`"))
209+
.collect::<Vec<_>>()
210+
.join(", ");
174211

175212
let mut diag = early_dcx.early_struct_fatal(format!("unknown print request: `{req}`"));
176213
#[allow(rustc::diagnostic_outside_of_impl)]

compiler/rustc_session/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#![allow(internal_features)]
33
#![feature(default_field_values)]
44
#![feature(iter_intersperse)]
5+
#![feature(macro_derive)]
56
#![feature(rustc_attrs)]
67
// To generate CodegenOptionsTargetModifiers and UnstableOptionsTargetModifiers enums
78
// with macro_rules, it is necessary to use recursive mechanic ("Incremental TT Munchers").
@@ -20,6 +21,7 @@ pub mod code_stats;
2021
pub mod config;
2122
pub mod cstore;
2223
pub mod filesearch;
24+
mod macros;
2325
mod options;
2426
pub mod search_paths;
2527

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/// Derivable trait for enums with no fields (i.e. C-style enums) that want to
2+
/// allow iteration over a list of all variant values.
3+
pub(crate) trait AllVariants: Copy + 'static {
4+
const ALL_VARIANTS: &[Self];
5+
}
6+
7+
macro_rules! AllVariantsDerive {
8+
derive() (
9+
$(#[$meta:meta])*
10+
$vis:vis enum $Type:ident {
11+
$(
12+
$(#[$varmeta:meta])*
13+
$Variant:ident $( = $value:literal )?
14+
), *$(,)?
15+
}
16+
) => {
17+
impl $crate::macros::AllVariants for $Type {
18+
const ALL_VARIANTS: &[$Type] = &[
19+
$( $Type::$Variant, )*
20+
];
21+
}
22+
};
23+
}
24+
25+
// For some reason the compiler won't allow `pub(crate) use AllVariants` due
26+
// to a conflict with the trait of the same name, but will allow this form.
27+
pub(crate) use AllVariantsDerive as AllVariants;

0 commit comments

Comments
 (0)