diff options
| author | Tshepang Mbambo <tshepang@gmail.com> | 2025-04-19 16:06:07 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-04-19 16:06:07 +0200 |
| commit | b886a8e654ab660f2f2cd02c68bf170dd4918fd8 (patch) | |
| tree | 86e6a9ab8518740ca6ce8deae8f409ee9c309f20 /compiler/rustc_session/src | |
| parent | 52616fa902a9a551ba4e574bee41dbf6162746f4 (diff) | |
| parent | 07b7f00a9e961fdf66ece2ecf70ae1dba505f10e (diff) | |
Merge pull request #2347 from rust-lang/rustc-pull
Rustc pull update
Diffstat (limited to 'compiler/rustc_session/src')
| -rw-r--r-- | compiler/rustc_session/src/code_stats.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_session/src/config.rs | 153 | ||||
| -rw-r--r-- | compiler/rustc_session/src/config/externs.rs | 79 | ||||
| -rw-r--r-- | compiler/rustc_session/src/config/externs/tests.rs | 92 | ||||
| -rw-r--r-- | compiler/rustc_session/src/options.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_session/src/output.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_session/src/session.rs | 27 |
7 files changed, 286 insertions, 79 deletions
diff --git a/compiler/rustc_session/src/code_stats.rs b/compiler/rustc_session/src/code_stats.rs index b4597ae2515..6b18d450e9e 100644 --- a/compiler/rustc_session/src/code_stats.rs +++ b/compiler/rustc_session/src/code_stats.rs @@ -72,7 +72,7 @@ pub struct TypeSizeInfo { #[derive(Default)] pub struct CodeStats { - type_sizes: Lock<FxHashSet<TypeSizeInfo>>, + pub type_sizes: Lock<FxHashSet<TypeSizeInfo>>, } impl CodeStats { diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 56b3fe2ab4c..ff7ea5bd718 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -14,6 +14,7 @@ use std::str::{self, FromStr}; use std::sync::LazyLock; use std::{cmp, fmt, fs, iter}; +use externs::{ExternOpt, split_extern_opt}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::stable_hasher::{StableOrd, ToStableHashKey}; use rustc_errors::emitter::HumanReadableErrorType; @@ -39,6 +40,7 @@ use crate::utils::CanonicalizedPath; use crate::{EarlyDiagCtxt, HashStableContext, Session, filesearch, lint}; mod cfg; +mod externs; mod native_libs; pub mod sigpipe; @@ -1015,11 +1017,14 @@ impl OutFileName { &self, outputs: &OutputFilenames, flavor: OutputType, - codegen_unit_name: Option<&str>, + codegen_unit_name: &str, + invocation_temp: Option<&str>, ) -> PathBuf { match *self { OutFileName::Real(ref path) => path.clone(), - OutFileName::Stdout => outputs.temp_path(flavor, codegen_unit_name), + OutFileName::Stdout => { + outputs.temp_path_for_cgu(flavor, codegen_unit_name, invocation_temp) + } } } @@ -1094,40 +1099,59 @@ impl OutputFilenames { /// Gets the path where a compilation artifact of the given type for the /// given codegen unit should be placed on disk. If codegen_unit_name is /// None, a path distinct from those of any codegen unit will be generated. - pub fn temp_path(&self, flavor: OutputType, codegen_unit_name: Option<&str>) -> PathBuf { + pub fn temp_path_for_cgu( + &self, + flavor: OutputType, + codegen_unit_name: &str, + invocation_temp: Option<&str>, + ) -> PathBuf { let extension = flavor.extension(); - self.temp_path_ext(extension, codegen_unit_name) + self.temp_path_ext_for_cgu(extension, codegen_unit_name, invocation_temp) } /// Like `temp_path`, but specifically for dwarf objects. - pub fn temp_path_dwo(&self, codegen_unit_name: Option<&str>) -> PathBuf { - self.temp_path_ext(DWARF_OBJECT_EXT, codegen_unit_name) + pub fn temp_path_dwo_for_cgu( + &self, + codegen_unit_name: &str, + invocation_temp: Option<&str>, + ) -> PathBuf { + self.temp_path_ext_for_cgu(DWARF_OBJECT_EXT, codegen_unit_name, invocation_temp) } /// Like `temp_path`, but also supports things where there is no corresponding /// OutputType, like noopt-bitcode or lto-bitcode. - pub fn temp_path_ext(&self, ext: &str, codegen_unit_name: Option<&str>) -> PathBuf { - let mut extension = String::new(); + pub fn temp_path_ext_for_cgu( + &self, + ext: &str, + codegen_unit_name: &str, + invocation_temp: Option<&str>, + ) -> PathBuf { + let mut extension = codegen_unit_name.to_string(); - if let Some(codegen_unit_name) = codegen_unit_name { - extension.push_str(codegen_unit_name); + // Append `.{invocation_temp}` to ensure temporary files are unique. + if let Some(rng) = invocation_temp { + extension.push('.'); + extension.push_str(rng); } + // FIXME: This is sketchy that we're not appending `.rcgu` when the ext is empty. + // Append `.rcgu.{ext}`. if !ext.is_empty() { - if !extension.is_empty() { - extension.push('.'); - extension.push_str(RUST_CGU_EXT); - extension.push('.'); - } - + extension.push('.'); + extension.push_str(RUST_CGU_EXT); + extension.push('.'); extension.push_str(ext); } let temps_directory = self.temps_directory.as_ref().unwrap_or(&self.out_directory); - self.with_directory_and_extension(temps_directory, &extension) } + pub fn temp_path_for_diagnostic(&self, ext: &str) -> PathBuf { + let temps_directory = self.temps_directory.as_ref().unwrap_or(&self.out_directory); + self.with_directory_and_extension(temps_directory, &ext) + } + pub fn with_extension(&self, extension: &str) -> PathBuf { self.with_directory_and_extension(&self.out_directory, extension) } @@ -1144,10 +1168,11 @@ impl OutputFilenames { &self, split_debuginfo_kind: SplitDebuginfo, split_dwarf_kind: SplitDwarfKind, - cgu_name: Option<&str>, + cgu_name: &str, + invocation_temp: Option<&str>, ) -> Option<PathBuf> { - let obj_out = self.temp_path(OutputType::Object, cgu_name); - let dwo_out = self.temp_path_dwo(cgu_name); + let obj_out = self.temp_path_for_cgu(OutputType::Object, cgu_name, invocation_temp); + let dwo_out = self.temp_path_dwo_for_cgu(cgu_name, invocation_temp); match (split_debuginfo_kind, split_dwarf_kind) { (SplitDebuginfo::Off, SplitDwarfKind::Single | SplitDwarfKind::Split) => None, // Single mode doesn't change how DWARF is emitted, but does add Split DWARF attributes @@ -1537,9 +1562,10 @@ The default is {DEFAULT_EDITION} and the latest stable edition is {LATEST_STABLE ) }); -static PRINT_KINDS_STRING: LazyLock<String> = LazyLock::new(|| { +static PRINT_HELP: LazyLock<String> = LazyLock::new(|| { format!( - "[{}]", + "Compiler information to print on stdout (or to a file)\n\ + INFO may be one of ({}).", PRINT_KINDS.iter().map(|(name, _)| format!("{name}")).collect::<Vec<_>>().join("|") ) }); @@ -1598,14 +1624,7 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> { "Comma separated list of types of output for the compiler to emit", "[asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir]", ), - opt( - Stable, - Multi, - "", - "print", - "Compiler information to print on stdout", - &PRINT_KINDS_STRING, - ), + opt(Stable, Multi, "", "print", &PRINT_HELP, "INFO[=FILE]"), opt(Stable, FlagMulti, "g", "", "Equivalent to -C debuginfo=2", ""), opt(Stable, FlagMulti, "O", "", "Equivalent to -C opt-level=3", ""), opt(Stable, Opt, "o", "", "Write output to <filename>", "FILENAME"), @@ -2046,7 +2065,8 @@ fn collect_print_requests( check_print_request_stability(early_dcx, unstable_opts, (print_name, *print_kind)); *print_kind } else { - emit_unknown_print_request_help(early_dcx, req) + let is_nightly = nightly_options::match_is_nightly_build(matches); + emit_unknown_print_request_help(early_dcx, req, is_nightly) }; let out = out.unwrap_or(OutFileName::Stdout); @@ -2070,25 +2090,37 @@ fn check_print_request_stability( unstable_opts: &UnstableOptions, (print_name, print_kind): (&str, PrintKind), ) { + if !is_print_request_stable(print_kind) && !unstable_opts.unstable_options { + early_dcx.early_fatal(format!( + "the `-Z unstable-options` flag must also be passed to enable the `{print_name}` \ + print option" + )); + } +} + +fn is_print_request_stable(print_kind: PrintKind) -> bool { match print_kind { PrintKind::AllTargetSpecsJson | PrintKind::CheckCfg | PrintKind::CrateRootLintLevels | PrintKind::SupportedCrateTypes - | PrintKind::TargetSpecJson - if !unstable_opts.unstable_options => - { - early_dcx.early_fatal(format!( - "the `-Z unstable-options` flag must also be passed to enable the `{print_name}` \ - print option" - )); - } - _ => {} + | PrintKind::TargetSpecJson => false, + _ => true, } } -fn emit_unknown_print_request_help(early_dcx: &EarlyDiagCtxt, req: &str) -> ! { - let prints = PRINT_KINDS.iter().map(|(name, _)| format!("`{name}`")).collect::<Vec<_>>(); +fn emit_unknown_print_request_help(early_dcx: &EarlyDiagCtxt, req: &str, is_nightly: bool) -> ! { + let prints = PRINT_KINDS + .iter() + .filter_map(|(name, kind)| { + // If we're not on nightly, we don't want to print unstable options + if !is_nightly && !is_print_request_stable(*kind) { + None + } else { + Some(format!("`{name}`")) + } + }) + .collect::<Vec<_>>(); let prints = prints.join(", "); let mut diag = early_dcx.early_struct_fatal(format!("unknown print request: `{req}`")); @@ -2188,44 +2220,13 @@ pub fn parse_externs( matches: &getopts::Matches, unstable_opts: &UnstableOptions, ) -> Externs { - fn is_ascii_ident(string: &str) -> bool { - let mut chars = string.chars(); - if let Some(start) = chars.next() - && (start.is_ascii_alphabetic() || start == '_') - { - chars.all(|char| char.is_ascii_alphanumeric() || char == '_') - } else { - false - } - } - let is_unstable_enabled = unstable_opts.unstable_options; let mut externs: BTreeMap<String, ExternEntry> = BTreeMap::new(); for arg in matches.opt_strs("extern") { - let (name, path) = match arg.split_once('=') { - None => (arg, None), - Some((name, path)) => (name.to_string(), Some(Path::new(path))), - }; - let (options, name) = match name.split_once(':') { - None => (None, name), - Some((opts, name)) => (Some(opts), name.to_string()), - }; - - if !is_ascii_ident(&name) { - let mut error = early_dcx.early_struct_fatal(format!( - "crate name `{name}` passed to `--extern` is not a valid ASCII identifier" - )); - let adjusted_name = name.replace('-', "_"); - if is_ascii_ident(&adjusted_name) { - #[allow(rustc::diagnostic_outside_of_impl)] // FIXME - error.help(format!( - "consider replacing the dashes with underscores: `{adjusted_name}`" - )); - } - error.emit(); - } + let ExternOpt { crate_name: name, path, options } = + split_extern_opt(early_dcx, unstable_opts, &arg).unwrap_or_else(|e| e.emit()); - let path = path.map(|p| CanonicalizedPath::new(p)); + let path = path.map(|p| CanonicalizedPath::new(p.as_path())); let entry = externs.entry(name.to_owned()); diff --git a/compiler/rustc_session/src/config/externs.rs b/compiler/rustc_session/src/config/externs.rs new file mode 100644 index 00000000000..1420ee38bf2 --- /dev/null +++ b/compiler/rustc_session/src/config/externs.rs @@ -0,0 +1,79 @@ +//! This module contains code to help parse and manipulate `--extern` arguments. + +use std::path::PathBuf; + +use rustc_errors::{Diag, FatalAbort}; + +use super::UnstableOptions; +use crate::EarlyDiagCtxt; + +#[cfg(test)] +mod tests; + +/// Represents the pieces of an `--extern` argument. +pub(crate) struct ExternOpt { + pub(crate) crate_name: String, + pub(crate) path: Option<PathBuf>, + pub(crate) options: Option<String>, +} + +/// Breaks out the major components of an `--extern` argument. +/// +/// The options field will be a string containing comma-separated options that will need further +/// parsing and processing. +pub(crate) fn split_extern_opt<'a>( + early_dcx: &'a EarlyDiagCtxt, + unstable_opts: &UnstableOptions, + extern_opt: &str, +) -> Result<ExternOpt, Diag<'a, FatalAbort>> { + let (name, path) = match extern_opt.split_once('=') { + None => (extern_opt.to_string(), None), + Some((name, path)) => (name.to_string(), Some(PathBuf::from(path))), + }; + let (options, crate_name) = match name.split_once(':') { + None => (None, name), + Some((opts, crate_name)) => { + if unstable_opts.namespaced_crates && crate_name.starts_with(':') { + // If the name starts with `:`, we know this was actually something like `foo::bar` and + // not a set of options. We can just use the original name as the crate name. + (None, name) + } else { + (Some(opts.to_string()), crate_name.to_string()) + } + } + }; + + if !valid_crate_name(&crate_name, unstable_opts) { + let mut error = early_dcx.early_struct_fatal(format!( + "crate name `{crate_name}` passed to `--extern` is not a valid ASCII identifier" + )); + let adjusted_name = crate_name.replace('-', "_"); + if is_ascii_ident(&adjusted_name) { + #[allow(rustc::diagnostic_outside_of_impl)] // FIXME + error + .help(format!("consider replacing the dashes with underscores: `{adjusted_name}`")); + } + return Err(error); + } + + Ok(ExternOpt { crate_name, path, options }) +} + +fn valid_crate_name(name: &str, unstable_opts: &UnstableOptions) -> bool { + match name.split_once("::") { + Some((a, b)) if unstable_opts.namespaced_crates => is_ascii_ident(a) && is_ascii_ident(b), + Some(_) => false, + None => is_ascii_ident(name), + } +} + +fn is_ascii_ident(string: &str) -> bool { + let mut chars = string.chars(); + if let Some(start) = chars.next() + && (start.is_ascii_alphabetic() || start == '_') + { + chars.all(|char| char.is_ascii_alphanumeric() || char == '_') + } else { + false + } +} diff --git a/compiler/rustc_session/src/config/externs/tests.rs b/compiler/rustc_session/src/config/externs/tests.rs new file mode 100644 index 00000000000..65448869515 --- /dev/null +++ b/compiler/rustc_session/src/config/externs/tests.rs @@ -0,0 +1,92 @@ +use std::path::PathBuf; + +use super::split_extern_opt; +use crate::EarlyDiagCtxt; +use crate::config::UnstableOptions; + +/// Verifies split_extern_opt handles the supported cases. +#[test] +fn test_split_extern_opt() { + let early_dcx = EarlyDiagCtxt::new(<_>::default()); + let unstable_opts = &UnstableOptions::default(); + + let extern_opt = + split_extern_opt(&early_dcx, unstable_opts, "priv,noprelude:foo=libbar.rlib").unwrap(); + assert_eq!(extern_opt.crate_name, "foo"); + assert_eq!(extern_opt.path, Some(PathBuf::from("libbar.rlib"))); + assert_eq!(extern_opt.options, Some("priv,noprelude".to_string())); + + let extern_opt = split_extern_opt(&early_dcx, unstable_opts, "priv,noprelude:foo").unwrap(); + assert_eq!(extern_opt.crate_name, "foo"); + assert_eq!(extern_opt.path, None); + assert_eq!(extern_opt.options, Some("priv,noprelude".to_string())); + + let extern_opt = split_extern_opt(&early_dcx, unstable_opts, "foo=libbar.rlib").unwrap(); + assert_eq!(extern_opt.crate_name, "foo"); + assert_eq!(extern_opt.path, Some(PathBuf::from("libbar.rlib"))); + assert_eq!(extern_opt.options, None); + + let extern_opt = split_extern_opt(&early_dcx, unstable_opts, "foo").unwrap(); + assert_eq!(extern_opt.crate_name, "foo"); + assert_eq!(extern_opt.path, None); + assert_eq!(extern_opt.options, None); +} + +/// Tests some invalid cases for split_extern_opt. +#[test] +fn test_split_extern_opt_invalid() { + let early_dcx = EarlyDiagCtxt::new(<_>::default()); + let unstable_opts = &UnstableOptions::default(); + + // too many `:`s + let result = split_extern_opt(&early_dcx, unstable_opts, "priv:noprelude:foo=libbar.rlib"); + assert!(result.is_err()); + let _ = result.map_err(|e| e.cancel()); + + // can't nest externs without the unstable flag + let result = split_extern_opt(&early_dcx, unstable_opts, "noprelude:foo::bar=libbar.rlib"); + assert!(result.is_err()); + let _ = result.map_err(|e| e.cancel()); +} + +/// Tests some cases for split_extern_opt with nested crates like `foo::bar`. +#[test] +fn test_split_extern_opt_nested() { + let early_dcx = EarlyDiagCtxt::new(<_>::default()); + let unstable_opts = &UnstableOptions { namespaced_crates: true, ..Default::default() }; + + let extern_opt = + split_extern_opt(&early_dcx, unstable_opts, "priv,noprelude:foo::bar=libbar.rlib").unwrap(); + assert_eq!(extern_opt.crate_name, "foo::bar"); + assert_eq!(extern_opt.path, Some(PathBuf::from("libbar.rlib"))); + assert_eq!(extern_opt.options, Some("priv,noprelude".to_string())); + + let extern_opt = + split_extern_opt(&early_dcx, unstable_opts, "priv,noprelude:foo::bar").unwrap(); + assert_eq!(extern_opt.crate_name, "foo::bar"); + assert_eq!(extern_opt.path, None); + assert_eq!(extern_opt.options, Some("priv,noprelude".to_string())); + + let extern_opt = split_extern_opt(&early_dcx, unstable_opts, "foo::bar=libbar.rlib").unwrap(); + assert_eq!(extern_opt.crate_name, "foo::bar"); + assert_eq!(extern_opt.path, Some(PathBuf::from("libbar.rlib"))); + assert_eq!(extern_opt.options, None); + + let extern_opt = split_extern_opt(&early_dcx, unstable_opts, "foo::bar").unwrap(); + assert_eq!(extern_opt.crate_name, "foo::bar"); + assert_eq!(extern_opt.path, None); + assert_eq!(extern_opt.options, None); +} + +/// Tests some invalid cases for split_extern_opt with nested crates like `foo::bar`. +#[test] +fn test_split_extern_opt_nested_invalid() { + let early_dcx = EarlyDiagCtxt::new(<_>::default()); + let unstable_opts = &UnstableOptions { namespaced_crates: true, ..Default::default() }; + + // crates can only be nested one deep. + let result = + split_extern_opt(&early_dcx, unstable_opts, "priv,noprelude:foo::bar::baz=libbar.rlib"); + assert!(result.is_err()); + let _ = result.map_err(|e| e.cancel()); +} diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index c70f1500d39..1b0794f79d3 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1956,6 +1956,9 @@ options! { "allow the linker to link its default libraries (default: no)"), dlltool: Option<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED], "import library generation tool (ignored except when targeting windows-gnu)"), + #[rustc_lint_opt_deny_field_access("use `Session::dwarf_version` instead of this field")] + dwarf_version: Option<u32> = (None, parse_opt_number, [TRACKED], + "version of DWARF debug information to emit (default: 2 or 4, depending on platform)"), embed_bitcode: bool = (true, parse_bool, [TRACKED], "emit bitcode in rlibs (default: yes)"), extra_filename: String = (String::new(), parse_string, [UNTRACKED], @@ -2331,6 +2334,8 @@ options! { "the size at which the `large_assignments` lint starts to be emitted"), mutable_noalias: bool = (true, parse_bool, [TRACKED], "emit noalias metadata for mutable references (default: yes)"), + namespaced_crates: bool = (false, parse_bool, [TRACKED], + "allow crates to be namespaced by other crates (default: no)"), next_solver: NextSolverConfig = (NextSolverConfig::default(), parse_next_solver_config, [TRACKED], "enable and configure the next generation trait solver used by rustc"), nll_facts: bool = (false, parse_bool, [UNTRACKED], diff --git a/compiler/rustc_session/src/output.rs b/compiler/rustc_session/src/output.rs index a24919e434c..46dae9144cd 100644 --- a/compiler/rustc_session/src/output.rs +++ b/compiler/rustc_session/src/output.rs @@ -177,6 +177,13 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<C // If we're generating a test executable, then ignore all other output // styles at all other locations if session.opts.test { + if !session.target.executables { + session.dcx().emit_warn(errors::UnsupportedCrateTypeForTarget { + crate_type: CrateType::Executable, + target_triple: &session.opts.target_triple, + }); + return Vec::new(); + } return vec![CrateType::Executable]; } diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index fb4a437a487..010ae42c280 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -6,6 +6,8 @@ use std::sync::Arc; use std::sync::atomic::AtomicBool; use std::{env, fmt, io}; +use rand::{RngCore, rng}; +use rustc_data_structures::base_n::{CASE_INSENSITIVE, ToBaseN}; use rustc_data_structures::flock; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_data_structures::profiling::{SelfProfiler, SelfProfilerRef}; @@ -203,6 +205,14 @@ pub struct Session { target_filesearch: FileSearch, host_filesearch: FileSearch, + + /// A random string generated per invocation of rustc. + /// + /// This is prepended to all temporary files so that they do not collide + /// during concurrent invocations of rustc, or past invocations that were + /// preserved with a flag like `-C save-temps`, since these files may be + /// hard linked. + pub invocation_temp: Option<String>, } #[derive(PartialEq, Eq, PartialOrd, Ord)] @@ -754,7 +764,11 @@ impl Session { /// Returns the DWARF version passed on the CLI or the default for the target. pub fn dwarf_version(&self) -> u32 { - self.opts.unstable_opts.dwarf_version.unwrap_or(self.target.default_dwarf_version) + self.opts + .cg + .dwarf_version + .or(self.opts.unstable_opts.dwarf_version) + .unwrap_or(self.target.default_dwarf_version) } pub fn stack_protector(&self) -> StackProtector { @@ -1117,6 +1131,12 @@ pub fn build_session( let target_filesearch = filesearch::FileSearch::new(&sopts.search_paths, &target_tlib_path, &target); let host_filesearch = filesearch::FileSearch::new(&sopts.search_paths, &host_tlib_path, &host); + + let invocation_temp = sopts + .incremental + .as_ref() + .map(|_| rng().next_u32().to_base_fixed_len(CASE_INSENSITIVE).to_string()); + let sess = Session { target, host, @@ -1140,6 +1160,7 @@ pub fn build_session( expanded_args, target_filesearch, host_filesearch, + invocation_temp, }; validate_commandline_args_with_session_available(&sess); @@ -1310,7 +1331,9 @@ fn validate_commandline_args_with_session_available(sess: &Session) { sess.dcx().emit_err(errors::BranchProtectionRequiresAArch64); } - if let Some(dwarf_version) = sess.opts.unstable_opts.dwarf_version { + if let Some(dwarf_version) = + sess.opts.cg.dwarf_version.or(sess.opts.unstable_opts.dwarf_version) + { // DWARF 1 is not supported by LLVM and DWARF 6 is not yet finalized. if dwarf_version < 2 || dwarf_version > 5 { sess.dcx().emit_err(errors::UnsupportedDwarfVersion { dwarf_version }); |
