1use std::collections::BTreeMap;
2use std::num::{IntErrorKind, NonZero};
3use std::path::PathBuf;
4use std::str;
5
6use rustc_abi::Align;
7use rustc_data_structures::fx::FxIndexMap;
8use rustc_data_structures::profiling::TimePassesFormat;
9use rustc_data_structures::stable_hasher::StableHasher;
10use rustc_errors::{ColorConfig, LanguageIdentifier, TerminalUrl};
11use rustc_feature::UnstableFeatures;
12use rustc_hashes::Hash64;
13use rustc_macros::{Decodable, Encodable};
14use rustc_span::edition::Edition;
15use rustc_span::{RealFileName, SourceFileHashAlgorithm};
16use rustc_target::spec::{
17 CodeModel, FramePointer, LinkerFlavorCli, MergeFunctions, OnBrokenPipe, PanicStrategy,
18 RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, SymbolVisibility,
19 TargetTuple, TlsModel,
20};
21
22use crate::config::*;
23use crate::search_paths::SearchPath;
24use crate::utils::NativeLib;
25use crate::{EarlyDiagCtxt, lint};
26
27macro_rules! insert {
28 ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr) => {
29 if $sub_hashes
30 .insert(stringify!($opt_name), $opt_expr as &dyn dep_tracking::DepTrackingHash)
31 .is_some()
32 {
33 panic!("duplicate key in CLI DepTrackingHash: {}", stringify!($opt_name))
34 }
35 };
36}
37
38macro_rules! hash_opt {
39 ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, $_for_crate_hash: ident, [UNTRACKED]) => {{}};
40 ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, $_for_crate_hash: ident, [TRACKED]) => {{ insert!($opt_name, $opt_expr, $sub_hashes) }};
41 ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, $for_crate_hash: ident, [TRACKED_NO_CRATE_HASH]) => {{
42 if !$for_crate_hash {
43 insert!($opt_name, $opt_expr, $sub_hashes)
44 }
45 }};
46 ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, $_for_crate_hash: ident, [SUBSTRUCT]) => {{}};
47}
48
49macro_rules! hash_substruct {
50 ($opt_name:ident, $opt_expr:expr, $error_format:expr, $for_crate_hash:expr, $hasher:expr, [UNTRACKED]) => {{}};
51 ($opt_name:ident, $opt_expr:expr, $error_format:expr, $for_crate_hash:expr, $hasher:expr, [TRACKED]) => {{}};
52 ($opt_name:ident, $opt_expr:expr, $error_format:expr, $for_crate_hash:expr, $hasher:expr, [TRACKED_NO_CRATE_HASH]) => {{}};
53 ($opt_name:ident, $opt_expr:expr, $error_format:expr, $for_crate_hash:expr, $hasher:expr, [SUBSTRUCT]) => {
54 use crate::config::dep_tracking::DepTrackingHash;
55 $opt_expr.dep_tracking_hash($for_crate_hash, $error_format).hash(
56 $hasher,
57 $error_format,
58 $for_crate_hash,
59 );
60 };
61}
62
63pub struct ExtendedTargetModifierInfo {
68 pub prefix: String,
70 pub name: String,
72 pub tech_value: String,
74}
75
76#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable)]
79pub struct TargetModifier {
80 pub opt: OptionsTargetModifiers,
82 pub value_name: String,
84}
85
86impl TargetModifier {
87 pub fn extend(&self) -> ExtendedTargetModifierInfo {
88 self.opt.reparse(&self.value_name)
89 }
90}
91
92fn tmod_push_impl(
93 opt: OptionsTargetModifiers,
94 tmod_vals: &BTreeMap<OptionsTargetModifiers, String>,
95 tmods: &mut Vec<TargetModifier>,
96) {
97 if let Some(v) = tmod_vals.get(&opt) {
98 tmods.push(TargetModifier { opt, value_name: v.clone() })
99 }
100}
101
102macro_rules! tmod_push {
103 ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr) => {
104 if *$opt_expr != $init {
105 tmod_push_impl(
106 OptionsTargetModifiers::$struct_name($tmod_enum_name::$opt_name),
107 $tmod_vals,
108 $mods,
109 );
110 }
111 };
112}
113
114macro_rules! gather_tmods {
115 ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr,
116 [SUBSTRUCT], [TARGET_MODIFIER]) => {
117 compile_error!("SUBSTRUCT can't be target modifier");
118 };
119 ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr,
120 [UNTRACKED], [TARGET_MODIFIER]) => {
121 tmod_push!($struct_name, $tmod_enum_name, $opt_name, $opt_expr, $init, $mods, $tmod_vals)
122 };
123 ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr,
124 [TRACKED], [TARGET_MODIFIER]) => {
125 tmod_push!($struct_name, $tmod_enum_name, $opt_name, $opt_expr, $init, $mods, $tmod_vals)
126 };
127 ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr,
128 [TRACKED_NO_CRATE_HASH], [TARGET_MODIFIER]) => {
129 tmod_push!($struct_name, $tmod_enum_name, $opt_name, $opt_expr, $init, $mods, $tmod_vals)
130 };
131 ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr,
132 [SUBSTRUCT], []) => {
133 $opt_expr.gather_target_modifiers($mods, $tmod_vals);
134 };
135 ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr,
136 [UNTRACKED], []) => {{}};
137 ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr,
138 [TRACKED], []) => {{}};
139 ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr,
140 [TRACKED_NO_CRATE_HASH], []) => {{}};
141}
142
143macro_rules! gather_tmods_top_level {
144 ($_opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr, [SUBSTRUCT $substruct_enum:ident]) => {
145 $opt_expr.gather_target_modifiers($mods, $tmod_vals);
146 };
147 ($opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr, [$non_substruct:ident TARGET_MODIFIER]) => {
148 compile_error!("Top level option can't be target modifier");
149 };
150 ($opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr, [$non_substruct:ident]) => {};
151}
152
153macro_rules! top_level_tmod_enum {
174 ($( {$($optinfo:tt)*} ),* $(,)*) => {
175 top_level_tmod_enum! { @parse {}, (user_value){}; $($($optinfo)*|)* }
176 };
177 (
179 @parse
180 {$($variant:tt($substruct_enum:tt))*},
181 ($user_value:ident){$($pout:tt)*};
182 ) => {
183 #[allow(non_camel_case_types)]
184 #[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Copy, Clone, Encodable, Decodable)]
185 pub enum OptionsTargetModifiers {
186 $($variant($substruct_enum)),*
187 }
188 impl OptionsTargetModifiers {
189 #[allow(unused_variables)]
190 pub fn reparse(&self, $user_value: &str) -> ExtendedTargetModifierInfo {
191 #[allow(unreachable_patterns)]
192 match self {
193 $($pout)*
194 _ => panic!("unknown target modifier option: {:?}", *self)
195 }
196 }
197 pub fn is_target_modifier(flag_name: &str) -> bool {
198 $($substruct_enum::is_target_modifier(flag_name))||*
199 }
200 }
201 };
202 (
204 @parse {$($eout:tt)*}, ($puser_value:ident){$($pout:tt)*};
205 [SUBSTRUCT $substruct_enum:ident $variant:ident] |
206 $($tail:tt)*
207 ) => {
208 top_level_tmod_enum! {
209 @parse
210 {
211 $($eout)*
212 $variant($substruct_enum)
213 },
214 ($puser_value){
215 $($pout)*
216 Self::$variant(v) => v.reparse($puser_value),
217 };
218 $($tail)*
219 }
220 };
221 (
223 @parse {$($eout:tt)*}, ($puser_value:ident){$($pout:tt)*};
224 [$non_substruct:ident] |
225 $($tail:tt)*
226 ) => {
227 top_level_tmod_enum! {
228 @parse
229 {
230 $($eout)*
231 },
232 ($puser_value){
233 $($pout)*
234 };
235 $($tail)*
236 }
237 };
238}
239
240macro_rules! top_level_options {
241 ( $( #[$top_level_attr:meta] )* pub struct Options { $(
242 $( #[$attr:meta] )*
243 $opt:ident : $t:ty [$dep_tracking_marker:ident $( $tmod:ident $variant:ident )?],
244 )* } ) => (
245 top_level_tmod_enum!( {$([$dep_tracking_marker $($tmod $variant),*])|*} );
246
247 #[derive(Clone)]
248 $( #[$top_level_attr] )*
249 pub struct Options {
250 $(
251 $( #[$attr] )*
252 pub $opt: $t
253 ),*,
254 pub target_modifiers: BTreeMap<OptionsTargetModifiers, String>,
255 }
256
257 impl Options {
258 pub fn dep_tracking_hash(&self, for_crate_hash: bool) -> Hash64 {
259 let mut sub_hashes = BTreeMap::new();
260 $({
261 hash_opt!($opt,
262 &self.$opt,
263 &mut sub_hashes,
264 for_crate_hash,
265 [$dep_tracking_marker]);
266 })*
267 let mut hasher = StableHasher::new();
268 dep_tracking::stable_hash(sub_hashes,
269 &mut hasher,
270 self.error_format,
271 for_crate_hash);
272 $({
273 hash_substruct!($opt,
274 &self.$opt,
275 self.error_format,
276 for_crate_hash,
277 &mut hasher,
278 [$dep_tracking_marker]);
279 })*
280 hasher.finish()
281 }
282
283 pub fn gather_target_modifiers(&self) -> Vec<TargetModifier> {
284 let mut mods = Vec::<TargetModifier>::new();
285 $({
286 gather_tmods_top_level!($opt,
287 &self.$opt, &mut mods, &self.target_modifiers,
288 [$dep_tracking_marker $($tmod),*]);
289 })*
290 mods.sort_by(|a, b| a.opt.cmp(&b.opt));
291 mods
292 }
293 }
294 );
295}
296
297top_level_options!(
298 #[rustc_lint_opt_ty]
323 pub struct Options {
324 #[rustc_lint_opt_deny_field_access("use `TyCtxt::crate_types` instead of this field")]
327 crate_types: Vec<CrateType> [TRACKED],
328 optimize: OptLevel [TRACKED],
329 debug_assertions: bool [TRACKED],
332 debuginfo: DebugInfo [TRACKED],
333 debuginfo_compression: DebugInfoCompression [TRACKED],
334 lint_opts: Vec<(String, lint::Level)> [TRACKED_NO_CRATE_HASH],
335 lint_cap: Option<lint::Level> [TRACKED_NO_CRATE_HASH],
336 describe_lints: bool [UNTRACKED],
337 output_types: OutputTypes [TRACKED],
338 search_paths: Vec<SearchPath> [UNTRACKED],
339 libs: Vec<NativeLib> [TRACKED],
340 sysroot: PathBuf [UNTRACKED],
341
342 target_triple: TargetTuple [TRACKED],
343
344 logical_env: FxIndexMap<String, String> [TRACKED],
346
347 test: bool [TRACKED],
348 error_format: ErrorOutputType [UNTRACKED],
349 diagnostic_width: Option<usize> [UNTRACKED],
350
351 incremental: Option<PathBuf> [UNTRACKED],
354 assert_incr_state: Option<IncrementalStateAssertion> [UNTRACKED],
355 #[rustc_lint_opt_deny_field_access("should only be used via `Config::hash_untracked_state`")]
358 untracked_state_hash: Hash64 [TRACKED_NO_CRATE_HASH],
359
360 unstable_opts: UnstableOptions [SUBSTRUCT UnstableOptionsTargetModifiers UnstableOptions],
361 prints: Vec<PrintRequest> [UNTRACKED],
362 cg: CodegenOptions [SUBSTRUCT CodegenOptionsTargetModifiers CodegenOptions],
363 externs: Externs [UNTRACKED],
364 crate_name: Option<String> [TRACKED],
365 unstable_features: UnstableFeatures [TRACKED],
367
368 actually_rustdoc: bool [TRACKED],
372 resolve_doc_links: ResolveDocLinks [TRACKED],
374
375 trimmed_def_paths: bool [TRACKED],
377
378 #[rustc_lint_opt_deny_field_access("use `Session::codegen_units` instead of this field")]
384 cli_forced_codegen_units: Option<usize> [UNTRACKED],
385 #[rustc_lint_opt_deny_field_access("use `Session::lto` instead of this field")]
386 cli_forced_local_thinlto_off: bool [UNTRACKED],
387
388 remap_path_prefix: Vec<(PathBuf, PathBuf)> [TRACKED_NO_CRATE_HASH],
390
391 real_rust_source_base_dir: Option<PathBuf> [TRACKED_NO_CRATE_HASH],
399
400 real_rustc_dev_source_base_dir: Option<PathBuf> [TRACKED_NO_CRATE_HASH],
408
409 edition: Edition [TRACKED],
410
411 json_artifact_notifications: bool [TRACKED],
414
415 json_timings: bool [UNTRACKED],
418
419 json_unused_externs: JsonUnusedExterns [UNTRACKED],
421
422 json_future_incompat: bool [TRACKED],
424
425 pretty: Option<PpMode> [UNTRACKED],
426
427 working_dir: RealFileName [TRACKED],
429 color: ColorConfig [UNTRACKED],
430
431 verbose: bool [TRACKED_NO_CRATE_HASH],
432 }
433);
434
435macro_rules! tmod_enum_opt {
436 ($struct_name:ident, $tmod_enum_name:ident, $opt:ident, $v:ident) => {
437 Some(OptionsTargetModifiers::$struct_name($tmod_enum_name::$opt))
438 };
439 ($struct_name:ident, $tmod_enum_name:ident, $opt:ident, ) => {
440 None
441 };
442}
443
444macro_rules! tmod_enum {
445 ($tmod_enum_name:ident, $prefix:expr, $( {$($optinfo:tt)*} ),* $(,)*) => {
446 tmod_enum! { $tmod_enum_name, $prefix, @parse {}, (user_value){}; $($($optinfo)*|)* }
447 };
448 (
450 $tmod_enum_name:ident, $prefix:expr,
451 @parse
452 {$($eout:tt)*},
453 ($user_value:ident){$($pout:tt)*};
454 ) => {
455 #[allow(non_camel_case_types)]
456 #[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Copy, Clone, Encodable, Decodable)]
457 pub enum $tmod_enum_name {
458 $($eout),*
459 }
460 impl $tmod_enum_name {
461 #[allow(unused_variables)]
462 pub fn reparse(&self, $user_value: &str) -> ExtendedTargetModifierInfo {
463 #[allow(unreachable_patterns)]
464 match self {
465 $($pout)*
466 _ => panic!("unknown target modifier option: {:?}", *self)
467 }
468 }
469 pub fn is_target_modifier(flag_name: &str) -> bool {
470 match flag_name.replace('-', "_").as_str() {
471 $(stringify!($eout) => true,)*
472 _ => false,
473 }
474 }
475 }
476 };
477 (
479 $tmod_enum_name:ident, $prefix:expr,
480 @parse {$($eout:tt)*}, ($puser_value:ident){$($pout:tt)*};
481 $opt:ident, $parse:ident, $t:ty, [TARGET_MODIFIER] |
482 $($tail:tt)*
483 ) => {
484 tmod_enum! {
485 $tmod_enum_name, $prefix,
486 @parse
487 {
488 $($eout)*
489 $opt
490 },
491 ($puser_value){
492 $($pout)*
493 Self::$opt => {
494 let mut parsed : $t = Default::default();
495 let val = if $puser_value.is_empty() { None } else { Some($puser_value) };
496 parse::$parse(&mut parsed, val);
497 ExtendedTargetModifierInfo {
498 prefix: $prefix.to_string(),
499 name: stringify!($opt).to_string().replace('_', "-"),
500 tech_value: format!("{:?}", parsed),
501 }
502 },
503 };
504 $($tail)*
505 }
506 };
507 (
509 $tmod_enum_name:ident, $prefix:expr,
510 @parse {$($eout:tt)*}, ($puser_value:ident){$($pout:tt)*};
511 $opt:ident, $parse:ident, $t:ty, [] |
512 $($tail:tt)*
513 ) => {
514 tmod_enum! {
515 $tmod_enum_name, $prefix,
516 @parse
517 {
518 $($eout)*
519 },
520 ($puser_value){
521 $($pout)*
522 };
523 $($tail)*
524 }
525 };
526}
527
528macro_rules! options {
537 ($struct_name:ident, $tmod_enum_name:ident, $stat:ident, $optmod:ident, $prefix:expr, $outputname:expr,
538 $($( #[$attr:meta] )* $opt:ident : $t:ty = (
539 $init:expr,
540 $parse:ident,
541 [$dep_tracking_marker:ident $( $tmod:ident )?],
542 $desc:expr
543 $(, deprecated_do_nothing: $dnn:literal )?)
544 ),* ,) =>
545(
546 #[derive(Clone)]
547 #[rustc_lint_opt_ty]
548 pub struct $struct_name { $( $( #[$attr] )* pub $opt: $t),* }
549
550 tmod_enum!( $tmod_enum_name, $prefix, {$($opt, $parse, $t, [$($tmod),*])|*} );
551
552 impl Default for $struct_name {
553 fn default() -> $struct_name {
554 $struct_name { $($opt: $init),* }
555 }
556 }
557
558 impl $struct_name {
559 pub fn build(
560 early_dcx: &EarlyDiagCtxt,
561 matches: &getopts::Matches,
562 target_modifiers: &mut BTreeMap<OptionsTargetModifiers, String>,
563 ) -> $struct_name {
564 build_options(early_dcx, matches, target_modifiers, $stat, $prefix, $outputname)
565 }
566
567 fn dep_tracking_hash(&self, for_crate_hash: bool, error_format: ErrorOutputType) -> Hash64 {
568 let mut sub_hashes = BTreeMap::new();
569 $({
570 hash_opt!($opt,
571 &self.$opt,
572 &mut sub_hashes,
573 for_crate_hash,
574 [$dep_tracking_marker]);
575 })*
576 let mut hasher = StableHasher::new();
577 dep_tracking::stable_hash(sub_hashes,
578 &mut hasher,
579 error_format,
580 for_crate_hash
581 );
582 hasher.finish()
583 }
584
585 pub fn gather_target_modifiers(
586 &self,
587 _mods: &mut Vec<TargetModifier>,
588 _tmod_vals: &BTreeMap<OptionsTargetModifiers, String>,
589 ) {
590 $({
591 gather_tmods!($struct_name, $tmod_enum_name, $opt, &self.$opt, $init, _mods, _tmod_vals,
592 [$dep_tracking_marker], [$($tmod),*]);
593 })*
594 }
595 }
596
597 pub const $stat: OptionDescrs<$struct_name> =
598 &[ $( OptionDesc{ name: stringify!($opt), setter: $optmod::$opt,
599 type_desc: desc::$parse, desc: $desc, is_deprecated_and_do_nothing: false $( || $dnn )?,
600 tmod: tmod_enum_opt!($struct_name, $tmod_enum_name, $opt, $($tmod),*) } ),* ];
601
602 mod $optmod {
603 $(
604 pub(super) fn $opt(cg: &mut super::$struct_name, v: Option<&str>) -> bool {
605 super::parse::$parse(&mut redirect_field!(cg.$opt), v)
606 }
607 )*
608 }
609
610) }
611
612impl CodegenOptions {
613 #[allow(rustc::bad_opt_access)]
615 pub fn instrument_coverage(&self) -> InstrumentCoverage {
616 self.instrument_coverage
617 }
618}
619
620macro_rules! redirect_field {
623 ($cg:ident.link_arg) => {
624 $cg.link_args
625 };
626 ($cg:ident.pre_link_arg) => {
627 $cg.pre_link_args
628 };
629 ($cg:ident.$field:ident) => {
630 $cg.$field
631 };
632}
633
634type OptionSetter<O> = fn(&mut O, v: Option<&str>) -> bool;
635type OptionDescrs<O> = &'static [OptionDesc<O>];
636
637pub struct OptionDesc<O> {
638 name: &'static str,
639 setter: OptionSetter<O>,
640 type_desc: &'static str,
642 desc: &'static str,
644 is_deprecated_and_do_nothing: bool,
645 tmod: Option<OptionsTargetModifiers>,
646}
647
648impl<O> OptionDesc<O> {
649 pub fn name(&self) -> &'static str {
650 self.name
651 }
652
653 pub fn desc(&self) -> &'static str {
654 self.desc
655 }
656}
657
658#[allow(rustc::untranslatable_diagnostic)] fn build_options<O: Default>(
660 early_dcx: &EarlyDiagCtxt,
661 matches: &getopts::Matches,
662 target_modifiers: &mut BTreeMap<OptionsTargetModifiers, String>,
663 descrs: OptionDescrs<O>,
664 prefix: &str,
665 outputname: &str,
666) -> O {
667 let mut op = O::default();
668 for option in matches.opt_strs(prefix) {
669 let (key, value) = match option.split_once('=') {
670 None => (option, None),
671 Some((k, v)) => (k.to_string(), Some(v)),
672 };
673
674 let option_to_lookup = key.replace('-', "_");
675 match descrs.iter().find(|opt_desc| opt_desc.name == option_to_lookup) {
676 Some(OptionDesc {
677 name: _,
678 setter,
679 type_desc,
680 desc,
681 is_deprecated_and_do_nothing,
682 tmod,
683 }) => {
684 if *is_deprecated_and_do_nothing {
685 assert!(!prefix.is_empty());
687 early_dcx.early_warn(format!("`-{prefix} {key}`: {desc}"));
688 }
689 if !setter(&mut op, value) {
690 match value {
691 None => early_dcx.early_fatal(
692 format!(
693 "{outputname} option `{key}` requires {type_desc} ({prefix} {key}=<value>)"
694 ),
695 ),
696 Some(value) => early_dcx.early_fatal(
697 format!(
698 "incorrect value `{value}` for {outputname} option `{key}` - {type_desc} was expected"
699 ),
700 ),
701 }
702 }
703 if let Some(tmod) = *tmod {
704 let v = value.map_or(String::new(), ToOwned::to_owned);
705 target_modifiers.insert(tmod, v);
706 }
707 }
708 None => early_dcx.early_fatal(format!("unknown {outputname} option: `{key}`")),
709 }
710 }
711 op
712}
713
714#[allow(non_upper_case_globals)]
715mod desc {
716 pub(crate) const parse_no_value: &str = "no value";
717 pub(crate) const parse_bool: &str =
718 "one of: `y`, `yes`, `on`, `true`, `n`, `no`, `off` or `false`";
719 pub(crate) const parse_opt_bool: &str = parse_bool;
720 pub(crate) const parse_string: &str = "a string";
721 pub(crate) const parse_opt_string: &str = parse_string;
722 pub(crate) const parse_string_push: &str = parse_string;
723 pub(crate) const parse_opt_langid: &str = "a language identifier";
724 pub(crate) const parse_opt_pathbuf: &str = "a path";
725 pub(crate) const parse_list: &str = "a space-separated list of strings";
726 pub(crate) const parse_list_with_polarity: &str =
727 "a comma-separated list of strings, with elements beginning with + or -";
728 pub(crate) const parse_autodiff: &str = "a comma separated list of settings: `Enable`, `PrintSteps`, `PrintTA`, `PrintAA`, `PrintPerf`, `PrintModBefore`, `PrintModAfter`, `PrintModFinal`, `PrintPasses`, `NoPostopt`, `LooseTypes`, `Inline`";
729 pub(crate) const parse_comma_list: &str = "a comma-separated list of strings";
730 pub(crate) const parse_opt_comma_list: &str = parse_comma_list;
731 pub(crate) const parse_number: &str = "a number";
732 pub(crate) const parse_opt_number: &str = parse_number;
733 pub(crate) const parse_frame_pointer: &str = "one of `true`/`yes`/`on`, `false`/`no`/`off`, or (with -Zunstable-options) `non-leaf` or `always`";
734 pub(crate) const parse_threads: &str = parse_number;
735 pub(crate) const parse_time_passes_format: &str = "`text` (default) or `json`";
736 pub(crate) const parse_passes: &str = "a space-separated list of passes, or `all`";
737 pub(crate) const parse_panic_strategy: &str = "either `unwind` or `abort`";
738 pub(crate) const parse_on_broken_pipe: &str = "either `kill`, `error`, or `inherit`";
739 pub(crate) const parse_patchable_function_entry: &str = "either two comma separated integers (total_nops,prefix_nops), with prefix_nops <= total_nops, or one integer (total_nops)";
740 pub(crate) const parse_opt_panic_strategy: &str = parse_panic_strategy;
741 pub(crate) const parse_oom_strategy: &str = "either `panic` or `abort`";
742 pub(crate) const parse_relro_level: &str = "one of: `full`, `partial`, or `off`";
743 pub(crate) const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `dataflow`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `safestack`, `shadow-call-stack`, or `thread`";
744 pub(crate) const parse_sanitizer_memory_track_origins: &str = "0, 1, or 2";
745 pub(crate) const parse_cfguard: &str =
746 "either a boolean (`yes`, `no`, `on`, `off`, etc), `checks`, or `nochecks`";
747 pub(crate) const parse_cfprotection: &str = "`none`|`no`|`n` (default), `branch`, `return`, or `full`|`yes`|`y` (equivalent to `branch` and `return`)";
748 pub(crate) const parse_debuginfo: &str = "either an integer (0, 1, 2), `none`, `line-directives-only`, `line-tables-only`, `limited`, or `full`";
749 pub(crate) const parse_debuginfo_compression: &str = "one of `none`, `zlib`, or `zstd`";
750 pub(crate) const parse_mir_strip_debuginfo: &str =
751 "one of `none`, `locals-in-tiny-functions`, or `all-locals`";
752 pub(crate) const parse_collapse_macro_debuginfo: &str = "one of `no`, `external`, or `yes`";
753 pub(crate) const parse_strip: &str = "either `none`, `debuginfo`, or `symbols`";
754 pub(crate) const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavorCli::one_of();
755 pub(crate) const parse_dump_mono_stats: &str = "`markdown` (default) or `json`";
756 pub(crate) const parse_instrument_coverage: &str = parse_bool;
757 pub(crate) const parse_coverage_options: &str =
758 "`block` | `branch` | `condition` | `mcdc` | `no-mir-spans`";
759 pub(crate) const parse_instrument_xray: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), or a comma separated list of settings: `always` or `never` (mutually exclusive), `ignore-loops`, `instruction-threshold=N`, `skip-entry`, `skip-exit`";
760 pub(crate) const parse_unpretty: &str = "`string` or `string=string`";
761 pub(crate) const parse_treat_err_as_bug: &str = "either no value or a non-negative number";
762 pub(crate) const parse_next_solver_config: &str =
763 "either `globally` (when used without an argument), `coherence` (default) or `no`";
764 pub(crate) const parse_lto: &str =
765 "either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted";
766 pub(crate) const parse_linker_plugin_lto: &str =
767 "either a boolean (`yes`, `no`, `on`, `off`, etc), or the path to the linker plugin";
768 pub(crate) const parse_location_detail: &str = "either `none`, or a comma separated list of location details to track: `file`, `line`, or `column`";
769 pub(crate) const parse_fmt_debug: &str = "either `full`, `shallow`, or `none`";
770 pub(crate) const parse_switch_with_opt_path: &str =
771 "an optional path to the profiling data output directory";
772 pub(crate) const parse_merge_functions: &str =
773 "one of: `disabled`, `trampolines`, or `aliases`";
774 pub(crate) const parse_symbol_mangling_version: &str =
775 "one of: `legacy`, `v0` (RFC 2603), or `hashed`";
776 pub(crate) const parse_opt_symbol_visibility: &str =
777 "one of: `hidden`, `protected`, or `interposable`";
778 pub(crate) const parse_cargo_src_file_hash: &str =
779 "one of `blake3`, `md5`, `sha1`, or `sha256`";
780 pub(crate) const parse_src_file_hash: &str = "one of `md5`, `sha1`, or `sha256`";
781 pub(crate) const parse_relocation_model: &str =
782 "one of supported relocation models (`rustc --print relocation-models`)";
783 pub(crate) const parse_code_model: &str =
784 "one of supported code models (`rustc --print code-models`)";
785 pub(crate) const parse_tls_model: &str =
786 "one of supported TLS models (`rustc --print tls-models`)";
787 pub(crate) const parse_target_feature: &str = parse_string;
788 pub(crate) const parse_terminal_url: &str =
789 "either a boolean (`yes`, `no`, `on`, `off`, etc), or `auto`";
790 pub(crate) const parse_wasi_exec_model: &str = "either `command` or `reactor`";
791 pub(crate) const parse_split_debuginfo: &str =
792 "one of supported split-debuginfo modes (`off`, `packed`, or `unpacked`)";
793 pub(crate) const parse_split_dwarf_kind: &str =
794 "one of supported split dwarf modes (`split` or `single`)";
795 pub(crate) const parse_link_self_contained: &str = "one of: `y`, `yes`, `on`, `n`, `no`, `off`, or a list of enabled (`+` prefix) and disabled (`-` prefix) \
796 components: `crto`, `libc`, `unwind`, `linker`, `sanitizers`, `mingw`";
797 pub(crate) const parse_linker_features: &str =
798 "a list of enabled (`+` prefix) and disabled (`-` prefix) features: `lld`";
799 pub(crate) const parse_polonius: &str = "either no value or `legacy` (the default), or `next`";
800 pub(crate) const parse_stack_protector: &str =
801 "one of (`none` (default), `basic`, `strong`, or `all`)";
802 pub(crate) const parse_branch_protection: &str = "a `,` separated combination of `bti`, `pac-ret`, followed by a combination of `pc`, `b-key`, or `leaf`";
803 pub(crate) const parse_proc_macro_execution_strategy: &str =
804 "one of supported execution strategies (`same-thread`, or `cross-thread`)";
805 pub(crate) const parse_remap_path_scope: &str =
806 "comma separated list of scopes: `macro`, `diagnostics`, `debuginfo`, `object`, `all`";
807 pub(crate) const parse_inlining_threshold: &str =
808 "either a boolean (`yes`, `no`, `on`, `off`, etc), or a non-negative number";
809 pub(crate) const parse_llvm_module_flag: &str = "<key>:<type>:<value>:<behavior>. Type must currently be `u32`. Behavior should be one of (`error`, `warning`, `require`, `override`, `append`, `appendunique`, `max`, `min`)";
810 pub(crate) const parse_function_return: &str = "`keep` or `thunk-extern`";
811 pub(crate) const parse_wasm_c_abi: &str = "`spec`";
812 pub(crate) const parse_mir_include_spans: &str =
813 "either a boolean (`yes`, `no`, `on`, `off`, etc), or `nll` (default: `nll`)";
814 pub(crate) const parse_align: &str = "a number that is a power of 2 between 1 and 2^29";
815}
816
817pub mod parse {
818 use std::str::FromStr;
819
820 pub(crate) use super::*;
821 pub(crate) const MAX_THREADS_CAP: usize = 256;
822
823 pub(crate) fn parse_no_value(slot: &mut bool, v: Option<&str>) -> bool {
829 match v {
830 None => {
831 *slot = true;
832 true
833 }
834 Some(_) => false,
836 }
837 }
838
839 pub(crate) fn parse_bool(slot: &mut bool, v: Option<&str>) -> bool {
841 match v {
842 Some("y") | Some("yes") | Some("on") | Some("true") | None => {
843 *slot = true;
844 true
845 }
846 Some("n") | Some("no") | Some("off") | Some("false") => {
847 *slot = false;
848 true
849 }
850 _ => false,
851 }
852 }
853
854 pub(crate) fn parse_opt_bool(slot: &mut Option<bool>, v: Option<&str>) -> bool {
858 match v {
859 Some("y") | Some("yes") | Some("on") | Some("true") | None => {
860 *slot = Some(true);
861 true
862 }
863 Some("n") | Some("no") | Some("off") | Some("false") => {
864 *slot = Some(false);
865 true
866 }
867 _ => false,
868 }
869 }
870
871 pub(crate) fn parse_polonius(slot: &mut Polonius, v: Option<&str>) -> bool {
873 match v {
874 Some("legacy") | None => {
875 *slot = Polonius::Legacy;
876 true
877 }
878 Some("next") => {
879 *slot = Polonius::Next;
880 true
881 }
882 _ => false,
883 }
884 }
885
886 pub(crate) fn parse_string(slot: &mut String, v: Option<&str>) -> bool {
888 match v {
889 Some(s) => {
890 *slot = s.to_string();
891 true
892 }
893 None => false,
894 }
895 }
896
897 pub(crate) fn parse_opt_string(slot: &mut Option<String>, v: Option<&str>) -> bool {
899 match v {
900 Some(s) => {
901 *slot = Some(s.to_string());
902 true
903 }
904 None => false,
905 }
906 }
907
908 pub(crate) fn parse_opt_langid(slot: &mut Option<LanguageIdentifier>, v: Option<&str>) -> bool {
910 match v {
911 Some(s) => {
912 *slot = rustc_errors::LanguageIdentifier::from_str(s).ok();
913 true
914 }
915 None => false,
916 }
917 }
918
919 pub(crate) fn parse_opt_pathbuf(slot: &mut Option<PathBuf>, v: Option<&str>) -> bool {
920 match v {
921 Some(s) => {
922 *slot = Some(PathBuf::from(s));
923 true
924 }
925 None => false,
926 }
927 }
928
929 pub(crate) fn parse_string_push(slot: &mut Vec<String>, v: Option<&str>) -> bool {
930 match v {
931 Some(s) => {
932 slot.push(s.to_string());
933 true
934 }
935 None => false,
936 }
937 }
938
939 pub(crate) fn parse_list(slot: &mut Vec<String>, v: Option<&str>) -> bool {
940 match v {
941 Some(s) => {
942 slot.extend(s.split_whitespace().map(|s| s.to_string()));
943 true
944 }
945 None => false,
946 }
947 }
948
949 pub(crate) fn parse_list_with_polarity(
950 slot: &mut Vec<(String, bool)>,
951 v: Option<&str>,
952 ) -> bool {
953 match v {
954 Some(s) => {
955 for s in s.split(',') {
956 let Some(pass_name) = s.strip_prefix(&['+', '-'][..]) else { return false };
957 slot.push((pass_name.to_string(), &s[..1] == "+"));
958 }
959 true
960 }
961 None => false,
962 }
963 }
964
965 pub(crate) fn parse_fmt_debug(opt: &mut FmtDebug, v: Option<&str>) -> bool {
966 *opt = match v {
967 Some("full") => FmtDebug::Full,
968 Some("shallow") => FmtDebug::Shallow,
969 Some("none") => FmtDebug::None,
970 _ => return false,
971 };
972 true
973 }
974
975 pub(crate) fn parse_location_detail(ld: &mut LocationDetail, v: Option<&str>) -> bool {
976 if let Some(v) = v {
977 ld.line = false;
978 ld.file = false;
979 ld.column = false;
980 if v == "none" {
981 return true;
982 }
983 for s in v.split(',') {
984 match s {
985 "file" => ld.file = true,
986 "line" => ld.line = true,
987 "column" => ld.column = true,
988 _ => return false,
989 }
990 }
991 true
992 } else {
993 false
994 }
995 }
996
997 pub(crate) fn parse_comma_list(slot: &mut Vec<String>, v: Option<&str>) -> bool {
998 match v {
999 Some(s) => {
1000 let mut v: Vec<_> = s.split(',').map(|s| s.to_string()).collect();
1001 v.sort_unstable();
1002 *slot = v;
1003 true
1004 }
1005 None => false,
1006 }
1007 }
1008
1009 pub(crate) fn parse_opt_comma_list(slot: &mut Option<Vec<String>>, v: Option<&str>) -> bool {
1010 match v {
1011 Some(s) => {
1012 let mut v: Vec<_> = s.split(',').map(|s| s.to_string()).collect();
1013 v.sort_unstable();
1014 *slot = Some(v);
1015 true
1016 }
1017 None => false,
1018 }
1019 }
1020
1021 pub(crate) fn parse_threads(slot: &mut usize, v: Option<&str>) -> bool {
1022 let ret = match v.and_then(|s| s.parse().ok()) {
1023 Some(0) => {
1024 *slot = std::thread::available_parallelism().map_or(1, NonZero::<usize>::get);
1025 true
1026 }
1027 Some(i) => {
1028 *slot = i;
1029 true
1030 }
1031 None => false,
1032 };
1033 *slot = slot.clone().min(MAX_THREADS_CAP);
1036 ret
1037 }
1038
1039 pub(crate) fn parse_number<T: Copy + FromStr>(slot: &mut T, v: Option<&str>) -> bool {
1041 match v.and_then(|s| s.parse().ok()) {
1042 Some(i) => {
1043 *slot = i;
1044 true
1045 }
1046 None => false,
1047 }
1048 }
1049
1050 pub(crate) fn parse_opt_number<T: Copy + FromStr>(
1052 slot: &mut Option<T>,
1053 v: Option<&str>,
1054 ) -> bool {
1055 match v {
1056 Some(s) => {
1057 *slot = s.parse().ok();
1058 slot.is_some()
1059 }
1060 None => false,
1061 }
1062 }
1063
1064 pub(crate) fn parse_frame_pointer(slot: &mut FramePointer, v: Option<&str>) -> bool {
1065 let mut yes = false;
1066 match v {
1067 _ if parse_bool(&mut yes, v) && yes => slot.ratchet(FramePointer::Always),
1068 _ if parse_bool(&mut yes, v) => slot.ratchet(FramePointer::MayOmit),
1069 Some("always") => slot.ratchet(FramePointer::Always),
1070 Some("non-leaf") => slot.ratchet(FramePointer::NonLeaf),
1071 _ => return false,
1072 };
1073 true
1074 }
1075
1076 pub(crate) fn parse_passes(slot: &mut Passes, v: Option<&str>) -> bool {
1077 match v {
1078 Some("all") => {
1079 *slot = Passes::All;
1080 true
1081 }
1082 v => {
1083 let mut passes = vec![];
1084 if parse_list(&mut passes, v) {
1085 slot.extend(passes);
1086 true
1087 } else {
1088 false
1089 }
1090 }
1091 }
1092 }
1093
1094 pub(crate) fn parse_opt_panic_strategy(
1095 slot: &mut Option<PanicStrategy>,
1096 v: Option<&str>,
1097 ) -> bool {
1098 match v {
1099 Some("unwind") => *slot = Some(PanicStrategy::Unwind),
1100 Some("abort") => *slot = Some(PanicStrategy::Abort),
1101 _ => return false,
1102 }
1103 true
1104 }
1105
1106 pub(crate) fn parse_panic_strategy(slot: &mut PanicStrategy, v: Option<&str>) -> bool {
1107 match v {
1108 Some("unwind") => *slot = PanicStrategy::Unwind,
1109 Some("abort") => *slot = PanicStrategy::Abort,
1110 _ => return false,
1111 }
1112 true
1113 }
1114
1115 pub(crate) fn parse_on_broken_pipe(slot: &mut OnBrokenPipe, v: Option<&str>) -> bool {
1116 match v {
1117 Some("kill") => *slot = OnBrokenPipe::Kill,
1119 Some("error") => *slot = OnBrokenPipe::Error,
1120 Some("inherit") => *slot = OnBrokenPipe::Inherit,
1121 _ => return false,
1122 }
1123 true
1124 }
1125
1126 pub(crate) fn parse_patchable_function_entry(
1127 slot: &mut PatchableFunctionEntry,
1128 v: Option<&str>,
1129 ) -> bool {
1130 let mut total_nops = 0;
1131 let mut prefix_nops = 0;
1132
1133 if !parse_number(&mut total_nops, v) {
1134 let parts = v.and_then(|v| v.split_once(',')).unzip();
1135 if !parse_number(&mut total_nops, parts.0) {
1136 return false;
1137 }
1138 if !parse_number(&mut prefix_nops, parts.1) {
1139 return false;
1140 }
1141 }
1142
1143 if let Some(pfe) =
1144 PatchableFunctionEntry::from_total_and_prefix_nops(total_nops, prefix_nops)
1145 {
1146 *slot = pfe;
1147 return true;
1148 }
1149 false
1150 }
1151
1152 pub(crate) fn parse_oom_strategy(slot: &mut OomStrategy, v: Option<&str>) -> bool {
1153 match v {
1154 Some("panic") => *slot = OomStrategy::Panic,
1155 Some("abort") => *slot = OomStrategy::Abort,
1156 _ => return false,
1157 }
1158 true
1159 }
1160
1161 pub(crate) fn parse_relro_level(slot: &mut Option<RelroLevel>, v: Option<&str>) -> bool {
1162 match v {
1163 Some(s) => match s.parse::<RelroLevel>() {
1164 Ok(level) => *slot = Some(level),
1165 _ => return false,
1166 },
1167 _ => return false,
1168 }
1169 true
1170 }
1171
1172 pub(crate) fn parse_sanitizers(slot: &mut SanitizerSet, v: Option<&str>) -> bool {
1173 if let Some(v) = v {
1174 for s in v.split(',') {
1175 *slot |= match s {
1176 "address" => SanitizerSet::ADDRESS,
1177 "cfi" => SanitizerSet::CFI,
1178 "dataflow" => SanitizerSet::DATAFLOW,
1179 "kcfi" => SanitizerSet::KCFI,
1180 "kernel-address" => SanitizerSet::KERNELADDRESS,
1181 "leak" => SanitizerSet::LEAK,
1182 "memory" => SanitizerSet::MEMORY,
1183 "memtag" => SanitizerSet::MEMTAG,
1184 "shadow-call-stack" => SanitizerSet::SHADOWCALLSTACK,
1185 "thread" => SanitizerSet::THREAD,
1186 "hwaddress" => SanitizerSet::HWADDRESS,
1187 "safestack" => SanitizerSet::SAFESTACK,
1188 _ => return false,
1189 }
1190 }
1191 true
1192 } else {
1193 false
1194 }
1195 }
1196
1197 pub(crate) fn parse_sanitizer_memory_track_origins(slot: &mut usize, v: Option<&str>) -> bool {
1198 match v {
1199 Some("2") | None => {
1200 *slot = 2;
1201 true
1202 }
1203 Some("1") => {
1204 *slot = 1;
1205 true
1206 }
1207 Some("0") => {
1208 *slot = 0;
1209 true
1210 }
1211 Some(_) => false,
1212 }
1213 }
1214
1215 pub(crate) fn parse_strip(slot: &mut Strip, v: Option<&str>) -> bool {
1216 match v {
1217 Some("none") => *slot = Strip::None,
1218 Some("debuginfo") => *slot = Strip::Debuginfo,
1219 Some("symbols") => *slot = Strip::Symbols,
1220 _ => return false,
1221 }
1222 true
1223 }
1224
1225 pub(crate) fn parse_cfguard(slot: &mut CFGuard, v: Option<&str>) -> bool {
1226 if v.is_some() {
1227 let mut bool_arg = None;
1228 if parse_opt_bool(&mut bool_arg, v) {
1229 *slot = if bool_arg.unwrap() { CFGuard::Checks } else { CFGuard::Disabled };
1230 return true;
1231 }
1232 }
1233
1234 *slot = match v {
1235 None => CFGuard::Checks,
1236 Some("checks") => CFGuard::Checks,
1237 Some("nochecks") => CFGuard::NoChecks,
1238 Some(_) => return false,
1239 };
1240 true
1241 }
1242
1243 pub(crate) fn parse_cfprotection(slot: &mut CFProtection, v: Option<&str>) -> bool {
1244 if v.is_some() {
1245 let mut bool_arg = None;
1246 if parse_opt_bool(&mut bool_arg, v) {
1247 *slot = if bool_arg.unwrap() { CFProtection::Full } else { CFProtection::None };
1248 return true;
1249 }
1250 }
1251
1252 *slot = match v {
1253 None | Some("none") => CFProtection::None,
1254 Some("branch") => CFProtection::Branch,
1255 Some("return") => CFProtection::Return,
1256 Some("full") => CFProtection::Full,
1257 Some(_) => return false,
1258 };
1259 true
1260 }
1261
1262 pub(crate) fn parse_debuginfo(slot: &mut DebugInfo, v: Option<&str>) -> bool {
1263 match v {
1264 Some("0") | Some("none") => *slot = DebugInfo::None,
1265 Some("line-directives-only") => *slot = DebugInfo::LineDirectivesOnly,
1266 Some("line-tables-only") => *slot = DebugInfo::LineTablesOnly,
1267 Some("1") | Some("limited") => *slot = DebugInfo::Limited,
1268 Some("2") | Some("full") => *slot = DebugInfo::Full,
1269 _ => return false,
1270 }
1271 true
1272 }
1273
1274 pub(crate) fn parse_debuginfo_compression(
1275 slot: &mut DebugInfoCompression,
1276 v: Option<&str>,
1277 ) -> bool {
1278 match v {
1279 Some("none") => *slot = DebugInfoCompression::None,
1280 Some("zlib") => *slot = DebugInfoCompression::Zlib,
1281 Some("zstd") => *slot = DebugInfoCompression::Zstd,
1282 _ => return false,
1283 };
1284 true
1285 }
1286
1287 pub(crate) fn parse_mir_strip_debuginfo(slot: &mut MirStripDebugInfo, v: Option<&str>) -> bool {
1288 match v {
1289 Some("none") => *slot = MirStripDebugInfo::None,
1290 Some("locals-in-tiny-functions") => *slot = MirStripDebugInfo::LocalsInTinyFunctions,
1291 Some("all-locals") => *slot = MirStripDebugInfo::AllLocals,
1292 _ => return false,
1293 };
1294 true
1295 }
1296
1297 pub(crate) fn parse_linker_flavor(slot: &mut Option<LinkerFlavorCli>, v: Option<&str>) -> bool {
1298 match v.and_then(LinkerFlavorCli::from_str) {
1299 Some(lf) => *slot = Some(lf),
1300 _ => return false,
1301 }
1302 true
1303 }
1304
1305 pub(crate) fn parse_opt_symbol_visibility(
1306 slot: &mut Option<SymbolVisibility>,
1307 v: Option<&str>,
1308 ) -> bool {
1309 if let Some(v) = v {
1310 if let Ok(vis) = SymbolVisibility::from_str(v) {
1311 *slot = Some(vis);
1312 } else {
1313 return false;
1314 }
1315 }
1316 true
1317 }
1318
1319 pub(crate) fn parse_unpretty(slot: &mut Option<String>, v: Option<&str>) -> bool {
1320 match v {
1321 None => false,
1322 Some(s) if s.split('=').count() <= 2 => {
1323 *slot = Some(s.to_string());
1324 true
1325 }
1326 _ => false,
1327 }
1328 }
1329
1330 pub(crate) fn parse_time_passes_format(slot: &mut TimePassesFormat, v: Option<&str>) -> bool {
1331 match v {
1332 None => true,
1333 Some("json") => {
1334 *slot = TimePassesFormat::Json;
1335 true
1336 }
1337 Some("text") => {
1338 *slot = TimePassesFormat::Text;
1339 true
1340 }
1341 Some(_) => false,
1342 }
1343 }
1344
1345 pub(crate) fn parse_dump_mono_stats(slot: &mut DumpMonoStatsFormat, v: Option<&str>) -> bool {
1346 match v {
1347 None => true,
1348 Some("json") => {
1349 *slot = DumpMonoStatsFormat::Json;
1350 true
1351 }
1352 Some("markdown") => {
1353 *slot = DumpMonoStatsFormat::Markdown;
1354 true
1355 }
1356 Some(_) => false,
1357 }
1358 }
1359
1360 pub(crate) fn parse_autodiff(slot: &mut Vec<AutoDiff>, v: Option<&str>) -> bool {
1361 let Some(v) = v else {
1362 *slot = vec![];
1363 return true;
1364 };
1365 let mut v: Vec<&str> = v.split(",").collect();
1366 v.sort_unstable();
1367 for &val in v.iter() {
1368 let variant = match val {
1369 "Enable" => AutoDiff::Enable,
1370 "PrintTA" => AutoDiff::PrintTA,
1371 "PrintAA" => AutoDiff::PrintAA,
1372 "PrintPerf" => AutoDiff::PrintPerf,
1373 "PrintSteps" => AutoDiff::PrintSteps,
1374 "PrintModBefore" => AutoDiff::PrintModBefore,
1375 "PrintModAfter" => AutoDiff::PrintModAfter,
1376 "PrintModFinal" => AutoDiff::PrintModFinal,
1377 "NoPostopt" => AutoDiff::NoPostopt,
1378 "PrintPasses" => AutoDiff::PrintPasses,
1379 "LooseTypes" => AutoDiff::LooseTypes,
1380 "Inline" => AutoDiff::Inline,
1381 _ => {
1382 return false;
1384 }
1385 };
1386 slot.push(variant);
1387 }
1388
1389 true
1390 }
1391
1392 pub(crate) fn parse_instrument_coverage(
1393 slot: &mut InstrumentCoverage,
1394 v: Option<&str>,
1395 ) -> bool {
1396 if v.is_some() {
1397 let mut bool_arg = false;
1398 if parse_bool(&mut bool_arg, v) {
1399 *slot = if bool_arg { InstrumentCoverage::Yes } else { InstrumentCoverage::No };
1400 return true;
1401 }
1402 }
1403
1404 let Some(v) = v else {
1405 *slot = InstrumentCoverage::Yes;
1406 return true;
1407 };
1408
1409 *slot = match v {
1412 "all" => InstrumentCoverage::Yes,
1413 "0" => InstrumentCoverage::No,
1414 _ => return false,
1415 };
1416 true
1417 }
1418
1419 pub(crate) fn parse_coverage_options(slot: &mut CoverageOptions, v: Option<&str>) -> bool {
1420 let Some(v) = v else { return true };
1421
1422 for option in v.split(',') {
1423 match option {
1424 "block" => slot.level = CoverageLevel::Block,
1425 "branch" => slot.level = CoverageLevel::Branch,
1426 "condition" => slot.level = CoverageLevel::Condition,
1427 "mcdc" => slot.level = CoverageLevel::Mcdc,
1428 "no-mir-spans" => slot.no_mir_spans = true,
1429 "discard-all-spans-in-codegen" => slot.discard_all_spans_in_codegen = true,
1430 _ => return false,
1431 }
1432 }
1433 true
1434 }
1435
1436 pub(crate) fn parse_instrument_xray(
1437 slot: &mut Option<InstrumentXRay>,
1438 v: Option<&str>,
1439 ) -> bool {
1440 if v.is_some() {
1441 let mut bool_arg = None;
1442 if parse_opt_bool(&mut bool_arg, v) {
1443 *slot = if bool_arg.unwrap() { Some(InstrumentXRay::default()) } else { None };
1444 return true;
1445 }
1446 }
1447
1448 let options = slot.get_or_insert_default();
1449 let mut seen_always = false;
1450 let mut seen_never = false;
1451 let mut seen_ignore_loops = false;
1452 let mut seen_instruction_threshold = false;
1453 let mut seen_skip_entry = false;
1454 let mut seen_skip_exit = false;
1455 for option in v.into_iter().flat_map(|v| v.split(',')) {
1456 match option {
1457 "always" if !seen_always && !seen_never => {
1458 options.always = true;
1459 options.never = false;
1460 seen_always = true;
1461 }
1462 "never" if !seen_never && !seen_always => {
1463 options.never = true;
1464 options.always = false;
1465 seen_never = true;
1466 }
1467 "ignore-loops" if !seen_ignore_loops => {
1468 options.ignore_loops = true;
1469 seen_ignore_loops = true;
1470 }
1471 option
1472 if option.starts_with("instruction-threshold")
1473 && !seen_instruction_threshold =>
1474 {
1475 let Some(("instruction-threshold", n)) = option.split_once('=') else {
1476 return false;
1477 };
1478 match n.parse() {
1479 Ok(n) => options.instruction_threshold = Some(n),
1480 Err(_) => return false,
1481 }
1482 seen_instruction_threshold = true;
1483 }
1484 "skip-entry" if !seen_skip_entry => {
1485 options.skip_entry = true;
1486 seen_skip_entry = true;
1487 }
1488 "skip-exit" if !seen_skip_exit => {
1489 options.skip_exit = true;
1490 seen_skip_exit = true;
1491 }
1492 _ => return false,
1493 }
1494 }
1495 true
1496 }
1497
1498 pub(crate) fn parse_treat_err_as_bug(
1499 slot: &mut Option<NonZero<usize>>,
1500 v: Option<&str>,
1501 ) -> bool {
1502 match v {
1503 Some(s) => match s.parse() {
1504 Ok(val) => {
1505 *slot = Some(val);
1506 true
1507 }
1508 Err(e) => {
1509 *slot = None;
1510 e.kind() == &IntErrorKind::Zero
1511 }
1512 },
1513 None => {
1514 *slot = NonZero::new(1);
1515 true
1516 }
1517 }
1518 }
1519
1520 pub(crate) fn parse_next_solver_config(slot: &mut NextSolverConfig, v: Option<&str>) -> bool {
1521 if let Some(config) = v {
1522 *slot = match config {
1523 "no" => NextSolverConfig { coherence: false, globally: false },
1524 "coherence" => NextSolverConfig { coherence: true, globally: false },
1525 "globally" => NextSolverConfig { coherence: true, globally: true },
1526 _ => return false,
1527 };
1528 } else {
1529 *slot = NextSolverConfig { coherence: true, globally: true };
1530 }
1531
1532 true
1533 }
1534
1535 pub(crate) fn parse_lto(slot: &mut LtoCli, v: Option<&str>) -> bool {
1536 if v.is_some() {
1537 let mut bool_arg = None;
1538 if parse_opt_bool(&mut bool_arg, v) {
1539 *slot = if bool_arg.unwrap() { LtoCli::Yes } else { LtoCli::No };
1540 return true;
1541 }
1542 }
1543
1544 *slot = match v {
1545 None => LtoCli::NoParam,
1546 Some("thin") => LtoCli::Thin,
1547 Some("fat") => LtoCli::Fat,
1548 Some(_) => return false,
1549 };
1550 true
1551 }
1552
1553 pub(crate) fn parse_linker_plugin_lto(slot: &mut LinkerPluginLto, v: Option<&str>) -> bool {
1554 if v.is_some() {
1555 let mut bool_arg = None;
1556 if parse_opt_bool(&mut bool_arg, v) {
1557 *slot = if bool_arg.unwrap() {
1558 LinkerPluginLto::LinkerPluginAuto
1559 } else {
1560 LinkerPluginLto::Disabled
1561 };
1562 return true;
1563 }
1564 }
1565
1566 *slot = match v {
1567 None => LinkerPluginLto::LinkerPluginAuto,
1568 Some(path) => LinkerPluginLto::LinkerPlugin(PathBuf::from(path)),
1569 };
1570 true
1571 }
1572
1573 pub(crate) fn parse_switch_with_opt_path(
1574 slot: &mut SwitchWithOptPath,
1575 v: Option<&str>,
1576 ) -> bool {
1577 *slot = match v {
1578 None => SwitchWithOptPath::Enabled(None),
1579 Some(path) => SwitchWithOptPath::Enabled(Some(PathBuf::from(path))),
1580 };
1581 true
1582 }
1583
1584 pub(crate) fn parse_merge_functions(
1585 slot: &mut Option<MergeFunctions>,
1586 v: Option<&str>,
1587 ) -> bool {
1588 match v.and_then(|s| MergeFunctions::from_str(s).ok()) {
1589 Some(mergefunc) => *slot = Some(mergefunc),
1590 _ => return false,
1591 }
1592 true
1593 }
1594
1595 pub(crate) fn parse_remap_path_scope(
1596 slot: &mut RemapPathScopeComponents,
1597 v: Option<&str>,
1598 ) -> bool {
1599 if let Some(v) = v {
1600 *slot = RemapPathScopeComponents::empty();
1601 for s in v.split(',') {
1602 *slot |= match s {
1603 "macro" => RemapPathScopeComponents::MACRO,
1604 "diagnostics" => RemapPathScopeComponents::DIAGNOSTICS,
1605 "debuginfo" => RemapPathScopeComponents::DEBUGINFO,
1606 "object" => RemapPathScopeComponents::OBJECT,
1607 "all" => RemapPathScopeComponents::all(),
1608 _ => return false,
1609 }
1610 }
1611 true
1612 } else {
1613 false
1614 }
1615 }
1616
1617 pub(crate) fn parse_relocation_model(slot: &mut Option<RelocModel>, v: Option<&str>) -> bool {
1618 match v.and_then(|s| RelocModel::from_str(s).ok()) {
1619 Some(relocation_model) => *slot = Some(relocation_model),
1620 None if v == Some("default") => *slot = None,
1621 _ => return false,
1622 }
1623 true
1624 }
1625
1626 pub(crate) fn parse_code_model(slot: &mut Option<CodeModel>, v: Option<&str>) -> bool {
1627 match v.and_then(|s| CodeModel::from_str(s).ok()) {
1628 Some(code_model) => *slot = Some(code_model),
1629 _ => return false,
1630 }
1631 true
1632 }
1633
1634 pub(crate) fn parse_tls_model(slot: &mut Option<TlsModel>, v: Option<&str>) -> bool {
1635 match v.and_then(|s| TlsModel::from_str(s).ok()) {
1636 Some(tls_model) => *slot = Some(tls_model),
1637 _ => return false,
1638 }
1639 true
1640 }
1641
1642 pub(crate) fn parse_terminal_url(slot: &mut TerminalUrl, v: Option<&str>) -> bool {
1643 *slot = match v {
1644 Some("on" | "" | "yes" | "y") | None => TerminalUrl::Yes,
1645 Some("off" | "no" | "n") => TerminalUrl::No,
1646 Some("auto") => TerminalUrl::Auto,
1647 _ => return false,
1648 };
1649 true
1650 }
1651
1652 pub(crate) fn parse_symbol_mangling_version(
1653 slot: &mut Option<SymbolManglingVersion>,
1654 v: Option<&str>,
1655 ) -> bool {
1656 *slot = match v {
1657 Some("legacy") => Some(SymbolManglingVersion::Legacy),
1658 Some("v0") => Some(SymbolManglingVersion::V0),
1659 Some("hashed") => Some(SymbolManglingVersion::Hashed),
1660 _ => return false,
1661 };
1662 true
1663 }
1664
1665 pub(crate) fn parse_src_file_hash(
1666 slot: &mut Option<SourceFileHashAlgorithm>,
1667 v: Option<&str>,
1668 ) -> bool {
1669 match v.and_then(|s| SourceFileHashAlgorithm::from_str(s).ok()) {
1670 Some(hash_kind) => *slot = Some(hash_kind),
1671 _ => return false,
1672 }
1673 true
1674 }
1675
1676 pub(crate) fn parse_cargo_src_file_hash(
1677 slot: &mut Option<SourceFileHashAlgorithm>,
1678 v: Option<&str>,
1679 ) -> bool {
1680 match v.and_then(|s| SourceFileHashAlgorithm::from_str(s).ok()) {
1681 Some(hash_kind) => {
1682 *slot = Some(hash_kind);
1683 }
1684 _ => return false,
1685 }
1686 true
1687 }
1688
1689 pub(crate) fn parse_target_feature(slot: &mut String, v: Option<&str>) -> bool {
1690 match v {
1691 Some(s) => {
1692 if !slot.is_empty() {
1693 slot.push(',');
1694 }
1695 slot.push_str(s);
1696 true
1697 }
1698 None => false,
1699 }
1700 }
1701
1702 pub(crate) fn parse_link_self_contained(slot: &mut LinkSelfContained, v: Option<&str>) -> bool {
1703 let s = v.unwrap_or("y");
1708 match s {
1709 "y" | "yes" | "on" => {
1710 slot.set_all_explicitly(true);
1711 return true;
1712 }
1713 "n" | "no" | "off" => {
1714 slot.set_all_explicitly(false);
1715 return true;
1716 }
1717 _ => {}
1718 }
1719
1720 for comp in s.split(',') {
1722 if slot.handle_cli_component(comp).is_none() {
1723 return false;
1724 }
1725 }
1726
1727 true
1728 }
1729
1730 pub(crate) fn parse_linker_features(slot: &mut LinkerFeaturesCli, v: Option<&str>) -> bool {
1732 match v {
1733 Some(s) => {
1734 for feature in s.split(',') {
1735 if slot.handle_cli_feature(feature).is_none() {
1736 return false;
1737 }
1738 }
1739
1740 true
1741 }
1742 None => false,
1743 }
1744 }
1745
1746 pub(crate) fn parse_wasi_exec_model(slot: &mut Option<WasiExecModel>, v: Option<&str>) -> bool {
1747 match v {
1748 Some("command") => *slot = Some(WasiExecModel::Command),
1749 Some("reactor") => *slot = Some(WasiExecModel::Reactor),
1750 _ => return false,
1751 }
1752 true
1753 }
1754
1755 pub(crate) fn parse_split_debuginfo(
1756 slot: &mut Option<SplitDebuginfo>,
1757 v: Option<&str>,
1758 ) -> bool {
1759 match v.and_then(|s| SplitDebuginfo::from_str(s).ok()) {
1760 Some(e) => *slot = Some(e),
1761 _ => return false,
1762 }
1763 true
1764 }
1765
1766 pub(crate) fn parse_split_dwarf_kind(slot: &mut SplitDwarfKind, v: Option<&str>) -> bool {
1767 match v.and_then(|s| SplitDwarfKind::from_str(s).ok()) {
1768 Some(e) => *slot = e,
1769 _ => return false,
1770 }
1771 true
1772 }
1773
1774 pub(crate) fn parse_stack_protector(slot: &mut StackProtector, v: Option<&str>) -> bool {
1775 match v.and_then(|s| StackProtector::from_str(s).ok()) {
1776 Some(ssp) => *slot = ssp,
1777 _ => return false,
1778 }
1779 true
1780 }
1781
1782 pub(crate) fn parse_branch_protection(
1783 slot: &mut Option<BranchProtection>,
1784 v: Option<&str>,
1785 ) -> bool {
1786 match v {
1787 Some(s) => {
1788 let slot = slot.get_or_insert_default();
1789 for opt in s.split(',') {
1790 match opt {
1791 "bti" => slot.bti = true,
1792 "pac-ret" if slot.pac_ret.is_none() => {
1793 slot.pac_ret = Some(PacRet { leaf: false, pc: false, key: PAuthKey::A })
1794 }
1795 "leaf" => match slot.pac_ret.as_mut() {
1796 Some(pac) => pac.leaf = true,
1797 _ => return false,
1798 },
1799 "b-key" => match slot.pac_ret.as_mut() {
1800 Some(pac) => pac.key = PAuthKey::B,
1801 _ => return false,
1802 },
1803 "pc" => match slot.pac_ret.as_mut() {
1804 Some(pac) => pac.pc = true,
1805 _ => return false,
1806 },
1807 _ => return false,
1808 };
1809 }
1810 }
1811 _ => return false,
1812 }
1813 true
1814 }
1815
1816 pub(crate) fn parse_collapse_macro_debuginfo(
1817 slot: &mut CollapseMacroDebuginfo,
1818 v: Option<&str>,
1819 ) -> bool {
1820 if v.is_some() {
1821 let mut bool_arg = None;
1822 if parse_opt_bool(&mut bool_arg, v) {
1823 *slot = if bool_arg.unwrap() {
1824 CollapseMacroDebuginfo::Yes
1825 } else {
1826 CollapseMacroDebuginfo::No
1827 };
1828 return true;
1829 }
1830 }
1831
1832 *slot = match v {
1833 Some("external") => CollapseMacroDebuginfo::External,
1834 _ => return false,
1835 };
1836 true
1837 }
1838
1839 pub(crate) fn parse_proc_macro_execution_strategy(
1840 slot: &mut ProcMacroExecutionStrategy,
1841 v: Option<&str>,
1842 ) -> bool {
1843 *slot = match v {
1844 Some("same-thread") => ProcMacroExecutionStrategy::SameThread,
1845 Some("cross-thread") => ProcMacroExecutionStrategy::CrossThread,
1846 _ => return false,
1847 };
1848 true
1849 }
1850
1851 pub(crate) fn parse_inlining_threshold(slot: &mut InliningThreshold, v: Option<&str>) -> bool {
1852 match v {
1853 Some("always" | "yes") => {
1854 *slot = InliningThreshold::Always;
1855 }
1856 Some("never") => {
1857 *slot = InliningThreshold::Never;
1858 }
1859 Some(v) => {
1860 if let Ok(threshold) = v.parse() {
1861 *slot = InliningThreshold::Sometimes(threshold);
1862 } else {
1863 return false;
1864 }
1865 }
1866 None => return false,
1867 }
1868 true
1869 }
1870
1871 pub(crate) fn parse_llvm_module_flag(
1872 slot: &mut Vec<(String, u32, String)>,
1873 v: Option<&str>,
1874 ) -> bool {
1875 let elements = v.unwrap_or_default().split(':').collect::<Vec<_>>();
1876 let [key, md_type, value, behavior] = elements.as_slice() else {
1877 return false;
1878 };
1879 if *md_type != "u32" {
1880 return false;
1883 }
1884 let Ok(value) = value.parse::<u32>() else {
1885 return false;
1886 };
1887 let behavior = behavior.to_lowercase();
1888 let all_behaviors =
1889 ["error", "warning", "require", "override", "append", "appendunique", "max", "min"];
1890 if !all_behaviors.contains(&behavior.as_str()) {
1891 return false;
1892 }
1893
1894 slot.push((key.to_string(), value, behavior));
1895 true
1896 }
1897
1898 pub(crate) fn parse_function_return(slot: &mut FunctionReturn, v: Option<&str>) -> bool {
1899 match v {
1900 Some("keep") => *slot = FunctionReturn::Keep,
1901 Some("thunk-extern") => *slot = FunctionReturn::ThunkExtern,
1902 _ => return false,
1903 }
1904 true
1905 }
1906
1907 pub(crate) fn parse_wasm_c_abi(_slot: &mut (), v: Option<&str>) -> bool {
1908 v == Some("spec")
1909 }
1910
1911 pub(crate) fn parse_mir_include_spans(slot: &mut MirIncludeSpans, v: Option<&str>) -> bool {
1912 *slot = match v {
1913 Some("on" | "yes" | "y" | "true") | None => MirIncludeSpans::On,
1914 Some("off" | "no" | "n" | "false") => MirIncludeSpans::Off,
1915 Some("nll") => MirIncludeSpans::Nll,
1916 _ => return false,
1917 };
1918
1919 true
1920 }
1921
1922 pub(crate) fn parse_align(slot: &mut Option<Align>, v: Option<&str>) -> bool {
1923 let mut bytes = 0u64;
1924 if !parse_number(&mut bytes, v) {
1925 return false;
1926 }
1927
1928 let Ok(align) = Align::from_bytes(bytes) else {
1929 return false;
1930 };
1931
1932 *slot = Some(align);
1933
1934 true
1935 }
1936}
1937
1938options! {
1939 CodegenOptions, CodegenOptionsTargetModifiers, CG_OPTIONS, cgopts, "C", "codegen",
1940
1941 #[rustc_lint_opt_deny_field_access("documented to do nothing")]
1947 ar: String = (String::new(), parse_string, [UNTRACKED],
1948 "this option is deprecated and does nothing",
1949 deprecated_do_nothing: true),
1950 #[rustc_lint_opt_deny_field_access("use `Session::code_model` instead of this field")]
1951 code_model: Option<CodeModel> = (None, parse_code_model, [TRACKED],
1952 "choose the code model to use (`rustc --print code-models` for details)"),
1953 codegen_units: Option<usize> = (None, parse_opt_number, [UNTRACKED],
1954 "divide crate into N units to optimize in parallel"),
1955 collapse_macro_debuginfo: CollapseMacroDebuginfo = (CollapseMacroDebuginfo::Unspecified,
1956 parse_collapse_macro_debuginfo, [TRACKED],
1957 "set option to collapse debuginfo for macros"),
1958 control_flow_guard: CFGuard = (CFGuard::Disabled, parse_cfguard, [TRACKED],
1959 "use Windows Control Flow Guard (default: no)"),
1960 debug_assertions: Option<bool> = (None, parse_opt_bool, [TRACKED],
1961 "explicitly enable the `cfg(debug_assertions)` directive"),
1962 debuginfo: DebugInfo = (DebugInfo::None, parse_debuginfo, [TRACKED],
1963 "debug info emission level (0-2, none, line-directives-only, \
1964 line-tables-only, limited, or full; default: 0)"),
1965 default_linker_libraries: bool = (false, parse_bool, [UNTRACKED],
1966 "allow the linker to link its default libraries (default: no)"),
1967 dlltool: Option<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED],
1968 "import library generation tool (ignored except when targeting windows-gnu)"),
1969 #[rustc_lint_opt_deny_field_access("use `Session::dwarf_version` instead of this field")]
1970 dwarf_version: Option<u32> = (None, parse_opt_number, [TRACKED],
1971 "version of DWARF debug information to emit (default: 2 or 4, depending on platform)"),
1972 embed_bitcode: bool = (true, parse_bool, [TRACKED],
1973 "emit bitcode in rlibs (default: yes)"),
1974 extra_filename: String = (String::new(), parse_string, [UNTRACKED],
1975 "extra data to put in each output filename"),
1976 force_frame_pointers: FramePointer = (FramePointer::MayOmit, parse_frame_pointer, [TRACKED],
1977 "force use of the frame pointers"),
1978 #[rustc_lint_opt_deny_field_access("use `Session::must_emit_unwind_tables` instead of this field")]
1979 force_unwind_tables: Option<bool> = (None, parse_opt_bool, [TRACKED],
1980 "force use of unwind tables"),
1981 incremental: Option<String> = (None, parse_opt_string, [UNTRACKED],
1982 "enable incremental compilation"),
1983 #[rustc_lint_opt_deny_field_access("documented to do nothing")]
1984 inline_threshold: Option<u32> = (None, parse_opt_number, [UNTRACKED],
1985 "this option is deprecated and does nothing \
1986 (consider using `-Cllvm-args=--inline-threshold=...`)",
1987 deprecated_do_nothing: true),
1988 #[rustc_lint_opt_deny_field_access("use `Session::instrument_coverage` instead of this field")]
1989 instrument_coverage: InstrumentCoverage = (InstrumentCoverage::No, parse_instrument_coverage, [TRACKED],
1990 "instrument the generated code to support LLVM source-based code coverage reports \
1991 (note, the compiler build config must include `profiler = true`); \
1992 implies `-C symbol-mangling-version=v0`"),
1993 link_arg: () = ((), parse_string_push, [UNTRACKED],
1994 "a single extra argument to append to the linker invocation (can be used several times)"),
1995 link_args: Vec<String> = (Vec::new(), parse_list, [UNTRACKED],
1996 "extra arguments to append to the linker invocation (space separated)"),
1997 #[rustc_lint_opt_deny_field_access("use `Session::link_dead_code` instead of this field")]
1998 link_dead_code: Option<bool> = (None, parse_opt_bool, [TRACKED],
1999 "try to generate and link dead code (default: no)"),
2000 link_self_contained: LinkSelfContained = (LinkSelfContained::default(), parse_link_self_contained, [UNTRACKED],
2001 "control whether to link Rust provided C objects/libraries or rely \
2002 on a C toolchain or linker installed in the system"),
2003 linker: Option<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED],
2004 "system linker to link outputs with"),
2005 linker_flavor: Option<LinkerFlavorCli> = (None, parse_linker_flavor, [UNTRACKED],
2006 "linker flavor"),
2007 linker_plugin_lto: LinkerPluginLto = (LinkerPluginLto::Disabled,
2008 parse_linker_plugin_lto, [TRACKED],
2009 "generate build artifacts that are compatible with linker-based LTO"),
2010 llvm_args: Vec<String> = (Vec::new(), parse_list, [TRACKED],
2011 "a list of arguments to pass to LLVM (space separated)"),
2012 #[rustc_lint_opt_deny_field_access("use `Session::lto` instead of this field")]
2013 lto: LtoCli = (LtoCli::Unspecified, parse_lto, [TRACKED],
2014 "perform LLVM link-time optimizations"),
2015 metadata: Vec<String> = (Vec::new(), parse_list, [TRACKED],
2016 "metadata to mangle symbol names with"),
2017 no_prepopulate_passes: bool = (false, parse_no_value, [TRACKED],
2018 "give an empty list of passes to the pass manager"),
2019 no_redzone: Option<bool> = (None, parse_opt_bool, [TRACKED],
2020 "disable the use of the redzone"),
2021 #[rustc_lint_opt_deny_field_access("documented to do nothing")]
2022 no_stack_check: bool = (false, parse_no_value, [UNTRACKED],
2023 "this option is deprecated and does nothing",
2024 deprecated_do_nothing: true),
2025 no_vectorize_loops: bool = (false, parse_no_value, [TRACKED],
2026 "disable loop vectorization optimization passes"),
2027 no_vectorize_slp: bool = (false, parse_no_value, [TRACKED],
2028 "disable LLVM's SLP vectorization pass"),
2029 opt_level: String = ("0".to_string(), parse_string, [TRACKED],
2030 "optimization level (0-3, s, or z; default: 0)"),
2031 #[rustc_lint_opt_deny_field_access("use `Session::overflow_checks` instead of this field")]
2032 overflow_checks: Option<bool> = (None, parse_opt_bool, [TRACKED],
2033 "use overflow checks for integer arithmetic"),
2034 #[rustc_lint_opt_deny_field_access("use `Session::panic_strategy` instead of this field")]
2035 panic: Option<PanicStrategy> = (None, parse_opt_panic_strategy, [TRACKED],
2036 "panic strategy to compile crate with"),
2037 passes: Vec<String> = (Vec::new(), parse_list, [TRACKED],
2038 "a list of extra LLVM passes to run (space separated)"),
2039 prefer_dynamic: bool = (false, parse_bool, [TRACKED],
2040 "prefer dynamic linking to static linking (default: no)"),
2041 profile_generate: SwitchWithOptPath = (SwitchWithOptPath::Disabled,
2042 parse_switch_with_opt_path, [TRACKED],
2043 "compile the program with profiling instrumentation"),
2044 profile_use: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
2045 "use the given `.profdata` file for profile-guided optimization"),
2046 #[rustc_lint_opt_deny_field_access("use `Session::relocation_model` instead of this field")]
2047 relocation_model: Option<RelocModel> = (None, parse_relocation_model, [TRACKED],
2048 "control generation of position-independent code (PIC) \
2049 (`rustc --print relocation-models` for details)"),
2050 relro_level: Option<RelroLevel> = (None, parse_relro_level, [TRACKED],
2051 "choose which RELRO level to use"),
2052 remark: Passes = (Passes::Some(Vec::new()), parse_passes, [UNTRACKED],
2053 "output remarks for these optimization passes (space separated, or \"all\")"),
2054 rpath: bool = (false, parse_bool, [UNTRACKED],
2055 "set rpath values in libs/exes (default: no)"),
2056 save_temps: bool = (false, parse_bool, [UNTRACKED],
2057 "save all temporary output files during compilation (default: no)"),
2058 soft_float: bool = (false, parse_bool, [TRACKED],
2059 "deprecated option: use soft float ABI (*eabihf targets only) (default: no)"),
2060 #[rustc_lint_opt_deny_field_access("use `Session::split_debuginfo` instead of this field")]
2061 split_debuginfo: Option<SplitDebuginfo> = (None, parse_split_debuginfo, [TRACKED],
2062 "how to handle split-debuginfo, a platform-specific option"),
2063 strip: Strip = (Strip::None, parse_strip, [UNTRACKED],
2064 "tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)"),
2065 symbol_mangling_version: Option<SymbolManglingVersion> = (None,
2066 parse_symbol_mangling_version, [TRACKED],
2067 "which mangling version to use for symbol names ('legacy' (default), 'v0', or 'hashed')"),
2068 target_cpu: Option<String> = (None, parse_opt_string, [TRACKED],
2069 "select target processor (`rustc --print target-cpus` for details)"),
2070 target_feature: String = (String::new(), parse_target_feature, [TRACKED],
2071 "target specific attributes. (`rustc --print target-features` for details). \
2072 This feature is unsafe."),
2073 unsafe_allow_abi_mismatch: Vec<String> = (Vec::new(), parse_comma_list, [UNTRACKED],
2074 "Allow incompatible target modifiers in dependency crates (comma separated list)"),
2075 }
2081
2082options! {
2083 UnstableOptions, UnstableOptionsTargetModifiers, Z_OPTIONS, dbopts, "Z", "unstable",
2084
2085 allow_features: Option<Vec<String>> = (None, parse_opt_comma_list, [TRACKED],
2091 "only allow the listed language features to be enabled in code (comma separated)"),
2092 always_encode_mir: bool = (false, parse_bool, [TRACKED],
2093 "encode MIR of all functions into the crate metadata (default: no)"),
2094 assert_incr_state: Option<String> = (None, parse_opt_string, [UNTRACKED],
2095 "assert that the incremental cache is in given state: \
2096 either `loaded` or `not-loaded`."),
2097 assume_incomplete_release: bool = (false, parse_bool, [TRACKED],
2098 "make cfg(version) treat the current version as incomplete (default: no)"),
2099 autodiff: Vec<crate::config::AutoDiff> = (Vec::new(), parse_autodiff, [TRACKED],
2100 "a list of autodiff flags to enable
2101 Mandatory setting:
2102 `=Enable`
2103 Optional extra settings:
2104 `=PrintTA`
2105 `=PrintAA`
2106 `=PrintPerf`
2107 `=PrintSteps`
2108 `=PrintModBefore`
2109 `=PrintModAfter`
2110 `=PrintModFinal`
2111 `=PrintPasses`,
2112 `=NoPostopt`
2113 `=LooseTypes`
2114 `=Inline`
2115 Multiple options can be combined with commas."),
2116 #[rustc_lint_opt_deny_field_access("use `Session::binary_dep_depinfo` instead of this field")]
2117 binary_dep_depinfo: bool = (false, parse_bool, [TRACKED],
2118 "include artifacts (sysroot, crate dependencies) used during compilation in dep-info \
2119 (default: no)"),
2120 box_noalias: bool = (true, parse_bool, [TRACKED],
2121 "emit noalias metadata for box (default: yes)"),
2122 branch_protection: Option<BranchProtection> = (None, parse_branch_protection, [TRACKED],
2123 "set options for branch target identification and pointer authentication on AArch64"),
2124 build_sdylib_interface: bool = (false, parse_bool, [UNTRACKED],
2125 "whether the stable interface is being built"),
2126 cf_protection: CFProtection = (CFProtection::None, parse_cfprotection, [TRACKED],
2127 "instrument control-flow architecture protection"),
2128 check_cfg_all_expected: bool = (false, parse_bool, [UNTRACKED],
2129 "show all expected values in check-cfg diagnostics (default: no)"),
2130 checksum_hash_algorithm: Option<SourceFileHashAlgorithm> = (None, parse_cargo_src_file_hash, [TRACKED],
2131 "hash algorithm of source files used to check freshness in cargo (`blake3` or `sha256`)"),
2132 codegen_backend: Option<String> = (None, parse_opt_string, [TRACKED],
2133 "the backend to use"),
2134 combine_cgu: bool = (false, parse_bool, [TRACKED],
2135 "combine CGUs into a single one"),
2136 contract_checks: Option<bool> = (None, parse_opt_bool, [TRACKED],
2137 "emit runtime checks for contract pre- and post-conditions (default: no)"),
2138 coverage_options: CoverageOptions = (CoverageOptions::default(), parse_coverage_options, [TRACKED],
2139 "control details of coverage instrumentation"),
2140 crate_attr: Vec<String> = (Vec::new(), parse_string_push, [TRACKED],
2141 "inject the given attribute in the crate"),
2142 cross_crate_inline_threshold: InliningThreshold = (InliningThreshold::Sometimes(100), parse_inlining_threshold, [TRACKED],
2143 "threshold to allow cross crate inlining of functions"),
2144 debug_info_for_profiling: bool = (false, parse_bool, [TRACKED],
2145 "emit discriminators and other data necessary for AutoFDO"),
2146 debug_info_type_line_numbers: bool = (false, parse_bool, [TRACKED],
2147 "emit type and line information for additional data types (default: no)"),
2148 debuginfo_compression: DebugInfoCompression = (DebugInfoCompression::None, parse_debuginfo_compression, [TRACKED],
2149 "compress debug info sections (none, zlib, zstd, default: none)"),
2150 deduplicate_diagnostics: bool = (true, parse_bool, [UNTRACKED],
2151 "deduplicate identical diagnostics (default: yes)"),
2152 default_visibility: Option<SymbolVisibility> = (None, parse_opt_symbol_visibility, [TRACKED],
2153 "overrides the `default_visibility` setting of the target"),
2154 dep_info_omit_d_target: bool = (false, parse_bool, [TRACKED],
2155 "in dep-info output, omit targets for tracking dependencies of the dep-info files \
2156 themselves (default: no)"),
2157 direct_access_external_data: Option<bool> = (None, parse_opt_bool, [TRACKED],
2158 "Direct or use GOT indirect to reference external data symbols"),
2159 dual_proc_macros: bool = (false, parse_bool, [TRACKED],
2160 "load proc macros for both target and host, but only link to the target (default: no)"),
2161 dump_dep_graph: bool = (false, parse_bool, [UNTRACKED],
2162 "dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv) \
2163 (default: no)"),
2164 dump_mir: Option<String> = (None, parse_opt_string, [UNTRACKED],
2165 "dump MIR state to file.
2166 `val` is used to select which passes and functions to dump. For example:
2167 `all` matches all passes and functions,
2168 `foo` matches all passes for functions whose name contains 'foo',
2169 `foo & ConstProp` only the 'ConstProp' pass for function names containing 'foo',
2170 `foo | bar` all passes for function names containing 'foo' or 'bar'."),
2171 dump_mir_dataflow: bool = (false, parse_bool, [UNTRACKED],
2172 "in addition to `.mir` files, create graphviz `.dot` files with dataflow results \
2173 (default: no)"),
2174 dump_mir_dir: String = ("mir_dump".to_string(), parse_string, [UNTRACKED],
2175 "the directory the MIR is dumped into (default: `mir_dump`)"),
2176 dump_mir_exclude_alloc_bytes: bool = (false, parse_bool, [UNTRACKED],
2177 "exclude the raw bytes of allocations when dumping MIR (used in tests) (default: no)"),
2178 dump_mir_exclude_pass_number: bool = (false, parse_bool, [UNTRACKED],
2179 "exclude the pass number when dumping MIR (used in tests) (default: no)"),
2180 dump_mir_graphviz: bool = (false, parse_bool, [UNTRACKED],
2181 "in addition to `.mir` files, create graphviz `.dot` files (default: no)"),
2182 dump_mono_stats: SwitchWithOptPath = (SwitchWithOptPath::Disabled,
2183 parse_switch_with_opt_path, [UNTRACKED],
2184 "output statistics about monomorphization collection"),
2185 dump_mono_stats_format: DumpMonoStatsFormat = (DumpMonoStatsFormat::Markdown, parse_dump_mono_stats, [UNTRACKED],
2186 "the format to use for -Z dump-mono-stats (`markdown` (default) or `json`)"),
2187 #[rustc_lint_opt_deny_field_access("use `Session::dwarf_version` instead of this field")]
2188 dwarf_version: Option<u32> = (None, parse_opt_number, [TRACKED],
2189 "version of DWARF debug information to emit (default: 2 or 4, depending on platform)"),
2190 dylib_lto: bool = (false, parse_bool, [UNTRACKED],
2191 "enables LTO for dylib crate type"),
2192 eagerly_emit_delayed_bugs: bool = (false, parse_bool, [UNTRACKED],
2193 "emit delayed bugs eagerly as errors instead of stashing them and emitting \
2194 them only if an error has not been emitted"),
2195 ehcont_guard: bool = (false, parse_bool, [TRACKED],
2196 "generate Windows EHCont Guard tables"),
2197 embed_metadata: bool = (true, parse_bool, [TRACKED],
2198 "embed metadata in rlibs and dylibs (default: yes)"),
2199 embed_source: bool = (false, parse_bool, [TRACKED],
2200 "embed source text in DWARF debug sections (default: no)"),
2201 emit_stack_sizes: bool = (false, parse_bool, [UNTRACKED],
2202 "emit a section containing stack size metadata (default: no)"),
2203 emit_thin_lto: bool = (true, parse_bool, [TRACKED],
2204 "emit the bc module with thin LTO info (default: yes)"),
2205 emscripten_wasm_eh: bool = (false, parse_bool, [TRACKED],
2206 "Use WebAssembly error handling for wasm32-unknown-emscripten"),
2207 enforce_type_length_limit: bool = (false, parse_bool, [TRACKED],
2208 "enforce the type length limit when monomorphizing instances in codegen"),
2209 experimental_default_bounds: bool = (false, parse_bool, [TRACKED],
2210 "enable default bounds for experimental group of auto traits"),
2211 export_executable_symbols: bool = (false, parse_bool, [TRACKED],
2212 "export symbols from executables, as if they were dynamic libraries"),
2213 external_clangrt: bool = (false, parse_bool, [UNTRACKED],
2214 "rely on user specified linker commands to find clangrt"),
2215 extra_const_ub_checks: bool = (false, parse_bool, [TRACKED],
2216 "turns on more checks to detect const UB, which can be slow (default: no)"),
2217 #[rustc_lint_opt_deny_field_access("use `Session::fewer_names` instead of this field")]
2218 fewer_names: Option<bool> = (None, parse_opt_bool, [TRACKED],
2219 "reduce memory use by retaining fewer names within compilation artifacts (LLVM-IR) \
2220 (default: no)"),
2221 fixed_x18: bool = (false, parse_bool, [TRACKED TARGET_MODIFIER],
2222 "make the x18 register reserved on AArch64 (default: no)"),
2223 flatten_format_args: bool = (true, parse_bool, [TRACKED],
2224 "flatten nested format_args!() and literals into a simplified format_args!() call \
2225 (default: yes)"),
2226 fmt_debug: FmtDebug = (FmtDebug::Full, parse_fmt_debug, [TRACKED],
2227 "how detailed `#[derive(Debug)]` should be. `full` prints types recursively, \
2228 `shallow` prints only type names, `none` prints nothing and disables `{:?}`. (default: `full`)"),
2229 force_unstable_if_unmarked: bool = (false, parse_bool, [TRACKED],
2230 "force all crates to be `rustc_private` unstable (default: no)"),
2231 function_return: FunctionReturn = (FunctionReturn::default(), parse_function_return, [TRACKED],
2232 "replace returns with jumps to `__x86_return_thunk` (default: `keep`)"),
2233 function_sections: Option<bool> = (None, parse_opt_bool, [TRACKED],
2234 "whether each function should go in its own section"),
2235 future_incompat_test: bool = (false, parse_bool, [UNTRACKED],
2236 "forces all lints to be future incompatible, used for internal testing (default: no)"),
2237 graphviz_dark_mode: bool = (false, parse_bool, [UNTRACKED],
2238 "use dark-themed colors in graphviz output (default: no)"),
2239 graphviz_font: String = ("Courier, monospace".to_string(), parse_string, [UNTRACKED],
2240 "use the given `fontname` in graphviz output; can be overridden by setting \
2241 environment variable `RUSTC_GRAPHVIZ_FONT` (default: `Courier, monospace`)"),
2242 has_thread_local: Option<bool> = (None, parse_opt_bool, [TRACKED],
2243 "explicitly enable the `cfg(target_thread_local)` directive"),
2244 hint_mostly_unused: bool = (false, parse_bool, [TRACKED],
2245 "hint that most of this crate will go unused, to minimize work for uncalled functions"),
2246 human_readable_cgu_names: bool = (false, parse_bool, [TRACKED],
2247 "generate human-readable, predictable names for codegen units (default: no)"),
2248 identify_regions: bool = (false, parse_bool, [UNTRACKED],
2249 "display unnamed regions as `'<id>`, using a non-ident unique id (default: no)"),
2250 ignore_directory_in_diagnostics_source_blocks: Vec<String> = (Vec::new(), parse_string_push, [UNTRACKED],
2251 "do not display the source code block in diagnostics for files in the directory"),
2252 incremental_ignore_spans: bool = (false, parse_bool, [TRACKED],
2253 "ignore spans during ICH computation -- used for testing (default: no)"),
2254 incremental_info: bool = (false, parse_bool, [UNTRACKED],
2255 "print high-level information about incremental reuse (or the lack thereof) \
2256 (default: no)"),
2257 incremental_verify_ich: bool = (false, parse_bool, [UNTRACKED],
2258 "verify extended properties for incr. comp. (default: no):
2259 - hashes of green query instances
2260 - hash collisions of query keys
2261 - hash collisions when creating dep-nodes"),
2262 inline_llvm: bool = (true, parse_bool, [TRACKED],
2263 "enable LLVM inlining (default: yes)"),
2264 inline_mir: Option<bool> = (None, parse_opt_bool, [TRACKED],
2265 "enable MIR inlining (default: no)"),
2266 inline_mir_forwarder_threshold: Option<usize> = (None, parse_opt_number, [TRACKED],
2267 "inlining threshold when the caller is a simple forwarding function (default: 30)"),
2268 inline_mir_hint_threshold: Option<usize> = (None, parse_opt_number, [TRACKED],
2269 "inlining threshold for functions with inline hint (default: 100)"),
2270 inline_mir_preserve_debug: Option<bool> = (None, parse_opt_bool, [TRACKED],
2271 "when MIR inlining, whether to preserve debug info for callee variables \
2272 (default: preserve for debuginfo != None, otherwise remove)"),
2273 inline_mir_threshold: Option<usize> = (None, parse_opt_number, [TRACKED],
2274 "a default MIR inlining threshold (default: 50)"),
2275 input_stats: bool = (false, parse_bool, [UNTRACKED],
2276 "print some statistics about AST and HIR (default: no)"),
2277 instrument_mcount: bool = (false, parse_bool, [TRACKED],
2278 "insert function instrument code for mcount-based tracing (default: no)"),
2279 instrument_xray: Option<InstrumentXRay> = (None, parse_instrument_xray, [TRACKED],
2280 "insert function instrument code for XRay-based tracing (default: no)
2281 Optional extra settings:
2282 `=always`
2283 `=never`
2284 `=ignore-loops`
2285 `=instruction-threshold=N`
2286 `=skip-entry`
2287 `=skip-exit`
2288 Multiple options can be combined with commas."),
2289 layout_seed: Option<u64> = (None, parse_opt_number, [TRACKED],
2290 "seed layout randomization"),
2291 link_directives: bool = (true, parse_bool, [TRACKED],
2292 "honor #[link] directives in the compiled crate (default: yes)"),
2293 link_native_libraries: bool = (true, parse_bool, [UNTRACKED],
2294 "link native libraries in the linker invocation (default: yes)"),
2295 link_only: bool = (false, parse_bool, [TRACKED],
2296 "link the `.rlink` file generated by `-Z no-link` (default: no)"),
2297 linker_features: LinkerFeaturesCli = (LinkerFeaturesCli::default(), parse_linker_features, [UNTRACKED],
2298 "a comma-separated list of linker features to enable (+) or disable (-): `lld`"),
2299 lint_llvm_ir: bool = (false, parse_bool, [TRACKED],
2300 "lint LLVM IR (default: no)"),
2301 lint_mir: bool = (false, parse_bool, [UNTRACKED],
2302 "lint MIR before and after each transformation"),
2303 llvm_module_flag: Vec<(String, u32, String)> = (Vec::new(), parse_llvm_module_flag, [TRACKED],
2304 "a list of module flags to pass to LLVM (space separated)"),
2305 llvm_plugins: Vec<String> = (Vec::new(), parse_list, [TRACKED],
2306 "a list LLVM plugins to enable (space separated)"),
2307 llvm_time_trace: bool = (false, parse_bool, [UNTRACKED],
2308 "generate JSON tracing data file from LLVM data (default: no)"),
2309 location_detail: LocationDetail = (LocationDetail::all(), parse_location_detail, [TRACKED],
2310 "what location details should be tracked when using caller_location, either \
2311 `none`, or a comma separated list of location details, for which \
2312 valid options are `file`, `line`, and `column` (default: `file,line,column`)"),
2313 ls: Vec<String> = (Vec::new(), parse_list, [UNTRACKED],
2314 "decode and print various parts of the crate metadata for a library crate \
2315 (space separated)"),
2316 macro_backtrace: bool = (false, parse_bool, [UNTRACKED],
2317 "show macro backtraces (default: no)"),
2318 macro_stats: bool = (false, parse_bool, [UNTRACKED],
2319 "print some statistics about macro expansions (default: no)"),
2320 maximal_hir_to_mir_coverage: bool = (false, parse_bool, [TRACKED],
2321 "save as much information as possible about the correspondence between MIR and HIR \
2322 as source scopes (default: no)"),
2323 merge_functions: Option<MergeFunctions> = (None, parse_merge_functions, [TRACKED],
2324 "control the operation of the MergeFunctions LLVM pass, taking \
2325 the same values as the target option of the same name"),
2326 meta_stats: bool = (false, parse_bool, [UNTRACKED],
2327 "gather metadata statistics (default: no)"),
2328 metrics_dir: Option<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED],
2329 "the directory metrics emitted by rustc are dumped into (implicitly enables default set of metrics)"),
2330 min_function_alignment: Option<Align> = (None, parse_align, [TRACKED],
2331 "align all functions to at least this many bytes. Must be a power of 2"),
2332 mir_emit_retag: bool = (false, parse_bool, [TRACKED],
2333 "emit Retagging MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 \
2334 (default: no)"),
2335 mir_enable_passes: Vec<(String, bool)> = (Vec::new(), parse_list_with_polarity, [TRACKED],
2336 "use like `-Zmir-enable-passes=+DestinationPropagation,-InstSimplify`. Forces the \
2337 specified passes to be enabled, overriding all other checks. In particular, this will \
2338 enable unsound (known-buggy and hence usually disabled) passes without further warning! \
2339 Passes that are not specified are enabled or disabled by other flags as usual."),
2340 mir_include_spans: MirIncludeSpans = (MirIncludeSpans::default(), parse_mir_include_spans, [UNTRACKED],
2341 "include extra comments in mir pretty printing, like line numbers and statement indices, \
2342 details about types, etc. (boolean for all passes, 'nll' to enable in NLL MIR only, default: 'nll')"),
2343 #[rustc_lint_opt_deny_field_access("use `Session::mir_opt_level` instead of this field")]
2344 mir_opt_level: Option<usize> = (None, parse_opt_number, [TRACKED],
2345 "MIR optimization level (0-4; default: 1 in non optimized builds and 2 in optimized builds)"),
2346 mir_preserve_ub: bool = (false, parse_bool, [TRACKED],
2347 "keep place mention statements and reads in trivial SwitchInt terminators, which are interpreted \
2348 e.g., by miri; implies -Zmir-opt-level=0 (default: no)"),
2349 mir_strip_debuginfo: MirStripDebugInfo = (MirStripDebugInfo::None, parse_mir_strip_debuginfo, [TRACKED],
2350 "Whether to remove some of the MIR debug info from methods. Default: None"),
2351 move_size_limit: Option<usize> = (None, parse_opt_number, [TRACKED],
2352 "the size at which the `large_assignments` lint starts to be emitted"),
2353 mutable_noalias: bool = (true, parse_bool, [TRACKED],
2354 "emit noalias metadata for mutable references (default: yes)"),
2355 namespaced_crates: bool = (false, parse_bool, [TRACKED],
2356 "allow crates to be namespaced by other crates (default: no)"),
2357 next_solver: NextSolverConfig = (NextSolverConfig::default(), parse_next_solver_config, [TRACKED],
2358 "enable and configure the next generation trait solver used by rustc"),
2359 nll_facts: bool = (false, parse_bool, [UNTRACKED],
2360 "dump facts from NLL analysis into side files (default: no)"),
2361 nll_facts_dir: String = ("nll-facts".to_string(), parse_string, [UNTRACKED],
2362 "the directory the NLL facts are dumped into (default: `nll-facts`)"),
2363 no_analysis: bool = (false, parse_no_value, [UNTRACKED],
2364 "parse and expand the source, but run no analysis"),
2365 no_codegen: bool = (false, parse_no_value, [TRACKED_NO_CRATE_HASH],
2366 "run all passes except codegen; no output"),
2367 no_generate_arange_section: bool = (false, parse_no_value, [TRACKED],
2368 "omit DWARF address ranges that give faster lookups"),
2369 no_implied_bounds_compat: bool = (false, parse_bool, [TRACKED],
2370 "disable the compatibility version of the `implied_bounds_ty` query"),
2371 no_jump_tables: bool = (false, parse_no_value, [TRACKED],
2372 "disable the jump tables and lookup tables that can be generated from a switch case lowering"),
2373 no_leak_check: bool = (false, parse_no_value, [UNTRACKED],
2374 "disable the 'leak check' for subtyping; unsound, but useful for tests"),
2375 no_link: bool = (false, parse_no_value, [TRACKED],
2376 "compile without linking"),
2377 no_parallel_backend: bool = (false, parse_no_value, [UNTRACKED],
2378 "run LLVM in non-parallel mode (while keeping codegen-units and ThinLTO)"),
2379 no_profiler_runtime: bool = (false, parse_no_value, [TRACKED],
2380 "prevent automatic injection of the profiler_builtins crate"),
2381 no_steal_thir: bool = (false, parse_bool, [UNTRACKED],
2382 "don't steal the THIR when we're done with it; useful for rustc drivers (default: no)"),
2383 no_trait_vptr: bool = (false, parse_no_value, [TRACKED],
2384 "disable generation of trait vptr in vtable for upcasting"),
2385 no_unique_section_names: bool = (false, parse_bool, [TRACKED],
2386 "do not use unique names for text and data sections when -Z function-sections is used"),
2387 normalize_docs: bool = (false, parse_bool, [TRACKED],
2388 "normalize associated items in rustdoc when generating documentation"),
2389 on_broken_pipe: OnBrokenPipe = (OnBrokenPipe::Default, parse_on_broken_pipe, [TRACKED],
2390 "behavior of std::io::ErrorKind::BrokenPipe (SIGPIPE)"),
2391 oom: OomStrategy = (OomStrategy::Abort, parse_oom_strategy, [TRACKED],
2392 "panic strategy for out-of-memory handling"),
2393 osx_rpath_install_name: bool = (false, parse_bool, [TRACKED],
2394 "pass `-install_name @rpath/...` to the macOS linker (default: no)"),
2395 packed_bundled_libs: bool = (false, parse_bool, [TRACKED],
2396 "change rlib format to store native libraries as archives"),
2397 panic_abort_tests: bool = (false, parse_bool, [TRACKED],
2398 "support compiling tests with panic=abort (default: no)"),
2399 panic_in_drop: PanicStrategy = (PanicStrategy::Unwind, parse_panic_strategy, [TRACKED],
2400 "panic strategy for panics in drops"),
2401 parse_crate_root_only: bool = (false, parse_bool, [UNTRACKED],
2402 "parse the crate root file only; do not parse other files, compile, assemble, or link \
2403 (default: no)"),
2404 patchable_function_entry: PatchableFunctionEntry = (PatchableFunctionEntry::default(), parse_patchable_function_entry, [TRACKED],
2405 "nop padding at function entry"),
2406 plt: Option<bool> = (None, parse_opt_bool, [TRACKED],
2407 "whether to use the PLT when calling into shared libraries;
2408 only has effect for PIC code on systems with ELF binaries
2409 (default: PLT is disabled if full relro is enabled on x86_64)"),
2410 polonius: Polonius = (Polonius::default(), parse_polonius, [TRACKED],
2411 "enable polonius-based borrow-checker (default: no)"),
2412 pre_link_arg: () = ((), parse_string_push, [UNTRACKED],
2413 "a single extra argument to prepend the linker invocation (can be used several times)"),
2414 pre_link_args: Vec<String> = (Vec::new(), parse_list, [UNTRACKED],
2415 "extra arguments to prepend to the linker invocation (space separated)"),
2416 precise_enum_drop_elaboration: bool = (true, parse_bool, [TRACKED],
2417 "use a more precise version of drop elaboration for matches on enums (default: yes). \
2418 This results in better codegen, but has caused miscompilations on some tier 2 platforms. \
2419 See #77382 and #74551."),
2420 #[rustc_lint_opt_deny_field_access("use `Session::print_codegen_stats` instead of this field")]
2421 print_codegen_stats: bool = (false, parse_bool, [UNTRACKED],
2422 "print codegen statistics (default: no)"),
2423 print_llvm_passes: bool = (false, parse_bool, [UNTRACKED],
2424 "print the LLVM optimization passes being run (default: no)"),
2425 print_mono_items: bool = (false, parse_bool, [UNTRACKED],
2426 "print the result of the monomorphization collection pass (default: no)"),
2427 print_type_sizes: bool = (false, parse_bool, [UNTRACKED],
2428 "print layout information for each type encountered (default: no)"),
2429 proc_macro_backtrace: bool = (false, parse_bool, [UNTRACKED],
2430 "show backtraces for panics during proc-macro execution (default: no)"),
2431 proc_macro_execution_strategy: ProcMacroExecutionStrategy = (ProcMacroExecutionStrategy::SameThread,
2432 parse_proc_macro_execution_strategy, [UNTRACKED],
2433 "how to run proc-macro code (default: same-thread)"),
2434 profile_closures: bool = (false, parse_no_value, [UNTRACKED],
2435 "profile size of closures"),
2436 profile_sample_use: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
2437 "use the given `.prof` file for sampled profile-guided optimization (also known as AutoFDO)"),
2438 profiler_runtime: String = (String::from("profiler_builtins"), parse_string, [TRACKED],
2439 "name of the profiler runtime crate to automatically inject (default: `profiler_builtins`)"),
2440 query_dep_graph: bool = (false, parse_bool, [UNTRACKED],
2441 "enable queries of the dependency graph for regression testing (default: no)"),
2442 randomize_layout: bool = (false, parse_bool, [TRACKED],
2443 "randomize the layout of types (default: no)"),
2444 reg_struct_return: bool = (false, parse_bool, [TRACKED TARGET_MODIFIER],
2445 "On x86-32 targets, it overrides the default ABI to return small structs in registers.
2446 It is UNSOUND to link together crates that use different values for this flag!"),
2447 regparm: Option<u32> = (None, parse_opt_number, [TRACKED TARGET_MODIFIER],
2448 "On x86-32 targets, setting this to N causes the compiler to pass N arguments \
2449 in registers EAX, EDX, and ECX instead of on the stack for\
2450 \"C\", \"cdecl\", and \"stdcall\" fn.\
2451 It is UNSOUND to link together crates that use different values for this flag!"),
2452 relax_elf_relocations: Option<bool> = (None, parse_opt_bool, [TRACKED],
2453 "whether ELF relocations can be relaxed"),
2454 remap_cwd_prefix: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
2455 "remap paths under the current working directory to this path prefix"),
2456 remap_path_scope: RemapPathScopeComponents = (RemapPathScopeComponents::all(), parse_remap_path_scope, [TRACKED],
2457 "remap path scope (default: all)"),
2458 remark_dir: Option<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED],
2459 "directory into which to write optimization remarks (if not specified, they will be \
2460written to standard error output)"),
2461 retpoline: bool = (false, parse_bool, [TRACKED TARGET_MODIFIER],
2462 "enables retpoline-indirect-branches and retpoline-indirect-calls target features (default: no)"),
2463 retpoline_external_thunk: bool = (false, parse_bool, [TRACKED TARGET_MODIFIER],
2464 "enables retpoline-external-thunk, retpoline-indirect-branches and retpoline-indirect-calls \
2465 target features (default: no)"),
2466 sanitizer: SanitizerSet = (SanitizerSet::empty(), parse_sanitizers, [TRACKED],
2467 "use a sanitizer"),
2468 sanitizer_cfi_canonical_jump_tables: Option<bool> = (Some(true), parse_opt_bool, [TRACKED],
2469 "enable canonical jump tables (default: yes)"),
2470 sanitizer_cfi_generalize_pointers: Option<bool> = (None, parse_opt_bool, [TRACKED],
2471 "enable generalizing pointer types (default: no)"),
2472 sanitizer_cfi_normalize_integers: Option<bool> = (None, parse_opt_bool, [TRACKED],
2473 "enable normalizing integer types (default: no)"),
2474 sanitizer_dataflow_abilist: Vec<String> = (Vec::new(), parse_comma_list, [TRACKED],
2475 "additional ABI list files that control how shadow parameters are passed (comma separated)"),
2476 sanitizer_kcfi_arity: Option<bool> = (None, parse_opt_bool, [TRACKED],
2477 "enable KCFI arity indicator (default: no)"),
2478 sanitizer_memory_track_origins: usize = (0, parse_sanitizer_memory_track_origins, [TRACKED],
2479 "enable origins tracking in MemorySanitizer"),
2480 sanitizer_recover: SanitizerSet = (SanitizerSet::empty(), parse_sanitizers, [TRACKED],
2481 "enable recovery for selected sanitizers"),
2482 saturating_float_casts: Option<bool> = (None, parse_opt_bool, [TRACKED],
2483 "make float->int casts UB-free: numbers outside the integer type's range are clipped to \
2484 the max/min integer respectively, and NaN is mapped to 0 (default: yes)"),
2485 self_profile: SwitchWithOptPath = (SwitchWithOptPath::Disabled,
2486 parse_switch_with_opt_path, [UNTRACKED],
2487 "run the self profiler and output the raw event data"),
2488 self_profile_counter: String = ("wall-time".to_string(), parse_string, [UNTRACKED],
2489 "counter used by the self profiler (default: `wall-time`), one of:
2490 `wall-time` (monotonic clock, i.e. `std::time::Instant`)
2491 `instructions:u` (retired instructions, userspace-only)
2492 `instructions-minus-irqs:u` (subtracting hardware interrupt counts for extra accuracy)"
2493 ),
2494 self_profile_events: Option<Vec<String>> = (None, parse_opt_comma_list, [UNTRACKED],
2496 "specify the events recorded by the self profiler;
2497 for example: `-Z self-profile-events=default,query-keys`
2498 all options: none, all, default, generic-activity, query-provider, query-cache-hit
2499 query-blocked, incr-cache-load, incr-result-hashing, query-keys, function-args, args, llvm, artifact-sizes"),
2500 share_generics: Option<bool> = (None, parse_opt_bool, [TRACKED],
2501 "make the current crate share its generic instantiations"),
2502 shell_argfiles: bool = (false, parse_bool, [UNTRACKED],
2503 "allow argument files to be specified with POSIX \"shell-style\" argument quoting"),
2504 simulate_remapped_rust_src_base: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
2505 "simulate the effect of remap-debuginfo = true at bootstrapping by remapping path \
2506 to rust's source base directory. only meant for testing purposes"),
2507 small_data_threshold: Option<usize> = (None, parse_opt_number, [TRACKED],
2508 "Set the threshold for objects to be stored in a \"small data\" section"),
2509 span_debug: bool = (false, parse_bool, [UNTRACKED],
2510 "forward proc_macro::Span's `Debug` impl to `Span`"),
2511 span_free_formats: bool = (false, parse_bool, [UNTRACKED],
2513 "exclude spans when debug-printing compiler state (default: no)"),
2514 split_dwarf_inlining: bool = (false, parse_bool, [TRACKED],
2515 "provide minimal debug info in the object/executable to facilitate online \
2516 symbolication/stack traces in the absence of .dwo/.dwp files when using Split DWARF"),
2517 split_dwarf_kind: SplitDwarfKind = (SplitDwarfKind::Split, parse_split_dwarf_kind, [TRACKED],
2518 "split dwarf variant (only if -Csplit-debuginfo is enabled and on relevant platform)
2519 (default: `split`)
2520
2521 `split`: sections which do not require relocation are written into a DWARF object (`.dwo`)
2522 file which is ignored by the linker
2523 `single`: sections which do not require relocation are written into object file but ignored
2524 by the linker"),
2525 split_lto_unit: Option<bool> = (None, parse_opt_bool, [TRACKED],
2526 "enable LTO unit splitting (default: no)"),
2527 src_hash_algorithm: Option<SourceFileHashAlgorithm> = (None, parse_src_file_hash, [TRACKED],
2528 "hash algorithm of source files in debug info (`md5`, `sha1`, or `sha256`)"),
2529 #[rustc_lint_opt_deny_field_access("use `Session::stack_protector` instead of this field")]
2530 stack_protector: StackProtector = (StackProtector::None, parse_stack_protector, [TRACKED],
2531 "control stack smash protection strategy (`rustc --print stack-protector-strategies` for details)"),
2532 staticlib_allow_rdylib_deps: bool = (false, parse_bool, [TRACKED],
2533 "allow staticlibs to have rust dylib dependencies"),
2534 staticlib_prefer_dynamic: bool = (false, parse_bool, [TRACKED],
2535 "prefer dynamic linking to static linking for staticlibs (default: no)"),
2536 strict_init_checks: bool = (false, parse_bool, [TRACKED],
2537 "control if mem::uninitialized and mem::zeroed panic on more UB"),
2538 #[rustc_lint_opt_deny_field_access("use `Session::teach` instead of this field")]
2539 teach: bool = (false, parse_bool, [TRACKED],
2540 "show extended diagnostic help (default: no)"),
2541 temps_dir: Option<String> = (None, parse_opt_string, [UNTRACKED],
2542 "the directory the intermediate files are written to"),
2543 terminal_urls: TerminalUrl = (TerminalUrl::No, parse_terminal_url, [UNTRACKED],
2544 "use the OSC 8 hyperlink terminal specification to print hyperlinks in the compiler output"),
2545 #[rustc_lint_opt_deny_field_access("use `Session::lto` instead of this field")]
2546 thinlto: Option<bool> = (None, parse_opt_bool, [TRACKED],
2547 "enable ThinLTO when possible"),
2548 #[rustc_lint_opt_deny_field_access("use `Session::threads` instead of this field")]
2553 threads: usize = (1, parse_threads, [UNTRACKED],
2554 "use a thread pool with N threads"),
2555 time_llvm_passes: bool = (false, parse_bool, [UNTRACKED],
2556 "measure time of each LLVM pass (default: no)"),
2557 time_passes: bool = (false, parse_bool, [UNTRACKED],
2558 "measure time of each rustc pass (default: no)"),
2559 time_passes_format: TimePassesFormat = (TimePassesFormat::Text, parse_time_passes_format, [UNTRACKED],
2560 "the format to use for -Z time-passes (`text` (default) or `json`)"),
2561 tiny_const_eval_limit: bool = (false, parse_bool, [TRACKED],
2562 "sets a tiny, non-configurable limit for const eval; useful for compiler tests"),
2563 #[rustc_lint_opt_deny_field_access("use `Session::tls_model` instead of this field")]
2564 tls_model: Option<TlsModel> = (None, parse_tls_model, [TRACKED],
2565 "choose the TLS model to use (`rustc --print tls-models` for details)"),
2566 trace_macros: bool = (false, parse_bool, [UNTRACKED],
2567 "for every macro invocation, print its name and arguments (default: no)"),
2568 track_diagnostics: bool = (false, parse_bool, [UNTRACKED],
2569 "tracks where in rustc a diagnostic was emitted"),
2570 translate_additional_ftl: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
2574 "additional fluent translation to preferentially use (for testing translation)"),
2575 translate_directionality_markers: bool = (false, parse_bool, [TRACKED],
2576 "emit directionality isolation markers in translated diagnostics"),
2577 translate_lang: Option<LanguageIdentifier> = (None, parse_opt_langid, [TRACKED],
2578 "language identifier for diagnostic output"),
2579 translate_remapped_path_to_local_path: bool = (true, parse_bool, [TRACKED],
2580 "translate remapped paths into local paths when possible (default: yes)"),
2581 trap_unreachable: Option<bool> = (None, parse_opt_bool, [TRACKED],
2582 "generate trap instructions for unreachable intrinsics (default: use target setting, usually yes)"),
2583 treat_err_as_bug: Option<NonZero<usize>> = (None, parse_treat_err_as_bug, [TRACKED],
2584 "treat the `val`th error that occurs as bug (default if not specified: 0 - don't treat errors as bugs. \
2585 default if specified without a value: 1 - treat the first error as bug)"),
2586 trim_diagnostic_paths: bool = (true, parse_bool, [UNTRACKED],
2587 "in diagnostics, use heuristics to shorten paths referring to items"),
2588 tune_cpu: Option<String> = (None, parse_opt_string, [TRACKED],
2589 "select processor to schedule for (`rustc --print target-cpus` for details)"),
2590 #[rustc_lint_opt_deny_field_access("use `TyCtxt::use_typing_mode_borrowck` instead of this field")]
2591 typing_mode_borrowck: bool = (false, parse_bool, [TRACKED],
2592 "enable `TypingMode::Borrowck`, changing the way opaque types are handled during MIR borrowck"),
2593 #[rustc_lint_opt_deny_field_access("use `Session::ub_checks` instead of this field")]
2594 ub_checks: Option<bool> = (None, parse_opt_bool, [TRACKED],
2595 "emit runtime checks for Undefined Behavior (default: -Cdebug-assertions)"),
2596 ui_testing: bool = (false, parse_bool, [UNTRACKED],
2597 "emit compiler diagnostics in a form suitable for UI testing (default: no)"),
2598 uninit_const_chunk_threshold: usize = (16, parse_number, [TRACKED],
2599 "allow generating const initializers with mixed init/uninit chunks, \
2600 and set the maximum number of chunks for which this is allowed (default: 16)"),
2601 unleash_the_miri_inside_of_you: bool = (false, parse_bool, [TRACKED],
2602 "take the brakes off const evaluation. NOTE: this is unsound (default: no)"),
2603 unpretty: Option<String> = (None, parse_unpretty, [UNTRACKED],
2604 "present the input source, unstable (and less-pretty) variants;
2605 `normal`, `identified`,
2606 `expanded`, `expanded,identified`,
2607 `expanded,hygiene` (with internal representations),
2608 `ast-tree` (raw AST before expansion),
2609 `ast-tree,expanded` (raw AST after expansion),
2610 `hir` (the HIR), `hir,identified`,
2611 `hir,typed` (HIR with types for each node),
2612 `hir-tree` (dump the raw HIR),
2613 `thir-tree`, `thir-flat`,
2614 `mir` (the MIR), or `mir-cfg` (graphviz formatted MIR)"),
2615 unsound_mir_opts: bool = (false, parse_bool, [TRACKED],
2616 "enable unsound and buggy MIR optimizations (default: no)"),
2617 #[rustc_lint_opt_deny_field_access("use `Session::unstable_options` instead of this field")]
2626 unstable_options: bool = (false, parse_no_value, [UNTRACKED],
2627 "adds unstable command line options to rustc interface (default: no)"),
2628 use_ctors_section: Option<bool> = (None, parse_opt_bool, [TRACKED],
2629 "use legacy .ctors section for initializers rather than .init_array"),
2630 use_sync_unwind: Option<bool> = (None, parse_opt_bool, [TRACKED],
2631 "Generate sync unwind tables instead of async unwind tables (default: no)"),
2632 validate_mir: bool = (false, parse_bool, [UNTRACKED],
2633 "validate MIR after each transformation"),
2634 verbose_asm: bool = (false, parse_bool, [TRACKED],
2635 "add descriptive comments from LLVM to the assembly (may change behavior) (default: no)"),
2636 #[rustc_lint_opt_deny_field_access("use `Session::verbose_internals` instead of this field")]
2637 verbose_internals: bool = (false, parse_bool, [TRACKED_NO_CRATE_HASH],
2638 "in general, enable more debug printouts (default: no)"),
2639 #[rustc_lint_opt_deny_field_access("use `Session::verify_llvm_ir` instead of this field")]
2640 verify_llvm_ir: bool = (false, parse_bool, [TRACKED],
2641 "verify LLVM IR (default: no)"),
2642 virtual_function_elimination: bool = (false, parse_bool, [TRACKED],
2643 "enables dead virtual function elimination optimization. \
2644 Requires `-Clto[=[fat,yes]]`"),
2645 wasi_exec_model: Option<WasiExecModel> = (None, parse_wasi_exec_model, [TRACKED],
2646 "whether to build a wasi command or reactor"),
2647 wasm_c_abi: () = ((), parse_wasm_c_abi, [TRACKED],
2651 "use spec-compliant C ABI for `wasm32-unknown-unknown` (deprecated, always enabled)"),
2652 write_long_types_to_disk: bool = (true, parse_bool, [UNTRACKED],
2653 "whether long type names should be written to files instead of being printed in errors"),
2654 }