1use std::fmt;
4use std::sync::LazyLock;
5
6use rustc_data_structures::fx::FxHashSet;
7
8use crate::EarlyDiagCtxt;
9use crate::config::{
10 CodegenOptions, OutFileName, UnstableOptions, nightly_options, split_out_file_name,
11};
12use crate::macros::AllVariants;
13
14#[derive(#[automatically_derived]
impl ::core::clone::Clone for PrintRequest {
#[inline]
fn clone(&self) -> PrintRequest {
PrintRequest {
kind: ::core::clone::Clone::clone(&self.kind),
out: ::core::clone::Clone::clone(&self.out),
arg: ::core::clone::Clone::clone(&self.arg),
}
}
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for PrintRequest {
#[inline]
fn eq(&self, other: &PrintRequest) -> bool {
self.kind == other.kind && self.out == other.out &&
self.arg == other.arg
}
}PartialEq, #[automatically_derived]
impl ::core::fmt::Debug for PrintRequest {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f, "PrintRequest",
"kind", &self.kind, "out", &self.out, "arg", &&self.arg)
}
}Debug)]
15pub struct PrintRequest {
16 pub kind: PrintKind,
17 pub out: OutFileName,
18 pub arg: Option<String>,
19}
20
21#[derive(#[automatically_derived]
impl ::core::marker::Copy for PrintKind { }Copy, #[automatically_derived]
impl ::core::clone::Clone for PrintKind {
#[inline]
fn clone(&self) -> PrintKind { *self }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for PrintKind {
#[inline]
fn eq(&self, other: &PrintKind) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for PrintKind {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::fmt::Debug for PrintKind {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
PrintKind::AllTargetSpecsJson => "AllTargetSpecsJson",
PrintKind::BackendHasMnemonic => "BackendHasMnemonic",
PrintKind::BackendHasZstd => "BackendHasZstd",
PrintKind::CallingConventions => "CallingConventions",
PrintKind::Cfg => "Cfg",
PrintKind::CheckCfg => "CheckCfg",
PrintKind::CodeModels => "CodeModels",
PrintKind::CrateName => "CrateName",
PrintKind::CrateRootLintLevels => "CrateRootLintLevels",
PrintKind::DeploymentTarget => "DeploymentTarget",
PrintKind::FileNames => "FileNames",
PrintKind::HostTuple => "HostTuple",
PrintKind::LinkArgs => "LinkArgs",
PrintKind::NativeStaticLibs => "NativeStaticLibs",
PrintKind::RelocationModels => "RelocationModels",
PrintKind::SplitDebuginfo => "SplitDebuginfo",
PrintKind::StackProtectorStrategies =>
"StackProtectorStrategies",
PrintKind::SupportedCrateTypes => "SupportedCrateTypes",
PrintKind::Sysroot => "Sysroot",
PrintKind::TargetCPUs => "TargetCPUs",
PrintKind::TargetFeatures => "TargetFeatures",
PrintKind::TargetLibdir => "TargetLibdir",
PrintKind::TargetList => "TargetList",
PrintKind::TargetSpecJson => "TargetSpecJson",
PrintKind::TargetSpecJsonSchema => "TargetSpecJsonSchema",
PrintKind::TlsModels => "TlsModels",
})
}
}Debug)]
22#[derive(impl crate::macros::AllVariants for PrintKind {
const ALL_VARIANTS: &[PrintKind] =
&[PrintKind::AllTargetSpecsJson, PrintKind::BackendHasMnemonic,
PrintKind::BackendHasZstd, PrintKind::CallingConventions,
PrintKind::Cfg, PrintKind::CheckCfg, PrintKind::CodeModels,
PrintKind::CrateName, PrintKind::CrateRootLintLevels,
PrintKind::DeploymentTarget, PrintKind::FileNames,
PrintKind::HostTuple, PrintKind::LinkArgs,
PrintKind::NativeStaticLibs, PrintKind::RelocationModels,
PrintKind::SplitDebuginfo,
PrintKind::StackProtectorStrategies,
PrintKind::SupportedCrateTypes, PrintKind::Sysroot,
PrintKind::TargetCPUs, PrintKind::TargetFeatures,
PrintKind::TargetLibdir, PrintKind::TargetList,
PrintKind::TargetSpecJson, PrintKind::TargetSpecJsonSchema,
PrintKind::TlsModels];
}AllVariants)]
23pub enum PrintKind {
24 AllTargetSpecsJson,
26 BackendHasMnemonic,
27 BackendHasZstd,
28 CallingConventions,
29 Cfg,
30 CheckCfg,
31 CodeModels,
32 CrateName,
33 CrateRootLintLevels,
34 DeploymentTarget,
35 FileNames,
36 HostTuple,
37 LinkArgs,
38 NativeStaticLibs,
39 RelocationModels,
40 SplitDebuginfo,
41 StackProtectorStrategies,
42 SupportedCrateTypes,
43 Sysroot,
44 TargetCPUs,
45 TargetFeatures,
46 TargetLibdir,
47 TargetList,
48 TargetSpecJson,
49 TargetSpecJsonSchema,
50 TlsModels,
51 }
53
54impl PrintKind {
55 fn name(self) -> &'static str {
56 use PrintKind::*;
57 match self {
58 AllTargetSpecsJson => "all-target-specs-json",
60 BackendHasMnemonic => "backend-has-mnemonic",
61 BackendHasZstd => "backend-has-zstd",
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 }
87 }
88
89 fn is_stable(self) -> bool {
90 use PrintKind::*;
91 match self {
92 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 AllTargetSpecsJson => false,
114 BackendHasMnemonic => false, BackendHasZstd => false, CheckCfg => false,
117 CrateRootLintLevels => false,
118 SupportedCrateTypes => false,
119 TargetSpecJson => false,
120 TargetSpecJsonSchema => false,
121 }
122 }
123
124 fn from_str(s: &str) -> Option<Self> {
125 Self::ALL_VARIANTS.iter().find(|kind| kind.name() == s).copied()
126 }
127}
128
129impl fmt::Display for PrintKind {
130 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
131 self.name().fmt(f)
132 }
133}
134
135pub(crate) static PRINT_HELP: LazyLock<String> = LazyLock::new(|| {
136 let print_kinds =
137 PrintKind::ALL_VARIANTS.iter().map(|kind| kind.name()).collect::<Vec<_>>().join("|");
138 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Compiler information to print on stdout (or to a file)\nINFO may be one of <{0}>.",
print_kinds))
})format!(
139 "Compiler information to print on stdout (or to a file)\n\
140 INFO may be one of <{print_kinds}>.",
141 )
142});
143
144pub(crate) fn collect_print_requests(
145 early_dcx: &EarlyDiagCtxt,
146 cg: &mut CodegenOptions,
147 unstable_opts: &UnstableOptions,
148 matches: &getopts::Matches,
149) -> Vec<PrintRequest> {
150 let mut prints = Vec::<PrintRequest>::new();
151 if cg.target_cpu.as_deref() == Some("help") {
152 prints.push(PrintRequest {
153 kind: PrintKind::TargetCPUs,
154 out: OutFileName::Stdout,
155 arg: None,
156 });
157 cg.target_cpu = None;
158 };
159 if cg.target_feature == "help" {
160 prints.push(PrintRequest {
161 kind: PrintKind::TargetFeatures,
162 out: OutFileName::Stdout,
163 arg: None,
164 });
165 cg.target_feature = String::new();
166 }
167
168 let mut printed_paths = FxHashSet::default();
173
174 prints.extend(matches.opt_strs("print").into_iter().map(|req| {
175 let (req, out) = split_out_file_name(&req);
176
177 let (kind, arg) = if let Some(mnemonic) = req.strip_prefix("backend-has-mnemonic") {
178 check_print_request_stability(early_dcx, unstable_opts, PrintKind::BackendHasMnemonic);
179 if let Some(mnemonic) = mnemonic.strip_prefix(':')
181 && !mnemonic.is_empty()
182 {
183 (PrintKind::BackendHasMnemonic, Some(mnemonic.to_string()))
184 } else {
185 early_dcx.early_fatal(
186 "expected mnemonic name after `--print=backend-has-mnemonic:`, \
187 for example: `--print=backend-has-mnemonic:RET`",
188 );
189 }
190 } else if let Some(print_kind) = PrintKind::from_str(req) {
191 check_print_request_stability(early_dcx, unstable_opts, print_kind);
192 (print_kind, None)
193 } else {
194 let is_nightly = nightly_options::match_is_nightly_build(matches);
195 emit_unknown_print_request_help(early_dcx, req, is_nightly)
196 };
197
198 let out = out.unwrap_or(OutFileName::Stdout);
199 if let OutFileName::Real(path) = &out {
200 if !printed_paths.insert(path.clone()) {
201 early_dcx.early_fatal(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("cannot print multiple outputs to the same path: {0}",
path.display()))
})format!(
202 "cannot print multiple outputs to the same path: {}",
203 path.display(),
204 ));
205 }
206 }
207
208 PrintRequest { kind, out, arg }
209 }));
210
211 prints
212}
213
214fn check_print_request_stability(
215 early_dcx: &EarlyDiagCtxt,
216 unstable_opts: &UnstableOptions,
217 print_kind: PrintKind,
218) {
219 if !print_kind.is_stable() && !unstable_opts.unstable_options {
220 early_dcx.early_fatal(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("the `-Z unstable-options` flag must also be passed to enable the `{0}` print option",
print_kind))
})format!(
221 "the `-Z unstable-options` flag must also be passed to enable the `{print_kind}` print option"
222 ));
223 }
224}
225
226fn emit_unknown_print_request_help(early_dcx: &EarlyDiagCtxt, req: &str, is_nightly: bool) -> ! {
227 let prints = PrintKind::ALL_VARIANTS
228 .iter()
229 .filter(|kind| is_nightly || kind.is_stable())
231 .map(|kind| ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`", kind))
})format!("`{kind}`"))
232 .collect::<Vec<_>>()
233 .join(", ");
234
235 let mut diag = early_dcx.early_struct_fatal(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("unknown print request: `{0}`",
req))
})format!("unknown print request: `{req}`"));
236 diag.help(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("valid print requests are: {0}",
prints))
})format!("valid print requests are: {prints}"));
237
238 if req == "lints" {
239 diag.help(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("use `-Whelp` to print a list of lints"))
})format!("use `-Whelp` to print a list of lints"));
240 }
241
242 diag.help(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information"))
})format!("for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information"));
243 diag.emit()
244}