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