diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:43 +0000 |
commit | 3e3e70d529d8c7d7c4d7bc4fefc9f109393b9245 (patch) | |
tree | daf049b282ab10e8c3d03e409b3cd84ff3f7690c /compiler/rustc_session | |
parent | Adding debian version 1.68.2+dfsg1-1. (diff) | |
download | rustc-3e3e70d529d8c7d7c4d7bc4fefc9f109393b9245.tar.xz rustc-3e3e70d529d8c7d7c4d7bc4fefc9f109393b9245.zip |
Merging upstream version 1.69.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_session')
-rw-r--r-- | compiler/rustc_session/locales/en-US.ftl | 95 | ||||
-rw-r--r-- | compiler/rustc_session/src/code_stats.rs | 32 | ||||
-rw-r--r-- | compiler/rustc_session/src/config.rs | 92 | ||||
-rw-r--r-- | compiler/rustc_session/src/cstore.rs | 14 | ||||
-rw-r--r-- | compiler/rustc_session/src/errors.rs | 40 | ||||
-rw-r--r-- | compiler/rustc_session/src/filesearch.rs | 14 | ||||
-rw-r--r-- | compiler/rustc_session/src/lib.rs | 5 | ||||
-rw-r--r-- | compiler/rustc_session/src/options.rs | 124 | ||||
-rw-r--r-- | compiler/rustc_session/src/parse.rs | 12 | ||||
-rw-r--r-- | compiler/rustc_session/src/session.rs | 128 |
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) |