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