summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_span/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_span/src')
-rw-r--r--compiler/rustc_span/src/analyze_source_file.rs8
-rw-r--r--compiler/rustc_span/src/fatal_error.rs8
-rw-r--r--compiler/rustc_span/src/hygiene.rs58
-rw-r--r--compiler/rustc_span/src/lib.rs81
-rw-r--r--compiler/rustc_span/src/source_map.rs84
-rw-r--r--compiler/rustc_span/src/source_map/tests.rs48
-rw-r--r--compiler/rustc_span/src/span_encoding.rs3
-rw-r--r--compiler/rustc_span/src/symbol.rs114
-rw-r--r--compiler/rustc_span/src/symbol/tests.rs2
9 files changed, 228 insertions, 178 deletions
diff --git a/compiler/rustc_span/src/analyze_source_file.rs b/compiler/rustc_span/src/analyze_source_file.rs
index 450d5455f..7da7dc610 100644
--- a/compiler/rustc_span/src/analyze_source_file.rs
+++ b/compiler/rustc_span/src/analyze_source_file.rs
@@ -33,8 +33,8 @@ pub fn analyze_source_file(
(lines, multi_byte_chars, non_narrow_chars)
}
-cfg_if::cfg_if! {
- if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
+cfg_match! {
+ cfg(any(target_arch = "x86", target_arch = "x86_64")) => {
fn analyze_source_file_dispatch(src: &str,
lines: &mut Vec<RelativeBytePos>,
multi_byte_chars: &mut Vec<MultiByteChar>,
@@ -172,8 +172,8 @@ cfg_if::cfg_if! {
non_narrow_chars);
}
}
- } else {
-
+ }
+ _ => {
// The target (or compiler version) does not support SSE2 ...
fn analyze_source_file_dispatch(src: &str,
lines: &mut Vec<RelativeBytePos>,
diff --git a/compiler/rustc_span/src/fatal_error.rs b/compiler/rustc_span/src/fatal_error.rs
index fa84c486d..26c571109 100644
--- a/compiler/rustc_span/src/fatal_error.rs
+++ b/compiler/rustc_span/src/fatal_error.rs
@@ -1,13 +1,11 @@
-/// Used as a return value to signify a fatal error occurred. (It is also
-/// used as the argument to panic at the moment, but that will eventually
-/// not be true.)
+/// Used as a return value to signify a fatal error occurred.
#[derive(Copy, Clone, Debug)]
#[must_use]
pub struct FatalError;
-pub struct FatalErrorMarker;
+pub use rustc_data_structures::FatalErrorMarker;
-// Don't implement Send on FatalError. This makes it impossible to panic!(FatalError).
+// Don't implement Send on FatalError. This makes it impossible to `panic_any!(FatalError)`.
// We don't want to invoke the panic handler and print a backtrace for fatal errors.
impl !Send for FatalError {}
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index 88081700c..36731d0fe 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -24,16 +24,13 @@
// because getting it wrong can lead to nested `HygieneData::with` calls that
// trigger runtime aborts. (Fortunately these are obvious and easy to fix.)
+use crate::def_id::{CrateNum, DefId, StableCrateId, CRATE_DEF_ID, LOCAL_CRATE};
use crate::edition::Edition;
use crate::symbol::{kw, sym, Symbol};
-use crate::with_session_globals;
-use crate::{HashStableContext, Span, DUMMY_SP};
-
-use crate::def_id::{CrateNum, DefId, StableCrateId, CRATE_DEF_ID, LOCAL_CRATE};
+use crate::{with_session_globals, HashStableContext, Span, DUMMY_SP};
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_data_structures::stable_hasher::HashingControls;
-use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{Hash64, HashStable, HashingControls, StableHasher};
use rustc_data_structures::sync::{Lock, Lrc, WorkerLocal};
use rustc_data_structures::unhash::UnhashMap;
use rustc_index::IndexVec;
@@ -130,7 +127,7 @@ impl ExpnHash {
/// Returns the crate-local part of the [ExpnHash].
///
- /// Used for tests.
+ /// Used for assertions.
#[inline]
pub fn local_hash(self) -> Hash64 {
self.0.split().1
@@ -173,7 +170,7 @@ impl LocalExpnId {
pub const ROOT: LocalExpnId = LocalExpnId::from_u32(0);
#[inline]
- pub fn from_raw(idx: ExpnIndex) -> LocalExpnId {
+ fn from_raw(idx: ExpnIndex) -> LocalExpnId {
LocalExpnId::from_u32(idx.as_u32())
}
@@ -205,11 +202,6 @@ impl LocalExpnId {
}
#[inline]
- pub fn expn_hash(self) -> ExpnHash {
- HygieneData::with(|data| data.local_expn_hash(self))
- }
-
- #[inline]
pub fn expn_data(self) -> ExpnData {
HygieneData::with(|data| data.local_expn_data(self).clone())
}
@@ -239,13 +231,6 @@ impl LocalExpnId {
self.to_expn_id().is_descendant_of(ancestor.to_expn_id())
}
- /// `expn_id.outer_expn_is_descendant_of(ctxt)` is equivalent to but faster than
- /// `expn_id.is_descendant_of(ctxt.outer_expn())`.
- #[inline]
- pub fn outer_expn_is_descendant_of(self, ctxt: SyntaxContext) -> bool {
- self.to_expn_id().outer_expn_is_descendant_of(ctxt)
- }
-
/// Returns span for the macro which originally caused this expansion to happen.
///
/// Stops backtracing at include! boundary.
@@ -253,12 +238,6 @@ impl LocalExpnId {
pub fn expansion_cause(self) -> Option<Span> {
self.to_expn_id().expansion_cause()
}
-
- #[inline]
- #[track_caller]
- pub fn parent(self) -> LocalExpnId {
- self.expn_data().parent.as_local().unwrap()
- }
}
impl ExpnId {
@@ -333,7 +312,7 @@ impl ExpnId {
}
#[derive(Debug)]
-pub struct HygieneData {
+pub(crate) struct HygieneData {
/// Each expansion should have an associated expansion data, but sometimes there's a delay
/// between creation of an expansion ID and obtaining its data (e.g. macros are collected
/// first and then resolved later), so we use an `Option` here.
@@ -384,16 +363,11 @@ impl HygieneData {
}
}
- pub fn with<T, F: FnOnce(&mut HygieneData) -> T>(f: F) -> T {
+ fn with<T, F: FnOnce(&mut HygieneData) -> T>(f: F) -> T {
with_session_globals(|session_globals| f(&mut session_globals.hygiene_data.borrow_mut()))
}
#[inline]
- fn local_expn_hash(&self, expn_id: LocalExpnId) -> ExpnHash {
- self.local_expn_hashes[expn_id]
- }
-
- #[inline]
fn expn_hash(&self, expn_id: ExpnId) -> ExpnHash {
match expn_id.as_local() {
Some(expn_id) => self.local_expn_hashes[expn_id],
@@ -746,7 +720,7 @@ impl SyntaxContext {
}
/// Like `SyntaxContext::adjust`, but also normalizes `self` to macros 2.0.
- pub fn normalize_to_macros_2_0_and_adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> {
+ pub(crate) fn normalize_to_macros_2_0_and_adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> {
HygieneData::with(|data| {
*self = data.normalize_to_macros_2_0(*self);
data.adjust(self, expn_id)
@@ -779,7 +753,11 @@ impl SyntaxContext {
/// ```
/// This returns `None` if the context cannot be glob-adjusted.
/// Otherwise, it returns the scope to use when privacy checking (see `adjust` for details).
- pub fn glob_adjust(&mut self, expn_id: ExpnId, glob_span: Span) -> Option<Option<ExpnId>> {
+ pub(crate) fn glob_adjust(
+ &mut self,
+ expn_id: ExpnId,
+ glob_span: Span,
+ ) -> Option<Option<ExpnId>> {
HygieneData::with(|data| {
let mut scope = None;
let mut glob_ctxt = data.normalize_to_macros_2_0(glob_span.ctxt());
@@ -803,7 +781,7 @@ impl SyntaxContext {
/// assert!(self.glob_adjust(expansion, glob_ctxt) == Some(privacy_checking_scope));
/// }
/// ```
- pub fn reverse_glob_adjust(
+ pub(crate) fn reverse_glob_adjust(
&mut self,
expn_id: ExpnId,
glob_span: Span,
@@ -858,11 +836,11 @@ impl SyntaxContext {
}
#[inline]
- pub fn outer_mark(self) -> (ExpnId, Transparency) {
+ fn outer_mark(self) -> (ExpnId, Transparency) {
HygieneData::with(|data| data.outer_mark(self))
}
- pub fn dollar_crate_name(self) -> Symbol {
+ pub(crate) fn dollar_crate_name(self) -> Symbol {
HygieneData::with(|data| data.syntax_context_data[self.0 as usize].dollar_crate_name)
}
@@ -961,12 +939,12 @@ pub struct ExpnData {
/// The normal module (`mod`) in which the expanded macro was defined.
pub parent_module: Option<DefId>,
/// Suppresses the `unsafe_code` lint for code produced by this macro.
- pub allow_internal_unsafe: bool,
+ pub(crate) allow_internal_unsafe: bool,
/// Enables the macro helper hack (`ident!(...)` -> `$crate::ident!(...)`) for this macro.
pub local_inner_macros: bool,
/// Should debuginfo for the macro be collapsed to the outermost expansion site (in other
/// words, was the macro definition annotated with `#[collapse_debuginfo]`)?
- pub collapse_debuginfo: bool,
+ pub(crate) collapse_debuginfo: bool,
}
impl !PartialEq for ExpnData {}
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 772e09291..489c8d189 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -4,28 +4,36 @@
//!
//! - the *span*, represented by [`SpanData`] and related types;
//! - source code as represented by a [`SourceMap`]; and
-//! - interned strings, represented by [`Symbol`]s, with some common symbols available statically in the [`sym`] module.
+//! - interned strings, represented by [`Symbol`]s, with some common symbols available statically
+//! in the [`sym`] module.
//!
-//! Unlike most compilers, the span contains not only the position in the source code, but also various other metadata,
-//! such as the edition and macro hygiene. This metadata is stored in [`SyntaxContext`] and [`ExpnData`].
+//! Unlike most compilers, the span contains not only the position in the source code, but also
+//! various other metadata, such as the edition and macro hygiene. This metadata is stored in
+//! [`SyntaxContext`] and [`ExpnData`].
//!
//! ## Note
//!
//! This API is completely unstable and subject to change.
+// tidy-alphabetical-start
+#![allow(internal_features)]
+#![cfg_attr(not(bootstrap), doc(rust_logo))]
+#![cfg_attr(not(bootstrap), feature(rustdoc_internals))]
+#![deny(rustc::diagnostic_outside_of_impl)]
+#![deny(rustc::untranslatable_diagnostic)]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(array_windows)]
+#![feature(cfg_match)]
+#![feature(core_io_borrowed_buf)]
#![feature(if_let_guard)]
-#![feature(negative_impls)]
-#![feature(min_specialization)]
-#![feature(rustc_attrs)]
#![feature(let_chains)]
-#![feature(round_char_boundary)]
-#![feature(read_buf)]
+#![feature(min_specialization)]
+#![feature(negative_impls)]
#![feature(new_uninit)]
-#![deny(rustc::untranslatable_diagnostic)]
-#![deny(rustc::diagnostic_outside_of_impl)]
-#![allow(internal_features)]
+#![feature(read_buf)]
+#![feature(round_char_boundary)]
+#![feature(rustc_attrs)]
+// tidy-alphabetical-end
#[macro_use]
extern crate rustc_macros;
@@ -112,7 +120,6 @@ impl SessionGlobals {
}
}
-#[inline]
pub fn create_session_globals_then<R>(edition: Edition, f: impl FnOnce() -> R) -> R {
assert!(
!SESSION_GLOBALS.is_set(),
@@ -123,7 +130,6 @@ pub fn create_session_globals_then<R>(edition: Edition, f: impl FnOnce() -> R) -
SESSION_GLOBALS.set(&session_globals, f)
}
-#[inline]
pub fn set_session_globals_then<R>(session_globals: &SessionGlobals, f: impl FnOnce() -> R) -> R {
assert!(
!SESSION_GLOBALS.is_set(),
@@ -133,7 +139,6 @@ pub fn set_session_globals_then<R>(session_globals: &SessionGlobals, f: impl FnO
SESSION_GLOBALS.set(session_globals, f)
}
-#[inline]
pub fn create_default_session_if_not_set_then<R, F>(f: F) -> R
where
F: FnOnce(&SessionGlobals) -> R,
@@ -141,7 +146,6 @@ where
create_session_if_not_set_then(edition::DEFAULT_EDITION, f)
}
-#[inline]
pub fn create_session_if_not_set_then<R, F>(edition: Edition, f: F) -> R
where
F: FnOnce(&SessionGlobals) -> R,
@@ -154,7 +158,6 @@ where
}
}
-#[inline]
pub fn with_session_globals<R, F>(f: F) -> R
where
F: FnOnce(&SessionGlobals) -> R,
@@ -162,7 +165,6 @@ where
SESSION_GLOBALS.with(f)
}
-#[inline]
pub fn create_default_session_globals_then<R>(f: impl FnOnce() -> R) -> R {
create_session_globals_then(edition::DEFAULT_EDITION, f)
}
@@ -174,8 +176,7 @@ scoped_tls::scoped_thread_local!(static SESSION_GLOBALS: SessionGlobals);
// FIXME: We should use this enum or something like it to get rid of the
// use of magic `/rust/1.x/...` paths across the board.
-#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd)]
-#[derive(Decodable)]
+#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Decodable)]
pub enum RealFileName {
LocalPath(PathBuf),
/// For remapped paths (namely paths into libstd that have been mapped
@@ -212,8 +213,8 @@ impl<S: Encoder> Encodable<S> for RealFileName {
RealFileName::Remapped { ref local_path, ref virtual_name } => encoder
.emit_enum_variant(1, |encoder| {
- // For privacy and build reproducibility, we must not embed host-dependant path in artifacts
- // if they have been remapped by --remap-path-prefix
+ // For privacy and build reproducibility, we must not embed host-dependant path
+ // in artifacts if they have been remapped by --remap-path-prefix
assert!(local_path.is_none());
local_path.encode(encoder);
virtual_name.encode(encoder);
@@ -280,8 +281,7 @@ impl RealFileName {
}
/// Differentiates between real files and common virtual files.
-#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
-#[derive(Decodable, Encodable)]
+#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash, Decodable, Encodable)]
pub enum FileName {
Real(RealFileName),
/// Call to `quote!`.
@@ -292,8 +292,6 @@ pub enum FileName {
// FIXME(jseyfried)
MacroExpansion(Hash64),
ProcMacroSourceCode(Hash64),
- /// Strings provided as `--cfg [cfgspec]` stored in a `crate_cfg`.
- CfgSpec(Hash64),
/// Strings provided as crate attributes in the CLI.
CliCrateAttr(Hash64),
/// Custom sources for explicit parser calls from plugins and drivers.
@@ -305,7 +303,6 @@ pub enum FileName {
impl From<PathBuf> for FileName {
fn from(p: PathBuf) -> Self {
- assert!(!p.to_string_lossy().ends_with('>'));
FileName::Real(RealFileName::LocalPath(p))
}
}
@@ -339,7 +336,6 @@ impl fmt::Display for FileNameDisplay<'_> {
MacroExpansion(_) => write!(fmt, "<macro expansion>"),
Anon(_) => write!(fmt, "<anon>"),
ProcMacroSourceCode(_) => write!(fmt, "<proc-macro source code>"),
- CfgSpec(_) => write!(fmt, "<cfgspec>"),
CliCrateAttr(_) => write!(fmt, "<crate attribute>"),
Custom(ref s) => write!(fmt, "<{s}>"),
DocTest(ref path, _) => write!(fmt, "{}", path.display()),
@@ -365,7 +361,6 @@ impl FileName {
Anon(_)
| MacroExpansion(_)
| ProcMacroSourceCode(_)
- | CfgSpec(_)
| CliCrateAttr(_)
| Custom(_)
| QuoteExpansion(_)
@@ -374,7 +369,7 @@ impl FileName {
}
}
- pub fn prefer_remapped(&self) -> FileNameDisplay<'_> {
+ pub fn prefer_remapped_unconditionaly(&self) -> FileNameDisplay<'_> {
FileNameDisplay { inner: self, display_pref: FileNameDisplayPreference::Remapped }
}
@@ -955,7 +950,7 @@ impl Span {
/// Produces a span with the same location as `self` and context produced by a macro with the
/// given ID and transparency, assuming that macro was defined directly and not produced by
/// some other macro (which is the case for built-in and procedural macros).
- pub fn with_ctxt_from_mark(self, expn_id: ExpnId, transparency: Transparency) -> Span {
+ fn with_ctxt_from_mark(self, expn_id: ExpnId, transparency: Transparency) -> Span {
self.with_ctxt(SyntaxContext::root().apply_mark(expn_id, transparency))
}
@@ -1530,7 +1525,8 @@ impl SourceFile {
})
}
- /// This converts the `lines` field to contain `SourceFileLines::Lines` if needed and freezes it.
+ /// This converts the `lines` field to contain `SourceFileLines::Lines` if needed and freezes
+ /// it.
fn convert_diffs_to_lines_frozen(&self) {
let mut guard = if let Some(guard) = self.lines.try_write() { guard } else { return };
@@ -2248,7 +2244,10 @@ where
/// Useful type to use with `Result<>` indicate that an error has already
/// been reported to the user, so no need to continue checking.
-#[derive(Clone, Copy, Debug, Encodable, Decodable, Hash, PartialEq, Eq, PartialOrd, Ord)]
+///
+/// The `()` field is necessary: it is non-`pub`, which means values of this
+/// type cannot be constructed outside of this crate.
+#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[derive(HashStable_Generic)]
pub struct ErrorGuaranteed(());
@@ -2260,3 +2259,21 @@ impl ErrorGuaranteed {
ErrorGuaranteed(())
}
}
+
+impl<E: rustc_serialize::Encoder> Encodable<E> for ErrorGuaranteed {
+ #[inline]
+ fn encode(&self, _e: &mut E) {
+ panic!(
+ "should never serialize an `ErrorGuaranteed`, as we do not write metadata or \
+ incremental caches in case errors occurred"
+ )
+ }
+}
+impl<D: rustc_serialize::Decoder> Decodable<D> for ErrorGuaranteed {
+ #[inline]
+ fn decode(_d: &mut D) -> ErrorGuaranteed {
+ panic!(
+ "`ErrorGuaranteed` should never have been serialized to metadata or incremental caches"
+ )
+ }
+}
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index 0b575c13a..dcf346acb 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -9,21 +9,16 @@
//! within the `SourceMap`, which upon request can be converted to line and column
//! information, source code snippets, etc.
-pub use crate::hygiene::{ExpnData, ExpnKind};
-pub use crate::*;
-
+use crate::*;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::{Hash128, Hash64, StableHasher};
use rustc_data_structures::sync::{IntoDynSyncSend, Lrc, MappedReadGuard, ReadGuard, RwLock};
use std::cmp;
+use std::fs;
use std::hash::Hash;
+use std::io::{self, BorrowedBuf, Read};
use std::path::{self, Path, PathBuf};
-use std::fs;
-use std::io;
-use std::io::BorrowedBuf;
-use std::io::Read;
-
#[cfg(test)]
mod tests;
@@ -41,7 +36,7 @@ pub fn original_sp(sp: Span, enclosing_sp: Span) -> Span {
}
}
-pub mod monotonic {
+mod monotonic {
use std::ops::{Deref, DerefMut};
/// A `MonotonicVec` is a `Vec` which can only be grown.
@@ -51,18 +46,14 @@ pub mod monotonic {
// field is inaccessible
pub struct MonotonicVec<T>(Vec<T>);
impl<T> MonotonicVec<T> {
- pub fn new(val: Vec<T>) -> MonotonicVec<T> {
- MonotonicVec(val)
- }
-
- pub fn push(&mut self, val: T) {
+ pub(super) fn push(&mut self, val: T) {
self.0.push(val);
}
}
impl<T> Default for MonotonicVec<T> {
fn default() -> Self {
- MonotonicVec::new(vec![])
+ MonotonicVec(vec![])
}
}
@@ -207,7 +198,7 @@ impl StableSourceFileId {
//
#[derive(Default)]
-pub(super) struct SourceMapFiles {
+struct SourceMapFiles {
source_files: monotonic::MonotonicVec<Lrc<SourceFile>>,
stable_id_to_source_file: FxHashMap<StableSourceFileId, Lrc<SourceFile>>,
}
@@ -466,33 +457,6 @@ impl SourceMap {
self.span_to_string(sp, FileNameDisplayPreference::Remapped)
}
- /// Format the span location suitable for pretty printing annotations with relative line numbers
- pub fn span_to_relative_line_string(&self, sp: Span, relative_to: Span) -> String {
- if self.files.borrow().source_files.is_empty() || sp.is_dummy() || relative_to.is_dummy() {
- return "no-location".to_string();
- }
-
- let lo = self.lookup_char_pos(sp.lo());
- let hi = self.lookup_char_pos(sp.hi());
- let offset = self.lookup_char_pos(relative_to.lo());
-
- if lo.file.name != offset.file.name || !relative_to.contains(sp) {
- return self.span_to_embeddable_string(sp);
- }
-
- let lo_line = lo.line.saturating_sub(offset.line);
- let hi_line = hi.line.saturating_sub(offset.line);
-
- format!(
- "{}:+{}:{}: +{}:{}",
- lo.file.name.display(FileNameDisplayPreference::Remapped),
- lo_line,
- lo.col.to_usize() + 1,
- hi_line,
- hi.col.to_usize() + 1,
- )
- }
-
/// Format the span location to be printed in diagnostics. Must not be emitted
/// to build artifacts as this may leak local file paths. Use span_to_embeddable_string
/// for string suitable for embedding.
@@ -1124,16 +1088,13 @@ pub struct FilePathMapping {
impl FilePathMapping {
pub fn empty() -> FilePathMapping {
- FilePathMapping::new(Vec::new())
+ FilePathMapping::new(Vec::new(), FileNameDisplayPreference::Local)
}
- pub fn new(mapping: Vec<(PathBuf, PathBuf)>) -> FilePathMapping {
- let filename_display_for_diagnostics = if mapping.is_empty() {
- FileNameDisplayPreference::Local
- } else {
- FileNameDisplayPreference::Remapped
- };
-
+ pub fn new(
+ mapping: Vec<(PathBuf, PathBuf)>,
+ filename_display_for_diagnostics: FileNameDisplayPreference,
+ ) -> FilePathMapping {
FilePathMapping { mapping, filename_display_for_diagnostics }
}
@@ -1287,6 +1248,27 @@ impl FilePathMapping {
}
}
+ /// Expand a relative path to an absolute path **without** remapping taken into account.
+ ///
+ /// The resulting `RealFileName` will have its `virtual_path` portion erased if
+ /// possible (i.e. if there's also a remapped path).
+ pub fn to_local_embeddable_absolute_path(
+ &self,
+ file_path: RealFileName,
+ working_directory: &RealFileName,
+ ) -> RealFileName {
+ let file_path = file_path.local_path_if_available();
+ if file_path.is_absolute() {
+ // No remapping has applied to this path and it is absolute,
+ // so the working directory cannot influence it either, so
+ // we are done.
+ return RealFileName::LocalPath(file_path.to_path_buf());
+ }
+ debug_assert!(file_path.is_relative());
+ let working_directory = working_directory.local_path_if_available();
+ RealFileName::LocalPath(Path::new(working_directory).join(file_path))
+ }
+
/// Attempts to (heuristically) reverse a prefix mapping.
///
/// Returns [`Some`] if there is exactly one mapping where the "to" part is
diff --git a/compiler/rustc_span/src/source_map/tests.rs b/compiler/rustc_span/src/source_map/tests.rs
index a12f50c87..5697969dd 100644
--- a/compiler/rustc_span/src/source_map/tests.rs
+++ b/compiler/rustc_span/src/source_map/tests.rs
@@ -351,7 +351,10 @@ fn reverse_map_prefix(mapping: &FilePathMapping, p: &str) -> Option<String> {
fn path_prefix_remapping() {
// Relative to relative
{
- let mapping = &FilePathMapping::new(vec![(path("abc/def"), path("foo"))]);
+ let mapping = &FilePathMapping::new(
+ vec![(path("abc/def"), path("foo"))],
+ FileNameDisplayPreference::Remapped,
+ );
assert_eq!(map_path_prefix(mapping, "abc/def/src/main.rs"), path_str("foo/src/main.rs"));
assert_eq!(map_path_prefix(mapping, "abc/def"), path_str("foo"));
@@ -359,7 +362,10 @@ fn path_prefix_remapping() {
// Relative to absolute
{
- let mapping = &FilePathMapping::new(vec![(path("abc/def"), path("/foo"))]);
+ let mapping = &FilePathMapping::new(
+ vec![(path("abc/def"), path("/foo"))],
+ FileNameDisplayPreference::Remapped,
+ );
assert_eq!(map_path_prefix(mapping, "abc/def/src/main.rs"), path_str("/foo/src/main.rs"));
assert_eq!(map_path_prefix(mapping, "abc/def"), path_str("/foo"));
@@ -367,7 +373,10 @@ fn path_prefix_remapping() {
// Absolute to relative
{
- let mapping = &FilePathMapping::new(vec![(path("/abc/def"), path("foo"))]);
+ let mapping = &FilePathMapping::new(
+ vec![(path("/abc/def"), path("foo"))],
+ FileNameDisplayPreference::Remapped,
+ );
assert_eq!(map_path_prefix(mapping, "/abc/def/src/main.rs"), path_str("foo/src/main.rs"));
assert_eq!(map_path_prefix(mapping, "/abc/def"), path_str("foo"));
@@ -375,7 +384,10 @@ fn path_prefix_remapping() {
// Absolute to absolute
{
- let mapping = &FilePathMapping::new(vec![(path("/abc/def"), path("/foo"))]);
+ let mapping = &FilePathMapping::new(
+ vec![(path("/abc/def"), path("/foo"))],
+ FileNameDisplayPreference::Remapped,
+ );
assert_eq!(map_path_prefix(mapping, "/abc/def/src/main.rs"), path_str("/foo/src/main.rs"));
assert_eq!(map_path_prefix(mapping, "/abc/def"), path_str("/foo"));
@@ -385,8 +397,10 @@ fn path_prefix_remapping() {
#[test]
fn path_prefix_remapping_expand_to_absolute() {
// "virtual" working directory is relative path
- let mapping =
- &FilePathMapping::new(vec![(path("/foo"), path("FOO")), (path("/bar"), path("BAR"))]);
+ let mapping = &FilePathMapping::new(
+ vec![(path("/foo"), path("FOO")), (path("/bar"), path("BAR"))],
+ FileNameDisplayPreference::Remapped,
+ );
let working_directory = path("/foo");
let working_directory = RealFileName::Remapped {
local_path: Some(working_directory.clone()),
@@ -487,8 +501,10 @@ fn path_prefix_remapping_expand_to_absolute() {
fn path_prefix_remapping_reverse() {
// Ignores options without alphanumeric chars.
{
- let mapping =
- &FilePathMapping::new(vec![(path("abc"), path("/")), (path("def"), path("."))]);
+ let mapping = &FilePathMapping::new(
+ vec![(path("abc"), path("/")), (path("def"), path("."))],
+ FileNameDisplayPreference::Remapped,
+ );
assert_eq!(reverse_map_prefix(mapping, "/hello.rs"), None);
assert_eq!(reverse_map_prefix(mapping, "./hello.rs"), None);
@@ -496,20 +512,20 @@ fn path_prefix_remapping_reverse() {
// Returns `None` if multiple options match.
{
- let mapping = &FilePathMapping::new(vec![
- (path("abc"), path("/redacted")),
- (path("def"), path("/redacted")),
- ]);
+ let mapping = &FilePathMapping::new(
+ vec![(path("abc"), path("/redacted")), (path("def"), path("/redacted"))],
+ FileNameDisplayPreference::Remapped,
+ );
assert_eq!(reverse_map_prefix(mapping, "/redacted/hello.rs"), None);
}
// Distinct reverse mappings.
{
- let mapping = &FilePathMapping::new(vec![
- (path("abc"), path("/redacted")),
- (path("def/ghi"), path("/fake/dir")),
- ]);
+ let mapping = &FilePathMapping::new(
+ vec![(path("abc"), path("/redacted")), (path("def/ghi"), path("/fake/dir"))],
+ FileNameDisplayPreference::Remapped,
+ );
assert_eq!(
reverse_map_prefix(mapping, "/redacted/path/hello.rs"),
diff --git a/compiler/rustc_span/src/span_encoding.rs b/compiler/rustc_span/src/span_encoding.rs
index 93ab15460..f7d17a267 100644
--- a/compiler/rustc_span/src/span_encoding.rs
+++ b/compiler/rustc_span/src/span_encoding.rs
@@ -126,7 +126,7 @@ impl Span {
return Span {
lo_or_index: lo2,
len_with_tag_or_marker: PARENT_TAG | len as u16,
- ctxt_or_parent_or_marker: parent2 as u16
+ ctxt_or_parent_or_marker: parent2 as u16,
};
}
}
@@ -212,6 +212,7 @@ impl Span {
/// This function is used as a fast path when decoding the full `SpanData` is not necessary.
/// It's a cut-down version of `data_untracked`.
+ #[cfg_attr(not(test), rustc_diagnostic_item = "SpanCtxt")]
#[inline]
pub fn ctxt(self) -> SyntaxContext {
if self.len_with_tag_or_marker != BASE_LEN_INTERNED_MARKER {
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 4f4625662..f287862cc 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -3,7 +3,7 @@
//! type, and vice versa.
use rustc_arena::DroplessArena;
-use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::fx::FxIndexSet;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
use rustc_data_structures::sync::Lock;
use rustc_macros::HashStable_Generic;
@@ -20,8 +20,8 @@ mod tests;
// The proc macro code for this is in `compiler/rustc_macros/src/symbols.rs`.
symbols! {
- // After modifying this list adjust `is_special`, `is_used_keyword`/`is_unused_keyword`,
- // this should be rarely necessary though if the keywords are kept in alphabetic order.
+ // If you modify this list, adjust `is_special` and `is_used_keyword`/`is_unused_keyword`.
+ // But this should rarely be necessary if the keywords are kept in alphabetic order.
Keywords {
// Special reserved identifiers used internally for elided lifetimes,
// unnamed method parameters, crate root module, error recovery etc.
@@ -98,6 +98,7 @@ symbols! {
Builtin: "builtin",
Catch: "catch",
Default: "default",
+ Gen: "gen",
MacroRules: "macro_rules",
Raw: "raw",
Union: "union",
@@ -129,9 +130,11 @@ symbols! {
Alignment,
Any,
Arc,
+ ArcWeak,
Argument,
ArgumentMethods,
Arguments,
+ ArrayIntoIter,
AsMut,
AsRef,
AssertParamIsClone,
@@ -164,6 +167,7 @@ symbols! {
Capture,
Center,
Clone,
+ Command,
ConstParamTy,
Context,
Continue,
@@ -171,6 +175,7 @@ symbols! {
Count,
Cow,
Debug,
+ DebugStruct,
Decodable,
Decoder,
DecorateLint,
@@ -189,11 +194,16 @@ symbols! {
Error,
File,
FileType,
+ Fn,
+ FnMut,
+ FnOnce,
FormatSpec,
Formatter,
From,
FromIterator,
FromResidual,
+ FsOpenOptions,
+ FsPermissions,
Future,
FutureOutput,
FxHashMap,
@@ -207,16 +217,23 @@ symbols! {
Implied,
IndexOutput,
Input,
+ Instant,
Into,
IntoDiagnostic,
IntoFuture,
IntoIterator,
+ IoLines,
IoRead,
+ IoSeek,
IoWrite,
IpAddr,
IrTyKind,
Is,
+ Item,
ItemContext,
+ IterEmpty,
+ IterOnce,
+ IterPeekable,
Iterator,
IteratorItem,
Layout,
@@ -227,6 +244,7 @@ symbols! {
Mutex,
MutexGuard,
N,
+ NonNull,
NonZeroI128,
NonZeroI16,
NonZeroI32,
@@ -259,15 +277,19 @@ symbols! {
ProcMacro,
ProceduralMasqueradeDummyType,
Range,
+ RangeBounds,
RangeFrom,
RangeFull,
RangeInclusive,
RangeTo,
RangeToInclusive,
Rc,
+ RcWeak,
Ready,
Receiver,
RefCell,
+ RefCellRef,
+ RefCellRefMut,
Relaxed,
Release,
Result,
@@ -284,7 +306,9 @@ symbols! {
Send,
SeqCst,
SliceIndex,
+ SliceIter,
Some,
+ SpanCtxt,
String,
StructuralEq,
StructuralPartialEq,
@@ -295,6 +319,7 @@ symbols! {
ToOwned,
ToString,
TokenStream,
+ Trait,
Try,
TryCaptureGeneric,
TryCapturePrintable,
@@ -561,6 +586,7 @@ symbols! {
constant,
constructor,
context,
+ convert_identity,
copy,
copy_closures,
copy_nonoverlapping,
@@ -571,6 +597,10 @@ symbols! {
core_panic_2015_macro,
core_panic_2021_macro,
core_panic_macro,
+ coroutine,
+ coroutine_clone,
+ coroutine_state,
+ coroutines,
cosf32,
cosf64,
count,
@@ -616,6 +646,7 @@ symbols! {
declare_lint_pass,
decode,
default_alloc_error_handler,
+ default_fn,
default_lib_allocator,
default_method_body_is_const,
default_type_parameter_fallback,
@@ -628,6 +659,7 @@ symbols! {
deref,
deref_method,
deref_mut,
+ deref_mut_method,
deref_target,
derive,
derive_const,
@@ -687,6 +719,7 @@ symbols! {
encode,
end,
env,
+ env_CFG_RELEASE: env!("CFG_RELEASE"),
eprint_macro,
eprintln_macro,
eq,
@@ -777,22 +810,24 @@ symbols! {
from_desugaring,
from_fn,
from_iter,
+ from_iter_fn,
from_output,
from_residual,
from_size_align_unchecked,
+ from_str_method,
from_usize,
from_yeet,
+ fs_create_dir,
fsub_fast,
fundamental,
future,
future_trait,
gdb_script_file,
ge,
+ gen_blocks,
gen_future,
gen_kill,
- generator,
generator_clone,
- generator_state,
generators,
generic_arg_infer,
generic_assert,
@@ -862,12 +897,16 @@ symbols! {
inline_const_pat,
inout,
instruction_set,
- integer_: "integer",
+ integer_: "integer", // underscore to avoid clashing with the function `sym::integer` below
integral,
into_future,
into_iter,
intra_doc_pointers,
intrinsics,
+ intrinsics_unaligned_volatile_load,
+ intrinsics_unaligned_volatile_store,
+ io_stderr,
+ io_stdout,
irrefutable_let_patterns,
isa_attribute,
isize,
@@ -879,6 +918,7 @@ symbols! {
iter,
iter_mut,
iter_repeat,
+ iterator,
iterator_collect_fn,
kcfi,
keyword,
@@ -926,6 +966,7 @@ symbols! {
log_syntax,
logf32,
logf64,
+ loongarch_target_feature,
loop_break_value,
lt,
macro_at_most_once_rep,
@@ -962,6 +1003,7 @@ symbols! {
mem_replace,
mem_size_of,
mem_size_of_val,
+ mem_swap,
mem_uninitialized,
mem_variant_count,
mem_zeroed,
@@ -1075,6 +1117,7 @@ symbols! {
off,
offset,
offset_of,
+ offset_of_enum,
omit_gdb_pretty_printer_section,
on,
on_unimplemented,
@@ -1091,6 +1134,7 @@ symbols! {
options,
or,
or_patterns,
+ ord_cmp_method,
other,
out,
overflow_checks,
@@ -1104,7 +1148,6 @@ symbols! {
panic_abort,
panic_bounds_check,
panic_cannot_unwind,
- panic_display,
panic_fmt,
panic_handler,
panic_impl,
@@ -1172,6 +1215,7 @@ symbols! {
proc_macro_mod,
proc_macro_non_items,
proc_macro_path_invoc,
+ process_exit,
profiler_builtins,
profiler_runtime,
ptr,
@@ -1179,6 +1223,10 @@ symbols! {
ptr_cast_const,
ptr_cast_mut,
ptr_const_is_null,
+ ptr_copy,
+ ptr_copy_nonoverlapping,
+ ptr_drop_in_place,
+ ptr_eq,
ptr_from_ref,
ptr_guaranteed_cmp,
ptr_is_null,
@@ -1187,8 +1235,17 @@ symbols! {
ptr_null_mut,
ptr_offset_from,
ptr_offset_from_unsigned,
+ ptr_read,
+ ptr_read_unaligned,
+ ptr_read_volatile,
+ ptr_replace,
+ ptr_slice_from_raw_parts,
+ ptr_slice_from_raw_parts_mut,
+ ptr_swap,
+ ptr_swap_nonoverlapping,
ptr_unique,
ptr_write,
+ ptr_write_bytes,
ptr_write_unaligned,
ptr_write_volatile,
pub_macro_rules,
@@ -1284,6 +1341,7 @@ symbols! {
rust_cold_cc,
rust_eh_catch_typeinfo,
rust_eh_personality,
+ rust_logo,
rustc,
rustc_abi,
rustc_allocator,
@@ -1299,6 +1357,7 @@ symbols! {
rustc_coherence_is_core,
rustc_coinductive,
rustc_confusables,
+ rustc_const_panic_str,
rustc_const_stable,
rustc_const_unstable,
rustc_conversion_suggestion,
@@ -1321,6 +1380,7 @@ symbols! {
rustc_evaluate_where_clauses,
rustc_expected_cgu_reuse,
rustc_has_incoherent_inherent_impls,
+ rustc_hidden_type_of_opaques,
rustc_host,
rustc_if_this_changed,
rustc_inherit_overflow_checks,
@@ -1478,6 +1538,8 @@ symbols! {
sized,
skip,
slice,
+ slice_from_raw_parts,
+ slice_from_raw_parts_mut,
slice_len_fn,
slice_patterns,
slicing_syntax,
@@ -1565,7 +1627,9 @@ symbols! {
thumb2,
thumb_mode: "thumb-mode",
tmm_reg,
+ to_owned_method,
to_string,
+ to_string_method,
to_vec,
todo_macro,
tool_attributes,
@@ -1588,6 +1652,7 @@ symbols! {
try_blocks,
try_capture,
try_from,
+ try_from_fn,
try_into,
try_trait_v2,
tt,
@@ -1722,6 +1787,7 @@ symbols! {
xmm_reg,
yeet_desugar_details,
yeet_expr,
+ yield_expr,
ymm_reg,
zmm_reg,
}
@@ -2015,43 +2081,33 @@ impl<CTX> ToStableHashKey<CTX> for Symbol {
}
}
-#[derive(Default)]
pub(crate) struct Interner(Lock<InternerInner>);
// The `&'static str`s in this type actually point into the arena.
//
-// The `FxHashMap`+`Vec` pair could be replaced by `FxIndexSet`, but #75278
-// found that to regress performance up to 2% in some cases. This might be
-// revisited after further improvements to `indexmap`.
-//
// This type is private to prevent accidentally constructing more than one
// `Interner` on the same thread, which makes it easy to mix up `Symbol`s
// between `Interner`s.
-#[derive(Default)]
struct InternerInner {
arena: DroplessArena,
- names: FxHashMap<&'static str, Symbol>,
- strings: Vec<&'static str>,
+ strings: FxIndexSet<&'static str>,
}
impl Interner {
fn prefill(init: &[&'static str]) -> Self {
Interner(Lock::new(InternerInner {
- strings: init.into(),
- names: init.iter().copied().zip((0..).map(Symbol::new)).collect(),
- ..Default::default()
+ arena: Default::default(),
+ strings: init.iter().copied().collect(),
}))
}
#[inline]
fn intern(&self, string: &str) -> Symbol {
let mut inner = self.0.lock();
- if let Some(&name) = inner.names.get(string) {
- return name;
+ if let Some(idx) = inner.strings.get_index_of(string) {
+ return Symbol::new(idx as u32);
}
- let name = Symbol::new(inner.strings.len() as u32);
-
// SAFETY: we convert from `&str` to `&[u8]`, clone it into the arena,
// and immediately convert the clone back to `&[u8]`, all because there
// is no `inner.arena.alloc_str()` method. This is clearly safe.
@@ -2061,20 +2117,21 @@ impl Interner {
// SAFETY: we can extend the arena allocation to `'static` because we
// only access these while the arena is still alive.
let string: &'static str = unsafe { &*(string as *const str) };
- inner.strings.push(string);
// This second hash table lookup can be avoided by using `RawEntryMut`,
// but this code path isn't hot enough for it to be worth it. See
// #91445 for details.
- inner.names.insert(string, name);
- name
+ let (idx, is_new) = inner.strings.insert_full(string);
+ debug_assert!(is_new); // due to the get_index_of check above
+
+ Symbol::new(idx as u32)
}
/// Get the symbol as a string.
///
/// [`Symbol::as_str()`] should be used in preference to this function.
fn get(&self, symbol: Symbol) -> &str {
- self.0.lock().strings[symbol.0.as_usize()]
+ self.0.lock().strings.get_index(symbol.0.as_usize()).unwrap()
}
}
@@ -2132,8 +2189,9 @@ impl Symbol {
self >= kw::Abstract && self <= kw::Yield
}
- fn is_unused_keyword_conditional(self, edition: impl FnOnce() -> Edition) -> bool {
- self == kw::Try && edition() >= Edition::Edition2018
+ fn is_unused_keyword_conditional(self, edition: impl Copy + FnOnce() -> Edition) -> bool {
+ self == kw::Try && edition().at_least_rust_2018()
+ || self == kw::Gen && edition().at_least_rust_2024()
}
pub fn is_reserved(self, edition: impl Copy + FnOnce() -> Edition) -> bool {
diff --git a/compiler/rustc_span/src/symbol/tests.rs b/compiler/rustc_span/src/symbol/tests.rs
index 0958fce5f..4366c5a2c 100644
--- a/compiler/rustc_span/src/symbol/tests.rs
+++ b/compiler/rustc_span/src/symbol/tests.rs
@@ -4,7 +4,7 @@ use crate::create_default_session_globals_then;
#[test]
fn interner_tests() {
- let i = Interner::default();
+ let i = Interner::prefill(&[]);
// first one is zero:
assert_eq!(i.intern("dog"), Symbol::new(0));
// re-use gets the same entry: