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),
}
}
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for PrintRequest {
#[inline]
fn eq(&self, other: &PrintRequest) -> bool {
self.kind == other.kind && self.out == other.out
}
}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_field2_finish(f, "PrintRequest",
"kind", &self.kind, "out", &&self.out)
}
}Debug)]
15pub struct PrintRequest {
16 pub kind: PrintKind,
17 pub out: OutFileName,
18}
19
20#[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_receiver_is_total_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::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)]
21#[derive(impl crate::macros::AllVariants for PrintKind {
const ALL_VARIANTS: &[PrintKind] =
&[PrintKind::AllTargetSpecsJson, 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)]
22pub enum PrintKind {
23 AllTargetSpecsJson,
25 BackendHasZstd,
26 CallingConventions,
27 Cfg,
28 CheckCfg,
29 CodeModels,
30 CrateName,
31 CrateRootLintLevels,
32 DeploymentTarget,
33 FileNames,
34 HostTuple,
35 LinkArgs,
36 NativeStaticLibs,
37 RelocationModels,
38 SplitDebuginfo,
39 StackProtectorStrategies,
40 SupportedCrateTypes,
41 Sysroot,
42 TargetCPUs,
43 TargetFeatures,
44 TargetLibdir,
45 TargetList,
46 TargetSpecJson,
47 TargetSpecJsonSchema,
48 TlsModels,
49 }
51
52impl PrintKind {
53 const ALL_VARIANTS: &[Self] = <Self as AllVariants>::ALL_VARIANTS;
57
58 fn name(self) -> &'static str {
59 use PrintKind::*;
60 match self {
61 AllTargetSpecsJson => "all-target-specs-json",
63 BackendHasZstd => "backend-has-zstd",
64 CallingConventions => "calling-conventions",
65 Cfg => "cfg",
66 CheckCfg => "check-cfg",
67 CodeModels => "code-models",
68 CrateName => "crate-name",
69 CrateRootLintLevels => "crate-root-lint-levels",
70 DeploymentTarget => "deployment-target",
71 FileNames => "file-names",
72 HostTuple => "host-tuple",
73 LinkArgs => "link-args",
74 NativeStaticLibs => "native-static-libs",
75 RelocationModels => "relocation-models",
76 SplitDebuginfo => "split-debuginfo",
77 StackProtectorStrategies => "stack-protector-strategies",
78 SupportedCrateTypes => "supported-crate-types",
79 Sysroot => "sysroot",
80 TargetCPUs => "target-cpus",
81 TargetFeatures => "target-features",
82 TargetLibdir => "target-libdir",
83 TargetList => "target-list",
84 TargetSpecJson => "target-spec-json",
85 TargetSpecJsonSchema => "target-spec-json-schema",
86 TlsModels => "tls-models",
87 }
89 }
90
91 fn is_stable(self) -> bool {
92 use PrintKind::*;
93 match self {
94 CallingConventions
96 | Cfg
97 | CodeModels
98 | CrateName
99 | DeploymentTarget
100 | FileNames
101 | HostTuple
102 | LinkArgs
103 | NativeStaticLibs
104 | RelocationModels
105 | SplitDebuginfo
106 | StackProtectorStrategies
107 | Sysroot
108 | TargetCPUs
109 | TargetFeatures
110 | TargetLibdir
111 | TargetList
112 | TlsModels => true,
113
114 AllTargetSpecsJson => false,
116 BackendHasZstd => false, CheckCfg => false,
118 CrateRootLintLevels => false,
119 SupportedCrateTypes => false,
120 TargetSpecJson => false,
121 TargetSpecJsonSchema => false,
122 }
123 }
124
125 fn from_str(s: &str) -> Option<Self> {
126 Self::ALL_VARIANTS.iter().find(|kind| kind.name() == s).copied()
127 }
128}
129
130impl fmt::Display for PrintKind {
131 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
132 self.name().fmt(f)
133 }
134}
135
136pub(crate) static PRINT_HELP: LazyLock<String> = LazyLock::new(|| {
137 let print_kinds =
138 PrintKind::ALL_VARIANTS.iter().map(|kind| kind.name()).collect::<Vec<_>>().join("|");
139 ::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!(
140 "Compiler information to print on stdout (or to a file)\n\
141 INFO may be one of <{print_kinds}>.",
142 )
143});
144
145pub(crate) fn collect_print_requests(
146 early_dcx: &EarlyDiagCtxt,
147 cg: &mut CodegenOptions,
148 unstable_opts: &UnstableOptions,
149 matches: &getopts::Matches,
150) -> Vec<PrintRequest> {
151 let mut prints = Vec::<PrintRequest>::new();
152 if cg.target_cpu.as_deref() == Some("help") {
153 prints.push(PrintRequest { kind: PrintKind::TargetCPUs, out: OutFileName::Stdout });
154 cg.target_cpu = None;
155 };
156 if cg.target_feature == "help" {
157 prints.push(PrintRequest { kind: PrintKind::TargetFeatures, out: OutFileName::Stdout });
158 cg.target_feature = String::new();
159 }
160
161 let mut printed_paths = FxHashSet::default();
166
167 prints.extend(matches.opt_strs("print").into_iter().map(|req| {
168 let (req, out) = split_out_file_name(&req);
169
170 let kind = if let Some(print_kind) = PrintKind::from_str(req) {
171 check_print_request_stability(early_dcx, unstable_opts, print_kind);
172 print_kind
173 } else {
174 let is_nightly = nightly_options::match_is_nightly_build(matches);
175 emit_unknown_print_request_help(early_dcx, req, is_nightly)
176 };
177
178 let out = out.unwrap_or(OutFileName::Stdout);
179 if let OutFileName::Real(path) = &out {
180 if !printed_paths.insert(path.clone()) {
181 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!(
182 "cannot print multiple outputs to the same path: {}",
183 path.display(),
184 ));
185 }
186 }
187
188 PrintRequest { kind, out }
189 }));
190
191 prints
192}
193
194fn check_print_request_stability(
195 early_dcx: &EarlyDiagCtxt,
196 unstable_opts: &UnstableOptions,
197 print_kind: PrintKind,
198) {
199 if !print_kind.is_stable() && !unstable_opts.unstable_options {
200 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!(
201 "the `-Z unstable-options` flag must also be passed to enable the `{print_kind}` print option"
202 ));
203 }
204}
205
206fn emit_unknown_print_request_help(early_dcx: &EarlyDiagCtxt, req: &str, is_nightly: bool) -> ! {
207 let prints = PrintKind::ALL_VARIANTS
208 .iter()
209 .filter(|kind| is_nightly || kind.is_stable())
211 .map(|kind| ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`", kind))
})format!("`{kind}`"))
212 .collect::<Vec<_>>()
213 .join(", ");
214
215 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}`"));
216 #[allow(rustc::diagnostic_outside_of_impl)]
217 diag.help(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("valid print requests are: {0}",
prints))
})format!("valid print requests are: {prints}"));
218
219 if req == "lints" {
220 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"));
221 }
222
223 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"));
224 diag.emit()
225}