diff options
Diffstat (limited to 'compiler/rustc_span/src')
-rw-r--r-- | compiler/rustc_span/src/analyze_source_file.rs | 8 | ||||
-rw-r--r-- | compiler/rustc_span/src/fatal_error.rs | 8 | ||||
-rw-r--r-- | compiler/rustc_span/src/hygiene.rs | 58 | ||||
-rw-r--r-- | compiler/rustc_span/src/lib.rs | 81 | ||||
-rw-r--r-- | compiler/rustc_span/src/source_map.rs | 84 | ||||
-rw-r--r-- | compiler/rustc_span/src/source_map/tests.rs | 48 | ||||
-rw-r--r-- | compiler/rustc_span/src/span_encoding.rs | 3 | ||||
-rw-r--r-- | compiler/rustc_span/src/symbol.rs | 114 | ||||
-rw-r--r-- | compiler/rustc_span/src/symbol/tests.rs | 2 |
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: |