summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_session/src/config.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_session/src/config.rs')
-rw-r--r--compiler/rustc_session/src/config.rs335
1 files changed, 189 insertions, 146 deletions
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 79eb31bb1..6c8c8e484 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -421,7 +421,7 @@ pub enum TrimmedDefPaths {
GoodPath,
}
-#[derive(Clone, Hash)]
+#[derive(Clone, Hash, Debug)]
pub enum ResolveDocLinks {
/// Do not resolve doc links.
None,
@@ -518,6 +518,12 @@ pub struct ExternEntry {
/// `--extern nounused:std=/path/to/lib/libstd.rlib`. This is used to
/// suppress `unused-crate-dependencies` warnings.
pub nounused_dep: bool,
+ /// If the extern entry is not referenced in the crate, force it to be resolved anyway.
+ ///
+ /// Allows a dependency satisfying, for instance, a missing panic handler to be injected
+ /// without modifying source:
+ /// `--extern force:extras=/path/to/lib/libstd.rlib`
+ pub force: bool,
}
#[derive(Clone, Debug)]
@@ -556,7 +562,13 @@ impl Externs {
impl ExternEntry {
fn new(location: ExternLocation) -> ExternEntry {
- ExternEntry { location, is_private_dep: false, add_prelude: false, nounused_dep: false }
+ ExternEntry {
+ location,
+ is_private_dep: false,
+ add_prelude: false,
+ nounused_dep: false,
+ force: false,
+ }
}
pub fn files(&self) -> Option<impl Iterator<Item = &CanonicalizedPath>> {
@@ -587,6 +599,7 @@ pub enum PrintRequest {
StackProtectorStrategies,
LinkArgs,
SplitDebuginfo,
+ DeploymentTarget,
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
@@ -1036,9 +1049,20 @@ fn default_configuration(sess: &Session) -> CrateConfig {
ret.insert((sym::sanitize, Some(symbol)));
}
+ if sess.is_sanitizer_cfi_generalize_pointers_enabled() {
+ ret.insert((sym::sanitizer_cfi_generalize_pointers, None));
+ }
+
+ if sess.is_sanitizer_cfi_normalize_integers_enabled() {
+ ret.insert((sym::sanitizer_cfi_normalize_integers, None));
+ }
+
if sess.opts.debug_assertions {
ret.insert((sym::debug_assertions, None));
}
+ if sess.overflow_checks() {
+ ret.insert((sym::overflow_checks, None));
+ }
// JUSTIFICATION: before wrapper fn is available
#[allow(rustc::bad_opt_access)]
if sess.opts.crate_types.contains(&CrateType::ProcMacro) {
@@ -1056,37 +1080,76 @@ pub fn to_crate_config(cfg: FxHashSet<(String, Option<String>)>) -> CrateConfig
/// The parsed `--check-cfg` options
pub struct CheckCfg<T = String> {
- /// The set of all `names()`, if None no name checking is performed
- pub names_valid: Option<FxHashSet<T>>,
+ /// Is well known names activated
+ pub exhaustive_names: bool,
/// Is well known values activated
- pub well_known_values: bool,
- /// The set of all `values()`
- pub values_valid: FxHashMap<T, FxHashSet<T>>,
+ pub exhaustive_values: bool,
+ /// All the expected values for a config name
+ pub expecteds: FxHashMap<T, ExpectedValues<T>>,
}
impl<T> Default for CheckCfg<T> {
fn default() -> Self {
CheckCfg {
- names_valid: Default::default(),
- values_valid: Default::default(),
- well_known_values: false,
+ exhaustive_names: false,
+ exhaustive_values: false,
+ expecteds: FxHashMap::default(),
}
}
}
impl<T> CheckCfg<T> {
- fn map_data<O: Eq + Hash>(&self, f: impl Fn(&T) -> O) -> CheckCfg<O> {
+ fn map_data<O: Eq + Hash>(self, f: impl Fn(T) -> O) -> CheckCfg<O> {
CheckCfg {
- names_valid: self
- .names_valid
- .as_ref()
- .map(|names_valid| names_valid.iter().map(|a| f(a)).collect()),
- values_valid: self
- .values_valid
- .iter()
- .map(|(a, b)| (f(a), b.iter().map(|b| f(b)).collect()))
+ exhaustive_names: self.exhaustive_names,
+ exhaustive_values: self.exhaustive_values,
+ expecteds: self
+ .expecteds
+ .into_iter()
+ .map(|(name, values)| {
+ (
+ f(name),
+ match values {
+ ExpectedValues::Some(values) => ExpectedValues::Some(
+ values.into_iter().map(|b| b.map(|b| f(b))).collect(),
+ ),
+ ExpectedValues::Any => ExpectedValues::Any,
+ },
+ )
+ })
.collect(),
- well_known_values: self.well_known_values,
+ }
+ }
+}
+
+pub enum ExpectedValues<T> {
+ Some(FxHashSet<Option<T>>),
+ Any,
+}
+
+impl<T: Eq + Hash> ExpectedValues<T> {
+ fn insert(&mut self, value: T) -> bool {
+ match self {
+ ExpectedValues::Some(expecteds) => expecteds.insert(Some(value)),
+ ExpectedValues::Any => false,
+ }
+ }
+}
+
+impl<T: Eq + Hash> Extend<T> for ExpectedValues<T> {
+ fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
+ match self {
+ ExpectedValues::Some(expecteds) => expecteds.extend(iter.into_iter().map(Some)),
+ ExpectedValues::Any => {}
+ }
+ }
+}
+
+impl<'a, T: Eq + Hash + Copy + 'a> Extend<&'a T> for ExpectedValues<T> {
+ fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
+ match self {
+ ExpectedValues::Some(expecteds) => expecteds.extend(iter.into_iter().map(|a| Some(*a))),
+ ExpectedValues::Any => {}
}
}
}
@@ -1095,58 +1158,27 @@ impl<T> CheckCfg<T> {
/// `rustc_interface::interface::Config` accepts this in the compiler configuration,
/// but the symbol interner is not yet set up then, so we must convert it later.
pub fn to_crate_check_config(cfg: CheckCfg) -> CrateCheckConfig {
- cfg.map_data(|s| Symbol::intern(s))
+ cfg.map_data(|s| Symbol::intern(&s))
}
impl CrateCheckConfig {
- /// Fills a `CrateCheckConfig` with well-known configuration names.
- fn fill_well_known_names(&mut self) {
- // NOTE: This should be kept in sync with `default_configuration` and
- // `fill_well_known_values`
- const WELL_KNOWN_NAMES: &[Symbol] = &[
- // rustc
- sym::unix,
- sym::windows,
- sym::target_os,
- sym::target_family,
- sym::target_arch,
- sym::target_endian,
- sym::target_pointer_width,
- sym::target_env,
- sym::target_abi,
- sym::target_vendor,
- sym::target_thread_local,
- sym::target_has_atomic_load_store,
- sym::target_has_atomic,
- sym::target_has_atomic_equal_alignment,
- sym::target_feature,
- sym::panic,
- sym::sanitize,
- sym::debug_assertions,
- sym::proc_macro,
- sym::test,
- sym::feature,
- // rustdoc
- sym::doc,
- sym::doctest,
- // miri
- sym::miri,
- ];
-
- // We only insert well-known names if `names()` was activated
- if let Some(names_valid) = &mut self.names_valid {
- names_valid.extend(WELL_KNOWN_NAMES);
- }
- }
-
- /// Fills a `CrateCheckConfig` with well-known configuration values.
- fn fill_well_known_values(&mut self, current_target: &Target) {
- if !self.well_known_values {
+ pub fn fill_well_known(&mut self, current_target: &Target) {
+ if !self.exhaustive_values && !self.exhaustive_names {
return;
}
- // NOTE: This should be kept in sync with `default_configuration` and
- // `fill_well_known_names`
+ let no_values = || {
+ let mut values = FxHashSet::default();
+ values.insert(None);
+ ExpectedValues::Some(values)
+ };
+
+ let empty_values = || {
+ let values = FxHashSet::default();
+ ExpectedValues::Some(values)
+ };
+
+ // NOTE: This should be kept in sync with `default_configuration`
let panic_values = &PanicStrategy::all();
@@ -1166,6 +1198,9 @@ impl CrateCheckConfig {
// Unknown possible values:
// - `feature`
// - `target_feature`
+ for name in [sym::feature, sym::target_feature] {
+ self.expecteds.entry(name).or_insert(ExpectedValues::Any);
+ }
// No-values
for name in [
@@ -1177,22 +1212,26 @@ impl CrateCheckConfig {
sym::windows,
sym::proc_macro,
sym::debug_assertions,
+ sym::overflow_checks,
sym::target_thread_local,
] {
- self.values_valid.entry(name).or_default();
+ self.expecteds.entry(name).or_insert_with(no_values);
}
// Pre-defined values
- self.values_valid.entry(sym::panic).or_default().extend(panic_values);
- self.values_valid.entry(sym::sanitize).or_default().extend(sanitize_values);
- self.values_valid.entry(sym::target_has_atomic).or_default().extend(atomic_values);
- self.values_valid
+ self.expecteds.entry(sym::panic).or_insert_with(empty_values).extend(panic_values);
+ self.expecteds.entry(sym::sanitize).or_insert_with(empty_values).extend(sanitize_values);
+ self.expecteds
+ .entry(sym::target_has_atomic)
+ .or_insert_with(no_values)
+ .extend(atomic_values);
+ self.expecteds
.entry(sym::target_has_atomic_load_store)
- .or_default()
+ .or_insert_with(no_values)
.extend(atomic_values);
- self.values_valid
+ self.expecteds
.entry(sym::target_has_atomic_equal_alignment)
- .or_default()
+ .or_insert_with(no_values)
.extend(atomic_values);
// Target specific values
@@ -1210,47 +1249,50 @@ impl CrateCheckConfig {
// Initialize (if not already initialized)
for &e in VALUES {
- self.values_valid.entry(e).or_default();
+ let entry = self.expecteds.entry(e);
+ if !self.exhaustive_values {
+ entry.or_insert(ExpectedValues::Any);
+ } else {
+ entry.or_insert_with(empty_values);
+ }
}
- // Get all values map at once otherwise it would be costly.
- // (8 values * 220 targets ~= 1760 times, at the time of writing this comment).
- let [
- values_target_os,
- values_target_family,
- values_target_arch,
- values_target_endian,
- values_target_env,
- values_target_abi,
- values_target_vendor,
- values_target_pointer_width,
- ] = self
- .values_valid
- .get_many_mut(VALUES)
- .expect("unable to get all the check-cfg values buckets");
-
- for target in TARGETS
- .iter()
- .map(|target| Target::expect_builtin(&TargetTriple::from_triple(target)))
- .chain(iter::once(current_target.clone()))
- {
- values_target_os.insert(Symbol::intern(&target.options.os));
- values_target_family
- .extend(target.options.families.iter().map(|family| Symbol::intern(family)));
- values_target_arch.insert(Symbol::intern(&target.arch));
- values_target_endian.insert(Symbol::intern(target.options.endian.as_str()));
- values_target_env.insert(Symbol::intern(&target.options.env));
- values_target_abi.insert(Symbol::intern(&target.options.abi));
- values_target_vendor.insert(Symbol::intern(&target.options.vendor));
- values_target_pointer_width.insert(sym::integer(target.pointer_width));
+ if self.exhaustive_values {
+ // Get all values map at once otherwise it would be costly.
+ // (8 values * 220 targets ~= 1760 times, at the time of writing this comment).
+ let [
+ values_target_os,
+ values_target_family,
+ values_target_arch,
+ values_target_endian,
+ values_target_env,
+ values_target_abi,
+ values_target_vendor,
+ values_target_pointer_width,
+ ] = self
+ .expecteds
+ .get_many_mut(VALUES)
+ .expect("unable to get all the check-cfg values buckets");
+
+ for target in TARGETS
+ .iter()
+ .map(|target| Target::expect_builtin(&TargetTriple::from_triple(target)))
+ .chain(iter::once(current_target.clone()))
+ {
+ values_target_os.insert(Symbol::intern(&target.options.os));
+ values_target_family.extend(
+ target.options.families.iter().map(|family| Symbol::intern(family)),
+ );
+ values_target_arch.insert(Symbol::intern(&target.arch));
+ values_target_endian.insert(Symbol::intern(target.options.endian.as_str()));
+ values_target_env.insert(Symbol::intern(&target.options.env));
+ values_target_abi.insert(Symbol::intern(&target.options.abi));
+ values_target_vendor.insert(Symbol::intern(&target.options.vendor));
+ values_target_pointer_width.insert(sym::integer(target.pointer_width));
+ }
}
}
}
-
- pub fn fill_well_known(&mut self, current_target: &Target) {
- self.fill_well_known_names();
- self.fill_well_known_values(current_target);
- }
}
pub fn build_configuration(sess: &Session, mut user_cfg: CrateConfig) -> CrateConfig {
@@ -1277,7 +1319,7 @@ pub(super) fn build_target_config(
let (target, target_warnings) = target_result.unwrap_or_else(|e| {
early_error(
opts.error_format,
- &format!(
+ format!(
"Error loading target specification: {}. \
Run `rustc --print target-list` for a list of built-in targets",
e
@@ -1285,15 +1327,14 @@ pub(super) fn build_target_config(
)
});
for warning in target_warnings.warning_messages() {
- early_warn(opts.error_format, &warning)
+ early_warn(opts.error_format, warning)
}
if !matches!(target.pointer_width, 16 | 32 | 64) {
early_error(
opts.error_format,
- &format!(
- "target specification was invalid: \
- unrecognized target-pointer-width {}",
+ format!(
+ "target specification was invalid: unrecognized target-pointer-width {}",
target.pointer_width
),
)
@@ -1400,7 +1441,8 @@ The default is {DEFAULT_EDITION} and the latest stable edition is {LATEST_STABLE
pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
vec![
opt::flag_s("h", "help", "Display this message"),
- opt::multi_s("", "cfg", "Configure the compilation environment", "SPEC"),
+ opt::multi_s("", "cfg", "Configure the compilation environment.
+ SPEC supports the syntax `NAME[=\"VALUE\"]`.", "SPEC"),
opt::multi("", "check-cfg", "Provide list of valid cfg options for checking", "SPEC"),
opt::multi_s(
"L",
@@ -1443,7 +1485,7 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
"[crate-name|file-names|sysroot|target-libdir|cfg|calling-conventions|\
target-list|target-cpus|target-features|relocation-models|code-models|\
tls-models|target-spec-json|all-target-specs-json|native-static-libs|\
- stack-protector-strategies|link-args]",
+ stack-protector-strategies|link-args|deployment-target]",
),
opt::flagmulti_s("g", "", "Equivalent to -C debuginfo=2"),
opt::flagmulti_s("O", "", "Equivalent to -C opt-level=2"),
@@ -1556,7 +1598,7 @@ pub fn get_cmd_lint_options(
let lint_cap = matches.opt_str("cap-lints").map(|cap| {
lint::Level::from_str(&cap)
- .unwrap_or_else(|| early_error(error_format, &format!("unknown lint level: `{cap}`")))
+ .unwrap_or_else(|| early_error(error_format, format!("unknown lint level: `{cap}`")))
});
(lint_opts, describe_lints, lint_cap)
@@ -1573,7 +1615,7 @@ pub fn parse_color(matches: &getopts::Matches) -> ColorConfig {
Some(arg) => early_error(
ErrorOutputType::default(),
- &format!(
+ format!(
"argument for `--color` must be auto, \
always or never (instead was `{arg}`)"
),
@@ -1648,7 +1690,7 @@ pub fn parse_json(matches: &getopts::Matches) -> JsonConfig {
"future-incompat" => json_future_incompat = true,
s => early_error(
ErrorOutputType::default(),
- &format!("unknown `--json` option `{s}`"),
+ format!("unknown `--json` option `{s}`"),
),
}
}
@@ -1686,7 +1728,7 @@ pub fn parse_error_format(
Some(arg) => early_error(
ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)),
- &format!(
+ format!(
"argument for `--error-format` must be `human`, `json` or \
`short` (instead was `{arg}`)"
),
@@ -1720,7 +1762,7 @@ pub fn parse_crate_edition(matches: &getopts::Matches) -> Edition {
Some(arg) => Edition::from_str(&arg).unwrap_or_else(|_| {
early_error(
ErrorOutputType::default(),
- &format!(
+ format!(
"argument for `--edition` must be one of: \
{EDITION_NAME_LIST}. (instead was `{arg}`)"
),
@@ -1739,7 +1781,7 @@ pub fn parse_crate_edition(matches: &getopts::Matches) -> Edition {
} else {
format!("edition {edition} is unstable and only available with -Z unstable-options")
};
- early_error(ErrorOutputType::default(), &msg)
+ early_error(ErrorOutputType::default(), msg)
}
edition
@@ -1784,7 +1826,7 @@ fn parse_output_types(
let output_type = OutputType::from_shorthand(shorthand).unwrap_or_else(|| {
early_error(
error_format,
- &format!(
+ format!(
"unknown emission type: `{shorthand}` - expected one of: {display}",
display = OutputType::shorthands_display(),
),
@@ -1823,7 +1865,7 @@ fn should_override_cgus_and_disable_thinlto(
for ot in &incompatible {
early_warn(
error_format,
- &format!(
+ format!(
"`--emit={ot}` with `-o` incompatible with \
`-C codegen-units=N` for N > 1",
),
@@ -1865,7 +1907,7 @@ fn collect_print_requests(
error_format: ErrorOutputType,
) -> Vec<PrintRequest> {
let mut prints = Vec::<PrintRequest>::new();
- if cg.target_cpu.as_ref().map_or(false, |s| s == "help") {
+ if cg.target_cpu.as_ref().is_some_and(|s| s == "help") {
prints.push(PrintRequest::TargetCPUs);
cg.target_cpu = None;
};
@@ -1893,6 +1935,7 @@ fn collect_print_requests(
("all-target-specs-json", PrintRequest::AllTargetSpecs),
("link-args", PrintRequest::LinkArgs),
("split-debuginfo", PrintRequest::SplitDebuginfo),
+ ("deployment-target", PrintRequest::DeploymentTarget),
];
prints.extend(matches.opt_strs("print").into_iter().map(|req| {
@@ -1926,7 +1969,7 @@ fn collect_print_requests(
let prints = prints.join(", ");
early_error(
error_format,
- &format!("unknown print request `{req}`. Valid print requests are: {prints}"),
+ format!("unknown print request `{req}`. Valid print requests are: {prints}"),
);
}
}
@@ -1943,7 +1986,7 @@ pub fn parse_target_triple(
Some(target) if target.ends_with(".json") => {
let path = Path::new(&target);
TargetTriple::from_path(path).unwrap_or_else(|_| {
- early_error(error_format, &format!("target file {path:?} does not exist"))
+ early_error(error_format, format!("target file {path:?} does not exist"))
})
}
Some(target) => TargetTriple::TargetTriple(target),
@@ -1984,7 +2027,7 @@ fn parse_opt_level(
arg => {
early_error(
error_format,
- &format!(
+ format!(
"optimization level needs to be \
between 0-3, s or z (instead was `{arg}`)"
),
@@ -2015,7 +2058,7 @@ pub(crate) fn parse_assert_incr_state(
Some(s) if s.as_str() == "loaded" => Some(IncrementalStateAssertion::Loaded),
Some(s) if s.as_str() == "not-loaded" => Some(IncrementalStateAssertion::NotLoaded),
Some(s) => {
- early_error(error_format, &format!("unexpected incremental state assertion value: {s}"))
+ early_error(error_format, format!("unexpected incremental state assertion value: {s}"))
}
None => None,
}
@@ -2042,13 +2085,13 @@ fn parse_native_lib_kind(
} else {
", the `-Z unstable-options` flag must also be passed to use it"
};
- early_error(error_format, &format!("library kind `link-arg` is unstable{why}"))
+ early_error(error_format, format!("library kind `link-arg` is unstable{why}"))
}
NativeLibKind::LinkArg
}
_ => early_error(
error_format,
- &format!(
+ format!(
"unknown library kind `{kind}`, expected one of: static, dylib, framework, link-arg"
),
),
@@ -2083,16 +2126,13 @@ fn parse_native_lib_modifiers(
} else {
", the `-Z unstable-options` flag must also be passed to use it"
};
- early_error(
- error_format,
- &format!("linking modifier `{modifier}` is unstable{why}"),
- )
+ early_error(error_format, format!("linking modifier `{modifier}` is unstable{why}"))
}
};
let assign_modifier = |dst: &mut Option<bool>| {
if dst.is_some() {
let msg = format!("multiple `{modifier}` modifiers in a single `-l` option");
- early_error(error_format, &msg)
+ early_error(error_format, msg)
} else {
*dst = Some(value);
}
@@ -2129,7 +2169,7 @@ fn parse_native_lib_modifiers(
// string, like `modifiers = ""`.
_ => early_error(
error_format,
- &format!(
+ format!(
"unknown linking modifier `{modifier}`, expected one \
of: bundle, verbatim, whole-archive, as-needed"
),
@@ -2235,6 +2275,7 @@ pub fn parse_externs(
let mut is_private_dep = false;
let mut add_prelude = true;
let mut nounused_dep = false;
+ let mut force = false;
if let Some(opts) = options {
if !is_unstable_enabled {
early_error(
@@ -2257,7 +2298,8 @@ pub fn parse_externs(
}
}
"nounused" => nounused_dep = true,
- _ => early_error(error_format, &format!("unknown --extern option `{opt}`")),
+ "force" => force = true,
+ _ => early_error(error_format, format!("unknown --extern option `{opt}`")),
}
}
}
@@ -2267,6 +2309,8 @@ pub fn parse_externs(
entry.is_private_dep |= is_private_dep;
// likewise `nounused`
entry.nounused_dep |= nounused_dep;
+ // and `force`
+ entry.force |= force;
// If any flag is missing `noprelude`, then add to the prelude.
entry.add_prelude |= add_prelude;
}
@@ -2321,7 +2365,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
let unparsed_crate_types = matches.opt_strs("crate-type");
let crate_types = parse_crate_types_from_list(unparsed_crate_types)
- .unwrap_or_else(|e| early_error(error_format, &e));
+ .unwrap_or_else(|e| early_error(error_format, e));
let mut unstable_opts = UnstableOptions::build(matches, error_format);
let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format);
@@ -2549,7 +2593,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
};
let working_dir = std::env::current_dir().unwrap_or_else(|e| {
- early_error(error_format, &format!("Current directory is invalid: {e}"));
+ early_error(error_format, format!("Current directory is invalid: {e}"));
});
let remap = FilePathMapping::new(remap_path_prefix.clone());
@@ -2621,7 +2665,7 @@ fn parse_pretty(unstable_opts: &UnstableOptions, efmt: ErrorOutputType) -> Optio
"mir-cfg" => MirCFG,
name => early_error(
efmt,
- &format!(
+ format!(
"argument to `unpretty` must be one of `normal`, `identified`, \
`expanded`, `expanded,identified`, `expanded,hygiene`, \
`ast-tree`, `ast-tree,expanded`, `hir`, `hir,identified`, \
@@ -2699,7 +2743,7 @@ pub mod nightly_options {
if opt.name != "Z" && !has_z_unstable_option {
early_error(
ErrorOutputType::default(),
- &format!(
+ format!(
"the `-Z unstable-options` flag must also be passed to enable \
the flag `{}`",
opt.name
@@ -2712,11 +2756,10 @@ pub mod nightly_options {
match opt.stability {
OptionStability::Unstable => {
let msg = format!(
- "the option `{}` is only accepted on the \
- nightly compiler",
+ "the option `{}` is only accepted on the nightly compiler",
opt.name
);
- early_error(ErrorOutputType::default(), &msg);
+ early_error(ErrorOutputType::default(), msg);
}
OptionStability::Stable => {}
}