Skip to content

rustc_session: Move more option building code from the options! macro #85079

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions compiler/rustc_session/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -685,10 +685,10 @@ impl Default for Options {
target_triple: TargetTriple::from_triple(host_triple()),
test: false,
incremental: None,
debugging_opts: basic_debugging_options(),
debugging_opts: Default::default(),
prints: Vec::new(),
borrowck_mode: BorrowckMode::Migrate,
cg: basic_codegen_options(),
cg: Default::default(),
error_format: ErrorOutputType::default(),
externs: Externs(BTreeMap::new()),
extern_dep_specs: ExternDepSpecs(BTreeMap::new()),
Expand Down Expand Up @@ -1925,7 +1925,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {

let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format);

let mut debugging_opts = build_debugging_options(matches, error_format);
let mut debugging_opts = DebuggingOptions::build(matches, error_format);
check_debug_option_stability(&debugging_opts, error_format, json_rendered);

if !debugging_opts.unstable_options && json_unused_externs {
Expand All @@ -1938,7 +1938,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {

let output_types = parse_output_types(&debugging_opts, matches, error_format);

let mut cg = build_codegen_options(matches, error_format);
let mut cg = CodegenOptions::build(matches, error_format);
let (disable_thinlto, mut codegen_units) = should_override_cgus_and_disable_thinlto(
&output_types,
matches,
Expand Down
140 changes: 78 additions & 62 deletions compiler/rustc_session/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,9 +210,7 @@ top_level_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,
Expand All @@ -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();
$({
Expand All @@ -284,26 +252,76 @@ macro_rules! options {
}
}

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";
Expand Down Expand Up @@ -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.
//
Expand Down Expand Up @@ -957,9 +974,8 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options,
// - 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.
//
Expand Down
9 changes: 3 additions & 6 deletions src/librustdoc/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@ use std::str::FromStr;

use rustc_data_structures::fx::FxHashMap;
use rustc_session::config::{self, parse_crate_types_from_list, parse_externs, CrateType};
use rustc_session::config::{
build_codegen_options, build_debugging_options, get_cmd_lint_options, host_triple,
nightly_options,
};
use rustc_session::config::{get_cmd_lint_options, host_triple, nightly_options};
use rustc_session::config::{CodegenOptions, DebuggingOptions, ErrorOutputType, Externs};
use rustc_session::getopts;
use rustc_session::lint::Level;
Expand Down Expand Up @@ -360,8 +357,8 @@ impl Options {
config::parse_json(&matches);
let error_format = config::parse_error_format(&matches, color, json_rendered);

let codegen_options = build_codegen_options(matches, error_format);
let debugging_opts = build_debugging_options(matches, error_format);
let codegen_options = CodegenOptions::build(matches, error_format);
let debugging_opts = DebuggingOptions::build(matches, error_format);

let diag = new_handler(error_format, None, &debugging_opts);

Expand Down
1 change: 0 additions & 1 deletion src/librustdoc/doctest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ crate fn run(options: Options) -> Result<(), ErrorReported> {
externs: options.externs.clone(),
unstable_features: options.render_options.unstable_features,
actually_rustdoc: true,
debugging_opts: config::DebuggingOptions { ..config::basic_debugging_options() },
edition: options.edition,
target_triple: options.target.clone(),
crate_name: options.crate_name.clone(),
Expand Down