]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_session/src/options.rs
Auto merge of #83129 - LeSeulArtichaut:thir-unsafeck, r=nikomatsakis
[rust.git] / compiler / rustc_session / src / options.rs
index 7799dfd19782aae312730b230edf96bb190243cc..c9f95ed1224d0d23312b94e6c8952b491dd0c110 100644 (file)
@@ -210,9 +210,7 @@ pub struct Options {
 /// generated code to parse an option into its respective field in the struct. There are a few
 /// hand-written parsers for parsing specific types of values in this module.
 macro_rules! options {
-    ($struct_name:ident, $setter_name:ident, $defaultfn:ident,
-     $buildfn:ident, $prefix:expr, $outputname:expr,
-     $stat:ident,
+    ($struct_name:ident, $stat:ident, $prefix:expr, $outputname:expr,
      $($( #[$attr:meta] )* $opt:ident : $t:ty = (
         $init:expr,
         $parse:ident,
@@ -223,50 +221,20 @@ macro_rules! options {
     #[derive(Clone)]
     pub struct $struct_name { $(pub $opt: $t),* }
 
-    pub fn $defaultfn() -> $struct_name {
-        $struct_name { $( $( #[$attr] )* $opt: $init),* }
-    }
-
-    pub fn $buildfn(matches: &getopts::Matches, error_format: ErrorOutputType) -> $struct_name
-    {
-        let mut op = $defaultfn();
-        for option in matches.opt_strs($prefix) {
-            let (key, value) = match option.split_once('=') {
-                None => (option, None),
-                Some((k, v)) => (k.to_string(), Some(v)),
-            };
-            let option_to_lookup = key.replace("-", "_");
-            let mut found = false;
-            for &(candidate, setter, type_desc, _) in $stat {
-                if option_to_lookup != candidate { continue }
-                if !setter(&mut op, value) {
-                    match value {
-                        None => {
-                            early_error(error_format, &format!("{0} option `{1}` requires \
-                                                                {2} ({3} {1}=<value>)",
-                                                               $outputname, key,
-                                                               type_desc, $prefix))
-                        }
-                        Some(value) => {
-                            early_error(error_format, &format!("incorrect value `{}` for {} \
-                                                                option `{}` - {} was expected",
-                                                               value, $outputname,
-                                                               key, type_desc))
-                        }
-                    }
-                }
-                found = true;
-                break;
-            }
-            if !found {
-                early_error(error_format, &format!("unknown {} option: `{}`",
-                                                   $outputname, key));
-            }
+    impl Default for $struct_name {
+        fn default() -> $struct_name {
+            $struct_name { $( $( #[$attr] )* $opt: $init),* }
         }
-        return op;
     }
 
     impl $struct_name {
+        pub fn build(
+            matches: &getopts::Matches,
+            error_format: ErrorOutputType,
+        ) -> $struct_name {
+            build_options(matches, $stat, $prefix, $outputname, error_format)
+        }
+
         fn dep_tracking_hash(&self, _for_crate_hash: bool, error_format: ErrorOutputType) -> u64 {
             let mut sub_hashes = BTreeMap::new();
             $({
@@ -284,26 +252,76 @@ fn dep_tracking_hash(&self, _for_crate_hash: bool, error_format: ErrorOutputType
         }
     }
 
-    pub type $setter_name = fn(&mut $struct_name, v: Option<&str>) -> bool;
-    pub const $stat: &[(&str, $setter_name, &str, &str)] =
-        &[ $( (stringify!($opt), $crate::options::parse::$opt, $crate::options::desc::$parse, $desc) ),* ];
-
-    // Sometimes different options need to build a common structure.
-    // That structure can kept in one of the options' fields, the others become dummy.
-    macro_rules! redirect_field {
-        ($cg:ident.link_arg) => { $cg.link_args };
-        ($cg:ident.pre_link_arg) => { $cg.pre_link_args };
-        ($cg:ident.$field:ident) => { $cg.$field };
-    }
+    pub const $stat: OptionDescrs<$struct_name> =
+        &[ $( (stringify!($opt), $opt, desc::$parse, $desc) ),* ];
 
     $(
-        pub fn $opt(cg: &mut $struct_name, v: Option<&str>) -> bool {
-            $crate::options::parse::$parse(&mut redirect_field!(cg.$opt), v)
+        fn $opt(cg: &mut $struct_name, v: Option<&str>) -> bool {
+            parse::$parse(&mut redirect_field!(cg.$opt), v)
         }
     )*
 
 ) }
 
+// Sometimes different options need to build a common structure.
+// That structure can be kept in one of the options' fields, the others become dummy.
+macro_rules! redirect_field {
+    ($cg:ident.link_arg) => {
+        $cg.link_args
+    };
+    ($cg:ident.pre_link_arg) => {
+        $cg.pre_link_args
+    };
+    ($cg:ident.$field:ident) => {
+        $cg.$field
+    };
+}
+
+type OptionSetter<O> = fn(&mut O, v: Option<&str>) -> bool;
+type OptionDescrs<O> = &'static [(&'static str, OptionSetter<O>, &'static str, &'static str)];
+
+fn build_options<O: Default>(
+    matches: &getopts::Matches,
+    descrs: OptionDescrs<O>,
+    prefix: &str,
+    outputname: &str,
+    error_format: ErrorOutputType,
+) -> O {
+    let mut op = O::default();
+    for option in matches.opt_strs(prefix) {
+        let (key, value) = match option.split_once('=') {
+            None => (option, None),
+            Some((k, v)) => (k.to_string(), Some(v)),
+        };
+
+        let option_to_lookup = key.replace("-", "_");
+        match descrs.iter().find(|(name, ..)| *name == option_to_lookup) {
+            Some((_, setter, type_desc, _)) => {
+                if !setter(&mut op, value) {
+                    match value {
+                        None => early_error(
+                            error_format,
+                            &format!(
+                                "{0} option `{1}` requires {2} ({3} {1}=<value>)",
+                                outputname, key, type_desc, prefix
+                            ),
+                        ),
+                        Some(value) => early_error(
+                            error_format,
+                            &format!(
+                                "incorrect value `{}` for {} option `{}` - {} was expected",
+                                value, outputname, key, type_desc
+                            ),
+                        ),
+                    }
+                }
+            }
+            None => early_error(error_format, &format!("unknown {} option: `{}`", outputname, key)),
+        }
+    }
+    return op;
+}
+
 #[allow(non_upper_case_globals)]
 mod desc {
     pub const parse_no_flag: &str = "no value";
@@ -603,9 +621,9 @@ mod parse {
         true
     }
 
-    crate fn parse_linker_flavor(slote: &mut Option<LinkerFlavor>, v: Option<&str>) -> bool {
+    crate fn parse_linker_flavor(slot: &mut Option<LinkerFlavor>, v: Option<&str>) -> bool {
         match v.and_then(LinkerFlavor::from_str) {
-            Some(lf) => *slote = Some(lf),
+            Some(lf) => *slot = Some(lf),
             _ => return false,
         }
         true
@@ -847,9 +865,8 @@ mod parse {
     }
 }
 
-options! {CodegenOptions, CodegenSetter, basic_codegen_options,
-          build_codegen_options, "C", "codegen",
-          CG_OPTIONS,
+options! {
+    CodegenOptions, CG_OPTIONS, "C", "codegen",
 
     // This list is in alphabetical order.
     //
@@ -957,9 +974,8 @@ mod parse {
     // - src/doc/rustc/src/codegen-options/index.md
 }
 
-options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
-          build_debugging_options, "Z", "debugging",
-          DB_OPTIONS,
+options! {
+    DebuggingOptions, DB_OPTIONS, "Z", "debugging",
 
     // This list is in alphabetical order.
     //
@@ -1080,12 +1096,12 @@ mod parse {
         "gather statistics about the input (default: no)"),
     instrument_coverage: Option<InstrumentCoverage> = (None, parse_instrument_coverage, [TRACKED],
         "instrument the generated code to support LLVM source-based code coverage \
-        reports (note, the compiler build config must include `profiler = true`, \
-        and is mutually exclusive with `-C profile-generate`/`-C profile-use`); \
-        implies `-Z symbol-mangling-version=v0`; disables/overrides some Rust \
-        optimizations. Optional values are: `=all` (default coverage), \
-        `=except-unused-generics`, `=except-unused-functions`, or `=off` \
-        (default: instrument-coverage=off)"),
+        reports (note, the compiler build config must include `profiler = true`); \
+        implies `-Z symbol-mangling-version=v0`. Optional values are:
+        `=all` (implicit value)
+        `=except-unused-generics`
+        `=except-unused-functions`
+        `=off` (default)"),
     instrument_mcount: bool = (false, parse_bool, [TRACKED],
         "insert function instrument code for mcount-based tracing (default: no)"),
     keep_hygiene_data: bool = (false, parse_bool, [UNTRACKED],
@@ -1112,7 +1128,7 @@ mod parse {
         "MIR optimization level (0-4; default: 1 in non optimized builds and 2 in optimized builds)"),
     mutable_noalias: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "emit noalias metadata for mutable references (default: yes for LLVM >= 12, otherwise no)"),
-    new_llvm_pass_manager: bool = (false, parse_bool, [TRACKED],
+    new_llvm_pass_manager: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "use new LLVM pass manager (default: no)"),
     nll_facts: bool = (false, parse_bool, [UNTRACKED],
         "dump facts from NLL analysis into side files (default: no)"),
@@ -1185,6 +1201,9 @@ mod parse {
         "whether ELF relocations can be relaxed"),
     relro_level: Option<RelroLevel> = (None, parse_relro_level, [TRACKED],
         "choose which RELRO level to use"),
+    simulate_remapped_rust_src_base: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
+        "simulate the effect of remap-debuginfo = true at bootstrapping by remapping path \
+        to rust's source base directory. only meant for testing purposes"),
     report_delayed_bugs: bool = (false, parse_bool, [TRACKED],
         "immediately print bugs registered with `delay_span_bug` (default: no)"),
     sanitizer: SanitizerSet = (SanitizerSet::empty(), parse_sanitizers, [TRACKED],
@@ -1235,6 +1254,8 @@ mod parse {
         "select processor to schedule for (`rustc --print target-cpus` for details)"),
     thinlto: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "enable ThinLTO when possible"),
+    thir_unsafeck: bool = (false, parse_bool, [TRACKED],
+        "use the work-in-progress THIR unsafety checker. NOTE: this is unsound (default: no)"),
     /// We default to 1 here since we want to behave like
     /// a sequential compiler for now. This'll likely be adjusted
     /// in the future. Note that -Zthreads=0 is the way to get