]>
Commit | Line | Data |
---|---|---|
1a4d82fc | 1 | //! Contains infrastructure for configuring the compiler, including parsing |
e1599b0c | 2 | //! command-line options. |
83c7162d | 3 | |
dfeec247 XL |
4 | pub use crate::options::*; |
5 | ||
e1599b0c | 6 | use crate::lint; |
dfeec247 | 7 | use crate::search_paths::SearchPath; |
5869c6ff | 8 | use crate::utils::{CanonicalizedPath, NativeLibKind}; |
60c5eb7d | 9 | use crate::{early_error, early_warn, Session}; |
1a4d82fc | 10 | |
e1599b0c | 11 | use rustc_data_structures::fx::FxHashSet; |
60c5eb7d | 12 | use rustc_data_structures::impl_stable_hash_via_hash; |
f035d41b | 13 | use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; |
e1599b0c | 14 | |
1b1a35ee | 15 | use rustc_target::abi::{Align, TargetDataLayout}; |
5869c6ff | 16 | use rustc_target::spec::{SplitDebuginfo, Target, TargetTriple}; |
1a4d82fc | 17 | |
6a06907d XL |
18 | use rustc_serialize::json; |
19 | ||
60c5eb7d | 20 | use crate::parse::CrateConfig; |
dfeec247 XL |
21 | use rustc_feature::UnstableFeatures; |
22 | use rustc_span::edition::{Edition, DEFAULT_EDITION, EDITION_NAME_LIST}; | |
23 | use rustc_span::source_map::{FileName, FilePathMapping}; | |
24 | use rustc_span::symbol::{sym, Symbol}; | |
ba9703b0 | 25 | use rustc_span::SourceFileHashAlgorithm; |
1a4d82fc | 26 | |
60c5eb7d | 27 | use rustc_errors::emitter::HumanReadableErrorType; |
ba9703b0 | 28 | use rustc_errors::{ColorConfig, HandlerFlags}; |
3157f602 | 29 | |
e1599b0c XL |
30 | use std::collections::btree_map::{ |
31 | Iter as BTreeMapIter, Keys as BTreeMapKeysIter, Values as BTreeMapValuesIter, | |
32 | }; | |
dfeec247 | 33 | use std::collections::{BTreeMap, BTreeSet}; |
e1599b0c | 34 | use std::fmt; |
60c5eb7d | 35 | use std::iter::{self, FromIterator}; |
0531ce1d | 36 | use std::path::{Path, PathBuf}; |
dfeec247 | 37 | use std::str::{self, FromStr}; |
1a4d82fc | 38 | |
f035d41b | 39 | bitflags! { |
3dfed10e | 40 | #[derive(Default, Encodable, Decodable)] |
f035d41b XL |
41 | pub struct SanitizerSet: u8 { |
42 | const ADDRESS = 1 << 0; | |
43 | const LEAK = 1 << 1; | |
44 | const MEMORY = 1 << 2; | |
45 | const THREAD = 1 << 3; | |
6a06907d | 46 | const HWADDRESS = 1 << 4; |
f035d41b | 47 | } |
8bb4bdeb XL |
48 | } |
49 | ||
f035d41b XL |
50 | /// Formats a sanitizer set as a comma separated list of sanitizers' names. |
51 | impl fmt::Display for SanitizerSet { | |
60c5eb7d | 52 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
f035d41b XL |
53 | let mut first = true; |
54 | for s in *self { | |
55 | let name = match s { | |
56 | SanitizerSet::ADDRESS => "address", | |
57 | SanitizerSet::LEAK => "leak", | |
58 | SanitizerSet::MEMORY => "memory", | |
59 | SanitizerSet::THREAD => "thread", | |
6a06907d | 60 | SanitizerSet::HWADDRESS => "hwaddress", |
f035d41b XL |
61 | _ => panic!("unrecognized sanitizer {:?}", s), |
62 | }; | |
63 | if !first { | |
64 | f.write_str(",")?; | |
65 | } | |
66 | f.write_str(name)?; | |
67 | first = false; | |
60c5eb7d | 68 | } |
f035d41b | 69 | Ok(()) |
60c5eb7d XL |
70 | } |
71 | } | |
72 | ||
f035d41b XL |
73 | impl IntoIterator for SanitizerSet { |
74 | type Item = SanitizerSet; | |
75 | type IntoIter = std::vec::IntoIter<SanitizerSet>; | |
76 | ||
77 | fn into_iter(self) -> Self::IntoIter { | |
6a06907d XL |
78 | [ |
79 | SanitizerSet::ADDRESS, | |
80 | SanitizerSet::LEAK, | |
81 | SanitizerSet::MEMORY, | |
82 | SanitizerSet::THREAD, | |
83 | SanitizerSet::HWADDRESS, | |
84 | ] | |
85 | .iter() | |
86 | .copied() | |
87 | .filter(|&s| self.contains(s)) | |
88 | .collect::<Vec<_>>() | |
89 | .into_iter() | |
f035d41b XL |
90 | } |
91 | } | |
92 | ||
93 | impl<CTX> HashStable<CTX> for SanitizerSet { | |
94 | fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { | |
95 | self.bits().hash_stable(ctx, hasher); | |
60c5eb7d XL |
96 | } |
97 | } | |
98 | ||
f9f354fc XL |
99 | /// The different settings that the `-Z strip` flag can have. |
100 | #[derive(Clone, Copy, PartialEq, Hash, Debug)] | |
101 | pub enum Strip { | |
102 | /// Do not strip at all. | |
103 | None, | |
104 | ||
105 | /// Strip debuginfo. | |
106 | Debuginfo, | |
107 | ||
108 | /// Strip all symbols. | |
109 | Symbols, | |
110 | } | |
111 | ||
3dfed10e | 112 | /// The different settings that the `-C control-flow-guard` flag can have. |
74b04a01 XL |
113 | #[derive(Clone, Copy, PartialEq, Hash, Debug)] |
114 | pub enum CFGuard { | |
115 | /// Do not emit Control Flow Guard metadata or checks. | |
116 | Disabled, | |
117 | ||
118 | /// Emit Control Flow Guard metadata but no checks. | |
119 | NoChecks, | |
120 | ||
121 | /// Emit Control Flow Guard metadata and checks. | |
122 | Checks, | |
123 | } | |
124 | ||
b7449926 | 125 | #[derive(Clone, Copy, Debug, PartialEq, Hash)] |
1a4d82fc | 126 | pub enum OptLevel { |
0531ce1d XL |
127 | No, // -O0 |
128 | Less, // -O1 | |
129 | Default, // -O2 | |
a7813a04 | 130 | Aggressive, // -O3 |
0531ce1d XL |
131 | Size, // -Os |
132 | SizeMin, // -Oz | |
1a4d82fc JJ |
133 | } |
134 | ||
9fa01778 XL |
135 | impl_stable_hash_via_hash!(OptLevel); |
136 | ||
b7449926 XL |
137 | /// This is what the `LtoCli` values get mapped to after resolving defaults and |
138 | /// and taking other command line options into account. | |
e74abb32 | 139 | #[derive(Clone, PartialEq)] |
2c00a5a8 XL |
140 | pub enum Lto { |
141 | /// Don't do any LTO whatsoever | |
142 | No, | |
143 | ||
2c00a5a8 XL |
144 | /// Do a full crate graph LTO with ThinLTO |
145 | Thin, | |
146 | ||
147 | /// Do a local graph LTO with ThinLTO (only relevant for multiple codegen | |
148 | /// units). | |
149 | ThinLocal, | |
150 | ||
151 | /// Do a full crate graph LTO with "fat" LTO | |
152 | Fat, | |
153 | } | |
154 | ||
b7449926 XL |
155 | /// The different settings that the `-C lto` flag can have. |
156 | #[derive(Clone, Copy, PartialEq, Hash, Debug)] | |
157 | pub enum LtoCli { | |
158 | /// `-C lto=no` | |
159 | No, | |
160 | /// `-C lto=yes` | |
161 | Yes, | |
162 | /// `-C lto` | |
163 | NoParam, | |
164 | /// `-C lto=thin` | |
165 | Thin, | |
166 | /// `-C lto=fat` | |
167 | Fat, | |
168 | /// No `-C lto` flag passed | |
169 | Unspecified, | |
170 | } | |
171 | ||
1b1a35ee XL |
172 | /// The different settings that the `-Z dump_mir_spanview` flag can have. `Statement` generates a |
173 | /// document highlighting each span of every statement (including terminators). `Terminator` and | |
174 | /// `Block` highlight a single span per `BasicBlock`: the span of the block's `Terminator`, or a | |
175 | /// computed span for the block, representing the entire range, covering the block's terminator and | |
176 | /// all of its statements. | |
177 | #[derive(Clone, Copy, PartialEq, Hash, Debug)] | |
178 | pub enum MirSpanview { | |
179 | /// Default `-Z dump_mir_spanview` or `-Z dump_mir_spanview=statement` | |
180 | Statement, | |
181 | /// `-Z dump_mir_spanview=terminator` | |
182 | Terminator, | |
183 | /// `-Z dump_mir_spanview=block` | |
184 | Block, | |
185 | } | |
186 | ||
94b46f34 | 187 | #[derive(Clone, PartialEq, Hash)] |
9fa01778 | 188 | pub enum LinkerPluginLto { |
94b46f34 | 189 | LinkerPlugin(PathBuf), |
8faf50e0 | 190 | LinkerPluginAuto, |
dfeec247 | 191 | Disabled, |
94b46f34 XL |
192 | } |
193 | ||
9fa01778 | 194 | impl LinkerPluginLto { |
8faf50e0 | 195 | pub fn enabled(&self) -> bool { |
94b46f34 | 196 | match *self { |
dfeec247 | 197 | LinkerPluginLto::LinkerPlugin(_) | LinkerPluginLto::LinkerPluginAuto => true, |
9fa01778 | 198 | LinkerPluginLto::Disabled => false, |
94b46f34 XL |
199 | } |
200 | } | |
201 | } | |
202 | ||
48663c56 | 203 | #[derive(Clone, PartialEq, Hash)] |
dc9dc135 | 204 | pub enum SwitchWithOptPath { |
48663c56 XL |
205 | Enabled(Option<PathBuf>), |
206 | Disabled, | |
207 | } | |
208 | ||
dc9dc135 | 209 | impl SwitchWithOptPath { |
48663c56 XL |
210 | pub fn enabled(&self) -> bool { |
211 | match *self { | |
dc9dc135 XL |
212 | SwitchWithOptPath::Enabled(_) => true, |
213 | SwitchWithOptPath::Disabled => false, | |
48663c56 XL |
214 | } |
215 | } | |
216 | } | |
217 | ||
3dfed10e XL |
218 | #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] |
219 | #[derive(Encodable, Decodable)] | |
dc9dc135 XL |
220 | pub enum SymbolManglingVersion { |
221 | Legacy, | |
222 | V0, | |
223 | } | |
224 | ||
225 | impl_stable_hash_via_hash!(SymbolManglingVersion); | |
226 | ||
fc512014 | 227 | #[derive(Clone, Copy, Debug, PartialEq, Hash)] |
b7449926 XL |
228 | pub enum DebugInfo { |
229 | None, | |
230 | Limited, | |
231 | Full, | |
1a4d82fc JJ |
232 | } |
233 | ||
3dfed10e XL |
234 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)] |
235 | #[derive(Encodable, Decodable)] | |
1a4d82fc | 236 | pub enum OutputType { |
b039eaaf SL |
237 | Bitcode, |
238 | Assembly, | |
239 | LlvmAssembly, | |
cc61c64b | 240 | Mir, |
32a655c1 | 241 | Metadata, |
b039eaaf SL |
242 | Object, |
243 | Exe, | |
244 | DepInfo, | |
1a4d82fc JJ |
245 | } |
246 | ||
b7449926 | 247 | impl_stable_hash_via_hash!(OutputType); |
ea8adc8c | 248 | |
92a42be0 SL |
249 | impl OutputType { |
250 | fn is_compatible_with_codegen_units_and_single_output_file(&self) -> bool { | |
251 | match *self { | |
48663c56 | 252 | OutputType::Exe | OutputType::DepInfo | OutputType::Metadata => true, |
0531ce1d XL |
253 | OutputType::Bitcode |
254 | | OutputType::Assembly | |
255 | | OutputType::LlvmAssembly | |
256 | | OutputType::Mir | |
48663c56 | 257 | | OutputType::Object => false, |
92a42be0 SL |
258 | } |
259 | } | |
260 | ||
261 | fn shorthand(&self) -> &'static str { | |
262 | match *self { | |
263 | OutputType::Bitcode => "llvm-bc", | |
264 | OutputType::Assembly => "asm", | |
265 | OutputType::LlvmAssembly => "llvm-ir", | |
cc61c64b | 266 | OutputType::Mir => "mir", |
92a42be0 | 267 | OutputType::Object => "obj", |
32a655c1 | 268 | OutputType::Metadata => "metadata", |
92a42be0 SL |
269 | OutputType::Exe => "link", |
270 | OutputType::DepInfo => "dep-info", | |
271 | } | |
272 | } | |
5bcae85e | 273 | |
abe05a73 XL |
274 | fn from_shorthand(shorthand: &str) -> Option<Self> { |
275 | Some(match shorthand { | |
0531ce1d XL |
276 | "asm" => OutputType::Assembly, |
277 | "llvm-ir" => OutputType::LlvmAssembly, | |
278 | "mir" => OutputType::Mir, | |
279 | "llvm-bc" => OutputType::Bitcode, | |
280 | "obj" => OutputType::Object, | |
281 | "metadata" => OutputType::Metadata, | |
282 | "link" => OutputType::Exe, | |
283 | "dep-info" => OutputType::DepInfo, | |
abe05a73 XL |
284 | _ => return None, |
285 | }) | |
286 | } | |
287 | ||
288 | fn shorthands_display() -> String { | |
289 | format!( | |
290 | "`{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}`", | |
291 | OutputType::Bitcode.shorthand(), | |
292 | OutputType::Assembly.shorthand(), | |
293 | OutputType::LlvmAssembly.shorthand(), | |
294 | OutputType::Mir.shorthand(), | |
295 | OutputType::Object.shorthand(), | |
296 | OutputType::Metadata.shorthand(), | |
297 | OutputType::Exe.shorthand(), | |
298 | OutputType::DepInfo.shorthand(), | |
299 | ) | |
300 | } | |
301 | ||
5bcae85e SL |
302 | pub fn extension(&self) -> &'static str { |
303 | match *self { | |
304 | OutputType::Bitcode => "bc", | |
305 | OutputType::Assembly => "s", | |
306 | OutputType::LlvmAssembly => "ll", | |
cc61c64b | 307 | OutputType::Mir => "mir", |
5bcae85e | 308 | OutputType::Object => "o", |
32a655c1 | 309 | OutputType::Metadata => "rmeta", |
5bcae85e SL |
310 | OutputType::DepInfo => "d", |
311 | OutputType::Exe => "", | |
312 | } | |
313 | } | |
92a42be0 SL |
314 | } |
315 | ||
dc9dc135 | 316 | /// The type of diagnostics output to generate. |
476ff2be SL |
317 | #[derive(Clone, Copy, Debug, PartialEq, Eq)] |
318 | pub enum ErrorOutputType { | |
dc9dc135 | 319 | /// Output meant for the consumption of humans. |
48663c56 | 320 | HumanReadable(HumanReadableErrorType), |
dc9dc135 | 321 | /// Output that's consumed by other tools such as `rustfix` or the `RLS`. |
48663c56 | 322 | Json { |
dc9dc135 | 323 | /// Render the JSON in a human readable way (with indents and newlines). |
48663c56 | 324 | pretty: bool, |
dc9dc135 XL |
325 | /// The JSON output includes a `rendered` field that includes the rendered |
326 | /// human output. | |
48663c56 XL |
327 | json_rendered: HumanReadableErrorType, |
328 | }, | |
476ff2be SL |
329 | } |
330 | ||
331 | impl Default for ErrorOutputType { | |
e1599b0c XL |
332 | fn default() -> Self { |
333 | Self::HumanReadable(HumanReadableErrorType::Default(ColorConfig::Auto)) | |
476ff2be SL |
334 | } |
335 | } | |
336 | ||
1b1a35ee XL |
337 | /// Parameter to control path trimming. |
338 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | |
339 | pub enum TrimmedDefPaths { | |
340 | /// `try_print_trimmed_def_path` never prints a trimmed path and never calls the expensive query | |
341 | Never, | |
342 | /// `try_print_trimmed_def_path` calls the expensive query, the query doesn't call `delay_good_path_bug` | |
343 | Always, | |
344 | /// `try_print_trimmed_def_path` calls the expensive query, the query calls `delay_good_path_bug` | |
345 | GoodPath, | |
346 | } | |
347 | ||
348 | impl Default for TrimmedDefPaths { | |
349 | fn default() -> Self { | |
350 | Self::Never | |
351 | } | |
352 | } | |
353 | ||
e1599b0c XL |
354 | /// Use tree-based collections to cheaply get a deterministic `Hash` implementation. |
355 | /// *Do not* switch `BTreeMap` out for an unsorted container type! That would break | |
356 | /// dependency tracking for command-line arguments. | |
5869c6ff | 357 | #[derive(Clone, Hash, Debug)] |
5bcae85e SL |
358 | pub struct OutputTypes(BTreeMap<OutputType, Option<PathBuf>>); |
359 | ||
b7449926 | 360 | impl_stable_hash_via_hash!(OutputTypes); |
ea8adc8c | 361 | |
5bcae85e SL |
362 | impl OutputTypes { |
363 | pub fn new(entries: &[(OutputType, Option<PathBuf>)]) -> OutputTypes { | |
dfeec247 | 364 | OutputTypes(BTreeMap::from_iter(entries.iter().map(|&(k, ref v)| (k, v.clone())))) |
5bcae85e SL |
365 | } |
366 | ||
367 | pub fn get(&self, key: &OutputType) -> Option<&Option<PathBuf>> { | |
368 | self.0.get(key) | |
369 | } | |
370 | ||
371 | pub fn contains_key(&self, key: &OutputType) -> bool { | |
372 | self.0.contains_key(key) | |
373 | } | |
374 | ||
416331ca | 375 | pub fn keys(&self) -> BTreeMapKeysIter<'_, OutputType, Option<PathBuf>> { |
5bcae85e SL |
376 | self.0.keys() |
377 | } | |
378 | ||
416331ca | 379 | pub fn values(&self) -> BTreeMapValuesIter<'_, OutputType, Option<PathBuf>> { |
5bcae85e SL |
380 | self.0.values() |
381 | } | |
32a655c1 | 382 | |
83c7162d XL |
383 | pub fn len(&self) -> usize { |
384 | self.0.len() | |
385 | } | |
386 | ||
e1599b0c | 387 | // Returns `true` if any of the output types require codegen or linking. |
94b46f34 | 388 | pub fn should_codegen(&self) -> bool { |
32a655c1 | 389 | self.0.keys().any(|k| match *k { |
0531ce1d XL |
390 | OutputType::Bitcode |
391 | | OutputType::Assembly | |
392 | | OutputType::LlvmAssembly | |
393 | | OutputType::Mir | |
394 | | OutputType::Object | |
395 | | OutputType::Exe => true, | |
396 | OutputType::Metadata | OutputType::DepInfo => false, | |
32a655c1 SL |
397 | }) |
398 | } | |
5869c6ff XL |
399 | |
400 | // Returns `true` if any of the output types require linking. | |
401 | pub fn should_link(&self) -> bool { | |
402 | self.0.keys().any(|k| match *k { | |
403 | OutputType::Bitcode | |
404 | | OutputType::Assembly | |
405 | | OutputType::LlvmAssembly | |
406 | | OutputType::Mir | |
407 | | OutputType::Metadata | |
408 | | OutputType::Object | |
409 | | OutputType::DepInfo => false, | |
410 | OutputType::Exe => true, | |
411 | }) | |
412 | } | |
5bcae85e SL |
413 | } |
414 | ||
e1599b0c XL |
415 | /// Use tree-based collections to cheaply get a deterministic `Hash` implementation. |
416 | /// *Do not* switch `BTreeMap` or `BTreeSet` out for an unsorted container type! That | |
417 | /// would break dependency tracking for command-line arguments. | |
e74abb32 | 418 | #[derive(Clone)] |
48663c56 XL |
419 | pub struct Externs(BTreeMap<String, ExternEntry>); |
420 | ||
6a06907d XL |
421 | #[derive(Clone)] |
422 | pub struct ExternDepSpecs(BTreeMap<String, ExternDepSpec>); | |
423 | ||
60c5eb7d | 424 | #[derive(Clone, Debug)] |
48663c56 | 425 | pub struct ExternEntry { |
60c5eb7d XL |
426 | pub location: ExternLocation, |
427 | /// Indicates this is a "private" dependency for the | |
428 | /// `exported_private_dependencies` lint. | |
429 | /// | |
430 | /// This can be set with the `priv` option like | |
431 | /// `--extern priv:name=foo.rlib`. | |
432 | pub is_private_dep: bool, | |
433 | /// Add the extern entry to the extern prelude. | |
434 | /// | |
435 | /// This can be disabled with the `noprelude` option like | |
436 | /// `--extern noprelude:name`. | |
437 | pub add_prelude: bool, | |
438 | } | |
439 | ||
440 | #[derive(Clone, Debug)] | |
441 | pub enum ExternLocation { | |
442 | /// Indicates to look for the library in the search paths. | |
443 | /// | |
444 | /// Added via `--extern name`. | |
445 | FoundInLibrarySearchDirectories, | |
446 | /// The locations where this extern entry must be found. | |
447 | /// | |
448 | /// The `CrateLoader` is responsible for loading these and figuring out | |
449 | /// which one to use. | |
450 | /// | |
451 | /// Added via `--extern prelude_name=some_file.rlib` | |
5869c6ff | 452 | ExactPaths(BTreeSet<CanonicalizedPath>), |
48663c56 | 453 | } |
5bcae85e | 454 | |
6a06907d XL |
455 | /// Supplied source location of a dependency - for example in a build specification |
456 | /// file like Cargo.toml. We support several syntaxes: if it makes sense to reference | |
457 | /// a file and line, then the build system can specify that. On the other hand, it may | |
458 | /// make more sense to have an arbitrary raw string. | |
459 | #[derive(Clone, PartialEq)] | |
460 | pub enum ExternDepSpec { | |
461 | /// Raw string | |
462 | Raw(String), | |
463 | /// Raw data in json format | |
464 | Json(json::Json), | |
465 | } | |
466 | ||
467 | impl<'a> From<&'a ExternDepSpec> for rustc_lint_defs::ExternDepSpec { | |
468 | fn from(from: &'a ExternDepSpec) -> Self { | |
469 | match from { | |
470 | ExternDepSpec::Raw(s) => rustc_lint_defs::ExternDepSpec::Raw(s.clone()), | |
471 | ExternDepSpec::Json(json) => rustc_lint_defs::ExternDepSpec::Json(json.clone()), | |
472 | } | |
473 | } | |
474 | } | |
475 | ||
5bcae85e | 476 | impl Externs { |
48663c56 | 477 | pub fn new(data: BTreeMap<String, ExternEntry>) -> Externs { |
5bcae85e SL |
478 | Externs(data) |
479 | } | |
480 | ||
48663c56 | 481 | pub fn get(&self, key: &str) -> Option<&ExternEntry> { |
5bcae85e SL |
482 | self.0.get(key) |
483 | } | |
484 | ||
416331ca | 485 | pub fn iter(&self) -> BTreeMapIter<'_, String, ExternEntry> { |
5bcae85e SL |
486 | self.0.iter() |
487 | } | |
1a4d82fc JJ |
488 | } |
489 | ||
60c5eb7d XL |
490 | impl ExternEntry { |
491 | fn new(location: ExternLocation) -> ExternEntry { | |
492 | ExternEntry { location, is_private_dep: false, add_prelude: false } | |
493 | } | |
494 | ||
5869c6ff | 495 | pub fn files(&self) -> Option<impl Iterator<Item = &CanonicalizedPath>> { |
60c5eb7d XL |
496 | match &self.location { |
497 | ExternLocation::ExactPaths(set) => Some(set.iter()), | |
498 | _ => None, | |
499 | } | |
500 | } | |
501 | } | |
48663c56 | 502 | |
6a06907d XL |
503 | impl ExternDepSpecs { |
504 | pub fn new(data: BTreeMap<String, ExternDepSpec>) -> ExternDepSpecs { | |
505 | ExternDepSpecs(data) | |
506 | } | |
507 | ||
508 | pub fn get(&self, key: &str) -> Option<&ExternDepSpec> { | |
509 | self.0.get(key) | |
510 | } | |
511 | } | |
512 | ||
513 | impl fmt::Display for ExternDepSpec { | |
514 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { | |
515 | match self { | |
516 | ExternDepSpec::Raw(raw) => fmt.write_str(raw), | |
517 | ExternDepSpec::Json(json) => json::as_json(json).fmt(fmt), | |
518 | } | |
519 | } | |
520 | } | |
521 | ||
7cac9316 | 522 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] |
1a4d82fc JJ |
523 | pub enum PrintRequest { |
524 | FileNames, | |
525 | Sysroot, | |
74b04a01 | 526 | TargetLibdir, |
1a4d82fc | 527 | CrateName, |
7453a54e SL |
528 | Cfg, |
529 | TargetList, | |
5bcae85e SL |
530 | TargetCPUs, |
531 | TargetFeatures, | |
532 | RelocationModels, | |
533 | CodeModels, | |
abe05a73 | 534 | TlsModels, |
476ff2be | 535 | TargetSpec, |
ea8adc8c | 536 | NativeStaticLibs, |
1a4d82fc JJ |
537 | } |
538 | ||
e74abb32 | 539 | #[derive(Copy, Clone)] |
ff7c6d11 | 540 | pub enum BorrowckMode { |
ff7c6d11 | 541 | Mir, |
8faf50e0 | 542 | Migrate, |
ff7c6d11 XL |
543 | } |
544 | ||
545 | impl BorrowckMode { | |
e1599b0c | 546 | /// Returns whether we should run the MIR-based borrow check, but also fall back |
8faf50e0 XL |
547 | /// on the AST borrow check if the MIR-based one errors. |
548 | pub fn migrate(self) -> bool { | |
549 | match self { | |
8faf50e0 XL |
550 | BorrowckMode::Mir => false, |
551 | BorrowckMode::Migrate => true, | |
552 | } | |
553 | } | |
ff7c6d11 XL |
554 | } |
555 | ||
1a4d82fc | 556 | pub enum Input { |
e1599b0c | 557 | /// Load source code from a file. |
c34b1796 | 558 | File(PathBuf), |
e1599b0c | 559 | /// Load source code from a string. |
54a0048b | 560 | Str { |
e1599b0c | 561 | /// A string that is shown in place of a filename. |
ff7c6d11 | 562 | name: FileName, |
e1599b0c | 563 | /// An anonymous string containing the source code. |
54a0048b SL |
564 | input: String, |
565 | }, | |
1a4d82fc JJ |
566 | } |
567 | ||
568 | impl Input { | |
0bf4aa26 | 569 | pub fn filestem(&self) -> &str { |
1a4d82fc | 570 | match *self { |
0bf4aa26 XL |
571 | Input::File(ref ifile) => ifile.file_stem().unwrap().to_str().unwrap(), |
572 | Input::Str { .. } => "rust_out", | |
1a4d82fc JJ |
573 | } |
574 | } | |
94b46f34 XL |
575 | |
576 | pub fn get_input(&mut self) -> Option<&mut String> { | |
577 | match *self { | |
578 | Input::File(_) => None, | |
579 | Input::Str { ref mut input, .. } => Some(input), | |
580 | } | |
581 | } | |
532ac7d7 XL |
582 | |
583 | pub fn source_name(&self) -> FileName { | |
584 | match *self { | |
585 | Input::File(ref ifile) => ifile.clone().into(), | |
586 | Input::Str { ref name, .. } => name.clone(), | |
587 | } | |
588 | } | |
1a4d82fc JJ |
589 | } |
590 | ||
5869c6ff | 591 | #[derive(Clone, Hash, Debug)] |
1a4d82fc | 592 | pub struct OutputFilenames { |
c34b1796 | 593 | pub out_directory: PathBuf, |
dfeec247 | 594 | filestem: String, |
c34b1796 | 595 | pub single_output_file: Option<PathBuf>, |
5bcae85e | 596 | pub outputs: OutputTypes, |
1a4d82fc JJ |
597 | } |
598 | ||
b7449926 | 599 | impl_stable_hash_via_hash!(OutputFilenames); |
ea8adc8c | 600 | |
74b04a01 | 601 | pub const RLINK_EXT: &str = "rlink"; |
abe05a73 | 602 | pub const RUST_CGU_EXT: &str = "rcgu"; |
fc512014 | 603 | pub const DWARF_OBJECT_EXT: &str = "dwo"; |
5bcae85e | 604 | |
1a4d82fc | 605 | impl OutputFilenames { |
dfeec247 XL |
606 | pub fn new( |
607 | out_directory: PathBuf, | |
608 | out_filestem: String, | |
609 | single_output_file: Option<PathBuf>, | |
610 | extra: String, | |
611 | outputs: OutputTypes, | |
612 | ) -> Self { | |
613 | OutputFilenames { | |
614 | out_directory, | |
615 | single_output_file, | |
616 | outputs, | |
617 | filestem: format!("{}{}", out_filestem, extra), | |
618 | } | |
619 | } | |
620 | ||
c34b1796 | 621 | pub fn path(&self, flavor: OutputType) -> PathBuf { |
0531ce1d XL |
622 | self.outputs |
623 | .get(&flavor) | |
624 | .and_then(|p| p.to_owned()) | |
b039eaaf | 625 | .or_else(|| self.single_output_file.clone()) |
5bcae85e SL |
626 | .unwrap_or_else(|| self.temp_path(flavor, None)) |
627 | } | |
628 | ||
9fa01778 | 629 | /// Gets the path where a compilation artifact of the given type for the |
5bcae85e SL |
630 | /// given codegen unit should be placed on disk. If codegen_unit_name is |
631 | /// None, a path distinct from those of any codegen unit will be generated. | |
0531ce1d | 632 | pub fn temp_path(&self, flavor: OutputType, codegen_unit_name: Option<&str>) -> PathBuf { |
5bcae85e SL |
633 | let extension = flavor.extension(); |
634 | self.temp_path_ext(extension, codegen_unit_name) | |
1a4d82fc JJ |
635 | } |
636 | ||
fc512014 XL |
637 | /// Like `temp_path`, but specifically for dwarf objects. |
638 | pub fn temp_path_dwo(&self, codegen_unit_name: Option<&str>) -> PathBuf { | |
639 | self.temp_path_ext(DWARF_OBJECT_EXT, codegen_unit_name) | |
640 | } | |
641 | ||
642 | /// Like `temp_path`, but also supports things where there is no corresponding | |
9fa01778 | 643 | /// OutputType, like noopt-bitcode or lto-bitcode. |
0531ce1d | 644 | pub fn temp_path_ext(&self, ext: &str, codegen_unit_name: Option<&str>) -> PathBuf { |
5bcae85e SL |
645 | let mut extension = String::new(); |
646 | ||
647 | if let Some(codegen_unit_name) = codegen_unit_name { | |
ea8adc8c | 648 | extension.push_str(codegen_unit_name); |
1a4d82fc | 649 | } |
5bcae85e SL |
650 | |
651 | if !ext.is_empty() { | |
652 | if !extension.is_empty() { | |
1b1a35ee | 653 | extension.push('.'); |
ea8adc8c | 654 | extension.push_str(RUST_CGU_EXT); |
1b1a35ee | 655 | extension.push('.'); |
5bcae85e SL |
656 | } |
657 | ||
658 | extension.push_str(ext); | |
659 | } | |
660 | ||
dfeec247 | 661 | self.with_extension(&extension) |
1a4d82fc JJ |
662 | } |
663 | ||
c34b1796 | 664 | pub fn with_extension(&self, extension: &str) -> PathBuf { |
dfeec247 XL |
665 | let mut path = self.out_directory.join(&self.filestem); |
666 | path.set_extension(extension); | |
667 | path | |
1a4d82fc | 668 | } |
fc512014 | 669 | |
fc512014 XL |
670 | /// Returns the path for the Split DWARF file - this can differ depending on which Split DWARF |
671 | /// mode is being used, which is the logic that this function is intended to encapsulate. | |
672 | pub fn split_dwarf_path( | |
673 | &self, | |
5869c6ff | 674 | split_debuginfo_kind: SplitDebuginfo, |
fc512014 XL |
675 | cgu_name: Option<&str>, |
676 | ) -> Option<PathBuf> { | |
677 | let obj_out = self.temp_path(OutputType::Object, cgu_name); | |
678 | let dwo_out = self.temp_path_dwo(cgu_name); | |
5869c6ff XL |
679 | match split_debuginfo_kind { |
680 | SplitDebuginfo::Off => None, | |
fc512014 XL |
681 | // Single mode doesn't change how DWARF is emitted, but does add Split DWARF attributes |
682 | // (pointing at the path which is being determined here). Use the path to the current | |
683 | // object file. | |
5869c6ff | 684 | SplitDebuginfo::Packed => Some(obj_out), |
fc512014 | 685 | // Split mode emits the DWARF into a different file, use that path. |
5869c6ff | 686 | SplitDebuginfo::Unpacked => Some(dwo_out), |
fc512014 XL |
687 | } |
688 | } | |
1a4d82fc JJ |
689 | } |
690 | ||
691 | pub fn host_triple() -> &'static str { | |
692 | // Get the host triple out of the build environment. This ensures that our | |
693 | // idea of the host triple is the same as for the set of libraries we've | |
694 | // actually built. We can't just take LLVM's host triple because they | |
695 | // normalize all ix86 architectures to i386. | |
696 | // | |
697 | // Instead of grabbing the host triple (for the current host), we grab (at | |
698 | // compile time) the target triple that this rustc is built with and | |
699 | // calling that (at runtime) the host triple. | |
0531ce1d | 700 | (option_env!("CFG_COMPILER_HOST_TRIPLE")).expect("CFG_COMPILER_HOST_TRIPLE") |
1a4d82fc JJ |
701 | } |
702 | ||
b7449926 XL |
703 | impl Default for Options { |
704 | fn default() -> Options { | |
705 | Options { | |
706 | crate_types: Vec::new(), | |
707 | optimize: OptLevel::No, | |
708 | debuginfo: DebugInfo::None, | |
709 | lint_opts: Vec::new(), | |
710 | lint_cap: None, | |
711 | describe_lints: false, | |
712 | output_types: OutputTypes(BTreeMap::new()), | |
0731742a | 713 | search_paths: vec![], |
b7449926 XL |
714 | maybe_sysroot: None, |
715 | target_triple: TargetTriple::from_triple(host_triple()), | |
716 | test: false, | |
717 | incremental: None, | |
718 | debugging_opts: basic_debugging_options(), | |
719 | prints: Vec::new(), | |
48663c56 | 720 | borrowck_mode: BorrowckMode::Migrate, |
b7449926 XL |
721 | cg: basic_codegen_options(), |
722 | error_format: ErrorOutputType::default(), | |
723 | externs: Externs(BTreeMap::new()), | |
6a06907d | 724 | extern_dep_specs: ExternDepSpecs(BTreeMap::new()), |
b7449926 XL |
725 | crate_name: None, |
726 | alt_std_name: None, | |
727 | libs: Vec::new(), | |
728 | unstable_features: UnstableFeatures::Disallow, | |
729 | debug_assertions: true, | |
730 | actually_rustdoc: false, | |
1b1a35ee | 731 | trimmed_def_paths: TrimmedDefPaths::default(), |
b7449926 XL |
732 | cli_forced_codegen_units: None, |
733 | cli_forced_thinlto_off: false, | |
734 | remap_path_prefix: Vec::new(), | |
735 | edition: DEFAULT_EDITION, | |
416331ca | 736 | json_artifact_notifications: false, |
60c5eb7d | 737 | pretty: None, |
b7449926 | 738 | } |
1a4d82fc JJ |
739 | } |
740 | } | |
741 | ||
54a0048b | 742 | impl Options { |
9fa01778 | 743 | /// Returns `true` if there is a reason to build the dep graph. |
54a0048b | 744 | pub fn build_dep_graph(&self) -> bool { |
dfeec247 XL |
745 | self.incremental.is_some() |
746 | || self.debugging_opts.dump_dep_graph | |
0531ce1d | 747 | || self.debugging_opts.query_dep_graph |
54a0048b | 748 | } |
5bcae85e | 749 | |
041b39d2 XL |
750 | #[inline(always)] |
751 | pub fn enable_dep_node_debug_strs(&self) -> bool { | |
0531ce1d XL |
752 | cfg!(debug_assertions) |
753 | && (self.debugging_opts.query_dep_graph || self.debugging_opts.incremental_info) | |
041b39d2 XL |
754 | } |
755 | ||
7cac9316 | 756 | pub fn file_path_mapping(&self) -> FilePathMapping { |
0531ce1d | 757 | FilePathMapping::new(self.remap_path_prefix.clone()) |
7cac9316 | 758 | } |
ff7c6d11 | 759 | |
e1599b0c | 760 | /// Returns `true` if there will be an output file generated. |
ff7c6d11 XL |
761 | pub fn will_create_output_file(&self) -> bool { |
762 | !self.debugging_opts.parse_only && // The file is just being parsed | |
763 | !self.debugging_opts.ls // The file is just being queried | |
764 | } | |
b7449926 XL |
765 | |
766 | #[inline] | |
767 | pub fn share_generics(&self) -> bool { | |
768 | match self.debugging_opts.share_generics { | |
769 | Some(setting) => setting, | |
dfeec247 XL |
770 | None => match self.optimize { |
771 | OptLevel::No | OptLevel::Less | OptLevel::Size | OptLevel::SizeMin => true, | |
772 | OptLevel::Default | OptLevel::Aggressive => false, | |
773 | }, | |
774 | } | |
775 | } | |
776 | } | |
777 | ||
778 | impl DebuggingOptions { | |
dfeec247 XL |
779 | pub fn diagnostic_handler_flags(&self, can_emit_warnings: bool) -> HandlerFlags { |
780 | HandlerFlags { | |
781 | can_emit_warnings, | |
782 | treat_err_as_bug: self.treat_err_as_bug, | |
783 | dont_buffer_diagnostics: self.dont_buffer_diagnostics, | |
784 | report_delayed_bugs: self.report_delayed_bugs, | |
74b04a01 | 785 | macro_backtrace: self.macro_backtrace, |
ba9703b0 | 786 | deduplicate_diagnostics: self.deduplicate_diagnostics, |
b7449926 XL |
787 | } |
788 | } | |
fc512014 XL |
789 | |
790 | pub fn get_symbol_mangling_version(&self) -> SymbolManglingVersion { | |
791 | self.symbol_mangling_version.unwrap_or(SymbolManglingVersion::Legacy) | |
792 | } | |
54a0048b SL |
793 | } |
794 | ||
9fa01778 XL |
795 | // The type of entry function, so users can have their own entry functions |
796 | #[derive(Copy, Clone, PartialEq, Hash, Debug)] | |
1a4d82fc | 797 | pub enum EntryFnType { |
b7449926 XL |
798 | Main, |
799 | Start, | |
1a4d82fc JJ |
800 | } |
801 | ||
9fa01778 XL |
802 | impl_stable_hash_via_hash!(EntryFnType); |
803 | ||
3dfed10e | 804 | #[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug, Encodable, Decodable)] |
1a4d82fc | 805 | pub enum CrateType { |
b7449926 XL |
806 | Executable, |
807 | Dylib, | |
808 | Rlib, | |
809 | Staticlib, | |
810 | Cdylib, | |
811 | ProcMacro, | |
1a4d82fc JJ |
812 | } |
813 | ||
60c5eb7d XL |
814 | impl_stable_hash_via_hash!(CrateType); |
815 | ||
5bcae85e | 816 | #[derive(Clone, Hash)] |
1a4d82fc | 817 | pub enum Passes { |
b7449926 XL |
818 | Some(Vec<String>), |
819 | All, | |
1a4d82fc JJ |
820 | } |
821 | ||
822 | impl Passes { | |
823 | pub fn is_empty(&self) -> bool { | |
824 | match *self { | |
b7449926 XL |
825 | Passes::Some(ref v) => v.is_empty(), |
826 | Passes::All => false, | |
1a4d82fc JJ |
827 | } |
828 | } | |
829 | } | |
830 | ||
e74abb32 | 831 | pub const fn default_lib_output() -> CrateType { |
b7449926 | 832 | CrateType::Rlib |
1a4d82fc JJ |
833 | } |
834 | ||
60c5eb7d | 835 | pub fn default_configuration(sess: &Session) -> CrateConfig { |
29967ef6 XL |
836 | let end = &sess.target.endian; |
837 | let arch = &sess.target.arch; | |
838 | let wordsz = sess.target.pointer_width.to_string(); | |
839 | let os = &sess.target.os; | |
840 | let env = &sess.target.env; | |
841 | let vendor = &sess.target.vendor; | |
842 | let min_atomic_width = sess.target.min_atomic_width(); | |
843 | let max_atomic_width = sess.target.max_atomic_width(); | |
844 | let atomic_cas = sess.target.atomic_cas; | |
845 | let layout = TargetDataLayout::parse(&sess.target).unwrap_or_else(|err| { | |
1b1a35ee XL |
846 | sess.fatal(&err); |
847 | }); | |
1a4d82fc | 848 | |
b7449926 | 849 | let mut ret = FxHashSet::default(); |
0bf4aa26 | 850 | ret.reserve(6); // the minimum number of insertions |
476ff2be | 851 | // Target bindings. |
3dfed10e | 852 | ret.insert((sym::target_os, Some(Symbol::intern(os)))); |
29967ef6 | 853 | if let Some(ref fam) = sess.target.os_family { |
3dfed10e XL |
854 | ret.insert((sym::target_family, Some(Symbol::intern(fam)))); |
855 | if fam == "windows" { | |
856 | ret.insert((sym::windows, None)); | |
857 | } else if fam == "unix" { | |
858 | ret.insert((sym::unix, None)); | |
32a655c1 SL |
859 | } |
860 | } | |
3dfed10e | 861 | ret.insert((sym::target_arch, Some(Symbol::intern(arch)))); |
5869c6ff | 862 | ret.insert((sym::target_endian, Some(Symbol::intern(end.as_str())))); |
29967ef6 | 863 | ret.insert((sym::target_pointer_width, Some(Symbol::intern(&wordsz)))); |
3dfed10e XL |
864 | ret.insert((sym::target_env, Some(Symbol::intern(env)))); |
865 | ret.insert((sym::target_vendor, Some(Symbol::intern(vendor)))); | |
29967ef6 | 866 | if sess.target.has_elf_tls { |
dc9dc135 | 867 | ret.insert((sym::target_thread_local, None)); |
9cc50fc6 | 868 | } |
1b1a35ee XL |
869 | for &(i, align) in &[ |
870 | (8, layout.i8_align.abi), | |
871 | (16, layout.i16_align.abi), | |
872 | (32, layout.i32_align.abi), | |
873 | (64, layout.i64_align.abi), | |
874 | (128, layout.i128_align.abi), | |
875 | ] { | |
32a655c1 | 876 | if i >= min_atomic_width && i <= max_atomic_width { |
1b1a35ee | 877 | let mut insert_atomic = |s, align: Align| { |
dfeec247 | 878 | ret.insert((sym::target_has_atomic_load_store, Some(Symbol::intern(s)))); |
e74abb32 | 879 | if atomic_cas { |
dfeec247 | 880 | ret.insert((sym::target_has_atomic, Some(Symbol::intern(s)))); |
e74abb32 | 881 | } |
1b1a35ee XL |
882 | if align.bits() == i { |
883 | ret.insert((sym::target_has_atomic_equal_alignment, Some(Symbol::intern(s)))); | |
884 | } | |
e74abb32 XL |
885 | }; |
886 | let s = i.to_string(); | |
1b1a35ee | 887 | insert_atomic(&s, align); |
29967ef6 | 888 | if s == wordsz { |
1b1a35ee | 889 | insert_atomic("ptr", layout.pointer_align.abi); |
a7813a04 XL |
890 | } |
891 | } | |
892 | } | |
f035d41b | 893 | |
29967ef6 XL |
894 | let panic_strategy = sess.panic_strategy(); |
895 | ret.insert((sym::panic, Some(panic_strategy.desc_symbol()))); | |
896 | ||
f035d41b | 897 | for s in sess.opts.debugging_opts.sanitizer { |
60c5eb7d XL |
898 | let symbol = Symbol::intern(&s.to_string()); |
899 | ret.insert((sym::sanitize, Some(symbol))); | |
900 | } | |
f035d41b | 901 | |
c34b1796 | 902 | if sess.opts.debug_assertions { |
3dfed10e | 903 | ret.insert((sym::debug_assertions, None)); |
c34b1796 | 904 | } |
b7449926 | 905 | if sess.opts.crate_types.contains(&CrateType::ProcMacro) { |
dc9dc135 | 906 | ret.insert((sym::proc_macro, None)); |
9e0c209e | 907 | } |
0bf4aa26 | 908 | ret |
1a4d82fc JJ |
909 | } |
910 | ||
e1599b0c | 911 | /// Converts the crate `cfg!` configuration from `String` to `Symbol`. |
532ac7d7 XL |
912 | /// `rustc_interface::interface::Config` accepts this in the compiler configuration, |
913 | /// but the symbol interner is not yet set up then, so we must convert it later. | |
60c5eb7d | 914 | pub fn to_crate_config(cfg: FxHashSet<(String, Option<String>)>) -> CrateConfig { |
dfeec247 | 915 | cfg.into_iter().map(|(a, b)| (Symbol::intern(&a), b.map(|b| Symbol::intern(&b)))).collect() |
532ac7d7 XL |
916 | } |
917 | ||
60c5eb7d | 918 | pub fn build_configuration(sess: &Session, mut user_cfg: CrateConfig) -> CrateConfig { |
1a4d82fc | 919 | // Combine the configuration requested by the session (command line) with |
e1599b0c | 920 | // some default and generated configuration items. |
1a4d82fc | 921 | let default_cfg = default_configuration(sess); |
e1599b0c | 922 | // If the user wants a test runner, then add the test cfg. |
1a4d82fc | 923 | if sess.opts.test { |
dc9dc135 | 924 | user_cfg.insert((sym::test, None)); |
1a4d82fc | 925 | } |
476ff2be SL |
926 | user_cfg.extend(default_cfg.iter().cloned()); |
927 | user_cfg | |
1a4d82fc JJ |
928 | } |
929 | ||
29967ef6 | 930 | pub fn build_target_config(opts: &Options, target_override: Option<Target>) -> Target { |
1b1a35ee XL |
931 | let target_result = target_override.map_or_else(|| Target::search(&opts.target_triple), Ok); |
932 | let target = target_result.unwrap_or_else(|e| { | |
ba9703b0 | 933 | early_error( |
1b1a35ee | 934 | opts.error_format, |
ba9703b0 XL |
935 | &format!( |
936 | "Error loading target specification: {}. \ | |
937 | Use `--print target-list` for a list of built-in targets", | |
938 | e | |
939 | ), | |
940 | ) | |
0bf4aa26 | 941 | }); |
1a4d82fc | 942 | |
29967ef6 XL |
943 | if !matches!(target.pointer_width, 16 | 32 | 64) { |
944 | early_error( | |
1b1a35ee | 945 | opts.error_format, |
ba9703b0 | 946 | &format!( |
dfeec247 | 947 | "target specification was invalid: \ |
0531ce1d | 948 | unrecognized target-pointer-width {}", |
29967ef6 | 949 | target.pointer_width |
ba9703b0 | 950 | ), |
29967ef6 XL |
951 | ) |
952 | } | |
1a4d82fc | 953 | |
29967ef6 | 954 | target |
1a4d82fc JJ |
955 | } |
956 | ||
85aaf69f | 957 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] |
7453a54e SL |
958 | pub enum OptionStability { |
959 | Stable, | |
7453a54e SL |
960 | Unstable, |
961 | } | |
1a4d82fc | 962 | |
1a4d82fc | 963 | pub struct RustcOptGroup { |
0531ce1d | 964 | pub apply: Box<dyn Fn(&mut getopts::Options) -> &mut getopts::Options>, |
041b39d2 | 965 | pub name: &'static str, |
1a4d82fc JJ |
966 | pub stability: OptionStability, |
967 | } | |
968 | ||
969 | impl RustcOptGroup { | |
970 | pub fn is_stable(&self) -> bool { | |
971 | self.stability == OptionStability::Stable | |
972 | } | |
973 | ||
041b39d2 | 974 | pub fn stable<F>(name: &'static str, f: F) -> RustcOptGroup |
0531ce1d XL |
975 | where |
976 | F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static, | |
041b39d2 | 977 | { |
dfeec247 | 978 | RustcOptGroup { name, apply: Box::new(f), stability: OptionStability::Stable } |
1a4d82fc JJ |
979 | } |
980 | ||
041b39d2 | 981 | pub fn unstable<F>(name: &'static str, f: F) -> RustcOptGroup |
0531ce1d XL |
982 | where |
983 | F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static, | |
041b39d2 | 984 | { |
dfeec247 | 985 | RustcOptGroup { name, apply: Box::new(f), stability: OptionStability::Unstable } |
1a4d82fc JJ |
986 | } |
987 | } | |
988 | ||
989 | // The `opt` local module holds wrappers around the `getopts` API that | |
990 | // adds extra rustc-specific metadata to each option; such metadata | |
991 | // is exposed by . The public | |
992 | // functions below ending with `_u` are the functions that return | |
0731742a | 993 | // *unstable* options, i.e., options that are only enabled when the |
1a4d82fc JJ |
994 | // user also passes the `-Z unstable-options` debugging flag. |
995 | mod opt { | |
416331ca | 996 | // The `fn flag*` etc below are written so that we can use them |
1a4d82fc JJ |
997 | // in the future; do not warn about them not being used right now. |
998 | #![allow(dead_code)] | |
999 | ||
1a4d82fc JJ |
1000 | use super::RustcOptGroup; |
1001 | ||
c34b1796 | 1002 | pub type R = RustcOptGroup; |
041b39d2 XL |
1003 | pub type S = &'static str; |
1004 | ||
1005 | fn stable<F>(name: S, f: F) -> R | |
0531ce1d XL |
1006 | where |
1007 | F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static, | |
041b39d2 XL |
1008 | { |
1009 | RustcOptGroup::stable(name, f) | |
1010 | } | |
1011 | ||
1012 | fn unstable<F>(name: S, f: F) -> R | |
0531ce1d XL |
1013 | where |
1014 | F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static, | |
041b39d2 XL |
1015 | { |
1016 | RustcOptGroup::unstable(name, f) | |
1017 | } | |
1a4d82fc | 1018 | |
041b39d2 | 1019 | fn longer(a: S, b: S) -> S { |
dfeec247 | 1020 | if a.len() > b.len() { a } else { b } |
041b39d2 | 1021 | } |
1a4d82fc | 1022 | |
7453a54e | 1023 | pub fn opt_s(a: S, b: S, c: S, d: S) -> R { |
041b39d2 | 1024 | stable(longer(a, b), move |opts| opts.optopt(a, b, c, d)) |
7453a54e SL |
1025 | } |
1026 | pub fn multi_s(a: S, b: S, c: S, d: S) -> R { | |
041b39d2 | 1027 | stable(longer(a, b), move |opts| opts.optmulti(a, b, c, d)) |
7453a54e SL |
1028 | } |
1029 | pub fn flag_s(a: S, b: S, c: S) -> R { | |
041b39d2 | 1030 | stable(longer(a, b), move |opts| opts.optflag(a, b, c)) |
7453a54e SL |
1031 | } |
1032 | pub fn flagopt_s(a: S, b: S, c: S, d: S) -> R { | |
041b39d2 | 1033 | stable(longer(a, b), move |opts| opts.optflagopt(a, b, c, d)) |
7453a54e SL |
1034 | } |
1035 | pub fn flagmulti_s(a: S, b: S, c: S) -> R { | |
041b39d2 | 1036 | stable(longer(a, b), move |opts| opts.optflagmulti(a, b, c)) |
7453a54e | 1037 | } |
d9579d0f | 1038 | |
7453a54e | 1039 | pub fn opt(a: S, b: S, c: S, d: S) -> R { |
041b39d2 | 1040 | unstable(longer(a, b), move |opts| opts.optopt(a, b, c, d)) |
7453a54e SL |
1041 | } |
1042 | pub fn multi(a: S, b: S, c: S, d: S) -> R { | |
041b39d2 | 1043 | unstable(longer(a, b), move |opts| opts.optmulti(a, b, c, d)) |
7453a54e SL |
1044 | } |
1045 | pub fn flag(a: S, b: S, c: S) -> R { | |
041b39d2 | 1046 | unstable(longer(a, b), move |opts| opts.optflag(a, b, c)) |
7453a54e SL |
1047 | } |
1048 | pub fn flagopt(a: S, b: S, c: S, d: S) -> R { | |
041b39d2 | 1049 | unstable(longer(a, b), move |opts| opts.optflagopt(a, b, c, d)) |
7453a54e SL |
1050 | } |
1051 | pub fn flagmulti(a: S, b: S, c: S) -> R { | |
041b39d2 | 1052 | unstable(longer(a, b), move |opts| opts.optflagmulti(a, b, c)) |
7453a54e | 1053 | } |
1a4d82fc JJ |
1054 | } |
1055 | ||
1056 | /// Returns the "short" subset of the rustc command line options, | |
1057 | /// including metadata for each option, such as whether the option is | |
1058 | /// part of the stable long-term interface for rustc. | |
1059 | pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> { | |
1060 | vec![ | |
7453a54e SL |
1061 | opt::flag_s("h", "help", "Display this message"), |
1062 | opt::multi_s("", "cfg", "Configure the compilation environment", "SPEC"), | |
0531ce1d XL |
1063 | opt::multi_s( |
1064 | "L", | |
1065 | "", | |
1066 | "Add a directory to the library search path. The | |
a7813a04 | 1067 | optional KIND can be one of dependency, crate, native, |
416331ca | 1068 | framework, or all (the default).", |
0531ce1d XL |
1069 | "[KIND=]PATH", |
1070 | ), | |
1071 | opt::multi_s( | |
1072 | "l", | |
1073 | "", | |
1074 | "Link the generated crate(s) to the specified native | |
a7813a04 | 1075 | library NAME. The optional KIND can be one of |
416331ca | 1076 | static, framework, or dylib (the default).", |
0531ce1d XL |
1077 | "[KIND=]NAME", |
1078 | ), | |
e1599b0c | 1079 | make_crate_type_option(), |
dfeec247 | 1080 | opt::opt_s("", "crate-name", "Specify the name of the crate being built", "NAME"), |
532ac7d7 XL |
1081 | opt::opt_s( |
1082 | "", | |
1083 | "edition", | |
1084 | "Specify which edition of the compiler to use when compiling code.", | |
1085 | EDITION_NAME_LIST, | |
1086 | ), | |
0531ce1d XL |
1087 | opt::multi_s( |
1088 | "", | |
1089 | "emit", | |
1090 | "Comma separated list of types of output for \ | |
1091 | the compiler to emit", | |
1092 | "[asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir]", | |
1093 | ), | |
1094 | opt::multi_s( | |
1095 | "", | |
1096 | "print", | |
48663c56 | 1097 | "Compiler information to print on stdout", |
74b04a01 | 1098 | "[crate-name|file-names|sysroot|target-libdir|cfg|target-list|\ |
0531ce1d XL |
1099 | target-cpus|target-features|relocation-models|\ |
1100 | code-models|tls-models|target-spec-json|native-static-libs]", | |
1101 | ), | |
1102 | opt::flagmulti_s("g", "", "Equivalent to -C debuginfo=2"), | |
7453a54e SL |
1103 | opt::flagmulti_s("O", "", "Equivalent to -C opt-level=2"), |
1104 | opt::opt_s("o", "", "Write output to <filename>", "FILENAME"), | |
0531ce1d XL |
1105 | opt::opt_s( |
1106 | "", | |
1107 | "out-dir", | |
1108 | "Write output to compiler-chosen filename \ | |
1109 | in <dir>", | |
1110 | "DIR", | |
1111 | ), | |
1112 | opt::opt_s( | |
1113 | "", | |
1114 | "explain", | |
1115 | "Provide a detailed explanation of an error \ | |
1116 | message", | |
1117 | "OPT", | |
1118 | ), | |
7453a54e | 1119 | opt::flag_s("", "test", "Build a test harness"), |
dfeec247 | 1120 | opt::opt_s("", "target", "Target triple for which the code is compiled", "TARGET"), |
7453a54e SL |
1121 | opt::multi_s("W", "warn", "Set lint warnings", "OPT"), |
1122 | opt::multi_s("A", "allow", "Set lint allowed", "OPT"), | |
1123 | opt::multi_s("D", "deny", "Set lint denied", "OPT"), | |
1124 | opt::multi_s("F", "forbid", "Set lint forbidden", "OPT"), | |
0531ce1d XL |
1125 | opt::multi_s( |
1126 | "", | |
1127 | "cap-lints", | |
1128 | "Set the most restrictive lint level. \ | |
1129 | More restrictive lints are capped at this \ | |
1130 | level", | |
1131 | "LEVEL", | |
1132 | ), | |
7453a54e SL |
1133 | opt::multi_s("C", "codegen", "Set a codegen option", "OPT[=VALUE]"), |
1134 | opt::flag_s("V", "version", "Print version info and exit"), | |
1135 | opt::flag_s("v", "verbose", "Use verbose output"), | |
1a4d82fc JJ |
1136 | ] |
1137 | } | |
1138 | ||
1139 | /// Returns all rustc command line options, including metadata for | |
1140 | /// each option, such as whether the option is part of the stable | |
1141 | /// long-term interface for rustc. | |
1142 | pub fn rustc_optgroups() -> Vec<RustcOptGroup> { | |
1143 | let mut opts = rustc_short_optgroups(); | |
041b39d2 | 1144 | opts.extend(vec![ |
0531ce1d XL |
1145 | opt::multi_s( |
1146 | "", | |
1147 | "extern", | |
1148 | "Specify where an external rust library is located", | |
60c5eb7d | 1149 | "NAME[=PATH]", |
9fa01778 | 1150 | ), |
6a06907d XL |
1151 | opt::multi_s( |
1152 | "", | |
1153 | "extern-location", | |
1154 | "Location where an external crate dependency is specified", | |
1155 | "NAME=LOCATION", | |
1156 | ), | |
7453a54e | 1157 | opt::opt_s("", "sysroot", "Override the system root", "PATH"), |
7cac9316 | 1158 | opt::multi("Z", "", "Set internal debugging options", "FLAG"), |
0531ce1d XL |
1159 | opt::opt_s( |
1160 | "", | |
1161 | "error-format", | |
1162 | "How errors and other messages are produced", | |
1163 | "human|json|short", | |
1164 | ), | |
dfeec247 | 1165 | opt::multi_s("", "json", "Configure the JSON output of the compiler", "CONFIG"), |
0531ce1d XL |
1166 | opt::opt_s( |
1167 | "", | |
1168 | "color", | |
1169 | "Configure coloring of output: | |
54a0048b SL |
1170 | auto = colorize, if output goes to a tty (default); |
1171 | always = always colorize output; | |
0531ce1d XL |
1172 | never = never colorize output", |
1173 | "auto|always|never", | |
1174 | ), | |
1175 | opt::opt( | |
1176 | "", | |
1177 | "pretty", | |
1178 | "Pretty-print the input instead of compiling; | |
ea8adc8c XL |
1179 | valid types are: `normal` (un-annotated source), |
1180 | `expanded` (crates expanded), or | |
1181 | `expanded,identified` (fully parenthesized, AST nodes with IDs).", | |
0531ce1d XL |
1182 | "TYPE", |
1183 | ), | |
1184 | opt::multi_s( | |
1185 | "", | |
1186 | "remap-path-prefix", | |
1187 | "Remap source names in all output (compiler messages and output files)", | |
1188 | "FROM=TO", | |
1189 | ), | |
1a4d82fc JJ |
1190 | ]); |
1191 | opts | |
1192 | } | |
1193 | ||
dfeec247 XL |
1194 | pub fn get_cmd_lint_options( |
1195 | matches: &getopts::Matches, | |
1196 | error_format: ErrorOutputType, | |
1197 | ) -> (Vec<(String, lint::Level)>, bool, Option<lint::Level>) { | |
74b04a01 | 1198 | let mut lint_opts_with_position = vec![]; |
8faf50e0 XL |
1199 | let mut describe_lints = false; |
1200 | ||
1201 | for &level in &[lint::Allow, lint::Warn, lint::Deny, lint::Forbid] { | |
ba9703b0 XL |
1202 | for (passed_arg_pos, lint_name) in matches.opt_strs_pos(level.as_str()) { |
1203 | let arg_pos = if let lint::Forbid = level { | |
1204 | // HACK: forbid is always specified last, so it can't be overridden. | |
1205 | // FIXME: remove this once <https://github.com/rust-lang/rust/issues/70819> is | |
1206 | // fixed and `forbid` works as expected. | |
f035d41b | 1207 | usize::MAX |
ba9703b0 XL |
1208 | } else { |
1209 | passed_arg_pos | |
1210 | }; | |
8faf50e0 XL |
1211 | if lint_name == "help" { |
1212 | describe_lints = true; | |
1213 | } else { | |
74b04a01 | 1214 | lint_opts_with_position.push((arg_pos, lint_name.replace("-", "_"), level)); |
8faf50e0 XL |
1215 | } |
1216 | } | |
1217 | } | |
1218 | ||
74b04a01 XL |
1219 | lint_opts_with_position.sort_by_key(|x| x.0); |
1220 | let lint_opts = lint_opts_with_position | |
1221 | .iter() | |
1222 | .cloned() | |
1223 | .map(|(_, lint_name, level)| (lint_name, level)) | |
1224 | .collect(); | |
1225 | ||
8faf50e0 XL |
1226 | let lint_cap = matches.opt_str("cap-lints").map(|cap| { |
1227 | lint::Level::from_str(&cap) | |
1228 | .unwrap_or_else(|| early_error(error_format, &format!("unknown lint level: `{}`", cap))) | |
1229 | }); | |
1230 | (lint_opts, describe_lints, lint_cap) | |
1231 | } | |
1232 | ||
e1599b0c | 1233 | /// Parses the `--color` flag. |
416331ca XL |
1234 | pub fn parse_color(matches: &getopts::Matches) -> ColorConfig { |
1235 | match matches.opt_str("color").as_ref().map(|s| &s[..]) { | |
0531ce1d | 1236 | Some("auto") => ColorConfig::Auto, |
9cc50fc6 | 1237 | Some("always") => ColorConfig::Always, |
0531ce1d | 1238 | Some("never") => ColorConfig::Never, |
e9174d1e | 1239 | |
9cc50fc6 | 1240 | None => ColorConfig::Auto, |
e9174d1e | 1241 | |
0531ce1d XL |
1242 | Some(arg) => early_error( |
1243 | ErrorOutputType::default(), | |
1244 | &format!( | |
e1599b0c | 1245 | "argument for `--color` must be auto, \ |
0531ce1d XL |
1246 | always or never (instead was `{}`)", |
1247 | arg | |
1248 | ), | |
1249 | ), | |
416331ca XL |
1250 | } |
1251 | } | |
9cc50fc6 | 1252 | |
416331ca XL |
1253 | /// Parse the `--json` flag. |
1254 | /// | |
1255 | /// The first value returned is how to render JSON diagnostics, and the second | |
1256 | /// is whether or not artifact notifications are enabled. | |
1257 | pub fn parse_json(matches: &getopts::Matches) -> (HumanReadableErrorType, bool) { | |
1258 | let mut json_rendered: fn(ColorConfig) -> HumanReadableErrorType = | |
1259 | HumanReadableErrorType::Default; | |
1260 | let mut json_color = ColorConfig::Never; | |
1261 | let mut json_artifact_notifications = false; | |
1262 | for option in matches.opt_strs("json") { | |
1263 | // For now conservatively forbid `--color` with `--json` since `--json` | |
1264 | // won't actually be emitting any colors and anything colorized is | |
1265 | // embedded in a diagnostic message anyway. | |
1266 | if matches.opt_str("color").is_some() { | |
0bf4aa26 | 1267 | early_error( |
83c7162d | 1268 | ErrorOutputType::default(), |
416331ca XL |
1269 | "cannot specify the `--color` option with `--json`", |
1270 | ); | |
1271 | } | |
83c7162d | 1272 | |
416331ca XL |
1273 | for sub_option in option.split(',') { |
1274 | match sub_option { | |
1275 | "diagnostic-short" => json_rendered = HumanReadableErrorType::Short, | |
1276 | "diagnostic-rendered-ansi" => json_color = ColorConfig::Always, | |
1277 | "artifacts" => json_artifact_notifications = true, | |
dfeec247 XL |
1278 | s => early_error( |
1279 | ErrorOutputType::default(), | |
1280 | &format!("unknown `--json` option `{}`", s), | |
1281 | ), | |
416331ca XL |
1282 | } |
1283 | } | |
83c7162d | 1284 | } |
416331ca XL |
1285 | (json_rendered(json_color), json_artifact_notifications) |
1286 | } | |
83c7162d | 1287 | |
e1599b0c | 1288 | /// Parses the `--error-format` flag. |
416331ca XL |
1289 | pub fn parse_error_format( |
1290 | matches: &getopts::Matches, | |
1291 | color: ColorConfig, | |
1292 | json_rendered: HumanReadableErrorType, | |
1293 | ) -> ErrorOutputType { | |
e1599b0c | 1294 | // We need the `opts_present` check because the driver will send us Matches |
9cc50fc6 | 1295 | // with only stable options if no unstable options are used. Since error-format |
e1599b0c XL |
1296 | // is unstable, it will not be present. We have to use `opts_present` not |
1297 | // `opt_present` because the latter will panic. | |
9cc50fc6 SL |
1298 | let error_format = if matches.opts_present(&["error-format".to_owned()]) { |
1299 | match matches.opt_str("error-format").as_ref().map(|s| &s[..]) { | |
dfeec247 XL |
1300 | None | Some("human") => { |
1301 | ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)) | |
1302 | } | |
dc9dc135 XL |
1303 | Some("human-annotate-rs") => { |
1304 | ErrorOutputType::HumanReadable(HumanReadableErrorType::AnnotateSnippet(color)) | |
dfeec247 | 1305 | } |
48663c56 XL |
1306 | Some("json") => ErrorOutputType::Json { pretty: false, json_rendered }, |
1307 | Some("pretty-json") => ErrorOutputType::Json { pretty: true, json_rendered }, | |
1308 | Some("short") => ErrorOutputType::HumanReadable(HumanReadableErrorType::Short(color)), | |
9cc50fc6 | 1309 | |
0531ce1d | 1310 | Some(arg) => early_error( |
48663c56 | 1311 | ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)), |
0531ce1d | 1312 | &format!( |
e1599b0c | 1313 | "argument for `--error-format` must be `human`, `json` or \ |
0531ce1d XL |
1314 | `short` (instead was `{}`)", |
1315 | arg | |
1316 | ), | |
1317 | ), | |
e9174d1e | 1318 | } |
9cc50fc6 | 1319 | } else { |
48663c56 | 1320 | ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)) |
e9174d1e SL |
1321 | }; |
1322 | ||
416331ca XL |
1323 | match error_format { |
1324 | ErrorOutputType::Json { .. } => {} | |
1325 | ||
1326 | // Conservatively require that the `--json` argument is coupled with | |
1327 | // `--error-format=json`. This means that `--json` is specified we | |
1328 | // should actually be emitting JSON blobs. | |
74b04a01 | 1329 | _ if !matches.opt_strs("json").is_empty() => { |
416331ca XL |
1330 | early_error( |
1331 | ErrorOutputType::default(), | |
1332 | "using `--json` requires also using `--error-format=json`", | |
1333 | ); | |
1334 | } | |
1335 | ||
1336 | _ => {} | |
1337 | } | |
1338 | ||
ba9703b0 | 1339 | error_format |
416331ca XL |
1340 | } |
1341 | ||
5869c6ff | 1342 | pub fn parse_crate_edition(matches: &getopts::Matches) -> Edition { |
416331ca | 1343 | let edition = match matches.opt_str("edition") { |
dfeec247 | 1344 | Some(arg) => Edition::from_str(&arg).unwrap_or_else(|_| { |
416331ca XL |
1345 | early_error( |
1346 | ErrorOutputType::default(), | |
1347 | &format!( | |
e1599b0c | 1348 | "argument for `--edition` must be one of: \ |
416331ca | 1349 | {}. (instead was `{}`)", |
dfeec247 | 1350 | EDITION_NAME_LIST, arg |
416331ca | 1351 | ), |
dfeec247 XL |
1352 | ) |
1353 | }), | |
416331ca XL |
1354 | None => DEFAULT_EDITION, |
1355 | }; | |
1356 | ||
5869c6ff | 1357 | if !edition.is_stable() && !nightly_options::is_unstable_enabled(matches) { |
416331ca | 1358 | early_error( |
dfeec247 XL |
1359 | ErrorOutputType::default(), |
1360 | &format!( | |
5869c6ff | 1361 | "edition {} is unstable and only available with -Z unstable-options.", |
dfeec247 XL |
1362 | edition, |
1363 | ), | |
416331ca XL |
1364 | ) |
1365 | } | |
1366 | ||
e74abb32 XL |
1367 | edition |
1368 | } | |
abe05a73 | 1369 | |
e74abb32 XL |
1370 | fn check_debug_option_stability( |
1371 | debugging_opts: &DebuggingOptions, | |
1372 | error_format: ErrorOutputType, | |
1373 | json_rendered: HumanReadableErrorType, | |
1374 | ) { | |
48663c56 | 1375 | if !debugging_opts.unstable_options { |
48663c56 XL |
1376 | if let ErrorOutputType::Json { pretty: true, json_rendered } = error_format { |
1377 | early_error( | |
1378 | ErrorOutputType::Json { pretty: false, json_rendered }, | |
e1599b0c | 1379 | "`--error-format=pretty-json` is unstable", |
48663c56 XL |
1380 | ); |
1381 | } | |
dc9dc135 | 1382 | if let ErrorOutputType::HumanReadable(HumanReadableErrorType::AnnotateSnippet(_)) = |
dfeec247 XL |
1383 | error_format |
1384 | { | |
dc9dc135 XL |
1385 | early_error( |
1386 | ErrorOutputType::Json { pretty: false, json_rendered }, | |
e1599b0c | 1387 | "`--error-format=human-annotate-rs` is unstable", |
dc9dc135 XL |
1388 | ); |
1389 | } | |
abe05a73 | 1390 | } |
e74abb32 | 1391 | } |
1a4d82fc | 1392 | |
e74abb32 XL |
1393 | fn parse_output_types( |
1394 | debugging_opts: &DebuggingOptions, | |
1395 | matches: &getopts::Matches, | |
1396 | error_format: ErrorOutputType, | |
1397 | ) -> OutputTypes { | |
5bcae85e | 1398 | let mut output_types = BTreeMap::new(); |
3157f602 | 1399 | if !debugging_opts.parse_only { |
b039eaaf SL |
1400 | for list in matches.opt_strs("emit") { |
1401 | for output_type in list.split(',') { | |
fc512014 XL |
1402 | let (shorthand, path) = match output_type.split_once('=') { |
1403 | None => (output_type, None), | |
1404 | Some((shorthand, path)) => (shorthand, Some(PathBuf::from(path))), | |
1405 | }; | |
dfeec247 | 1406 | let output_type = OutputType::from_shorthand(shorthand).unwrap_or_else(|| { |
0bf4aa26 | 1407 | early_error( |
0531ce1d XL |
1408 | error_format, |
1409 | &format!( | |
1410 | "unknown emission type: `{}` - expected one of: {}", | |
1411 | shorthand, | |
1412 | OutputType::shorthands_display(), | |
1413 | ), | |
dfeec247 XL |
1414 | ) |
1415 | }); | |
b039eaaf | 1416 | output_types.insert(output_type, path); |
1a4d82fc JJ |
1417 | } |
1418 | } | |
1419 | }; | |
7cac9316 | 1420 | if output_types.is_empty() { |
b039eaaf | 1421 | output_types.insert(OutputType::Exe, None); |
1a4d82fc | 1422 | } |
e74abb32 XL |
1423 | OutputTypes(output_types) |
1424 | } | |
1a4d82fc | 1425 | |
e74abb32 XL |
1426 | fn should_override_cgus_and_disable_thinlto( |
1427 | output_types: &OutputTypes, | |
1428 | matches: &getopts::Matches, | |
1429 | error_format: ErrorOutputType, | |
1430 | mut codegen_units: Option<usize>, | |
1431 | ) -> (bool, Option<usize>) { | |
2c00a5a8 | 1432 | let mut disable_thinlto = false; |
e1599b0c | 1433 | // Issue #30063: if user requests LLVM-related output to one |
92a42be0 | 1434 | // particular path, disable codegen-units. |
dfeec247 XL |
1435 | let incompatible: Vec<_> = output_types |
1436 | .0 | |
0531ce1d | 1437 | .iter() |
ea8adc8c | 1438 | .map(|ot_path| ot_path.0) |
0531ce1d | 1439 | .filter(|ot| !ot.is_compatible_with_codegen_units_and_single_output_file()) |
ea8adc8c XL |
1440 | .map(|ot| ot.shorthand()) |
1441 | .collect(); | |
1442 | if !incompatible.is_empty() { | |
1443 | match codegen_units { | |
1444 | Some(n) if n > 1 => { | |
1445 | if matches.opt_present("o") { | |
1446 | for ot in &incompatible { | |
0531ce1d XL |
1447 | early_warn( |
1448 | error_format, | |
1449 | &format!( | |
e1599b0c XL |
1450 | "`--emit={}` with `-o` incompatible with \ |
1451 | `-C codegen-units=N` for N > 1", | |
0531ce1d XL |
1452 | ot |
1453 | ), | |
1454 | ); | |
ea8adc8c XL |
1455 | } |
1456 | early_warn(error_format, "resetting to default -C codegen-units=1"); | |
1457 | codegen_units = Some(1); | |
2c00a5a8 | 1458 | disable_thinlto = true; |
ea8adc8c | 1459 | } |
92a42be0 | 1460 | } |
ff7c6d11 XL |
1461 | _ => { |
1462 | codegen_units = Some(1); | |
2c00a5a8 | 1463 | disable_thinlto = true; |
ff7c6d11 | 1464 | } |
92a42be0 SL |
1465 | } |
1466 | } | |
1467 | ||
e74abb32 | 1468 | if codegen_units == Some(0) { |
dfeec247 | 1469 | early_error(error_format, "value for codegen units must be a positive non-zero integer"); |
ff7c6d11 XL |
1470 | } |
1471 | ||
e74abb32 XL |
1472 | (disable_thinlto, codegen_units) |
1473 | } | |
1474 | ||
1475 | fn check_thread_count(debugging_opts: &DebuggingOptions, error_format: ErrorOutputType) { | |
1476 | if debugging_opts.threads == 0 { | |
dfeec247 | 1477 | early_error(error_format, "value for threads must be a positive non-zero integer"); |
83c7162d XL |
1478 | } |
1479 | ||
e74abb32 | 1480 | if debugging_opts.threads > 1 && debugging_opts.fuel.is_some() { |
dfeec247 | 1481 | early_error(error_format, "optimization fuel is incompatible with multiple threads"); |
54a0048b | 1482 | } |
e74abb32 | 1483 | } |
54a0048b | 1484 | |
e74abb32 XL |
1485 | fn collect_print_requests( |
1486 | cg: &mut CodegenOptions, | |
1487 | dopts: &mut DebuggingOptions, | |
1488 | matches: &getopts::Matches, | |
e74abb32 XL |
1489 | error_format: ErrorOutputType, |
1490 | ) -> Vec<PrintRequest> { | |
5bcae85e SL |
1491 | let mut prints = Vec::<PrintRequest>::new(); |
1492 | if cg.target_cpu.as_ref().map_or(false, |s| s == "help") { | |
1493 | prints.push(PrintRequest::TargetCPUs); | |
1494 | cg.target_cpu = None; | |
1495 | }; | |
1496 | if cg.target_feature == "help" { | |
1497 | prints.push(PrintRequest::TargetFeatures); | |
b7449926 | 1498 | cg.target_feature = String::new(); |
5bcae85e | 1499 | } |
5bcae85e | 1500 | |
e74abb32 XL |
1501 | prints.extend(matches.opt_strs("print").into_iter().map(|s| match &*s { |
1502 | "crate-name" => PrintRequest::CrateName, | |
1503 | "file-names" => PrintRequest::FileNames, | |
1504 | "sysroot" => PrintRequest::Sysroot, | |
74b04a01 | 1505 | "target-libdir" => PrintRequest::TargetLibdir, |
e74abb32 XL |
1506 | "cfg" => PrintRequest::Cfg, |
1507 | "target-list" => PrintRequest::TargetList, | |
1508 | "target-cpus" => PrintRequest::TargetCPUs, | |
1509 | "target-features" => PrintRequest::TargetFeatures, | |
1510 | "relocation-models" => PrintRequest::RelocationModels, | |
1511 | "code-models" => PrintRequest::CodeModels, | |
1512 | "tls-models" => PrintRequest::TlsModels, | |
1513 | "native-static-libs" => PrintRequest::NativeStaticLibs, | |
1514 | "target-spec-json" => { | |
60c5eb7d | 1515 | if dopts.unstable_options { |
e74abb32 XL |
1516 | PrintRequest::TargetSpec |
1517 | } else { | |
1518 | early_error( | |
1519 | error_format, | |
1520 | "the `-Z unstable-options` flag must also be passed to \ | |
1521 | enable the target-spec-json print option", | |
1522 | ); | |
1523 | } | |
1524 | } | |
1525 | req => early_error(error_format, &format!("unknown print request `{}`", req)), | |
1526 | })); | |
1a4d82fc | 1527 | |
e74abb32 XL |
1528 | prints |
1529 | } | |
1530 | ||
1531 | fn parse_target_triple(matches: &getopts::Matches, error_format: ErrorOutputType) -> TargetTriple { | |
1532 | match matches.opt_str("target") { | |
1533 | Some(target) if target.ends_with(".json") => { | |
0531ce1d | 1534 | let path = Path::new(&target); |
dfeec247 XL |
1535 | TargetTriple::from_path(&path).unwrap_or_else(|_| { |
1536 | early_error(error_format, &format!("target file {:?} does not exist", path)) | |
1537 | }) | |
e74abb32 | 1538 | } |
6a06907d | 1539 | Some(target) => TargetTriple::TargetTriple(target), |
e74abb32 XL |
1540 | _ => TargetTriple::from_triple(host_triple()), |
1541 | } | |
1542 | } | |
1543 | ||
1544 | fn parse_opt_level( | |
1545 | matches: &getopts::Matches, | |
1546 | cg: &CodegenOptions, | |
1547 | error_format: ErrorOutputType, | |
1548 | ) -> OptLevel { | |
1549 | // The `-O` and `-C opt-level` flags specify the same setting, so we want to be able | |
1550 | // to use them interchangeably. However, because they're technically different flags, | |
1551 | // we need to work out manually which should take precedence if both are supplied (i.e. | |
1552 | // the rightmost flag). We do this by finding the (rightmost) position of both flags and | |
1553 | // comparing them. Note that if a flag is not found, its position will be `None`, which | |
1554 | // always compared less than `Some(_)`. | |
1555 | let max_o = matches.opt_positions("O").into_iter().max(); | |
dfeec247 XL |
1556 | let max_c = matches |
1557 | .opt_strs_pos("C") | |
1558 | .into_iter() | |
fc512014 XL |
1559 | .flat_map(|(i, s)| { |
1560 | // NB: This can match a string without `=`. | |
1561 | if let Some("opt-level") = s.splitn(2, '=').next() { Some(i) } else { None } | |
1562 | }) | |
dfeec247 | 1563 | .max(); |
e74abb32 XL |
1564 | if max_o > max_c { |
1565 | OptLevel::Default | |
0531ce1d | 1566 | } else { |
ba9703b0 XL |
1567 | match cg.opt_level.as_ref() { |
1568 | "0" => OptLevel::No, | |
1569 | "1" => OptLevel::Less, | |
1570 | "2" => OptLevel::Default, | |
1571 | "3" => OptLevel::Aggressive, | |
1572 | "s" => OptLevel::Size, | |
1573 | "z" => OptLevel::SizeMin, | |
1574 | arg => { | |
e74abb32 XL |
1575 | early_error( |
1576 | error_format, | |
1577 | &format!( | |
1578 | "optimization level needs to be \ | |
1579 | between 0-3, s or z (instead was `{}`)", | |
1580 | arg | |
1581 | ), | |
1582 | ); | |
1a4d82fc JJ |
1583 | } |
1584 | } | |
e74abb32 XL |
1585 | } |
1586 | } | |
1587 | ||
1588 | fn select_debuginfo( | |
1589 | matches: &getopts::Matches, | |
1590 | cg: &CodegenOptions, | |
1591 | error_format: ErrorOutputType, | |
1592 | ) -> DebugInfo { | |
48663c56 | 1593 | let max_g = matches.opt_positions("g").into_iter().max(); |
dfeec247 XL |
1594 | let max_c = matches |
1595 | .opt_strs_pos("C") | |
1596 | .into_iter() | |
fc512014 XL |
1597 | .flat_map(|(i, s)| { |
1598 | // NB: This can match a string without `=`. | |
1599 | if let Some("debuginfo") = s.splitn(2, '=').next() { Some(i) } else { None } | |
1600 | }) | |
dfeec247 | 1601 | .max(); |
e74abb32 | 1602 | if max_g > max_c { |
b7449926 | 1603 | DebugInfo::Full |
1a4d82fc JJ |
1604 | } else { |
1605 | match cg.debuginfo { | |
ba9703b0 XL |
1606 | 0 => DebugInfo::None, |
1607 | 1 => DebugInfo::Limited, | |
1608 | 2 => DebugInfo::Full, | |
1609 | arg => { | |
0531ce1d XL |
1610 | early_error( |
1611 | error_format, | |
1612 | &format!( | |
1613 | "debug info level needs to be between \ | |
1614 | 0-2 (instead was `{}`)", | |
1615 | arg | |
1616 | ), | |
1617 | ); | |
1a4d82fc JJ |
1618 | } |
1619 | } | |
1a4d82fc | 1620 | } |
e74abb32 | 1621 | } |
1a4d82fc | 1622 | |
e74abb32 XL |
1623 | fn parse_libs( |
1624 | matches: &getopts::Matches, | |
1625 | error_format: ErrorOutputType, | |
f9f354fc | 1626 | ) -> Vec<(String, Option<String>, NativeLibKind)> { |
e74abb32 | 1627 | matches |
0531ce1d XL |
1628 | .opt_strs("l") |
1629 | .into_iter() | |
1630 | .map(|s| { | |
1631 | // Parse string of the form "[KIND=]lib[:new_name]", | |
1632 | // where KIND is one of "dylib", "framework", "static". | |
fc512014 XL |
1633 | let (name, kind) = match s.split_once('=') { |
1634 | None => (s, NativeLibKind::Unspecified), | |
1635 | Some((kind, name)) => { | |
1636 | let kind = match kind { | |
1637 | "dylib" => NativeLibKind::Dylib, | |
1638 | "framework" => NativeLibKind::Framework, | |
1639 | "static" => NativeLibKind::StaticBundle, | |
1640 | "static-nobundle" => NativeLibKind::StaticNoBundle, | |
1641 | s => { | |
1642 | early_error( | |
1643 | error_format, | |
1644 | &format!( | |
1645 | "unknown library kind `{}`, expected \ | |
1646 | one of dylib, framework, or static", | |
1647 | s | |
1648 | ), | |
1649 | ); | |
1650 | } | |
1651 | }; | |
1652 | (name.to_string(), kind) | |
0531ce1d XL |
1653 | } |
1654 | }; | |
fc512014 XL |
1655 | if kind == NativeLibKind::StaticNoBundle |
1656 | && !nightly_options::match_is_nightly_build(matches) | |
1657 | { | |
0531ce1d XL |
1658 | early_error( |
1659 | error_format, | |
74b04a01 XL |
1660 | "the library kind 'static-nobundle' is only \ |
1661 | accepted on the nightly compiler", | |
0531ce1d | 1662 | ); |
1a4d82fc | 1663 | } |
fc512014 XL |
1664 | let (name, new_name) = match name.split_once(':') { |
1665 | None => (name, None), | |
1666 | Some((name, new_name)) => (name.to_string(), Some(new_name.to_owned())), | |
1667 | }; | |
1668 | (name, new_name, kind) | |
0531ce1d | 1669 | }) |
e74abb32 XL |
1670 | .collect() |
1671 | } | |
1a4d82fc | 1672 | |
e74abb32 | 1673 | fn parse_borrowck_mode(dopts: &DebuggingOptions, error_format: ErrorOutputType) -> BorrowckMode { |
ba9703b0 XL |
1674 | match dopts.borrowck.as_ref() { |
1675 | "migrate" => BorrowckMode::Migrate, | |
1676 | "mir" => BorrowckMode::Mir, | |
1677 | m => early_error(error_format, &format!("unknown borrowck mode `{}`", m)), | |
1a4d82fc | 1678 | } |
e74abb32 | 1679 | } |
1a4d82fc | 1680 | |
60c5eb7d | 1681 | pub fn parse_externs( |
e74abb32 XL |
1682 | matches: &getopts::Matches, |
1683 | debugging_opts: &DebuggingOptions, | |
1684 | error_format: ErrorOutputType, | |
e74abb32 | 1685 | ) -> Externs { |
60c5eb7d | 1686 | let is_unstable_enabled = debugging_opts.unstable_options; |
48663c56 | 1687 | let mut externs: BTreeMap<String, ExternEntry> = BTreeMap::new(); |
60c5eb7d | 1688 | for arg in matches.opt_strs("extern") { |
fc512014 XL |
1689 | let (name, path) = match arg.split_once('=') { |
1690 | None => (arg, None), | |
5869c6ff | 1691 | Some((name, path)) => (name.to_string(), Some(Path::new(path))), |
fc512014 XL |
1692 | }; |
1693 | let (options, name) = match name.split_once(':') { | |
1694 | None => (None, name), | |
1695 | Some((opts, name)) => (Some(opts), name.to_string()), | |
1a4d82fc JJ |
1696 | }; |
1697 | ||
5869c6ff XL |
1698 | let path = path.map(|p| CanonicalizedPath::new(p)); |
1699 | ||
60c5eb7d | 1700 | let entry = externs.entry(name.to_owned()); |
48663c56 | 1701 | |
60c5eb7d | 1702 | use std::collections::btree_map::Entry; |
48663c56 | 1703 | |
60c5eb7d XL |
1704 | let entry = if let Some(path) = path { |
1705 | // --extern prelude_name=some_file.rlib | |
1706 | match entry { | |
1707 | Entry::Vacant(vacant) => { | |
1708 | let files = BTreeSet::from_iter(iter::once(path)); | |
1709 | vacant.insert(ExternEntry::new(ExternLocation::ExactPaths(files))) | |
1710 | } | |
1711 | Entry::Occupied(occupied) => { | |
1712 | let ext_ent = occupied.into_mut(); | |
1713 | match ext_ent { | |
1714 | ExternEntry { location: ExternLocation::ExactPaths(files), .. } => { | |
1715 | files.insert(path); | |
1716 | } | |
1717 | ExternEntry { | |
1718 | location: location @ ExternLocation::FoundInLibrarySearchDirectories, | |
1719 | .. | |
1720 | } => { | |
1721 | // Exact paths take precedence over search directories. | |
1722 | let files = BTreeSet::from_iter(iter::once(path)); | |
1723 | *location = ExternLocation::ExactPaths(files); | |
1724 | } | |
1725 | } | |
1726 | ext_ent | |
1727 | } | |
1728 | } | |
1729 | } else { | |
1730 | // --extern prelude_name | |
1731 | match entry { | |
1732 | Entry::Vacant(vacant) => { | |
1733 | vacant.insert(ExternEntry::new(ExternLocation::FoundInLibrarySearchDirectories)) | |
1734 | } | |
1735 | Entry::Occupied(occupied) => { | |
1736 | // Ignore if already specified. | |
1737 | occupied.into_mut() | |
1738 | } | |
1739 | } | |
1740 | }; | |
1741 | ||
1742 | let mut is_private_dep = false; | |
1743 | let mut add_prelude = true; | |
1744 | if let Some(opts) = options { | |
1745 | if !is_unstable_enabled { | |
1746 | early_error( | |
1747 | error_format, | |
1748 | "the `-Z unstable-options` flag must also be passed to \ | |
1749 | enable `--extern options", | |
1750 | ); | |
1751 | } | |
1752 | for opt in opts.split(',') { | |
1753 | match opt { | |
1754 | "priv" => is_private_dep = true, | |
1755 | "noprelude" => { | |
1756 | if let ExternLocation::ExactPaths(_) = &entry.location { | |
1757 | add_prelude = false; | |
1758 | } else { | |
1759 | early_error( | |
1760 | error_format, | |
1761 | "the `noprelude` --extern option requires a file path", | |
1762 | ); | |
1763 | } | |
1764 | } | |
1765 | _ => early_error(error_format, &format!("unknown --extern option `{}`", opt)), | |
1766 | } | |
1767 | } | |
1768 | } | |
48663c56 | 1769 | |
60c5eb7d XL |
1770 | // Crates start out being not private, and go to being private `priv` |
1771 | // is specified. | |
1772 | entry.is_private_dep |= is_private_dep; | |
1773 | // If any flag is missing `noprelude`, then add to the prelude. | |
1774 | entry.add_prelude |= add_prelude; | |
1a4d82fc | 1775 | } |
e74abb32 XL |
1776 | Externs(externs) |
1777 | } | |
1a4d82fc | 1778 | |
6a06907d XL |
1779 | fn parse_extern_dep_specs( |
1780 | matches: &getopts::Matches, | |
1781 | debugging_opts: &DebuggingOptions, | |
1782 | error_format: ErrorOutputType, | |
1783 | ) -> ExternDepSpecs { | |
1784 | let is_unstable_enabled = debugging_opts.unstable_options; | |
1785 | let mut map = BTreeMap::new(); | |
1786 | ||
1787 | for arg in matches.opt_strs("extern-location") { | |
1788 | if !is_unstable_enabled { | |
1789 | early_error( | |
1790 | error_format, | |
1791 | "`--extern-location` option is unstable: set `-Z unstable-options`", | |
1792 | ); | |
1793 | } | |
1794 | ||
1795 | let mut parts = arg.splitn(2, '='); | |
1796 | let name = parts.next().unwrap_or_else(|| { | |
1797 | early_error(error_format, "`--extern-location` value must not be empty") | |
1798 | }); | |
1799 | let loc = parts.next().unwrap_or_else(|| { | |
1800 | early_error( | |
1801 | error_format, | |
1802 | &format!("`--extern-location`: specify location for extern crate `{}`", name), | |
1803 | ) | |
1804 | }); | |
1805 | ||
1806 | let locparts: Vec<_> = loc.split(":").collect(); | |
1807 | let spec = match &locparts[..] { | |
1808 | ["raw", ..] => { | |
1809 | // Don't want `:` split string | |
1810 | let raw = loc.splitn(2, ':').nth(1).unwrap_or_else(|| { | |
1811 | early_error(error_format, "`--extern-location`: missing `raw` location") | |
1812 | }); | |
1813 | ExternDepSpec::Raw(raw.to_string()) | |
1814 | } | |
1815 | ["json", ..] => { | |
1816 | // Don't want `:` split string | |
1817 | let raw = loc.splitn(2, ':').nth(1).unwrap_or_else(|| { | |
1818 | early_error(error_format, "`--extern-location`: missing `json` location") | |
1819 | }); | |
1820 | let json = json::from_str(raw).unwrap_or_else(|_| { | |
1821 | early_error( | |
1822 | error_format, | |
1823 | &format!("`--extern-location`: malformed json location `{}`", raw), | |
1824 | ) | |
1825 | }); | |
1826 | ExternDepSpec::Json(json) | |
1827 | } | |
1828 | [bad, ..] => early_error( | |
1829 | error_format, | |
1830 | &format!("unknown location type `{}`: use `raw` or `json`", bad), | |
1831 | ), | |
1832 | [] => early_error(error_format, "missing location specification"), | |
1833 | }; | |
1834 | ||
1835 | map.insert(name.to_string(), spec); | |
1836 | } | |
1837 | ||
1838 | ExternDepSpecs::new(map) | |
1839 | } | |
1840 | ||
e74abb32 XL |
1841 | fn parse_remap_path_prefix( |
1842 | matches: &getopts::Matches, | |
dfeec247 | 1843 | error_format: ErrorOutputType, |
e74abb32 XL |
1844 | ) -> Vec<(PathBuf, PathBuf)> { |
1845 | matches | |
0531ce1d XL |
1846 | .opt_strs("remap-path-prefix") |
1847 | .into_iter() | |
fc512014 XL |
1848 | .map(|remap| match remap.rsplit_once('=') { |
1849 | None => early_error( | |
1850 | error_format, | |
1851 | "--remap-path-prefix must contain '=' between FROM and TO", | |
1852 | ), | |
1853 | Some((from, to)) => (PathBuf::from(from), PathBuf::from(to)), | |
0531ce1d | 1854 | }) |
e74abb32 XL |
1855 | .collect() |
1856 | } | |
0531ce1d | 1857 | |
e74abb32 XL |
1858 | pub fn build_session_options(matches: &getopts::Matches) -> Options { |
1859 | let color = parse_color(matches); | |
1860 | ||
1861 | let edition = parse_crate_edition(matches); | |
1862 | ||
1863 | let (json_rendered, json_artifact_notifications) = parse_json(matches); | |
1864 | ||
1865 | let error_format = parse_error_format(matches, color, json_rendered); | |
1866 | ||
1867 | let unparsed_crate_types = matches.opt_strs("crate-type"); | |
1868 | let crate_types = parse_crate_types_from_list(unparsed_crate_types) | |
1869 | .unwrap_or_else(|e| early_error(error_format, &e[..])); | |
1870 | ||
1871 | let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format); | |
1872 | ||
1873 | let mut debugging_opts = build_debugging_options(matches, error_format); | |
1874 | check_debug_option_stability(&debugging_opts, error_format, json_rendered); | |
1875 | ||
1876 | let output_types = parse_output_types(&debugging_opts, matches, error_format); | |
1877 | ||
1878 | let mut cg = build_codegen_options(matches, error_format); | |
ba9703b0 | 1879 | let (disable_thinlto, mut codegen_units) = should_override_cgus_and_disable_thinlto( |
e74abb32 XL |
1880 | &output_types, |
1881 | matches, | |
1882 | error_format, | |
1883 | cg.codegen_units, | |
1884 | ); | |
1885 | ||
1886 | check_thread_count(&debugging_opts, error_format); | |
1887 | ||
f20569fa XL |
1888 | let incremental = |
1889 | if std::env::var_os("RUSTC_FORCE_INCREMENTAL").map(|v| v == "1").unwrap_or(false) { | |
1890 | cg.incremental.as_ref().map(PathBuf::from) | |
1891 | } else { | |
1892 | None | |
1893 | }; | |
e74abb32 XL |
1894 | |
1895 | if debugging_opts.profile && incremental.is_some() { | |
1896 | early_error( | |
0531ce1d | 1897 | error_format, |
e74abb32 XL |
1898 | "can't instrument with gcov profiling when compiling incrementally", |
1899 | ); | |
1900 | } | |
ba9703b0 XL |
1901 | if debugging_opts.profile { |
1902 | match codegen_units { | |
1903 | Some(1) => {} | |
1904 | None => codegen_units = Some(1), | |
1905 | Some(_) => early_error( | |
1906 | error_format, | |
1907 | "can't instrument with gcov profiling with multiple codegen units", | |
1908 | ), | |
1909 | } | |
1910 | } | |
e74abb32 XL |
1911 | |
1912 | if cg.profile_generate.enabled() && cg.profile_use.is_some() { | |
1913 | early_error( | |
1914 | error_format, | |
1915 | "options `-C profile-generate` and `-C profile-use` are exclusive", | |
1916 | ); | |
1917 | } | |
1918 | ||
3dfed10e XL |
1919 | if debugging_opts.instrument_coverage { |
1920 | if cg.profile_generate.enabled() || cg.profile_use.is_some() { | |
1921 | early_error( | |
1922 | error_format, | |
1923 | "option `-Z instrument-coverage` is not compatible with either `-C profile-use` \ | |
1924 | or `-C profile-generate`", | |
1925 | ); | |
1926 | } | |
1927 | ||
1b1a35ee XL |
1928 | // `-Z instrument-coverage` implies `-Z symbol-mangling-version=v0` - to ensure consistent |
1929 | // and reversible name mangling. Note, LLVM coverage tools can analyze coverage over | |
1930 | // multiple runs, including some changes to source code; so mangled names must be consistent | |
1931 | // across compilations. | |
fc512014 XL |
1932 | match debugging_opts.symbol_mangling_version { |
1933 | None => { | |
1934 | debugging_opts.symbol_mangling_version = Some(SymbolManglingVersion::V0); | |
1935 | } | |
1936 | Some(SymbolManglingVersion::Legacy) => { | |
1937 | early_warn( | |
1938 | error_format, | |
1939 | "-Z instrument-coverage requires symbol mangling version `v0`, \ | |
1940 | but `-Z symbol-mangling-version=legacy` was specified", | |
1941 | ); | |
1942 | } | |
1943 | Some(SymbolManglingVersion::V0) => {} | |
1944 | } | |
1b1a35ee XL |
1945 | } |
1946 | ||
1947 | if let Ok(graphviz_font) = std::env::var("RUSTC_GRAPHVIZ_FONT") { | |
1948 | debugging_opts.graphviz_font = graphviz_font; | |
3dfed10e XL |
1949 | } |
1950 | ||
f9f354fc XL |
1951 | if !cg.embed_bitcode { |
1952 | match cg.lto { | |
1953 | LtoCli::No | LtoCli::Unspecified => {} | |
1954 | LtoCli::Yes | LtoCli::NoParam | LtoCli::Thin | LtoCli::Fat => early_error( | |
1955 | error_format, | |
1956 | "options `-C embed-bitcode=no` and `-C lto` are incompatible", | |
1957 | ), | |
1958 | } | |
1959 | } | |
1960 | ||
dfeec247 | 1961 | let prints = collect_print_requests(&mut cg, &mut debugging_opts, matches, error_format); |
e74abb32 XL |
1962 | |
1963 | let cg = cg; | |
1964 | ||
1965 | let sysroot_opt = matches.opt_str("sysroot").map(|m| PathBuf::from(&m)); | |
1966 | let target_triple = parse_target_triple(matches, error_format); | |
1967 | let opt_level = parse_opt_level(matches, &cg, error_format); | |
1968 | // The `-g` and `-C debuginfo` flags specify the same setting, so we want to be able | |
1969 | // to use them interchangeably. See the note above (regarding `-O` and `-C opt-level`) | |
1970 | // for more details. | |
1971 | let debug_assertions = cg.debug_assertions.unwrap_or(opt_level == OptLevel::No); | |
1972 | let debuginfo = select_debuginfo(matches, &cg, error_format); | |
1973 | ||
1974 | let mut search_paths = vec![]; | |
1975 | for s in &matches.opt_strs("L") { | |
1976 | search_paths.push(SearchPath::from_cli_opt(&s[..], error_format)); | |
1977 | } | |
1978 | ||
1979 | let libs = parse_libs(matches, error_format); | |
1980 | ||
1981 | let test = matches.opt_present("test"); | |
1982 | ||
1983 | let borrowck_mode = parse_borrowck_mode(&debugging_opts, error_format); | |
1984 | ||
1985 | if !cg.remark.is_empty() && debuginfo == DebugInfo::None { | |
dfeec247 | 1986 | early_warn(error_format, "-C remark requires \"-C debuginfo=n\" to show source locations"); |
e74abb32 XL |
1987 | } |
1988 | ||
60c5eb7d | 1989 | let externs = parse_externs(matches, &debugging_opts, error_format); |
6a06907d | 1990 | let extern_dep_specs = parse_extern_dep_specs(matches, &debugging_opts, error_format); |
e74abb32 XL |
1991 | |
1992 | let crate_name = matches.opt_str("crate-name"); | |
1993 | ||
1994 | let remap_path_prefix = parse_remap_path_prefix(matches, error_format); | |
1995 | ||
60c5eb7d XL |
1996 | let pretty = parse_pretty(matches, &debugging_opts, error_format); |
1997 | ||
5869c6ff XL |
1998 | if !debugging_opts.unstable_options |
1999 | && !target_triple.triple().contains("apple") | |
2000 | && cg.split_debuginfo.is_some() | |
2001 | { | |
2002 | { | |
2003 | early_error(error_format, "`-Csplit-debuginfo` is unstable on this platform"); | |
2004 | } | |
2005 | } | |
2006 | ||
e74abb32 XL |
2007 | Options { |
2008 | crate_types, | |
2009 | optimize: opt_level, | |
2010 | debuginfo, | |
2011 | lint_opts, | |
2012 | lint_cap, | |
2013 | describe_lints, | |
2014 | output_types, | |
2015 | search_paths, | |
2016 | maybe_sysroot: sysroot_opt, | |
2017 | target_triple, | |
2018 | test, | |
2019 | incremental, | |
2020 | debugging_opts, | |
2021 | prints, | |
2022 | borrowck_mode, | |
2023 | cg, | |
2024 | error_format, | |
2025 | externs, | |
fc512014 | 2026 | unstable_features: UnstableFeatures::from_environment(crate_name.as_deref()), |
6a06907d | 2027 | extern_dep_specs, |
e74abb32 XL |
2028 | crate_name, |
2029 | alt_std_name: None, | |
2030 | libs, | |
e74abb32 XL |
2031 | debug_assertions, |
2032 | actually_rustdoc: false, | |
1b1a35ee | 2033 | trimmed_def_paths: TrimmedDefPaths::default(), |
e74abb32 XL |
2034 | cli_forced_codegen_units: codegen_units, |
2035 | cli_forced_thinlto_off: disable_thinlto, | |
2036 | remap_path_prefix, | |
2037 | edition, | |
2038 | json_artifact_notifications, | |
60c5eb7d XL |
2039 | pretty, |
2040 | } | |
2041 | } | |
2042 | ||
2043 | fn parse_pretty( | |
2044 | matches: &getopts::Matches, | |
2045 | debugging_opts: &DebuggingOptions, | |
2046 | efmt: ErrorOutputType, | |
2047 | ) -> Option<PpMode> { | |
dfeec247 | 2048 | fn parse_pretty_inner(efmt: ErrorOutputType, name: &str, extended: bool) -> PpMode { |
60c5eb7d | 2049 | use PpMode::*; |
60c5eb7d | 2050 | let first = match (name, extended) { |
6a06907d XL |
2051 | ("normal", _) => Source(PpSourceMode::Normal), |
2052 | ("identified", _) => Source(PpSourceMode::Identified), | |
2053 | ("everybody_loops", true) => Source(PpSourceMode::EveryBodyLoops), | |
2054 | ("expanded", _) => Source(PpSourceMode::Expanded), | |
2055 | ("expanded,identified", _) => Source(PpSourceMode::ExpandedIdentified), | |
2056 | ("expanded,hygiene", _) => Source(PpSourceMode::ExpandedHygiene), | |
2057 | ("ast-tree", true) => AstTree(PpAstTreeMode::Normal), | |
2058 | ("ast-tree,expanded", true) => AstTree(PpAstTreeMode::Expanded), | |
2059 | ("hir", true) => Hir(PpHirMode::Normal), | |
2060 | ("hir,identified", true) => Hir(PpHirMode::Identified), | |
2061 | ("hir,typed", true) => Hir(PpHirMode::Typed), | |
2062 | ("hir-tree", true) => HirTree, | |
2063 | ("thir-tree", true) => ThirTree, | |
2064 | ("mir", true) => Mir, | |
2065 | ("mir-cfg", true) => MirCFG, | |
60c5eb7d XL |
2066 | _ => { |
2067 | if extended { | |
dfeec247 XL |
2068 | early_error( |
2069 | efmt, | |
2070 | &format!( | |
2071 | "argument to `unpretty` must be one of `normal`, \ | |
60c5eb7d XL |
2072 | `expanded`, `identified`, `expanded,identified`, \ |
2073 | `expanded,hygiene`, `everybody_loops`, \ | |
6a06907d XL |
2074 | `ast-tree`, `ast-tree,expanded`, `hir`, `hir,identified`, \ |
2075 | `hir,typed`, `hir-tree`, `mir` or `mir-cfg`; got {}", | |
dfeec247 XL |
2076 | name |
2077 | ), | |
2078 | ); | |
60c5eb7d | 2079 | } else { |
dfeec247 XL |
2080 | early_error( |
2081 | efmt, | |
2082 | &format!( | |
2083 | "argument to `pretty` must be one of `normal`, \ | |
60c5eb7d | 2084 | `expanded`, `identified`, or `expanded,identified`; got {}", |
dfeec247 XL |
2085 | name |
2086 | ), | |
2087 | ); | |
60c5eb7d XL |
2088 | } |
2089 | } | |
2090 | }; | |
3dfed10e | 2091 | tracing::debug!("got unpretty option: {:?}", first); |
60c5eb7d | 2092 | first |
e74abb32 | 2093 | } |
6a06907d XL |
2094 | |
2095 | if debugging_opts.unstable_options { | |
2096 | if let Some(a) = matches.opt_default("pretty", "normal") { | |
2097 | // stable pretty-print variants only | |
2098 | return Some(parse_pretty_inner(efmt, &a, false)); | |
2099 | } | |
2100 | } | |
2101 | ||
2102 | debugging_opts.unpretty.as_ref().map(|a| { | |
2103 | // extended with unstable pretty-print variants | |
2104 | parse_pretty_inner(efmt, &a, true) | |
2105 | }) | |
85aaf69f SL |
2106 | } |
2107 | ||
e1599b0c XL |
2108 | pub fn make_crate_type_option() -> RustcOptGroup { |
2109 | opt::multi_s( | |
2110 | "", | |
2111 | "crate-type", | |
2112 | "Comma separated list of types of crates | |
2113 | for the compiler to emit", | |
2114 | "[bin|lib|rlib|dylib|cdylib|staticlib|proc-macro]", | |
2115 | ) | |
2116 | } | |
2117 | ||
0531ce1d | 2118 | pub fn parse_crate_types_from_list(list_list: Vec<String>) -> Result<Vec<CrateType>, String> { |
1a4d82fc | 2119 | let mut crate_types: Vec<CrateType> = Vec::new(); |
85aaf69f | 2120 | for unparsed_crate_type in &list_list { |
1a4d82fc JJ |
2121 | for part in unparsed_crate_type.split(',') { |
2122 | let new_part = match part { | |
0531ce1d | 2123 | "lib" => default_lib_output(), |
b7449926 XL |
2124 | "rlib" => CrateType::Rlib, |
2125 | "staticlib" => CrateType::Staticlib, | |
2126 | "dylib" => CrateType::Dylib, | |
2127 | "cdylib" => CrateType::Cdylib, | |
2128 | "bin" => CrateType::Executable, | |
2129 | "proc-macro" => CrateType::ProcMacro, | |
dfeec247 | 2130 | _ => return Err(format!("unknown crate type: `{}`", part)), |
1a4d82fc | 2131 | }; |
85aaf69f SL |
2132 | if !crate_types.contains(&new_part) { |
2133 | crate_types.push(new_part) | |
2134 | } | |
1a4d82fc JJ |
2135 | } |
2136 | } | |
2137 | ||
7cac9316 | 2138 | Ok(crate_types) |
1a4d82fc JJ |
2139 | } |
2140 | ||
54a0048b | 2141 | pub mod nightly_options { |
9e0c209e | 2142 | use super::{ErrorOutputType, OptionStability, RustcOptGroup}; |
60c5eb7d | 2143 | use crate::early_error; |
dfeec247 | 2144 | use rustc_feature::UnstableFeatures; |
54a0048b SL |
2145 | |
2146 | pub fn is_unstable_enabled(matches: &getopts::Matches) -> bool { | |
fc512014 XL |
2147 | match_is_nightly_build(matches) |
2148 | && matches.opt_strs("Z").iter().any(|x| *x == "unstable-options") | |
2149 | } | |
2150 | ||
2151 | pub fn match_is_nightly_build(matches: &getopts::Matches) -> bool { | |
2152 | is_nightly_build(matches.opt_str("crate-name").as_deref()) | |
54a0048b SL |
2153 | } |
2154 | ||
fc512014 XL |
2155 | pub fn is_nightly_build(krate: Option<&str>) -> bool { |
2156 | UnstableFeatures::from_environment(krate).is_nightly_build() | |
54a0048b SL |
2157 | } |
2158 | ||
2159 | pub fn check_nightly_options(matches: &getopts::Matches, flags: &[RustcOptGroup]) { | |
dfeec247 | 2160 | let has_z_unstable_option = matches.opt_strs("Z").iter().any(|x| *x == "unstable-options"); |
fc512014 | 2161 | let really_allows_unstable_options = match_is_nightly_build(matches); |
54a0048b SL |
2162 | |
2163 | for opt in flags.iter() { | |
2164 | if opt.stability == OptionStability::Stable { | |
0531ce1d | 2165 | continue; |
54a0048b | 2166 | } |
041b39d2 | 2167 | if !matches.opt_present(opt.name) { |
0531ce1d | 2168 | continue; |
54a0048b | 2169 | } |
041b39d2 | 2170 | if opt.name != "Z" && !has_z_unstable_option { |
0531ce1d XL |
2171 | early_error( |
2172 | ErrorOutputType::default(), | |
2173 | &format!( | |
2174 | "the `-Z unstable-options` flag must also be passed to enable \ | |
2175 | the flag `{}`", | |
2176 | opt.name | |
2177 | ), | |
2178 | ); | |
54a0048b SL |
2179 | } |
2180 | if really_allows_unstable_options { | |
0531ce1d | 2181 | continue; |
54a0048b SL |
2182 | } |
2183 | match opt.stability { | |
2184 | OptionStability::Unstable => { | |
0531ce1d XL |
2185 | let msg = format!( |
2186 | "the option `{}` is only accepted on the \ | |
2187 | nightly compiler", | |
2188 | opt.name | |
2189 | ); | |
54a0048b SL |
2190 | early_error(ErrorOutputType::default(), &msg); |
2191 | } | |
54a0048b SL |
2192 | OptionStability::Stable => {} |
2193 | } | |
2194 | } | |
2195 | } | |
2196 | } | |
2197 | ||
85aaf69f | 2198 | impl fmt::Display for CrateType { |
0bf4aa26 | 2199 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1a4d82fc | 2200 | match *self { |
b7449926 XL |
2201 | CrateType::Executable => "bin".fmt(f), |
2202 | CrateType::Dylib => "dylib".fmt(f), | |
2203 | CrateType::Rlib => "rlib".fmt(f), | |
2204 | CrateType::Staticlib => "staticlib".fmt(f), | |
2205 | CrateType::Cdylib => "cdylib".fmt(f), | |
2206 | CrateType::ProcMacro => "proc-macro".fmt(f), | |
1a4d82fc JJ |
2207 | } |
2208 | } | |
2209 | } | |
2210 | ||
60c5eb7d XL |
2211 | #[derive(Copy, Clone, PartialEq, Debug)] |
2212 | pub enum PpSourceMode { | |
6a06907d XL |
2213 | /// `--pretty=normal` |
2214 | Normal, | |
2215 | /// `-Zunpretty=everybody_loops` | |
2216 | EveryBodyLoops, | |
2217 | /// `--pretty=expanded` | |
2218 | Expanded, | |
2219 | /// `--pretty=identified` | |
2220 | Identified, | |
2221 | /// `--pretty=expanded,identified` | |
2222 | ExpandedIdentified, | |
2223 | /// `--pretty=expanded,hygiene` | |
2224 | ExpandedHygiene, | |
2225 | } | |
2226 | ||
2227 | #[derive(Copy, Clone, PartialEq, Debug)] | |
2228 | pub enum PpAstTreeMode { | |
2229 | /// `-Zunpretty=ast` | |
2230 | Normal, | |
2231 | /// `-Zunpretty=ast,expanded` | |
2232 | Expanded, | |
2233 | } | |
2234 | ||
2235 | #[derive(Copy, Clone, PartialEq, Debug)] | |
2236 | pub enum PpHirMode { | |
2237 | /// `-Zunpretty=hir` | |
2238 | Normal, | |
2239 | /// `-Zunpretty=hir,identified` | |
2240 | Identified, | |
2241 | /// `-Zunpretty=hir,typed` | |
2242 | Typed, | |
60c5eb7d XL |
2243 | } |
2244 | ||
2245 | #[derive(Copy, Clone, PartialEq, Debug)] | |
2246 | pub enum PpMode { | |
6a06907d XL |
2247 | /// Options that print the source code, i.e. |
2248 | /// `--pretty` and `-Zunpretty=everybody_loops` | |
2249 | Source(PpSourceMode), | |
2250 | AstTree(PpAstTreeMode), | |
2251 | /// Options that print the HIR, i.e. `-Zunpretty=hir` | |
2252 | Hir(PpHirMode), | |
2253 | /// `-Zunpretty=hir-tree` | |
2254 | HirTree, | |
2255 | /// `-Zunpretty=thir-tree` | |
2256 | ThirTree, | |
2257 | /// `-Zunpretty=mir` | |
2258 | Mir, | |
2259 | /// `-Zunpretty=mir-cfg` | |
2260 | MirCFG, | |
60c5eb7d XL |
2261 | } |
2262 | ||
2263 | impl PpMode { | |
2264 | pub fn needs_ast_map(&self) -> bool { | |
2265 | use PpMode::*; | |
2266 | use PpSourceMode::*; | |
2267 | match *self { | |
6a06907d XL |
2268 | Source(Normal | Identified) | AstTree(PpAstTreeMode::Normal) => false, |
2269 | ||
2270 | Source(Expanded | EveryBodyLoops | ExpandedIdentified | ExpandedHygiene) | |
2271 | | AstTree(PpAstTreeMode::Expanded) | |
2272 | | Hir(_) | |
2273 | | HirTree | |
2274 | | ThirTree | |
2275 | | Mir | |
2276 | | MirCFG => true, | |
60c5eb7d XL |
2277 | } |
2278 | } | |
2279 | ||
2280 | pub fn needs_analysis(&self) -> bool { | |
2281 | use PpMode::*; | |
6a06907d | 2282 | matches!(*self, Mir | MirCFG) |
60c5eb7d XL |
2283 | } |
2284 | } | |
2285 | ||
a1dfa0c6 | 2286 | /// Command-line arguments passed to the compiler have to be incorporated with |
5bcae85e SL |
2287 | /// the dependency tracking system for incremental compilation. This module |
2288 | /// provides some utilities to make this more convenient. | |
2289 | /// | |
a1dfa0c6 | 2290 | /// The values of all command-line arguments that are relevant for dependency |
5bcae85e SL |
2291 | /// tracking are hashed into a single value that determines whether the |
2292 | /// incremental compilation cache can be re-used or not. This hashing is done | |
e1599b0c XL |
2293 | /// via the `DepTrackingHash` trait defined below, since the standard `Hash` |
2294 | /// implementation might not be suitable (e.g., arguments are stored in a `Vec`, | |
5bcae85e SL |
2295 | /// the hash of which is order dependent, but we might not want the order of |
2296 | /// arguments to make a difference for the hash). | |
2297 | /// | |
e1599b0c | 2298 | /// However, since the value provided by `Hash::hash` often *is* suitable, |
5bcae85e | 2299 | /// especially for primitive types, there is the |
e1599b0c XL |
2300 | /// `impl_dep_tracking_hash_via_hash!()` macro that allows to simply reuse the |
2301 | /// `Hash` implementation for `DepTrackingHash`. It's important though that | |
5bcae85e | 2302 | /// we have an opt-in scheme here, so one is hopefully forced to think about |
a1dfa0c6 | 2303 | /// how the hash should be calculated when adding a new command-line argument. |
dfeec247 XL |
2304 | crate mod dep_tracking { |
2305 | use super::{ | |
74b04a01 | 2306 | CFGuard, CrateType, DebugInfo, ErrorOutputType, LinkerPluginLto, LtoCli, OptLevel, |
f035d41b | 2307 | OutputTypes, Passes, SanitizerSet, SourceFileHashAlgorithm, SwitchWithOptPath, |
1b1a35ee | 2308 | SymbolManglingVersion, TrimmedDefPaths, |
dfeec247 | 2309 | }; |
9fa01778 | 2310 | use crate::lint; |
5869c6ff | 2311 | use crate::options::WasiExecModel; |
f9f354fc | 2312 | use crate::utils::NativeLibKind; |
dfeec247 XL |
2313 | use rustc_feature::UnstableFeatures; |
2314 | use rustc_span::edition::Edition; | |
f9f354fc | 2315 | use rustc_target::spec::{CodeModel, MergeFunctions, PanicStrategy, RelocModel}; |
5869c6ff | 2316 | use rustc_target::spec::{RelroLevel, SplitDebuginfo, TargetTriple, TlsModel}; |
dfeec247 | 2317 | use std::collections::hash_map::DefaultHasher; |
5bcae85e | 2318 | use std::collections::BTreeMap; |
9e0c209e | 2319 | use std::hash::Hash; |
6a06907d | 2320 | use std::num::NonZeroUsize; |
5bcae85e | 2321 | use std::path::PathBuf; |
5bcae85e SL |
2322 | |
2323 | pub trait DepTrackingHash { | |
7cac9316 | 2324 | fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType); |
5bcae85e SL |
2325 | } |
2326 | ||
2327 | macro_rules! impl_dep_tracking_hash_via_hash { | |
dfeec247 | 2328 | ($t:ty) => { |
5bcae85e | 2329 | impl DepTrackingHash for $t { |
9e0c209e | 2330 | fn hash(&self, hasher: &mut DefaultHasher, _: ErrorOutputType) { |
5bcae85e SL |
2331 | Hash::hash(self, hasher); |
2332 | } | |
2333 | } | |
dfeec247 | 2334 | }; |
5bcae85e SL |
2335 | } |
2336 | ||
2337 | macro_rules! impl_dep_tracking_hash_for_sortable_vec_of { | |
dfeec247 | 2338 | ($t:ty) => { |
5bcae85e | 2339 | impl DepTrackingHash for Vec<$t> { |
9e0c209e | 2340 | fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) { |
5bcae85e SL |
2341 | let mut elems: Vec<&$t> = self.iter().collect(); |
2342 | elems.sort(); | |
2343 | Hash::hash(&elems.len(), hasher); | |
2344 | for (index, elem) in elems.iter().enumerate() { | |
2345 | Hash::hash(&index, hasher); | |
2346 | DepTrackingHash::hash(*elem, hasher, error_format); | |
2347 | } | |
2348 | } | |
2349 | } | |
dfeec247 | 2350 | }; |
5bcae85e SL |
2351 | } |
2352 | ||
2353 | impl_dep_tracking_hash_via_hash!(bool); | |
2354 | impl_dep_tracking_hash_via_hash!(usize); | |
cc61c64b | 2355 | impl_dep_tracking_hash_via_hash!(u64); |
5bcae85e | 2356 | impl_dep_tracking_hash_via_hash!(String); |
ff7c6d11 | 2357 | impl_dep_tracking_hash_via_hash!(PathBuf); |
5bcae85e SL |
2358 | impl_dep_tracking_hash_via_hash!(lint::Level); |
2359 | impl_dep_tracking_hash_via_hash!(Option<bool>); | |
2360 | impl_dep_tracking_hash_via_hash!(Option<usize>); | |
6a06907d | 2361 | impl_dep_tracking_hash_via_hash!(Option<NonZeroUsize>); |
5bcae85e | 2362 | impl_dep_tracking_hash_via_hash!(Option<String>); |
cc61c64b | 2363 | impl_dep_tracking_hash_via_hash!(Option<(String, u64)>); |
9fa01778 XL |
2364 | impl_dep_tracking_hash_via_hash!(Option<Vec<String>>); |
2365 | impl_dep_tracking_hash_via_hash!(Option<MergeFunctions>); | |
f9f354fc XL |
2366 | impl_dep_tracking_hash_via_hash!(Option<RelocModel>); |
2367 | impl_dep_tracking_hash_via_hash!(Option<CodeModel>); | |
2368 | impl_dep_tracking_hash_via_hash!(Option<TlsModel>); | |
5869c6ff | 2369 | impl_dep_tracking_hash_via_hash!(Option<WasiExecModel>); |
c30ab7b3 | 2370 | impl_dep_tracking_hash_via_hash!(Option<PanicStrategy>); |
3b2f2976 | 2371 | impl_dep_tracking_hash_via_hash!(Option<RelroLevel>); |
5bcae85e SL |
2372 | impl_dep_tracking_hash_via_hash!(Option<lint::Level>); |
2373 | impl_dep_tracking_hash_via_hash!(Option<PathBuf>); | |
2374 | impl_dep_tracking_hash_via_hash!(CrateType); | |
9fa01778 | 2375 | impl_dep_tracking_hash_via_hash!(MergeFunctions); |
5bcae85e | 2376 | impl_dep_tracking_hash_via_hash!(PanicStrategy); |
3b2f2976 | 2377 | impl_dep_tracking_hash_via_hash!(RelroLevel); |
5bcae85e SL |
2378 | impl_dep_tracking_hash_via_hash!(Passes); |
2379 | impl_dep_tracking_hash_via_hash!(OptLevel); | |
b7449926 XL |
2380 | impl_dep_tracking_hash_via_hash!(LtoCli); |
2381 | impl_dep_tracking_hash_via_hash!(DebugInfo); | |
5bcae85e | 2382 | impl_dep_tracking_hash_via_hash!(UnstableFeatures); |
5bcae85e | 2383 | impl_dep_tracking_hash_via_hash!(OutputTypes); |
f9f354fc | 2384 | impl_dep_tracking_hash_via_hash!(NativeLibKind); |
f035d41b | 2385 | impl_dep_tracking_hash_via_hash!(SanitizerSet); |
74b04a01 | 2386 | impl_dep_tracking_hash_via_hash!(CFGuard); |
0531ce1d | 2387 | impl_dep_tracking_hash_via_hash!(TargetTriple); |
83c7162d | 2388 | impl_dep_tracking_hash_via_hash!(Edition); |
9fa01778 | 2389 | impl_dep_tracking_hash_via_hash!(LinkerPluginLto); |
5869c6ff | 2390 | impl_dep_tracking_hash_via_hash!(Option<SplitDebuginfo>); |
dc9dc135 | 2391 | impl_dep_tracking_hash_via_hash!(SwitchWithOptPath); |
fc512014 | 2392 | impl_dep_tracking_hash_via_hash!(Option<SymbolManglingVersion>); |
ba9703b0 | 2393 | impl_dep_tracking_hash_via_hash!(Option<SourceFileHashAlgorithm>); |
1b1a35ee | 2394 | impl_dep_tracking_hash_via_hash!(TrimmedDefPaths); |
5bcae85e SL |
2395 | |
2396 | impl_dep_tracking_hash_for_sortable_vec_of!(String); | |
ff7c6d11 | 2397 | impl_dep_tracking_hash_for_sortable_vec_of!(PathBuf); |
5bcae85e SL |
2398 | impl_dep_tracking_hash_for_sortable_vec_of!(CrateType); |
2399 | impl_dep_tracking_hash_for_sortable_vec_of!((String, lint::Level)); | |
f9f354fc | 2400 | impl_dep_tracking_hash_for_sortable_vec_of!((String, Option<String>, NativeLibKind)); |
cc61c64b | 2401 | impl_dep_tracking_hash_for_sortable_vec_of!((String, u64)); |
5bcae85e SL |
2402 | |
2403 | impl<T1, T2> DepTrackingHash for (T1, T2) | |
0531ce1d XL |
2404 | where |
2405 | T1: DepTrackingHash, | |
2406 | T2: DepTrackingHash, | |
5bcae85e | 2407 | { |
9e0c209e | 2408 | fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) { |
5bcae85e SL |
2409 | Hash::hash(&0, hasher); |
2410 | DepTrackingHash::hash(&self.0, hasher, error_format); | |
2411 | Hash::hash(&1, hasher); | |
2412 | DepTrackingHash::hash(&self.1, hasher, error_format); | |
2413 | } | |
2414 | } | |
2415 | ||
476ff2be | 2416 | impl<T1, T2, T3> DepTrackingHash for (T1, T2, T3) |
0531ce1d XL |
2417 | where |
2418 | T1: DepTrackingHash, | |
2419 | T2: DepTrackingHash, | |
2420 | T3: DepTrackingHash, | |
476ff2be SL |
2421 | { |
2422 | fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) { | |
2423 | Hash::hash(&0, hasher); | |
2424 | DepTrackingHash::hash(&self.0, hasher, error_format); | |
2425 | Hash::hash(&1, hasher); | |
2426 | DepTrackingHash::hash(&self.1, hasher, error_format); | |
2427 | Hash::hash(&2, hasher); | |
2428 | DepTrackingHash::hash(&self.2, hasher, error_format); | |
2429 | } | |
2430 | } | |
2431 | ||
5bcae85e | 2432 | // This is a stable hash because BTreeMap is a sorted container |
0531ce1d XL |
2433 | pub fn stable_hash( |
2434 | sub_hashes: BTreeMap<&'static str, &dyn DepTrackingHash>, | |
2435 | hasher: &mut DefaultHasher, | |
2436 | error_format: ErrorOutputType, | |
2437 | ) { | |
5bcae85e SL |
2438 | for (key, sub_hash) in sub_hashes { |
2439 | // Using Hash::hash() instead of DepTrackingHash::hash() is fine for | |
2440 | // the keys, as they are just plain strings | |
2441 | Hash::hash(&key.len(), hasher); | |
2442 | Hash::hash(key, hasher); | |
2443 | sub_hash.hash(hasher, error_format); | |
2444 | } | |
2445 | } | |
2446 | } |