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