summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_session
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_session')
-rw-r--r--compiler/rustc_session/Cargo.toml8
-rw-r--r--compiler/rustc_session/src/cgu_reuse_tracker.rs2
-rw-r--r--compiler/rustc_session/src/config.rs110
-rw-r--r--compiler/rustc_session/src/errors.rs166
-rw-r--r--compiler/rustc_session/src/filesearch.rs136
-rw-r--r--compiler/rustc_session/src/options.rs9
-rw-r--r--compiler/rustc_session/src/output.rs29
-rw-r--r--compiler/rustc_session/src/parse.rs6
-rw-r--r--compiler/rustc_session/src/session.rs81
9 files changed, 449 insertions, 98 deletions
diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml
index 6b1eaa4d3..cbbba2252 100644
--- a/compiler/rustc_session/Cargo.toml
+++ b/compiler/rustc_session/Cargo.toml
@@ -17,3 +17,11 @@ rustc_span = { path = "../rustc_span" }
rustc_fs_util = { path = "../rustc_fs_util" }
rustc_ast = { path = "../rustc_ast" }
rustc_lint_defs = { path = "../rustc_lint_defs" }
+smallvec = "1.8.1"
+termize = "0.1.1"
+
+[target.'cfg(unix)'.dependencies]
+libc = "0.2"
+
+[target.'cfg(windows)'.dependencies]
+winapi = { version = "0.3", features = ["libloaderapi"] }
diff --git a/compiler/rustc_session/src/cgu_reuse_tracker.rs b/compiler/rustc_session/src/cgu_reuse_tracker.rs
index 2336d9936..8703e5754 100644
--- a/compiler/rustc_session/src/cgu_reuse_tracker.rs
+++ b/compiler/rustc_session/src/cgu_reuse_tracker.rs
@@ -121,7 +121,7 @@ impl CguReuseTracker {
let at_least = if at_least { 1 } else { 0 };
IncorrectCguReuseType {
span: error_span.0,
- cgu_user_name: &cgu_user_name,
+ cgu_user_name,
actual_reuse,
expected_reuse,
at_least,
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index f2ee52262..7a20100fd 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -10,8 +10,8 @@ use crate::{lint, HashStableContext};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_data_structures::stable_hasher::ToStableHashKey;
-use rustc_target::abi::{Align, TargetDataLayout};
+use rustc_data_structures::stable_hasher::{StableOrd, ToStableHashKey};
+use rustc_target::abi::Align;
use rustc_target::spec::{PanicStrategy, SanitizerSet, SplitDebuginfo};
use rustc_target::spec::{Target, TargetTriple, TargetWarnings, TARGETS};
@@ -288,6 +288,9 @@ pub enum OutputType {
DepInfo,
}
+// Safety: Trivial C-Style enums have a stable sort order across compilation sessions.
+unsafe impl StableOrd for OutputType {}
+
impl<HCX: HashStableContext> ToStableHashKey<HCX> for OutputType {
type KeyType = Self;
@@ -548,6 +551,7 @@ pub enum PrintRequest {
NativeStaticLibs,
StackProtectorStrategies,
LinkArgs,
+ SplitDebuginfo,
}
pub enum Input {
@@ -621,7 +625,7 @@ impl OutputFilenames {
/// should be placed on disk.
pub fn output_path(&self, flavor: OutputType) -> PathBuf {
let extension = flavor.extension();
- self.with_directory_and_extension(&self.out_directory, &extension)
+ self.with_directory_and_extension(&self.out_directory, extension)
}
/// Gets the path where a compilation artifact of the given type for the
@@ -658,7 +662,7 @@ impl OutputFilenames {
let temps_directory = self.temps_directory.as_ref().unwrap_or(&self.out_directory);
- self.with_directory_and_extension(&temps_directory, &extension)
+ self.with_directory_and_extension(temps_directory, &extension)
}
pub fn with_extension(&self, extension: &str) -> PathBuf {
@@ -738,7 +742,7 @@ impl Default for Options {
actually_rustdoc: false,
trimmed_def_paths: TrimmedDefPaths::default(),
cli_forced_codegen_units: None,
- cli_forced_thinlto_off: false,
+ cli_forced_local_thinlto_off: false,
remap_path_prefix: Vec::new(),
real_rust_source_base_dir: None,
edition: DEFAULT_EDITION,
@@ -794,6 +798,7 @@ impl UnstableOptions {
report_delayed_bugs: self.report_delayed_bugs,
macro_backtrace: self.macro_backtrace,
deduplicate_diagnostics: self.deduplicate_diagnostics,
+ track_diagnostics: self.track_diagnostics,
}
}
}
@@ -898,7 +903,7 @@ fn default_configuration(sess: &Session) -> CrateConfig {
let min_atomic_width = sess.target.min_atomic_width();
let max_atomic_width = sess.target.max_atomic_width();
let atomic_cas = sess.target.atomic_cas;
- let layout = TargetDataLayout::parse(&sess.target).unwrap_or_else(|err| {
+ let layout = sess.target.parse_data_layout().unwrap_or_else(|err| {
sess.emit_fatal(err);
});
@@ -1157,7 +1162,7 @@ impl CrateCheckConfig {
values_target_family
.extend(target.options.families.iter().map(|family| Symbol::intern(family)));
values_target_arch.insert(Symbol::intern(&target.arch));
- values_target_endian.insert(Symbol::intern(&target.options.endian.as_str()));
+ values_target_endian.insert(Symbol::intern(target.options.endian.as_str()));
values_target_env.insert(Symbol::intern(&target.options.env));
values_target_abi.insert(Symbol::intern(&target.options.abi));
values_target_vendor.insert(Symbol::intern(&target.options.vendor));
@@ -1478,7 +1483,7 @@ pub fn get_cmd_lint_options(
/// Parses the `--color` flag.
pub fn parse_color(matches: &getopts::Matches) -> ColorConfig {
- match matches.opt_str("color").as_ref().map(|s| &s[..]) {
+ match matches.opt_str("color").as_deref() {
Some("auto") => ColorConfig::Auto,
Some("always") => ColorConfig::Always,
Some("never") => ColorConfig::Never,
@@ -1587,7 +1592,7 @@ pub fn parse_error_format(
// is unstable, it will not be present. We have to use `opts_present` not
// `opt_present` because the latter will panic.
let error_format = if matches.opts_present(&["error-format".to_owned()]) {
- match matches.opt_str("error-format").as_ref().map(|s| &s[..]) {
+ match matches.opt_str("error-format").as_deref() {
None | Some("human") => {
ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color))
}
@@ -1720,7 +1725,7 @@ fn should_override_cgus_and_disable_thinlto(
error_format: ErrorOutputType,
mut codegen_units: Option<usize>,
) -> (bool, Option<usize>) {
- let mut disable_thinlto = false;
+ let mut disable_local_thinlto = false;
// Issue #30063: if user requests LLVM-related output to one
// particular path, disable codegen-units.
let incompatible: Vec<_> = output_types
@@ -1745,12 +1750,12 @@ fn should_override_cgus_and_disable_thinlto(
}
early_warn(error_format, "resetting to default -C codegen-units=1");
codegen_units = Some(1);
- disable_thinlto = true;
+ disable_local_thinlto = true;
}
}
_ => {
codegen_units = Some(1);
- disable_thinlto = true;
+ disable_local_thinlto = true;
}
}
}
@@ -1759,7 +1764,7 @@ fn should_override_cgus_and_disable_thinlto(
early_error(error_format, "value for codegen units must be a positive non-zero integer");
}
- (disable_thinlto, codegen_units)
+ (disable_local_thinlto, codegen_units)
}
fn check_thread_count(unstable_opts: &UnstableOptions, error_format: ErrorOutputType) {
@@ -1788,34 +1793,50 @@ fn collect_print_requests(
cg.target_feature = String::new();
}
- prints.extend(matches.opt_strs("print").into_iter().map(|s| match &*s {
- "crate-name" => PrintRequest::CrateName,
- "file-names" => PrintRequest::FileNames,
- "sysroot" => PrintRequest::Sysroot,
- "target-libdir" => PrintRequest::TargetLibdir,
- "cfg" => PrintRequest::Cfg,
- "calling-conventions" => PrintRequest::CallingConventions,
- "target-list" => PrintRequest::TargetList,
- "target-cpus" => PrintRequest::TargetCPUs,
- "target-features" => PrintRequest::TargetFeatures,
- "relocation-models" => PrintRequest::RelocationModels,
- "code-models" => PrintRequest::CodeModels,
- "tls-models" => PrintRequest::TlsModels,
- "native-static-libs" => PrintRequest::NativeStaticLibs,
- "stack-protector-strategies" => PrintRequest::StackProtectorStrategies,
- "target-spec-json" => {
- if unstable_opts.unstable_options {
- PrintRequest::TargetSpec
- } else {
+ const PRINT_REQUESTS: &[(&str, PrintRequest)] = &[
+ ("crate-name", PrintRequest::CrateName),
+ ("file-names", PrintRequest::FileNames),
+ ("sysroot", PrintRequest::Sysroot),
+ ("target-libdir", PrintRequest::TargetLibdir),
+ ("cfg", PrintRequest::Cfg),
+ ("calling-conventions", PrintRequest::CallingConventions),
+ ("target-list", PrintRequest::TargetList),
+ ("target-cpus", PrintRequest::TargetCPUs),
+ ("target-features", PrintRequest::TargetFeatures),
+ ("relocation-models", PrintRequest::RelocationModels),
+ ("code-models", PrintRequest::CodeModels),
+ ("tls-models", PrintRequest::TlsModels),
+ ("native-static-libs", PrintRequest::NativeStaticLibs),
+ ("stack-protector-strategies", PrintRequest::StackProtectorStrategies),
+ ("target-spec-json", PrintRequest::TargetSpec),
+ ("link-args", PrintRequest::LinkArgs),
+ ("split-debuginfo", PrintRequest::SplitDebuginfo),
+ ];
+
+ prints.extend(matches.opt_strs("print").into_iter().map(|req| {
+ match PRINT_REQUESTS.iter().find(|&&(name, _)| name == req) {
+ Some((_, PrintRequest::TargetSpec)) => {
+ if unstable_opts.unstable_options {
+ PrintRequest::TargetSpec
+ } else {
+ early_error(
+ error_format,
+ "the `-Z unstable-options` flag must also be passed to \
+ enable the target-spec-json print option",
+ );
+ }
+ }
+ Some(&(_, print_request)) => print_request,
+ None => {
+ let prints =
+ PRINT_REQUESTS.iter().map(|(name, _)| format!("`{name}`")).collect::<Vec<_>>();
+ let prints = prints.join(", ");
early_error(
error_format,
- "the `-Z unstable-options` flag must also be passed to \
- enable the target-spec-json print option",
+ &format!("unknown print request `{req}`. Valid print requests are: {prints}"),
);
}
}
- "link-args" => PrintRequest::LinkArgs,
- req => early_error(error_format, &format!("unknown print request `{req}`")),
}));
prints
@@ -1828,7 +1849,7 @@ pub fn parse_target_triple(
match matches.opt_str("target") {
Some(target) if target.ends_with(".json") => {
let path = Path::new(&target);
- TargetTriple::from_path(&path).unwrap_or_else(|_| {
+ TargetTriple::from_path(path).unwrap_or_else(|_| {
early_error(error_format, &format!("target file {path:?} does not exist"))
})
}
@@ -1974,7 +1995,7 @@ fn parse_native_lib_modifiers(
) -> (NativeLibKind, Option<bool>) {
let mut verbatim = None;
for modifier in modifiers.split(',') {
- let (modifier, value) = match modifier.strip_prefix(&['+', '-']) {
+ let (modifier, value) = match modifier.strip_prefix(['+', '-']) {
Some(m) => (m, modifier.starts_with('+')),
None => early_error(
error_format,
@@ -2011,10 +2032,7 @@ fn parse_native_lib_modifiers(
"linking modifier `bundle` is only compatible with `static` linking kind",
),
- ("verbatim", _) => {
- report_unstable_modifier();
- assign_modifier(&mut verbatim)
- }
+ ("verbatim", _) => assign_modifier(&mut verbatim),
("whole-archive", NativeLibKind::Static { whole_archive, .. }) => {
assign_modifier(whole_archive)
@@ -2249,7 +2267,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
let output_types = parse_output_types(&unstable_opts, matches, error_format);
let mut cg = CodegenOptions::build(matches, error_format);
- let (disable_thinlto, mut codegen_units) = should_override_cgus_and_disable_thinlto(
+ let (disable_local_thinlto, mut codegen_units) = should_override_cgus_and_disable_thinlto(
&output_types,
matches,
error_format,
@@ -2406,7 +2424,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
let mut search_paths = vec![];
for s in &matches.opt_strs("L") {
- search_paths.push(SearchPath::from_cli_opt(&s, error_format));
+ search_paths.push(SearchPath::from_cli_opt(s, error_format));
}
let libs = parse_libs(matches, error_format);
@@ -2431,7 +2449,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
let sysroot = match &sysroot_opt {
Some(s) => s,
None => {
- tmp_buf = crate::filesearch::get_or_default_sysroot();
+ tmp_buf = crate::filesearch::get_or_default_sysroot().expect("Failed finding sysroot");
&tmp_buf
}
};
@@ -2492,7 +2510,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
actually_rustdoc: false,
trimmed_def_paths: TrimmedDefPaths::default(),
cli_forced_codegen_units: codegen_units,
- cli_forced_thinlto_off: disable_thinlto,
+ cli_forced_local_thinlto_off: disable_local_thinlto,
remap_path_prefix,
real_rust_source_base_dir,
edition,
diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs
index bf542faec..ee492f802 100644
--- a/compiler/rustc_session/src/errors.rs
+++ b/compiler/rustc_session/src/errors.rs
@@ -1,6 +1,9 @@
use std::num::NonZeroU32;
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_macros::Diagnostic;
use rustc_span::{Span, Symbol};
@@ -126,10 +129,10 @@ pub struct FileIsNotWriteable<'a> {
#[derive(Diagnostic)]
#[diag(session_crate_name_does_not_match)]
-pub struct CrateNameDoesNotMatch<'a> {
+pub struct CrateNameDoesNotMatch {
#[primary_span]
pub span: Span,
- pub s: &'a str,
+ pub s: Symbol,
pub name: Symbol,
}
@@ -148,11 +151,11 @@ pub struct CrateNameEmpty {
#[derive(Diagnostic)]
#[diag(session_invalid_character_in_create_name)]
-pub struct InvalidCharacterInCrateName<'a> {
+pub struct InvalidCharacterInCrateName {
#[primary_span]
pub span: Option<Span>,
pub character: char,
- pub crate_name: &'a str,
+ pub crate_name: Symbol,
}
#[derive(Subdiagnostic)]
@@ -191,3 +194,158 @@ pub enum UnleashedFeatureHelp {
span: Span,
},
}
+
+#[derive(Diagnostic)]
+#[diag(session_invalid_literal_suffix)]
+pub(crate) struct InvalidLiteralSuffix<'a> {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ // FIXME(#100717)
+ pub kind: &'a str,
+ pub suffix: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(session_invalid_int_literal_width)]
+#[help]
+pub(crate) struct InvalidIntLiteralWidth {
+ #[primary_span]
+ pub span: Span,
+ pub width: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(session_invalid_num_literal_base_prefix)]
+#[note]
+pub(crate) struct InvalidNumLiteralBasePrefix {
+ #[primary_span]
+ #[suggestion(applicability = "maybe-incorrect", code = "{fixed}")]
+ pub span: Span,
+ pub fixed: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(session_invalid_num_literal_suffix)]
+#[help]
+pub(crate) struct InvalidNumLiteralSuffix {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub suffix: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(session_invalid_float_literal_width)]
+#[help]
+pub(crate) struct InvalidFloatLiteralWidth {
+ #[primary_span]
+ pub span: Span,
+ pub width: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(session_invalid_float_literal_suffix)]
+#[help]
+pub(crate) struct InvalidFloatLiteralSuffix {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub suffix: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(session_int_literal_too_large)]
+pub(crate) struct IntLiteralTooLarge {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(session_hexadecimal_float_literal_not_supported)]
+pub(crate) struct HexadecimalFloatLiteralNotSupported {
+ #[primary_span]
+ #[label(session_not_supported)]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(session_octal_float_literal_not_supported)]
+pub(crate) struct OctalFloatLiteralNotSupported {
+ #[primary_span]
+ #[label(session_not_supported)]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(session_binary_float_literal_not_supported)]
+pub(crate) struct BinaryFloatLiteralNotSupported {
+ #[primary_span]
+ #[label(session_not_supported)]
+ pub span: Span,
+}
+
+pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span: Span) {
+ // Checks if `s` looks like i32 or u1234 etc.
+ fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool {
+ s.len() > 1 && s.starts_with(first_chars) && s[1..].chars().all(|c| c.is_ascii_digit())
+ }
+
+ // Try to lowercase the prefix if it's a valid base prefix.
+ fn fix_base_capitalisation(s: &str) -> Option<String> {
+ if let Some(stripped) = s.strip_prefix('B') {
+ Some(format!("0b{stripped}"))
+ } else if let Some(stripped) = s.strip_prefix('O') {
+ Some(format!("0o{stripped}"))
+ } else if let Some(stripped) = s.strip_prefix('X') {
+ Some(format!("0x{stripped}"))
+ } else {
+ None
+ }
+ }
+
+ let token::Lit { kind, suffix, .. } = lit;
+ match err {
+ // `LexerError` is an error, but it was already reported
+ // by lexer, so here we don't report it the second time.
+ LitError::LexerError => {}
+ LitError::InvalidSuffix => {
+ if let Some(suffix) = suffix {
+ sess.emit_err(InvalidLiteralSuffix { span, kind: kind.descr(), suffix });
+ }
+ }
+ LitError::InvalidIntSuffix => {
+ let suf = suffix.expect("suffix error with no suffix");
+ let suf = suf.as_str();
+ if looks_like_width_suffix(&['i', 'u'], suf) {
+ // If it looks like a width, try to be helpful.
+ sess.emit_err(InvalidIntLiteralWidth { span, width: suf[1..].into() });
+ } else if let Some(fixed) = fix_base_capitalisation(suf) {
+ sess.emit_err(InvalidNumLiteralBasePrefix { span, fixed });
+ } else {
+ sess.emit_err(InvalidNumLiteralSuffix { span, suffix: suf.to_string() });
+ }
+ }
+ LitError::InvalidFloatSuffix => {
+ let suf = suffix.expect("suffix error with no suffix");
+ let suf = suf.as_str();
+ if looks_like_width_suffix(&['f'], suf) {
+ // If it looks like a width, try to be helpful.
+ sess.emit_err(InvalidFloatLiteralWidth { span, width: suf[1..].to_string() });
+ } else {
+ sess.emit_err(InvalidFloatLiteralSuffix { span, suffix: suf.to_string() });
+ }
+ }
+ LitError::NonDecimalFloat(base) => {
+ match base {
+ 16 => sess.emit_err(HexadecimalFloatLiteralNotSupported { span }),
+ 8 => sess.emit_err(OctalFloatLiteralNotSupported { span }),
+ 2 => sess.emit_err(BinaryFloatLiteralNotSupported { span }),
+ _ => unreachable!(),
+ };
+ }
+ LitError::IntTooLarge => {
+ sess.emit_err(IntLiteralTooLarge { span });
+ }
+ }
+}
diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs
index e8edb38f5..1b66773be 100644
--- a/compiler/rustc_session/src/filesearch.rs
+++ b/compiler/rustc_session/src/filesearch.rs
@@ -1,5 +1,6 @@
//! A module for searching for libraries
+use smallvec::{smallvec, SmallVec};
use std::env;
use std::fs;
use std::iter::FromIterator;
@@ -62,9 +63,99 @@ pub fn make_target_lib_path(sysroot: &Path, target_triple: &str) -> PathBuf {
PathBuf::from_iter([sysroot, Path::new(&rustlib_path), Path::new("lib")])
}
+#[cfg(unix)]
+fn current_dll_path() -> Result<PathBuf, String> {
+ use std::ffi::{CStr, OsStr};
+ use std::os::unix::prelude::*;
+
+ unsafe {
+ let addr = current_dll_path as usize as *mut _;
+ let mut info = std::mem::zeroed();
+ if libc::dladdr(addr, &mut info) == 0 {
+ return Err("dladdr failed".into());
+ }
+ if info.dli_fname.is_null() {
+ return Err("dladdr returned null pointer".into());
+ }
+ let bytes = CStr::from_ptr(info.dli_fname).to_bytes();
+ let os = OsStr::from_bytes(bytes);
+ Ok(PathBuf::from(os))
+ }
+}
+
+#[cfg(windows)]
+fn current_dll_path() -> Result<PathBuf, String> {
+ use std::ffi::OsString;
+ use std::io;
+ use std::os::windows::prelude::*;
+ use std::ptr;
+
+ use winapi::um::libloaderapi::{
+ GetModuleFileNameW, GetModuleHandleExW, GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
+ };
+
+ unsafe {
+ let mut module = ptr::null_mut();
+ let r = GetModuleHandleExW(
+ GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
+ current_dll_path as usize as *mut _,
+ &mut module,
+ );
+ if r == 0 {
+ return Err(format!("GetModuleHandleExW failed: {}", io::Error::last_os_error()));
+ }
+ let mut space = Vec::with_capacity(1024);
+ let r = GetModuleFileNameW(module, space.as_mut_ptr(), space.capacity() as u32);
+ if r == 0 {
+ return Err(format!("GetModuleFileNameW failed: {}", io::Error::last_os_error()));
+ }
+ let r = r as usize;
+ if r >= space.capacity() {
+ return Err(format!("our buffer was too small? {}", io::Error::last_os_error()));
+ }
+ space.set_len(r);
+ let os = OsString::from_wide(&space);
+ Ok(PathBuf::from(os))
+ }
+}
+
+pub fn sysroot_candidates() -> SmallVec<[PathBuf; 2]> {
+ let target = crate::config::host_triple();
+ let mut sysroot_candidates: SmallVec<[PathBuf; 2]> =
+ smallvec![get_or_default_sysroot().expect("Failed finding sysroot")];
+ let path = current_dll_path().and_then(|s| Ok(s.canonicalize().map_err(|e| e.to_string())?));
+ if let Ok(dll) = path {
+ // use `parent` twice to chop off the file name and then also the
+ // directory containing the dll which should be either `lib` or `bin`.
+ if let Some(path) = dll.parent().and_then(|p| p.parent()) {
+ // The original `path` pointed at the `rustc_driver` crate's dll.
+ // Now that dll should only be in one of two locations. The first is
+ // in the compiler's libdir, for example `$sysroot/lib/*.dll`. The
+ // other is the target's libdir, for example
+ // `$sysroot/lib/rustlib/$target/lib/*.dll`.
+ //
+ // We don't know which, so let's assume that if our `path` above
+ // ends in `$target` we *could* be in the target libdir, and always
+ // assume that we may be in the main libdir.
+ sysroot_candidates.push(path.to_owned());
+
+ if path.ends_with(target) {
+ sysroot_candidates.extend(
+ path.parent() // chop off `$target`
+ .and_then(|p| p.parent()) // chop off `rustlib`
+ .and_then(|p| p.parent()) // chop off `lib`
+ .map(|s| s.to_owned()),
+ );
+ }
+ }
+ }
+
+ return sysroot_candidates;
+}
+
/// This function checks if sysroot is found using env::args().next(), and if it
-/// is not found, uses env::current_exe() to imply sysroot.
-pub fn get_or_default_sysroot() -> PathBuf {
+/// is not found, finds sysroot from current rustc_driver dll.
+pub fn get_or_default_sysroot() -> Result<PathBuf, String> {
// Follow symlinks. If the resolved path is relative, make it absolute.
fn canonicalize(path: PathBuf) -> PathBuf {
let path = fs::canonicalize(&path).unwrap_or(path);
@@ -74,17 +165,32 @@ pub fn get_or_default_sysroot() -> PathBuf {
fix_windows_verbatim_for_gcc(&path)
}
- // Use env::current_exe() to get the path of the executable following
- // symlinks/canonicalizing components.
- fn from_current_exe() -> PathBuf {
- match env::current_exe() {
- Ok(exe) => {
- let mut p = canonicalize(exe);
- p.pop();
- p.pop();
- p
- }
- Err(e) => panic!("failed to get current_exe: {e}"),
+ fn default_from_rustc_driver_dll() -> Result<PathBuf, String> {
+ let dll = current_dll_path().and_then(|s| Ok(canonicalize(s)))?;
+
+ // `dll` will be in one of the following two:
+ // - compiler's libdir: $sysroot/lib/*.dll
+ // - target's libdir: $sysroot/lib/rustlib/$target/lib/*.dll
+ //
+ // use `parent` twice to chop off the file name and then also the
+ // directory containing the dll
+ let dir = dll.parent().and_then(|p| p.parent()).ok_or(format!(
+ "Could not move 2 levels upper using `parent()` on {}",
+ dll.display()
+ ))?;
+
+ // if `dir` points target's dir, move up to the sysroot
+ 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`
+ .map(|s| s.to_owned())
+ .ok_or(format!(
+ "Could not move 3 levels upper using `parent()` on {}",
+ dir.display()
+ ))
+ } else {
+ Ok(dir.to_owned())
}
}
@@ -118,7 +224,5 @@ pub fn get_or_default_sysroot() -> PathBuf {
}
}
- // Check if sysroot is found using env::args().next(), and if is not found,
- // use env::current_exe() to imply sysroot.
- from_env_args_next().unwrap_or_else(from_current_exe)
+ Ok(from_env_args_next().unwrap_or(default_from_rustc_driver_dll()?))
}
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 3f234a47a..8e9198b79 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -181,7 +181,7 @@ top_level_options!(
#[rustc_lint_opt_deny_field_access("use `Session::codegen_units` instead of this field")]
cli_forced_codegen_units: Option<usize> [UNTRACKED],
#[rustc_lint_opt_deny_field_access("use `Session::lto` instead of this field")]
- cli_forced_thinlto_off: bool [UNTRACKED],
+ cli_forced_local_thinlto_off: bool [UNTRACKED],
/// Remap source path prefixes in all output (messages, object files, debug, etc.).
remap_path_prefix: Vec<(PathBuf, PathBuf)> [TRACKED_NO_CRATE_HASH],
@@ -1382,6 +1382,9 @@ options! {
"list the symbols defined by a library crate (default: no)"),
macro_backtrace: bool = (false, parse_bool, [UNTRACKED],
"show macro backtraces (default: no)"),
+ maximal_hir_to_mir_coverage: bool = (false, parse_bool, [TRACKED],
+ "save as much information as possible about the correspondence between MIR and HIR \
+ as source scopes (default: no)"),
merge_functions: Option<MergeFunctions> = (None, parse_merge_functions, [TRACKED],
"control the operation of the MergeFunctions LLVM pass, taking \
the same values as the target option of the same name"),
@@ -1414,8 +1417,6 @@ options! {
"run all passes except codegen; no output"),
no_generate_arange_section: bool = (false, parse_no_flag, [TRACKED],
"omit DWARF address ranges that give faster lookups"),
- no_interleave_lints: bool = (false, parse_no_flag, [UNTRACKED],
- "execute lints separately; allows benchmarking individual lints"),
no_leak_check: bool = (false, parse_no_flag, [UNTRACKED],
"disable the 'leak check' for subtyping; unsound, but useful for tests"),
no_link: bool = (false, parse_no_flag, [TRACKED],
@@ -1587,6 +1588,8 @@ options! {
"choose the TLS model to use (`rustc --print tls-models` for details)"),
trace_macros: bool = (false, parse_bool, [UNTRACKED],
"for every macro invocation, print its name and arguments (default: no)"),
+ track_diagnostics: bool = (false, parse_bool, [UNTRACKED],
+ "tracks where in rustc a diagnostic was emitted"),
// Diagnostics are considered side-effects of a query (see `QuerySideEffects`) and are saved
// alongside query results and changes to translation options can affect diagnostics - so
// translation options should be tracked.
diff --git a/compiler/rustc_session/src/output.rs b/compiler/rustc_session/src/output.rs
index 2511bee46..8ee3057de 100644
--- a/compiler/rustc_session/src/output.rs
+++ b/compiler/rustc_session/src/output.rs
@@ -7,14 +7,14 @@ use crate::errors::{
use crate::Session;
use rustc_ast as ast;
use rustc_span::symbol::sym;
-use rustc_span::Span;
+use rustc_span::{Span, Symbol};
use std::path::{Path, PathBuf};
pub fn out_filename(
sess: &Session,
crate_type: CrateType,
outputs: &OutputFilenames,
- crate_name: &str,
+ crate_name: Symbol,
) -> PathBuf {
let default_filename = filename_for_input(sess, crate_type, crate_name, outputs);
let out_filename = outputs
@@ -45,9 +45,9 @@ fn is_writeable(p: &Path) -> bool {
}
}
-pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute], input: &Input) -> String {
- let validate = |s: String, span: Option<Span>| {
- validate_crate_name(sess, &s, span);
+pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute], input: &Input) -> Symbol {
+ let validate = |s: Symbol, span: Option<Span>| {
+ validate_crate_name(sess, s, span);
s
};
@@ -59,38 +59,39 @@ pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute], input: &Input)
sess.find_by_name(attrs, sym::crate_name).and_then(|at| at.value_str().map(|s| (at, s)));
if let Some(ref s) = sess.opts.crate_name {
+ let s = Symbol::intern(s);
if let Some((attr, name)) = attr_crate_name {
- if name.as_str() != s {
+ if name != s {
sess.emit_err(CrateNameDoesNotMatch { span: attr.span, s, name });
}
}
- return validate(s.clone(), None);
+ return validate(s, None);
}
if let Some((attr, s)) = attr_crate_name {
- return validate(s.to_string(), Some(attr.span));
+ return validate(s, Some(attr.span));
}
if let Input::File(ref path) = *input {
if let Some(s) = path.file_stem().and_then(|s| s.to_str()) {
if s.starts_with('-') {
sess.emit_err(CrateNameInvalid { s });
} else {
- return validate(s.replace('-', "_"), None);
+ return validate(Symbol::intern(&s.replace('-', "_")), None);
}
}
}
- "rust_out".to_string()
+ Symbol::intern("rust_out")
}
-pub fn validate_crate_name(sess: &Session, s: &str, sp: Option<Span>) {
+pub fn validate_crate_name(sess: &Session, s: Symbol, sp: Option<Span>) {
let mut err_count = 0;
{
if s.is_empty() {
err_count += 1;
sess.emit_err(CrateNameEmpty { span: sp });
}
- for c in s.chars() {
+ for c in s.as_str().chars() {
if c.is_alphanumeric() {
continue;
}
@@ -109,7 +110,7 @@ pub fn validate_crate_name(sess: &Session, s: &str, sp: Option<Span>) {
pub fn filename_for_metadata(
sess: &Session,
- crate_name: &str,
+ crate_name: Symbol,
outputs: &OutputFilenames,
) -> PathBuf {
// If the command-line specified the path, use that directly.
@@ -132,7 +133,7 @@ pub fn filename_for_metadata(
pub fn filename_for_input(
sess: &Session,
crate_type: CrateType,
- crate_name: &str,
+ crate_name: Symbol,
outputs: &OutputFilenames,
) -> PathBuf {
let libname = format!("{}{}", crate_name, sess.opts.cg.extra_filename);
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index a199947eb..f9f4f2979 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -97,6 +97,7 @@ pub fn feature_err<'a>(
///
/// This variant allows you to control whether it is a library or language feature.
/// Almost always, you want to use this for a language feature. If so, prefer `feature_err`.
+#[track_caller]
pub fn feature_err_issue<'a>(
sess: &'a ParseSess,
feature: Symbol,
@@ -332,6 +333,7 @@ impl ParseSess {
self.proc_macro_quoted_spans.lock().clone()
}
+ #[track_caller]
pub fn create_err<'a>(
&'a self,
err: impl IntoDiagnostic<'a>,
@@ -339,10 +341,12 @@ impl ParseSess {
err.into_diagnostic(&self.span_diagnostic)
}
+ #[track_caller]
pub fn emit_err<'a>(&'a self, err: impl IntoDiagnostic<'a>) -> ErrorGuaranteed {
self.create_err(err).emit()
}
+ #[track_caller]
pub fn create_warning<'a>(
&'a self,
warning: impl IntoDiagnostic<'a, ()>,
@@ -350,6 +354,7 @@ impl ParseSess {
warning.into_diagnostic(&self.span_diagnostic)
}
+ #[track_caller]
pub fn emit_warning<'a>(&'a self, warning: impl IntoDiagnostic<'a, ()>) {
self.create_warning(warning).emit()
}
@@ -377,6 +382,7 @@ impl ParseSess {
}
#[rustc_lint_diagnostics]
+ #[track_caller]
pub fn struct_err(
&self,
msg: impl Into<DiagnosticMessage>,
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 100c66f63..4c049a8d6 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -286,6 +286,7 @@ impl Session {
}
#[rustc_lint_diagnostics]
+ #[track_caller]
pub fn struct_span_warn<S: Into<MultiSpan>>(
&self,
sp: S,
@@ -294,6 +295,7 @@ impl Session {
self.diagnostic().struct_span_warn(sp, msg)
}
#[rustc_lint_diagnostics]
+ #[track_caller]
pub fn struct_span_warn_with_expectation<S: Into<MultiSpan>>(
&self,
sp: S,
@@ -303,6 +305,7 @@ impl Session {
self.diagnostic().struct_span_warn_with_expectation(sp, msg, id)
}
#[rustc_lint_diagnostics]
+ #[track_caller]
pub fn struct_span_warn_with_code<S: Into<MultiSpan>>(
&self,
sp: S,
@@ -312,10 +315,12 @@ impl Session {
self.diagnostic().struct_span_warn_with_code(sp, msg, code)
}
#[rustc_lint_diagnostics]
+ #[track_caller]
pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
self.diagnostic().struct_warn(msg)
}
#[rustc_lint_diagnostics]
+ #[track_caller]
pub fn struct_warn_with_expectation(
&self,
msg: impl Into<DiagnosticMessage>,
@@ -324,6 +329,7 @@ impl Session {
self.diagnostic().struct_warn_with_expectation(msg, id)
}
#[rustc_lint_diagnostics]
+ #[track_caller]
pub fn struct_span_allow<S: Into<MultiSpan>>(
&self,
sp: S,
@@ -332,10 +338,12 @@ impl Session {
self.diagnostic().struct_span_allow(sp, msg)
}
#[rustc_lint_diagnostics]
+ #[track_caller]
pub fn struct_allow(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
self.diagnostic().struct_allow(msg)
}
#[rustc_lint_diagnostics]
+ #[track_caller]
pub fn struct_expect(
&self,
msg: impl Into<DiagnosticMessage>,
@@ -344,6 +352,7 @@ impl Session {
self.diagnostic().struct_expect(msg, id)
}
#[rustc_lint_diagnostics]
+ #[track_caller]
pub fn struct_span_err<S: Into<MultiSpan>>(
&self,
sp: S,
@@ -352,6 +361,7 @@ impl Session {
self.diagnostic().struct_span_err(sp, msg)
}
#[rustc_lint_diagnostics]
+ #[track_caller]
pub fn struct_span_err_with_code<S: Into<MultiSpan>>(
&self,
sp: S,
@@ -362,12 +372,14 @@ impl Session {
}
// FIXME: This method should be removed (every error should have an associated error code).
#[rustc_lint_diagnostics]
+ #[track_caller]
pub fn struct_err(
&self,
msg: impl Into<DiagnosticMessage>,
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
self.parse_sess.struct_err(msg)
}
+ #[track_caller]
#[rustc_lint_diagnostics]
pub fn struct_err_with_code(
&self,
@@ -377,6 +389,7 @@ impl Session {
self.diagnostic().struct_err_with_code(msg, code)
}
#[rustc_lint_diagnostics]
+ #[track_caller]
pub fn struct_warn_with_code(
&self,
msg: impl Into<DiagnosticMessage>,
@@ -385,6 +398,7 @@ impl Session {
self.diagnostic().struct_warn_with_code(msg, code)
}
#[rustc_lint_diagnostics]
+ #[track_caller]
pub fn struct_span_fatal<S: Into<MultiSpan>>(
&self,
sp: S,
@@ -407,6 +421,7 @@ impl Session {
}
#[rustc_lint_diagnostics]
+ #[track_caller]
pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) -> ! {
self.diagnostic().span_fatal(sp, msg)
}
@@ -424,6 +439,7 @@ impl Session {
self.diagnostic().fatal(msg).raise()
}
#[rustc_lint_diagnostics]
+ #[track_caller]
pub fn span_err_or_warn<S: Into<MultiSpan>>(
&self,
is_warning: bool,
@@ -437,6 +453,7 @@ impl Session {
}
}
#[rustc_lint_diagnostics]
+ #[track_caller]
pub fn span_err<S: Into<MultiSpan>>(
&self,
sp: S,
@@ -457,12 +474,14 @@ impl Session {
pub fn err(&self, msg: impl Into<DiagnosticMessage>) -> ErrorGuaranteed {
self.diagnostic().err(msg)
}
+ #[track_caller]
pub fn create_err<'a>(
&'a self,
err: impl IntoDiagnostic<'a>,
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
self.parse_sess.create_err(err)
}
+ #[track_caller]
pub fn create_feature_err<'a>(
&'a self,
err: impl IntoDiagnostic<'a>,
@@ -475,33 +494,40 @@ impl Session {
add_feature_diagnostics(&mut err, &self.parse_sess, feature);
err
}
+ #[track_caller]
pub fn emit_err<'a>(&'a self, err: impl IntoDiagnostic<'a>) -> ErrorGuaranteed {
self.parse_sess.emit_err(err)
}
+ #[track_caller]
pub fn create_warning<'a>(
&'a self,
err: impl IntoDiagnostic<'a, ()>,
) -> DiagnosticBuilder<'a, ()> {
self.parse_sess.create_warning(err)
}
+ #[track_caller]
pub fn emit_warning<'a>(&'a self, warning: impl IntoDiagnostic<'a, ()>) {
self.parse_sess.emit_warning(warning)
}
+ #[track_caller]
pub fn create_note<'a>(
&'a self,
note: impl IntoDiagnostic<'a, Noted>,
) -> DiagnosticBuilder<'a, Noted> {
self.parse_sess.create_note(note)
}
+ #[track_caller]
pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, Noted>) -> Noted {
self.parse_sess.emit_note(note)
}
+ #[track_caller]
pub fn create_fatal<'a>(
&'a self,
fatal: impl IntoDiagnostic<'a, !>,
) -> DiagnosticBuilder<'a, !> {
self.parse_sess.create_fatal(fatal)
}
+ #[track_caller]
pub fn emit_fatal<'a>(&'a self, fatal: impl IntoDiagnostic<'a, !>) -> ! {
self.parse_sess.emit_fatal(fatal)
}
@@ -512,9 +538,12 @@ impl Session {
pub fn has_errors(&self) -> Option<ErrorGuaranteed> {
self.diagnostic().has_errors()
}
- pub fn has_errors_or_delayed_span_bugs(&self) -> bool {
+ pub fn has_errors_or_delayed_span_bugs(&self) -> Option<ErrorGuaranteed> {
self.diagnostic().has_errors_or_delayed_span_bugs()
}
+ pub fn is_compilation_going_to_fail(&self) -> Option<ErrorGuaranteed> {
+ self.diagnostic().is_compilation_going_to_fail()
+ }
pub fn abort_if_errors(&self) {
self.diagnostic().abort_if_errors();
}
@@ -536,11 +565,15 @@ impl Session {
if self.err_count() == old_count {
Ok(result)
} else {
- Err(ErrorGuaranteed::unchecked_claim_error_was_emitted())
+ Err(self.delay_span_bug(
+ rustc_span::DUMMY_SP,
+ "`self.err_count()` changed but an error was not emitted",
+ ))
}
}
#[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)
}
@@ -587,6 +620,8 @@ impl Session {
pub fn note_without_error(&self, msg: impl Into<DiagnosticMessage>) {
self.diagnostic().note_without_error(msg)
}
+
+ #[track_caller]
pub fn span_note_without_error<S: Into<MultiSpan>>(
&self,
sp: S,
@@ -917,6 +952,17 @@ impl Session {
) -> Option<Symbol> {
attrs.iter().find(|at| at.has_name(name)).and_then(|at| at.value_str())
}
+
+ pub fn diagnostic_width(&self) -> usize {
+ let default_column_width = 140;
+ if let Some(width) = self.opts.diagnostic_width {
+ width
+ } else if self.opts.unstable_opts.ui_testing {
+ default_column_width
+ } else {
+ termize::dimensions().map_or(default_column_width, |(w, _)| w)
+ }
+ }
}
// JUSTIFICATION: defn of the suggested wrapper fns
@@ -989,11 +1035,8 @@ impl Session {
return config::Lto::Fat;
}
config::LtoCli::Thin => {
- return if self.opts.cli_forced_thinlto_off {
- config::Lto::Fat
- } else {
- config::Lto::Thin
- };
+ // The user explicitly asked for ThinLTO
+ return config::Lto::Thin;
}
}
@@ -1005,7 +1048,7 @@ impl Session {
// If processing command line options determined that we're incompatible
// with ThinLTO (e.g., `-C lto --emit llvm-ir`) then return that option.
- if self.opts.cli_forced_thinlto_off {
+ if self.opts.cli_forced_local_thinlto_off {
return config::Lto::No;
}
@@ -1213,6 +1256,7 @@ fn default_emitter(
fallback_bundle: LazyFallbackBundle,
) -> Box<dyn Emitter + sync::Send> {
let macro_backtrace = sopts.unstable_opts.macro_backtrace;
+ let track_diagnostics = sopts.unstable_opts.track_diagnostics;
match sopts.error_format {
config::ErrorOutputType::HumanReadable(kind) => {
let (short, color_config) = kind.unzip();
@@ -1236,6 +1280,7 @@ fn default_emitter(
sopts.unstable_opts.teach,
sopts.diagnostic_width,
macro_backtrace,
+ track_diagnostics,
);
Box::new(emitter.ui_testing(sopts.unstable_opts.ui_testing))
}
@@ -1250,6 +1295,7 @@ fn default_emitter(
json_rendered,
sopts.diagnostic_width,
macro_backtrace,
+ track_diagnostics,
)
.ui_testing(sopts.unstable_opts.ui_testing),
),
@@ -1280,7 +1326,7 @@ pub fn build_session(
let sysroot = match &sopts.maybe_sysroot {
Some(sysroot) => sysroot.clone(),
- None => filesearch::get_or_default_sysroot(),
+ None => filesearch::get_or_default_sysroot().expect("Failed finding sysroot"),
};
let target_cfg = config::build_target_config(&sopts, target_override, &sysroot);
@@ -1325,7 +1371,7 @@ pub fn build_session(
let profiler = SelfProfiler::new(
directory,
sopts.crate_name.as_deref(),
- sopts.unstable_opts.self_profile_events.as_ref().map(|xs| &xs[..]),
+ sopts.unstable_opts.self_profile_events.as_deref(),
&sopts.unstable_opts.self_profile_counter,
);
match profiler {
@@ -1359,7 +1405,7 @@ pub fn build_session(
local_crate_source_file.map(|path| file_path_mapping.map_prefix(path).0);
let optimization_fuel = Lock::new(OptimizationFuel {
- remaining: sopts.unstable_opts.fuel.as_ref().map_or(0, |i| i.1),
+ remaining: sopts.unstable_opts.fuel.as_ref().map_or(0, |&(_, i)| i),
out_of_fuel: false,
});
let print_fuel = AtomicU64::new(0);
@@ -1552,11 +1598,18 @@ fn early_error_handler(output: config::ErrorOutputType) -> rustc_errors::Handler
false,
None,
false,
+ false,
))
}
- config::ErrorOutputType::Json { pretty, json_rendered } => {
- Box::new(JsonEmitter::basic(pretty, json_rendered, None, fallback_bundle, None, false))
- }
+ config::ErrorOutputType::Json { pretty, json_rendered } => Box::new(JsonEmitter::basic(
+ pretty,
+ json_rendered,
+ None,
+ fallback_bundle,
+ None,
+ false,
+ false,
+ )),
};
rustc_errors::Handler::with_emitter(true, None, emitter)
}