summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_session/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_session/src')
-rw-r--r--compiler/rustc_session/src/code_stats.rs4
-rw-r--r--compiler/rustc_session/src/config.rs797
-rw-r--r--compiler/rustc_session/src/cstore.rs19
-rw-r--r--compiler/rustc_session/src/errors.rs24
-rw-r--r--compiler/rustc_session/src/filesearch.rs6
-rw-r--r--compiler/rustc_session/src/lib.rs8
-rw-r--r--compiler/rustc_session/src/options.rs154
-rw-r--r--compiler/rustc_session/src/output.rs2
-rw-r--r--compiler/rustc_session/src/parse.rs53
-rw-r--r--compiler/rustc_session/src/search_paths.rs6
-rw-r--r--compiler/rustc_session/src/session.rs303
-rw-r--r--compiler/rustc_session/src/utils.rs11
-rw-r--r--compiler/rustc_session/src/version.rs2
13 files changed, 756 insertions, 633 deletions
diff --git a/compiler/rustc_session/src/code_stats.rs b/compiler/rustc_session/src/code_stats.rs
index e1eb58fec..2553df33c 100644
--- a/compiler/rustc_session/src/code_stats.rs
+++ b/compiler/rustc_session/src/code_stats.rs
@@ -132,6 +132,8 @@ impl CodeStats {
pub fn print_type_sizes(&self) {
let type_sizes = self.type_sizes.borrow();
+ // We will soon sort, so the initial order does not matter.
+ #[allow(rustc::potential_query_instability)]
let mut sorted: Vec<_> = type_sizes.iter().collect();
// Primary sort: large-to-small.
@@ -227,6 +229,8 @@ impl CodeStats {
}
pub fn print_vtable_sizes(&self, crate_name: Symbol) {
+ // We will soon sort, so the initial order does not matter.
+ #[allow(rustc::potential_query_instability)]
let mut infos =
std::mem::take(&mut *self.vtable_sizes.lock()).into_values().collect::<Vec<_>>();
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index f745bc390..0c21e4eb4 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -7,24 +7,20 @@ use crate::errors::FileWriteFail;
use crate::search_paths::SearchPath;
use crate::utils::{CanonicalizedPath, NativeLib, NativeLibKind};
use crate::{lint, HashStableContext};
-use crate::{EarlyErrorHandler, Session};
-
-use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
+use crate::{EarlyDiagCtxt, Session};
+use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
use rustc_data_structures::stable_hasher::{StableOrd, ToStableHashKey};
-use rustc_target::abi::Align;
-use rustc_target::spec::LinkSelfContainedComponents;
-use rustc_target::spec::{PanicStrategy, RelocModel, SanitizerSet, SplitDebuginfo};
-use rustc_target::spec::{Target, TargetTriple, TargetWarnings, TARGETS};
-
+use rustc_errors::emitter::HumanReadableErrorType;
+use rustc_errors::{ColorConfig, DiagCtxtFlags, DiagnosticArgValue, IntoDiagnosticArg};
use rustc_feature::UnstableFeatures;
use rustc_span::edition::{Edition, DEFAULT_EDITION, EDITION_NAME_LIST, LATEST_STABLE_EDITION};
use rustc_span::source_map::FilePathMapping;
use rustc_span::symbol::{sym, Symbol};
use rustc_span::{FileName, FileNameDisplayPreference, RealFileName, SourceFileHashAlgorithm};
-
-use rustc_errors::emitter::HumanReadableErrorType;
-use rustc_errors::{ColorConfig, DiagnosticArgValue, HandlerFlags, IntoDiagnosticArg};
-
+use rustc_target::abi::Align;
+use rustc_target::spec::LinkSelfContainedComponents;
+use rustc_target::spec::{PanicStrategy, RelocModel, SanitizerSet, SplitDebuginfo};
+use rustc_target::spec::{Target, TargetTriple, TargetWarnings, TARGETS};
use std::collections::btree_map::{
Iter as BTreeMapIter, Keys as BTreeMapKeysIter, Values as BTreeMapValuesIter,
};
@@ -555,12 +551,15 @@ impl Default for ErrorOutputType {
/// Parameter to control path trimming.
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub enum TrimmedDefPaths {
- /// `try_print_trimmed_def_path` never prints a trimmed path and never calls the expensive query
+ /// `try_print_trimmed_def_path` never prints a trimmed path and never calls the expensive
+ /// query.
#[default]
Never,
- /// `try_print_trimmed_def_path` calls the expensive query, the query doesn't call `delay_good_path_bug`
+ /// `try_print_trimmed_def_path` calls the expensive query, the query doesn't call
+ /// `good_path_delayed_bug`.
Always,
- /// `try_print_trimmed_def_path` calls the expensive query, the query calls `delay_good_path_bug`
+ /// `try_print_trimmed_def_path` calls the expensive query, the query calls
+ /// `good_path_delayed_bug`.
GoodPath,
}
@@ -580,7 +579,7 @@ pub enum ResolveDocLinks {
/// *Do not* switch `BTreeMap` out for an unsorted container type! That would break
/// dependency tracking for command-line arguments. Also only hash keys, since tracking
/// should only depend on the output types, not the paths they're written to.
-#[derive(Clone, Debug, Hash, HashStable_Generic)]
+#[derive(Clone, Debug, Hash, HashStable_Generic, Encodable, Decodable)]
pub struct OutputTypes(BTreeMap<OutputType, Option<OutFileName>>);
impl OutputTypes {
@@ -756,13 +755,14 @@ pub enum PrintKind {
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
-pub enum TraitSolver {
- /// Classic trait solver in `rustc_trait_selection::traits::select`
- Classic,
- /// Experimental trait solver in `rustc_trait_selection::solve`
- Next,
- /// Use the new trait solver during coherence
- NextCoherence,
+pub struct NextSolverConfig {
+ /// Whether the new trait solver should be enabled in coherence.
+ pub coherence: bool,
+ /// Whether the new trait solver should be enabled everywhere.
+ /// This is only `true` if `coherence` is also enabled.
+ pub globally: bool,
+ /// Whether to dump proof trees after computing a proof tree.
+ pub dump_tree: DumpSolverProofTree,
}
#[derive(Default, Debug, Copy, Clone, Hash, PartialEq, Eq)]
@@ -818,7 +818,7 @@ impl Input {
}
}
-#[derive(Clone, Hash, Debug, HashStable_Generic, PartialEq)]
+#[derive(Clone, Hash, Debug, HashStable_Generic, PartialEq, Encodable, Decodable)]
pub enum OutFileName {
Real(PathBuf),
Stdout,
@@ -857,7 +857,7 @@ impl OutFileName {
pub fn as_path(&self) -> &Path {
match *self {
OutFileName::Real(ref path) => path.as_ref(),
- OutFileName::Stdout => &Path::new("stdout"),
+ OutFileName::Stdout => Path::new("stdout"),
}
}
@@ -890,7 +890,7 @@ impl OutFileName {
}
}
-#[derive(Clone, Hash, Debug, HashStable_Generic)]
+#[derive(Clone, Hash, Debug, HashStable_Generic, Encodable, Decodable)]
pub struct OutputFilenames {
pub out_directory: PathBuf,
/// Crate name. Never contains '-'.
@@ -1115,6 +1115,7 @@ impl Default for Options {
pretty: None,
working_dir: RealFileName::LocalPath(std::env::current_dir().unwrap()),
color: ColorConfig::Auto,
+ logical_env: FxIndexMap::default(),
}
}
}
@@ -1154,8 +1155,8 @@ impl Options {
}
impl UnstableOptions {
- pub fn diagnostic_handler_flags(&self, can_emit_warnings: bool) -> HandlerFlags {
- HandlerFlags {
+ pub fn dcx_flags(&self, can_emit_warnings: bool) -> DiagCtxtFlags {
+ DiagCtxtFlags {
can_emit_warnings,
treat_err_as_bug: self.treat_err_as_bug,
dont_buffer_diagnostics: self.dont_buffer_diagnostics,
@@ -1247,46 +1248,85 @@ pub const fn default_lib_output() -> CrateType {
}
fn default_configuration(sess: &Session) -> Cfg {
- // NOTE: This should be kept in sync with `CheckCfg::fill_well_known` below.
- let end = &sess.target.endian;
- let arch = &sess.target.arch;
- let wordsz = sess.target.pointer_width.to_string();
- let os = &sess.target.os;
- let env = &sess.target.env;
- let abi = &sess.target.abi;
- let relocation_model = sess.target.relocation_model.desc_symbol();
- let vendor = &sess.target.vendor;
- let min_atomic_width = sess.target.min_atomic_width();
- let max_atomic_width = sess.target.max_atomic_width();
- let atomic_cas = sess.target.atomic_cas;
- let layout = sess.target.parse_data_layout().unwrap_or_else(|err| {
- sess.emit_fatal(err);
- });
-
let mut ret = Cfg::default();
- ret.reserve(7); // the minimum number of insertions
- // Target bindings.
- ret.insert((sym::target_os, Some(Symbol::intern(os))));
- for fam in sess.target.families.as_ref() {
- ret.insert((sym::target_family, Some(Symbol::intern(fam))));
- if fam == "windows" {
- ret.insert((sym::windows, None));
- } else if fam == "unix" {
- ret.insert((sym::unix, None));
- }
- }
- ret.insert((sym::target_arch, Some(Symbol::intern(arch))));
- ret.insert((sym::target_endian, Some(Symbol::intern(end.as_str()))));
- ret.insert((sym::target_pointer_width, Some(Symbol::intern(&wordsz))));
- ret.insert((sym::target_env, Some(Symbol::intern(env))));
- ret.insert((sym::target_abi, Some(Symbol::intern(abi))));
+
+ macro_rules! ins_none {
+ ($key:expr) => {
+ ret.insert(($key, None));
+ };
+ }
+ macro_rules! ins_str {
+ ($key:expr, $val_str:expr) => {
+ ret.insert(($key, Some(Symbol::intern($val_str))));
+ };
+ }
+ macro_rules! ins_sym {
+ ($key:expr, $val_sym:expr) => {
+ ret.insert(($key, Some($val_sym)));
+ };
+ }
+
+ // Symbols are inserted in alphabetical order as much as possible.
+ // The exceptions are where control flow forces things out of order.
+ //
+ // Run `rustc --print cfg` to see the configuration in practice.
+ //
+ // NOTE: These insertions should be kept in sync with
+ // `CheckCfg::fill_well_known` below.
+
+ if sess.opts.debug_assertions {
+ ins_none!(sym::debug_assertions);
+ }
+
+ if sess.overflow_checks() {
+ ins_none!(sym::overflow_checks);
+ }
+
+ ins_sym!(sym::panic, sess.panic_strategy().desc_symbol());
+
+ // JUSTIFICATION: before wrapper fn is available
+ #[allow(rustc::bad_opt_access)]
+ if sess.opts.crate_types.contains(&CrateType::ProcMacro) {
+ ins_none!(sym::proc_macro);
+ }
+
if sess.is_nightly_build() {
- ret.insert((sym::relocation_model, Some(relocation_model)));
+ ins_sym!(sym::relocation_model, sess.target.relocation_model.desc_symbol());
+ }
+
+ for mut s in sess.opts.unstable_opts.sanitizer {
+ // KASAN is still ASAN under the hood, so it uses the same attribute.
+ if s == SanitizerSet::KERNELADDRESS {
+ s = SanitizerSet::ADDRESS;
+ }
+ ins_str!(sym::sanitize, &s.to_string());
+ }
+
+ if sess.is_sanitizer_cfi_generalize_pointers_enabled() {
+ ins_none!(sym::sanitizer_cfi_generalize_pointers);
}
- ret.insert((sym::target_vendor, Some(Symbol::intern(vendor))));
- if sess.target.has_thread_local {
- ret.insert((sym::target_thread_local, None));
+ if sess.is_sanitizer_cfi_normalize_integers_enabled() {
+ ins_none!(sym::sanitizer_cfi_normalize_integers);
}
+
+ ins_str!(sym::target_abi, &sess.target.abi);
+ ins_str!(sym::target_arch, &sess.target.arch);
+ ins_str!(sym::target_endian, sess.target.endian.as_str());
+ ins_str!(sym::target_env, &sess.target.env);
+
+ for family in sess.target.families.as_ref() {
+ ins_str!(sym::target_family, family);
+ if family == "windows" {
+ ins_none!(sym::windows);
+ } else if family == "unix" {
+ ins_none!(sym::unix);
+ }
+ }
+
+ // `target_has_atomic*`
+ let layout = sess.target.parse_data_layout().unwrap_or_else(|err| {
+ sess.emit_fatal(err);
+ });
let mut has_atomic = false;
for (i, align) in [
(8, layout.i8_align.abi),
@@ -1295,64 +1335,46 @@ fn default_configuration(sess: &Session) -> Cfg {
(64, layout.i64_align.abi),
(128, layout.i128_align.abi),
] {
- if i >= min_atomic_width && i <= max_atomic_width {
- has_atomic = true;
- let mut insert_atomic = |s, align: Align| {
- ret.insert((sym::target_has_atomic_load_store, Some(Symbol::intern(s))));
- if atomic_cas {
- ret.insert((sym::target_has_atomic, Some(Symbol::intern(s))));
+ if i >= sess.target.min_atomic_width() && i <= sess.target.max_atomic_width() {
+ if !has_atomic {
+ has_atomic = true;
+ if sess.is_nightly_build() {
+ if sess.target.atomic_cas {
+ ins_none!(sym::target_has_atomic);
+ }
+ ins_none!(sym::target_has_atomic_load_store);
+ }
+ }
+ let mut insert_atomic = |sym, align: Align| {
+ if sess.target.atomic_cas {
+ ins_sym!(sym::target_has_atomic, sym);
}
if align.bits() == i {
- ret.insert((sym::target_has_atomic_equal_alignment, Some(Symbol::intern(s))));
+ ins_sym!(sym::target_has_atomic_equal_alignment, sym);
}
+ ins_sym!(sym::target_has_atomic_load_store, sym);
};
- let s = i.to_string();
- insert_atomic(&s, align);
- if s == wordsz {
- insert_atomic("ptr", layout.pointer_align.abi);
+ insert_atomic(sym::integer(i), align);
+ if sess.target.pointer_width as u64 == i {
+ insert_atomic(sym::ptr, layout.pointer_align.abi);
}
}
}
- if sess.is_nightly_build() && has_atomic {
- ret.insert((sym::target_has_atomic_load_store, None));
- if atomic_cas {
- ret.insert((sym::target_has_atomic, None));
- }
- }
- let panic_strategy = sess.panic_strategy();
- ret.insert((sym::panic, Some(panic_strategy.desc_symbol())));
+ ins_str!(sym::target_os, &sess.target.os);
+ ins_sym!(sym::target_pointer_width, sym::integer(sess.target.pointer_width));
- for mut s in sess.opts.unstable_opts.sanitizer {
- // KASAN should use the same attribute name as ASAN, as it's still ASAN
- // under the hood
- if s == SanitizerSet::KERNELADDRESS {
- s = SanitizerSet::ADDRESS;
- }
-
- let symbol = Symbol::intern(&s.to_string());
- ret.insert((sym::sanitize, Some(symbol)));
+ if sess.opts.unstable_opts.has_thread_local.unwrap_or(sess.target.has_thread_local) {
+ ins_none!(sym::target_thread_local);
}
- if sess.is_sanitizer_cfi_generalize_pointers_enabled() {
- ret.insert((sym::sanitizer_cfi_generalize_pointers, None));
- }
+ ins_str!(sym::target_vendor, &sess.target.vendor);
- if sess.is_sanitizer_cfi_normalize_integers_enabled() {
- ret.insert((sym::sanitizer_cfi_normalize_integers, None));
+ // If the user wants a test runner, then add the test cfg.
+ if sess.is_test_crate() {
+ ins_none!(sym::test);
}
- 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) {
- ret.insert((sym::proc_macro, None));
- }
ret
}
@@ -1423,88 +1445,73 @@ impl CheckCfg {
ExpectedValues::Some(values)
};
- // NOTE: This should be kept in sync with `default_configuration`
+ macro_rules! ins {
+ ($name:expr, $values:expr) => {
+ self.expecteds.entry($name).or_insert_with($values)
+ };
+ }
+
+ // Symbols are inserted in alphabetical order as much as possible.
+ // The exceptions are where control flow forces things out of order.
+ //
+ // NOTE: This should be kept in sync with `default_configuration`.
+ // Note that symbols inserted conditionally in `default_configuration`
+ // are inserted unconditionally here.
+ //
+ // When adding a new config here you should also update
+ // `tests/ui/check-cfg/well-known-values.rs`.
- let panic_values = &PanicStrategy::all();
+ ins!(sym::debug_assertions, no_values);
- let atomic_values = &[
- sym::ptr,
- sym::integer(8usize),
- sym::integer(16usize),
- sym::integer(32usize),
- sym::integer(64usize),
- sym::integer(128usize),
- ];
+ // These three are never set by rustc, but we set them anyway: they
+ // should not trigger a lint because `cargo doc`, `cargo test`, and
+ // `cargo miri run` (respectively) can set them.
+ ins!(sym::doc, no_values);
+ ins!(sym::doctest, no_values);
+ ins!(sym::miri, no_values);
+
+ ins!(sym::overflow_checks, no_values);
+
+ ins!(sym::panic, empty_values).extend(&PanicStrategy::all());
+
+ ins!(sym::proc_macro, no_values);
+
+ ins!(sym::relocation_model, empty_values).extend(RelocModel::all());
let sanitize_values = SanitizerSet::all()
.into_iter()
.map(|sanitizer| Symbol::intern(sanitizer.as_str().unwrap()));
+ ins!(sym::sanitize, empty_values).extend(sanitize_values);
- let relocation_model_values = RelocModel::all();
-
- // 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 [
- sym::doc,
- sym::miri,
- sym::unix,
- sym::test,
- sym::doctest,
- sym::windows,
- sym::proc_macro,
- sym::debug_assertions,
- sym::overflow_checks,
- sym::target_thread_local,
- ] {
- self.expecteds.entry(name).or_insert_with(no_values);
- }
-
- // Pre-defined values
- 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_insert_with(no_values)
- .extend(atomic_values);
- self.expecteds
- .entry(sym::target_has_atomic_equal_alignment)
- .or_insert_with(no_values)
- .extend(atomic_values);
- self.expecteds
- .entry(sym::relocation_model)
- .or_insert_with(empty_values)
- .extend(relocation_model_values);
-
- // Target specific values
+ ins!(sym::sanitizer_cfi_generalize_pointers, no_values);
+ ins!(sym::sanitizer_cfi_normalize_integers, no_values);
+
+ ins!(sym::target_feature, empty_values).extend(
+ rustc_target::target_features::all_known_features()
+ .map(|(f, _sb)| f)
+ .chain(rustc_target::target_features::RUSTC_SPECIFIC_FEATURES.iter().cloned())
+ .map(Symbol::intern),
+ );
+
+ // sym::target_*
{
const VALUES: [&Symbol; 8] = [
- &sym::target_os,
- &sym::target_family,
+ &sym::target_abi,
&sym::target_arch,
&sym::target_endian,
&sym::target_env,
- &sym::target_abi,
- &sym::target_vendor,
+ &sym::target_family,
+ &sym::target_os,
&sym::target_pointer_width,
+ &sym::target_vendor,
];
// Initialize (if not already initialized)
for &e in VALUES {
- let entry = self.expecteds.entry(e);
if !self.exhaustive_values {
- entry.or_insert(ExpectedValues::Any);
+ ins!(e, || ExpectedValues::Any);
} else {
- entry.or_insert_with(empty_values);
+ ins!(e, empty_values);
}
}
@@ -1512,14 +1519,14 @@ impl CheckCfg {
// 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_abi,
values_target_arch,
values_target_endian,
values_target_env,
- values_target_abi,
- values_target_vendor,
+ values_target_family,
+ values_target_os,
values_target_pointer_width,
+ values_target_vendor,
] = self
.expecteds
.get_many_mut(VALUES)
@@ -1530,36 +1537,54 @@ impl CheckCfg {
.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_abi.insert(Symbol::intern(&target.options.abi));
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_family.extend(
+ target.options.families.iter().map(|family| Symbol::intern(family)),
+ );
+ values_target_os.insert(Symbol::intern(&target.options.os));
values_target_pointer_width.insert(sym::integer(target.pointer_width));
+ values_target_vendor.insert(Symbol::intern(&target.options.vendor));
}
}
}
+
+ let atomic_values = &[
+ sym::ptr,
+ sym::integer(8usize),
+ sym::integer(16usize),
+ sym::integer(32usize),
+ sym::integer(64usize),
+ sym::integer(128usize),
+ ];
+ for sym in [
+ sym::target_has_atomic,
+ sym::target_has_atomic_equal_alignment,
+ sym::target_has_atomic_load_store,
+ ] {
+ ins!(sym, no_values).extend(atomic_values);
+ }
+
+ ins!(sym::target_thread_local, no_values);
+
+ ins!(sym::test, no_values);
+
+ ins!(sym::unix, no_values);
+ ins!(sym::windows, no_values);
}
}
pub fn build_configuration(sess: &Session, mut user_cfg: Cfg) -> Cfg {
// Combine the configuration requested by the session (command line) with
// some default and generated configuration items.
- let default_cfg = default_configuration(sess);
- // If the user wants a test runner, then add the test cfg.
- if sess.is_test_crate() {
- user_cfg.insert((sym::test, None));
- }
- user_cfg.extend(default_cfg.iter().cloned());
+ user_cfg.extend(default_configuration(sess));
user_cfg
}
pub(super) fn build_target_config(
- handler: &EarlyErrorHandler,
+ early_dcx: &EarlyDiagCtxt,
opts: &Options,
target_override: Option<Target>,
sysroot: &Path,
@@ -1569,17 +1594,17 @@ pub(super) fn build_target_config(
|t| Ok((t, TargetWarnings::empty())),
);
let (target, target_warnings) = target_result.unwrap_or_else(|e| {
- handler.early_error(format!(
+ early_dcx.early_error(format!(
"Error loading target specification: {e}. \
Run `rustc --print target-list` for a list of built-in targets"
))
});
for warning in target_warnings.warning_messages() {
- handler.early_warn(warning)
+ early_dcx.early_warn(warning)
}
if !matches!(target.pointer_width, 16 | 32 | 64) {
- handler.early_error(format!(
+ early_dcx.early_error(format!(
"target specification was invalid: unrecognized target-pointer-width {}",
target.pointer_width
))
@@ -1813,12 +1838,13 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
"Remap source names in all output (compiler messages and output files)",
"FROM=TO",
),
+ opt::multi("", "env", "Inject an environment variable", "VAR=VALUE"),
]);
opts
}
pub fn get_cmd_lint_options(
- handler: &EarlyErrorHandler,
+ early_dcx: &EarlyDiagCtxt,
matches: &getopts::Matches,
) -> (Vec<(String, lint::Level)>, bool, Option<lint::Level>) {
let mut lint_opts_with_position = vec![];
@@ -1843,14 +1869,14 @@ pub fn get_cmd_lint_options(
let lint_cap = matches.opt_str("cap-lints").map(|cap| {
lint::Level::from_str(&cap)
- .unwrap_or_else(|| handler.early_error(format!("unknown lint level: `{cap}`")))
+ .unwrap_or_else(|| early_dcx.early_error(format!("unknown lint level: `{cap}`")))
});
(lint_opts, describe_lints, lint_cap)
}
/// Parses the `--color` flag.
-pub fn parse_color(handler: &EarlyErrorHandler, matches: &getopts::Matches) -> ColorConfig {
+pub fn parse_color(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> ColorConfig {
match matches.opt_str("color").as_deref() {
Some("auto") => ColorConfig::Auto,
Some("always") => ColorConfig::Always,
@@ -1858,7 +1884,7 @@ pub fn parse_color(handler: &EarlyErrorHandler, matches: &getopts::Matches) -> C
None => ColorConfig::Auto,
- Some(arg) => handler.early_error(format!(
+ Some(arg) => early_dcx.early_error(format!(
"argument for `--color` must be auto, \
always or never (instead was `{arg}`)"
)),
@@ -1904,7 +1930,7 @@ impl JsonUnusedExterns {
///
/// The first value returned is how to render JSON diagnostics, and the second
/// is whether or not artifact notifications are enabled.
-pub fn parse_json(handler: &EarlyErrorHandler, matches: &getopts::Matches) -> JsonConfig {
+pub fn parse_json(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> JsonConfig {
let mut json_rendered: fn(ColorConfig) -> HumanReadableErrorType =
HumanReadableErrorType::Default;
let mut json_color = ColorConfig::Never;
@@ -1916,7 +1942,7 @@ pub fn parse_json(handler: &EarlyErrorHandler, matches: &getopts::Matches) -> Js
// won't actually be emitting any colors and anything colorized is
// embedded in a diagnostic message anyway.
if matches.opt_str("color").is_some() {
- handler.early_error("cannot specify the `--color` option with `--json`");
+ early_dcx.early_error("cannot specify the `--color` option with `--json`");
}
for sub_option in option.split(',') {
@@ -1927,7 +1953,7 @@ pub fn parse_json(handler: &EarlyErrorHandler, matches: &getopts::Matches) -> Js
"unused-externs" => json_unused_externs = JsonUnusedExterns::Loud,
"unused-externs-silent" => json_unused_externs = JsonUnusedExterns::Silent,
"future-incompat" => json_future_incompat = true,
- s => handler.early_error(format!("unknown `--json` option `{s}`")),
+ s => early_dcx.early_error(format!("unknown `--json` option `{s}`")),
}
}
}
@@ -1942,7 +1968,7 @@ pub fn parse_json(handler: &EarlyErrorHandler, matches: &getopts::Matches) -> Js
/// Parses the `--error-format` flag.
pub fn parse_error_format(
- handler: &mut EarlyErrorHandler,
+ early_dcx: &mut EarlyDiagCtxt,
matches: &getopts::Matches,
color: ColorConfig,
json_rendered: HumanReadableErrorType,
@@ -1964,10 +1990,10 @@ pub fn parse_error_format(
Some("short") => ErrorOutputType::HumanReadable(HumanReadableErrorType::Short(color)),
Some(arg) => {
- handler.abort_if_error_and_set_error_format(ErrorOutputType::HumanReadable(
+ early_dcx.abort_if_error_and_set_error_format(ErrorOutputType::HumanReadable(
HumanReadableErrorType::Default(color),
));
- handler.early_error(format!(
+ early_dcx.early_error(format!(
"argument for `--error-format` must be `human`, `json` or \
`short` (instead was `{arg}`)"
))
@@ -1984,7 +2010,7 @@ pub fn parse_error_format(
// `--error-format=json`. This means that `--json` is specified we
// should actually be emitting JSON blobs.
_ if !matches.opt_strs("json").is_empty() => {
- handler.early_error("using `--json` requires also using `--error-format=json`");
+ early_dcx.early_error("using `--json` requires also using `--error-format=json`");
}
_ => {}
@@ -1993,10 +2019,10 @@ pub fn parse_error_format(
error_format
}
-pub fn parse_crate_edition(handler: &EarlyErrorHandler, matches: &getopts::Matches) -> Edition {
+pub fn parse_crate_edition(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> Edition {
let edition = match matches.opt_str("edition") {
Some(arg) => Edition::from_str(&arg).unwrap_or_else(|_| {
- handler.early_error(format!(
+ early_dcx.early_error(format!(
"argument for `--edition` must be one of: \
{EDITION_NAME_LIST}. (instead was `{arg}`)"
))
@@ -2013,40 +2039,40 @@ pub fn parse_crate_edition(handler: &EarlyErrorHandler, matches: &getopts::Match
} else {
format!("edition {edition} is unstable and only available with -Z unstable-options")
};
- handler.early_error(msg)
+ early_dcx.early_error(msg)
}
edition
}
fn check_error_format_stability(
- handler: &mut EarlyErrorHandler,
+ early_dcx: &mut EarlyDiagCtxt,
unstable_opts: &UnstableOptions,
error_format: ErrorOutputType,
json_rendered: HumanReadableErrorType,
) {
if !unstable_opts.unstable_options {
if let ErrorOutputType::Json { pretty: true, json_rendered } = error_format {
- handler.abort_if_error_and_set_error_format(ErrorOutputType::Json {
+ early_dcx.abort_if_error_and_set_error_format(ErrorOutputType::Json {
pretty: false,
json_rendered,
});
- handler.early_error("`--error-format=pretty-json` is unstable");
+ early_dcx.early_error("`--error-format=pretty-json` is unstable");
}
if let ErrorOutputType::HumanReadable(HumanReadableErrorType::AnnotateSnippet(_)) =
error_format
{
- handler.abort_if_error_and_set_error_format(ErrorOutputType::Json {
+ early_dcx.abort_if_error_and_set_error_format(ErrorOutputType::Json {
pretty: false,
json_rendered,
});
- handler.early_error("`--error-format=human-annotate-rs` is unstable");
+ early_dcx.early_error("`--error-format=human-annotate-rs` is unstable");
}
}
}
fn parse_output_types(
- handler: &EarlyErrorHandler,
+ early_dcx: &EarlyDiagCtxt,
unstable_opts: &UnstableOptions,
matches: &getopts::Matches,
) -> OutputTypes {
@@ -2056,7 +2082,7 @@ fn parse_output_types(
for output_type in list.split(',') {
let (shorthand, path) = split_out_file_name(output_type);
let output_type = OutputType::from_shorthand(shorthand).unwrap_or_else(|| {
- handler.early_error(format!(
+ early_dcx.early_error(format!(
"unknown emission type: `{shorthand}` - expected one of: {display}",
display = OutputType::shorthands_display(),
))
@@ -2080,7 +2106,7 @@ fn split_out_file_name(arg: &str) -> (&str, Option<OutFileName>) {
}
fn should_override_cgus_and_disable_thinlto(
- handler: &EarlyErrorHandler,
+ early_dcx: &EarlyDiagCtxt,
output_types: &OutputTypes,
matches: &getopts::Matches,
mut codegen_units: Option<usize>,
@@ -2100,12 +2126,12 @@ fn should_override_cgus_and_disable_thinlto(
Some(n) if n > 1 => {
if matches.opt_present("o") {
for ot in &incompatible {
- handler.early_warn(format!(
+ early_dcx.early_warn(format!(
"`--emit={ot}` with `-o` incompatible with \
`-C codegen-units=N` for N > 1",
));
}
- handler.early_warn("resetting to default -C codegen-units=1");
+ early_dcx.early_warn("resetting to default -C codegen-units=1");
codegen_units = Some(1);
disable_local_thinlto = true;
}
@@ -2118,24 +2144,14 @@ fn should_override_cgus_and_disable_thinlto(
}
if codegen_units == Some(0) {
- handler.early_error("value for codegen units must be a positive non-zero integer");
+ early_dcx.early_error("value for codegen units must be a positive non-zero integer");
}
(disable_local_thinlto, codegen_units)
}
-fn check_thread_count(handler: &EarlyErrorHandler, unstable_opts: &UnstableOptions) {
- if unstable_opts.threads == 0 {
- handler.early_error("value for threads must be a positive non-zero integer");
- }
-
- if unstable_opts.threads > 1 && unstable_opts.fuel.is_some() {
- handler.early_error("optimization fuel is incompatible with multiple threads");
- }
-}
-
fn collect_print_requests(
- handler: &EarlyErrorHandler,
+ early_dcx: &EarlyDiagCtxt,
cg: &mut CodegenOptions,
unstable_opts: &mut UnstableOptions,
matches: &getopts::Matches,
@@ -2151,25 +2167,27 @@ fn collect_print_requests(
}
const PRINT_KINDS: &[(&str, PrintKind)] = &[
+ // tidy-alphabetical-start
+ ("all-target-specs-json", PrintKind::AllTargetSpecs),
+ ("calling-conventions", PrintKind::CallingConventions),
+ ("cfg", PrintKind::Cfg),
+ ("code-models", PrintKind::CodeModels),
("crate-name", PrintKind::CrateName),
+ ("deployment-target", PrintKind::DeploymentTarget),
("file-names", PrintKind::FileNames),
+ ("link-args", PrintKind::LinkArgs),
+ ("native-static-libs", PrintKind::NativeStaticLibs),
+ ("relocation-models", PrintKind::RelocationModels),
+ ("split-debuginfo", PrintKind::SplitDebuginfo),
+ ("stack-protector-strategies", PrintKind::StackProtectorStrategies),
("sysroot", PrintKind::Sysroot),
- ("target-libdir", PrintKind::TargetLibdir),
- ("cfg", PrintKind::Cfg),
- ("calling-conventions", PrintKind::CallingConventions),
- ("target-list", PrintKind::TargetList),
("target-cpus", PrintKind::TargetCPUs),
("target-features", PrintKind::TargetFeatures),
- ("relocation-models", PrintKind::RelocationModels),
- ("code-models", PrintKind::CodeModels),
- ("tls-models", PrintKind::TlsModels),
- ("native-static-libs", PrintKind::NativeStaticLibs),
- ("stack-protector-strategies", PrintKind::StackProtectorStrategies),
+ ("target-libdir", PrintKind::TargetLibdir),
+ ("target-list", PrintKind::TargetList),
("target-spec-json", PrintKind::TargetSpec),
- ("all-target-specs-json", PrintKind::AllTargetSpecs),
- ("link-args", PrintKind::LinkArgs),
- ("split-debuginfo", PrintKind::SplitDebuginfo),
- ("deployment-target", PrintKind::DeploymentTarget),
+ ("tls-models", PrintKind::TlsModels),
+ // tidy-alphabetical-end
];
// We disallow reusing the same path in multiple prints, such as `--print
@@ -2186,7 +2204,7 @@ fn collect_print_requests(
if unstable_opts.unstable_options {
PrintKind::TargetSpec
} else {
- handler.early_error(
+ early_dcx.early_error(
"the `-Z unstable-options` flag must also be passed to \
enable the target-spec-json print option",
);
@@ -2196,7 +2214,7 @@ fn collect_print_requests(
if unstable_opts.unstable_options {
PrintKind::AllTargetSpecs
} else {
- handler.early_error(
+ early_dcx.early_error(
"the `-Z unstable-options` flag must also be passed to \
enable the all-target-specs-json print option",
);
@@ -2207,7 +2225,7 @@ fn collect_print_requests(
let prints =
PRINT_KINDS.iter().map(|(name, _)| format!("`{name}`")).collect::<Vec<_>>();
let prints = prints.join(", ");
- handler.early_error(format!(
+ early_dcx.early_error(format!(
"unknown print request `{req}`. Valid print requests are: {prints}"
));
}
@@ -2216,7 +2234,7 @@ fn collect_print_requests(
let out = out.unwrap_or(OutFileName::Stdout);
if let OutFileName::Real(path) = &out {
if !printed_paths.insert(path.clone()) {
- handler.early_error(format!(
+ early_dcx.early_error(format!(
"cannot print multiple outputs to the same path: {}",
path.display(),
));
@@ -2229,15 +2247,12 @@ fn collect_print_requests(
prints
}
-pub fn parse_target_triple(
- handler: &EarlyErrorHandler,
- matches: &getopts::Matches,
-) -> TargetTriple {
+pub fn parse_target_triple(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> TargetTriple {
match matches.opt_str("target") {
Some(target) if target.ends_with(".json") => {
let path = Path::new(&target);
TargetTriple::from_path(path).unwrap_or_else(|_| {
- handler.early_error(format!("target file {path:?} does not exist"))
+ early_dcx.early_error(format!("target file {path:?} does not exist"))
})
}
Some(target) => TargetTriple::TargetTriple(target),
@@ -2246,7 +2261,7 @@ pub fn parse_target_triple(
}
fn parse_opt_level(
- handler: &EarlyErrorHandler,
+ early_dcx: &EarlyDiagCtxt,
matches: &getopts::Matches,
cg: &CodegenOptions,
) -> OptLevel {
@@ -2276,7 +2291,7 @@ fn parse_opt_level(
"s" => OptLevel::Size,
"z" => OptLevel::SizeMin,
arg => {
- handler.early_error(format!(
+ early_dcx.early_error(format!(
"optimization level needs to be \
between 0-3, s or z (instead was `{arg}`)"
));
@@ -2298,29 +2313,22 @@ fn select_debuginfo(matches: &getopts::Matches, cg: &CodegenOptions) -> DebugInf
if max_g > max_c { DebugInfo::Full } else { cg.debuginfo }
}
-fn select_debuginfo_compression(
- _handler: &EarlyErrorHandler,
- unstable_opts: &UnstableOptions,
-) -> DebugInfoCompression {
- unstable_opts.debuginfo_compression
-}
-
-pub(crate) fn parse_assert_incr_state(
- handler: &EarlyErrorHandler,
+fn parse_assert_incr_state(
+ early_dcx: &EarlyDiagCtxt,
opt_assertion: &Option<String>,
) -> Option<IncrementalStateAssertion> {
match opt_assertion {
Some(s) if s.as_str() == "loaded" => Some(IncrementalStateAssertion::Loaded),
Some(s) if s.as_str() == "not-loaded" => Some(IncrementalStateAssertion::NotLoaded),
Some(s) => {
- handler.early_error(format!("unexpected incremental state assertion value: {s}"))
+ early_dcx.early_error(format!("unexpected incremental state assertion value: {s}"))
}
None => None,
}
}
fn parse_native_lib_kind(
- handler: &EarlyErrorHandler,
+ early_dcx: &EarlyDiagCtxt,
matches: &getopts::Matches,
kind: &str,
) -> (NativeLibKind, Option<bool>) {
@@ -2340,22 +2348,22 @@ fn parse_native_lib_kind(
} else {
", the `-Z unstable-options` flag must also be passed to use it"
};
- handler.early_error(format!("library kind `link-arg` is unstable{why}"))
+ early_dcx.early_error(format!("library kind `link-arg` is unstable{why}"))
}
NativeLibKind::LinkArg
}
- _ => handler.early_error(format!(
+ _ => early_dcx.early_error(format!(
"unknown library kind `{kind}`, expected one of: static, dylib, framework, link-arg"
)),
};
match modifiers {
None => (kind, None),
- Some(modifiers) => parse_native_lib_modifiers(handler, kind, modifiers, matches),
+ Some(modifiers) => parse_native_lib_modifiers(early_dcx, kind, modifiers, matches),
}
}
fn parse_native_lib_modifiers(
- handler: &EarlyErrorHandler,
+ early_dcx: &EarlyDiagCtxt,
mut kind: NativeLibKind,
modifiers: &str,
matches: &getopts::Matches,
@@ -2364,7 +2372,7 @@ fn parse_native_lib_modifiers(
for modifier in modifiers.split(',') {
let (modifier, value) = match modifier.strip_prefix(['+', '-']) {
Some(m) => (m, modifier.starts_with('+')),
- None => handler.early_error(
+ None => early_dcx.early_error(
"invalid linking modifier syntax, expected '+' or '-' prefix \
before one of: bundle, verbatim, whole-archive, as-needed",
),
@@ -2377,20 +2385,20 @@ fn parse_native_lib_modifiers(
} else {
", the `-Z unstable-options` flag must also be passed to use it"
};
- handler.early_error(format!("linking modifier `{modifier}` is unstable{why}"))
+ early_dcx.early_error(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");
- handler.early_error(msg)
+ early_dcx.early_error(msg)
} else {
*dst = Some(value);
}
};
match (modifier, &mut kind) {
("bundle", NativeLibKind::Static { bundle, .. }) => assign_modifier(bundle),
- ("bundle", _) => handler.early_error(
+ ("bundle", _) => early_dcx.early_error(
"linking modifier `bundle` is only compatible with `static` linking kind",
),
@@ -2399,7 +2407,7 @@ fn parse_native_lib_modifiers(
("whole-archive", NativeLibKind::Static { whole_archive, .. }) => {
assign_modifier(whole_archive)
}
- ("whole-archive", _) => handler.early_error(
+ ("whole-archive", _) => early_dcx.early_error(
"linking modifier `whole-archive` is only compatible with `static` linking kind",
),
@@ -2408,14 +2416,14 @@ fn parse_native_lib_modifiers(
report_unstable_modifier();
assign_modifier(as_needed)
}
- ("as-needed", _) => handler.early_error(
+ ("as-needed", _) => early_dcx.early_error(
"linking modifier `as-needed` is only compatible with \
`dylib` and `framework` linking kinds",
),
// Note: this error also excludes the case with empty modifier
// string, like `modifiers = ""`.
- _ => handler.early_error(format!(
+ _ => early_dcx.early_error(format!(
"unknown linking modifier `{modifier}`, expected one \
of: bundle, verbatim, whole-archive, as-needed"
)),
@@ -2425,7 +2433,7 @@ fn parse_native_lib_modifiers(
(kind, verbatim)
}
-fn parse_libs(handler: &EarlyErrorHandler, matches: &getopts::Matches) -> Vec<NativeLib> {
+fn parse_libs(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> Vec<NativeLib> {
matches
.opt_strs("l")
.into_iter()
@@ -2439,7 +2447,7 @@ fn parse_libs(handler: &EarlyErrorHandler, matches: &getopts::Matches) -> Vec<Na
let (name, kind, verbatim) = match s.split_once('=') {
None => (s, NativeLibKind::Unspecified, None),
Some((kind, name)) => {
- let (kind, verbatim) = parse_native_lib_kind(handler, matches, kind);
+ let (kind, verbatim) = parse_native_lib_kind(early_dcx, matches, kind);
(name.to_string(), kind, verbatim)
}
};
@@ -2449,7 +2457,7 @@ fn parse_libs(handler: &EarlyErrorHandler, matches: &getopts::Matches) -> Vec<Na
Some((name, new_name)) => (name.to_string(), Some(new_name.to_owned())),
};
if name.is_empty() {
- handler.early_error("library name must not be empty");
+ early_dcx.early_error("library name must not be empty");
}
NativeLib { name, new_name, kind, verbatim }
})
@@ -2457,10 +2465,21 @@ fn parse_libs(handler: &EarlyErrorHandler, matches: &getopts::Matches) -> Vec<Na
}
pub fn parse_externs(
- handler: &EarlyErrorHandler,
+ early_dcx: &EarlyDiagCtxt,
matches: &getopts::Matches,
unstable_opts: &UnstableOptions,
) -> Externs {
+ fn is_ascii_ident(string: &str) -> bool {
+ let mut chars = string.chars();
+ if let Some(start) = chars.next()
+ && (start.is_ascii_alphabetic() || start == '_')
+ {
+ chars.all(|char| char.is_ascii_alphanumeric() || char == '_')
+ } else {
+ false
+ }
+ }
+
let is_unstable_enabled = unstable_opts.unstable_options;
let mut externs: BTreeMap<String, ExternEntry> = BTreeMap::new();
for arg in matches.opt_strs("extern") {
@@ -2473,12 +2492,12 @@ pub fn parse_externs(
Some((opts, name)) => (Some(opts), name.to_string()),
};
- if !crate::utils::is_ascii_ident(&name) {
- let mut error = handler.early_struct_error(format!(
+ if !is_ascii_ident(&name) {
+ let mut error = early_dcx.early_struct_error(format!(
"crate name `{name}` passed to `--extern` is not a valid ASCII identifier"
));
let adjusted_name = name.replace('-', "_");
- if crate::utils::is_ascii_ident(&adjusted_name) {
+ if is_ascii_ident(&adjusted_name) {
error.help(format!(
"consider replacing the dashes with underscores: `{adjusted_name}`"
));
@@ -2536,7 +2555,7 @@ pub fn parse_externs(
let mut force = false;
if let Some(opts) = options {
if !is_unstable_enabled {
- handler.early_error(
+ early_dcx.early_error(
"the `-Z unstable-options` flag must also be passed to \
enable `--extern` options",
);
@@ -2548,14 +2567,14 @@ pub fn parse_externs(
if let ExternLocation::ExactPaths(_) = &entry.location {
add_prelude = false;
} else {
- handler.early_error(
+ early_dcx.early_error(
"the `noprelude` --extern option requires a file path",
);
}
}
"nounused" => nounused_dep = true,
"force" => force = true,
- _ => handler.early_error(format!("unknown --extern option `{opt}`")),
+ _ => early_dcx.early_error(format!("unknown --extern option `{opt}`")),
}
}
}
@@ -2574,7 +2593,7 @@ pub fn parse_externs(
}
fn parse_remap_path_prefix(
- handler: &EarlyErrorHandler,
+ early_dcx: &EarlyDiagCtxt,
matches: &getopts::Matches,
unstable_opts: &UnstableOptions,
) -> Vec<(PathBuf, PathBuf)> {
@@ -2582,7 +2601,9 @@ fn parse_remap_path_prefix(
.opt_strs("remap-path-prefix")
.into_iter()
.map(|remap| match remap.rsplit_once('=') {
- None => handler.early_error("--remap-path-prefix must contain '=' between FROM and TO"),
+ None => {
+ early_dcx.early_error("--remap-path-prefix must contain '=' between FROM and TO")
+ }
Some((from, to)) => (PathBuf::from(from), PathBuf::from(to)),
})
.collect();
@@ -2596,79 +2617,107 @@ fn parse_remap_path_prefix(
mapping
}
+fn parse_logical_env(
+ early_dcx: &mut EarlyDiagCtxt,
+ matches: &getopts::Matches,
+) -> FxIndexMap<String, String> {
+ let mut vars = FxIndexMap::default();
+
+ for arg in matches.opt_strs("env") {
+ if let Some((name, val)) = arg.split_once('=') {
+ vars.insert(name.to_string(), val.to_string());
+ } else {
+ early_dcx.early_error(format!("`--env`: specify value for variable `{arg}`"));
+ }
+ }
+
+ vars
+}
+
// JUSTIFICATION: before wrapper fn is available
#[allow(rustc::bad_opt_access)]
-pub fn build_session_options(
- handler: &mut EarlyErrorHandler,
- matches: &getopts::Matches,
-) -> Options {
- let color = parse_color(handler, matches);
+pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::Matches) -> Options {
+ let color = parse_color(early_dcx, matches);
- let edition = parse_crate_edition(handler, matches);
+ let edition = parse_crate_edition(early_dcx, matches);
let JsonConfig {
json_rendered,
json_artifact_notifications,
json_unused_externs,
json_future_incompat,
- } = parse_json(handler, matches);
+ } = parse_json(early_dcx, matches);
- let error_format = parse_error_format(handler, matches, color, json_rendered);
+ let error_format = parse_error_format(early_dcx, matches, color, json_rendered);
- handler.abort_if_error_and_set_error_format(error_format);
+ early_dcx.abort_if_error_and_set_error_format(error_format);
let diagnostic_width = matches.opt_get("diagnostic-width").unwrap_or_else(|_| {
- handler.early_error("`--diagnostic-width` must be an positive integer");
+ early_dcx.early_error("`--diagnostic-width` must be an positive integer");
});
let unparsed_crate_types = matches.opt_strs("crate-type");
let crate_types = parse_crate_types_from_list(unparsed_crate_types)
- .unwrap_or_else(|e| handler.early_error(e));
+ .unwrap_or_else(|e| early_dcx.early_error(e));
- let mut unstable_opts = UnstableOptions::build(handler, matches);
- let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(handler, matches);
+ let mut unstable_opts = UnstableOptions::build(early_dcx, matches);
+ let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(early_dcx, matches);
- check_error_format_stability(handler, &unstable_opts, error_format, json_rendered);
+ check_error_format_stability(early_dcx, &unstable_opts, error_format, json_rendered);
if !unstable_opts.unstable_options && json_unused_externs.is_enabled() {
- handler.early_error(
+ early_dcx.early_error(
"the `-Z unstable-options` flag must also be passed to enable \
the flag `--json=unused-externs`",
);
}
- let output_types = parse_output_types(handler, &unstable_opts, matches);
+ let output_types = parse_output_types(early_dcx, &unstable_opts, matches);
- let mut cg = CodegenOptions::build(handler, matches);
- let (disable_local_thinlto, mut codegen_units) =
- should_override_cgus_and_disable_thinlto(handler, &output_types, matches, cg.codegen_units);
+ let mut cg = CodegenOptions::build(early_dcx, matches);
+ let (disable_local_thinlto, mut codegen_units) = should_override_cgus_and_disable_thinlto(
+ early_dcx,
+ &output_types,
+ matches,
+ cg.codegen_units,
+ );
- check_thread_count(handler, &unstable_opts);
+ if unstable_opts.threads == 0 {
+ early_dcx.early_error("value for threads must be a positive non-zero integer");
+ }
+
+ let fuel = unstable_opts.fuel.is_some() || unstable_opts.print_fuel.is_some();
+ if fuel && unstable_opts.threads > 1 {
+ early_dcx.early_error("optimization fuel is incompatible with multiple threads");
+ }
+ if fuel && cg.incremental.is_some() {
+ early_dcx.early_error("optimization fuel is incompatible with incremental compilation");
+ }
let incremental = cg.incremental.as_ref().map(PathBuf::from);
- let assert_incr_state = parse_assert_incr_state(handler, &unstable_opts.assert_incr_state);
+ let assert_incr_state = parse_assert_incr_state(early_dcx, &unstable_opts.assert_incr_state);
if unstable_opts.profile && incremental.is_some() {
- handler.early_error("can't instrument with gcov profiling when compiling incrementally");
+ early_dcx.early_error("can't instrument with gcov profiling when compiling incrementally");
}
if unstable_opts.profile {
match codegen_units {
Some(1) => {}
None => codegen_units = Some(1),
- Some(_) => handler
+ Some(_) => early_dcx
.early_error("can't instrument with gcov profiling with multiple codegen units"),
}
}
if cg.profile_generate.enabled() && cg.profile_use.is_some() {
- handler.early_error("options `-C profile-generate` and `-C profile-use` are exclusive");
+ early_dcx.early_error("options `-C profile-generate` and `-C profile-use` are exclusive");
}
if unstable_opts.profile_sample_use.is_some()
&& (cg.profile_generate.enabled() || cg.profile_use.is_some())
{
- handler.early_error(
+ early_dcx.early_error(
"option `-Z profile-sample-use` cannot be used with `-C profile-generate` or `-C profile-use`",
);
}
@@ -2681,7 +2730,7 @@ pub fn build_session_options(
// Unstable values:
Some(SymbolManglingVersion::Legacy) => {
if !unstable_opts.unstable_options {
- handler.early_error(
+ early_dcx.early_error(
"`-C symbol-mangling-version=legacy` requires `-Z unstable-options`",
);
}
@@ -2698,7 +2747,7 @@ pub fn build_session_options(
| InstrumentCoverage::ExceptUnusedFunctions
| InstrumentCoverage::ExceptUnusedGenerics => {
if !unstable_opts.unstable_options {
- handler.early_error(
+ early_dcx.early_error(
"`-C instrument-coverage=branch` and `-C instrument-coverage=except-*` \
require `-Z unstable-options`",
);
@@ -2708,7 +2757,7 @@ pub fn build_session_options(
if cg.instrument_coverage != InstrumentCoverage::Off {
if cg.profile_generate.enabled() || cg.profile_use.is_some() {
- handler.early_error(
+ early_dcx.early_error(
"option `-C instrument-coverage` is not compatible with either `-C profile-use` \
or `-C profile-generate`",
);
@@ -2721,7 +2770,7 @@ pub fn build_session_options(
match cg.symbol_mangling_version {
None => cg.symbol_mangling_version = Some(SymbolManglingVersion::V0),
Some(SymbolManglingVersion::Legacy) => {
- handler.early_warn(
+ early_dcx.early_warn(
"-C instrument-coverage requires symbol mangling version `v0`, \
but `-C symbol-mangling-version=legacy` was specified",
);
@@ -2738,7 +2787,7 @@ pub fn build_session_options(
match cg.lto {
LtoCli::No | LtoCli::Unspecified => {}
LtoCli::Yes | LtoCli::NoParam | LtoCli::Thin | LtoCli::Fat => {
- handler.early_error("options `-C embed-bitcode=no` and `-C lto` are incompatible")
+ early_dcx.early_error("options `-C embed-bitcode=no` and `-C lto` are incompatible")
}
}
}
@@ -2750,7 +2799,7 @@ pub fn build_session_options(
let uses_unstable_self_contained_option =
cg.link_self_contained.are_unstable_variants_set();
if uses_unstable_self_contained_option {
- handler.early_error(
+ early_dcx.early_error(
"only `-C link-self-contained` values `y`/`yes`/`on`/`n`/`no`/`off` are stable, \
the `-Z unstable-options` flag must also be passed to use the unstable values",
);
@@ -2758,7 +2807,7 @@ pub fn build_session_options(
if let Some(flavor) = cg.linker_flavor {
if flavor.is_unstable() {
- handler.early_error(format!(
+ early_dcx.early_error(format!(
"the linker flavor `{}` is unstable, the `-Z unstable-options` \
flag must also be passed to use the unstable values",
flavor.desc()
@@ -2775,56 +2824,58 @@ pub fn build_session_options(
.map(|c| c.as_str().unwrap())
.intersperse(", ")
.collect();
- handler.early_error(format!(
+ early_dcx.early_error(format!(
"some `-C link-self-contained` components were both enabled and disabled: {names}"
));
}
- let prints = collect_print_requests(handler, &mut cg, &mut unstable_opts, matches);
+ let prints = collect_print_requests(early_dcx, &mut cg, &mut unstable_opts, matches);
let cg = cg;
let sysroot_opt = matches.opt_str("sysroot").map(|m| PathBuf::from(&m));
- let target_triple = parse_target_triple(handler, matches);
- let opt_level = parse_opt_level(handler, matches, &cg);
+ let target_triple = parse_target_triple(early_dcx, matches);
+ let opt_level = parse_opt_level(early_dcx, matches, &cg);
// The `-g` and `-C debuginfo` flags specify the same setting, so we want to be able
// to use them interchangeably. See the note above (regarding `-O` and `-C opt-level`)
// for more details.
let debug_assertions = cg.debug_assertions.unwrap_or(opt_level == OptLevel::No);
let debuginfo = select_debuginfo(matches, &cg);
- let debuginfo_compression: DebugInfoCompression =
- select_debuginfo_compression(handler, &unstable_opts);
+ let debuginfo_compression = unstable_opts.debuginfo_compression;
let mut search_paths = vec![];
for s in &matches.opt_strs("L") {
- search_paths.push(SearchPath::from_cli_opt(handler, s));
+ search_paths.push(SearchPath::from_cli_opt(early_dcx, s));
}
- let libs = parse_libs(handler, matches);
+ let libs = parse_libs(early_dcx, matches);
let test = matches.opt_present("test");
if !cg.remark.is_empty() && debuginfo == DebugInfo::None {
- handler.early_warn("-C remark requires \"-C debuginfo=n\" to show source locations");
+ early_dcx.early_warn("-C remark requires \"-C debuginfo=n\" to show source locations");
}
if cg.remark.is_empty() && unstable_opts.remark_dir.is_some() {
- handler.early_warn("using -Z remark-dir without enabling remarks using e.g. -C remark=all");
+ early_dcx
+ .early_warn("using -Z remark-dir without enabling remarks using e.g. -C remark=all");
}
- let externs = parse_externs(handler, matches, &unstable_opts);
+ let externs = parse_externs(early_dcx, matches, &unstable_opts);
let crate_name = matches.opt_str("crate-name");
- let remap_path_prefix = parse_remap_path_prefix(handler, matches, &unstable_opts);
+ let remap_path_prefix = parse_remap_path_prefix(early_dcx, matches, &unstable_opts);
- let pretty = parse_pretty(handler, &unstable_opts);
+ let pretty = parse_pretty(early_dcx, &unstable_opts);
// query-dep-graph is required if dump-dep-graph is given #106736
if unstable_opts.dump_dep_graph && !unstable_opts.query_dep_graph {
- handler.early_error("can't dump dependency graph without `-Z query-dep-graph`");
+ early_dcx.early_error("can't dump dependency graph without `-Z query-dep-graph`");
}
+ let logical_env = parse_logical_env(early_dcx, matches);
+
// Try to find a directory containing the Rust `src`, for more details see
// the doc comment on the `real_rust_source_base_dir` field.
let tmp_buf;
@@ -2854,7 +2905,7 @@ pub fn build_session_options(
};
let working_dir = std::env::current_dir().unwrap_or_else(|e| {
- handler.early_error(format!("Current directory is invalid: {e}"));
+ early_dcx.early_error(format!("Current directory is invalid: {e}"));
});
let remap = file_path_mapping(remap_path_prefix.clone(), &unstable_opts);
@@ -2905,10 +2956,11 @@ pub fn build_session_options(
pretty,
working_dir,
color,
+ logical_env,
}
}
-fn parse_pretty(handler: &EarlyErrorHandler, unstable_opts: &UnstableOptions) -> Option<PpMode> {
+fn parse_pretty(early_dcx: &EarlyDiagCtxt, unstable_opts: &UnstableOptions) -> Option<PpMode> {
use PpMode::*;
let first = match unstable_opts.unpretty.as_deref()? {
@@ -2926,12 +2978,13 @@ fn parse_pretty(handler: &EarlyErrorHandler, unstable_opts: &UnstableOptions) ->
"thir-tree" => ThirTree,
"thir-flat" => ThirFlat,
"mir" => Mir,
+ "stable-mir" => StableMir,
"mir-cfg" => MirCFG,
- name => handler.early_error(format!(
+ name => early_dcx.early_error(format!(
"argument to `unpretty` must be one of `normal`, `identified`, \
`expanded`, `expanded,identified`, `expanded,hygiene`, \
`ast-tree`, `ast-tree,expanded`, `hir`, `hir,identified`, \
- `hir,typed`, `hir-tree`, `thir-tree`, `thir-flat`, `mir` or \
+ `hir,typed`, `hir-tree`, `thir-tree`, `thir-flat`, `mir`, `stable-mir`, or \
`mir-cfg`; got {name}"
)),
};
@@ -2974,7 +3027,7 @@ pub fn parse_crate_types_from_list(list_list: Vec<String>) -> Result<Vec<CrateTy
pub mod nightly_options {
use super::{OptionStability, RustcOptGroup};
- use crate::EarlyErrorHandler;
+ use crate::EarlyDiagCtxt;
use rustc_feature::UnstableFeatures;
pub fn is_unstable_enabled(matches: &getopts::Matches) -> bool {
@@ -2991,7 +3044,7 @@ pub mod nightly_options {
}
pub fn check_nightly_options(
- handler: &EarlyErrorHandler,
+ early_dcx: &EarlyDiagCtxt,
matches: &getopts::Matches,
flags: &[RustcOptGroup],
) {
@@ -3007,7 +3060,7 @@ pub mod nightly_options {
continue;
}
if opt.name != "Z" && !has_z_unstable_option {
- handler.early_error(format!(
+ early_dcx.early_error(format!(
"the `-Z unstable-options` flag must also be passed to enable \
the flag `{}`",
opt.name
@@ -3023,17 +3076,17 @@ pub mod nightly_options {
"the option `{}` is only accepted on the nightly compiler",
opt.name
);
- let _ = handler.early_error_no_abort(msg);
+ let _ = early_dcx.early_error_no_abort(msg);
}
OptionStability::Stable => {}
}
}
if nightly_options_on_stable > 0 {
- handler
+ early_dcx
.early_help("consider switching to a nightly toolchain: `rustup default nightly`");
- handler.early_note("selecting a toolchain with `+toolchain` arguments require a rustup proxy; see <https://rust-lang.github.io/rustup/concepts/index.html>");
- handler.early_note("for more information about Rust's stability policy, see <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html#unstable-features>");
- handler.early_error(format!(
+ early_dcx.early_note("selecting a toolchain with `+toolchain` arguments require a rustup proxy; see <https://rust-lang.github.io/rustup/concepts/index.html>");
+ early_dcx.early_note("for more information about Rust's stability policy, see <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html#unstable-features>");
+ early_dcx.early_error(format!(
"{} nightly option{} were parsed",
nightly_options_on_stable,
if nightly_options_on_stable > 1 { "s" } else { "" }
@@ -3106,6 +3159,8 @@ pub enum PpMode {
Mir,
/// `-Zunpretty=mir-cfg`
MirCFG,
+ /// `-Zunpretty=stable-mir`
+ StableMir,
}
impl PpMode {
@@ -3122,7 +3177,8 @@ impl PpMode {
| ThirTree
| ThirFlat
| Mir
- | MirCFG => true,
+ | MirCFG
+ | StableMir => true,
}
}
pub fn needs_hir(&self) -> bool {
@@ -3130,16 +3186,22 @@ impl PpMode {
match *self {
Source(_) | AstTree | AstTreeExpanded => false,
- Hir(_) | HirTree | ThirTree | ThirFlat | Mir | MirCFG => true,
+ Hir(_) | HirTree | ThirTree | ThirFlat | Mir | MirCFG | StableMir => true,
}
}
pub fn needs_analysis(&self) -> bool {
use PpMode::*;
- matches!(*self, Hir(PpHirMode::Typed) | Mir | MirCFG | ThirTree | ThirFlat)
+ matches!(*self, Hir(PpHirMode::Typed) | Mir | StableMir | MirCFG | ThirTree | ThirFlat)
}
}
+#[derive(Clone, Hash, PartialEq, Eq, Debug)]
+pub enum WasiExecModel {
+ Command,
+ Reactor,
+}
+
/// Command-line arguments passed to the compiler have to be incorporated with
/// the dependency tracking system for incremental compilation. This module
/// provides some utilities to make this more convenient.
@@ -3161,14 +3223,15 @@ impl PpMode {
pub(crate) mod dep_tracking {
use super::{
BranchProtection, CFGuard, CFProtection, CrateType, DebugInfo, DebugInfoCompression,
- ErrorOutputType, InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto,
- LocationDetail, LtoCli, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes,
- Polonius, RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm,
- SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion, TraitSolver, TrimmedDefPaths,
+ ErrorOutputType, FunctionReturn, InliningThreshold, InstrumentCoverage, InstrumentXRay,
+ LinkerPluginLto, LocationDetail, LtoCli, NextSolverConfig, OomStrategy, OptLevel,
+ OutFileName, OutputType, OutputTypes, Polonius, RemapPathScopeComponents, ResolveDocLinks,
+ SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion,
+ TrimmedDefPaths, WasiExecModel,
};
use crate::lint;
- use crate::options::WasiExecModel;
use crate::utils::NativeLib;
+ use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::stable_hasher::Hash64;
use rustc_errors::LanguageIdentifier;
use rustc_feature::UnstableFeatures;
@@ -3178,9 +3241,8 @@ pub(crate) mod dep_tracking {
use rustc_target::spec::{
RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TargetTriple, TlsModel,
};
- use std::collections::hash_map::DefaultHasher;
use std::collections::BTreeMap;
- use std::hash::Hash;
+ use std::hash::{DefaultHasher, Hash};
use std::num::NonZeroUsize;
use std::path::PathBuf;
@@ -3268,9 +3330,10 @@ pub(crate) mod dep_tracking {
BranchProtection,
OomStrategy,
LanguageIdentifier,
- TraitSolver,
+ NextSolverConfig,
Polonius,
InliningThreshold,
+ FunctionReturn,
);
impl<T1, T2> DepTrackingHash for (T1, T2)
@@ -3327,6 +3390,21 @@ pub(crate) mod dep_tracking {
}
}
+ impl<T: DepTrackingHash, V: DepTrackingHash> DepTrackingHash for FxIndexMap<T, V> {
+ fn hash(
+ &self,
+ hasher: &mut DefaultHasher,
+ error_format: ErrorOutputType,
+ for_crate_hash: bool,
+ ) {
+ Hash::hash(&self.len(), hasher);
+ for (key, value) in self.iter() {
+ DepTrackingHash::hash(key, hasher, error_format, for_crate_hash);
+ DepTrackingHash::hash(value, hasher, error_format, for_crate_hash);
+ }
+ }
+ }
+
impl DepTrackingHash for OutputTypes {
fn hash(
&self,
@@ -3449,3 +3527,14 @@ impl Default for InliningThreshold {
Self::Sometimes(100)
}
}
+
+/// The different settings that the `-Zfunction-return` flag can have.
+#[derive(Clone, Copy, PartialEq, Hash, Debug, Default)]
+pub enum FunctionReturn {
+ /// Keep the function return unmodified.
+ #[default]
+ Keep,
+
+ /// Replace returns with jumps to thunk, without emitting the thunk.
+ ThunkExtern,
+}
diff --git a/compiler/rustc_session/src/cstore.rs b/compiler/rustc_session/src/cstore.rs
index d816842b0..a0f5eb59b 100644
--- a/compiler/rustc_session/src/cstore.rs
+++ b/compiler/rustc_session/src/cstore.rs
@@ -6,7 +6,6 @@ use crate::search_paths::PathKind;
use crate::utils::NativeLibKind;
use crate::Session;
use rustc_ast as ast;
-use rustc_data_structures::owned_slice::OwnedSlice;
use rustc_data_structures::sync::{self, AppendOnlyIndexVec, FreezeLock};
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, StableCrateId, LOCAL_CRATE};
use rustc_hir::definitions::{DefKey, DefPath, DefPathHash, Definitions};
@@ -14,10 +13,9 @@ use rustc_span::hygiene::{ExpnHash, ExpnId};
use rustc_span::symbol::Symbol;
use rustc_span::Span;
use rustc_target::spec::abi::Abi;
-use rustc_target::spec::Target;
use std::any::Any;
-use std::path::{Path, PathBuf};
+use std::path::PathBuf;
// lonely orphan structs and enums looking for a better home
@@ -197,21 +195,6 @@ pub enum ExternCrateSource {
Path,
}
-/// The backend's way to give the crate store access to the metadata in a library.
-/// Note that it returns the raw metadata bytes stored in the library file, whether
-/// it is compressed, uncompressed, some weird mix, etc.
-/// rmeta files are backend independent and not handled here.
-///
-/// At the time of this writing, there is only one backend and one way to store
-/// metadata in library -- this trait just serves to decouple rustc_metadata from
-/// the archive reader, which depends on LLVM.
-pub trait MetadataLoader: std::fmt::Debug {
- fn get_rlib_metadata(&self, target: &Target, filename: &Path) -> Result<OwnedSlice, String>;
- fn get_dylib_metadata(&self, target: &Target, filename: &Path) -> Result<OwnedSlice, String>;
-}
-
-pub type MetadataLoaderDyn = dyn MetadataLoader + Send + Sync + sync::DynSend + sync::DynSync;
-
/// A store of Rust crates, through which their metadata can be accessed.
///
/// Note that this trait should probably not be expanding today. All new
diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs
index 31094e0d2..c3360815a 100644
--- a/compiler/rustc_session/src/errors.rs
+++ b/compiler/rustc_session/src/errors.rs
@@ -3,7 +3,7 @@ use std::num::NonZeroU32;
use crate::parse::ParseSess;
use rustc_ast::token;
use rustc_ast::util::literal::LitError;
-use rustc_errors::{error_code, DiagnosticMessage, EmissionGuarantee, IntoDiagnostic, MultiSpan};
+use rustc_errors::{error_code, DiagnosticMessage, ErrorGuaranteed, IntoDiagnostic, MultiSpan};
use rustc_macros::Diagnostic;
use rustc_span::{BytePos, Span, Symbol};
use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple};
@@ -13,13 +13,13 @@ pub struct FeatureGateError {
pub explain: DiagnosticMessage,
}
-impl<'a, T: EmissionGuarantee> IntoDiagnostic<'a, T> for FeatureGateError {
+impl<'a> IntoDiagnostic<'a> for FeatureGateError {
#[track_caller]
fn into_diagnostic(
self,
- handler: &'a rustc_errors::Handler,
- ) -> rustc_errors::DiagnosticBuilder<'a, T> {
- let mut diag = handler.struct_diagnostic(self.explain);
+ dcx: &'a rustc_errors::DiagCtxt,
+ ) -> rustc_errors::DiagnosticBuilder<'a, ErrorGuaranteed> {
+ let mut diag = dcx.struct_err(self.explain);
diag.set_span(self.span);
diag.code(error_code!(E0658));
diag
@@ -436,3 +436,17 @@ pub struct IncompatibleLinkerFlavor {
pub flavor: &'static str,
pub compatible_list: String,
}
+
+#[derive(Diagnostic)]
+#[diag(session_function_return_requires_x86_or_x86_64)]
+pub(crate) struct FunctionReturnRequiresX86OrX8664;
+
+#[derive(Diagnostic)]
+#[diag(session_function_return_thunk_extern_requires_non_large_code_model)]
+pub(crate) struct FunctionReturnThunkExternRequiresNonLargeCodeModel;
+
+#[derive(Diagnostic)]
+#[diag(session_failed_to_create_profiler)]
+pub struct FailedToCreateProfiler {
+ pub err: String,
+}
diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs
index 3988416d0..6e459ac45 100644
--- a/compiler/rustc_session/src/filesearch.rs
+++ b/compiler/rustc_session/src/filesearch.rs
@@ -9,12 +9,6 @@ use std::path::{Path, PathBuf};
use crate::search_paths::{PathKind, SearchPath};
use rustc_fs_util::fix_windows_verbatim_for_gcc;
-#[derive(Copy, Clone)]
-pub enum FileMatch {
- FileMatches,
- FileDoesntMatch,
-}
-
#[derive(Clone)]
pub struct FileSearch<'a> {
sysroot: &'a Path,
diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs
index 17ac3e991..805854bd5 100644
--- a/compiler/rustc_session/src/lib.rs
+++ b/compiler/rustc_session/src/lib.rs
@@ -1,6 +1,4 @@
-#![feature(if_let_guard)]
#![feature(let_chains)]
-#![feature(min_specialization)]
#![feature(never_type)]
#![feature(lazy_cell)]
#![feature(option_get_or_insert_default)]
@@ -8,7 +6,6 @@
#![feature(map_many_mut)]
#![feature(iter_intersperse)]
#![recursion_limit = "256"]
-#![allow(rustc::potential_query_instability)]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
#![allow(internal_features)]
@@ -20,9 +17,6 @@ pub mod errors;
#[macro_use]
extern crate tracing;
-use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
-use rustc_fluent_macro::fluent_messages;
-
pub mod utils;
pub use lint::{declare_lint, declare_lint_pass, declare_tool_lint, impl_lint_pass};
pub use rustc_lint_defs as lint;
@@ -46,7 +40,7 @@ pub use getopts;
mod version;
pub use version::RustcVersion;
-fluent_messages! { "../messages.ftl" }
+rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
/// Requirements for a `StableHashingContext` to be used in this crate.
/// This is a hack to allow using the `HashStable_Generic` derive macro
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index ed00851b4..06b554e8e 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -2,7 +2,8 @@ use crate::config::*;
use crate::search_paths::SearchPath;
use crate::utils::NativeLib;
-use crate::{lint, EarlyErrorHandler};
+use crate::{lint, EarlyDiagCtxt};
+use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::profiling::TimePassesFormat;
use rustc_data_structures::stable_hasher::Hash64;
use rustc_errors::ColorConfig;
@@ -19,8 +20,7 @@ use rustc_span::SourceFileHashAlgorithm;
use std::collections::BTreeMap;
-use std::collections::hash_map::DefaultHasher;
-use std::hash::Hasher;
+use std::hash::{DefaultHasher, Hasher};
use std::num::{IntErrorKind, NonZeroUsize};
use std::path::PathBuf;
use std::str;
@@ -151,6 +151,9 @@ top_level_options!(
target_triple: TargetTriple [TRACKED],
+ /// Effective logical environment used by `env!`/`option_env!` macros
+ logical_env: FxIndexMap<String, String> [TRACKED],
+
test: bool [TRACKED],
error_format: ErrorOutputType [UNTRACKED],
diagnostic_width: Option<usize> [UNTRACKED],
@@ -252,10 +255,10 @@ macro_rules! options {
impl $struct_name {
pub fn build(
- handler: &EarlyErrorHandler,
+ early_dcx: &EarlyDiagCtxt,
matches: &getopts::Matches,
) -> $struct_name {
- build_options(handler, matches, $stat, $prefix, $outputname)
+ build_options(early_dcx, matches, $stat, $prefix, $outputname)
}
fn dep_tracking_hash(&self, for_crate_hash: bool, error_format: ErrorOutputType) -> u64 {
@@ -316,7 +319,7 @@ 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>(
- handler: &EarlyErrorHandler,
+ early_dcx: &EarlyDiagCtxt,
matches: &getopts::Matches,
descrs: OptionDescrs<O>,
prefix: &str,
@@ -334,12 +337,12 @@ fn build_options<O: Default>(
Some((_, setter, type_desc, _)) => {
if !setter(&mut op, value) {
match value {
- None => handler.early_error(
+ None => early_dcx.early_error(
format!(
"{outputname} option `{key}` requires {type_desc} ({prefix} {key}=<value>)"
),
),
- Some(value) => handler.early_error(
+ Some(value) => early_dcx.early_error(
format!(
"incorrect value `{value}` for {outputname} option `{key}` - {type_desc} was expected"
),
@@ -347,7 +350,7 @@ fn build_options<O: Default>(
}
}
}
- None => handler.early_error(format!("unknown {outputname} option: `{key}`")),
+ None => early_dcx.early_error(format!("unknown {outputname} option: `{key}`")),
}
}
return op;
@@ -393,8 +396,7 @@ mod desc {
pub 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`";
pub const parse_unpretty: &str = "`string` or `string=string`";
pub const parse_treat_err_as_bug: &str = "either no value or a non-negative number";
- pub const parse_trait_solver: &str =
- "one of the supported solver modes (`classic`, `next`, or `next-coherence`)";
+ pub const parse_next_solver_config: &str = "a comma separated list of solver configurations: `globally` (default), `coherence`, `dump-tree`, `dump-tree-on-error";
pub const parse_lto: &str =
"either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted";
pub const parse_linker_plugin_lto: &str =
@@ -426,10 +428,11 @@ mod desc {
"a `,` separated combination of `bti`, `b-key`, `pac-ret`, or `leaf`";
pub const parse_proc_macro_execution_strategy: &str =
"one of supported execution strategies (`same-thread`, or `cross-thread`)";
- pub const parse_dump_solver_proof_tree: &str = "one of: `always`, `on-request`, `on-error`";
pub const parse_remap_path_scope: &str = "comma separated list of scopes: `macro`, `diagnostics`, `unsplit-debuginfo`, `split-debuginfo`, `split-debuginfo-path`, `object`, `all`";
pub const parse_inlining_threshold: &str =
"either a boolean (`yes`, `no`, `on`, `off`, etc), or a non-negative number";
+ pub 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`)";
+ pub const parse_function_return: &str = "`keep` or `thunk-extern`";
}
mod parse {
@@ -1027,15 +1030,48 @@ mod parse {
}
}
- pub(crate) fn parse_trait_solver(slot: &mut TraitSolver, v: Option<&str>) -> bool {
- match v {
- Some("classic") => *slot = TraitSolver::Classic,
- Some("next") => *slot = TraitSolver::Next,
- Some("next-coherence") => *slot = TraitSolver::NextCoherence,
- // default trait solver is subject to change..
- Some("default") => *slot = TraitSolver::Classic,
- _ => return false,
+ pub(crate) fn parse_next_solver_config(
+ slot: &mut Option<NextSolverConfig>,
+ v: Option<&str>,
+ ) -> bool {
+ if let Some(config) = v {
+ let mut coherence = false;
+ let mut globally = true;
+ let mut dump_tree = None;
+ for c in config.split(',') {
+ match c {
+ "globally" => globally = true,
+ "coherence" => {
+ globally = false;
+ coherence = true;
+ }
+ "dump-tree" => {
+ if dump_tree.replace(DumpSolverProofTree::Always).is_some() {
+ return false;
+ }
+ }
+ "dump-tree-on-error" => {
+ if dump_tree.replace(DumpSolverProofTree::OnError).is_some() {
+ return false;
+ }
+ }
+ _ => return false,
+ }
+ }
+
+ *slot = Some(NextSolverConfig {
+ coherence: coherence || globally,
+ globally,
+ dump_tree: dump_tree.unwrap_or_default(),
+ });
+ } else {
+ *slot = Some(NextSolverConfig {
+ coherence: true,
+ globally: true,
+ dump_tree: Default::default(),
+ });
}
+
true
}
@@ -1300,19 +1336,6 @@ mod parse {
true
}
- pub(crate) fn parse_dump_solver_proof_tree(
- slot: &mut DumpSolverProofTree,
- v: Option<&str>,
- ) -> bool {
- match v {
- None | Some("always") => *slot = DumpSolverProofTree::Always,
- Some("never") => *slot = DumpSolverProofTree::Never,
- Some("on-error") => *slot = DumpSolverProofTree::OnError,
- _ => return false,
- };
- true
- }
-
pub(crate) fn parse_inlining_threshold(slot: &mut InliningThreshold, v: Option<&str>) -> bool {
match v {
Some("always" | "yes") => {
@@ -1332,6 +1355,42 @@ mod parse {
}
true
}
+
+ pub(crate) fn parse_llvm_module_flag(
+ slot: &mut Vec<(String, u32, String)>,
+ v: Option<&str>,
+ ) -> bool {
+ let elements = v.unwrap_or_default().split(':').collect::<Vec<_>>();
+ let [key, md_type, value, behavior] = elements.as_slice() else {
+ return false;
+ };
+ if *md_type != "u32" {
+ // Currently we only support u32 metadata flags, but require the
+ // type for forward-compatibility.
+ return false;
+ }
+ let Ok(value) = value.parse::<u32>() else {
+ return false;
+ };
+ let behavior = behavior.to_lowercase();
+ let all_behaviors =
+ ["error", "warning", "require", "override", "append", "appendunique", "max", "min"];
+ if !all_behaviors.contains(&behavior.as_str()) {
+ return false;
+ }
+
+ slot.push((key.to_string(), value, behavior));
+ true
+ }
+
+ pub(crate) fn parse_function_return(slot: &mut FunctionReturn, v: Option<&str>) -> bool {
+ match v {
+ Some("keep") => *slot = FunctionReturn::Keep,
+ Some("thunk-extern") => *slot = FunctionReturn::ThunkExtern,
+ _ => return false,
+ }
+ true
+ }
}
options! {
@@ -1511,6 +1570,8 @@ options! {
"compress debug info sections (none, zlib, zstd, default: none)"),
deduplicate_diagnostics: bool = (true, parse_bool, [UNTRACKED],
"deduplicate identical diagnostics (default: yes)"),
+ default_hidden_visibility: Option<bool> = (None, parse_opt_bool, [TRACKED],
+ "overrides the `default_hidden_visibility` setting of the target"),
dep_info_omit_d_target: bool = (false, parse_bool, [TRACKED],
"in dep-info output, omit targets for tracking dependencies of the dep-info files \
themselves (default: no)"),
@@ -1548,13 +1609,12 @@ options! {
"output statistics about monomorphization collection"),
dump_mono_stats_format: DumpMonoStatsFormat = (DumpMonoStatsFormat::Markdown, parse_dump_mono_stats, [UNTRACKED],
"the format to use for -Z dump-mono-stats (`markdown` (default) or `json`)"),
- dump_solver_proof_tree: DumpSolverProofTree = (DumpSolverProofTree::Never, parse_dump_solver_proof_tree, [UNTRACKED],
- "dump a proof tree for every goal evaluated by the new trait solver. If the flag is specified without any options after it
- then it defaults to `always`. If the flag is not specified at all it defaults to `on-request`."),
dwarf_version: Option<u32> = (None, parse_opt_number, [TRACKED],
"version of DWARF debug information to emit (default: 2 or 4, depending on platform)"),
dylib_lto: bool = (false, parse_bool, [UNTRACKED],
"enables LTO for dylib crate type"),
+ ehcont_guard: bool = (false, parse_bool, [TRACKED],
+ "generate Windows EHCont Guard tables"),
emit_stack_sizes: bool = (false, parse_bool, [UNTRACKED],
"emit a section containing stack size metadata (default: no)"),
emit_thin_lto: bool = (true, parse_bool, [TRACKED],
@@ -1574,6 +1634,8 @@ options! {
"force all crates to be `rustc_private` unstable (default: no)"),
fuel: Option<(String, u64)> = (None, parse_optimization_fuel, [TRACKED],
"set the optimization fuel quota for a crate"),
+ function_return: FunctionReturn = (FunctionReturn::default(), parse_function_return, [TRACKED],
+ "replace returns with jumps to `__x86_return_thunk` (default: `keep`)"),
function_sections: Option<bool> = (None, parse_opt_bool, [TRACKED],
"whether each function should go in its own section"),
future_incompat_test: bool = (false, parse_bool, [UNTRACKED],
@@ -1583,6 +1645,8 @@ options! {
graphviz_font: String = ("Courier, monospace".to_string(), parse_string, [UNTRACKED],
"use the given `fontname` in graphviz output; can be overridden by setting \
environment variable `RUSTC_GRAPHVIZ_FONT` (default: `Courier, monospace`)"),
+ has_thread_local: Option<bool> = (None, parse_opt_bool, [TRACKED],
+ "explicitly enable the `cfg(target_thread_local)` directive"),
hir_stats: bool = (false, parse_bool, [UNTRACKED],
"print some statistics about AST and HIR (default: no)"),
human_readable_cgu_names: bool = (false, parse_bool, [TRACKED],
@@ -1622,8 +1686,6 @@ options! {
`=skip-entry`
`=skip-exit`
Multiple options can be combined with commas."),
- keep_hygiene_data: bool = (false, parse_bool, [UNTRACKED],
- "keep hygiene data after analysis (default: no)"),
layout_seed: Option<u64> = (None, parse_opt_number, [TRACKED],
"seed layout randomization"),
link_directives: bool = (true, parse_bool, [TRACKED],
@@ -1632,6 +1694,8 @@ options! {
"link native libraries in the linker invocation (default: yes)"),
link_only: bool = (false, parse_bool, [TRACKED],
"link the `.rlink` file generated by `-Z no-link` (default: no)"),
+ llvm_module_flag: Vec<(String, u32, String)> = (Vec::new(), parse_llvm_module_flag, [TRACKED],
+ "a list of module flags to pass to LLVM (space separated)"),
llvm_plugins: Vec<String> = (Vec::new(), parse_list, [TRACKED],
"a list LLVM plugins to enable (space separated)"),
llvm_time_trace: bool = (false, parse_bool, [UNTRACKED],
@@ -1673,6 +1737,8 @@ options! {
"the size at which the `large_assignments` lint starts to be emitted"),
mutable_noalias: bool = (true, parse_bool, [TRACKED],
"emit noalias metadata for mutable references (default: yes)"),
+ next_solver: Option<NextSolverConfig> = (None, parse_next_solver_config, [TRACKED],
+ "enable and configure the next generation trait solver used by rustc"),
nll_facts: bool = (false, parse_bool, [UNTRACKED],
"dump facts from NLL analysis into side files (default: no)"),
nll_facts_dir: String = ("nll-facts".to_string(), parse_string, [UNTRACKED],
@@ -1711,8 +1777,6 @@ options! {
"panic strategy for panics in drops"),
parse_only: bool = (false, parse_bool, [UNTRACKED],
"parse only; do not compile, assemble, or link (default: no)"),
- perf_stats: bool = (false, parse_bool, [UNTRACKED],
- "print some performance-related statistics (default: no)"),
plt: Option<bool> = (None, parse_opt_bool, [TRACKED],
"whether to use the PLT when calling into shared libraries;
only has effect for PIC code on systems with ELF binaries
@@ -1774,7 +1838,7 @@ options! {
"directory into which to write optimization remarks (if not specified, they will be \
written to standard error output)"),
report_delayed_bugs: bool = (false, parse_bool, [TRACKED],
- "immediately print bugs registered with `delay_span_bug` (default: no)"),
+ "immediately print bugs registered with `span_delayed_bug` (default: no)"),
sanitizer: SanitizerSet = (SanitizerSet::empty(), parse_sanitizers, [TRACKED],
"use a sanitizer"),
sanitizer_cfi_canonical_jump_tables: Option<bool> = (Some(true), parse_opt_bool, [TRACKED],
@@ -1875,8 +1939,6 @@ written to standard error output)"),
"for every macro invocation, print its name and arguments (default: no)"),
track_diagnostics: bool = (false, parse_bool, [UNTRACKED],
"tracks where in rustc a diagnostic was emitted"),
- trait_solver: TraitSolver = (TraitSolver::Classic, parse_trait_solver, [TRACKED],
- "specify the trait solver mode used by rustc (default: classic)"),
// Diagnostics are considered side-effects of a query (see `QuerySideEffects`) and are saved
// alongside query results and changes to translation options can affect diagnostics - so
// translation options should be tracked.
@@ -1946,9 +2008,3 @@ written to standard error output)"),
// - compiler/rustc_interface/src/tests.rs
// - src/doc/unstable-book/src/compiler-flags
}
-
-#[derive(Clone, Hash, PartialEq, Eq, Debug)]
-pub enum WasiExecModel {
- Command,
- Reactor,
-}
diff --git a/compiler/rustc_session/src/output.rs b/compiler/rustc_session/src/output.rs
index 9cd96895a..2ff32b5bb 100644
--- a/compiler/rustc_session/src/output.rs
+++ b/compiler/rustc_session/src/output.rs
@@ -1,4 +1,4 @@
-//! Related to out filenames of compilation (e.g. save analysis, binaries).
+//! Related to out filenames of compilation (e.g. binaries).
use crate::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType};
use crate::errors::{
CrateNameDoesNotMatch, CrateNameEmpty, CrateNameInvalid, FileIsNotWriteable,
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index 4d20d6d41..2cb47e3a9 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -11,10 +11,10 @@ use crate::lint::{
use rustc_ast::node_id::NodeId;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sync::{AppendOnlyVec, Lock, Lrc};
-use rustc_errors::{emitter::SilentEmitter, Handler};
+use rustc_errors::{emitter::SilentEmitter, DiagCtxt};
use rustc_errors::{
fallback_fluent_bundle, Diagnostic, DiagnosticBuilder, DiagnosticId, DiagnosticMessage,
- EmissionGuarantee, ErrorGuaranteed, IntoDiagnostic, MultiSpan, Noted, StashKey,
+ ErrorGuaranteed, IntoDiagnostic, MultiSpan, Noted, StashKey,
};
use rustc_feature::{find_feature_issue, GateIssue, UnstableFeatures};
use rustc_span::edition::Edition;
@@ -51,6 +51,9 @@ impl GatedSpans {
/// Prepend the given set of `spans` onto the set in `self`.
pub fn merge(&self, mut spans: FxHashMap<Symbol, Vec<Span>>) {
let mut inner = self.spans.borrow_mut();
+ // The entries will be moved to another map so the drain order does not
+ // matter.
+ #[allow(rustc::potential_query_instability)]
for (gate, mut gate_spans) in inner.drain() {
spans.entry(gate).or_default().append(&mut gate_spans);
}
@@ -100,8 +103,7 @@ pub fn feature_err_issue(
// Cancel an earlier warning for this same error, if it exists.
if let Some(span) = span.primary_span() {
- if let Some(err) = sess.span_diagnostic.steal_diagnostic(span, StashKey::EarlySyntaxWarning)
- {
+ if let Some(err) = sess.dcx.steal_diagnostic(span, StashKey::EarlySyntaxWarning) {
err.cancel()
}
}
@@ -135,7 +137,7 @@ pub fn feature_warn_issue(
issue: GateIssue,
explain: &'static str,
) {
- let mut err = sess.span_diagnostic.struct_span_warn(span, explain);
+ let mut err = sess.dcx.struct_span_warn(span, explain);
add_feature_diagnostics_for_issue(&mut err, sess, feature, issue, false);
// Decorate this as a future-incompatibility lint as in rustc_middle::lint::struct_lint_level
@@ -186,7 +188,7 @@ pub fn add_feature_diagnostics_for_issue(
/// Info about a parsing session.
pub struct ParseSess {
- pub span_diagnostic: Handler,
+ pub dcx: DiagCtxt,
pub unstable_features: UnstableFeatures,
pub config: Cfg,
pub check_config: CheckCfg,
@@ -214,7 +216,7 @@ pub struct ParseSess {
pub assume_incomplete_release: bool,
/// Spans passed to `proc_macro::quote_span`. Each span has a numerical
/// identifier represented by its position in the vector.
- pub proc_macro_quoted_spans: AppendOnlyVec<Span>,
+ proc_macro_quoted_spans: AppendOnlyVec<Span>,
/// Used to generate new `AttrId`s. Every `AttrId` is unique.
pub attr_id_generator: AttrIdGenerator,
}
@@ -224,13 +226,13 @@ impl ParseSess {
pub fn new(locale_resources: Vec<&'static str>, file_path_mapping: FilePathMapping) -> Self {
let fallback_bundle = fallback_fluent_bundle(locale_resources, false);
let sm = Lrc::new(SourceMap::new(file_path_mapping));
- let handler = Handler::with_tty_emitter(Some(sm.clone()), fallback_bundle);
- ParseSess::with_span_handler(handler, sm)
+ let dcx = DiagCtxt::with_tty_emitter(Some(sm.clone()), fallback_bundle);
+ ParseSess::with_dcx(dcx, sm)
}
- pub fn with_span_handler(handler: Handler, source_map: Lrc<SourceMap>) -> Self {
+ pub fn with_dcx(dcx: DiagCtxt, source_map: Lrc<SourceMap>) -> Self {
Self {
- span_diagnostic: handler,
+ dcx,
unstable_features: UnstableFeatures::from_environment(None),
config: Cfg::default(),
check_config: CheckCfg::default(),
@@ -253,10 +255,10 @@ impl ParseSess {
pub fn with_silent_emitter(fatal_note: Option<String>) -> Self {
let fallback_bundle = fallback_fluent_bundle(Vec::new(), false);
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
- let fatal_handler = Handler::with_tty_emitter(None, fallback_bundle).disable_warnings();
- let handler = Handler::with_emitter(Box::new(SilentEmitter { fatal_handler, fatal_note }))
+ let fatal_dcx = DiagCtxt::with_tty_emitter(None, fallback_bundle).disable_warnings();
+ let dcx = DiagCtxt::with_emitter(Box::new(SilentEmitter { fatal_dcx, fatal_note }))
.disable_warnings();
- ParseSess::with_span_handler(handler, sm)
+ ParseSess::with_dcx(dcx, sm)
}
#[inline]
@@ -320,7 +322,7 @@ impl ParseSess {
&'a self,
err: impl IntoDiagnostic<'a>,
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
- err.into_diagnostic(&self.span_diagnostic)
+ err.into_diagnostic(&self.dcx)
}
#[track_caller]
@@ -333,7 +335,7 @@ impl ParseSess {
&'a self,
warning: impl IntoDiagnostic<'a, ()>,
) -> DiagnosticBuilder<'a, ()> {
- warning.into_diagnostic(&self.span_diagnostic)
+ warning.into_diagnostic(&self.dcx)
}
#[track_caller]
@@ -346,7 +348,7 @@ impl ParseSess {
&'a self,
note: impl IntoDiagnostic<'a, Noted>,
) -> DiagnosticBuilder<'a, Noted> {
- note.into_diagnostic(&self.span_diagnostic)
+ note.into_diagnostic(&self.dcx)
}
#[track_caller]
@@ -359,7 +361,7 @@ impl ParseSess {
&'a self,
fatal: impl IntoDiagnostic<'a, !>,
) -> DiagnosticBuilder<'a, !> {
- fatal.into_diagnostic(&self.span_diagnostic)
+ fatal.into_diagnostic(&self.dcx)
}
#[track_caller]
@@ -373,27 +375,18 @@ impl ParseSess {
&self,
msg: impl Into<DiagnosticMessage>,
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
- self.span_diagnostic.struct_err(msg)
+ self.dcx.struct_err(msg)
}
#[rustc_lint_diagnostics]
#[track_caller]
pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
- self.span_diagnostic.struct_warn(msg)
+ self.dcx.struct_warn(msg)
}
#[rustc_lint_diagnostics]
#[track_caller]
pub fn struct_fatal(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, !> {
- self.span_diagnostic.struct_fatal(msg)
- }
-
- #[rustc_lint_diagnostics]
- #[track_caller]
- pub fn struct_diagnostic<G: EmissionGuarantee>(
- &self,
- msg: impl Into<DiagnosticMessage>,
- ) -> DiagnosticBuilder<'_, G> {
- self.span_diagnostic.struct_diagnostic(msg)
+ self.dcx.struct_fatal(msg)
}
}
diff --git a/compiler/rustc_session/src/search_paths.rs b/compiler/rustc_session/src/search_paths.rs
index 07e78d176..8ed50f6a1 100644
--- a/compiler/rustc_session/src/search_paths.rs
+++ b/compiler/rustc_session/src/search_paths.rs
@@ -1,5 +1,5 @@
use crate::filesearch::make_target_lib_path;
-use crate::EarlyErrorHandler;
+use crate::EarlyDiagCtxt;
use std::path::{Path, PathBuf};
#[derive(Clone, Debug)]
@@ -46,7 +46,7 @@ impl PathKind {
}
impl SearchPath {
- pub fn from_cli_opt(handler: &EarlyErrorHandler, path: &str) -> Self {
+ pub fn from_cli_opt(early_dcx: &EarlyDiagCtxt, path: &str) -> Self {
let (kind, path) = if let Some(stripped) = path.strip_prefix("native=") {
(PathKind::Native, stripped)
} else if let Some(stripped) = path.strip_prefix("crate=") {
@@ -61,7 +61,7 @@ impl SearchPath {
(PathKind::All, path)
};
if path.is_empty() {
- handler.early_error("empty search path given via `-L`");
+ early_dcx.early_error("empty search path given via `-L`");
}
let dir = PathBuf::from(path);
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 80a549b30..7f168572f 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -1,7 +1,7 @@
use crate::code_stats::CodeStats;
pub use crate::code_stats::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo};
use crate::config::{
- self, CrateType, InstrumentCoverage, OptLevel, OutFileName, OutputType,
+ self, CrateType, FunctionReturn, InstrumentCoverage, OptLevel, OutFileName, OutputType,
RemapPathScopeComponents, SwitchWithOptPath,
};
use crate::config::{ErrorOutputType, Input};
@@ -10,23 +10,21 @@ use crate::parse::{add_feature_diagnostics, ParseSess};
use crate::search_paths::{PathKind, SearchPath};
use crate::{filesearch, lint};
-pub use rustc_ast::attr::MarkedAttrs;
-pub use rustc_ast::Attribute;
use rustc_data_structures::flock;
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
use rustc_data_structures::jobserver::{self, Client};
-use rustc_data_structures::profiling::{duration_to_secs_str, SelfProfiler, SelfProfilerRef};
+use rustc_data_structures::profiling::{SelfProfiler, SelfProfilerRef};
use rustc_data_structures::sync::{
- AtomicU64, AtomicUsize, Lock, Lrc, OneThread, Ordering, Ordering::SeqCst,
+ AtomicU64, DynSend, DynSync, Lock, Lrc, OneThread, Ordering::SeqCst,
};
use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitterWriter;
use rustc_errors::emitter::{DynEmitter, EmitterWriter, HumanReadableErrorType};
use rustc_errors::json::JsonEmitter;
use rustc_errors::registry::Registry;
use rustc_errors::{
- error_code, fallback_fluent_bundle, DiagnosticBuilder, DiagnosticId, DiagnosticMessage,
- ErrorGuaranteed, FluentBundle, Handler, IntoDiagnostic, LazyFallbackBundle, MultiSpan, Noted,
- TerminalUrl,
+ error_code, fallback_fluent_bundle, DiagCtxt, DiagnosticBuilder, DiagnosticId,
+ DiagnosticMessage, ErrorGuaranteed, FluentBundle, IntoDiagnostic, LazyFallbackBundle,
+ MultiSpan, Noted, TerminalUrl,
};
use rustc_macros::HashStable_Generic;
pub use rustc_span::def_id::StableCrateId;
@@ -39,6 +37,7 @@ use rustc_target::spec::{
DebuginfoKind, SanitizerSet, SplitDebuginfo, StackProtector, Target, TargetTriple, TlsModel,
};
+use std::any::Any;
use std::cell::{self, RefCell};
use std::env;
use std::fmt;
@@ -46,9 +45,8 @@ use std::ops::{Div, Mul};
use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::sync::{atomic::AtomicBool, Arc};
-use std::time::Duration;
-pub struct OptimizationFuel {
+struct OptimizationFuel {
/// If `-zfuel=crate=n` is specified, initially set to `n`, otherwise `0`.
remaining: u64,
/// We're rejecting all further optimizations.
@@ -139,6 +137,8 @@ pub struct CompilerIO {
pub temps_dir: Option<PathBuf>,
}
+pub trait LintStoreMarker: Any + DynSync + DynSend {}
+
/// Represents the data associated with a compilation
/// session for a single crate.
pub struct Session {
@@ -157,9 +157,6 @@ pub struct Session {
/// Used by `-Z self-profile`.
pub prof: SelfProfilerRef,
- /// Some measurements that are being gathered during compilation.
- pub perf_stats: PerfStats,
-
/// Data about code being compiled, gathered during compilation.
pub code_stats: CodeStats,
@@ -173,6 +170,12 @@ pub struct Session {
/// false positives about a job server in our environment.
pub jobserver: Client,
+ /// This only ever stores a `LintStore` but we don't want a dependency on that type here.
+ pub lint_store: Option<Lrc<dyn LintStoreMarker>>,
+
+ /// Should be set if any lints are registered in `lint_store`.
+ pub registered_lints: bool,
+
/// Cap lint level specified by a driver specifically.
pub driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
@@ -215,17 +218,6 @@ pub struct Session {
pub expanded_args: Vec<String>,
}
-pub struct PerfStats {
- /// The accumulated time spent on computing symbol hashes.
- pub symbol_hash_time: Lock<Duration>,
- /// Total number of values canonicalized queries constructed.
- pub queries_canonicalized: AtomicUsize,
- /// Number of times this query is invoked.
- pub normalize_generic_arg_after_erasing_regions: AtomicUsize,
- /// Number of times this query is invoked.
- pub normalize_projection_ty: AtomicUsize,
-}
-
#[derive(PartialEq, Eq, PartialOrd, Ord)]
pub enum MetadataKind {
None,
@@ -297,7 +289,7 @@ impl Session {
/// Invoked all the way at the end to finish off diagnostics printing.
pub fn finish_diagnostics(&self, registry: &Registry) {
self.check_miri_unleashed_features();
- self.diagnostic().print_error_count(registry);
+ self.dcx().print_error_count(registry);
self.emit_future_breakage();
}
@@ -306,11 +298,11 @@ impl Session {
return;
}
- let diags = self.diagnostic().take_future_breakage_diagnostics();
+ let diags = self.dcx().take_future_breakage_diagnostics();
if diags.is_empty() {
return;
}
- self.parse_sess.span_diagnostic.emit_future_breakage_report(diags);
+ self.dcx().emit_future_breakage_report(diags);
}
/// Returns true if the crate is a testing one.
@@ -325,7 +317,7 @@ impl Session {
sp: S,
msg: impl Into<DiagnosticMessage>,
) -> DiagnosticBuilder<'_, ()> {
- self.diagnostic().struct_span_warn(sp, msg)
+ self.dcx().struct_span_warn(sp, msg)
}
#[rustc_lint_diagnostics]
#[track_caller]
@@ -335,7 +327,7 @@ impl Session {
msg: impl Into<DiagnosticMessage>,
id: lint::LintExpectationId,
) -> DiagnosticBuilder<'_, ()> {
- self.diagnostic().struct_span_warn_with_expectation(sp, msg, id)
+ self.dcx().struct_span_warn_with_expectation(sp, msg, id)
}
#[rustc_lint_diagnostics]
#[track_caller]
@@ -345,12 +337,12 @@ impl Session {
msg: impl Into<DiagnosticMessage>,
code: DiagnosticId,
) -> DiagnosticBuilder<'_, ()> {
- self.diagnostic().struct_span_warn_with_code(sp, msg, code)
+ self.dcx().struct_span_warn_with_code(sp, msg, code)
}
#[rustc_lint_diagnostics]
#[track_caller]
pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
- self.diagnostic().struct_warn(msg)
+ self.dcx().struct_warn(msg)
}
#[rustc_lint_diagnostics]
#[track_caller]
@@ -359,7 +351,7 @@ impl Session {
msg: impl Into<DiagnosticMessage>,
id: lint::LintExpectationId,
) -> DiagnosticBuilder<'_, ()> {
- self.diagnostic().struct_warn_with_expectation(msg, id)
+ self.dcx().struct_warn_with_expectation(msg, id)
}
#[rustc_lint_diagnostics]
#[track_caller]
@@ -368,12 +360,12 @@ impl Session {
sp: S,
msg: impl Into<DiagnosticMessage>,
) -> DiagnosticBuilder<'_, ()> {
- self.diagnostic().struct_span_allow(sp, msg)
+ self.dcx().struct_span_allow(sp, msg)
}
#[rustc_lint_diagnostics]
#[track_caller]
pub fn struct_allow(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
- self.diagnostic().struct_allow(msg)
+ self.dcx().struct_allow(msg)
}
#[rustc_lint_diagnostics]
#[track_caller]
@@ -382,7 +374,7 @@ impl Session {
msg: impl Into<DiagnosticMessage>,
id: lint::LintExpectationId,
) -> DiagnosticBuilder<'_, ()> {
- self.diagnostic().struct_expect(msg, id)
+ self.dcx().struct_expect(msg, id)
}
#[rustc_lint_diagnostics]
#[track_caller]
@@ -391,7 +383,7 @@ impl Session {
sp: S,
msg: impl Into<DiagnosticMessage>,
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
- self.diagnostic().struct_span_err(sp, msg)
+ self.dcx().struct_span_err(sp, msg)
}
#[rustc_lint_diagnostics]
#[track_caller]
@@ -401,7 +393,7 @@ impl Session {
msg: impl Into<DiagnosticMessage>,
code: DiagnosticId,
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
- self.diagnostic().struct_span_err_with_code(sp, msg, code)
+ self.dcx().struct_span_err_with_code(sp, msg, code)
}
// FIXME: This method should be removed (every error should have an associated error code).
#[rustc_lint_diagnostics]
@@ -419,7 +411,7 @@ impl Session {
msg: impl Into<DiagnosticMessage>,
code: DiagnosticId,
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
- self.diagnostic().struct_err_with_code(msg, code)
+ self.dcx().struct_err_with_code(msg, code)
}
#[rustc_lint_diagnostics]
#[track_caller]
@@ -428,7 +420,7 @@ impl Session {
msg: impl Into<DiagnosticMessage>,
code: DiagnosticId,
) -> DiagnosticBuilder<'_, ()> {
- self.diagnostic().struct_warn_with_code(msg, code)
+ self.dcx().struct_warn_with_code(msg, code)
}
#[rustc_lint_diagnostics]
#[track_caller]
@@ -437,7 +429,7 @@ impl Session {
sp: S,
msg: impl Into<DiagnosticMessage>,
) -> DiagnosticBuilder<'_, !> {
- self.diagnostic().struct_span_fatal(sp, msg)
+ self.dcx().struct_span_fatal(sp, msg)
}
#[rustc_lint_diagnostics]
pub fn struct_span_fatal_with_code<S: Into<MultiSpan>>(
@@ -446,17 +438,17 @@ impl Session {
msg: impl Into<DiagnosticMessage>,
code: DiagnosticId,
) -> DiagnosticBuilder<'_, !> {
- self.diagnostic().struct_span_fatal_with_code(sp, msg, code)
+ self.dcx().struct_span_fatal_with_code(sp, msg, code)
}
#[rustc_lint_diagnostics]
pub fn struct_fatal(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, !> {
- self.diagnostic().struct_fatal(msg)
+ self.dcx().struct_fatal(msg)
}
#[rustc_lint_diagnostics]
#[track_caller]
pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) -> ! {
- self.diagnostic().span_fatal(sp, msg)
+ self.dcx().span_fatal(sp, msg)
}
#[rustc_lint_diagnostics]
pub fn span_fatal_with_code<S: Into<MultiSpan>>(
@@ -465,11 +457,11 @@ impl Session {
msg: impl Into<DiagnosticMessage>,
code: DiagnosticId,
) -> ! {
- self.diagnostic().span_fatal_with_code(sp, msg, code)
+ self.dcx().span_fatal_with_code(sp, msg, code)
}
#[rustc_lint_diagnostics]
pub fn fatal(&self, msg: impl Into<DiagnosticMessage>) -> ! {
- self.diagnostic().fatal(msg).raise()
+ self.dcx().fatal(msg)
}
#[rustc_lint_diagnostics]
#[track_caller]
@@ -478,7 +470,7 @@ impl Session {
sp: S,
msg: impl Into<DiagnosticMessage>,
) -> ErrorGuaranteed {
- self.diagnostic().span_err(sp, msg)
+ self.dcx().span_err(sp, msg)
}
#[rustc_lint_diagnostics]
pub fn span_err_with_code<S: Into<MultiSpan>>(
@@ -486,14 +478,14 @@ impl Session {
sp: S,
msg: impl Into<DiagnosticMessage>,
code: DiagnosticId,
- ) {
- self.diagnostic().span_err_with_code(sp, msg, code)
+ ) -> ErrorGuaranteed {
+ self.dcx().span_err_with_code(sp, msg, code)
}
#[rustc_lint_diagnostics]
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
pub fn err(&self, msg: impl Into<DiagnosticMessage>) -> ErrorGuaranteed {
- self.diagnostic().err(msg)
+ self.dcx().err(msg)
}
#[track_caller]
pub fn create_err<'a>(
@@ -554,23 +546,23 @@ impl Session {
}
#[inline]
pub fn err_count(&self) -> usize {
- self.diagnostic().err_count()
+ self.dcx().err_count()
}
pub fn has_errors(&self) -> Option<ErrorGuaranteed> {
- self.diagnostic().has_errors()
+ self.dcx().has_errors()
}
- pub fn has_errors_or_delayed_span_bugs(&self) -> Option<ErrorGuaranteed> {
- self.diagnostic().has_errors_or_delayed_span_bugs()
+ pub fn has_errors_or_span_delayed_bugs(&self) -> Option<ErrorGuaranteed> {
+ self.dcx().has_errors_or_span_delayed_bugs()
}
pub fn is_compilation_going_to_fail(&self) -> Option<ErrorGuaranteed> {
- self.diagnostic().is_compilation_going_to_fail()
+ self.dcx().is_compilation_going_to_fail()
}
pub fn abort_if_errors(&self) {
- self.diagnostic().abort_if_errors();
+ self.dcx().abort_if_errors();
}
pub fn compile_status(&self) -> Result<(), ErrorGuaranteed> {
- if let Some(reported) = self.diagnostic().has_errors_or_lint_errors() {
- let _ = self.diagnostic().emit_stashed_diagnostics();
+ if let Some(reported) = self.dcx().has_errors_or_lint_errors() {
+ let _ = self.dcx().emit_stashed_diagnostics();
Err(reported)
} else {
Ok(())
@@ -586,7 +578,7 @@ impl Session {
if self.err_count() == old_count {
Ok(result)
} else {
- Err(self.delay_span_bug(
+ Err(self.span_delayed_bug(
rustc_span::DUMMY_SP,
"`self.err_count()` changed but an error was not emitted",
))
@@ -598,7 +590,7 @@ impl Session {
#[allow(rustc::diagnostic_outside_of_impl)]
#[track_caller]
pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) {
- self.diagnostic().span_warn(sp, msg)
+ self.dcx().span_warn(sp, msg)
}
#[rustc_lint_diagnostics]
@@ -610,14 +602,14 @@ impl Session {
msg: impl Into<DiagnosticMessage>,
code: DiagnosticId,
) {
- self.diagnostic().span_warn_with_code(sp, msg, code)
+ self.dcx().span_warn_with_code(sp, msg, code)
}
#[rustc_lint_diagnostics]
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
pub fn warn(&self, msg: impl Into<DiagnosticMessage>) {
- self.diagnostic().warn(msg)
+ self.dcx().warn(msg)
}
/// Ensures that compilation cannot succeed.
@@ -627,24 +619,28 @@ impl Session {
///
/// This can be used in code paths that should never run on successful compilations.
/// For example, it can be used to create an [`ErrorGuaranteed`]
- /// (but you should prefer threading through the [`ErrorGuaranteed`] from an error emission directly).
+ /// (but you should prefer threading through the [`ErrorGuaranteed`] from an error emission
+ /// directly).
///
/// If no span is available, use [`DUMMY_SP`].
///
/// [`DUMMY_SP`]: rustc_span::DUMMY_SP
+ ///
+ /// Note: this function used to be called `delay_span_bug`. It was renamed
+ /// to match similar functions like `span_err`, `span_warn`, etc.
#[track_caller]
- pub fn delay_span_bug<S: Into<MultiSpan>>(
+ pub fn span_delayed_bug<S: Into<MultiSpan>>(
&self,
sp: S,
- msg: impl Into<String>,
+ msg: impl Into<DiagnosticMessage>,
) -> ErrorGuaranteed {
- self.diagnostic().delay_span_bug(sp, msg)
+ self.dcx().span_delayed_bug(sp, msg)
}
/// Used for code paths of expensive computations that should only take place when
/// warnings or errors are emitted. If no messages are emitted ("good path"), then
/// it's likely a bug.
- pub fn delay_good_path_bug(&self, msg: impl Into<DiagnosticMessage>) {
+ pub fn good_path_delayed_bug(&self, msg: impl Into<DiagnosticMessage>) {
if self.opts.unstable_opts.print_type_sizes
|| self.opts.unstable_opts.query_dep_graph
|| self.opts.unstable_opts.dump_mir.is_some()
@@ -655,41 +651,34 @@ impl Session {
return;
}
- self.diagnostic().delay_good_path_bug(msg)
+ self.dcx().good_path_delayed_bug(msg)
}
#[rustc_lint_diagnostics]
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
- pub fn note_without_error(&self, msg: impl Into<DiagnosticMessage>) {
- self.diagnostic().note_without_error(msg)
+ pub fn note(&self, msg: impl Into<DiagnosticMessage>) {
+ self.dcx().note(msg)
}
#[track_caller]
#[rustc_lint_diagnostics]
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
- pub fn span_note_without_error<S: Into<MultiSpan>>(
- &self,
- sp: S,
- msg: impl Into<DiagnosticMessage>,
- ) {
- self.diagnostic().span_note_without_error(sp, msg)
+ pub fn span_note<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) {
+ self.dcx().span_note(sp, msg)
}
#[rustc_lint_diagnostics]
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
- pub fn struct_note_without_error(
- &self,
- msg: impl Into<DiagnosticMessage>,
- ) -> DiagnosticBuilder<'_, ()> {
- self.diagnostic().struct_note_without_error(msg)
+ pub fn struct_note(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
+ self.dcx().struct_note(msg)
}
#[inline]
- pub fn diagnostic(&self) -> &rustc_errors::Handler {
- &self.parse_sess.span_diagnostic
+ pub fn dcx(&self) -> &DiagCtxt {
+ &self.parse_sess.dcx
}
#[inline]
@@ -813,7 +802,7 @@ impl Session {
/// Returns a list of directories where target-specific tool binaries are located.
pub fn get_tools_search_paths(&self, self_contained: bool) -> Vec<PathBuf> {
- let rustlib_path = rustc_target::target_rustlib_path(&self.sysroot, &config::host_triple());
+ let rustlib_path = rustc_target::target_rustlib_path(&self.sysroot, config::host_triple());
let p = PathBuf::from_iter([
Path::new(&self.sysroot),
Path::new(&rustlib_path),
@@ -822,12 +811,7 @@ impl Session {
if self_contained { vec![p.clone(), p.join("self-contained")] } else { vec![p] }
}
- pub fn init_incr_comp_session(
- &self,
- session_dir: PathBuf,
- lock_file: flock::Lock,
- load_dep_graph: bool,
- ) {
+ pub fn init_incr_comp_session(&self, session_dir: PathBuf, lock_file: flock::Lock) {
let mut incr_comp_session = self.incr_comp_session.borrow_mut();
if let IncrCompSession::NotInitialized = *incr_comp_session {
@@ -836,7 +820,7 @@ impl Session {
}
*incr_comp_session =
- IncrCompSession::Active { session_directory: session_dir, lock_file, load_dep_graph };
+ IncrCompSession::Active { session_directory: session_dir, _lock_file: lock_file };
}
pub fn finalize_incr_comp_session(&self, new_directory_path: PathBuf) {
@@ -883,25 +867,6 @@ impl Session {
self.opts.incremental.as_ref().map(|_| self.incr_comp_session_dir())
}
- pub fn print_perf_stats(&self) {
- eprintln!(
- "Total time spent computing symbol hashes: {}",
- duration_to_secs_str(*self.perf_stats.symbol_hash_time.lock())
- );
- eprintln!(
- "Total queries canonicalized: {}",
- self.perf_stats.queries_canonicalized.load(Ordering::Relaxed)
- );
- eprintln!(
- "normalize_generic_arg_after_erasing_regions: {}",
- self.perf_stats.normalize_generic_arg_after_erasing_regions.load(Ordering::Relaxed)
- );
- eprintln!(
- "normalize_projection_ty: {}",
- self.perf_stats.normalize_projection_ty.load(Ordering::Relaxed)
- );
- }
-
/// We want to know if we're allowed to do an optimization for crate foo from -z fuel=foo=n.
/// This expends fuel if applicable, and records fuel if applicable.
pub fn consider_optimizing(
@@ -916,9 +881,9 @@ impl Session {
let mut fuel = self.optimization_fuel.lock();
ret = fuel.remaining != 0;
if fuel.remaining == 0 && !fuel.out_of_fuel {
- if self.diagnostic().can_emit_warnings() {
+ if self.dcx().can_emit_warnings() {
// We only call `msg` in case we can actually emit warnings.
- // Otherwise, this could cause a `delay_good_path_bug` to
+ // Otherwise, this could cause a `good_path_delayed_bug` to
// trigger (issue #79546).
self.emit_warning(errors::OptimisationFuelExhausted { msg: msg() });
}
@@ -996,6 +961,14 @@ impl Session {
termize::dimensions().map_or(default_column_width, |(w, _)| w)
}
}
+
+ /// Whether the default visibility of symbols should be "hidden" rather than "default".
+ pub fn default_hidden_visibility(&self) -> bool {
+ self.opts
+ .unstable_opts
+ .default_hidden_visibility
+ .unwrap_or(self.target.options.default_hidden_visibility)
+ }
}
// JUSTIFICATION: defn of the suggested wrapper fns
@@ -1248,7 +1221,7 @@ impl Session {
}
pub fn teach(&self, code: &DiagnosticId) -> bool {
- self.opts.unstable_opts.teach && self.diagnostic().must_teach(code)
+ self.opts.unstable_opts.teach && self.dcx().must_teach(code)
}
pub fn edition(&self) -> Edition {
@@ -1384,7 +1357,7 @@ fn default_emitter(
// JUSTIFICATION: literally session construction
#[allow(rustc::bad_opt_access)]
pub fn build_session(
- handler: &EarlyErrorHandler,
+ early_dcx: EarlyDiagCtxt,
sopts: config::Options,
io: CompilerIO,
bundle: Option<Lrc<rustc_errors::FluentBundle>>,
@@ -1414,12 +1387,13 @@ pub fn build_session(
None => filesearch::get_or_default_sysroot().expect("Failed finding sysroot"),
};
- let target_cfg = config::build_target_config(handler, &sopts, target_override, &sysroot);
+ let target_cfg = config::build_target_config(&early_dcx, &sopts, target_override, &sysroot);
let host_triple = TargetTriple::from_triple(config::host_triple());
- let (host, target_warnings) = Target::search(&host_triple, &sysroot)
- .unwrap_or_else(|e| handler.early_error(format!("Error loading host specification: {e}")));
+ let (host, target_warnings) = Target::search(&host_triple, &sysroot).unwrap_or_else(|e| {
+ early_dcx.early_error(format!("Error loading host specification: {e}"))
+ });
for warning in target_warnings.warning_messages() {
- handler.early_warn(warning)
+ early_dcx.early_warn(warning)
}
let loader = file_loader.unwrap_or_else(|| Box::new(RealFileLoader));
@@ -1442,12 +1416,16 @@ pub fn build_session(
);
let emitter = default_emitter(&sopts, registry, source_map.clone(), bundle, fallback_bundle);
- let mut span_diagnostic = rustc_errors::Handler::with_emitter(emitter)
- .with_flags(sopts.unstable_opts.diagnostic_handler_flags(can_emit_warnings));
+ let mut dcx = DiagCtxt::with_emitter(emitter)
+ .with_flags(sopts.unstable_opts.dcx_flags(can_emit_warnings));
if let Some(ice_file) = ice_file {
- span_diagnostic = span_diagnostic.with_ice_file(ice_file);
+ dcx = dcx.with_ice_file(ice_file);
}
+ // Now that the proper handler has been constructed, drop early_dcx to
+ // prevent accidental use.
+ drop(early_dcx);
+
let self_profiler = if let SwitchWithOptPath::Enabled(ref d) = sopts.unstable_opts.self_profile
{
let directory =
@@ -1462,7 +1440,7 @@ pub fn build_session(
match profiler {
Ok(profiler) => Some(Arc::new(profiler)),
Err(e) => {
- handler.early_warn(format!("failed to create profiler: {e}"));
+ dcx.emit_warning(errors::FailedToCreateProfiler { err: e.to_string() });
None
}
}
@@ -1470,7 +1448,7 @@ pub fn build_session(
None
};
- let mut parse_sess = ParseSess::with_span_handler(span_diagnostic, source_map);
+ let mut parse_sess = ParseSess::with_dcx(dcx, source_map);
parse_sess.assume_incomplete_release = sopts.unstable_opts.assume_incomplete_release;
let host_triple = config::host_triple();
@@ -1515,16 +1493,12 @@ pub fn build_session(
io,
incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)),
prof,
- perf_stats: PerfStats {
- symbol_hash_time: Lock::new(Duration::from_secs(0)),
- queries_canonicalized: AtomicUsize::new(0),
- normalize_generic_arg_after_erasing_regions: AtomicUsize::new(0),
- normalize_projection_ty: AtomicUsize::new(0),
- },
code_stats: Default::default(),
optimization_fuel,
print_fuel,
jobserver: jobserver::client(),
+ lint_store: None,
+ registered_lints: false,
driver_lint_caps,
ctfe_backtrace,
miri_unleashed_features: Lock::new(Default::default()),
@@ -1707,17 +1681,41 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
sess.emit_err(errors::IncompatibleLinkerFlavor { flavor, compatible_list });
}
}
+
+ if sess.opts.unstable_opts.function_return != FunctionReturn::default() {
+ if sess.target.arch != "x86" && sess.target.arch != "x86_64" {
+ sess.emit_err(errors::FunctionReturnRequiresX86OrX8664);
+ }
+ }
+
+ // The code model check applies to `thunk` and `thunk-extern`, but not `thunk-inline`, so it is
+ // kept as a `match` to force a change if new ones are added, even if we currently only support
+ // `thunk-extern` like Clang.
+ match sess.opts.unstable_opts.function_return {
+ FunctionReturn::Keep => (),
+ FunctionReturn::ThunkExtern => {
+ // FIXME: In principle, the inherited base LLVM target code model could be large,
+ // but this only checks whether we were passed one explicitly (like Clang does).
+ if let Some(code_model) = sess.code_model()
+ && code_model == CodeModel::Large
+ {
+ sess.emit_err(errors::FunctionReturnThunkExternRequiresNonLargeCodeModel);
+ }
+ }
+ }
}
/// Holds data on the current incremental compilation session, if there is one.
#[derive(Debug)]
-pub enum IncrCompSession {
+enum IncrCompSession {
/// This is the state the session will be in until the incr. comp. dir is
/// needed.
NotInitialized,
/// This is the state during which the session directory is private and can
- /// be modified.
- Active { session_directory: PathBuf, lock_file: flock::Lock, load_dep_graph: bool },
+ /// be modified. `_lock_file` is never directly used, but its presence
+ /// alone has an effect, because the file will unlock when the session is
+ /// dropped.
+ Active { session_directory: PathBuf, _lock_file: flock::Lock },
/// This is the state after the session directory has been finalized. In this
/// state, the contents of the directory must not be modified any more.
Finalized { session_directory: PathBuf },
@@ -1727,69 +1725,78 @@ pub enum IncrCompSession {
InvalidBecauseOfErrors { session_directory: PathBuf },
}
-/// A wrapper around an [`Handler`] that is used for early error emissions.
-pub struct EarlyErrorHandler {
- handler: Handler,
+/// A wrapper around an [`DiagCtxt`] that is used for early error emissions.
+pub struct EarlyDiagCtxt {
+ dcx: DiagCtxt,
}
-impl EarlyErrorHandler {
+impl EarlyDiagCtxt {
pub fn new(output: ErrorOutputType) -> Self {
let emitter = mk_emitter(output);
- Self { handler: rustc_errors::Handler::with_emitter(emitter) }
+ Self { dcx: DiagCtxt::with_emitter(emitter) }
}
pub fn abort_if_errors(&self) {
- self.handler.abort_if_errors()
+ self.dcx.abort_if_errors()
}
- /// Swap out the underlying handler once we acquire the user's preference on error emission
+ /// Swap out the underlying dcx once we acquire the user's preference on error emission
/// format. Any errors prior to that will cause an abort and all stashed diagnostics of the
- /// previous handler will be emitted.
+ /// previous dcx will be emitted.
pub fn abort_if_error_and_set_error_format(&mut self, output: ErrorOutputType) {
- self.handler.abort_if_errors();
+ self.dcx.abort_if_errors();
let emitter = mk_emitter(output);
- self.handler = Handler::with_emitter(emitter);
+ self.dcx = DiagCtxt::with_emitter(emitter);
}
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
pub fn early_note(&self, msg: impl Into<DiagnosticMessage>) {
- self.handler.struct_note_without_error(msg).emit()
+ self.dcx.struct_note(msg).emit()
}
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
pub fn early_help(&self, msg: impl Into<DiagnosticMessage>) {
- self.handler.struct_help(msg).emit()
+ self.dcx.struct_help(msg).emit()
}
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
#[must_use = "ErrorGuaranteed must be returned from `run_compiler` in order to exit with a non-zero status code"]
pub fn early_error_no_abort(&self, msg: impl Into<DiagnosticMessage>) -> ErrorGuaranteed {
- self.handler.struct_err(msg).emit()
+ self.dcx.struct_err(msg).emit()
}
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
pub fn early_error(&self, msg: impl Into<DiagnosticMessage>) -> ! {
- self.handler.struct_fatal(msg).emit()
+ self.dcx.struct_fatal(msg).emit()
}
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
- pub(crate) fn early_struct_error(
+ pub fn early_struct_error(
&self,
msg: impl Into<DiagnosticMessage>,
) -> DiagnosticBuilder<'_, !> {
- self.handler.struct_fatal(msg)
+ self.dcx.struct_fatal(msg)
}
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
pub fn early_warn(&self, msg: impl Into<DiagnosticMessage>) {
- self.handler.struct_warn(msg).emit()
+ self.dcx.struct_warn(msg).emit()
+ }
+
+ pub fn initialize_checked_jobserver(&self) {
+ // initialize jobserver before getting `jobserver::client` and `build_session`.
+ jobserver::initialize_checked(|err| {
+ #[allow(rustc::untranslatable_diagnostic)]
+ #[allow(rustc::diagnostic_outside_of_impl)]
+ self.dcx.struct_warn(err).note("the build environment is likely misconfigured").emit()
+ });
}
}
diff --git a/compiler/rustc_session/src/utils.rs b/compiler/rustc_session/src/utils.rs
index 3ed044ad7..f76c69af5 100644
--- a/compiler/rustc_session/src/utils.rs
+++ b/compiler/rustc_session/src/utils.rs
@@ -158,14 +158,3 @@ pub fn extra_compiler_flags() -> Option<(Vec<String>, bool)> {
if !result.is_empty() { Some((result, excluded_cargo_defaults)) } else { None }
}
-
-pub(crate) fn is_ascii_ident(string: &str) -> bool {
- let mut chars = string.chars();
- if let Some(start) = chars.next()
- && (start.is_ascii_alphabetic() || start == '_')
- {
- chars.all(|char| char.is_ascii_alphanumeric() || char == '_')
- } else {
- false
- }
-}
diff --git a/compiler/rustc_session/src/version.rs b/compiler/rustc_session/src/version.rs
index 1ad8620bf..c0c088bce 100644
--- a/compiler/rustc_session/src/version.rs
+++ b/compiler/rustc_session/src/version.rs
@@ -9,7 +9,7 @@ pub struct RustcVersion {
}
impl RustcVersion {
- pub const CURRENT: Self = current_rustc_version!(env!("CFG_RELEASE"));
+ pub const CURRENT: Self = current_rustc_version!();
}
impl Display for RustcVersion {