summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_session
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_session')
-rw-r--r--compiler/rustc_session/locales/en-US.ftl95
-rw-r--r--compiler/rustc_session/src/code_stats.rs32
-rw-r--r--compiler/rustc_session/src/config.rs92
-rw-r--r--compiler/rustc_session/src/cstore.rs14
-rw-r--r--compiler/rustc_session/src/errors.rs40
-rw-r--r--compiler/rustc_session/src/filesearch.rs14
-rw-r--r--compiler/rustc_session/src/lib.rs5
-rw-r--r--compiler/rustc_session/src/options.rs124
-rw-r--r--compiler/rustc_session/src/parse.rs12
-rw-r--r--compiler/rustc_session/src/session.rs128
10 files changed, 449 insertions, 107 deletions
diff --git a/compiler/rustc_session/locales/en-US.ftl b/compiler/rustc_session/locales/en-US.ftl
new file mode 100644
index 000000000..ff53f22d4
--- /dev/null
+++ b/compiler/rustc_session/locales/en-US.ftl
@@ -0,0 +1,95 @@
+session_incorrect_cgu_reuse_type =
+ CGU-reuse for `{$cgu_user_name}` is `{$actual_reuse}` but should be {$at_least ->
+ [one] {"at least "}
+ *[other] {""}
+ }`{$expected_reuse}`
+
+session_cgu_not_recorded =
+ CGU-reuse for `{$cgu_user_name}` is (mangled: `{$cgu_name}`) was not recorded
+
+session_feature_gate_error = {$explain}
+
+session_feature_diagnostic_for_issue =
+ see issue #{$n} <https://github.com/rust-lang/rust/issues/{$n}> for more information
+
+session_feature_diagnostic_help =
+ add `#![feature({$feature})]` to the crate attributes to enable
+
+session_not_circumvent_feature = `-Zunleash-the-miri-inside-of-you` may not be used to circumvent feature gates, except when testing error paths in the CTFE engine
+
+session_profile_use_file_does_not_exist = file `{$path}` passed to `-C profile-use` does not exist.
+
+session_linker_plugin_lto_windows_not_supported = linker plugin based LTO is not supported together with `-C prefer-dynamic` when targeting Windows-like targets
+
+session_profile_sample_use_file_does_not_exist = file `{$path}` passed to `-C profile-sample-use` does not exist.
+
+session_target_requires_unwind_tables = target requires unwind tables, they cannot be disabled with `-C force-unwind-tables=no`
+
+session_instrumentation_not_supported = {$us} instrumentation is not supported for this target
+
+session_sanitizer_not_supported = {$us} sanitizer is not supported for this target
+
+session_sanitizers_not_supported = {$us} sanitizers are not supported for this target
+
+session_cannot_mix_and_match_sanitizers = `-Zsanitizer={$first}` is incompatible with `-Zsanitizer={$second}`
+
+session_cannot_enable_crt_static_linux = sanitizer is incompatible with statically linked libc, disable it using `-C target-feature=-crt-static`
+
+session_sanitizer_cfi_enabled = `-Zsanitizer=cfi` requires `-Clto`
+
+session_unstable_virtual_function_elimination = `-Zvirtual-function-elimination` requires `-Clto`
+
+session_unsupported_dwarf_version = requested DWARF version {$dwarf_version} is greater than 5
+
+session_target_stack_protector_not_supported = `-Z stack-protector={$stack_protector}` is not supported for target {$target_triple} and will be ignored
+
+session_branch_protection_requires_aarch64 = `-Zbranch-protection` is only supported on aarch64
+
+session_split_debuginfo_unstable_platform = `-Csplit-debuginfo={$debuginfo}` is unstable on this platform
+
+session_file_is_not_writeable = output file {$file} is not writeable -- check its permissions
+
+session_crate_name_does_not_match = `--crate-name` and `#[crate_name]` are required to match, but `{$s}` != `{$name}`
+
+session_crate_name_invalid = crate names cannot start with a `-`, but `{$s}` has a leading hyphen
+
+session_crate_name_empty = crate name must not be empty
+
+session_invalid_character_in_create_name = invalid character `{$character}` in crate name: `{$crate_name}`
+
+session_expr_parentheses_needed = parentheses are required to parse this as an expression
+
+session_skipping_const_checks = skipping const checks
+session_unleashed_feature_help_named = skipping check for `{$gate}` feature
+session_unleashed_feature_help_unnamed = skipping check that does not even have a feature gate
+
+session_hexadecimal_float_literal_not_supported = hexadecimal float literal is not supported
+session_octal_float_literal_not_supported = octal float literal is not supported
+session_binary_float_literal_not_supported = binary float literal is not supported
+session_not_supported = not supported
+
+session_invalid_literal_suffix = suffixes on {$kind} literals are invalid
+ .label = invalid suffix `{$suffix}`
+
+session_invalid_num_literal_base_prefix = invalid base prefix for number literal
+ .note = base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+ .suggestion = try making the prefix lowercase
+
+session_invalid_num_literal_suffix = invalid suffix `{$suffix}` for number literal
+ .label = invalid suffix `{$suffix}`
+ .help = the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+session_invalid_float_literal_width = invalid width `{$width}` for float literal
+ .help = valid widths are 32 and 64
+
+session_invalid_float_literal_suffix = invalid suffix `{$suffix}` for float literal
+ .label = invalid suffix `{$suffix}`
+ .help = valid suffixes are `f32` and `f64`
+
+session_int_literal_too_large = integer literal is too large
+ .note = value exceeds limit of `{$limit}`
+
+session_invalid_int_literal_width = invalid width `{$width}` for integer literal
+ .help = valid widths are 8, 16, 32, 64 and 128
+
+session_optimization_fuel_exhausted = optimization-fuel-exhausted: {$msg}
diff --git a/compiler/rustc_session/src/code_stats.rs b/compiler/rustc_session/src/code_stats.rs
index 1085bce44..551782504 100644
--- a/compiler/rustc_session/src/code_stats.rs
+++ b/compiler/rustc_session/src/code_stats.rs
@@ -20,7 +20,25 @@ pub enum SizeKind {
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+pub enum FieldKind {
+ AdtField,
+ Upvar,
+ GeneratorLocal,
+}
+
+impl std::fmt::Display for FieldKind {
+ fn fmt(&self, w: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match self {
+ FieldKind::AdtField => write!(w, "field"),
+ FieldKind::Upvar => write!(w, "upvar"),
+ FieldKind::GeneratorLocal => write!(w, "local"),
+ }
+ }
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub struct FieldInfo {
+ pub kind: FieldKind,
pub name: Symbol,
pub offset: u64,
pub size: u64,
@@ -66,7 +84,11 @@ impl CodeStats {
// Sort variants so the largest ones are shown first. A stable sort is
// used here so that source code order is preserved for all variants
// that have the same size.
- variants.sort_by(|info1, info2| info2.size.cmp(&info1.size));
+ // Except for Generators, whose variants are already sorted according to
+ // their yield points in `variant_info_for_generator`.
+ if kind != DataTypeKind::Generator {
+ variants.sort_by(|info1, info2| info2.size.cmp(&info1.size));
+ }
let info = TypeSizeInfo {
kind,
type_description: type_desc.to_string(),
@@ -145,7 +167,7 @@ impl CodeStats {
fields.sort_by_key(|f| (f.offset, f.size));
for field in fields {
- let FieldInfo { ref name, offset, size, align } = field;
+ let FieldInfo { kind, ref name, offset, size, align } = field;
if offset > min_offset {
let pad = offset - min_offset;
@@ -155,16 +177,16 @@ impl CodeStats {
if offset < min_offset {
// If this happens it's probably a union.
println!(
- "print-type-size {indent}field `.{name}`: {size} bytes, \
+ "print-type-size {indent}{kind} `.{name}`: {size} bytes, \
offset: {offset} bytes, \
alignment: {align} bytes"
);
} else if info.packed || offset == min_offset {
- println!("print-type-size {indent}field `.{name}`: {size} bytes");
+ println!("print-type-size {indent}{kind} `.{name}`: {size} bytes");
} else {
// Include field alignment in output only if it caused padding injection
println!(
- "print-type-size {indent}field `.{name}`: {size} bytes, \
+ "print-type-size {indent}{kind} `.{name}`: {size} bytes, \
alignment: {align} bytes"
);
}
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 586454f76..d4e4ace88 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -24,7 +24,7 @@ use rustc_span::RealFileName;
use rustc_span::SourceFileHashAlgorithm;
use rustc_errors::emitter::HumanReadableErrorType;
-use rustc_errors::{ColorConfig, HandlerFlags};
+use rustc_errors::{ColorConfig, DiagnosticArgValue, HandlerFlags, IntoDiagnosticArg};
use std::collections::btree_map::{
Iter as BTreeMapIter, Keys as BTreeMapKeysIter, Values as BTreeMapValuesIter,
@@ -174,6 +174,25 @@ pub enum InstrumentCoverage {
Off,
}
+/// Settings for `-Z instrument-xray` flag.
+#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
+pub struct InstrumentXRay {
+ /// `-Z instrument-xray=always`, force instrumentation
+ pub always: bool,
+ /// `-Z instrument-xray=never`, disable instrumentation
+ pub never: bool,
+ /// `-Z instrument-xray=ignore-loops`, ignore presence of loops,
+ /// instrument functions based only on instruction count
+ pub ignore_loops: bool,
+ /// `-Z instrument-xray=instruction-threshold=N`, explicitly set instruction threshold
+ /// for instrumentation, or `None` to use compiler's default
+ pub instruction_threshold: Option<usize>,
+ /// `-Z instrument-xray=skip-entry`, do not instrument function entry
+ pub skip_entry: bool,
+ /// `-Z instrument-xray=skip-exit`, do not instrument function exit
+ pub skip_exit: bool,
+}
+
#[derive(Clone, PartialEq, Hash, Debug)]
pub enum LinkerPluginLto {
LinkerPlugin(PathBuf),
@@ -400,6 +419,18 @@ pub enum TrimmedDefPaths {
GoodPath,
}
+#[derive(Clone, Hash)]
+pub enum ResolveDocLinks {
+ /// Do not resolve doc links.
+ None,
+ /// Resolve doc links on exported items only for crate types that have metadata.
+ ExportedMetadata,
+ /// Resolve doc links on exported items.
+ Exported,
+ /// Resolve doc links on all items.
+ All,
+}
+
/// Use tree-based collections to cheaply get a deterministic `Hash` implementation.
/// *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
@@ -769,6 +800,7 @@ impl Default for Options {
unstable_features: UnstableFeatures::Disallow,
debug_assertions: true,
actually_rustdoc: false,
+ resolve_doc_links: ResolveDocLinks::None,
trimmed_def_paths: TrimmedDefPaths::default(),
cli_forced_codegen_units: None,
cli_forced_local_thinlto_off: false,
@@ -865,13 +897,10 @@ pub enum CrateType {
}
impl CrateType {
- /// When generated, is this crate type an archive?
- pub fn is_archive(&self) -> bool {
- match *self {
- CrateType::Rlib | CrateType::Staticlib => true,
- CrateType::Executable | CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro => {
- false
- }
+ pub fn has_metadata(self) -> bool {
+ match self {
+ CrateType::Rlib | CrateType::Dylib | CrateType::ProcMacro => true,
+ CrateType::Executable | CrateType::Cdylib | CrateType::Staticlib => false,
}
}
}
@@ -957,6 +986,7 @@ fn default_configuration(sess: &Session) -> CrateConfig {
if sess.target.has_thread_local {
ret.insert((sym::target_thread_local, None));
}
+ let mut has_atomic = false;
for (i, align) in [
(8, layout.i8_align.abi),
(16, layout.i16_align.abi),
@@ -965,6 +995,7 @@ fn default_configuration(sess: &Session) -> CrateConfig {
(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 {
@@ -981,11 +1012,23 @@ fn default_configuration(sess: &Session) -> CrateConfig {
}
}
}
+ 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())));
- for s in sess.opts.unstable_opts.sanitizer {
+ 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)));
}
@@ -2202,7 +2245,7 @@ pub fn parse_externs(
early_error(
error_format,
"the `-Z unstable-options` flag must also be passed to \
- enable `--extern options",
+ enable `--extern` options",
);
}
for opt in opts.split(',') {
@@ -2507,7 +2550,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
}
// Only use this directory if it has a file we can expect to always find.
- if candidate.join("library/std/src/lib.rs").is_file() { Some(candidate) } else { None }
+ candidate.join("library/std/src/lib.rs").is_file().then_some(candidate)
};
let working_dir = std::env::current_dir().unwrap_or_else(|e| {
@@ -2547,6 +2590,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
libs,
debug_assertions,
actually_rustdoc: false,
+ resolve_doc_links: ResolveDocLinks::ExportedMetadata,
trimmed_def_paths: TrimmedDefPaths::default(),
cli_forced_codegen_units: codegen_units,
cli_forced_local_thinlto_off: disable_local_thinlto,
@@ -2577,6 +2621,7 @@ fn parse_pretty(unstable_opts: &UnstableOptions, efmt: ErrorOutputType) -> Optio
"hir,typed" => Hir(PpHirMode::Typed),
"hir-tree" => HirTree,
"thir-tree" => ThirTree,
+ "thir-flat" => ThirFlat,
"mir" => Mir,
"mir-cfg" => MirCFG,
name => early_error(
@@ -2585,7 +2630,8 @@ fn parse_pretty(unstable_opts: &UnstableOptions, efmt: ErrorOutputType) -> Optio
"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`, `mir` or `mir-cfg`; got {name}"
+ `hir,typed`, `hir-tree`, `thir-tree`, `thir-flat`, `mir` or \
+ `mir-cfg`; got {name}"
),
),
};
@@ -2696,6 +2742,12 @@ impl fmt::Display for CrateType {
}
}
+impl IntoDiagnosticArg for CrateType {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ self.to_string().into_diagnostic_arg()
+ }
+}
+
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum PpSourceMode {
/// `-Zunpretty=normal`
@@ -2740,6 +2792,8 @@ pub enum PpMode {
HirTree,
/// `-Zunpretty=thir-tree`
ThirTree,
+ /// `-Zunpretty=thir-flat`
+ ThirFlat,
/// `-Zunpretty=mir`
Mir,
/// `-Zunpretty=mir-cfg`
@@ -2758,6 +2812,7 @@ impl PpMode {
| Hir(_)
| HirTree
| ThirTree
+ | ThirFlat
| Mir
| MirCFG => true,
}
@@ -2767,13 +2822,13 @@ impl PpMode {
match *self {
Source(_) | AstTree(_) => false,
- Hir(_) | HirTree | ThirTree | Mir | MirCFG => true,
+ Hir(_) | HirTree | ThirTree | ThirFlat | Mir | MirCFG => true,
}
}
pub fn needs_analysis(&self) -> bool {
use PpMode::*;
- matches!(*self, Mir | MirCFG | ThirTree)
+ matches!(*self, Mir | MirCFG | ThirTree | ThirFlat)
}
}
@@ -2798,9 +2853,10 @@ impl PpMode {
pub(crate) mod dep_tracking {
use super::{
BranchProtection, CFGuard, CFProtection, CrateType, DebugInfo, ErrorOutputType,
- InstrumentCoverage, LdImpl, LinkerPluginLto, LocationDetail, LtoCli, OomStrategy, OptLevel,
- OutputType, OutputTypes, Passes, SourceFileHashAlgorithm, SplitDwarfKind,
- SwitchWithOptPath, SymbolManglingVersion, TraitSolver, TrimmedDefPaths,
+ InstrumentCoverage, InstrumentXRay, LdImpl, LinkerPluginLto, LocationDetail, LtoCli,
+ OomStrategy, OptLevel, OutputType, OutputTypes, Passes, ResolveDocLinks,
+ SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion,
+ TraitSolver, TrimmedDefPaths,
};
use crate::lint;
use crate::options::WasiExecModel;
@@ -2869,6 +2925,7 @@ pub(crate) mod dep_tracking {
CodeModel,
TlsModel,
InstrumentCoverage,
+ InstrumentXRay,
CrateType,
MergeFunctions,
PanicStrategy,
@@ -2886,6 +2943,7 @@ pub(crate) mod dep_tracking {
TargetTriple,
Edition,
LinkerPluginLto,
+ ResolveDocLinks,
SplitDebuginfo,
SplitDwarfKind,
StackProtector,
diff --git a/compiler/rustc_session/src/cstore.rs b/compiler/rustc_session/src/cstore.rs
index 4ae9a3fae..868ffdf0f 100644
--- a/compiler/rustc_session/src/cstore.rs
+++ b/compiler/rustc_session/src/cstore.rs
@@ -6,10 +6,9 @@ use crate::search_paths::PathKind;
use crate::utils::NativeLibKind;
use crate::Session;
use rustc_ast as ast;
-use rustc_data_structures::sync::{self, MetadataRef, RwLock};
+use rustc_data_structures::sync::{self, AppendOnlyVec, MetadataRef, RwLock};
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, StableCrateId, LOCAL_CRATE};
use rustc_hir::definitions::{DefKey, DefPath, DefPathHash, Definitions};
-use rustc_index::vec::IndexVec;
use rustc_span::hygiene::{ExpnHash, ExpnId};
use rustc_span::symbol::Symbol;
use rustc_span::Span;
@@ -200,12 +199,12 @@ pub enum ExternCrateSource {
/// 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 {
+pub trait MetadataLoader: std::fmt::Debug {
fn get_rlib_metadata(&self, target: &Target, filename: &Path) -> Result<MetadataRef, String>;
fn get_dylib_metadata(&self, target: &Target, filename: &Path) -> Result<MetadataRef, String>;
}
-pub type MetadataLoaderDyn = dyn MetadataLoader + Sync;
+pub type MetadataLoaderDyn = dyn MetadataLoader + Send + Sync;
/// A store of Rust crates, through which their metadata can be accessed.
///
@@ -250,12 +249,11 @@ pub trait CrateStore: std::fmt::Debug {
fn import_source_files(&self, sess: &Session, cnum: CrateNum);
}
-pub type CrateStoreDyn = dyn CrateStore + sync::Sync;
+pub type CrateStoreDyn = dyn CrateStore + sync::Sync + sync::Send;
-#[derive(Debug)]
pub struct Untracked {
- pub cstore: Box<CrateStoreDyn>,
+ pub cstore: RwLock<Box<CrateStoreDyn>>,
/// Reference span for definitions.
- pub source_span: IndexVec<LocalDefId, Span>,
+ pub source_span: AppendOnlyVec<LocalDefId, Span>,
pub definitions: RwLock<Definitions>,
}
diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs
index f5a72573d..bd32adbbd 100644
--- a/compiler/rustc_session/src/errors.rs
+++ b/compiler/rustc_session/src/errors.rs
@@ -4,7 +4,7 @@ use crate::cgu_reuse_tracker::CguReuse;
use crate::parse::ParseSess;
use rustc_ast::token;
use rustc_ast::util::literal::LitError;
-use rustc_errors::MultiSpan;
+use rustc_errors::{error_code, DiagnosticMessage, EmissionGuarantee, IntoDiagnostic, MultiSpan};
use rustc_macros::Diagnostic;
use rustc_span::{Span, Symbol};
use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple};
@@ -27,12 +27,22 @@ pub struct CguNotRecorded<'a> {
pub cgu_name: &'a str,
}
-#[derive(Diagnostic)]
-#[diag(session_feature_gate_error, code = "E0658")]
-pub struct FeatureGateError<'a> {
- #[primary_span]
+pub struct FeatureGateError {
pub span: MultiSpan,
- pub explain: &'a str,
+ pub explain: DiagnosticMessage,
+}
+
+impl<'a, T: EmissionGuarantee> IntoDiagnostic<'a, T> 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);
+ diag.set_span(self.span);
+ diag.code(error_code!(E0658));
+ diag
+ }
}
#[derive(Subdiagnostic)]
@@ -72,6 +82,12 @@ pub struct ProfileSampleUseFileDoesNotExist<'a> {
pub struct TargetRequiresUnwindTables;
#[derive(Diagnostic)]
+#[diag(session_instrumentation_not_supported)]
+pub struct InstrumentationNotSupported {
+ pub us: String,
+}
+
+#[derive(Diagnostic)]
#[diag(session_sanitizer_not_supported)]
pub struct SanitizerNotSupported {
pub us: String,
@@ -316,11 +332,7 @@ pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span:
.take_while(|c| *c != 'i' && *c != 'u')
.all(|c| c.to_digit(base).is_some());
- if valid {
- Some(format!("0{}{}", base_char.to_ascii_lowercase(), &suffix[1..]))
- } else {
- None
- }
+ valid.then(|| format!("0{}{}", base_char.to_ascii_lowercase(), &suffix[1..]))
}
let token::Lit { kind, symbol, suffix, .. } = lit;
@@ -375,3 +387,9 @@ pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span:
}
}
}
+
+#[derive(Diagnostic)]
+#[diag(session_optimization_fuel_exhausted)]
+pub struct OptimisationFuelExhausted {
+ pub msg: String,
+}
diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs
index b6a328908..f1fbf3821 100644
--- a/compiler/rustc_session/src/filesearch.rs
+++ b/compiler/rustc_session/src/filesearch.rs
@@ -182,7 +182,17 @@ pub fn get_or_default_sysroot() -> Result<PathBuf, String> {
if dir.ends_with(crate::config::host_triple()) {
dir.parent() // chop off `$target`
.and_then(|p| p.parent()) // chop off `rustlib`
- .and_then(|p| p.parent()) // chop off `lib`
+ .and_then(|p| {
+ // chop off `lib` (this could be also $arch dir if the host sysroot uses a
+ // multi-arch layout like Debian or Ubuntu)
+ match p.parent() {
+ Some(p) => match p.file_name() {
+ Some(f) if f == "lib" => p.parent(), // first chop went for $arch, so chop again for `lib`
+ _ => Some(p),
+ },
+ None => None,
+ }
+ })
.map(|s| s.to_owned())
.ok_or(format!(
"Could not move 3 levels upper using `parent()` on {}",
@@ -217,7 +227,7 @@ pub fn get_or_default_sysroot() -> Result<PathBuf, String> {
// Look for the target rustlib directory in the suspected sysroot.
let mut rustlib_path = rustc_target::target_rustlib_path(&p, "dummy");
rustlib_path.pop(); // pop off the dummy target.
- if rustlib_path.exists() { Some(p) } else { None }
+ rustlib_path.exists().then_some(p)
}
None => None,
}
diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs
index 39e871f53..e1f1a5f6d 100644
--- a/compiler/rustc_session/src/lib.rs
+++ b/compiler/rustc_session/src/lib.rs
@@ -18,6 +18,9 @@ pub mod errors;
#[macro_use]
extern crate tracing;
+use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
+use rustc_macros::fluent_messages;
+
pub mod cgu_reuse_tracker;
pub mod utils;
pub use lint::{declare_lint, declare_lint_pass, declare_tool_lint, impl_lint_pass};
@@ -39,6 +42,8 @@ pub mod output;
pub use getopts;
+fluent_messages! { "../locales/en-US.ftl" }
+
/// Requirements for a `StableHashingContext` to be used in this crate.
/// This is a hack to allow using the `HashStable_Generic` derive macro
/// instead of implementing everything in `rustc_middle`.
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 7b5fd6cc2..b466a3fcd 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -4,7 +4,7 @@ use crate::early_error;
use crate::lint;
use crate::search_paths::SearchPath;
use crate::utils::NativeLib;
-use rustc_errors::LanguageIdentifier;
+use rustc_errors::{LanguageIdentifier, TerminalUrl};
use rustc_target::spec::{CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, SanitizerSet};
use rustc_target::spec::{
RelocModel, RelroLevel, SplitDebuginfo, StackProtector, TargetTriple, TlsModel,
@@ -169,6 +169,8 @@ top_level_options!(
/// is currently just a hack and will be removed eventually, so please
/// try to not rely on this too much.
actually_rustdoc: bool [TRACKED],
+ /// Whether name resolver should resolve documentation links.
+ resolve_doc_links: ResolveDocLinks [TRACKED],
/// Control path trimming.
trimmed_def_paths: TrimmedDefPaths [TRACKED],
@@ -349,7 +351,7 @@ fn build_options<O: Default>(
#[allow(non_upper_case_globals)]
mod desc {
pub const parse_no_flag: &str = "no value";
- pub const parse_bool: &str = "one of: `y`, `yes`, `on`, `n`, `no`, or `off`";
+ pub const parse_bool: &str = "one of: `y`, `yes`, `on`, `true`, `n`, `no`, `off` or `false`";
pub const parse_opt_bool: &str = parse_bool;
pub const parse_string: &str = "a string";
pub const parse_opt_string: &str = parse_string;
@@ -368,7 +370,7 @@ mod desc {
pub const parse_opt_panic_strategy: &str = parse_panic_strategy;
pub const parse_oom_strategy: &str = "either `panic` or `abort`";
pub const parse_relro_level: &str = "one of: `full`, `partial`, or `off`";
- pub const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `hwaddress`, `kcfi`, `leak`, `memory`, `memtag`, `shadow-call-stack`, or `thread`";
+ pub const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `shadow-call-stack`, or `thread`";
pub const parse_sanitizer_memory_track_origins: &str = "0, 1, or 2";
pub const parse_cfguard: &str =
"either a boolean (`yes`, `no`, `on`, `off`, etc), `checks`, or `nochecks`";
@@ -380,6 +382,7 @@ mod desc {
pub const parse_dump_mono_stats: &str = "`markdown` (default) or `json`";
pub const parse_instrument_coverage: &str =
"`all` (default), `except-unused-generics`, `except-unused-functions`, or `off`";
+ 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 number bigger than 0";
pub const parse_trait_solver: &str =
@@ -399,6 +402,8 @@ mod desc {
pub const parse_code_model: &str = "one of supported code models (`rustc --print code-models`)";
pub const parse_tls_model: &str = "one of supported TLS models (`rustc --print tls-models`)";
pub const parse_target_feature: &str = parse_string;
+ pub const parse_terminal_url: &str =
+ "either a boolean (`yes`, `no`, `on`, `off`, etc), or `auto`";
pub const parse_wasi_exec_model: &str = "either `command` or `reactor`";
pub const parse_split_debuginfo: &str =
"one of supported split-debuginfo modes (`off`, `packed`, or `unpacked`)";
@@ -432,11 +437,11 @@ mod parse {
/// Use this for any boolean option that has a static default.
pub(crate) fn parse_bool(slot: &mut bool, v: Option<&str>) -> bool {
match v {
- Some("y") | Some("yes") | Some("on") | None => {
+ Some("y") | Some("yes") | Some("on") | Some("true") | None => {
*slot = true;
true
}
- Some("n") | Some("no") | Some("off") => {
+ Some("n") | Some("no") | Some("off") | Some("false") => {
*slot = false;
true
}
@@ -449,11 +454,11 @@ mod parse {
/// other factors, such as other options, or target options.)
pub(crate) fn parse_opt_bool(slot: &mut Option<bool>, v: Option<&str>) -> bool {
match v {
- Some("y") | Some("yes") | Some("on") | None => {
+ Some("y") | Some("yes") | Some("on") | Some("true") | None => {
*slot = Some(true);
true
}
- Some("n") | Some("no") | Some("off") => {
+ Some("n") | Some("no") | Some("off") | Some("false") => {
*slot = Some(false);
true
}
@@ -679,6 +684,7 @@ mod parse {
"address" => SanitizerSet::ADDRESS,
"cfi" => SanitizerSet::CFI,
"kcfi" => SanitizerSet::KCFI,
+ "kernel-address" => SanitizerSet::KERNELADDRESS,
"leak" => SanitizerSet::LEAK,
"memory" => SanitizerSet::MEMORY,
"memtag" => SanitizerSet::MEMTAG,
@@ -804,7 +810,7 @@ mod parse {
if v.is_some() {
let mut bool_arg = None;
if parse_opt_bool(&mut bool_arg, v) {
- *slot = if bool_arg.unwrap() { Some(MirSpanview::Statement) } else { None };
+ *slot = bool_arg.unwrap().then_some(MirSpanview::Statement);
return true;
}
}
@@ -845,7 +851,7 @@ mod parse {
if v.is_some() {
let mut bool_arg = None;
if parse_opt_bool(&mut bool_arg, v) {
- *slot = if bool_arg.unwrap() { Some(InstrumentCoverage::All) } else { None };
+ *slot = bool_arg.unwrap().then_some(InstrumentCoverage::All);
return true;
}
}
@@ -869,6 +875,68 @@ mod parse {
true
}
+ pub(crate) fn parse_instrument_xray(
+ slot: &mut Option<InstrumentXRay>,
+ v: Option<&str>,
+ ) -> bool {
+ if v.is_some() {
+ let mut bool_arg = None;
+ if parse_opt_bool(&mut bool_arg, v) {
+ *slot = if bool_arg.unwrap() { Some(InstrumentXRay::default()) } else { None };
+ return true;
+ }
+ }
+
+ let mut options = slot.get_or_insert_default();
+ let mut seen_always = false;
+ let mut seen_never = false;
+ let mut seen_ignore_loops = false;
+ let mut seen_instruction_threshold = false;
+ let mut seen_skip_entry = false;
+ let mut seen_skip_exit = false;
+ for option in v.into_iter().map(|v| v.split(',')).flatten() {
+ match option {
+ "always" if !seen_always && !seen_never => {
+ options.always = true;
+ options.never = false;
+ seen_always = true;
+ }
+ "never" if !seen_never && !seen_always => {
+ options.never = true;
+ options.always = false;
+ seen_never = true;
+ }
+ "ignore-loops" if !seen_ignore_loops => {
+ options.ignore_loops = true;
+ seen_ignore_loops = true;
+ }
+ option
+ if option.starts_with("instruction-threshold")
+ && !seen_instruction_threshold =>
+ {
+ let Some(("instruction-threshold", n)) = option.split_once('=') else {
+ return false;
+ };
+ match n.parse() {
+ Ok(n) => options.instruction_threshold = Some(n),
+ Err(_) => return false,
+ }
+ seen_instruction_threshold = true;
+ }
+ "skip-entry" if !seen_skip_entry => {
+ options.skip_entry = true;
+ seen_skip_entry = true;
+ }
+ "skip-exit" if !seen_skip_exit => {
+ options.skip_exit = true;
+ seen_skip_exit = true;
+ }
+ _ => return false,
+ }
+ }
+ true
+ }
+
pub(crate) fn parse_treat_err_as_bug(slot: &mut Option<NonZeroUsize>, v: Option<&str>) -> bool {
match v {
Some(s) => {
@@ -979,6 +1047,16 @@ mod parse {
true
}
+ pub(crate) fn parse_terminal_url(slot: &mut TerminalUrl, v: Option<&str>) -> bool {
+ *slot = match v {
+ Some("on" | "" | "yes" | "y") | None => TerminalUrl::Yes,
+ Some("off" | "no" | "n") => TerminalUrl::No,
+ Some("auto") => TerminalUrl::Auto,
+ _ => return false,
+ };
+ true
+ }
+
pub(crate) fn parse_symbol_mangling_version(
slot: &mut Option<SymbolManglingVersion>,
v: Option<&str>,
@@ -1290,6 +1368,8 @@ options! {
(default: no)"),
drop_tracking: bool = (false, parse_bool, [TRACKED],
"enables drop tracking in generators (default: no)"),
+ drop_tracking_mir: bool = (false, parse_bool, [TRACKED],
+ "enables drop tracking on MIR in generators (default: no)"),
dual_proc_macros: bool = (false, parse_bool, [TRACKED],
"load proc macros for both target and host, but only link to the target (default: no)"),
dump_dep_graph: bool = (false, parse_bool, [UNTRACKED],
@@ -1395,10 +1475,22 @@ options! {
`=off` (default)"),
instrument_mcount: bool = (false, parse_bool, [TRACKED],
"insert function instrument code for mcount-based tracing (default: no)"),
+ instrument_xray: Option<InstrumentXRay> = (None, parse_instrument_xray, [TRACKED],
+ "insert function instrument code for XRay-based tracing (default: no)
+ Optional extra settings:
+ `=always`
+ `=never`
+ `=ignore-loops`
+ `=instruction-threshold=N`
+ `=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],
+ "honor #[link] directives in the compiled crate (default: yes)"),
link_native_libraries: bool = (true, parse_bool, [UNTRACKED],
"link native libraries in the linker invocation (default: yes)"),
link_only: bool = (false, parse_bool, [TRACKED],
@@ -1411,8 +1503,9 @@ options! {
"what location details should be tracked when using caller_location, either \
`none`, or a comma separated list of location details, for which \
valid options are `file`, `line`, and `column` (default: `file,line,column`)"),
- log_backtrace: Option<String> = (None, parse_opt_string, [TRACKED],
- "add a backtrace along with logging"),
+ lower_impl_trait_in_trait_to_assoc_ty: bool = (false, parse_bool, [TRACKED],
+ "modify the lowering strategy for `impl Trait` in traits so that they are lowered to \
+ generic associated types"),
ls: bool = (false, parse_bool, [UNTRACKED],
"list the symbols defined by a library crate (default: no)"),
macro_backtrace: bool = (false, parse_bool, [UNTRACKED],
@@ -1479,8 +1572,6 @@ options! {
"parse only; do not compile, assemble, or link (default: no)"),
perf_stats: bool = (false, parse_bool, [UNTRACKED],
"print some performance-related statistics (default: no)"),
- pick_stable_methods_before_any_unstable: bool = (true, parse_bool, [TRACKED],
- "try to pick stable methods first before picking any unstable methods (default: yes)"),
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
@@ -1542,9 +1633,6 @@ options! {
saturating_float_casts: Option<bool> = (None, parse_opt_bool, [TRACKED],
"make float->int casts UB-free: numbers outside the integer type's range are clipped to \
the max/min integer respectively, and NaN is mapped to 0 (default: yes)"),
- save_analysis: bool = (false, parse_bool, [UNTRACKED],
- "write syntax and type analysis (in JSON format) information, in \
- addition to normal output (default: no)"),
self_profile: SwitchWithOptPath = (SwitchWithOptPath::Disabled,
parse_switch_with_opt_path, [UNTRACKED],
"run the self profiler and output the raw event data"),
@@ -1600,6 +1688,8 @@ options! {
"show extended diagnostic help (default: no)"),
temps_dir: Option<String> = (None, parse_opt_string, [UNTRACKED],
"the directory the intermediate files are written to"),
+ terminal_urls: TerminalUrl = (TerminalUrl::No, parse_terminal_url, [UNTRACKED],
+ "use the OSC 8 hyperlink terminal specification to print hyperlinks in the compiler output"),
#[rustc_lint_opt_deny_field_access("use `Session::lto` instead of this field")]
thinlto: Option<bool> = (None, parse_opt_bool, [TRACKED],
"enable ThinLTO when possible"),
@@ -1616,6 +1706,8 @@ options! {
"measure time of each LLVM pass (default: no)"),
time_passes: bool = (false, parse_bool, [UNTRACKED],
"measure time of each rustc pass (default: no)"),
+ tiny_const_eval_limit: bool = (false, parse_bool, [TRACKED],
+ "sets a tiny, non-configurable limit for const eval; useful for compiler tests"),
#[rustc_lint_opt_deny_field_access("use `Session::tls_model` instead of this field")]
tls_model: Option<TlsModel> = (None, parse_tls_model, [TRACKED],
"choose the TLS model to use (`rustc --print tls-models` for details)"),
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index 2aa8ca9e4..4e8c3f73e 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -88,7 +88,7 @@ pub fn feature_err<'a>(
sess: &'a ParseSess,
feature: Symbol,
span: impl Into<MultiSpan>,
- explain: &str,
+ explain: impl Into<DiagnosticMessage>,
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
feature_err_issue(sess, feature, span, GateIssue::Language, explain)
}
@@ -103,7 +103,7 @@ pub fn feature_err_issue<'a>(
feature: Symbol,
span: impl Into<MultiSpan>,
issue: GateIssue,
- explain: &str,
+ explain: impl Into<DiagnosticMessage>,
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
let span = span.into();
@@ -114,7 +114,7 @@ pub fn feature_err_issue<'a>(
.map(|err| err.cancel());
}
- let mut err = sess.create_err(FeatureGateError { span, explain });
+ let mut err = sess.create_err(FeatureGateError { span, explain: explain.into() });
add_feature_diagnostics_for_issue(&mut err, sess, feature, issue);
err
}
@@ -226,8 +226,8 @@ pub struct ParseSess {
impl ParseSess {
/// Used for testing.
- pub fn new(file_path_mapping: FilePathMapping) -> Self {
- let fallback_bundle = fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);
+ 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(
ColorConfig::Auto,
@@ -265,7 +265,7 @@ impl ParseSess {
}
pub fn with_silent_emitter(fatal_note: Option<String>) -> Self {
- let fallback_bundle = fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);
+ let fallback_bundle = fallback_fluent_bundle(Vec::new(), false);
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
let fatal_handler =
Handler::with_tty_emitter(ColorConfig::Auto, false, None, None, None, fallback_bundle);
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 95f199de6..12634f671 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -1,16 +1,9 @@
use crate::cgu_reuse_tracker::CguReuseTracker;
use crate::code_stats::CodeStats;
-pub use crate::code_stats::{DataTypeKind, FieldInfo, SizeKind, VariantInfo};
+pub use crate::code_stats::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo};
use crate::config::Input;
use crate::config::{self, CrateType, InstrumentCoverage, OptLevel, OutputType, SwitchWithOptPath};
-use crate::errors::{
- BranchProtectionRequiresAArch64, CannotEnableCrtStaticLinux, CannotMixAndMatchSanitizers,
- LinkerPluginToWindowsNotSupported, NotCircumventFeature, ProfileSampleUseFileDoesNotExist,
- ProfileUseFileDoesNotExist, SanitizerCfiEnabled, SanitizerNotSupported, SanitizersNotSupported,
- SkippingConstChecks, SplitDebugInfoUnstablePlatform, StackProtectorNotSupportedForTarget,
- TargetRequiresUnwindTables, UnleashedFeatureHelp, UnstableVirtualFunctionElimination,
- UnsupportedDwarfVersion,
-};
+use crate::errors;
use crate::parse::{add_feature_diagnostics, ParseSess};
use crate::search_paths::{PathKind, SearchPath};
use crate::{filesearch, lint};
@@ -31,6 +24,7 @@ use rustc_errors::registry::Registry;
use rustc_errors::{
error_code, fallback_fluent_bundle, DiagnosticBuilder, DiagnosticId, DiagnosticMessage,
ErrorGuaranteed, FluentBundle, IntoDiagnostic, LazyFallbackBundle, MultiSpan, Noted,
+ TerminalUrl,
};
use rustc_macros::HashStable_Generic;
pub use rustc_span::def_id::StableCrateId;
@@ -163,7 +157,7 @@ pub struct Session {
/// `-C metadata` arguments passed to the compiler. Its value forms a unique
/// global identifier for the crate. It is used to allow multiple crates
/// with the same name to coexist. See the
- /// `rustc_codegen_llvm::back::symbol_names` module for more information.
+ /// `rustc_symbol_mangling` crate for more information.
pub stable_crate_id: OnceCell<StableCrateId>,
features: OnceCell<rustc_feature::Features>,
@@ -245,15 +239,15 @@ impl Session {
if !unleashed_features.is_empty() {
let mut must_err = false;
// Create a diagnostic pointing at where things got unleashed.
- self.emit_warning(SkippingConstChecks {
+ self.emit_warning(errors::SkippingConstChecks {
unleashed_features: unleashed_features
.iter()
.map(|(span, gate)| {
gate.map(|gate| {
must_err = true;
- UnleashedFeatureHelp::Named { span: *span, gate }
+ errors::UnleashedFeatureHelp::Named { span: *span, gate }
})
- .unwrap_or(UnleashedFeatureHelp::Unnamed { span: *span })
+ .unwrap_or(errors::UnleashedFeatureHelp::Unnamed { span: *span })
})
.collect(),
});
@@ -261,7 +255,7 @@ impl Session {
// If we should err, make sure we did.
if must_err && self.has_errors().is_none() {
// We have skipped a feature gate, and not run into other errors... reject.
- self.emit_err(NotCircumventFeature);
+ self.emit_err(errors::NotCircumventFeature);
}
}
}
@@ -483,6 +477,8 @@ impl Session {
self.diagnostic().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)
}
@@ -583,12 +579,16 @@ impl Session {
))
}
}
+
+ #[rustc_lint_diagnostics]
#[allow(rustc::untranslatable_diagnostic)]
#[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)
}
+
+ #[rustc_lint_diagnostics]
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
pub fn span_warn_with_code<S: Into<MultiSpan>>(
@@ -599,6 +599,10 @@ impl Session {
) {
self.diagnostic().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)
}
@@ -641,11 +645,17 @@ impl Session {
self.diagnostic().delay_good_path_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)
}
#[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,
@@ -653,6 +663,8 @@ impl Session {
) {
self.diagnostic().span_note_without_error(sp, msg)
}
+
+ #[rustc_lint_diagnostics]
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
pub fn struct_note_without_error(
@@ -870,10 +882,14 @@ impl Session {
/// 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<T: Fn() -> String>(&self, crate_name: &str, msg: T) -> bool {
+ pub fn consider_optimizing(
+ &self,
+ get_crate_name: impl Fn() -> Symbol,
+ msg: impl Fn() -> String,
+ ) -> bool {
let mut ret = true;
if let Some((ref c, _)) = self.opts.unstable_opts.fuel {
- if c == crate_name {
+ if c == get_crate_name().as_str() {
assert_eq!(self.threads(), 1);
let mut fuel = self.optimization_fuel.lock();
ret = fuel.remaining != 0;
@@ -882,7 +898,7 @@ impl Session {
// We only call `msg` in case we can actually emit warnings.
// Otherwise, this could cause a `delay_good_path_bug` to
// trigger (issue #79546).
- self.warn(&format!("optimization-fuel-exhausted: {}", msg()));
+ self.emit_warning(errors::OptimisationFuelExhausted { msg: msg() });
}
fuel.out_of_fuel = true;
} else if fuel.remaining > 0 {
@@ -891,7 +907,7 @@ impl Session {
}
}
if let Some(ref c) = self.opts.unstable_opts.print_fuel {
- if c == crate_name {
+ if c == get_crate_name().as_str() {
assert_eq!(self.threads(), 1);
self.print_fuel.fetch_add(1, SeqCst);
}
@@ -899,23 +915,24 @@ impl Session {
ret
}
- pub fn rust_2015(&self) -> bool {
- self.edition() == Edition::Edition2015
+ /// Is this edition 2015?
+ pub fn is_rust_2015(&self) -> bool {
+ self.edition().is_rust_2015()
}
/// Are we allowed to use features from the Rust 2018 edition?
pub fn rust_2018(&self) -> bool {
- self.edition() >= Edition::Edition2018
+ self.edition().rust_2018()
}
/// Are we allowed to use features from the Rust 2021 edition?
pub fn rust_2021(&self) -> bool {
- self.edition() >= Edition::Edition2021
+ self.edition().rust_2021()
}
/// Are we allowed to use features from the Rust 2024 edition?
pub fn rust_2024(&self) -> bool {
- self.edition() >= Edition::Edition2024
+ self.edition().rust_2024()
}
/// Returns `true` if we cannot skip the PLT for shared library calls.
@@ -941,10 +958,10 @@ impl Session {
/// Checks if LLVM lifetime markers should be emitted.
pub fn emit_lifetime_markers(&self) -> bool {
self.opts.optimize != config::OptLevel::No
- // AddressSanitizer uses lifetimes to detect use after scope bugs.
+ // AddressSanitizer and KernelAddressSanitizer uses lifetimes to detect use after scope bugs.
// MemorySanitizer uses lifetimes to detect use of uninitialized stack variables.
// HWAddressSanitizer will use lifetimes to detect use after scope bugs in the future.
- || self.opts.unstable_opts.sanitizer.intersects(SanitizerSet::ADDRESS | SanitizerSet::MEMORY | SanitizerSet::HWADDRESS)
+ || self.opts.unstable_opts.sanitizer.intersects(SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS | SanitizerSet::MEMORY | SanitizerSet::HWADDRESS)
}
pub fn is_proc_macro_attr(&self, attr: &Attribute) -> bool {
@@ -1261,6 +1278,19 @@ fn default_emitter(
) -> Box<dyn Emitter + sync::Send> {
let macro_backtrace = sopts.unstable_opts.macro_backtrace;
let track_diagnostics = sopts.unstable_opts.track_diagnostics;
+ let terminal_url = match sopts.unstable_opts.terminal_urls {
+ TerminalUrl::Auto => {
+ match (std::env::var("COLORTERM").as_deref(), std::env::var("TERM").as_deref()) {
+ (Ok("truecolor"), Ok("xterm-256color"))
+ if sopts.unstable_features.is_nightly_build() =>
+ {
+ TerminalUrl::Yes
+ }
+ _ => TerminalUrl::No,
+ }
+ }
+ t => t,
+ };
match sopts.error_format {
config::ErrorOutputType::HumanReadable(kind) => {
let (short, color_config) = kind.unzip();
@@ -1285,6 +1315,7 @@ fn default_emitter(
sopts.diagnostic_width,
macro_backtrace,
track_diagnostics,
+ terminal_url,
);
Box::new(emitter.ui_testing(sopts.unstable_opts.ui_testing))
}
@@ -1300,6 +1331,7 @@ fn default_emitter(
sopts.diagnostic_width,
macro_backtrace,
track_diagnostics,
+ terminal_url,
)
.ui_testing(sopts.unstable_opts.ui_testing),
),
@@ -1313,6 +1345,7 @@ pub fn build_session(
io: CompilerIO,
bundle: Option<Lrc<rustc_errors::FluentBundle>>,
registry: rustc_errors::registry::Registry,
+ fluent_resources: Vec<&'static str>,
driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
file_loader: Option<Box<dyn FileLoader + Send + Sync + 'static>>,
target_override: Option<Target>,
@@ -1357,7 +1390,7 @@ pub fn build_session(
));
let fallback_bundle = fallback_fluent_bundle(
- rustc_errors::DEFAULT_LOCALE_RESOURCES,
+ fluent_resources,
sopts.unstable_opts.translate_directionality_markers,
);
let emitter = default_emitter(&sopts, registry, source_map.clone(), bundle, fallback_bundle);
@@ -1482,28 +1515,28 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
&& sess.opts.cg.prefer_dynamic
&& sess.target.is_like_windows
{
- sess.emit_err(LinkerPluginToWindowsNotSupported);
+ sess.emit_err(errors::LinkerPluginToWindowsNotSupported);
}
// Make sure that any given profiling data actually exists so LLVM can't
// decide to silently skip PGO.
if let Some(ref path) = sess.opts.cg.profile_use {
if !path.exists() {
- sess.emit_err(ProfileUseFileDoesNotExist { path });
+ sess.emit_err(errors::ProfileUseFileDoesNotExist { path });
}
}
// Do the same for sample profile data.
if let Some(ref path) = sess.opts.unstable_opts.profile_sample_use {
if !path.exists() {
- sess.emit_err(ProfileSampleUseFileDoesNotExist { path });
+ sess.emit_err(errors::ProfileSampleUseFileDoesNotExist { path });
}
}
// Unwind tables cannot be disabled if the target requires them.
if let Some(include_uwtables) = sess.opts.cg.force_unwind_tables {
if sess.target.requires_uwtable && !include_uwtables {
- sess.emit_err(TargetRequiresUnwindTables);
+ sess.emit_err(errors::TargetRequiresUnwindTables);
}
}
@@ -1513,16 +1546,18 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
match unsupported_sanitizers.into_iter().count() {
0 => {}
1 => {
- sess.emit_err(SanitizerNotSupported { us: unsupported_sanitizers.to_string() });
+ sess.emit_err(errors::SanitizerNotSupported { us: unsupported_sanitizers.to_string() });
}
_ => {
- sess.emit_err(SanitizersNotSupported { us: unsupported_sanitizers.to_string() });
+ sess.emit_err(errors::SanitizersNotSupported {
+ us: unsupported_sanitizers.to_string(),
+ });
}
}
// Cannot mix and match sanitizers.
let mut sanitizer_iter = sess.opts.unstable_opts.sanitizer.into_iter();
if let (Some(first), Some(second)) = (sanitizer_iter.next(), sanitizer_iter.next()) {
- sess.emit_err(CannotMixAndMatchSanitizers {
+ sess.emit_err(errors::CannotMixAndMatchSanitizers {
first: first.to_string(),
second: second.to_string(),
});
@@ -1530,22 +1565,22 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
// Cannot enable crt-static with sanitizers on Linux
if sess.crt_static(None) && !sess.opts.unstable_opts.sanitizer.is_empty() {
- sess.emit_err(CannotEnableCrtStaticLinux);
+ sess.emit_err(errors::CannotEnableCrtStaticLinux);
}
// LLVM CFI and VFE both require LTO.
if sess.lto() != config::Lto::Fat {
if sess.is_sanitizer_cfi_enabled() {
- sess.emit_err(SanitizerCfiEnabled);
+ sess.emit_err(errors::SanitizerCfiEnabled);
}
if sess.opts.unstable_opts.virtual_function_elimination {
- sess.emit_err(UnstableVirtualFunctionElimination);
+ sess.emit_err(errors::UnstableVirtualFunctionElimination);
}
}
// LLVM CFI and KCFI are mutually exclusive
if sess.is_sanitizer_cfi_enabled() && sess.is_sanitizer_kcfi_enabled() {
- sess.emit_err(CannotMixAndMatchSanitizers {
+ sess.emit_err(errors::CannotMixAndMatchSanitizers {
first: "cfi".to_string(),
second: "kcfi".to_string(),
});
@@ -1553,7 +1588,7 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
if sess.opts.unstable_opts.stack_protector != StackProtector::None {
if !sess.target.options.supports_stack_protector {
- sess.emit_warning(StackProtectorNotSupportedForTarget {
+ sess.emit_warning(errors::StackProtectorNotSupportedForTarget {
stack_protector: sess.opts.unstable_opts.stack_protector,
target_triple: &sess.opts.target_triple,
});
@@ -1561,19 +1596,23 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
}
if sess.opts.unstable_opts.branch_protection.is_some() && sess.target.arch != "aarch64" {
- sess.emit_err(BranchProtectionRequiresAArch64);
+ sess.emit_err(errors::BranchProtectionRequiresAArch64);
}
if let Some(dwarf_version) = sess.opts.unstable_opts.dwarf_version {
if dwarf_version > 5 {
- sess.emit_err(UnsupportedDwarfVersion { dwarf_version });
+ sess.emit_err(errors::UnsupportedDwarfVersion { dwarf_version });
}
}
if !sess.target.options.supported_split_debuginfo.contains(&sess.split_debuginfo())
&& !sess.opts.unstable_opts.unstable_options
{
- sess.emit_err(SplitDebugInfoUnstablePlatform { debuginfo: sess.split_debuginfo() });
+ sess.emit_err(errors::SplitDebugInfoUnstablePlatform { debuginfo: sess.split_debuginfo() });
+ }
+
+ if sess.opts.unstable_opts.instrument_xray.is_some() && !sess.target.options.supports_xray {
+ sess.emit_err(errors::InstrumentationNotSupported { us: "XRay".to_string() });
}
}
@@ -1596,7 +1635,10 @@ pub enum IncrCompSession {
}
fn early_error_handler(output: config::ErrorOutputType) -> rustc_errors::Handler {
- let fallback_bundle = fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);
+ // FIXME(#100717): early errors aren't translated at the moment, so this is fine, but it will
+ // need to reference every crate that might emit an early error for translation to work.
+ let fallback_bundle =
+ fallback_fluent_bundle(vec![rustc_errors::DEFAULT_LOCALE_RESOURCE], false);
let emitter: Box<dyn Emitter + sync::Send> = match output {
config::ErrorOutputType::HumanReadable(kind) => {
let (short, color_config) = kind.unzip();
@@ -1610,6 +1652,7 @@ fn early_error_handler(output: config::ErrorOutputType) -> rustc_errors::Handler
None,
false,
false,
+ TerminalUrl::No,
))
}
config::ErrorOutputType::Json { pretty, json_rendered } => Box::new(JsonEmitter::basic(
@@ -1620,6 +1663,7 @@ fn early_error_handler(output: config::ErrorOutputType) -> rustc_errors::Handler
None,
false,
false,
+ TerminalUrl::No,
)),
};
rustc_errors::Handler::with_emitter(true, None, emitter)