]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_session/src/config.rs
New upstream version 1.65.0+dfsg1
[rustc.git] / compiler / rustc_session / src / config.rs
CommitLineData
1a4d82fc 1//! Contains infrastructure for configuring the compiler, including parsing
e1599b0c 2//! command-line options.
83c7162d 3
dfeec247
XL
4pub use crate::options::*;
5
dfeec247 6use crate::search_paths::SearchPath;
17df50a5 7use crate::utils::{CanonicalizedPath, NativeLib, NativeLibKind};
60c5eb7d 8use crate::{early_error, early_warn, Session};
04454e1e 9use crate::{lint, HashStableContext};
1a4d82fc 10
5e7ed085 11use rustc_data_structures::fx::{FxHashMap, FxHashSet};
e1599b0c 12
04454e1e 13use rustc_data_structures::stable_hasher::ToStableHashKey;
1b1a35ee 14use rustc_target::abi::{Align, TargetDataLayout};
f2b60f7d
FG
15use rustc_target::spec::{PanicStrategy, SanitizerSet, SplitDebuginfo};
16use rustc_target::spec::{Target, TargetTriple, TargetWarnings, TARGETS};
1a4d82fc 17
5099ac24 18use crate::parse::{CrateCheckConfig, CrateConfig};
dfeec247 19use rustc_feature::UnstableFeatures;
cdc7bbd5 20use rustc_span::edition::{Edition, DEFAULT_EDITION, EDITION_NAME_LIST, LATEST_STABLE_EDITION};
dfeec247
XL
21use rustc_span::source_map::{FileName, FilePathMapping};
22use rustc_span::symbol::{sym, Symbol};
94222f64 23use rustc_span::RealFileName;
ba9703b0 24use rustc_span::SourceFileHashAlgorithm;
1a4d82fc 25
60c5eb7d 26use rustc_errors::emitter::HumanReadableErrorType;
ba9703b0 27use rustc_errors::{ColorConfig, HandlerFlags};
3157f602 28
e1599b0c
XL
29use std::collections::btree_map::{
30 Iter as BTreeMapIter, Keys as BTreeMapKeysIter, Values as BTreeMapValuesIter,
31};
dfeec247 32use std::collections::{BTreeMap, BTreeSet};
e1599b0c 33use std::fmt;
136023e0 34use std::hash::Hash;
60c5eb7d 35use std::iter::{self, FromIterator};
0531ce1d 36use std::path::{Path, PathBuf};
dfeec247 37use std::str::{self, FromStr};
1a4d82fc 38
f2b60f7d
FG
39pub mod sigpipe;
40
3c0e092e 41/// The different settings that the `-C strip` flag can have.
f9f354fc
XL
42#[derive(Clone, Copy, PartialEq, Hash, Debug)]
43pub enum Strip {
44 /// Do not strip at all.
45 None,
46
47 /// Strip debuginfo.
48 Debuginfo,
49
50 /// Strip all symbols.
51 Symbols,
52}
53
3dfed10e 54/// The different settings that the `-C control-flow-guard` flag can have.
74b04a01
XL
55#[derive(Clone, Copy, PartialEq, Hash, Debug)]
56pub enum CFGuard {
57 /// Do not emit Control Flow Guard metadata or checks.
58 Disabled,
59
60 /// Emit Control Flow Guard metadata but no checks.
61 NoChecks,
62
63 /// Emit Control Flow Guard metadata and checks.
64 Checks,
65}
66
5099ac24
FG
67/// The different settings that the `-Z cf-protection` flag can have.
68#[derive(Clone, Copy, PartialEq, Hash, Debug)]
69pub enum CFProtection {
70 /// Do not enable control-flow protection
71 None,
72
73 /// Emit control-flow protection for branches (enables indirect branch tracking).
74 Branch,
75
76 /// Emit control-flow protection for returns.
77 Return,
78
79 /// Emit control-flow protection for both branches and returns.
80 Full,
81}
82
04454e1e 83#[derive(Clone, Copy, Debug, PartialEq, Hash, HashStable_Generic)]
1a4d82fc 84pub enum OptLevel {
0531ce1d
XL
85 No, // -O0
86 Less, // -O1
87 Default, // -O2
a7813a04 88 Aggressive, // -O3
0531ce1d
XL
89 Size, // -Os
90 SizeMin, // -Oz
1a4d82fc
JJ
91}
92
b7449926
XL
93/// This is what the `LtoCli` values get mapped to after resolving defaults and
94/// and taking other command line options into account.
cdc7bbd5
XL
95///
96/// Note that linker plugin-based LTO is a different mechanism entirely.
e74abb32 97#[derive(Clone, PartialEq)]
2c00a5a8 98pub enum Lto {
cdc7bbd5 99 /// Don't do any LTO whatsoever.
2c00a5a8
XL
100 No,
101
cdc7bbd5 102 /// Do a full-crate-graph (inter-crate) LTO with ThinLTO.
2c00a5a8
XL
103 Thin,
104
cdc7bbd5
XL
105 /// Do a local ThinLTO (intra-crate, over the CodeGen Units of the local crate only). This is
106 /// only relevant if multiple CGUs are used.
2c00a5a8
XL
107 ThinLocal,
108
cdc7bbd5 109 /// Do a full-crate-graph (inter-crate) LTO with "fat" LTO.
2c00a5a8
XL
110 Fat,
111}
112
b7449926
XL
113/// The different settings that the `-C lto` flag can have.
114#[derive(Clone, Copy, PartialEq, Hash, Debug)]
115pub enum LtoCli {
116 /// `-C lto=no`
117 No,
118 /// `-C lto=yes`
119 Yes,
120 /// `-C lto`
121 NoParam,
122 /// `-C lto=thin`
123 Thin,
124 /// `-C lto=fat`
125 Fat,
126 /// No `-C lto` flag passed
127 Unspecified,
128}
129
1b1a35ee
XL
130/// The different settings that the `-Z dump_mir_spanview` flag can have. `Statement` generates a
131/// document highlighting each span of every statement (including terminators). `Terminator` and
132/// `Block` highlight a single span per `BasicBlock`: the span of the block's `Terminator`, or a
133/// computed span for the block, representing the entire range, covering the block's terminator and
134/// all of its statements.
135#[derive(Clone, Copy, PartialEq, Hash, Debug)]
136pub enum MirSpanview {
137 /// Default `-Z dump_mir_spanview` or `-Z dump_mir_spanview=statement`
138 Statement,
139 /// `-Z dump_mir_spanview=terminator`
140 Terminator,
141 /// `-Z dump_mir_spanview=block`
142 Block,
143}
144
5099ac24 145/// The different settings that the `-C instrument-coverage` flag can have.
cdc7bbd5 146///
5099ac24 147/// Coverage instrumentation now supports combining `-C instrument-coverage`
cdc7bbd5
XL
148/// with compiler and linker optimization (enabled with `-O` or `-C opt-level=1`
149/// and higher). Nevertheless, there are many variables, depending on options
150/// selected, code structure, and enabled attributes. If errors are encountered,
151/// either while compiling or when generating `llvm-cov show` reports, consider
152/// lowering the optimization level, including or excluding `-C link-dead-code`,
5099ac24
FG
153/// or using `-Zunstable-options -C instrument-coverage=except-unused-functions`
154/// or `-Zunstable-options -C instrument-coverage=except-unused-generics`.
cdc7bbd5
XL
155///
156/// Note that `ExceptUnusedFunctions` means: When `mapgen.rs` generates the
157/// coverage map, it will not attempt to generate synthetic functions for unused
158/// (and not code-generated) functions (whether they are generic or not). As a
159/// result, non-codegenned functions will not be included in the coverage map,
160/// and will not appear, as covered or uncovered, in coverage reports.
161///
162/// `ExceptUnusedGenerics` will add synthetic functions to the coverage map,
163/// unless the function has type parameters.
164#[derive(Clone, Copy, PartialEq, Hash, Debug)]
165pub enum InstrumentCoverage {
5099ac24 166 /// Default `-C instrument-coverage` or `-C instrument-coverage=statement`
cdc7bbd5 167 All,
5099ac24 168 /// `-Zunstable-options -C instrument-coverage=except-unused-generics`
cdc7bbd5 169 ExceptUnusedGenerics,
5099ac24 170 /// `-Zunstable-options -C instrument-coverage=except-unused-functions`
cdc7bbd5 171 ExceptUnusedFunctions,
5099ac24 172 /// `-C instrument-coverage=off` (or `no`, etc.)
cdc7bbd5
XL
173 Off,
174}
175
176#[derive(Clone, PartialEq, Hash, Debug)]
9fa01778 177pub enum LinkerPluginLto {
94b46f34 178 LinkerPlugin(PathBuf),
8faf50e0 179 LinkerPluginAuto,
dfeec247 180 Disabled,
94b46f34
XL
181}
182
3c0e092e
XL
183/// Used with `-Z assert-incr-state`.
184#[derive(Clone, Copy, PartialEq, Hash, Debug)]
185pub enum IncrementalStateAssertion {
186 /// Found and loaded an existing session directory.
187 ///
188 /// Note that this says nothing about whether any particular query
189 /// will be found to be red or green.
190 Loaded,
191 /// Did not load an existing session directory.
192 NotLoaded,
193}
194
9fa01778 195impl LinkerPluginLto {
8faf50e0 196 pub fn enabled(&self) -> bool {
94b46f34 197 match *self {
dfeec247 198 LinkerPluginLto::LinkerPlugin(_) | LinkerPluginLto::LinkerPluginAuto => true,
9fa01778 199 LinkerPluginLto::Disabled => false,
94b46f34
XL
200 }
201 }
202}
203
3c0e092e
XL
204/// The different settings that can be enabled via the `-Z location-detail` flag.
205#[derive(Clone, PartialEq, Hash, Debug)]
206pub struct LocationDetail {
207 pub file: bool,
208 pub line: bool,
209 pub column: bool,
210}
211
212impl LocationDetail {
213 pub fn all() -> Self {
214 Self { file: true, line: true, column: true }
215 }
216}
217
cdc7bbd5 218#[derive(Clone, PartialEq, Hash, Debug)]
dc9dc135 219pub enum SwitchWithOptPath {
48663c56
XL
220 Enabled(Option<PathBuf>),
221 Disabled,
222}
223
dc9dc135 224impl SwitchWithOptPath {
48663c56
XL
225 pub fn enabled(&self) -> bool {
226 match *self {
dc9dc135
XL
227 SwitchWithOptPath::Enabled(_) => true,
228 SwitchWithOptPath::Disabled => false,
48663c56
XL
229 }
230 }
231}
232
04454e1e 233#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable_Generic)]
3dfed10e 234#[derive(Encodable, Decodable)]
dc9dc135
XL
235pub enum SymbolManglingVersion {
236 Legacy,
237 V0,
238}
239
fc512014 240#[derive(Clone, Copy, Debug, PartialEq, Hash)]
b7449926
XL
241pub enum DebugInfo {
242 None,
243 Limited,
244 Full,
1a4d82fc
JJ
245}
246
a2a8927a
XL
247/// Split debug-information is enabled by `-C split-debuginfo`, this enum is only used if split
248/// debug-information is enabled (in either `Packed` or `Unpacked` modes), and the platform
249/// uses DWARF for debug-information.
250///
251/// Some debug-information requires link-time relocation and some does not. LLVM can partition
252/// the debuginfo into sections depending on whether or not it requires link-time relocation. Split
253/// DWARF provides a mechanism which allows the linker to skip the sections which don't require
254/// link-time relocation - either by putting those sections in DWARF object files, or by keeping
255/// them in the object file in such a way that the linker will skip them.
256#[derive(Clone, Copy, Debug, PartialEq, Hash)]
257pub enum SplitDwarfKind {
258 /// Sections which do not require relocation are written into object file but ignored by the
259 /// linker.
260 Single,
261 /// Sections which do not require relocation are written into a DWARF object (`.dwo`) file
262 /// which is ignored by the linker.
263 Split,
264}
265
266impl FromStr for SplitDwarfKind {
267 type Err = ();
268
269 fn from_str(s: &str) -> Result<Self, ()> {
270 Ok(match s {
271 "single" => SplitDwarfKind::Single,
272 "split" => SplitDwarfKind::Split,
273 _ => return Err(()),
274 })
275 }
276}
277
04454e1e 278#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord, HashStable_Generic)]
3dfed10e 279#[derive(Encodable, Decodable)]
1a4d82fc 280pub enum OutputType {
b039eaaf
SL
281 Bitcode,
282 Assembly,
283 LlvmAssembly,
cc61c64b 284 Mir,
32a655c1 285 Metadata,
b039eaaf
SL
286 Object,
287 Exe,
288 DepInfo,
1a4d82fc
JJ
289}
290
04454e1e
FG
291impl<HCX: HashStableContext> ToStableHashKey<HCX> for OutputType {
292 type KeyType = Self;
293
294 fn to_stable_hash_key(&self, _: &HCX) -> Self::KeyType {
295 *self
296 }
297}
ea8adc8c 298
92a42be0
SL
299impl OutputType {
300 fn is_compatible_with_codegen_units_and_single_output_file(&self) -> bool {
301 match *self {
48663c56 302 OutputType::Exe | OutputType::DepInfo | OutputType::Metadata => true,
0531ce1d
XL
303 OutputType::Bitcode
304 | OutputType::Assembly
305 | OutputType::LlvmAssembly
306 | OutputType::Mir
48663c56 307 | OutputType::Object => false,
92a42be0
SL
308 }
309 }
310
311 fn shorthand(&self) -> &'static str {
312 match *self {
313 OutputType::Bitcode => "llvm-bc",
314 OutputType::Assembly => "asm",
315 OutputType::LlvmAssembly => "llvm-ir",
cc61c64b 316 OutputType::Mir => "mir",
92a42be0 317 OutputType::Object => "obj",
32a655c1 318 OutputType::Metadata => "metadata",
92a42be0
SL
319 OutputType::Exe => "link",
320 OutputType::DepInfo => "dep-info",
321 }
322 }
5bcae85e 323
abe05a73
XL
324 fn from_shorthand(shorthand: &str) -> Option<Self> {
325 Some(match shorthand {
0531ce1d
XL
326 "asm" => OutputType::Assembly,
327 "llvm-ir" => OutputType::LlvmAssembly,
328 "mir" => OutputType::Mir,
329 "llvm-bc" => OutputType::Bitcode,
330 "obj" => OutputType::Object,
331 "metadata" => OutputType::Metadata,
332 "link" => OutputType::Exe,
333 "dep-info" => OutputType::DepInfo,
abe05a73
XL
334 _ => return None,
335 })
336 }
337
338 fn shorthands_display() -> String {
339 format!(
340 "`{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}`",
341 OutputType::Bitcode.shorthand(),
342 OutputType::Assembly.shorthand(),
343 OutputType::LlvmAssembly.shorthand(),
344 OutputType::Mir.shorthand(),
345 OutputType::Object.shorthand(),
346 OutputType::Metadata.shorthand(),
347 OutputType::Exe.shorthand(),
348 OutputType::DepInfo.shorthand(),
349 )
350 }
351
5bcae85e
SL
352 pub fn extension(&self) -> &'static str {
353 match *self {
354 OutputType::Bitcode => "bc",
355 OutputType::Assembly => "s",
356 OutputType::LlvmAssembly => "ll",
cc61c64b 357 OutputType::Mir => "mir",
5bcae85e 358 OutputType::Object => "o",
32a655c1 359 OutputType::Metadata => "rmeta",
5bcae85e
SL
360 OutputType::DepInfo => "d",
361 OutputType::Exe => "",
362 }
363 }
92a42be0
SL
364}
365
dc9dc135 366/// The type of diagnostics output to generate.
476ff2be
SL
367#[derive(Clone, Copy, Debug, PartialEq, Eq)]
368pub enum ErrorOutputType {
dc9dc135 369 /// Output meant for the consumption of humans.
48663c56 370 HumanReadable(HumanReadableErrorType),
dc9dc135 371 /// Output that's consumed by other tools such as `rustfix` or the `RLS`.
48663c56 372 Json {
dc9dc135 373 /// Render the JSON in a human readable way (with indents and newlines).
48663c56 374 pretty: bool,
dc9dc135
XL
375 /// The JSON output includes a `rendered` field that includes the rendered
376 /// human output.
48663c56
XL
377 json_rendered: HumanReadableErrorType,
378 },
476ff2be
SL
379}
380
381impl Default for ErrorOutputType {
e1599b0c
XL
382 fn default() -> Self {
383 Self::HumanReadable(HumanReadableErrorType::Default(ColorConfig::Auto))
476ff2be
SL
384 }
385}
386
1b1a35ee 387/// Parameter to control path trimming.
3c0e092e 388#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
1b1a35ee
XL
389pub enum TrimmedDefPaths {
390 /// `try_print_trimmed_def_path` never prints a trimmed path and never calls the expensive query
3c0e092e 391 #[default]
1b1a35ee
XL
392 Never,
393 /// `try_print_trimmed_def_path` calls the expensive query, the query doesn't call `delay_good_path_bug`
394 Always,
395 /// `try_print_trimmed_def_path` calls the expensive query, the query calls `delay_good_path_bug`
396 GoodPath,
397}
398
e1599b0c
XL
399/// Use tree-based collections to cheaply get a deterministic `Hash` implementation.
400/// *Do not* switch `BTreeMap` out for an unsorted container type! That would break
136023e0
XL
401/// dependency tracking for command-line arguments. Also only hash keys, since tracking
402/// should only depend on the output types, not the paths they're written to.
04454e1e 403#[derive(Clone, Debug, Hash, HashStable_Generic)]
5bcae85e
SL
404pub struct OutputTypes(BTreeMap<OutputType, Option<PathBuf>>);
405
406impl OutputTypes {
407 pub fn new(entries: &[(OutputType, Option<PathBuf>)]) -> OutputTypes {
dfeec247 408 OutputTypes(BTreeMap::from_iter(entries.iter().map(|&(k, ref v)| (k, v.clone()))))
5bcae85e
SL
409 }
410
411 pub fn get(&self, key: &OutputType) -> Option<&Option<PathBuf>> {
412 self.0.get(key)
413 }
414
415 pub fn contains_key(&self, key: &OutputType) -> bool {
416 self.0.contains_key(key)
417 }
418
416331ca 419 pub fn keys(&self) -> BTreeMapKeysIter<'_, OutputType, Option<PathBuf>> {
5bcae85e
SL
420 self.0.keys()
421 }
422
416331ca 423 pub fn values(&self) -> BTreeMapValuesIter<'_, OutputType, Option<PathBuf>> {
5bcae85e
SL
424 self.0.values()
425 }
32a655c1 426
83c7162d
XL
427 pub fn len(&self) -> usize {
428 self.0.len()
429 }
430
a2a8927a 431 /// Returns `true` if any of the output types require codegen or linking.
94b46f34 432 pub fn should_codegen(&self) -> bool {
32a655c1 433 self.0.keys().any(|k| match *k {
0531ce1d
XL
434 OutputType::Bitcode
435 | OutputType::Assembly
436 | OutputType::LlvmAssembly
437 | OutputType::Mir
438 | OutputType::Object
439 | OutputType::Exe => true,
440 OutputType::Metadata | OutputType::DepInfo => false,
32a655c1
SL
441 })
442 }
5869c6ff 443
a2a8927a 444 /// Returns `true` if any of the output types require linking.
5869c6ff
XL
445 pub fn should_link(&self) -> bool {
446 self.0.keys().any(|k| match *k {
447 OutputType::Bitcode
448 | OutputType::Assembly
449 | OutputType::LlvmAssembly
450 | OutputType::Mir
451 | OutputType::Metadata
452 | OutputType::Object
453 | OutputType::DepInfo => false,
454 OutputType::Exe => true,
455 })
456 }
5bcae85e
SL
457}
458
e1599b0c
XL
459/// Use tree-based collections to cheaply get a deterministic `Hash` implementation.
460/// *Do not* switch `BTreeMap` or `BTreeSet` out for an unsorted container type! That
461/// would break dependency tracking for command-line arguments.
e74abb32 462#[derive(Clone)]
48663c56
XL
463pub struct Externs(BTreeMap<String, ExternEntry>);
464
60c5eb7d 465#[derive(Clone, Debug)]
48663c56 466pub struct ExternEntry {
60c5eb7d
XL
467 pub location: ExternLocation,
468 /// Indicates this is a "private" dependency for the
469 /// `exported_private_dependencies` lint.
470 ///
471 /// This can be set with the `priv` option like
472 /// `--extern priv:name=foo.rlib`.
473 pub is_private_dep: bool,
474 /// Add the extern entry to the extern prelude.
475 ///
476 /// This can be disabled with the `noprelude` option like
477 /// `--extern noprelude:name`.
478 pub add_prelude: bool,
04454e1e
FG
479 /// The extern entry shouldn't be considered for unused dependency warnings.
480 ///
481 /// `--extern nounused:std=/path/to/lib/libstd.rlib`. This is used to
482 /// suppress `unused-crate-dependencies` warnings.
483 pub nounused_dep: bool,
60c5eb7d
XL
484}
485
486#[derive(Clone, Debug)]
487pub enum ExternLocation {
488 /// Indicates to look for the library in the search paths.
489 ///
490 /// Added via `--extern name`.
491 FoundInLibrarySearchDirectories,
492 /// The locations where this extern entry must be found.
493 ///
494 /// The `CrateLoader` is responsible for loading these and figuring out
495 /// which one to use.
496 ///
497 /// Added via `--extern prelude_name=some_file.rlib`
5869c6ff 498 ExactPaths(BTreeSet<CanonicalizedPath>),
48663c56 499}
5bcae85e
SL
500
501impl Externs {
cdc7bbd5 502 /// Used for testing.
48663c56 503 pub fn new(data: BTreeMap<String, ExternEntry>) -> Externs {
5bcae85e
SL
504 Externs(data)
505 }
506
48663c56 507 pub fn get(&self, key: &str) -> Option<&ExternEntry> {
5bcae85e
SL
508 self.0.get(key)
509 }
510
416331ca 511 pub fn iter(&self) -> BTreeMapIter<'_, String, ExternEntry> {
5bcae85e
SL
512 self.0.iter()
513 }
cdc7bbd5
XL
514
515 pub fn len(&self) -> usize {
516 self.0.len()
517 }
1a4d82fc
JJ
518}
519
60c5eb7d
XL
520impl ExternEntry {
521 fn new(location: ExternLocation) -> ExternEntry {
04454e1e 522 ExternEntry { location, is_private_dep: false, add_prelude: false, nounused_dep: false }
60c5eb7d
XL
523 }
524
5869c6ff 525 pub fn files(&self) -> Option<impl Iterator<Item = &CanonicalizedPath>> {
60c5eb7d
XL
526 match &self.location {
527 ExternLocation::ExactPaths(set) => Some(set.iter()),
528 _ => None,
529 }
530 }
531}
48663c56 532
7cac9316 533#[derive(Copy, Clone, PartialEq, Eq, Debug)]
1a4d82fc
JJ
534pub enum PrintRequest {
535 FileNames,
536 Sysroot,
74b04a01 537 TargetLibdir,
1a4d82fc 538 CrateName,
7453a54e
SL
539 Cfg,
540 TargetList,
5bcae85e
SL
541 TargetCPUs,
542 TargetFeatures,
543 RelocationModels,
544 CodeModels,
abe05a73 545 TlsModels,
476ff2be 546 TargetSpec,
ea8adc8c 547 NativeStaticLibs,
3c0e092e 548 StackProtectorStrategies,
5099ac24 549 LinkArgs,
1a4d82fc
JJ
550}
551
552pub enum Input {
e1599b0c 553 /// Load source code from a file.
c34b1796 554 File(PathBuf),
e1599b0c 555 /// Load source code from a string.
54a0048b 556 Str {
e1599b0c 557 /// A string that is shown in place of a filename.
ff7c6d11 558 name: FileName,
e1599b0c 559 /// An anonymous string containing the source code.
54a0048b
SL
560 input: String,
561 },
1a4d82fc
JJ
562}
563
564impl Input {
0bf4aa26 565 pub fn filestem(&self) -> &str {
1a4d82fc 566 match *self {
0bf4aa26
XL
567 Input::File(ref ifile) => ifile.file_stem().unwrap().to_str().unwrap(),
568 Input::Str { .. } => "rust_out",
1a4d82fc
JJ
569 }
570 }
94b46f34 571
532ac7d7
XL
572 pub fn source_name(&self) -> FileName {
573 match *self {
574 Input::File(ref ifile) => ifile.clone().into(),
575 Input::Str { ref name, .. } => name.clone(),
576 }
577 }
1a4d82fc
JJ
578}
579
04454e1e 580#[derive(Clone, Hash, Debug, HashStable_Generic)]
1a4d82fc 581pub struct OutputFilenames {
c34b1796 582 pub out_directory: PathBuf,
dfeec247 583 filestem: String,
c34b1796 584 pub single_output_file: Option<PathBuf>,
3c0e092e 585 pub temps_directory: Option<PathBuf>,
5bcae85e 586 pub outputs: OutputTypes,
1a4d82fc
JJ
587}
588
74b04a01 589pub const RLINK_EXT: &str = "rlink";
abe05a73 590pub const RUST_CGU_EXT: &str = "rcgu";
fc512014 591pub const DWARF_OBJECT_EXT: &str = "dwo";
5bcae85e 592
1a4d82fc 593impl OutputFilenames {
dfeec247
XL
594 pub fn new(
595 out_directory: PathBuf,
596 out_filestem: String,
597 single_output_file: Option<PathBuf>,
3c0e092e 598 temps_directory: Option<PathBuf>,
dfeec247
XL
599 extra: String,
600 outputs: OutputTypes,
601 ) -> Self {
602 OutputFilenames {
603 out_directory,
604 single_output_file,
3c0e092e 605 temps_directory,
dfeec247 606 outputs,
5e7ed085 607 filestem: format!("{out_filestem}{extra}"),
dfeec247
XL
608 }
609 }
610
c34b1796 611 pub fn path(&self, flavor: OutputType) -> PathBuf {
0531ce1d
XL
612 self.outputs
613 .get(&flavor)
614 .and_then(|p| p.to_owned())
b039eaaf 615 .or_else(|| self.single_output_file.clone())
3c0e092e
XL
616 .unwrap_or_else(|| self.output_path(flavor))
617 }
618
619 /// Gets the output path where a compilation artifact of the given type
620 /// should be placed on disk.
621 pub fn output_path(&self, flavor: OutputType) -> PathBuf {
622 let extension = flavor.extension();
623 self.with_directory_and_extension(&self.out_directory, &extension)
5bcae85e
SL
624 }
625
9fa01778 626 /// Gets the path where a compilation artifact of the given type for the
5bcae85e
SL
627 /// given codegen unit should be placed on disk. If codegen_unit_name is
628 /// None, a path distinct from those of any codegen unit will be generated.
0531ce1d 629 pub fn temp_path(&self, flavor: OutputType, codegen_unit_name: Option<&str>) -> PathBuf {
5bcae85e
SL
630 let extension = flavor.extension();
631 self.temp_path_ext(extension, codegen_unit_name)
1a4d82fc
JJ
632 }
633
fc512014
XL
634 /// Like `temp_path`, but specifically for dwarf objects.
635 pub fn temp_path_dwo(&self, codegen_unit_name: Option<&str>) -> PathBuf {
636 self.temp_path_ext(DWARF_OBJECT_EXT, codegen_unit_name)
637 }
638
639 /// Like `temp_path`, but also supports things where there is no corresponding
9fa01778 640 /// OutputType, like noopt-bitcode or lto-bitcode.
0531ce1d 641 pub fn temp_path_ext(&self, ext: &str, codegen_unit_name: Option<&str>) -> PathBuf {
5bcae85e
SL
642 let mut extension = String::new();
643
644 if let Some(codegen_unit_name) = codegen_unit_name {
ea8adc8c 645 extension.push_str(codegen_unit_name);
1a4d82fc 646 }
5bcae85e
SL
647
648 if !ext.is_empty() {
649 if !extension.is_empty() {
1b1a35ee 650 extension.push('.');
ea8adc8c 651 extension.push_str(RUST_CGU_EXT);
1b1a35ee 652 extension.push('.');
5bcae85e
SL
653 }
654
655 extension.push_str(ext);
656 }
657
3c0e092e
XL
658 let temps_directory = self.temps_directory.as_ref().unwrap_or(&self.out_directory);
659
660 self.with_directory_and_extension(&temps_directory, &extension)
1a4d82fc
JJ
661 }
662
c34b1796 663 pub fn with_extension(&self, extension: &str) -> PathBuf {
3c0e092e
XL
664 self.with_directory_and_extension(&self.out_directory, extension)
665 }
666
667 fn with_directory_and_extension(&self, directory: &PathBuf, extension: &str) -> PathBuf {
668 let mut path = directory.join(&self.filestem);
dfeec247
XL
669 path.set_extension(extension);
670 path
1a4d82fc 671 }
fc512014 672
fc512014
XL
673 /// Returns the path for the Split DWARF file - this can differ depending on which Split DWARF
674 /// mode is being used, which is the logic that this function is intended to encapsulate.
675 pub fn split_dwarf_path(
676 &self,
5869c6ff 677 split_debuginfo_kind: SplitDebuginfo,
a2a8927a 678 split_dwarf_kind: SplitDwarfKind,
fc512014
XL
679 cgu_name: Option<&str>,
680 ) -> Option<PathBuf> {
681 let obj_out = self.temp_path(OutputType::Object, cgu_name);
682 let dwo_out = self.temp_path_dwo(cgu_name);
a2a8927a
XL
683 match (split_debuginfo_kind, split_dwarf_kind) {
684 (SplitDebuginfo::Off, SplitDwarfKind::Single | SplitDwarfKind::Split) => None,
fc512014
XL
685 // Single mode doesn't change how DWARF is emitted, but does add Split DWARF attributes
686 // (pointing at the path which is being determined here). Use the path to the current
687 // object file.
a2a8927a
XL
688 (SplitDebuginfo::Packed | SplitDebuginfo::Unpacked, SplitDwarfKind::Single) => {
689 Some(obj_out)
690 }
fc512014 691 // Split mode emits the DWARF into a different file, use that path.
a2a8927a
XL
692 (SplitDebuginfo::Packed | SplitDebuginfo::Unpacked, SplitDwarfKind::Split) => {
693 Some(dwo_out)
694 }
fc512014
XL
695 }
696 }
1a4d82fc
JJ
697}
698
699pub fn host_triple() -> &'static str {
700 // Get the host triple out of the build environment. This ensures that our
701 // idea of the host triple is the same as for the set of libraries we've
702 // actually built. We can't just take LLVM's host triple because they
703 // normalize all ix86 architectures to i386.
704 //
705 // Instead of grabbing the host triple (for the current host), we grab (at
706 // compile time) the target triple that this rustc is built with and
707 // calling that (at runtime) the host triple.
0531ce1d 708 (option_env!("CFG_COMPILER_HOST_TRIPLE")).expect("CFG_COMPILER_HOST_TRIPLE")
1a4d82fc
JJ
709}
710
b7449926
XL
711impl Default for Options {
712 fn default() -> Options {
713 Options {
3c0e092e 714 assert_incr_state: None,
b7449926
XL
715 crate_types: Vec::new(),
716 optimize: OptLevel::No,
717 debuginfo: DebugInfo::None,
718 lint_opts: Vec::new(),
719 lint_cap: None,
720 describe_lints: false,
721 output_types: OutputTypes(BTreeMap::new()),
0731742a 722 search_paths: vec![],
b7449926
XL
723 maybe_sysroot: None,
724 target_triple: TargetTriple::from_triple(host_triple()),
725 test: false,
726 incremental: None,
064997fb 727 unstable_opts: Default::default(),
b7449926 728 prints: Vec::new(),
17df50a5 729 cg: Default::default(),
b7449926 730 error_format: ErrorOutputType::default(),
064997fb 731 diagnostic_width: None,
b7449926
XL
732 externs: Externs(BTreeMap::new()),
733 crate_name: None,
b7449926
XL
734 libs: Vec::new(),
735 unstable_features: UnstableFeatures::Disallow,
736 debug_assertions: true,
737 actually_rustdoc: false,
1b1a35ee 738 trimmed_def_paths: TrimmedDefPaths::default(),
b7449926
XL
739 cli_forced_codegen_units: None,
740 cli_forced_thinlto_off: false,
741 remap_path_prefix: Vec::new(),
cdc7bbd5 742 real_rust_source_base_dir: None,
b7449926 743 edition: DEFAULT_EDITION,
416331ca 744 json_artifact_notifications: false,
04454e1e 745 json_unused_externs: JsonUnusedExterns::No,
a2a8927a 746 json_future_incompat: false,
60c5eb7d 747 pretty: None,
94222f64 748 working_dir: RealFileName::LocalPath(std::env::current_dir().unwrap()),
b7449926 749 }
1a4d82fc
JJ
750 }
751}
752
54a0048b 753impl Options {
9fa01778 754 /// Returns `true` if there is a reason to build the dep graph.
54a0048b 755 pub fn build_dep_graph(&self) -> bool {
dfeec247 756 self.incremental.is_some()
064997fb
FG
757 || self.unstable_opts.dump_dep_graph
758 || self.unstable_opts.query_dep_graph
54a0048b 759 }
5bcae85e 760
7cac9316 761 pub fn file_path_mapping(&self) -> FilePathMapping {
0531ce1d 762 FilePathMapping::new(self.remap_path_prefix.clone())
7cac9316 763 }
ff7c6d11 764
e1599b0c 765 /// Returns `true` if there will be an output file generated.
ff7c6d11 766 pub fn will_create_output_file(&self) -> bool {
064997fb
FG
767 !self.unstable_opts.parse_only && // The file is just being parsed
768 !self.unstable_opts.ls // The file is just being queried
ff7c6d11 769 }
b7449926
XL
770
771 #[inline]
772 pub fn share_generics(&self) -> bool {
064997fb 773 match self.unstable_opts.share_generics {
b7449926 774 Some(setting) => setting,
dfeec247
XL
775 None => match self.optimize {
776 OptLevel::No | OptLevel::Less | OptLevel::Size | OptLevel::SizeMin => true,
777 OptLevel::Default | OptLevel::Aggressive => false,
778 },
779 }
780 }
a2a8927a
XL
781
782 pub fn get_symbol_mangling_version(&self) -> SymbolManglingVersion {
783 self.cg.symbol_mangling_version.unwrap_or(SymbolManglingVersion::Legacy)
784 }
dfeec247
XL
785}
786
064997fb 787impl UnstableOptions {
dfeec247
XL
788 pub fn diagnostic_handler_flags(&self, can_emit_warnings: bool) -> HandlerFlags {
789 HandlerFlags {
790 can_emit_warnings,
791 treat_err_as_bug: self.treat_err_as_bug,
792 dont_buffer_diagnostics: self.dont_buffer_diagnostics,
793 report_delayed_bugs: self.report_delayed_bugs,
74b04a01 794 macro_backtrace: self.macro_backtrace,
ba9703b0 795 deduplicate_diagnostics: self.deduplicate_diagnostics,
b7449926
XL
796 }
797 }
54a0048b
SL
798}
799
9fa01778 800// The type of entry function, so users can have their own entry functions
04454e1e 801#[derive(Copy, Clone, PartialEq, Hash, Debug, HashStable_Generic)]
1a4d82fc 802pub enum EntryFnType {
f2b60f7d
FG
803 Main {
804 /// Specifies what to do with `SIGPIPE` before calling `fn main()`.
805 ///
806 /// What values that are valid and what they mean must be in sync
807 /// across rustc and libstd, but we don't want it public in libstd,
808 /// so we take a bit of an unusual approach with simple constants
809 /// and an `include!()`.
810 sigpipe: u8,
811 },
b7449926 812 Start,
1a4d82fc
JJ
813}
814
3dfed10e 815#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug, Encodable, Decodable)]
04454e1e 816#[derive(HashStable_Generic)]
1a4d82fc 817pub enum CrateType {
b7449926
XL
818 Executable,
819 Dylib,
820 Rlib,
821 Staticlib,
822 Cdylib,
823 ProcMacro,
1a4d82fc
JJ
824}
825
a2a8927a
XL
826impl CrateType {
827 /// When generated, is this crate type an archive?
828 pub fn is_archive(&self) -> bool {
829 match *self {
830 CrateType::Rlib | CrateType::Staticlib => true,
831 CrateType::Executable | CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro => {
832 false
833 }
834 }
835 }
836}
837
cdc7bbd5 838#[derive(Clone, Hash, Debug, PartialEq, Eq)]
1a4d82fc 839pub enum Passes {
b7449926
XL
840 Some(Vec<String>),
841 All,
1a4d82fc
JJ
842}
843
844impl Passes {
845 pub fn is_empty(&self) -> bool {
846 match *self {
b7449926
XL
847 Passes::Some(ref v) => v.is_empty(),
848 Passes::All => false,
1a4d82fc
JJ
849 }
850 }
a2a8927a
XL
851
852 pub fn extend(&mut self, passes: impl IntoIterator<Item = String>) {
853 match *self {
854 Passes::Some(ref mut v) => v.extend(passes),
855 Passes::All => {}
856 }
857 }
1a4d82fc
JJ
858}
859
5099ac24
FG
860#[derive(Clone, Copy, Hash, Debug, PartialEq)]
861pub enum PAuthKey {
862 A,
863 B,
864}
865
866#[derive(Clone, Copy, Hash, Debug, PartialEq)]
867pub struct PacRet {
868 pub leaf: bool,
869 pub key: PAuthKey,
870}
871
872#[derive(Clone, Copy, Hash, Debug, PartialEq)]
873pub struct BranchProtection {
874 pub bti: bool,
875 pub pac_ret: Option<PacRet>,
876}
877
878impl Default for BranchProtection {
879 fn default() -> Self {
880 BranchProtection { bti: false, pac_ret: None }
881 }
882}
883
e74abb32 884pub const fn default_lib_output() -> CrateType {
b7449926 885 CrateType::Rlib
1a4d82fc
JJ
886}
887
cdc7bbd5 888fn default_configuration(sess: &Session) -> CrateConfig {
5099ac24 889 // NOTE: This should be kept in sync with `CrateCheckConfig::fill_well_known` below.
29967ef6
XL
890 let end = &sess.target.endian;
891 let arch = &sess.target.arch;
892 let wordsz = sess.target.pointer_width.to_string();
893 let os = &sess.target.os;
894 let env = &sess.target.env;
136023e0 895 let abi = &sess.target.abi;
29967ef6
XL
896 let vendor = &sess.target.vendor;
897 let min_atomic_width = sess.target.min_atomic_width();
898 let max_atomic_width = sess.target.max_atomic_width();
899 let atomic_cas = sess.target.atomic_cas;
900 let layout = TargetDataLayout::parse(&sess.target).unwrap_or_else(|err| {
f2b60f7d 901 sess.emit_fatal(err);
1b1a35ee 902 });
1a4d82fc 903
f2b60f7d 904 let mut ret = CrateConfig::default();
136023e0 905 ret.reserve(7); // the minimum number of insertions
476ff2be 906 // Target bindings.
3dfed10e 907 ret.insert((sym::target_os, Some(Symbol::intern(os))));
5e7ed085 908 for fam in sess.target.families.as_ref() {
3dfed10e
XL
909 ret.insert((sym::target_family, Some(Symbol::intern(fam))));
910 if fam == "windows" {
911 ret.insert((sym::windows, None));
912 } else if fam == "unix" {
913 ret.insert((sym::unix, None));
32a655c1
SL
914 }
915 }
3dfed10e 916 ret.insert((sym::target_arch, Some(Symbol::intern(arch))));
5869c6ff 917 ret.insert((sym::target_endian, Some(Symbol::intern(end.as_str()))));
29967ef6 918 ret.insert((sym::target_pointer_width, Some(Symbol::intern(&wordsz))));
3dfed10e 919 ret.insert((sym::target_env, Some(Symbol::intern(env))));
136023e0 920 ret.insert((sym::target_abi, Some(Symbol::intern(abi))));
3dfed10e 921 ret.insert((sym::target_vendor, Some(Symbol::intern(vendor))));
a2a8927a 922 if sess.target.has_thread_local {
dc9dc135 923 ret.insert((sym::target_thread_local, None));
9cc50fc6 924 }
136023e0 925 for (i, align) in [
1b1a35ee
XL
926 (8, layout.i8_align.abi),
927 (16, layout.i16_align.abi),
928 (32, layout.i32_align.abi),
929 (64, layout.i64_align.abi),
930 (128, layout.i128_align.abi),
931 ] {
32a655c1 932 if i >= min_atomic_width && i <= max_atomic_width {
1b1a35ee 933 let mut insert_atomic = |s, align: Align| {
dfeec247 934 ret.insert((sym::target_has_atomic_load_store, Some(Symbol::intern(s))));
e74abb32 935 if atomic_cas {
dfeec247 936 ret.insert((sym::target_has_atomic, Some(Symbol::intern(s))));
e74abb32 937 }
1b1a35ee
XL
938 if align.bits() == i {
939 ret.insert((sym::target_has_atomic_equal_alignment, Some(Symbol::intern(s))));
940 }
e74abb32
XL
941 };
942 let s = i.to_string();
1b1a35ee 943 insert_atomic(&s, align);
29967ef6 944 if s == wordsz {
1b1a35ee 945 insert_atomic("ptr", layout.pointer_align.abi);
a7813a04
XL
946 }
947 }
948 }
f035d41b 949
29967ef6
XL
950 let panic_strategy = sess.panic_strategy();
951 ret.insert((sym::panic, Some(panic_strategy.desc_symbol())));
952
064997fb 953 for s in sess.opts.unstable_opts.sanitizer {
60c5eb7d
XL
954 let symbol = Symbol::intern(&s.to_string());
955 ret.insert((sym::sanitize, Some(symbol)));
956 }
f035d41b 957
c34b1796 958 if sess.opts.debug_assertions {
3dfed10e 959 ret.insert((sym::debug_assertions, None));
c34b1796 960 }
064997fb 961 // JUSTIFICATION: before wrapper fn is available
f2b60f7d 962 #[allow(rustc::bad_opt_access)]
b7449926 963 if sess.opts.crate_types.contains(&CrateType::ProcMacro) {
dc9dc135 964 ret.insert((sym::proc_macro, None));
9e0c209e 965 }
0bf4aa26 966 ret
1a4d82fc
JJ
967}
968
e1599b0c 969/// Converts the crate `cfg!` configuration from `String` to `Symbol`.
532ac7d7
XL
970/// `rustc_interface::interface::Config` accepts this in the compiler configuration,
971/// but the symbol interner is not yet set up then, so we must convert it later.
60c5eb7d 972pub fn to_crate_config(cfg: FxHashSet<(String, Option<String>)>) -> CrateConfig {
dfeec247 973 cfg.into_iter().map(|(a, b)| (Symbol::intern(&a), b.map(|b| Symbol::intern(&b)))).collect()
532ac7d7
XL
974}
975
5099ac24
FG
976/// The parsed `--check-cfg` options
977pub struct CheckCfg<T = String> {
5e7ed085
FG
978 /// The set of all `names()`, if None no name checking is performed
979 pub names_valid: Option<FxHashSet<T>>,
980 /// Is well known values activated
981 pub well_known_values: bool,
982 /// The set of all `values()`
983 pub values_valid: FxHashMap<T, FxHashSet<T>>,
5099ac24
FG
984}
985
986impl<T> Default for CheckCfg<T> {
987 fn default() -> Self {
988 CheckCfg {
5e7ed085
FG
989 names_valid: Default::default(),
990 values_valid: Default::default(),
991 well_known_values: false,
5099ac24
FG
992 }
993 }
994}
995
996impl<T> CheckCfg<T> {
997 fn map_data<O: Eq + Hash>(&self, f: impl Fn(&T) -> O) -> CheckCfg<O> {
998 CheckCfg {
5e7ed085
FG
999 names_valid: self
1000 .names_valid
1001 .as_ref()
1002 .map(|names_valid| names_valid.iter().map(|a| f(a)).collect()),
1003 values_valid: self
1004 .values_valid
1005 .iter()
1006 .map(|(a, b)| (f(a), b.iter().map(|b| f(b)).collect()))
1007 .collect(),
1008 well_known_values: self.well_known_values,
5099ac24
FG
1009 }
1010 }
1011}
1012
1013/// Converts the crate `--check-cfg` options from `String` to `Symbol`.
1014/// `rustc_interface::interface::Config` accepts this in the compiler configuration,
1015/// but the symbol interner is not yet set up then, so we must convert it later.
1016pub fn to_crate_check_config(cfg: CheckCfg) -> CrateCheckConfig {
1017 cfg.map_data(|s| Symbol::intern(s))
1018}
1019
1020impl CrateCheckConfig {
1021 /// Fills a `CrateCheckConfig` with well-known configuration names.
5e7ed085
FG
1022 fn fill_well_known_names(&mut self) {
1023 // NOTE: This should be kept in sync with `default_configuration` and
1024 // `fill_well_known_values`
5099ac24 1025 const WELL_KNOWN_NAMES: &[Symbol] = &[
5e7ed085 1026 // rustc
5099ac24
FG
1027 sym::unix,
1028 sym::windows,
1029 sym::target_os,
1030 sym::target_family,
1031 sym::target_arch,
1032 sym::target_endian,
1033 sym::target_pointer_width,
1034 sym::target_env,
1035 sym::target_abi,
1036 sym::target_vendor,
1037 sym::target_thread_local,
1038 sym::target_has_atomic_load_store,
1039 sym::target_has_atomic,
1040 sym::target_has_atomic_equal_alignment,
04454e1e 1041 sym::target_feature,
5099ac24
FG
1042 sym::panic,
1043 sym::sanitize,
1044 sym::debug_assertions,
1045 sym::proc_macro,
1046 sym::test,
5e7ed085
FG
1047 sym::feature,
1048 // rustdoc
5099ac24
FG
1049 sym::doc,
1050 sym::doctest,
5e7ed085
FG
1051 // miri
1052 sym::miri,
5099ac24 1053 ];
5e7ed085
FG
1054
1055 // We only insert well-known names if `names()` was activated
1056 if let Some(names_valid) = &mut self.names_valid {
1057 names_valid.extend(WELL_KNOWN_NAMES);
5099ac24
FG
1058 }
1059 }
1060
5e7ed085
FG
1061 /// Fills a `CrateCheckConfig` with well-known configuration values.
1062 fn fill_well_known_values(&mut self) {
1063 if !self.well_known_values {
1064 return;
1065 }
1066
1067 // NOTE: This should be kept in sync with `default_configuration` and
1068 // `fill_well_known_names`
1069
1070 let panic_values = &PanicStrategy::all();
1071
1072 let atomic_values = &[
1073 sym::ptr,
1074 sym::integer(8usize),
1075 sym::integer(16usize),
1076 sym::integer(32usize),
1077 sym::integer(64usize),
1078 sym::integer(128usize),
1079 ];
1080
1081 let sanitize_values = SanitizerSet::all()
1082 .into_iter()
1083 .map(|sanitizer| Symbol::intern(sanitizer.as_str().unwrap()));
1084
04454e1e
FG
1085 // Unknown possible values:
1086 // - `feature`
1087 // - `target_feature`
1088
5e7ed085
FG
1089 // No-values
1090 for name in [
1091 sym::doc,
1092 sym::miri,
1093 sym::unix,
1094 sym::test,
1095 sym::doctest,
1096 sym::windows,
1097 sym::proc_macro,
1098 sym::debug_assertions,
1099 sym::target_thread_local,
1100 ] {
1101 self.values_valid.entry(name).or_default();
1102 }
1103
1104 // Pre-defined values
1105 self.values_valid.entry(sym::panic).or_default().extend(panic_values);
1106 self.values_valid.entry(sym::sanitize).or_default().extend(sanitize_values);
1107 self.values_valid.entry(sym::target_has_atomic).or_default().extend(atomic_values);
1108 self.values_valid
1109 .entry(sym::target_has_atomic_load_store)
1110 .or_default()
1111 .extend(atomic_values);
1112 self.values_valid
1113 .entry(sym::target_has_atomic_equal_alignment)
1114 .or_default()
1115 .extend(atomic_values);
1116
1117 // Target specific values
5e7ed085 1118 {
923072b8
FG
1119 const VALUES: [&Symbol; 8] = [
1120 &sym::target_os,
1121 &sym::target_family,
1122 &sym::target_arch,
1123 &sym::target_endian,
1124 &sym::target_env,
1125 &sym::target_abi,
1126 &sym::target_vendor,
1127 &sym::target_pointer_width,
1128 ];
1129
1130 // Initialize (if not already initialized)
1131 for &e in VALUES {
1132 self.values_valid.entry(e).or_default();
1133 }
1134
1135 // Get all values map at once otherwise it would be costly.
1136 // (8 values * 220 targets ~= 1760 times, at the time of writing this comment).
1137 let [
1138 values_target_os,
1139 values_target_family,
1140 values_target_arch,
1141 values_target_endian,
1142 values_target_env,
1143 values_target_abi,
1144 values_target_vendor,
1145 values_target_pointer_width,
1146 ] = self
1147 .values_valid
1148 .get_many_mut(VALUES)
1149 .expect("unable to get all the check-cfg values buckets");
1150
1151 for target in TARGETS
1152 .iter()
1153 .map(|target| Target::expect_builtin(&TargetTriple::from_triple(target)))
1154 {
1155 values_target_os.insert(Symbol::intern(&target.options.os));
1156 values_target_family
1157 .extend(target.options.families.iter().map(|family| Symbol::intern(family)));
1158 values_target_arch.insert(Symbol::intern(&target.arch));
1159 values_target_endian.insert(Symbol::intern(&target.options.endian.as_str()));
1160 values_target_env.insert(Symbol::intern(&target.options.env));
1161 values_target_abi.insert(Symbol::intern(&target.options.abi));
1162 values_target_vendor.insert(Symbol::intern(&target.options.vendor));
1163 values_target_pointer_width.insert(sym::integer(target.pointer_width));
1164 }
5e7ed085
FG
1165 }
1166 }
1167
1168 pub fn fill_well_known(&mut self) {
1169 self.fill_well_known_names();
1170 self.fill_well_known_values();
1171 }
5099ac24
FG
1172}
1173
60c5eb7d 1174pub fn build_configuration(sess: &Session, mut user_cfg: CrateConfig) -> CrateConfig {
1a4d82fc 1175 // Combine the configuration requested by the session (command line) with
e1599b0c 1176 // some default and generated configuration items.
1a4d82fc 1177 let default_cfg = default_configuration(sess);
e1599b0c 1178 // If the user wants a test runner, then add the test cfg.
1a4d82fc 1179 if sess.opts.test {
dc9dc135 1180 user_cfg.insert((sym::test, None));
1a4d82fc 1181 }
476ff2be
SL
1182 user_cfg.extend(default_cfg.iter().cloned());
1183 user_cfg
1a4d82fc
JJ
1184}
1185
17df50a5
XL
1186pub(super) fn build_target_config(
1187 opts: &Options,
1188 target_override: Option<Target>,
3c0e092e 1189 sysroot: &Path,
17df50a5 1190) -> Target {
136023e0
XL
1191 let target_result = target_override.map_or_else(
1192 || Target::search(&opts.target_triple, sysroot),
1193 |t| Ok((t, TargetWarnings::empty())),
1194 );
1195 let (target, target_warnings) = target_result.unwrap_or_else(|e| {
ba9703b0 1196 early_error(
1b1a35ee 1197 opts.error_format,
ba9703b0
XL
1198 &format!(
1199 "Error loading target specification: {}. \
cdc7bbd5 1200 Run `rustc --print target-list` for a list of built-in targets",
ba9703b0
XL
1201 e
1202 ),
1203 )
0bf4aa26 1204 });
136023e0
XL
1205 for warning in target_warnings.warning_messages() {
1206 early_warn(opts.error_format, &warning)
1207 }
1a4d82fc 1208
29967ef6
XL
1209 if !matches!(target.pointer_width, 16 | 32 | 64) {
1210 early_error(
1b1a35ee 1211 opts.error_format,
ba9703b0 1212 &format!(
dfeec247 1213 "target specification was invalid: \
0531ce1d 1214 unrecognized target-pointer-width {}",
29967ef6 1215 target.pointer_width
ba9703b0 1216 ),
29967ef6
XL
1217 )
1218 }
1a4d82fc 1219
29967ef6 1220 target
1a4d82fc
JJ
1221}
1222
85aaf69f 1223#[derive(Copy, Clone, PartialEq, Eq, Debug)]
7453a54e
SL
1224pub enum OptionStability {
1225 Stable,
7453a54e
SL
1226 Unstable,
1227}
1a4d82fc 1228
1a4d82fc 1229pub struct RustcOptGroup {
0531ce1d 1230 pub apply: Box<dyn Fn(&mut getopts::Options) -> &mut getopts::Options>,
041b39d2 1231 pub name: &'static str,
1a4d82fc
JJ
1232 pub stability: OptionStability,
1233}
1234
1235impl RustcOptGroup {
1236 pub fn is_stable(&self) -> bool {
1237 self.stability == OptionStability::Stable
1238 }
1239
041b39d2 1240 pub fn stable<F>(name: &'static str, f: F) -> RustcOptGroup
0531ce1d
XL
1241 where
1242 F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static,
041b39d2 1243 {
dfeec247 1244 RustcOptGroup { name, apply: Box::new(f), stability: OptionStability::Stable }
1a4d82fc
JJ
1245 }
1246
041b39d2 1247 pub fn unstable<F>(name: &'static str, f: F) -> RustcOptGroup
0531ce1d
XL
1248 where
1249 F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static,
041b39d2 1250 {
dfeec247 1251 RustcOptGroup { name, apply: Box::new(f), stability: OptionStability::Unstable }
1a4d82fc
JJ
1252 }
1253}
1254
1255// The `opt` local module holds wrappers around the `getopts` API that
1256// adds extra rustc-specific metadata to each option; such metadata
1257// is exposed by . The public
1258// functions below ending with `_u` are the functions that return
0731742a 1259// *unstable* options, i.e., options that are only enabled when the
1a4d82fc
JJ
1260// user also passes the `-Z unstable-options` debugging flag.
1261mod opt {
416331ca 1262 // The `fn flag*` etc below are written so that we can use them
1a4d82fc
JJ
1263 // in the future; do not warn about them not being used right now.
1264 #![allow(dead_code)]
1265
1a4d82fc
JJ
1266 use super::RustcOptGroup;
1267
c34b1796 1268 pub type R = RustcOptGroup;
041b39d2
XL
1269 pub type S = &'static str;
1270
1271 fn stable<F>(name: S, f: F) -> R
0531ce1d
XL
1272 where
1273 F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static,
041b39d2
XL
1274 {
1275 RustcOptGroup::stable(name, f)
1276 }
1277
1278 fn unstable<F>(name: S, f: F) -> R
0531ce1d
XL
1279 where
1280 F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static,
041b39d2
XL
1281 {
1282 RustcOptGroup::unstable(name, f)
1283 }
1a4d82fc 1284
041b39d2 1285 fn longer(a: S, b: S) -> S {
dfeec247 1286 if a.len() > b.len() { a } else { b }
041b39d2 1287 }
1a4d82fc 1288
7453a54e 1289 pub fn opt_s(a: S, b: S, c: S, d: S) -> R {
041b39d2 1290 stable(longer(a, b), move |opts| opts.optopt(a, b, c, d))
7453a54e
SL
1291 }
1292 pub fn multi_s(a: S, b: S, c: S, d: S) -> R {
041b39d2 1293 stable(longer(a, b), move |opts| opts.optmulti(a, b, c, d))
7453a54e
SL
1294 }
1295 pub fn flag_s(a: S, b: S, c: S) -> R {
041b39d2 1296 stable(longer(a, b), move |opts| opts.optflag(a, b, c))
7453a54e 1297 }
7453a54e 1298 pub fn flagmulti_s(a: S, b: S, c: S) -> R {
041b39d2 1299 stable(longer(a, b), move |opts| opts.optflagmulti(a, b, c))
7453a54e 1300 }
d9579d0f 1301
7453a54e 1302 pub fn opt(a: S, b: S, c: S, d: S) -> R {
041b39d2 1303 unstable(longer(a, b), move |opts| opts.optopt(a, b, c, d))
7453a54e
SL
1304 }
1305 pub fn multi(a: S, b: S, c: S, d: S) -> R {
041b39d2 1306 unstable(longer(a, b), move |opts| opts.optmulti(a, b, c, d))
7453a54e 1307 }
1a4d82fc
JJ
1308}
1309
1310/// Returns the "short" subset of the rustc command line options,
1311/// including metadata for each option, such as whether the option is
1312/// part of the stable long-term interface for rustc.
1313pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
1314 vec![
7453a54e
SL
1315 opt::flag_s("h", "help", "Display this message"),
1316 opt::multi_s("", "cfg", "Configure the compilation environment", "SPEC"),
5099ac24 1317 opt::multi("", "check-cfg", "Provide list of valid cfg options for checking", "SPEC"),
0531ce1d
XL
1318 opt::multi_s(
1319 "L",
1320 "",
1321 "Add a directory to the library search path. The
a7813a04 1322 optional KIND can be one of dependency, crate, native,
416331ca 1323 framework, or all (the default).",
0531ce1d
XL
1324 "[KIND=]PATH",
1325 ),
1326 opt::multi_s(
1327 "l",
1328 "",
1329 "Link the generated crate(s) to the specified native
a7813a04 1330 library NAME. The optional KIND can be one of
17df50a5
XL
1331 static, framework, or dylib (the default).
1332 Optional comma separated MODIFIERS (bundle|verbatim|whole-archive|as-needed)
1333 may be specified each with a prefix of either '+' to
1334 enable or '-' to disable.",
1335 "[KIND[:MODIFIERS]=]NAME[:RENAME]",
0531ce1d 1336 ),
e1599b0c 1337 make_crate_type_option(),
dfeec247 1338 opt::opt_s("", "crate-name", "Specify the name of the crate being built", "NAME"),
532ac7d7
XL
1339 opt::opt_s(
1340 "",
1341 "edition",
1342 "Specify which edition of the compiler to use when compiling code.",
1343 EDITION_NAME_LIST,
1344 ),
0531ce1d
XL
1345 opt::multi_s(
1346 "",
1347 "emit",
1348 "Comma separated list of types of output for \
1349 the compiler to emit",
1350 "[asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir]",
1351 ),
1352 opt::multi_s(
1353 "",
1354 "print",
48663c56 1355 "Compiler information to print on stdout",
74b04a01 1356 "[crate-name|file-names|sysroot|target-libdir|cfg|target-list|\
3c0e092e 1357 target-cpus|target-features|relocation-models|code-models|\
5099ac24
FG
1358 tls-models|target-spec-json|native-static-libs|stack-protector-strategies|\
1359 link-args]",
0531ce1d
XL
1360 ),
1361 opt::flagmulti_s("g", "", "Equivalent to -C debuginfo=2"),
7453a54e
SL
1362 opt::flagmulti_s("O", "", "Equivalent to -C opt-level=2"),
1363 opt::opt_s("o", "", "Write output to <filename>", "FILENAME"),
0531ce1d
XL
1364 opt::opt_s(
1365 "",
1366 "out-dir",
1367 "Write output to compiler-chosen filename \
1368 in <dir>",
1369 "DIR",
1370 ),
1371 opt::opt_s(
1372 "",
1373 "explain",
1374 "Provide a detailed explanation of an error \
1375 message",
1376 "OPT",
1377 ),
7453a54e 1378 opt::flag_s("", "test", "Build a test harness"),
dfeec247 1379 opt::opt_s("", "target", "Target triple for which the code is compiled", "TARGET"),
94222f64
XL
1380 opt::multi_s("A", "allow", "Set lint allowed", "LINT"),
1381 opt::multi_s("W", "warn", "Set lint warnings", "LINT"),
1382 opt::multi_s("", "force-warn", "Set lint force-warn", "LINT"),
1383 opt::multi_s("D", "deny", "Set lint denied", "LINT"),
1384 opt::multi_s("F", "forbid", "Set lint forbidden", "LINT"),
0531ce1d
XL
1385 opt::multi_s(
1386 "",
1387 "cap-lints",
1388 "Set the most restrictive lint level. \
1389 More restrictive lints are capped at this \
1390 level",
1391 "LEVEL",
1392 ),
7453a54e
SL
1393 opt::multi_s("C", "codegen", "Set a codegen option", "OPT[=VALUE]"),
1394 opt::flag_s("V", "version", "Print version info and exit"),
1395 opt::flag_s("v", "verbose", "Use verbose output"),
1a4d82fc
JJ
1396 ]
1397}
1398
1399/// Returns all rustc command line options, including metadata for
1400/// each option, such as whether the option is part of the stable
1401/// long-term interface for rustc.
1402pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
1403 let mut opts = rustc_short_optgroups();
064997fb 1404 // FIXME: none of these descriptions are actually used
041b39d2 1405 opts.extend(vec![
0531ce1d
XL
1406 opt::multi_s(
1407 "",
1408 "extern",
1409 "Specify where an external rust library is located",
60c5eb7d 1410 "NAME[=PATH]",
9fa01778 1411 ),
7453a54e 1412 opt::opt_s("", "sysroot", "Override the system root", "PATH"),
064997fb 1413 opt::multi("Z", "", "Set unstable / perma-unstable options", "FLAG"),
0531ce1d
XL
1414 opt::opt_s(
1415 "",
1416 "error-format",
1417 "How errors and other messages are produced",
1418 "human|json|short",
1419 ),
dfeec247 1420 opt::multi_s("", "json", "Configure the JSON output of the compiler", "CONFIG"),
0531ce1d
XL
1421 opt::opt_s(
1422 "",
1423 "color",
1424 "Configure coloring of output:
54a0048b
SL
1425 auto = colorize, if output goes to a tty (default);
1426 always = always colorize output;
0531ce1d
XL
1427 never = never colorize output",
1428 "auto|always|never",
1429 ),
064997fb
FG
1430 opt::opt_s(
1431 "",
1432 "diagnostic-width",
1433 "Inform rustc of the width of the output so that diagnostics can be truncated to fit",
1434 "WIDTH",
1435 ),
0531ce1d
XL
1436 opt::multi_s(
1437 "",
1438 "remap-path-prefix",
1439 "Remap source names in all output (compiler messages and output files)",
1440 "FROM=TO",
1441 ),
1a4d82fc
JJ
1442 ]);
1443 opts
1444}
1445
dfeec247
XL
1446pub fn get_cmd_lint_options(
1447 matches: &getopts::Matches,
1448 error_format: ErrorOutputType,
136023e0 1449) -> (Vec<(String, lint::Level)>, bool, Option<lint::Level>) {
74b04a01 1450 let mut lint_opts_with_position = vec![];
8faf50e0
XL
1451 let mut describe_lints = false;
1452
923072b8 1453 for level in [lint::Allow, lint::Warn, lint::ForceWarn(None), lint::Deny, lint::Forbid] {
136023e0 1454 for (arg_pos, lint_name) in matches.opt_strs_pos(level.as_str()) {
8faf50e0
XL
1455 if lint_name == "help" {
1456 describe_lints = true;
1457 } else {
a2a8927a 1458 lint_opts_with_position.push((arg_pos, lint_name.replace('-', "_"), level));
8faf50e0
XL
1459 }
1460 }
1461 }
1462
74b04a01
XL
1463 lint_opts_with_position.sort_by_key(|x| x.0);
1464 let lint_opts = lint_opts_with_position
1465 .iter()
1466 .cloned()
1467 .map(|(_, lint_name, level)| (lint_name, level))
1468 .collect();
1469
8faf50e0
XL
1470 let lint_cap = matches.opt_str("cap-lints").map(|cap| {
1471 lint::Level::from_str(&cap)
5e7ed085 1472 .unwrap_or_else(|| early_error(error_format, &format!("unknown lint level: `{cap}`")))
8faf50e0 1473 });
17df50a5 1474
136023e0 1475 (lint_opts, describe_lints, lint_cap)
8faf50e0
XL
1476}
1477
e1599b0c 1478/// Parses the `--color` flag.
416331ca
XL
1479pub fn parse_color(matches: &getopts::Matches) -> ColorConfig {
1480 match matches.opt_str("color").as_ref().map(|s| &s[..]) {
0531ce1d 1481 Some("auto") => ColorConfig::Auto,
9cc50fc6 1482 Some("always") => ColorConfig::Always,
0531ce1d 1483 Some("never") => ColorConfig::Never,
e9174d1e 1484
9cc50fc6 1485 None => ColorConfig::Auto,
e9174d1e 1486
0531ce1d
XL
1487 Some(arg) => early_error(
1488 ErrorOutputType::default(),
1489 &format!(
e1599b0c 1490 "argument for `--color` must be auto, \
5e7ed085 1491 always or never (instead was `{arg}`)"
0531ce1d
XL
1492 ),
1493 ),
416331ca
XL
1494 }
1495}
9cc50fc6 1496
cdc7bbd5
XL
1497/// Possible json config files
1498pub struct JsonConfig {
1499 pub json_rendered: HumanReadableErrorType,
1500 pub json_artifact_notifications: bool,
04454e1e 1501 pub json_unused_externs: JsonUnusedExterns,
a2a8927a 1502 pub json_future_incompat: bool,
cdc7bbd5
XL
1503}
1504
04454e1e
FG
1505/// Report unused externs in event stream
1506#[derive(Copy, Clone)]
1507pub enum JsonUnusedExterns {
1508 /// Do not
1509 No,
1510 /// Report, but do not exit with failure status for deny/forbid
1511 Silent,
1512 /// Report, and also exit with failure status for deny/forbid
1513 Loud,
1514}
1515
1516impl JsonUnusedExterns {
1517 pub fn is_enabled(&self) -> bool {
1518 match self {
1519 JsonUnusedExterns::No => false,
1520 JsonUnusedExterns::Loud | JsonUnusedExterns::Silent => true,
1521 }
1522 }
1523
1524 pub fn is_loud(&self) -> bool {
1525 match self {
1526 JsonUnusedExterns::No | JsonUnusedExterns::Silent => false,
1527 JsonUnusedExterns::Loud => true,
1528 }
1529 }
1530}
1531
416331ca
XL
1532/// Parse the `--json` flag.
1533///
1534/// The first value returned is how to render JSON diagnostics, and the second
1535/// is whether or not artifact notifications are enabled.
cdc7bbd5 1536pub fn parse_json(matches: &getopts::Matches) -> JsonConfig {
416331ca
XL
1537 let mut json_rendered: fn(ColorConfig) -> HumanReadableErrorType =
1538 HumanReadableErrorType::Default;
1539 let mut json_color = ColorConfig::Never;
1540 let mut json_artifact_notifications = false;
04454e1e 1541 let mut json_unused_externs = JsonUnusedExterns::No;
a2a8927a 1542 let mut json_future_incompat = false;
416331ca
XL
1543 for option in matches.opt_strs("json") {
1544 // For now conservatively forbid `--color` with `--json` since `--json`
1545 // won't actually be emitting any colors and anything colorized is
1546 // embedded in a diagnostic message anyway.
1547 if matches.opt_str("color").is_some() {
0bf4aa26 1548 early_error(
83c7162d 1549 ErrorOutputType::default(),
416331ca
XL
1550 "cannot specify the `--color` option with `--json`",
1551 );
1552 }
83c7162d 1553
416331ca
XL
1554 for sub_option in option.split(',') {
1555 match sub_option {
1556 "diagnostic-short" => json_rendered = HumanReadableErrorType::Short,
1557 "diagnostic-rendered-ansi" => json_color = ColorConfig::Always,
1558 "artifacts" => json_artifact_notifications = true,
04454e1e
FG
1559 "unused-externs" => json_unused_externs = JsonUnusedExterns::Loud,
1560 "unused-externs-silent" => json_unused_externs = JsonUnusedExterns::Silent,
a2a8927a 1561 "future-incompat" => json_future_incompat = true,
dfeec247
XL
1562 s => early_error(
1563 ErrorOutputType::default(),
5e7ed085 1564 &format!("unknown `--json` option `{s}`"),
dfeec247 1565 ),
416331ca
XL
1566 }
1567 }
83c7162d 1568 }
cdc7bbd5
XL
1569
1570 JsonConfig {
1571 json_rendered: json_rendered(json_color),
1572 json_artifact_notifications,
1573 json_unused_externs,
a2a8927a 1574 json_future_incompat,
cdc7bbd5 1575 }
416331ca 1576}
83c7162d 1577
e1599b0c 1578/// Parses the `--error-format` flag.
416331ca
XL
1579pub fn parse_error_format(
1580 matches: &getopts::Matches,
1581 color: ColorConfig,
1582 json_rendered: HumanReadableErrorType,
1583) -> ErrorOutputType {
e1599b0c 1584 // We need the `opts_present` check because the driver will send us Matches
9cc50fc6 1585 // with only stable options if no unstable options are used. Since error-format
e1599b0c
XL
1586 // is unstable, it will not be present. We have to use `opts_present` not
1587 // `opt_present` because the latter will panic.
9cc50fc6
SL
1588 let error_format = if matches.opts_present(&["error-format".to_owned()]) {
1589 match matches.opt_str("error-format").as_ref().map(|s| &s[..]) {
dfeec247
XL
1590 None | Some("human") => {
1591 ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color))
1592 }
dc9dc135
XL
1593 Some("human-annotate-rs") => {
1594 ErrorOutputType::HumanReadable(HumanReadableErrorType::AnnotateSnippet(color))
dfeec247 1595 }
48663c56
XL
1596 Some("json") => ErrorOutputType::Json { pretty: false, json_rendered },
1597 Some("pretty-json") => ErrorOutputType::Json { pretty: true, json_rendered },
1598 Some("short") => ErrorOutputType::HumanReadable(HumanReadableErrorType::Short(color)),
9cc50fc6 1599
0531ce1d 1600 Some(arg) => early_error(
48663c56 1601 ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)),
0531ce1d 1602 &format!(
e1599b0c 1603 "argument for `--error-format` must be `human`, `json` or \
5e7ed085 1604 `short` (instead was `{arg}`)"
0531ce1d
XL
1605 ),
1606 ),
e9174d1e 1607 }
9cc50fc6 1608 } else {
48663c56 1609 ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color))
e9174d1e
SL
1610 };
1611
416331ca
XL
1612 match error_format {
1613 ErrorOutputType::Json { .. } => {}
1614
1615 // Conservatively require that the `--json` argument is coupled with
1616 // `--error-format=json`. This means that `--json` is specified we
1617 // should actually be emitting JSON blobs.
74b04a01 1618 _ if !matches.opt_strs("json").is_empty() => {
416331ca
XL
1619 early_error(
1620 ErrorOutputType::default(),
1621 "using `--json` requires also using `--error-format=json`",
1622 );
1623 }
1624
1625 _ => {}
1626 }
1627
ba9703b0 1628 error_format
416331ca
XL
1629}
1630
5869c6ff 1631pub fn parse_crate_edition(matches: &getopts::Matches) -> Edition {
416331ca 1632 let edition = match matches.opt_str("edition") {
dfeec247 1633 Some(arg) => Edition::from_str(&arg).unwrap_or_else(|_| {
416331ca
XL
1634 early_error(
1635 ErrorOutputType::default(),
1636 &format!(
e1599b0c 1637 "argument for `--edition` must be one of: \
5e7ed085 1638 {EDITION_NAME_LIST}. (instead was `{arg}`)"
416331ca 1639 ),
dfeec247
XL
1640 )
1641 }),
416331ca
XL
1642 None => DEFAULT_EDITION,
1643 };
1644
5869c6ff 1645 if !edition.is_stable() && !nightly_options::is_unstable_enabled(matches) {
cdc7bbd5
XL
1646 let is_nightly = nightly_options::match_is_nightly_build(matches);
1647 let msg = if !is_nightly {
1648 format!(
1649 "the crate requires edition {}, but the latest edition supported by this Rust version is {}",
1650 edition, LATEST_STABLE_EDITION
1651 )
1652 } else {
5e7ed085 1653 format!("edition {edition} is unstable and only available with -Z unstable-options")
cdc7bbd5
XL
1654 };
1655 early_error(ErrorOutputType::default(), &msg)
416331ca
XL
1656 }
1657
e74abb32
XL
1658 edition
1659}
abe05a73 1660
064997fb
FG
1661fn check_error_format_stability(
1662 unstable_opts: &UnstableOptions,
e74abb32
XL
1663 error_format: ErrorOutputType,
1664 json_rendered: HumanReadableErrorType,
1665) {
064997fb 1666 if !unstable_opts.unstable_options {
48663c56
XL
1667 if let ErrorOutputType::Json { pretty: true, json_rendered } = error_format {
1668 early_error(
1669 ErrorOutputType::Json { pretty: false, json_rendered },
e1599b0c 1670 "`--error-format=pretty-json` is unstable",
48663c56
XL
1671 );
1672 }
dc9dc135 1673 if let ErrorOutputType::HumanReadable(HumanReadableErrorType::AnnotateSnippet(_)) =
dfeec247
XL
1674 error_format
1675 {
dc9dc135
XL
1676 early_error(
1677 ErrorOutputType::Json { pretty: false, json_rendered },
e1599b0c 1678 "`--error-format=human-annotate-rs` is unstable",
dc9dc135
XL
1679 );
1680 }
abe05a73 1681 }
e74abb32 1682}
1a4d82fc 1683
e74abb32 1684fn parse_output_types(
064997fb 1685 unstable_opts: &UnstableOptions,
e74abb32
XL
1686 matches: &getopts::Matches,
1687 error_format: ErrorOutputType,
1688) -> OutputTypes {
5bcae85e 1689 let mut output_types = BTreeMap::new();
064997fb 1690 if !unstable_opts.parse_only {
b039eaaf
SL
1691 for list in matches.opt_strs("emit") {
1692 for output_type in list.split(',') {
fc512014
XL
1693 let (shorthand, path) = match output_type.split_once('=') {
1694 None => (output_type, None),
1695 Some((shorthand, path)) => (shorthand, Some(PathBuf::from(path))),
1696 };
dfeec247 1697 let output_type = OutputType::from_shorthand(shorthand).unwrap_or_else(|| {
0bf4aa26 1698 early_error(
0531ce1d
XL
1699 error_format,
1700 &format!(
5e7ed085
FG
1701 "unknown emission type: `{shorthand}` - expected one of: {display}",
1702 display = OutputType::shorthands_display(),
0531ce1d 1703 ),
dfeec247
XL
1704 )
1705 });
b039eaaf 1706 output_types.insert(output_type, path);
1a4d82fc
JJ
1707 }
1708 }
1709 };
7cac9316 1710 if output_types.is_empty() {
b039eaaf 1711 output_types.insert(OutputType::Exe, None);
1a4d82fc 1712 }
e74abb32
XL
1713 OutputTypes(output_types)
1714}
1a4d82fc 1715
e74abb32
XL
1716fn should_override_cgus_and_disable_thinlto(
1717 output_types: &OutputTypes,
1718 matches: &getopts::Matches,
1719 error_format: ErrorOutputType,
1720 mut codegen_units: Option<usize>,
1721) -> (bool, Option<usize>) {
2c00a5a8 1722 let mut disable_thinlto = false;
e1599b0c 1723 // Issue #30063: if user requests LLVM-related output to one
92a42be0 1724 // particular path, disable codegen-units.
dfeec247
XL
1725 let incompatible: Vec<_> = output_types
1726 .0
0531ce1d 1727 .iter()
ea8adc8c 1728 .map(|ot_path| ot_path.0)
0531ce1d 1729 .filter(|ot| !ot.is_compatible_with_codegen_units_and_single_output_file())
ea8adc8c
XL
1730 .map(|ot| ot.shorthand())
1731 .collect();
1732 if !incompatible.is_empty() {
1733 match codegen_units {
1734 Some(n) if n > 1 => {
1735 if matches.opt_present("o") {
1736 for ot in &incompatible {
0531ce1d
XL
1737 early_warn(
1738 error_format,
1739 &format!(
5e7ed085 1740 "`--emit={ot}` with `-o` incompatible with \
e1599b0c 1741 `-C codegen-units=N` for N > 1",
0531ce1d
XL
1742 ),
1743 );
ea8adc8c
XL
1744 }
1745 early_warn(error_format, "resetting to default -C codegen-units=1");
1746 codegen_units = Some(1);
2c00a5a8 1747 disable_thinlto = true;
ea8adc8c 1748 }
92a42be0 1749 }
ff7c6d11
XL
1750 _ => {
1751 codegen_units = Some(1);
2c00a5a8 1752 disable_thinlto = true;
ff7c6d11 1753 }
92a42be0
SL
1754 }
1755 }
1756
e74abb32 1757 if codegen_units == Some(0) {
dfeec247 1758 early_error(error_format, "value for codegen units must be a positive non-zero integer");
ff7c6d11
XL
1759 }
1760
e74abb32
XL
1761 (disable_thinlto, codegen_units)
1762}
1763
064997fb
FG
1764fn check_thread_count(unstable_opts: &UnstableOptions, error_format: ErrorOutputType) {
1765 if unstable_opts.threads == 0 {
dfeec247 1766 early_error(error_format, "value for threads must be a positive non-zero integer");
83c7162d
XL
1767 }
1768
064997fb 1769 if unstable_opts.threads > 1 && unstable_opts.fuel.is_some() {
dfeec247 1770 early_error(error_format, "optimization fuel is incompatible with multiple threads");
54a0048b 1771 }
e74abb32 1772}
54a0048b 1773
e74abb32
XL
1774fn collect_print_requests(
1775 cg: &mut CodegenOptions,
064997fb 1776 unstable_opts: &mut UnstableOptions,
e74abb32 1777 matches: &getopts::Matches,
e74abb32
XL
1778 error_format: ErrorOutputType,
1779) -> Vec<PrintRequest> {
5bcae85e
SL
1780 let mut prints = Vec::<PrintRequest>::new();
1781 if cg.target_cpu.as_ref().map_or(false, |s| s == "help") {
1782 prints.push(PrintRequest::TargetCPUs);
1783 cg.target_cpu = None;
1784 };
1785 if cg.target_feature == "help" {
1786 prints.push(PrintRequest::TargetFeatures);
b7449926 1787 cg.target_feature = String::new();
5bcae85e 1788 }
5bcae85e 1789
e74abb32
XL
1790 prints.extend(matches.opt_strs("print").into_iter().map(|s| match &*s {
1791 "crate-name" => PrintRequest::CrateName,
1792 "file-names" => PrintRequest::FileNames,
1793 "sysroot" => PrintRequest::Sysroot,
74b04a01 1794 "target-libdir" => PrintRequest::TargetLibdir,
e74abb32
XL
1795 "cfg" => PrintRequest::Cfg,
1796 "target-list" => PrintRequest::TargetList,
1797 "target-cpus" => PrintRequest::TargetCPUs,
1798 "target-features" => PrintRequest::TargetFeatures,
1799 "relocation-models" => PrintRequest::RelocationModels,
1800 "code-models" => PrintRequest::CodeModels,
1801 "tls-models" => PrintRequest::TlsModels,
1802 "native-static-libs" => PrintRequest::NativeStaticLibs,
3c0e092e 1803 "stack-protector-strategies" => PrintRequest::StackProtectorStrategies,
e74abb32 1804 "target-spec-json" => {
064997fb 1805 if unstable_opts.unstable_options {
e74abb32
XL
1806 PrintRequest::TargetSpec
1807 } else {
1808 early_error(
1809 error_format,
1810 "the `-Z unstable-options` flag must also be passed to \
1811 enable the target-spec-json print option",
1812 );
1813 }
1814 }
5099ac24 1815 "link-args" => PrintRequest::LinkArgs,
5e7ed085 1816 req => early_error(error_format, &format!("unknown print request `{req}`")),
e74abb32 1817 }));
1a4d82fc 1818
e74abb32
XL
1819 prints
1820}
1821
17df50a5
XL
1822pub fn parse_target_triple(
1823 matches: &getopts::Matches,
1824 error_format: ErrorOutputType,
1825) -> TargetTriple {
e74abb32
XL
1826 match matches.opt_str("target") {
1827 Some(target) if target.ends_with(".json") => {
0531ce1d 1828 let path = Path::new(&target);
dfeec247 1829 TargetTriple::from_path(&path).unwrap_or_else(|_| {
5e7ed085 1830 early_error(error_format, &format!("target file {path:?} does not exist"))
dfeec247 1831 })
e74abb32 1832 }
6a06907d 1833 Some(target) => TargetTriple::TargetTriple(target),
e74abb32
XL
1834 _ => TargetTriple::from_triple(host_triple()),
1835 }
1836}
1837
1838fn parse_opt_level(
1839 matches: &getopts::Matches,
1840 cg: &CodegenOptions,
1841 error_format: ErrorOutputType,
1842) -> OptLevel {
1843 // The `-O` and `-C opt-level` flags specify the same setting, so we want to be able
1844 // to use them interchangeably. However, because they're technically different flags,
1845 // we need to work out manually which should take precedence if both are supplied (i.e.
1846 // the rightmost flag). We do this by finding the (rightmost) position of both flags and
1847 // comparing them. Note that if a flag is not found, its position will be `None`, which
1848 // always compared less than `Some(_)`.
1849 let max_o = matches.opt_positions("O").into_iter().max();
dfeec247
XL
1850 let max_c = matches
1851 .opt_strs_pos("C")
1852 .into_iter()
fc512014
XL
1853 .flat_map(|(i, s)| {
1854 // NB: This can match a string without `=`.
1855 if let Some("opt-level") = s.splitn(2, '=').next() { Some(i) } else { None }
1856 })
dfeec247 1857 .max();
e74abb32
XL
1858 if max_o > max_c {
1859 OptLevel::Default
0531ce1d 1860 } else {
ba9703b0
XL
1861 match cg.opt_level.as_ref() {
1862 "0" => OptLevel::No,
1863 "1" => OptLevel::Less,
1864 "2" => OptLevel::Default,
1865 "3" => OptLevel::Aggressive,
1866 "s" => OptLevel::Size,
1867 "z" => OptLevel::SizeMin,
1868 arg => {
e74abb32
XL
1869 early_error(
1870 error_format,
1871 &format!(
1872 "optimization level needs to be \
5e7ed085 1873 between 0-3, s or z (instead was `{arg}`)"
e74abb32
XL
1874 ),
1875 );
1a4d82fc
JJ
1876 }
1877 }
e74abb32
XL
1878 }
1879}
1880
1881fn select_debuginfo(
1882 matches: &getopts::Matches,
1883 cg: &CodegenOptions,
1884 error_format: ErrorOutputType,
1885) -> DebugInfo {
48663c56 1886 let max_g = matches.opt_positions("g").into_iter().max();
dfeec247
XL
1887 let max_c = matches
1888 .opt_strs_pos("C")
1889 .into_iter()
fc512014
XL
1890 .flat_map(|(i, s)| {
1891 // NB: This can match a string without `=`.
1892 if let Some("debuginfo") = s.splitn(2, '=').next() { Some(i) } else { None }
1893 })
dfeec247 1894 .max();
e74abb32 1895 if max_g > max_c {
b7449926 1896 DebugInfo::Full
1a4d82fc
JJ
1897 } else {
1898 match cg.debuginfo {
ba9703b0
XL
1899 0 => DebugInfo::None,
1900 1 => DebugInfo::Limited,
1901 2 => DebugInfo::Full,
1902 arg => {
0531ce1d
XL
1903 early_error(
1904 error_format,
1905 &format!(
1906 "debug info level needs to be between \
5e7ed085 1907 0-2 (instead was `{arg}`)"
0531ce1d
XL
1908 ),
1909 );
1a4d82fc
JJ
1910 }
1911 }
1a4d82fc 1912 }
e74abb32 1913}
1a4d82fc 1914
923072b8 1915pub(crate) fn parse_assert_incr_state(
3c0e092e
XL
1916 opt_assertion: &Option<String>,
1917 error_format: ErrorOutputType,
1918) -> Option<IncrementalStateAssertion> {
1919 match opt_assertion {
1920 Some(s) if s.as_str() == "loaded" => Some(IncrementalStateAssertion::Loaded),
1921 Some(s) if s.as_str() == "not-loaded" => Some(IncrementalStateAssertion::NotLoaded),
5e7ed085
FG
1922 Some(s) => {
1923 early_error(error_format, &format!("unexpected incremental state assertion value: {s}"))
1924 }
3c0e092e
XL
1925 None => None,
1926 }
1927}
1928
94222f64
XL
1929fn parse_native_lib_kind(
1930 matches: &getopts::Matches,
1931 kind: &str,
1932 error_format: ErrorOutputType,
1933) -> (NativeLibKind, Option<bool>) {
94222f64
XL
1934 let (kind, modifiers) = match kind.split_once(':') {
1935 None => (kind, None),
1936 Some((kind, modifiers)) => (kind, Some(modifiers)),
1937 };
1938
1939 let kind = match kind {
923072b8 1940 "static" => NativeLibKind::Static { bundle: None, whole_archive: None },
17df50a5
XL
1941 "dylib" => NativeLibKind::Dylib { as_needed: None },
1942 "framework" => NativeLibKind::Framework { as_needed: None },
064997fb
FG
1943 "link-arg" => {
1944 if !nightly_options::is_unstable_enabled(matches) {
1945 let why = if nightly_options::match_is_nightly_build(matches) {
1946 " and only accepted on the nightly compiler"
1947 } else {
1948 ", the `-Z unstable-options` flag must also be passed to use it"
1949 };
1950 early_error(error_format, &format!("library kind `link-arg` is unstable{why}"))
1951 }
1952 NativeLibKind::LinkArg
1953 }
923072b8 1954 _ => early_error(
17df50a5 1955 error_format,
064997fb
FG
1956 &format!(
1957 "unknown library kind `{kind}`, expected one of: static, dylib, framework, link-arg"
1958 ),
17df50a5 1959 ),
94222f64
XL
1960 };
1961 match modifiers {
1962 None => (kind, None),
5e7ed085 1963 Some(modifiers) => parse_native_lib_modifiers(kind, modifiers, error_format, matches),
17df50a5
XL
1964 }
1965}
1966
1967fn parse_native_lib_modifiers(
17df50a5
XL
1968 mut kind: NativeLibKind,
1969 modifiers: &str,
e74abb32 1970 error_format: ErrorOutputType,
5e7ed085 1971 matches: &getopts::Matches,
17df50a5
XL
1972) -> (NativeLibKind, Option<bool>) {
1973 let mut verbatim = None;
1974 for modifier in modifiers.split(',') {
a2a8927a 1975 let (modifier, value) = match modifier.strip_prefix(&['+', '-']) {
17df50a5
XL
1976 Some(m) => (m, modifier.starts_with('+')),
1977 None => early_error(
1978 error_format,
1979 "invalid linking modifier syntax, expected '+' or '-' prefix \
923072b8 1980 before one of: bundle, verbatim, whole-archive, as-needed",
17df50a5
XL
1981 ),
1982 };
1983
923072b8
FG
1984 let report_unstable_modifier = || {
1985 if !nightly_options::is_unstable_enabled(matches) {
1986 let why = if nightly_options::match_is_nightly_build(matches) {
1987 " and only accepted on the nightly compiler"
1988 } else {
1989 ", the `-Z unstable-options` flag must also be passed to use it"
1990 };
1991 early_error(
1992 error_format,
1993 &format!("linking modifier `{modifier}` is unstable{why}"),
1994 )
1995 }
1996 };
1997 let assign_modifier = |dst: &mut Option<bool>| {
1998 if dst.is_some() {
1999 let msg = format!("multiple `{modifier}` modifiers in a single `-l` option");
2000 early_error(error_format, &msg)
2001 } else {
2002 *dst = Some(value);
17df50a5 2003 }
923072b8
FG
2004 };
2005 match (modifier, &mut kind) {
2006 ("bundle", NativeLibKind::Static { bundle, .. }) => assign_modifier(bundle),
17df50a5
XL
2007 ("bundle", _) => early_error(
2008 error_format,
923072b8 2009 "linking modifier `bundle` is only compatible with `static` linking kind",
17df50a5
XL
2010 ),
2011
5e7ed085 2012 ("verbatim", _) => {
923072b8
FG
2013 report_unstable_modifier();
2014 assign_modifier(&mut verbatim)
5e7ed085 2015 }
17df50a5
XL
2016
2017 ("whole-archive", NativeLibKind::Static { whole_archive, .. }) => {
923072b8 2018 assign_modifier(whole_archive)
17df50a5
XL
2019 }
2020 ("whole-archive", _) => early_error(
2021 error_format,
923072b8 2022 "linking modifier `whole-archive` is only compatible with `static` linking kind",
17df50a5
XL
2023 ),
2024
2025 ("as-needed", NativeLibKind::Dylib { as_needed })
2026 | ("as-needed", NativeLibKind::Framework { as_needed }) => {
923072b8
FG
2027 report_unstable_modifier();
2028 assign_modifier(as_needed)
17df50a5
XL
2029 }
2030 ("as-needed", _) => early_error(
2031 error_format,
923072b8
FG
2032 "linking modifier `as-needed` is only compatible with \
2033 `dylib` and `framework` linking kinds",
17df50a5
XL
2034 ),
2035
5e7ed085
FG
2036 // Note: this error also excludes the case with empty modifier
2037 // string, like `modifiers = ""`.
17df50a5
XL
2038 _ => early_error(
2039 error_format,
2040 &format!(
923072b8
FG
2041 "unknown linking modifier `{modifier}`, expected one \
2042 of: bundle, verbatim, whole-archive, as-needed"
17df50a5
XL
2043 ),
2044 ),
2045 }
2046 }
2047
2048 (kind, verbatim)
2049}
2050
2051fn parse_libs(matches: &getopts::Matches, error_format: ErrorOutputType) -> Vec<NativeLib> {
e74abb32 2052 matches
0531ce1d
XL
2053 .opt_strs("l")
2054 .into_iter()
2055 .map(|s| {
17df50a5 2056 // Parse string of the form "[KIND[:MODIFIERS]=]lib[:new_name]",
064997fb 2057 // where KIND is one of "dylib", "framework", "static", "link-arg" and
17df50a5
XL
2058 // where MODIFIERS are a comma separated list of supported modifiers
2059 // (bundle, verbatim, whole-archive, as-needed). Each modifier is prefixed
2060 // with either + or - to indicate whether it is enabled or disabled.
2061 // The last value specified for a given modifier wins.
2062 let (name, kind, verbatim) = match s.split_once('=') {
2063 None => (s, NativeLibKind::Unspecified, None),
fc512014 2064 Some((kind, name)) => {
94222f64 2065 let (kind, verbatim) = parse_native_lib_kind(matches, kind, error_format);
17df50a5 2066 (name.to_string(), kind, verbatim)
0531ce1d
XL
2067 }
2068 };
17df50a5 2069
fc512014
XL
2070 let (name, new_name) = match name.split_once(':') {
2071 None => (name, None),
2072 Some((name, new_name)) => (name.to_string(), Some(new_name.to_owned())),
2073 };
923072b8
FG
2074 if name.is_empty() {
2075 early_error(error_format, "library name must not be empty");
2076 }
17df50a5 2077 NativeLib { name, new_name, kind, verbatim }
0531ce1d 2078 })
e74abb32
XL
2079 .collect()
2080}
1a4d82fc 2081
60c5eb7d 2082pub fn parse_externs(
e74abb32 2083 matches: &getopts::Matches,
064997fb 2084 unstable_opts: &UnstableOptions,
e74abb32 2085 error_format: ErrorOutputType,
e74abb32 2086) -> Externs {
064997fb 2087 let is_unstable_enabled = unstable_opts.unstable_options;
48663c56 2088 let mut externs: BTreeMap<String, ExternEntry> = BTreeMap::new();
60c5eb7d 2089 for arg in matches.opt_strs("extern") {
fc512014
XL
2090 let (name, path) = match arg.split_once('=') {
2091 None => (arg, None),
5869c6ff 2092 Some((name, path)) => (name.to_string(), Some(Path::new(path))),
fc512014
XL
2093 };
2094 let (options, name) = match name.split_once(':') {
2095 None => (None, name),
2096 Some((opts, name)) => (Some(opts), name.to_string()),
1a4d82fc
JJ
2097 };
2098
5869c6ff
XL
2099 let path = path.map(|p| CanonicalizedPath::new(p));
2100
60c5eb7d 2101 let entry = externs.entry(name.to_owned());
48663c56 2102
60c5eb7d 2103 use std::collections::btree_map::Entry;
48663c56 2104
60c5eb7d
XL
2105 let entry = if let Some(path) = path {
2106 // --extern prelude_name=some_file.rlib
2107 match entry {
2108 Entry::Vacant(vacant) => {
2109 let files = BTreeSet::from_iter(iter::once(path));
2110 vacant.insert(ExternEntry::new(ExternLocation::ExactPaths(files)))
2111 }
2112 Entry::Occupied(occupied) => {
2113 let ext_ent = occupied.into_mut();
2114 match ext_ent {
2115 ExternEntry { location: ExternLocation::ExactPaths(files), .. } => {
2116 files.insert(path);
2117 }
2118 ExternEntry {
2119 location: location @ ExternLocation::FoundInLibrarySearchDirectories,
2120 ..
2121 } => {
2122 // Exact paths take precedence over search directories.
2123 let files = BTreeSet::from_iter(iter::once(path));
2124 *location = ExternLocation::ExactPaths(files);
2125 }
2126 }
2127 ext_ent
2128 }
2129 }
2130 } else {
2131 // --extern prelude_name
2132 match entry {
2133 Entry::Vacant(vacant) => {
2134 vacant.insert(ExternEntry::new(ExternLocation::FoundInLibrarySearchDirectories))
2135 }
2136 Entry::Occupied(occupied) => {
2137 // Ignore if already specified.
2138 occupied.into_mut()
2139 }
2140 }
2141 };
2142
2143 let mut is_private_dep = false;
2144 let mut add_prelude = true;
04454e1e 2145 let mut nounused_dep = false;
60c5eb7d
XL
2146 if let Some(opts) = options {
2147 if !is_unstable_enabled {
2148 early_error(
2149 error_format,
2150 "the `-Z unstable-options` flag must also be passed to \
2151 enable `--extern options",
2152 );
2153 }
2154 for opt in opts.split(',') {
2155 match opt {
2156 "priv" => is_private_dep = true,
2157 "noprelude" => {
2158 if let ExternLocation::ExactPaths(_) = &entry.location {
2159 add_prelude = false;
2160 } else {
2161 early_error(
2162 error_format,
2163 "the `noprelude` --extern option requires a file path",
2164 );
2165 }
2166 }
04454e1e 2167 "nounused" => nounused_dep = true,
5e7ed085 2168 _ => early_error(error_format, &format!("unknown --extern option `{opt}`")),
60c5eb7d
XL
2169 }
2170 }
2171 }
48663c56 2172
60c5eb7d
XL
2173 // Crates start out being not private, and go to being private `priv`
2174 // is specified.
2175 entry.is_private_dep |= is_private_dep;
04454e1e
FG
2176 // likewise `nounused`
2177 entry.nounused_dep |= nounused_dep;
60c5eb7d
XL
2178 // If any flag is missing `noprelude`, then add to the prelude.
2179 entry.add_prelude |= add_prelude;
1a4d82fc 2180 }
e74abb32
XL
2181 Externs(externs)
2182}
1a4d82fc 2183
e74abb32
XL
2184fn parse_remap_path_prefix(
2185 matches: &getopts::Matches,
064997fb 2186 unstable_opts: &UnstableOptions,
dfeec247 2187 error_format: ErrorOutputType,
e74abb32 2188) -> Vec<(PathBuf, PathBuf)> {
c295e0f8 2189 let mut mapping: Vec<(PathBuf, PathBuf)> = matches
0531ce1d
XL
2190 .opt_strs("remap-path-prefix")
2191 .into_iter()
fc512014
XL
2192 .map(|remap| match remap.rsplit_once('=') {
2193 None => early_error(
2194 error_format,
2195 "--remap-path-prefix must contain '=' between FROM and TO",
2196 ),
2197 Some((from, to)) => (PathBuf::from(from), PathBuf::from(to)),
0531ce1d 2198 })
c295e0f8 2199 .collect();
064997fb 2200 match &unstable_opts.remap_cwd_prefix {
c295e0f8
XL
2201 Some(to) => match std::env::current_dir() {
2202 Ok(cwd) => mapping.push((cwd, to.clone())),
2203 Err(_) => (),
2204 },
2205 None => (),
2206 };
2207 mapping
e74abb32 2208}
0531ce1d 2209
064997fb 2210// JUSTIFICATION: before wrapper fn is available
f2b60f7d 2211#[allow(rustc::bad_opt_access)]
e74abb32
XL
2212pub fn build_session_options(matches: &getopts::Matches) -> Options {
2213 let color = parse_color(matches);
2214
2215 let edition = parse_crate_edition(matches);
2216
a2a8927a
XL
2217 let JsonConfig {
2218 json_rendered,
2219 json_artifact_notifications,
2220 json_unused_externs,
2221 json_future_incompat,
2222 } = parse_json(matches);
e74abb32
XL
2223
2224 let error_format = parse_error_format(matches, color, json_rendered);
2225
064997fb
FG
2226 let diagnostic_width = matches.opt_get("diagnostic-width").unwrap_or_else(|_| {
2227 early_error(error_format, "`--diagnostic-width` must be an positive integer");
2228 });
2229
e74abb32
XL
2230 let unparsed_crate_types = matches.opt_strs("crate-type");
2231 let crate_types = parse_crate_types_from_list(unparsed_crate_types)
a2a8927a 2232 .unwrap_or_else(|e| early_error(error_format, &e));
e74abb32 2233
064997fb 2234 let mut unstable_opts = UnstableOptions::build(matches, error_format);
94222f64 2235 let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format);
e74abb32 2236
064997fb 2237 check_error_format_stability(&unstable_opts, error_format, json_rendered);
e74abb32 2238
064997fb 2239 if !unstable_opts.unstable_options && json_unused_externs.is_enabled() {
cdc7bbd5
XL
2240 early_error(
2241 error_format,
2242 "the `-Z unstable-options` flag must also be passed to enable \
2243 the flag `--json=unused-externs`",
2244 );
2245 }
2246
064997fb 2247 let output_types = parse_output_types(&unstable_opts, matches, error_format);
e74abb32 2248
17df50a5 2249 let mut cg = CodegenOptions::build(matches, error_format);
ba9703b0 2250 let (disable_thinlto, mut codegen_units) = should_override_cgus_and_disable_thinlto(
e74abb32
XL
2251 &output_types,
2252 matches,
2253 error_format,
2254 cg.codegen_units,
2255 );
2256
064997fb 2257 check_thread_count(&unstable_opts, error_format);
e74abb32 2258
5099ac24 2259 let incremental = cg.incremental.as_ref().map(PathBuf::from);
e74abb32 2260
064997fb 2261 let assert_incr_state = parse_assert_incr_state(&unstable_opts.assert_incr_state, error_format);
3c0e092e 2262
064997fb 2263 if unstable_opts.profile && incremental.is_some() {
e74abb32 2264 early_error(
0531ce1d 2265 error_format,
e74abb32
XL
2266 "can't instrument with gcov profiling when compiling incrementally",
2267 );
2268 }
064997fb 2269 if unstable_opts.profile {
ba9703b0
XL
2270 match codegen_units {
2271 Some(1) => {}
2272 None => codegen_units = Some(1),
2273 Some(_) => early_error(
2274 error_format,
2275 "can't instrument with gcov profiling with multiple codegen units",
2276 ),
2277 }
2278 }
e74abb32
XL
2279
2280 if cg.profile_generate.enabled() && cg.profile_use.is_some() {
2281 early_error(
2282 error_format,
2283 "options `-C profile-generate` and `-C profile-use` are exclusive",
2284 );
2285 }
2286
064997fb 2287 if unstable_opts.profile_sample_use.is_some()
c295e0f8
XL
2288 && (cg.profile_generate.enabled() || cg.profile_use.is_some())
2289 {
2290 early_error(
2291 error_format,
2292 "option `-Z profile-sample-use` cannot be used with `-C profile-generate` or `-C profile-use`",
2293 );
2294 }
2295
a2a8927a
XL
2296 // Handle both `-Z symbol-mangling-version` and `-C symbol-mangling-version`; the latter takes
2297 // precedence.
064997fb 2298 match (cg.symbol_mangling_version, unstable_opts.symbol_mangling_version) {
a2a8927a
XL
2299 (Some(smv_c), Some(smv_z)) if smv_c != smv_z => {
2300 early_error(
2301 error_format,
2302 "incompatible values passed for `-C symbol-mangling-version` \
2303 and `-Z symbol-mangling-version`",
2304 );
2305 }
2306 (Some(SymbolManglingVersion::V0), _) => {}
064997fb 2307 (Some(_), _) if !unstable_opts.unstable_options => {
a2a8927a
XL
2308 early_error(
2309 error_format,
2310 "`-C symbol-mangling-version=legacy` requires `-Z unstable-options`",
2311 );
2312 }
2313 (None, None) => {}
2314 (None, smv) => {
2315 early_warn(
2316 error_format,
2317 "`-Z symbol-mangling-version` is deprecated; use `-C symbol-mangling-version`",
2318 );
2319 cg.symbol_mangling_version = smv;
2320 }
2321 _ => {}
2322 }
2323
5099ac24
FG
2324 // Handle both `-Z instrument-coverage` and `-C instrument-coverage`; the latter takes
2325 // precedence.
064997fb 2326 match (cg.instrument_coverage, unstable_opts.instrument_coverage) {
5099ac24
FG
2327 (Some(ic_c), Some(ic_z)) if ic_c != ic_z => {
2328 early_error(
2329 error_format,
2330 "incompatible values passed for `-C instrument-coverage` \
2331 and `-Z instrument-coverage`",
2332 );
2333 }
2334 (Some(InstrumentCoverage::Off | InstrumentCoverage::All), _) => {}
064997fb 2335 (Some(_), _) if !unstable_opts.unstable_options => {
5099ac24
FG
2336 early_error(
2337 error_format,
2338 "`-C instrument-coverage=except-*` requires `-Z unstable-options`",
2339 );
2340 }
2341 (None, None) => {}
2342 (None, ic) => {
2343 early_warn(
2344 error_format,
2345 "`-Z instrument-coverage` is deprecated; use `-C instrument-coverage`",
2346 );
2347 cg.instrument_coverage = ic;
2348 }
2349 _ => {}
2350 }
2351
2352 if cg.instrument_coverage.is_some() && cg.instrument_coverage != Some(InstrumentCoverage::Off) {
3dfed10e
XL
2353 if cg.profile_generate.enabled() || cg.profile_use.is_some() {
2354 early_error(
2355 error_format,
5099ac24 2356 "option `-C instrument-coverage` is not compatible with either `-C profile-use` \
3dfed10e
XL
2357 or `-C profile-generate`",
2358 );
2359 }
2360
5099ac24 2361 // `-C instrument-coverage` implies `-C symbol-mangling-version=v0` - to ensure consistent
1b1a35ee
XL
2362 // and reversible name mangling. Note, LLVM coverage tools can analyze coverage over
2363 // multiple runs, including some changes to source code; so mangled names must be consistent
2364 // across compilations.
a2a8927a
XL
2365 match cg.symbol_mangling_version {
2366 None => cg.symbol_mangling_version = Some(SymbolManglingVersion::V0),
fc512014
XL
2367 Some(SymbolManglingVersion::Legacy) => {
2368 early_warn(
2369 error_format,
5099ac24 2370 "-C instrument-coverage requires symbol mangling version `v0`, \
a2a8927a 2371 but `-C symbol-mangling-version=legacy` was specified",
fc512014
XL
2372 );
2373 }
2374 Some(SymbolManglingVersion::V0) => {}
2375 }
1b1a35ee
XL
2376 }
2377
2378 if let Ok(graphviz_font) = std::env::var("RUSTC_GRAPHVIZ_FONT") {
064997fb 2379 unstable_opts.graphviz_font = graphviz_font;
3dfed10e
XL
2380 }
2381
f9f354fc
XL
2382 if !cg.embed_bitcode {
2383 match cg.lto {
2384 LtoCli::No | LtoCli::Unspecified => {}
2385 LtoCli::Yes | LtoCli::NoParam | LtoCli::Thin | LtoCli::Fat => early_error(
2386 error_format,
2387 "options `-C embed-bitcode=no` and `-C lto` are incompatible",
2388 ),
2389 }
2390 }
2391
064997fb 2392 let prints = collect_print_requests(&mut cg, &mut unstable_opts, matches, error_format);
e74abb32
XL
2393
2394 let cg = cg;
2395
2396 let sysroot_opt = matches.opt_str("sysroot").map(|m| PathBuf::from(&m));
2397 let target_triple = parse_target_triple(matches, error_format);
2398 let opt_level = parse_opt_level(matches, &cg, error_format);
2399 // The `-g` and `-C debuginfo` flags specify the same setting, so we want to be able
2400 // to use them interchangeably. See the note above (regarding `-O` and `-C opt-level`)
2401 // for more details.
2402 let debug_assertions = cg.debug_assertions.unwrap_or(opt_level == OptLevel::No);
2403 let debuginfo = select_debuginfo(matches, &cg, error_format);
2404
2405 let mut search_paths = vec![];
2406 for s in &matches.opt_strs("L") {
a2a8927a 2407 search_paths.push(SearchPath::from_cli_opt(&s, error_format));
e74abb32
XL
2408 }
2409
2410 let libs = parse_libs(matches, error_format);
2411
2412 let test = matches.opt_present("test");
2413
e74abb32 2414 if !cg.remark.is_empty() && debuginfo == DebugInfo::None {
dfeec247 2415 early_warn(error_format, "-C remark requires \"-C debuginfo=n\" to show source locations");
e74abb32
XL
2416 }
2417
064997fb 2418 let externs = parse_externs(matches, &unstable_opts, error_format);
e74abb32
XL
2419
2420 let crate_name = matches.opt_str("crate-name");
2421
064997fb 2422 let remap_path_prefix = parse_remap_path_prefix(matches, &unstable_opts, error_format);
e74abb32 2423
064997fb 2424 let pretty = parse_pretty(&unstable_opts, error_format);
60c5eb7d 2425
cdc7bbd5
XL
2426 // Try to find a directory containing the Rust `src`, for more details see
2427 // the doc comment on the `real_rust_source_base_dir` field.
2428 let tmp_buf;
2429 let sysroot = match &sysroot_opt {
2430 Some(s) => s,
2431 None => {
2432 tmp_buf = crate::filesearch::get_or_default_sysroot();
2433 &tmp_buf
2434 }
2435 };
2436 let real_rust_source_base_dir = {
2437 // This is the location used by the `rust-src` `rustup` component.
2438 let mut candidate = sysroot.join("lib/rustlib/src/rust");
2439 if let Ok(metadata) = candidate.symlink_metadata() {
2440 // Replace the symlink rustbuild creates, with its destination.
2441 // We could try to use `fs::canonicalize` instead, but that might
2442 // produce unnecessarily verbose path.
2443 if metadata.file_type().is_symlink() {
2444 if let Ok(symlink_dest) = std::fs::read_link(&candidate) {
2445 candidate = symlink_dest;
2446 }
2447 }
2448 }
2449
2450 // Only use this directory if it has a file we can expect to always find.
2451 if candidate.join("library/std/src/lib.rs").is_file() { Some(candidate) } else { None }
2452 };
2453
94222f64 2454 let working_dir = std::env::current_dir().unwrap_or_else(|e| {
5e7ed085 2455 early_error(error_format, &format!("Current directory is invalid: {e}"));
94222f64
XL
2456 });
2457
2458 let (path, remapped) =
2459 FilePathMapping::new(remap_path_prefix.clone()).map_prefix(working_dir.clone());
2460 let working_dir = if remapped {
2461 RealFileName::Remapped { local_path: Some(working_dir), virtual_name: path }
2462 } else {
2463 RealFileName::LocalPath(path)
2464 };
2465
e74abb32 2466 Options {
3c0e092e 2467 assert_incr_state,
e74abb32
XL
2468 crate_types,
2469 optimize: opt_level,
2470 debuginfo,
2471 lint_opts,
2472 lint_cap,
2473 describe_lints,
2474 output_types,
2475 search_paths,
2476 maybe_sysroot: sysroot_opt,
2477 target_triple,
2478 test,
2479 incremental,
064997fb 2480 unstable_opts,
e74abb32 2481 prints,
e74abb32
XL
2482 cg,
2483 error_format,
064997fb 2484 diagnostic_width,
e74abb32 2485 externs,
fc512014 2486 unstable_features: UnstableFeatures::from_environment(crate_name.as_deref()),
e74abb32 2487 crate_name,
e74abb32 2488 libs,
e74abb32
XL
2489 debug_assertions,
2490 actually_rustdoc: false,
1b1a35ee 2491 trimmed_def_paths: TrimmedDefPaths::default(),
e74abb32
XL
2492 cli_forced_codegen_units: codegen_units,
2493 cli_forced_thinlto_off: disable_thinlto,
2494 remap_path_prefix,
cdc7bbd5 2495 real_rust_source_base_dir,
e74abb32
XL
2496 edition,
2497 json_artifact_notifications,
cdc7bbd5 2498 json_unused_externs,
a2a8927a 2499 json_future_incompat,
60c5eb7d 2500 pretty,
94222f64
XL
2501 working_dir,
2502 }
2503}
2504
064997fb 2505fn parse_pretty(unstable_opts: &UnstableOptions, efmt: ErrorOutputType) -> Option<PpMode> {
94222f64
XL
2506 use PpMode::*;
2507
064997fb 2508 let first = match unstable_opts.unpretty.as_deref()? {
94222f64
XL
2509 "normal" => Source(PpSourceMode::Normal),
2510 "identified" => Source(PpSourceMode::Identified),
94222f64
XL
2511 "expanded" => Source(PpSourceMode::Expanded),
2512 "expanded,identified" => Source(PpSourceMode::ExpandedIdentified),
2513 "expanded,hygiene" => Source(PpSourceMode::ExpandedHygiene),
2514 "ast-tree" => AstTree(PpAstTreeMode::Normal),
2515 "ast-tree,expanded" => AstTree(PpAstTreeMode::Expanded),
2516 "hir" => Hir(PpHirMode::Normal),
2517 "hir,identified" => Hir(PpHirMode::Identified),
2518 "hir,typed" => Hir(PpHirMode::Typed),
2519 "hir-tree" => HirTree,
2520 "thir-tree" => ThirTree,
2521 "mir" => Mir,
2522 "mir-cfg" => MirCFG,
2523 name => early_error(
2524 efmt,
2525 &format!(
5e7ed085
FG
2526 "argument to `unpretty` must be one of `normal`, `identified`, \
2527 `expanded`, `expanded,identified`, `expanded,hygiene`, \
94222f64 2528 `ast-tree`, `ast-tree,expanded`, `hir`, `hir,identified`, \
5e7ed085 2529 `hir,typed`, `hir-tree`, `thir-tree`, `mir` or `mir-cfg`; got {name}"
94222f64
XL
2530 ),
2531 ),
2532 };
f2b60f7d 2533 debug!("got unpretty option: {first:?}");
94222f64 2534 Some(first)
85aaf69f
SL
2535}
2536
e1599b0c
XL
2537pub fn make_crate_type_option() -> RustcOptGroup {
2538 opt::multi_s(
2539 "",
2540 "crate-type",
2541 "Comma separated list of types of crates
2542 for the compiler to emit",
2543 "[bin|lib|rlib|dylib|cdylib|staticlib|proc-macro]",
2544 )
2545}
2546
0531ce1d 2547pub fn parse_crate_types_from_list(list_list: Vec<String>) -> Result<Vec<CrateType>, String> {
1a4d82fc 2548 let mut crate_types: Vec<CrateType> = Vec::new();
85aaf69f 2549 for unparsed_crate_type in &list_list {
1a4d82fc
JJ
2550 for part in unparsed_crate_type.split(',') {
2551 let new_part = match part {
0531ce1d 2552 "lib" => default_lib_output(),
b7449926
XL
2553 "rlib" => CrateType::Rlib,
2554 "staticlib" => CrateType::Staticlib,
2555 "dylib" => CrateType::Dylib,
2556 "cdylib" => CrateType::Cdylib,
2557 "bin" => CrateType::Executable,
2558 "proc-macro" => CrateType::ProcMacro,
5e7ed085 2559 _ => return Err(format!("unknown crate type: `{part}`")),
1a4d82fc 2560 };
85aaf69f
SL
2561 if !crate_types.contains(&new_part) {
2562 crate_types.push(new_part)
2563 }
1a4d82fc
JJ
2564 }
2565 }
2566
7cac9316 2567 Ok(crate_types)
1a4d82fc
JJ
2568}
2569
54a0048b 2570pub mod nightly_options {
9e0c209e 2571 use super::{ErrorOutputType, OptionStability, RustcOptGroup};
60c5eb7d 2572 use crate::early_error;
dfeec247 2573 use rustc_feature::UnstableFeatures;
54a0048b
SL
2574
2575 pub fn is_unstable_enabled(matches: &getopts::Matches) -> bool {
fc512014
XL
2576 match_is_nightly_build(matches)
2577 && matches.opt_strs("Z").iter().any(|x| *x == "unstable-options")
2578 }
2579
2580 pub fn match_is_nightly_build(matches: &getopts::Matches) -> bool {
2581 is_nightly_build(matches.opt_str("crate-name").as_deref())
54a0048b
SL
2582 }
2583
fc512014
XL
2584 pub fn is_nightly_build(krate: Option<&str>) -> bool {
2585 UnstableFeatures::from_environment(krate).is_nightly_build()
54a0048b
SL
2586 }
2587
2588 pub fn check_nightly_options(matches: &getopts::Matches, flags: &[RustcOptGroup]) {
dfeec247 2589 let has_z_unstable_option = matches.opt_strs("Z").iter().any(|x| *x == "unstable-options");
fc512014 2590 let really_allows_unstable_options = match_is_nightly_build(matches);
54a0048b
SL
2591
2592 for opt in flags.iter() {
2593 if opt.stability == OptionStability::Stable {
0531ce1d 2594 continue;
54a0048b 2595 }
041b39d2 2596 if !matches.opt_present(opt.name) {
0531ce1d 2597 continue;
54a0048b 2598 }
041b39d2 2599 if opt.name != "Z" && !has_z_unstable_option {
0531ce1d
XL
2600 early_error(
2601 ErrorOutputType::default(),
2602 &format!(
2603 "the `-Z unstable-options` flag must also be passed to enable \
2604 the flag `{}`",
2605 opt.name
2606 ),
2607 );
54a0048b
SL
2608 }
2609 if really_allows_unstable_options {
0531ce1d 2610 continue;
54a0048b
SL
2611 }
2612 match opt.stability {
2613 OptionStability::Unstable => {
0531ce1d
XL
2614 let msg = format!(
2615 "the option `{}` is only accepted on the \
2616 nightly compiler",
2617 opt.name
2618 );
54a0048b
SL
2619 early_error(ErrorOutputType::default(), &msg);
2620 }
54a0048b
SL
2621 OptionStability::Stable => {}
2622 }
2623 }
2624 }
2625}
2626
85aaf69f 2627impl fmt::Display for CrateType {
0bf4aa26 2628 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1a4d82fc 2629 match *self {
b7449926
XL
2630 CrateType::Executable => "bin".fmt(f),
2631 CrateType::Dylib => "dylib".fmt(f),
2632 CrateType::Rlib => "rlib".fmt(f),
2633 CrateType::Staticlib => "staticlib".fmt(f),
2634 CrateType::Cdylib => "cdylib".fmt(f),
2635 CrateType::ProcMacro => "proc-macro".fmt(f),
1a4d82fc
JJ
2636 }
2637 }
2638}
2639
60c5eb7d
XL
2640#[derive(Copy, Clone, PartialEq, Debug)]
2641pub enum PpSourceMode {
94222f64 2642 /// `-Zunpretty=normal`
6a06907d 2643 Normal,
94222f64 2644 /// `-Zunpretty=expanded`
6a06907d 2645 Expanded,
94222f64 2646 /// `-Zunpretty=identified`
6a06907d 2647 Identified,
94222f64 2648 /// `-Zunpretty=expanded,identified`
6a06907d 2649 ExpandedIdentified,
94222f64 2650 /// `-Zunpretty=expanded,hygiene`
6a06907d
XL
2651 ExpandedHygiene,
2652}
2653
2654#[derive(Copy, Clone, PartialEq, Debug)]
2655pub enum PpAstTreeMode {
2656 /// `-Zunpretty=ast`
2657 Normal,
2658 /// `-Zunpretty=ast,expanded`
2659 Expanded,
2660}
2661
2662#[derive(Copy, Clone, PartialEq, Debug)]
2663pub enum PpHirMode {
2664 /// `-Zunpretty=hir`
2665 Normal,
2666 /// `-Zunpretty=hir,identified`
2667 Identified,
2668 /// `-Zunpretty=hir,typed`
2669 Typed,
60c5eb7d
XL
2670}
2671
2672#[derive(Copy, Clone, PartialEq, Debug)]
2673pub enum PpMode {
6a06907d 2674 /// Options that print the source code, i.e.
5e7ed085 2675 /// `-Zunpretty=normal` and `-Zunpretty=expanded`
6a06907d
XL
2676 Source(PpSourceMode),
2677 AstTree(PpAstTreeMode),
2678 /// Options that print the HIR, i.e. `-Zunpretty=hir`
2679 Hir(PpHirMode),
2680 /// `-Zunpretty=hir-tree`
2681 HirTree,
2682 /// `-Zunpretty=thir-tree`
2683 ThirTree,
2684 /// `-Zunpretty=mir`
2685 Mir,
2686 /// `-Zunpretty=mir-cfg`
2687 MirCFG,
60c5eb7d
XL
2688}
2689
2690impl PpMode {
2691 pub fn needs_ast_map(&self) -> bool {
2692 use PpMode::*;
2693 use PpSourceMode::*;
2694 match *self {
6a06907d
XL
2695 Source(Normal | Identified) | AstTree(PpAstTreeMode::Normal) => false,
2696
5e7ed085 2697 Source(Expanded | ExpandedIdentified | ExpandedHygiene)
6a06907d
XL
2698 | AstTree(PpAstTreeMode::Expanded)
2699 | Hir(_)
2700 | HirTree
2701 | ThirTree
2702 | Mir
2703 | MirCFG => true,
60c5eb7d
XL
2704 }
2705 }
064997fb
FG
2706 pub fn needs_hir(&self) -> bool {
2707 use PpMode::*;
2708 match *self {
2709 Source(_) | AstTree(_) => false,
2710
2711 Hir(_) | HirTree | ThirTree | Mir | MirCFG => true,
2712 }
2713 }
60c5eb7d
XL
2714
2715 pub fn needs_analysis(&self) -> bool {
2716 use PpMode::*;
cdc7bbd5 2717 matches!(*self, Mir | MirCFG | ThirTree)
60c5eb7d
XL
2718 }
2719}
2720
a1dfa0c6 2721/// Command-line arguments passed to the compiler have to be incorporated with
5bcae85e
SL
2722/// the dependency tracking system for incremental compilation. This module
2723/// provides some utilities to make this more convenient.
2724///
a1dfa0c6 2725/// The values of all command-line arguments that are relevant for dependency
5bcae85e
SL
2726/// tracking are hashed into a single value that determines whether the
2727/// incremental compilation cache can be re-used or not. This hashing is done
e1599b0c
XL
2728/// via the `DepTrackingHash` trait defined below, since the standard `Hash`
2729/// implementation might not be suitable (e.g., arguments are stored in a `Vec`,
5bcae85e
SL
2730/// the hash of which is order dependent, but we might not want the order of
2731/// arguments to make a difference for the hash).
2732///
e1599b0c 2733/// However, since the value provided by `Hash::hash` often *is* suitable,
5bcae85e 2734/// especially for primitive types, there is the
e1599b0c
XL
2735/// `impl_dep_tracking_hash_via_hash!()` macro that allows to simply reuse the
2736/// `Hash` implementation for `DepTrackingHash`. It's important though that
5bcae85e 2737/// we have an opt-in scheme here, so one is hopefully forced to think about
a1dfa0c6 2738/// how the hash should be calculated when adding a new command-line argument.
923072b8 2739pub(crate) mod dep_tracking {
dfeec247 2740 use super::{
5099ac24 2741 BranchProtection, CFGuard, CFProtection, CrateType, DebugInfo, ErrorOutputType,
5e7ed085 2742 InstrumentCoverage, LdImpl, LinkerPluginLto, LocationDetail, LtoCli, OomStrategy, OptLevel,
064997fb
FG
2743 OutputType, OutputTypes, Passes, SourceFileHashAlgorithm, SplitDwarfKind,
2744 SwitchWithOptPath, SymbolManglingVersion, TrimmedDefPaths,
dfeec247 2745 };
9fa01778 2746 use crate::lint;
5869c6ff 2747 use crate::options::WasiExecModel;
17df50a5 2748 use crate::utils::{NativeLib, NativeLibKind};
04454e1e 2749 use rustc_errors::LanguageIdentifier;
dfeec247
XL
2750 use rustc_feature::UnstableFeatures;
2751 use rustc_span::edition::Edition;
94222f64 2752 use rustc_span::RealFileName;
f9f354fc 2753 use rustc_target::spec::{CodeModel, MergeFunctions, PanicStrategy, RelocModel};
3c0e092e
XL
2754 use rustc_target::spec::{
2755 RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TargetTriple, TlsModel,
2756 };
dfeec247 2757 use std::collections::hash_map::DefaultHasher;
5bcae85e 2758 use std::collections::BTreeMap;
9e0c209e 2759 use std::hash::Hash;
6a06907d 2760 use std::num::NonZeroUsize;
5bcae85e 2761 use std::path::PathBuf;
5bcae85e
SL
2762
2763 pub trait DepTrackingHash {
136023e0
XL
2764 fn hash(
2765 &self,
2766 hasher: &mut DefaultHasher,
2767 error_format: ErrorOutputType,
2768 for_crate_hash: bool,
2769 );
5bcae85e
SL
2770 }
2771
2772 macro_rules! impl_dep_tracking_hash_via_hash {
17df50a5 2773 ($($t:ty),+ $(,)?) => {$(
5bcae85e 2774 impl DepTrackingHash for $t {
136023e0 2775 fn hash(&self, hasher: &mut DefaultHasher, _: ErrorOutputType, _for_crate_hash: bool) {
5bcae85e
SL
2776 Hash::hash(self, hasher);
2777 }
2778 }
17df50a5 2779 )+};
5bcae85e
SL
2780 }
2781
17df50a5 2782 impl<T: DepTrackingHash> DepTrackingHash for Option<T> {
136023e0
XL
2783 fn hash(
2784 &self,
2785 hasher: &mut DefaultHasher,
2786 error_format: ErrorOutputType,
2787 for_crate_hash: bool,
2788 ) {
17df50a5
XL
2789 match self {
2790 Some(x) => {
2791 Hash::hash(&1, hasher);
136023e0 2792 DepTrackingHash::hash(x, hasher, error_format, for_crate_hash);
5bcae85e 2793 }
17df50a5 2794 None => Hash::hash(&0, hasher),
5bcae85e 2795 }
17df50a5 2796 }
5bcae85e
SL
2797 }
2798
17df50a5
XL
2799 impl_dep_tracking_hash_via_hash!(
2800 bool,
2801 usize,
2802 NonZeroUsize,
2803 u64,
2804 String,
2805 PathBuf,
2806 lint::Level,
2807 WasiExecModel,
2808 u32,
2809 RelocModel,
2810 CodeModel,
2811 TlsModel,
2812 InstrumentCoverage,
2813 CrateType,
2814 MergeFunctions,
2815 PanicStrategy,
2816 RelroLevel,
2817 Passes,
2818 OptLevel,
2819 LtoCli,
2820 DebugInfo,
2821 UnstableFeatures,
17df50a5
XL
2822 NativeLib,
2823 NativeLibKind,
2824 SanitizerSet,
2825 CFGuard,
5099ac24 2826 CFProtection,
17df50a5
XL
2827 TargetTriple,
2828 Edition,
2829 LinkerPluginLto,
2830 SplitDebuginfo,
064997fb 2831 SplitDwarfKind,
3c0e092e 2832 StackProtector,
17df50a5
XL
2833 SwitchWithOptPath,
2834 SymbolManglingVersion,
2835 SourceFileHashAlgorithm,
2836 TrimmedDefPaths,
2837 Option<LdImpl>,
136023e0 2838 OutputType,
94222f64 2839 RealFileName,
3c0e092e 2840 LocationDetail,
5099ac24 2841 BranchProtection,
5e7ed085 2842 OomStrategy,
04454e1e 2843 LanguageIdentifier,
17df50a5 2844 );
5bcae85e
SL
2845
2846 impl<T1, T2> DepTrackingHash for (T1, T2)
0531ce1d
XL
2847 where
2848 T1: DepTrackingHash,
2849 T2: DepTrackingHash,
5bcae85e 2850 {
136023e0
XL
2851 fn hash(
2852 &self,
2853 hasher: &mut DefaultHasher,
2854 error_format: ErrorOutputType,
2855 for_crate_hash: bool,
2856 ) {
5bcae85e 2857 Hash::hash(&0, hasher);
136023e0 2858 DepTrackingHash::hash(&self.0, hasher, error_format, for_crate_hash);
5bcae85e 2859 Hash::hash(&1, hasher);
136023e0 2860 DepTrackingHash::hash(&self.1, hasher, error_format, for_crate_hash);
5bcae85e
SL
2861 }
2862 }
2863
476ff2be 2864 impl<T1, T2, T3> DepTrackingHash for (T1, T2, T3)
0531ce1d
XL
2865 where
2866 T1: DepTrackingHash,
2867 T2: DepTrackingHash,
2868 T3: DepTrackingHash,
476ff2be 2869 {
136023e0
XL
2870 fn hash(
2871 &self,
2872 hasher: &mut DefaultHasher,
2873 error_format: ErrorOutputType,
2874 for_crate_hash: bool,
2875 ) {
476ff2be 2876 Hash::hash(&0, hasher);
136023e0 2877 DepTrackingHash::hash(&self.0, hasher, error_format, for_crate_hash);
476ff2be 2878 Hash::hash(&1, hasher);
136023e0 2879 DepTrackingHash::hash(&self.1, hasher, error_format, for_crate_hash);
476ff2be 2880 Hash::hash(&2, hasher);
136023e0 2881 DepTrackingHash::hash(&self.2, hasher, error_format, for_crate_hash);
476ff2be
SL
2882 }
2883 }
2884
17df50a5 2885 impl<T: DepTrackingHash> DepTrackingHash for Vec<T> {
136023e0
XL
2886 fn hash(
2887 &self,
2888 hasher: &mut DefaultHasher,
2889 error_format: ErrorOutputType,
2890 for_crate_hash: bool,
2891 ) {
17df50a5
XL
2892 Hash::hash(&self.len(), hasher);
2893 for (index, elem) in self.iter().enumerate() {
2894 Hash::hash(&index, hasher);
136023e0
XL
2895 DepTrackingHash::hash(elem, hasher, error_format, for_crate_hash);
2896 }
2897 }
2898 }
2899
2900 impl DepTrackingHash for OutputTypes {
2901 fn hash(
2902 &self,
2903 hasher: &mut DefaultHasher,
2904 error_format: ErrorOutputType,
2905 for_crate_hash: bool,
2906 ) {
2907 Hash::hash(&self.0.len(), hasher);
2908 for (key, val) in &self.0 {
2909 DepTrackingHash::hash(key, hasher, error_format, for_crate_hash);
2910 if !for_crate_hash {
2911 DepTrackingHash::hash(val, hasher, error_format, for_crate_hash);
2912 }
17df50a5
XL
2913 }
2914 }
2915 }
2916
5bcae85e 2917 // This is a stable hash because BTreeMap is a sorted container
923072b8 2918 pub(crate) fn stable_hash(
0531ce1d
XL
2919 sub_hashes: BTreeMap<&'static str, &dyn DepTrackingHash>,
2920 hasher: &mut DefaultHasher,
2921 error_format: ErrorOutputType,
136023e0 2922 for_crate_hash: bool,
0531ce1d 2923 ) {
5bcae85e
SL
2924 for (key, sub_hash) in sub_hashes {
2925 // Using Hash::hash() instead of DepTrackingHash::hash() is fine for
2926 // the keys, as they are just plain strings
2927 Hash::hash(&key.len(), hasher);
2928 Hash::hash(key, hasher);
136023e0 2929 sub_hash.hash(hasher, error_format, for_crate_hash);
5bcae85e
SL
2930 }
2931 }
2932}
5e7ed085
FG
2933
2934/// Default behavior to use in out-of-memory situations.
2935#[derive(Clone, Copy, PartialEq, Hash, Debug, Encodable, Decodable, HashStable_Generic)]
2936pub enum OomStrategy {
2937 /// Generate a panic that can be caught by `catch_unwind`.
2938 Panic,
2939
2940 /// Abort the process immediately.
2941 Abort,
2942}
2943
2944impl OomStrategy {
2945 pub const SYMBOL: &'static str = "__rust_alloc_error_handler_should_panic";
2946
2947 pub fn should_panic(self) -> u8 {
2948 match self {
2949 OomStrategy::Panic => 1,
2950 OomStrategy::Abort => 0,
2951 }
2952 }
2953}
064997fb
FG
2954
2955/// How to run proc-macro code when building this crate
2956#[derive(Clone, Copy, PartialEq, Hash, Debug)]
2957pub enum ProcMacroExecutionStrategy {
2958 /// Run the proc-macro code on the same thread as the server.
2959 SameThread,
2960
2961 /// Run the proc-macro code on a different thread.
2962 CrossThread,
2963}