1#![allow(internal_features)]
20#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
21#![doc(rust_logo)]
22#![feature(array_windows)]
23#![feature(cfg_select)]
24#![feature(core_io_borrowed_buf)]
25#![feature(if_let_guard)]
26#![feature(map_try_insert)]
27#![feature(negative_impls)]
28#![feature(read_buf)]
29#![feature(round_char_boundary)]
30#![feature(rustc_attrs)]
31#![feature(rustdoc_internals)]
32extern crate self as rustc_span;
38
39use derive_where::derive_where;
40use rustc_data_structures::{AtomicRef, outline};
41use rustc_macros::{Decodable, Encodable, HashStable_Generic};
42use rustc_serialize::opaque::{FileEncoder, MemDecoder};
43use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
44use tracing::debug;
45
46mod caching_source_map_view;
47pub mod source_map;
48use source_map::{SourceMap, SourceMapInputs};
49
50pub use self::caching_source_map_view::CachingSourceMapView;
51use crate::fatal_error::FatalError;
52
53pub mod edition;
54use edition::Edition;
55pub mod hygiene;
56use hygiene::Transparency;
57pub use hygiene::{
58 DesugaringKind, ExpnData, ExpnHash, ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContext,
59};
60use rustc_data_structures::stable_hasher::HashingControls;
61pub mod def_id;
62use def_id::{CrateNum, DefId, DefIndex, DefPathHash, LOCAL_CRATE, LocalDefId, StableCrateId};
63pub mod edit_distance;
64mod span_encoding;
65pub use span_encoding::{DUMMY_SP, Span};
66
67pub mod symbol;
68pub use symbol::{
69 ByteSymbol, Ident, MacroRulesNormalizedIdent, STDLIB_STABLE_CRATES, Symbol, kw, sym,
70};
71
72mod analyze_source_file;
73pub mod fatal_error;
74
75pub mod profiling;
76
77use std::borrow::Cow;
78use std::cmp::{self, Ordering};
79use std::fmt::Display;
80use std::hash::Hash;
81use std::io::{self, Read};
82use std::ops::{Add, Range, Sub};
83use std::path::{Path, PathBuf};
84use std::str::FromStr;
85use std::sync::Arc;
86use std::{fmt, iter};
87
88use md5::{Digest, Md5};
89use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
90use rustc_data_structures::sync::{FreezeLock, FreezeWriteGuard, Lock};
91use rustc_data_structures::unord::UnordMap;
92use rustc_hashes::{Hash64, Hash128};
93use sha1::Sha1;
94use sha2::Sha256;
95
96#[cfg(test)]
97mod tests;
98
99pub struct SessionGlobals {
104 symbol_interner: symbol::Interner,
105 span_interner: Lock<span_encoding::SpanInterner>,
106 metavar_spans: MetavarSpansMap,
109 hygiene_data: Lock<hygiene::HygieneData>,
110
111 source_map: Option<Arc<SourceMap>>,
115}
116
117impl SessionGlobals {
118 pub fn new(
119 edition: Edition,
120 extra_symbols: &[&'static str],
121 sm_inputs: Option<SourceMapInputs>,
122 ) -> SessionGlobals {
123 SessionGlobals {
124 symbol_interner: symbol::Interner::with_extra_symbols(extra_symbols),
125 span_interner: Lock::new(span_encoding::SpanInterner::default()),
126 metavar_spans: Default::default(),
127 hygiene_data: Lock::new(hygiene::HygieneData::new(edition)),
128 source_map: sm_inputs.map(|inputs| Arc::new(SourceMap::with_inputs(inputs))),
129 }
130 }
131}
132
133pub fn create_session_globals_then<R>(
134 edition: Edition,
135 extra_symbols: &[&'static str],
136 sm_inputs: Option<SourceMapInputs>,
137 f: impl FnOnce() -> R,
138) -> R {
139 assert!(
140 !SESSION_GLOBALS.is_set(),
141 "SESSION_GLOBALS should never be overwritten! \
142 Use another thread if you need another SessionGlobals"
143 );
144 let session_globals = SessionGlobals::new(edition, extra_symbols, sm_inputs);
145 SESSION_GLOBALS.set(&session_globals, f)
146}
147
148pub fn set_session_globals_then<R>(session_globals: &SessionGlobals, f: impl FnOnce() -> R) -> R {
149 assert!(
150 !SESSION_GLOBALS.is_set(),
151 "SESSION_GLOBALS should never be overwritten! \
152 Use another thread if you need another SessionGlobals"
153 );
154 SESSION_GLOBALS.set(session_globals, f)
155}
156
157pub fn create_session_if_not_set_then<R, F>(edition: Edition, f: F) -> R
159where
160 F: FnOnce(&SessionGlobals) -> R,
161{
162 if !SESSION_GLOBALS.is_set() {
163 let session_globals = SessionGlobals::new(edition, &[], None);
164 SESSION_GLOBALS.set(&session_globals, || SESSION_GLOBALS.with(f))
165 } else {
166 SESSION_GLOBALS.with(f)
167 }
168}
169
170#[inline]
171pub fn with_session_globals<R, F>(f: F) -> R
172where
173 F: FnOnce(&SessionGlobals) -> R,
174{
175 SESSION_GLOBALS.with(f)
176}
177
178pub fn create_default_session_globals_then<R>(f: impl FnOnce() -> R) -> R {
180 create_session_globals_then(edition::DEFAULT_EDITION, &[], None, f)
181}
182
183scoped_tls::scoped_thread_local!(static SESSION_GLOBALS: SessionGlobals);
187
188#[derive(Default)]
189pub struct MetavarSpansMap(FreezeLock<UnordMap<Span, (Span, bool)>>);
190
191impl MetavarSpansMap {
192 pub fn insert(&self, span: Span, var_span: Span) -> bool {
193 match self.0.write().try_insert(span, (var_span, false)) {
194 Ok(_) => true,
195 Err(entry) => entry.entry.get().0 == var_span,
196 }
197 }
198
199 pub fn get(&self, span: Span) -> Option<Span> {
201 if let Some(mut mspans) = self.0.try_write() {
202 if let Some((var_span, read)) = mspans.get_mut(&span) {
203 *read = true;
204 Some(*var_span)
205 } else {
206 None
207 }
208 } else {
209 if let Some((span, true)) = self.0.read().get(&span) { Some(*span) } else { None }
210 }
211 }
212
213 pub fn freeze_and_get_read_spans(&self) -> UnordMap<Span, Span> {
217 self.0.freeze().items().filter(|(_, (_, b))| *b).map(|(s1, (s2, _))| (*s1, *s2)).collect()
218 }
219}
220
221#[inline]
222pub fn with_metavar_spans<R>(f: impl FnOnce(&MetavarSpansMap) -> R) -> R {
223 with_session_globals(|session_globals| f(&session_globals.metavar_spans))
224}
225
226#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Decodable, Encodable)]
229pub enum RealFileName {
230 LocalPath(PathBuf),
231 Remapped {
235 local_path: Option<PathBuf>,
238 virtual_name: PathBuf,
241 },
242}
243
244impl Hash for RealFileName {
245 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
246 self.remapped_path_if_available().hash(state)
251 }
252}
253
254impl RealFileName {
255 pub fn local_path(&self) -> Option<&Path> {
259 match self {
260 RealFileName::LocalPath(p) => Some(p),
261 RealFileName::Remapped { local_path, virtual_name: _ } => local_path.as_deref(),
262 }
263 }
264
265 pub fn into_local_path(self) -> Option<PathBuf> {
269 match self {
270 RealFileName::LocalPath(p) => Some(p),
271 RealFileName::Remapped { local_path: p, virtual_name: _ } => p,
272 }
273 }
274
275 pub fn remapped_path_if_available(&self) -> &Path {
280 match self {
281 RealFileName::LocalPath(p)
282 | RealFileName::Remapped { local_path: _, virtual_name: p } => p,
283 }
284 }
285
286 pub fn local_path_if_available(&self) -> &Path {
290 match self {
291 RealFileName::LocalPath(path)
292 | RealFileName::Remapped { local_path: None, virtual_name: path }
293 | RealFileName::Remapped { local_path: Some(path), virtual_name: _ } => path,
294 }
295 }
296
297 pub fn to_path(&self, display_pref: FileNameDisplayPreference) -> &Path {
301 match display_pref {
302 FileNameDisplayPreference::Local | FileNameDisplayPreference::Short => {
303 self.local_path_if_available()
304 }
305 FileNameDisplayPreference::Remapped => self.remapped_path_if_available(),
306 }
307 }
308
309 pub fn to_string_lossy(&self, display_pref: FileNameDisplayPreference) -> Cow<'_, str> {
310 match display_pref {
311 FileNameDisplayPreference::Local => self.local_path_if_available().to_string_lossy(),
312 FileNameDisplayPreference::Remapped => {
313 self.remapped_path_if_available().to_string_lossy()
314 }
315 FileNameDisplayPreference::Short => self
316 .local_path_if_available()
317 .file_name()
318 .map_or_else(|| "".into(), |f| f.to_string_lossy()),
319 }
320 }
321}
322
323#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash, Decodable, Encodable)]
325pub enum FileName {
326 Real(RealFileName),
327 CfgSpec(Hash64),
329 Anon(Hash64),
331 MacroExpansion(Hash64),
334 ProcMacroSourceCode(Hash64),
335 CliCrateAttr(Hash64),
337 Custom(String),
339 DocTest(PathBuf, isize),
340 InlineAsm(Hash64),
342}
343
344impl From<PathBuf> for FileName {
345 fn from(p: PathBuf) -> Self {
346 FileName::Real(RealFileName::LocalPath(p))
347 }
348}
349
350#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
351pub enum FileNameEmbeddablePreference {
352 RemappedOnly,
356 LocalAndRemapped,
358}
359
360#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
361pub enum FileNameDisplayPreference {
362 Remapped,
365 Local,
368 Short,
371}
372
373pub struct FileNameDisplay<'a> {
374 inner: &'a FileName,
375 display_pref: FileNameDisplayPreference,
376}
377
378impl fmt::Display for FileNameDisplay<'_> {
379 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
380 use FileName::*;
381 match *self.inner {
382 Real(ref name) => {
383 write!(fmt, "{}", name.to_string_lossy(self.display_pref))
384 }
385 CfgSpec(_) => write!(fmt, "<cfgspec>"),
386 MacroExpansion(_) => write!(fmt, "<macro expansion>"),
387 Anon(_) => write!(fmt, "<anon>"),
388 ProcMacroSourceCode(_) => write!(fmt, "<proc-macro source code>"),
389 CliCrateAttr(_) => write!(fmt, "<crate attribute>"),
390 Custom(ref s) => write!(fmt, "<{s}>"),
391 DocTest(ref path, _) => write!(fmt, "{}", path.display()),
392 InlineAsm(_) => write!(fmt, "<inline asm>"),
393 }
394 }
395}
396
397impl<'a> FileNameDisplay<'a> {
398 pub fn to_string_lossy(&self) -> Cow<'a, str> {
399 match self.inner {
400 FileName::Real(inner) => inner.to_string_lossy(self.display_pref),
401 _ => Cow::from(self.to_string()),
402 }
403 }
404}
405
406impl FileName {
407 pub fn is_real(&self) -> bool {
408 use FileName::*;
409 match *self {
410 Real(_) => true,
411 Anon(_)
412 | MacroExpansion(_)
413 | ProcMacroSourceCode(_)
414 | CliCrateAttr(_)
415 | Custom(_)
416 | CfgSpec(_)
417 | DocTest(_, _)
418 | InlineAsm(_) => false,
419 }
420 }
421
422 pub fn prefer_remapped_unconditionally(&self) -> FileNameDisplay<'_> {
423 FileNameDisplay { inner: self, display_pref: FileNameDisplayPreference::Remapped }
424 }
425
426 pub fn prefer_local(&self) -> FileNameDisplay<'_> {
429 FileNameDisplay { inner: self, display_pref: FileNameDisplayPreference::Local }
430 }
431
432 pub fn display(&self, display_pref: FileNameDisplayPreference) -> FileNameDisplay<'_> {
433 FileNameDisplay { inner: self, display_pref }
434 }
435
436 pub fn macro_expansion_source_code(src: &str) -> FileName {
437 let mut hasher = StableHasher::new();
438 src.hash(&mut hasher);
439 FileName::MacroExpansion(hasher.finish())
440 }
441
442 pub fn anon_source_code(src: &str) -> FileName {
443 let mut hasher = StableHasher::new();
444 src.hash(&mut hasher);
445 FileName::Anon(hasher.finish())
446 }
447
448 pub fn proc_macro_source_code(src: &str) -> FileName {
449 let mut hasher = StableHasher::new();
450 src.hash(&mut hasher);
451 FileName::ProcMacroSourceCode(hasher.finish())
452 }
453
454 pub fn cfg_spec_source_code(src: &str) -> FileName {
455 let mut hasher = StableHasher::new();
456 src.hash(&mut hasher);
457 FileName::CfgSpec(hasher.finish())
458 }
459
460 pub fn cli_crate_attr_source_code(src: &str) -> FileName {
461 let mut hasher = StableHasher::new();
462 src.hash(&mut hasher);
463 FileName::CliCrateAttr(hasher.finish())
464 }
465
466 pub fn doc_test_source_code(path: PathBuf, line: isize) -> FileName {
467 FileName::DocTest(path, line)
468 }
469
470 pub fn inline_asm_source_code(src: &str) -> FileName {
471 let mut hasher = StableHasher::new();
472 src.hash(&mut hasher);
473 FileName::InlineAsm(hasher.finish())
474 }
475
476 pub fn into_local_path(self) -> Option<PathBuf> {
480 match self {
481 FileName::Real(path) => path.into_local_path(),
482 FileName::DocTest(path, _) => Some(path),
483 _ => None,
484 }
485 }
486}
487
488#[derive(Clone, Copy, Hash, PartialEq, Eq)]
504#[derive_where(PartialOrd, Ord)]
505pub struct SpanData {
506 pub lo: BytePos,
507 pub hi: BytePos,
508 #[derive_where(skip)]
511 pub ctxt: SyntaxContext,
514 #[derive_where(skip)]
515 pub parent: Option<LocalDefId>,
518}
519
520impl SpanData {
521 #[inline]
522 pub fn span(&self) -> Span {
523 Span::new(self.lo, self.hi, self.ctxt, self.parent)
524 }
525 #[inline]
526 pub fn with_lo(&self, lo: BytePos) -> Span {
527 Span::new(lo, self.hi, self.ctxt, self.parent)
528 }
529 #[inline]
530 pub fn with_hi(&self, hi: BytePos) -> Span {
531 Span::new(self.lo, hi, self.ctxt, self.parent)
532 }
533 #[inline]
535 fn with_ctxt(&self, ctxt: SyntaxContext) -> Span {
536 Span::new(self.lo, self.hi, ctxt, self.parent)
537 }
538 #[inline]
540 fn with_parent(&self, parent: Option<LocalDefId>) -> Span {
541 Span::new(self.lo, self.hi, self.ctxt, parent)
542 }
543 #[inline]
545 pub fn is_dummy(self) -> bool {
546 self.lo.0 == 0 && self.hi.0 == 0
547 }
548 pub fn contains(self, other: Self) -> bool {
550 self.lo <= other.lo && other.hi <= self.hi
551 }
552}
553
554impl Default for SpanData {
555 fn default() -> Self {
556 Self { lo: BytePos(0), hi: BytePos(0), ctxt: SyntaxContext::root(), parent: None }
557 }
558}
559
560impl PartialOrd for Span {
561 fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
562 PartialOrd::partial_cmp(&self.data(), &rhs.data())
563 }
564}
565impl Ord for Span {
566 fn cmp(&self, rhs: &Self) -> Ordering {
567 Ord::cmp(&self.data(), &rhs.data())
568 }
569}
570
571impl Span {
572 #[inline]
573 pub fn lo(self) -> BytePos {
574 self.data().lo
575 }
576 #[inline]
577 pub fn with_lo(self, lo: BytePos) -> Span {
578 self.data().with_lo(lo)
579 }
580 #[inline]
581 pub fn hi(self) -> BytePos {
582 self.data().hi
583 }
584 #[inline]
585 pub fn with_hi(self, hi: BytePos) -> Span {
586 self.data().with_hi(hi)
587 }
588 #[inline]
589 pub fn with_ctxt(self, ctxt: SyntaxContext) -> Span {
590 self.map_ctxt(|_| ctxt)
591 }
592
593 #[inline]
594 pub fn is_visible(self, sm: &SourceMap) -> bool {
595 !self.is_dummy() && sm.is_span_accessible(self)
596 }
597
598 #[inline]
603 pub fn in_external_macro(self, sm: &SourceMap) -> bool {
604 self.ctxt().in_external_macro(sm)
605 }
606
607 pub fn in_derive_expansion(self) -> bool {
609 matches!(self.ctxt().outer_expn_data().kind, ExpnKind::Macro(MacroKind::Derive, _))
610 }
611
612 pub fn is_from_async_await(self) -> bool {
614 matches!(
615 self.ctxt().outer_expn_data().kind,
616 ExpnKind::Desugaring(DesugaringKind::Async | DesugaringKind::Await),
617 )
618 }
619
620 pub fn can_be_used_for_suggestions(self) -> bool {
622 !self.from_expansion()
623 || (self.in_derive_expansion()
627 && self.parent_callsite().map(|p| (p.lo(), p.hi())) != Some((self.lo(), self.hi())))
628 }
629
630 #[inline]
631 pub fn with_root_ctxt(lo: BytePos, hi: BytePos) -> Span {
632 Span::new(lo, hi, SyntaxContext::root(), None)
633 }
634
635 #[inline]
637 pub fn shrink_to_lo(self) -> Span {
638 let span = self.data_untracked();
639 span.with_hi(span.lo)
640 }
641 #[inline]
643 pub fn shrink_to_hi(self) -> Span {
644 let span = self.data_untracked();
645 span.with_lo(span.hi)
646 }
647
648 #[inline]
649 pub fn is_empty(self) -> bool {
651 let span = self.data_untracked();
652 span.hi == span.lo
653 }
654
655 pub fn substitute_dummy(self, other: Span) -> Span {
657 if self.is_dummy() { other } else { self }
658 }
659
660 pub fn contains(self, other: Span) -> bool {
662 let span = self.data();
663 let other = other.data();
664 span.contains(other)
665 }
666
667 pub fn overlaps(self, other: Span) -> bool {
669 let span = self.data();
670 let other = other.data();
671 span.lo < other.hi && other.lo < span.hi
672 }
673
674 pub fn overlaps_or_adjacent(self, other: Span) -> bool {
676 let span = self.data();
677 let other = other.data();
678 span.lo <= other.hi && other.lo <= span.hi
679 }
680
681 pub fn source_equal(self, other: Span) -> bool {
686 let span = self.data();
687 let other = other.data();
688 span.lo == other.lo && span.hi == other.hi
689 }
690
691 pub fn trim_start(self, other: Span) -> Option<Span> {
693 let span = self.data();
694 let other = other.data();
695 if span.hi > other.hi { Some(span.with_lo(cmp::max(span.lo, other.hi))) } else { None }
696 }
697
698 pub fn trim_end(self, other: Span) -> Option<Span> {
700 let span = self.data();
701 let other = other.data();
702 if span.lo < other.lo { Some(span.with_hi(cmp::min(span.hi, other.lo))) } else { None }
703 }
704
705 pub fn source_callsite(self) -> Span {
708 let ctxt = self.ctxt();
709 if !ctxt.is_root() { ctxt.outer_expn_data().call_site.source_callsite() } else { self }
710 }
711
712 pub fn parent_callsite(self) -> Option<Span> {
715 let ctxt = self.ctxt();
716 (!ctxt.is_root()).then(|| ctxt.outer_expn_data().call_site)
717 }
718
719 pub fn find_ancestor_inside(mut self, outer: Span) -> Option<Span> {
732 while !outer.contains(self) {
733 self = self.parent_callsite()?;
734 }
735 Some(self)
736 }
737
738 pub fn find_ancestor_in_same_ctxt(mut self, other: Span) -> Option<Span> {
751 while !self.eq_ctxt(other) {
752 self = self.parent_callsite()?;
753 }
754 Some(self)
755 }
756
757 pub fn find_ancestor_inside_same_ctxt(mut self, outer: Span) -> Option<Span> {
770 while !outer.contains(self) || !self.eq_ctxt(outer) {
771 self = self.parent_callsite()?;
772 }
773 Some(self)
774 }
775
776 pub fn find_ancestor_not_from_extern_macro(mut self, sm: &SourceMap) -> Option<Span> {
790 while self.in_external_macro(sm) {
791 self = self.parent_callsite()?;
792 }
793 Some(self)
794 }
795
796 pub fn find_ancestor_not_from_macro(mut self) -> Option<Span> {
809 while self.from_expansion() {
810 self = self.parent_callsite()?;
811 }
812 Some(self)
813 }
814
815 pub fn edition(self) -> edition::Edition {
817 self.ctxt().edition()
818 }
819
820 #[inline]
822 pub fn is_rust_2015(self) -> bool {
823 self.edition().is_rust_2015()
824 }
825
826 #[inline]
828 pub fn at_least_rust_2018(self) -> bool {
829 self.edition().at_least_rust_2018()
830 }
831
832 #[inline]
834 pub fn at_least_rust_2021(self) -> bool {
835 self.edition().at_least_rust_2021()
836 }
837
838 #[inline]
840 pub fn at_least_rust_2024(self) -> bool {
841 self.edition().at_least_rust_2024()
842 }
843
844 pub fn source_callee(self) -> Option<ExpnData> {
850 let mut ctxt = self.ctxt();
851 let mut opt_expn_data = None;
852 while !ctxt.is_root() {
853 let expn_data = ctxt.outer_expn_data();
854 ctxt = expn_data.call_site.ctxt();
855 opt_expn_data = Some(expn_data);
856 }
857 opt_expn_data
858 }
859
860 pub fn allows_unstable(self, feature: Symbol) -> bool {
864 self.ctxt()
865 .outer_expn_data()
866 .allow_internal_unstable
867 .is_some_and(|features| features.contains(&feature))
868 }
869
870 pub fn is_desugaring(self, kind: DesugaringKind) -> bool {
872 match self.ctxt().outer_expn_data().kind {
873 ExpnKind::Desugaring(k) => k == kind,
874 _ => false,
875 }
876 }
877
878 pub fn desugaring_kind(self) -> Option<DesugaringKind> {
881 match self.ctxt().outer_expn_data().kind {
882 ExpnKind::Desugaring(k) => Some(k),
883 _ => None,
884 }
885 }
886
887 pub fn allows_unsafe(self) -> bool {
891 self.ctxt().outer_expn_data().allow_internal_unsafe
892 }
893
894 pub fn macro_backtrace(mut self) -> impl Iterator<Item = ExpnData> {
895 let mut prev_span = DUMMY_SP;
896 iter::from_fn(move || {
897 loop {
898 let ctxt = self.ctxt();
899 if ctxt.is_root() {
900 return None;
901 }
902
903 let expn_data = ctxt.outer_expn_data();
904 let is_recursive = expn_data.call_site.source_equal(prev_span);
905
906 prev_span = self;
907 self = expn_data.call_site;
908
909 if !is_recursive {
911 return Some(expn_data);
912 }
913 }
914 })
915 }
916
917 pub fn split_at(self, pos: u32) -> (Span, Span) {
919 let len = self.hi().0 - self.lo().0;
920 debug_assert!(pos <= len);
921
922 let split_pos = BytePos(self.lo().0 + pos);
923 (
924 Span::new(self.lo(), split_pos, self.ctxt(), self.parent()),
925 Span::new(split_pos, self.hi(), self.ctxt(), self.parent()),
926 )
927 }
928
929 fn try_metavars(a: SpanData, b: SpanData, a_orig: Span, b_orig: Span) -> (SpanData, SpanData) {
931 match with_metavar_spans(|mspans| (mspans.get(a_orig), mspans.get(b_orig))) {
932 (None, None) => {}
933 (Some(meta_a), None) => {
934 let meta_a = meta_a.data();
935 if meta_a.ctxt == b.ctxt {
936 return (meta_a, b);
937 }
938 }
939 (None, Some(meta_b)) => {
940 let meta_b = meta_b.data();
941 if a.ctxt == meta_b.ctxt {
942 return (a, meta_b);
943 }
944 }
945 (Some(meta_a), Some(meta_b)) => {
946 let meta_b = meta_b.data();
947 if a.ctxt == meta_b.ctxt {
948 return (a, meta_b);
949 }
950 let meta_a = meta_a.data();
951 if meta_a.ctxt == b.ctxt {
952 return (meta_a, b);
953 } else if meta_a.ctxt == meta_b.ctxt {
954 return (meta_a, meta_b);
955 }
956 }
957 }
958
959 (a, b)
960 }
961
962 fn prepare_to_combine(
964 a_orig: Span,
965 b_orig: Span,
966 ) -> Result<(SpanData, SpanData, Option<LocalDefId>), Span> {
967 let (a, b) = (a_orig.data(), b_orig.data());
968 if a.ctxt == b.ctxt {
969 return Ok((a, b, if a.parent == b.parent { a.parent } else { None }));
970 }
971
972 let (a, b) = Span::try_metavars(a, b, a_orig, b_orig);
973 if a.ctxt == b.ctxt {
974 return Ok((a, b, if a.parent == b.parent { a.parent } else { None }));
975 }
976
977 let a_is_callsite = a.ctxt.is_root() || a.ctxt == b.span().source_callsite().ctxt();
985 Err(if a_is_callsite { b_orig } else { a_orig })
986 }
987
988 pub fn with_neighbor(self, neighbor: Span) -> Span {
990 match Span::prepare_to_combine(self, neighbor) {
991 Ok((this, ..)) => this.span(),
992 Err(_) => self,
993 }
994 }
995
996 pub fn to(self, end: Span) -> Span {
1007 match Span::prepare_to_combine(self, end) {
1008 Ok((from, to, parent)) => {
1009 Span::new(cmp::min(from.lo, to.lo), cmp::max(from.hi, to.hi), from.ctxt, parent)
1010 }
1011 Err(fallback) => fallback,
1012 }
1013 }
1014
1015 pub fn between(self, end: Span) -> Span {
1023 match Span::prepare_to_combine(self, end) {
1024 Ok((from, to, parent)) => {
1025 Span::new(cmp::min(from.hi, to.hi), cmp::max(from.lo, to.lo), from.ctxt, parent)
1026 }
1027 Err(fallback) => fallback,
1028 }
1029 }
1030
1031 pub fn until(self, end: Span) -> Span {
1039 match Span::prepare_to_combine(self, end) {
1040 Ok((from, to, parent)) => {
1041 Span::new(cmp::min(from.lo, to.lo), cmp::max(from.lo, to.lo), from.ctxt, parent)
1042 }
1043 Err(fallback) => fallback,
1044 }
1045 }
1046
1047 pub fn within_macro(self, within: Span, sm: &SourceMap) -> Option<Span> {
1062 match Span::prepare_to_combine(self, within) {
1063 Ok((self_, _, parent))
1070 if self_.hi < self.lo() || self.hi() < self_.lo && !sm.is_imported(within) =>
1071 {
1072 Some(Span::new(self_.lo, self_.hi, self_.ctxt, parent))
1073 }
1074 _ => None,
1075 }
1076 }
1077
1078 pub fn from_inner(self, inner: InnerSpan) -> Span {
1079 let span = self.data();
1080 Span::new(
1081 span.lo + BytePos::from_usize(inner.start),
1082 span.lo + BytePos::from_usize(inner.end),
1083 span.ctxt,
1084 span.parent,
1085 )
1086 }
1087
1088 pub fn with_def_site_ctxt(self, expn_id: ExpnId) -> Span {
1091 self.with_ctxt_from_mark(expn_id, Transparency::Opaque)
1092 }
1093
1094 pub fn with_call_site_ctxt(self, expn_id: ExpnId) -> Span {
1097 self.with_ctxt_from_mark(expn_id, Transparency::Transparent)
1098 }
1099
1100 pub fn with_mixed_site_ctxt(self, expn_id: ExpnId) -> Span {
1103 self.with_ctxt_from_mark(expn_id, Transparency::SemiOpaque)
1104 }
1105
1106 fn with_ctxt_from_mark(self, expn_id: ExpnId, transparency: Transparency) -> Span {
1110 self.with_ctxt(SyntaxContext::root().apply_mark(expn_id, transparency))
1111 }
1112
1113 #[inline]
1114 pub fn apply_mark(self, expn_id: ExpnId, transparency: Transparency) -> Span {
1115 self.map_ctxt(|ctxt| ctxt.apply_mark(expn_id, transparency))
1116 }
1117
1118 #[inline]
1119 pub fn remove_mark(&mut self) -> ExpnId {
1120 let mut mark = ExpnId::root();
1121 *self = self.map_ctxt(|mut ctxt| {
1122 mark = ctxt.remove_mark();
1123 ctxt
1124 });
1125 mark
1126 }
1127
1128 #[inline]
1129 pub fn adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> {
1130 let mut mark = None;
1131 *self = self.map_ctxt(|mut ctxt| {
1132 mark = ctxt.adjust(expn_id);
1133 ctxt
1134 });
1135 mark
1136 }
1137
1138 #[inline]
1139 pub fn normalize_to_macros_2_0_and_adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> {
1140 let mut mark = None;
1141 *self = self.map_ctxt(|mut ctxt| {
1142 mark = ctxt.normalize_to_macros_2_0_and_adjust(expn_id);
1143 ctxt
1144 });
1145 mark
1146 }
1147
1148 #[inline]
1149 pub fn glob_adjust(&mut self, expn_id: ExpnId, glob_span: Span) -> Option<Option<ExpnId>> {
1150 let mut mark = None;
1151 *self = self.map_ctxt(|mut ctxt| {
1152 mark = ctxt.glob_adjust(expn_id, glob_span);
1153 ctxt
1154 });
1155 mark
1156 }
1157
1158 #[inline]
1159 pub fn reverse_glob_adjust(
1160 &mut self,
1161 expn_id: ExpnId,
1162 glob_span: Span,
1163 ) -> Option<Option<ExpnId>> {
1164 let mut mark = None;
1165 *self = self.map_ctxt(|mut ctxt| {
1166 mark = ctxt.reverse_glob_adjust(expn_id, glob_span);
1167 ctxt
1168 });
1169 mark
1170 }
1171
1172 #[inline]
1173 pub fn normalize_to_macros_2_0(self) -> Span {
1174 self.map_ctxt(|ctxt| ctxt.normalize_to_macros_2_0())
1175 }
1176
1177 #[inline]
1178 pub fn normalize_to_macro_rules(self) -> Span {
1179 self.map_ctxt(|ctxt| ctxt.normalize_to_macro_rules())
1180 }
1181}
1182
1183impl Default for Span {
1184 fn default() -> Self {
1185 DUMMY_SP
1186 }
1187}
1188
1189rustc_index::newtype_index! {
1190 #[orderable]
1191 #[debug_format = "AttrId({})"]
1192 pub struct AttrId {}
1193}
1194
1195pub trait SpanEncoder: Encoder {
1198 fn encode_span(&mut self, span: Span);
1199 fn encode_symbol(&mut self, sym: Symbol);
1200 fn encode_byte_symbol(&mut self, byte_sym: ByteSymbol);
1201 fn encode_expn_id(&mut self, expn_id: ExpnId);
1202 fn encode_syntax_context(&mut self, syntax_context: SyntaxContext);
1203 fn encode_crate_num(&mut self, crate_num: CrateNum);
1206 fn encode_def_index(&mut self, def_index: DefIndex);
1207 fn encode_def_id(&mut self, def_id: DefId);
1208}
1209
1210impl SpanEncoder for FileEncoder {
1211 fn encode_span(&mut self, span: Span) {
1212 let span = span.data();
1213 span.lo.encode(self);
1214 span.hi.encode(self);
1215 }
1216
1217 fn encode_symbol(&mut self, sym: Symbol) {
1218 self.emit_str(sym.as_str());
1219 }
1220
1221 fn encode_byte_symbol(&mut self, byte_sym: ByteSymbol) {
1222 self.emit_byte_str(byte_sym.as_byte_str());
1223 }
1224
1225 fn encode_expn_id(&mut self, _expn_id: ExpnId) {
1226 panic!("cannot encode `ExpnId` with `FileEncoder`");
1227 }
1228
1229 fn encode_syntax_context(&mut self, _syntax_context: SyntaxContext) {
1230 panic!("cannot encode `SyntaxContext` with `FileEncoder`");
1231 }
1232
1233 fn encode_crate_num(&mut self, crate_num: CrateNum) {
1234 self.emit_u32(crate_num.as_u32());
1235 }
1236
1237 fn encode_def_index(&mut self, _def_index: DefIndex) {
1238 panic!("cannot encode `DefIndex` with `FileEncoder`");
1239 }
1240
1241 fn encode_def_id(&mut self, def_id: DefId) {
1242 def_id.krate.encode(self);
1243 def_id.index.encode(self);
1244 }
1245}
1246
1247impl<E: SpanEncoder> Encodable<E> for Span {
1248 fn encode(&self, s: &mut E) {
1249 s.encode_span(*self);
1250 }
1251}
1252
1253impl<E: SpanEncoder> Encodable<E> for Symbol {
1254 fn encode(&self, s: &mut E) {
1255 s.encode_symbol(*self);
1256 }
1257}
1258
1259impl<E: SpanEncoder> Encodable<E> for ByteSymbol {
1260 fn encode(&self, s: &mut E) {
1261 s.encode_byte_symbol(*self);
1262 }
1263}
1264
1265impl<E: SpanEncoder> Encodable<E> for ExpnId {
1266 fn encode(&self, s: &mut E) {
1267 s.encode_expn_id(*self)
1268 }
1269}
1270
1271impl<E: SpanEncoder> Encodable<E> for SyntaxContext {
1272 fn encode(&self, s: &mut E) {
1273 s.encode_syntax_context(*self)
1274 }
1275}
1276
1277impl<E: SpanEncoder> Encodable<E> for CrateNum {
1278 fn encode(&self, s: &mut E) {
1279 s.encode_crate_num(*self)
1280 }
1281}
1282
1283impl<E: SpanEncoder> Encodable<E> for DefIndex {
1284 fn encode(&self, s: &mut E) {
1285 s.encode_def_index(*self)
1286 }
1287}
1288
1289impl<E: SpanEncoder> Encodable<E> for DefId {
1290 fn encode(&self, s: &mut E) {
1291 s.encode_def_id(*self)
1292 }
1293}
1294
1295impl<E: SpanEncoder> Encodable<E> for AttrId {
1296 fn encode(&self, _s: &mut E) {
1297 }
1299}
1300
1301pub trait SpanDecoder: Decoder {
1304 fn decode_span(&mut self) -> Span;
1305 fn decode_symbol(&mut self) -> Symbol;
1306 fn decode_byte_symbol(&mut self) -> ByteSymbol;
1307 fn decode_expn_id(&mut self) -> ExpnId;
1308 fn decode_syntax_context(&mut self) -> SyntaxContext;
1309 fn decode_crate_num(&mut self) -> CrateNum;
1310 fn decode_def_index(&mut self) -> DefIndex;
1311 fn decode_def_id(&mut self) -> DefId;
1312 fn decode_attr_id(&mut self) -> AttrId;
1313}
1314
1315impl SpanDecoder for MemDecoder<'_> {
1316 fn decode_span(&mut self) -> Span {
1317 let lo = Decodable::decode(self);
1318 let hi = Decodable::decode(self);
1319
1320 Span::new(lo, hi, SyntaxContext::root(), None)
1321 }
1322
1323 fn decode_symbol(&mut self) -> Symbol {
1324 Symbol::intern(self.read_str())
1325 }
1326
1327 fn decode_byte_symbol(&mut self) -> ByteSymbol {
1328 ByteSymbol::intern(self.read_byte_str())
1329 }
1330
1331 fn decode_expn_id(&mut self) -> ExpnId {
1332 panic!("cannot decode `ExpnId` with `MemDecoder`");
1333 }
1334
1335 fn decode_syntax_context(&mut self) -> SyntaxContext {
1336 panic!("cannot decode `SyntaxContext` with `MemDecoder`");
1337 }
1338
1339 fn decode_crate_num(&mut self) -> CrateNum {
1340 CrateNum::from_u32(self.read_u32())
1341 }
1342
1343 fn decode_def_index(&mut self) -> DefIndex {
1344 panic!("cannot decode `DefIndex` with `MemDecoder`");
1345 }
1346
1347 fn decode_def_id(&mut self) -> DefId {
1348 DefId { krate: Decodable::decode(self), index: Decodable::decode(self) }
1349 }
1350
1351 fn decode_attr_id(&mut self) -> AttrId {
1352 panic!("cannot decode `AttrId` with `MemDecoder`");
1353 }
1354}
1355
1356impl<D: SpanDecoder> Decodable<D> for Span {
1357 fn decode(s: &mut D) -> Span {
1358 s.decode_span()
1359 }
1360}
1361
1362impl<D: SpanDecoder> Decodable<D> for Symbol {
1363 fn decode(s: &mut D) -> Symbol {
1364 s.decode_symbol()
1365 }
1366}
1367
1368impl<D: SpanDecoder> Decodable<D> for ByteSymbol {
1369 fn decode(s: &mut D) -> ByteSymbol {
1370 s.decode_byte_symbol()
1371 }
1372}
1373
1374impl<D: SpanDecoder> Decodable<D> for ExpnId {
1375 fn decode(s: &mut D) -> ExpnId {
1376 s.decode_expn_id()
1377 }
1378}
1379
1380impl<D: SpanDecoder> Decodable<D> for SyntaxContext {
1381 fn decode(s: &mut D) -> SyntaxContext {
1382 s.decode_syntax_context()
1383 }
1384}
1385
1386impl<D: SpanDecoder> Decodable<D> for CrateNum {
1387 fn decode(s: &mut D) -> CrateNum {
1388 s.decode_crate_num()
1389 }
1390}
1391
1392impl<D: SpanDecoder> Decodable<D> for DefIndex {
1393 fn decode(s: &mut D) -> DefIndex {
1394 s.decode_def_index()
1395 }
1396}
1397
1398impl<D: SpanDecoder> Decodable<D> for DefId {
1399 fn decode(s: &mut D) -> DefId {
1400 s.decode_def_id()
1401 }
1402}
1403
1404impl<D: SpanDecoder> Decodable<D> for AttrId {
1405 fn decode(s: &mut D) -> AttrId {
1406 s.decode_attr_id()
1407 }
1408}
1409
1410impl fmt::Debug for Span {
1411 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1412 fn fallback(span: Span, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1416 f.debug_struct("Span")
1417 .field("lo", &span.lo())
1418 .field("hi", &span.hi())
1419 .field("ctxt", &span.ctxt())
1420 .finish()
1421 }
1422
1423 if SESSION_GLOBALS.is_set() {
1424 with_session_globals(|session_globals| {
1425 if let Some(source_map) = &session_globals.source_map {
1426 write!(f, "{} ({:?})", source_map.span_to_diagnostic_string(*self), self.ctxt())
1427 } else {
1428 fallback(*self, f)
1429 }
1430 })
1431 } else {
1432 fallback(*self, f)
1433 }
1434 }
1435}
1436
1437impl fmt::Debug for SpanData {
1438 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1439 fmt::Debug::fmt(&self.span(), f)
1440 }
1441}
1442
1443#[derive(Copy, Clone, Encodable, Decodable, Eq, PartialEq, Debug, HashStable_Generic)]
1445pub struct MultiByteChar {
1446 pub pos: RelativeBytePos,
1448 pub bytes: u8,
1450}
1451
1452#[derive(Copy, Clone, Encodable, Decodable, Eq, PartialEq, Debug, HashStable_Generic)]
1454pub struct NormalizedPos {
1455 pub pos: RelativeBytePos,
1457 pub diff: u32,
1459}
1460
1461#[derive(PartialEq, Eq, Clone, Debug)]
1462pub enum ExternalSource {
1463 Unneeded,
1465 Foreign {
1466 kind: ExternalSourceKind,
1467 metadata_index: u32,
1469 },
1470}
1471
1472#[derive(PartialEq, Eq, Clone, Debug)]
1474pub enum ExternalSourceKind {
1475 Present(Arc<String>),
1477 AbsentOk,
1479 AbsentErr,
1481}
1482
1483impl ExternalSource {
1484 pub fn get_source(&self) -> Option<&str> {
1485 match self {
1486 ExternalSource::Foreign { kind: ExternalSourceKind::Present(src), .. } => Some(src),
1487 _ => None,
1488 }
1489 }
1490}
1491
1492#[derive(Debug)]
1493pub struct OffsetOverflowError;
1494
1495#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
1496#[derive(HashStable_Generic)]
1497pub enum SourceFileHashAlgorithm {
1498 Md5,
1499 Sha1,
1500 Sha256,
1501 Blake3,
1502}
1503
1504impl Display for SourceFileHashAlgorithm {
1505 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1506 f.write_str(match self {
1507 Self::Md5 => "md5",
1508 Self::Sha1 => "sha1",
1509 Self::Sha256 => "sha256",
1510 Self::Blake3 => "blake3",
1511 })
1512 }
1513}
1514
1515impl FromStr for SourceFileHashAlgorithm {
1516 type Err = ();
1517
1518 fn from_str(s: &str) -> Result<SourceFileHashAlgorithm, ()> {
1519 match s {
1520 "md5" => Ok(SourceFileHashAlgorithm::Md5),
1521 "sha1" => Ok(SourceFileHashAlgorithm::Sha1),
1522 "sha256" => Ok(SourceFileHashAlgorithm::Sha256),
1523 "blake3" => Ok(SourceFileHashAlgorithm::Blake3),
1524 _ => Err(()),
1525 }
1526 }
1527}
1528
1529#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
1531#[derive(HashStable_Generic, Encodable, Decodable)]
1532pub struct SourceFileHash {
1533 pub kind: SourceFileHashAlgorithm,
1534 value: [u8; 32],
1535}
1536
1537impl Display for SourceFileHash {
1538 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1539 write!(f, "{}=", self.kind)?;
1540 for byte in self.value[0..self.hash_len()].into_iter() {
1541 write!(f, "{byte:02x}")?;
1542 }
1543 Ok(())
1544 }
1545}
1546
1547impl SourceFileHash {
1548 pub fn new_in_memory(kind: SourceFileHashAlgorithm, src: impl AsRef<[u8]>) -> SourceFileHash {
1549 let mut hash = SourceFileHash { kind, value: Default::default() };
1550 let len = hash.hash_len();
1551 let value = &mut hash.value[..len];
1552 let data = src.as_ref();
1553 match kind {
1554 SourceFileHashAlgorithm::Md5 => {
1555 value.copy_from_slice(&Md5::digest(data));
1556 }
1557 SourceFileHashAlgorithm::Sha1 => {
1558 value.copy_from_slice(&Sha1::digest(data));
1559 }
1560 SourceFileHashAlgorithm::Sha256 => {
1561 value.copy_from_slice(&Sha256::digest(data));
1562 }
1563 SourceFileHashAlgorithm::Blake3 => value.copy_from_slice(blake3::hash(data).as_bytes()),
1564 };
1565 hash
1566 }
1567
1568 pub fn new(kind: SourceFileHashAlgorithm, src: impl Read) -> Result<SourceFileHash, io::Error> {
1569 let mut hash = SourceFileHash { kind, value: Default::default() };
1570 let len = hash.hash_len();
1571 let value = &mut hash.value[..len];
1572 let mut buf = vec![0; 16 * 1024];
1575
1576 fn digest<T>(
1577 mut hasher: T,
1578 mut update: impl FnMut(&mut T, &[u8]),
1579 finish: impl FnOnce(T, &mut [u8]),
1580 mut src: impl Read,
1581 buf: &mut [u8],
1582 value: &mut [u8],
1583 ) -> Result<(), io::Error> {
1584 loop {
1585 let bytes_read = src.read(buf)?;
1586 if bytes_read == 0 {
1587 break;
1588 }
1589 update(&mut hasher, &buf[0..bytes_read]);
1590 }
1591 finish(hasher, value);
1592 Ok(())
1593 }
1594
1595 match kind {
1596 SourceFileHashAlgorithm::Sha256 => {
1597 digest(
1598 Sha256::new(),
1599 |h, b| {
1600 h.update(b);
1601 },
1602 |h, out| out.copy_from_slice(&h.finalize()),
1603 src,
1604 &mut buf,
1605 value,
1606 )?;
1607 }
1608 SourceFileHashAlgorithm::Sha1 => {
1609 digest(
1610 Sha1::new(),
1611 |h, b| {
1612 h.update(b);
1613 },
1614 |h, out| out.copy_from_slice(&h.finalize()),
1615 src,
1616 &mut buf,
1617 value,
1618 )?;
1619 }
1620 SourceFileHashAlgorithm::Md5 => {
1621 digest(
1622 Md5::new(),
1623 |h, b| {
1624 h.update(b);
1625 },
1626 |h, out| out.copy_from_slice(&h.finalize()),
1627 src,
1628 &mut buf,
1629 value,
1630 )?;
1631 }
1632 SourceFileHashAlgorithm::Blake3 => {
1633 digest(
1634 blake3::Hasher::new(),
1635 |h, b| {
1636 h.update(b);
1637 },
1638 |h, out| out.copy_from_slice(h.finalize().as_bytes()),
1639 src,
1640 &mut buf,
1641 value,
1642 )?;
1643 }
1644 }
1645 Ok(hash)
1646 }
1647
1648 pub fn matches(&self, src: &str) -> bool {
1650 Self::new_in_memory(self.kind, src.as_bytes()) == *self
1651 }
1652
1653 pub fn hash_bytes(&self) -> &[u8] {
1655 let len = self.hash_len();
1656 &self.value[..len]
1657 }
1658
1659 fn hash_len(&self) -> usize {
1660 match self.kind {
1661 SourceFileHashAlgorithm::Md5 => 16,
1662 SourceFileHashAlgorithm::Sha1 => 20,
1663 SourceFileHashAlgorithm::Sha256 | SourceFileHashAlgorithm::Blake3 => 32,
1664 }
1665 }
1666}
1667
1668#[derive(Clone)]
1669pub enum SourceFileLines {
1670 Lines(Vec<RelativeBytePos>),
1672
1673 Diffs(SourceFileDiffs),
1675}
1676
1677impl SourceFileLines {
1678 pub fn is_lines(&self) -> bool {
1679 matches!(self, SourceFileLines::Lines(_))
1680 }
1681}
1682
1683#[derive(Clone)]
1691pub struct SourceFileDiffs {
1692 bytes_per_diff: usize,
1696
1697 num_diffs: usize,
1700
1701 raw_diffs: Vec<u8>,
1707}
1708
1709pub struct SourceFile {
1711 pub name: FileName,
1715 pub src: Option<Arc<String>>,
1717 pub src_hash: SourceFileHash,
1719 pub checksum_hash: Option<SourceFileHash>,
1723 pub external_src: FreezeLock<ExternalSource>,
1726 pub start_pos: BytePos,
1728 pub source_len: RelativeBytePos,
1730 pub lines: FreezeLock<SourceFileLines>,
1732 pub multibyte_chars: Vec<MultiByteChar>,
1734 pub normalized_pos: Vec<NormalizedPos>,
1736 pub stable_id: StableSourceFileId,
1740 pub cnum: CrateNum,
1742}
1743
1744impl Clone for SourceFile {
1745 fn clone(&self) -> Self {
1746 Self {
1747 name: self.name.clone(),
1748 src: self.src.clone(),
1749 src_hash: self.src_hash,
1750 checksum_hash: self.checksum_hash,
1751 external_src: self.external_src.clone(),
1752 start_pos: self.start_pos,
1753 source_len: self.source_len,
1754 lines: self.lines.clone(),
1755 multibyte_chars: self.multibyte_chars.clone(),
1756 normalized_pos: self.normalized_pos.clone(),
1757 stable_id: self.stable_id,
1758 cnum: self.cnum,
1759 }
1760 }
1761}
1762
1763impl<S: SpanEncoder> Encodable<S> for SourceFile {
1764 fn encode(&self, s: &mut S) {
1765 self.name.encode(s);
1766 self.src_hash.encode(s);
1767 self.checksum_hash.encode(s);
1768 self.source_len.encode(s);
1770
1771 assert!(self.lines.read().is_lines());
1773 let lines = self.lines();
1774 s.emit_u32(lines.len() as u32);
1776
1777 if lines.len() != 0 {
1779 let max_line_length = if lines.len() == 1 {
1780 0
1781 } else {
1782 lines
1783 .array_windows()
1784 .map(|&[fst, snd]| snd - fst)
1785 .map(|bp| bp.to_usize())
1786 .max()
1787 .unwrap()
1788 };
1789
1790 let bytes_per_diff: usize = match max_line_length {
1791 0..=0xFF => 1,
1792 0x100..=0xFFFF => 2,
1793 _ => 4,
1794 };
1795
1796 s.emit_u8(bytes_per_diff as u8);
1798
1799 assert_eq!(lines[0], RelativeBytePos(0));
1801
1802 let diff_iter = lines.array_windows().map(|&[fst, snd]| snd - fst);
1804 let num_diffs = lines.len() - 1;
1805 let mut raw_diffs;
1806 match bytes_per_diff {
1807 1 => {
1808 raw_diffs = Vec::with_capacity(num_diffs);
1809 for diff in diff_iter {
1810 raw_diffs.push(diff.0 as u8);
1811 }
1812 }
1813 2 => {
1814 raw_diffs = Vec::with_capacity(bytes_per_diff * num_diffs);
1815 for diff in diff_iter {
1816 raw_diffs.extend_from_slice(&(diff.0 as u16).to_le_bytes());
1817 }
1818 }
1819 4 => {
1820 raw_diffs = Vec::with_capacity(bytes_per_diff * num_diffs);
1821 for diff in diff_iter {
1822 raw_diffs.extend_from_slice(&(diff.0).to_le_bytes());
1823 }
1824 }
1825 _ => unreachable!(),
1826 }
1827 s.emit_raw_bytes(&raw_diffs);
1828 }
1829
1830 self.multibyte_chars.encode(s);
1831 self.stable_id.encode(s);
1832 self.normalized_pos.encode(s);
1833 self.cnum.encode(s);
1834 }
1835}
1836
1837impl<D: SpanDecoder> Decodable<D> for SourceFile {
1838 fn decode(d: &mut D) -> SourceFile {
1839 let name: FileName = Decodable::decode(d);
1840 let src_hash: SourceFileHash = Decodable::decode(d);
1841 let checksum_hash: Option<SourceFileHash> = Decodable::decode(d);
1842 let source_len: RelativeBytePos = Decodable::decode(d);
1843 let lines = {
1844 let num_lines: u32 = Decodable::decode(d);
1845 if num_lines > 0 {
1846 let bytes_per_diff = d.read_u8() as usize;
1848
1849 let num_diffs = num_lines as usize - 1;
1851 let raw_diffs = d.read_raw_bytes(bytes_per_diff * num_diffs).to_vec();
1852 SourceFileLines::Diffs(SourceFileDiffs { bytes_per_diff, num_diffs, raw_diffs })
1853 } else {
1854 SourceFileLines::Lines(vec![])
1855 }
1856 };
1857 let multibyte_chars: Vec<MultiByteChar> = Decodable::decode(d);
1858 let stable_id = Decodable::decode(d);
1859 let normalized_pos: Vec<NormalizedPos> = Decodable::decode(d);
1860 let cnum: CrateNum = Decodable::decode(d);
1861 SourceFile {
1862 name,
1863 start_pos: BytePos::from_u32(0),
1864 source_len,
1865 src: None,
1866 src_hash,
1867 checksum_hash,
1868 external_src: FreezeLock::frozen(ExternalSource::Unneeded),
1871 lines: FreezeLock::new(lines),
1872 multibyte_chars,
1873 normalized_pos,
1874 stable_id,
1875 cnum,
1876 }
1877 }
1878}
1879
1880impl fmt::Debug for SourceFile {
1881 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1882 write!(fmt, "SourceFile({:?})", self.name)
1883 }
1884}
1885
1886#[derive(
1908 Debug,
1909 Clone,
1910 Copy,
1911 Hash,
1912 PartialEq,
1913 Eq,
1914 HashStable_Generic,
1915 Encodable,
1916 Decodable,
1917 Default,
1918 PartialOrd,
1919 Ord
1920)]
1921pub struct StableSourceFileId(Hash128);
1922
1923impl StableSourceFileId {
1924 fn from_filename_in_current_crate(filename: &FileName) -> Self {
1925 Self::from_filename_and_stable_crate_id(filename, None)
1926 }
1927
1928 pub fn from_filename_for_export(
1929 filename: &FileName,
1930 local_crate_stable_crate_id: StableCrateId,
1931 ) -> Self {
1932 Self::from_filename_and_stable_crate_id(filename, Some(local_crate_stable_crate_id))
1933 }
1934
1935 fn from_filename_and_stable_crate_id(
1936 filename: &FileName,
1937 stable_crate_id: Option<StableCrateId>,
1938 ) -> Self {
1939 let mut hasher = StableHasher::new();
1940 filename.hash(&mut hasher);
1941 stable_crate_id.hash(&mut hasher);
1942 StableSourceFileId(hasher.finish())
1943 }
1944}
1945
1946impl SourceFile {
1947 const MAX_FILE_SIZE: u32 = u32::MAX - 1;
1948
1949 pub fn new(
1950 name: FileName,
1951 mut src: String,
1952 hash_kind: SourceFileHashAlgorithm,
1953 checksum_hash_kind: Option<SourceFileHashAlgorithm>,
1954 ) -> Result<Self, OffsetOverflowError> {
1955 let src_hash = SourceFileHash::new_in_memory(hash_kind, src.as_bytes());
1957 let checksum_hash = checksum_hash_kind.map(|checksum_hash_kind| {
1958 if checksum_hash_kind == hash_kind {
1959 src_hash
1960 } else {
1961 SourceFileHash::new_in_memory(checksum_hash_kind, src.as_bytes())
1962 }
1963 });
1964 let normalized_pos = normalize_src(&mut src);
1965
1966 let stable_id = StableSourceFileId::from_filename_in_current_crate(&name);
1967 let source_len = src.len();
1968 let source_len = u32::try_from(source_len).map_err(|_| OffsetOverflowError)?;
1969 if source_len > Self::MAX_FILE_SIZE {
1970 return Err(OffsetOverflowError);
1971 }
1972
1973 let (lines, multibyte_chars) = analyze_source_file::analyze_source_file(&src);
1974
1975 Ok(SourceFile {
1976 name,
1977 src: Some(Arc::new(src)),
1978 src_hash,
1979 checksum_hash,
1980 external_src: FreezeLock::frozen(ExternalSource::Unneeded),
1981 start_pos: BytePos::from_u32(0),
1982 source_len: RelativeBytePos::from_u32(source_len),
1983 lines: FreezeLock::frozen(SourceFileLines::Lines(lines)),
1984 multibyte_chars,
1985 normalized_pos,
1986 stable_id,
1987 cnum: LOCAL_CRATE,
1988 })
1989 }
1990
1991 fn convert_diffs_to_lines_frozen(&self) {
1994 let mut guard = if let Some(guard) = self.lines.try_write() { guard } else { return };
1995
1996 let SourceFileDiffs { bytes_per_diff, num_diffs, raw_diffs } = match &*guard {
1997 SourceFileLines::Diffs(diffs) => diffs,
1998 SourceFileLines::Lines(..) => {
1999 FreezeWriteGuard::freeze(guard);
2000 return;
2001 }
2002 };
2003
2004 let num_lines = num_diffs + 1;
2006 let mut lines = Vec::with_capacity(num_lines);
2007 let mut line_start = RelativeBytePos(0);
2008 lines.push(line_start);
2009
2010 assert_eq!(*num_diffs, raw_diffs.len() / bytes_per_diff);
2011 match bytes_per_diff {
2012 1 => {
2013 lines.extend(raw_diffs.into_iter().map(|&diff| {
2014 line_start = line_start + RelativeBytePos(diff as u32);
2015 line_start
2016 }));
2017 }
2018 2 => {
2019 lines.extend((0..*num_diffs).map(|i| {
2020 let pos = bytes_per_diff * i;
2021 let bytes = [raw_diffs[pos], raw_diffs[pos + 1]];
2022 let diff = u16::from_le_bytes(bytes);
2023 line_start = line_start + RelativeBytePos(diff as u32);
2024 line_start
2025 }));
2026 }
2027 4 => {
2028 lines.extend((0..*num_diffs).map(|i| {
2029 let pos = bytes_per_diff * i;
2030 let bytes = [
2031 raw_diffs[pos],
2032 raw_diffs[pos + 1],
2033 raw_diffs[pos + 2],
2034 raw_diffs[pos + 3],
2035 ];
2036 let diff = u32::from_le_bytes(bytes);
2037 line_start = line_start + RelativeBytePos(diff);
2038 line_start
2039 }));
2040 }
2041 _ => unreachable!(),
2042 }
2043
2044 *guard = SourceFileLines::Lines(lines);
2045
2046 FreezeWriteGuard::freeze(guard);
2047 }
2048
2049 pub fn lines(&self) -> &[RelativeBytePos] {
2050 if let Some(SourceFileLines::Lines(lines)) = self.lines.get() {
2051 return &lines[..];
2052 }
2053
2054 outline(|| {
2055 self.convert_diffs_to_lines_frozen();
2056 if let Some(SourceFileLines::Lines(lines)) = self.lines.get() {
2057 return &lines[..];
2058 }
2059 unreachable!()
2060 })
2061 }
2062
2063 pub fn line_begin_pos(&self, pos: BytePos) -> BytePos {
2065 let pos = self.relative_position(pos);
2066 let line_index = self.lookup_line(pos).unwrap();
2067 let line_start_pos = self.lines()[line_index];
2068 self.absolute_position(line_start_pos)
2069 }
2070
2071 pub fn add_external_src<F>(&self, get_src: F) -> bool
2076 where
2077 F: FnOnce() -> Option<String>,
2078 {
2079 if !self.external_src.is_frozen() {
2080 let src = get_src();
2081 let src = src.and_then(|mut src| {
2082 self.src_hash.matches(&src).then(|| {
2084 normalize_src(&mut src);
2085 src
2086 })
2087 });
2088
2089 self.external_src.try_write().map(|mut external_src| {
2090 if let ExternalSource::Foreign {
2091 kind: src_kind @ ExternalSourceKind::AbsentOk,
2092 ..
2093 } = &mut *external_src
2094 {
2095 *src_kind = if let Some(src) = src {
2096 ExternalSourceKind::Present(Arc::new(src))
2097 } else {
2098 ExternalSourceKind::AbsentErr
2099 };
2100 } else {
2101 panic!("unexpected state {:?}", *external_src)
2102 }
2103
2104 FreezeWriteGuard::freeze(external_src)
2106 });
2107 }
2108
2109 self.src.is_some() || self.external_src.read().get_source().is_some()
2110 }
2111
2112 pub fn get_line(&self, line_number: usize) -> Option<Cow<'_, str>> {
2115 fn get_until_newline(src: &str, begin: usize) -> &str {
2116 let slice = &src[begin..];
2120 match slice.find('\n') {
2121 Some(e) => &slice[..e],
2122 None => slice,
2123 }
2124 }
2125
2126 let begin = {
2127 let line = self.lines().get(line_number).copied()?;
2128 line.to_usize()
2129 };
2130
2131 if let Some(ref src) = self.src {
2132 Some(Cow::from(get_until_newline(src, begin)))
2133 } else {
2134 self.external_src
2135 .borrow()
2136 .get_source()
2137 .map(|src| Cow::Owned(String::from(get_until_newline(src, begin))))
2138 }
2139 }
2140
2141 pub fn is_real_file(&self) -> bool {
2142 self.name.is_real()
2143 }
2144
2145 #[inline]
2146 pub fn is_imported(&self) -> bool {
2147 self.src.is_none()
2148 }
2149
2150 pub fn count_lines(&self) -> usize {
2151 self.lines().len()
2152 }
2153
2154 #[inline]
2155 pub fn absolute_position(&self, pos: RelativeBytePos) -> BytePos {
2156 BytePos::from_u32(pos.to_u32() + self.start_pos.to_u32())
2157 }
2158
2159 #[inline]
2160 pub fn relative_position(&self, pos: BytePos) -> RelativeBytePos {
2161 RelativeBytePos::from_u32(pos.to_u32() - self.start_pos.to_u32())
2162 }
2163
2164 #[inline]
2165 pub fn end_position(&self) -> BytePos {
2166 self.absolute_position(self.source_len)
2167 }
2168
2169 pub fn lookup_line(&self, pos: RelativeBytePos) -> Option<usize> {
2174 self.lines().partition_point(|x| x <= &pos).checked_sub(1)
2175 }
2176
2177 pub fn line_bounds(&self, line_index: usize) -> Range<BytePos> {
2178 if self.is_empty() {
2179 return self.start_pos..self.start_pos;
2180 }
2181
2182 let lines = self.lines();
2183 assert!(line_index < lines.len());
2184 if line_index == (lines.len() - 1) {
2185 self.absolute_position(lines[line_index])..self.end_position()
2186 } else {
2187 self.absolute_position(lines[line_index])..self.absolute_position(lines[line_index + 1])
2188 }
2189 }
2190
2191 #[inline]
2196 pub fn contains(&self, byte_pos: BytePos) -> bool {
2197 byte_pos >= self.start_pos && byte_pos <= self.end_position()
2198 }
2199
2200 #[inline]
2201 pub fn is_empty(&self) -> bool {
2202 self.source_len.to_u32() == 0
2203 }
2204
2205 pub fn original_relative_byte_pos(&self, pos: BytePos) -> RelativeBytePos {
2208 let pos = self.relative_position(pos);
2209
2210 let diff = match self.normalized_pos.binary_search_by(|np| np.pos.cmp(&pos)) {
2214 Ok(i) => self.normalized_pos[i].diff,
2215 Err(0) => 0,
2216 Err(i) => self.normalized_pos[i - 1].diff,
2217 };
2218
2219 RelativeBytePos::from_u32(pos.0 + diff)
2220 }
2221
2222 pub fn normalized_byte_pos(&self, offset: u32) -> BytePos {
2232 let diff = match self
2233 .normalized_pos
2234 .binary_search_by(|np| (np.pos.0 + np.diff).cmp(&(self.start_pos.0 + offset)))
2235 {
2236 Ok(i) => self.normalized_pos[i].diff,
2237 Err(0) => 0,
2238 Err(i) => self.normalized_pos[i - 1].diff,
2239 };
2240
2241 BytePos::from_u32(self.start_pos.0 + offset - diff)
2242 }
2243
2244 fn bytepos_to_file_charpos(&self, bpos: RelativeBytePos) -> CharPos {
2246 let mut total_extra_bytes = 0;
2248
2249 for mbc in self.multibyte_chars.iter() {
2250 debug!("{}-byte char at {:?}", mbc.bytes, mbc.pos);
2251 if mbc.pos < bpos {
2252 total_extra_bytes += mbc.bytes as u32 - 1;
2255 assert!(bpos.to_u32() >= mbc.pos.to_u32() + mbc.bytes as u32);
2258 } else {
2259 break;
2260 }
2261 }
2262
2263 assert!(total_extra_bytes <= bpos.to_u32());
2264 CharPos(bpos.to_usize() - total_extra_bytes as usize)
2265 }
2266
2267 fn lookup_file_pos(&self, pos: RelativeBytePos) -> (usize, CharPos) {
2270 let chpos = self.bytepos_to_file_charpos(pos);
2271 match self.lookup_line(pos) {
2272 Some(a) => {
2273 let line = a + 1; let linebpos = self.lines()[a];
2275 let linechpos = self.bytepos_to_file_charpos(linebpos);
2276 let col = chpos - linechpos;
2277 debug!("byte pos {:?} is on the line at byte pos {:?}", pos, linebpos);
2278 debug!("char pos {:?} is on the line at char pos {:?}", chpos, linechpos);
2279 debug!("byte is on line: {}", line);
2280 assert!(chpos >= linechpos);
2281 (line, col)
2282 }
2283 None => (0, chpos),
2284 }
2285 }
2286
2287 pub fn lookup_file_pos_with_col_display(&self, pos: BytePos) -> (usize, CharPos, usize) {
2290 let pos = self.relative_position(pos);
2291 let (line, col_or_chpos) = self.lookup_file_pos(pos);
2292 if line > 0 {
2293 let Some(code) = self.get_line(line - 1) else {
2294 tracing::info!("couldn't find line {line} {:?}", self.name);
2302 return (line, col_or_chpos, col_or_chpos.0);
2303 };
2304 let display_col = code.chars().take(col_or_chpos.0).map(|ch| char_width(ch)).sum();
2305 (line, col_or_chpos, display_col)
2306 } else {
2307 (0, col_or_chpos, col_or_chpos.0)
2309 }
2310 }
2311}
2312
2313pub fn char_width(ch: char) -> usize {
2314 match ch {
2317 '\t' => 4,
2318 '\u{0000}' | '\u{0001}' | '\u{0002}' | '\u{0003}' | '\u{0004}' | '\u{0005}'
2322 | '\u{0006}' | '\u{0007}' | '\u{0008}' | '\u{000B}' | '\u{000C}' | '\u{000D}'
2323 | '\u{000E}' | '\u{000F}' | '\u{0010}' | '\u{0011}' | '\u{0012}' | '\u{0013}'
2324 | '\u{0014}' | '\u{0015}' | '\u{0016}' | '\u{0017}' | '\u{0018}' | '\u{0019}'
2325 | '\u{001A}' | '\u{001B}' | '\u{001C}' | '\u{001D}' | '\u{001E}' | '\u{001F}'
2326 | '\u{007F}' | '\u{202A}' | '\u{202B}' | '\u{202D}' | '\u{202E}' | '\u{2066}'
2327 | '\u{2067}' | '\u{2068}' | '\u{202C}' | '\u{2069}' => 1,
2328 _ => unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1),
2329 }
2330}
2331
2332pub fn str_width(s: &str) -> usize {
2333 s.chars().map(char_width).sum()
2334}
2335
2336fn normalize_src(src: &mut String) -> Vec<NormalizedPos> {
2338 let mut normalized_pos = vec![];
2339 remove_bom(src, &mut normalized_pos);
2340 normalize_newlines(src, &mut normalized_pos);
2341 normalized_pos
2342}
2343
2344fn remove_bom(src: &mut String, normalized_pos: &mut Vec<NormalizedPos>) {
2346 if src.starts_with('\u{feff}') {
2347 src.drain(..3);
2348 normalized_pos.push(NormalizedPos { pos: RelativeBytePos(0), diff: 3 });
2349 }
2350}
2351
2352fn normalize_newlines(src: &mut String, normalized_pos: &mut Vec<NormalizedPos>) {
2356 if !src.as_bytes().contains(&b'\r') {
2357 return;
2358 }
2359
2360 let mut buf = std::mem::replace(src, String::new()).into_bytes();
2366 let mut gap_len = 0;
2367 let mut tail = buf.as_mut_slice();
2368 let mut cursor = 0;
2369 let original_gap = normalized_pos.last().map_or(0, |l| l.diff);
2370 loop {
2371 let idx = match find_crlf(&tail[gap_len..]) {
2372 None => tail.len(),
2373 Some(idx) => idx + gap_len,
2374 };
2375 tail.copy_within(gap_len..idx, 0);
2376 tail = &mut tail[idx - gap_len..];
2377 if tail.len() == gap_len {
2378 break;
2379 }
2380 cursor += idx - gap_len;
2381 gap_len += 1;
2382 normalized_pos.push(NormalizedPos {
2383 pos: RelativeBytePos::from_usize(cursor + 1),
2384 diff: original_gap + gap_len as u32,
2385 });
2386 }
2387
2388 let new_len = buf.len() - gap_len;
2391 unsafe {
2392 buf.set_len(new_len);
2393 *src = String::from_utf8_unchecked(buf);
2394 }
2395
2396 fn find_crlf(src: &[u8]) -> Option<usize> {
2397 let mut search_idx = 0;
2398 while let Some(idx) = find_cr(&src[search_idx..]) {
2399 if src[search_idx..].get(idx + 1) != Some(&b'\n') {
2400 search_idx += idx + 1;
2401 continue;
2402 }
2403 return Some(search_idx + idx);
2404 }
2405 None
2406 }
2407
2408 fn find_cr(src: &[u8]) -> Option<usize> {
2409 src.iter().position(|&b| b == b'\r')
2410 }
2411}
2412
2413pub trait Pos {
2418 fn from_usize(n: usize) -> Self;
2419 fn to_usize(&self) -> usize;
2420 fn from_u32(n: u32) -> Self;
2421 fn to_u32(&self) -> u32;
2422}
2423
2424macro_rules! impl_pos {
2425 (
2426 $(
2427 $(#[$attr:meta])*
2428 $vis:vis struct $ident:ident($inner_vis:vis $inner_ty:ty);
2429 )*
2430 ) => {
2431 $(
2432 $(#[$attr])*
2433 $vis struct $ident($inner_vis $inner_ty);
2434
2435 impl Pos for $ident {
2436 #[inline(always)]
2437 fn from_usize(n: usize) -> $ident {
2438 $ident(n as $inner_ty)
2439 }
2440
2441 #[inline(always)]
2442 fn to_usize(&self) -> usize {
2443 self.0 as usize
2444 }
2445
2446 #[inline(always)]
2447 fn from_u32(n: u32) -> $ident {
2448 $ident(n as $inner_ty)
2449 }
2450
2451 #[inline(always)]
2452 fn to_u32(&self) -> u32 {
2453 self.0 as u32
2454 }
2455 }
2456
2457 impl Add for $ident {
2458 type Output = $ident;
2459
2460 #[inline(always)]
2461 fn add(self, rhs: $ident) -> $ident {
2462 $ident(self.0 + rhs.0)
2463 }
2464 }
2465
2466 impl Sub for $ident {
2467 type Output = $ident;
2468
2469 #[inline(always)]
2470 fn sub(self, rhs: $ident) -> $ident {
2471 $ident(self.0 - rhs.0)
2472 }
2473 }
2474 )*
2475 };
2476}
2477
2478impl_pos! {
2479 #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
2483 pub struct BytePos(pub u32);
2484
2485 #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
2487 pub struct RelativeBytePos(pub u32);
2488
2489 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
2495 pub struct CharPos(pub usize);
2496}
2497
2498impl<S: Encoder> Encodable<S> for BytePos {
2499 fn encode(&self, s: &mut S) {
2500 s.emit_u32(self.0);
2501 }
2502}
2503
2504impl<D: Decoder> Decodable<D> for BytePos {
2505 fn decode(d: &mut D) -> BytePos {
2506 BytePos(d.read_u32())
2507 }
2508}
2509
2510impl<H: HashStableContext> HashStable<H> for RelativeBytePos {
2511 fn hash_stable(&self, hcx: &mut H, hasher: &mut StableHasher) {
2512 self.0.hash_stable(hcx, hasher);
2513 }
2514}
2515
2516impl<S: Encoder> Encodable<S> for RelativeBytePos {
2517 fn encode(&self, s: &mut S) {
2518 s.emit_u32(self.0);
2519 }
2520}
2521
2522impl<D: Decoder> Decodable<D> for RelativeBytePos {
2523 fn decode(d: &mut D) -> RelativeBytePos {
2524 RelativeBytePos(d.read_u32())
2525 }
2526}
2527
2528#[derive(Debug, Clone)]
2534pub struct Loc {
2535 pub file: Arc<SourceFile>,
2537 pub line: usize,
2539 pub col: CharPos,
2541 pub col_display: usize,
2543}
2544
2545#[derive(Debug)]
2547pub struct SourceFileAndLine {
2548 pub sf: Arc<SourceFile>,
2549 pub line: usize,
2551}
2552#[derive(Debug)]
2553pub struct SourceFileAndBytePos {
2554 pub sf: Arc<SourceFile>,
2555 pub pos: BytePos,
2556}
2557
2558#[derive(Copy, Clone, Debug, PartialEq, Eq)]
2559pub struct LineInfo {
2560 pub line_index: usize,
2562
2563 pub start_col: CharPos,
2565
2566 pub end_col: CharPos,
2568}
2569
2570pub struct FileLines {
2571 pub file: Arc<SourceFile>,
2572 pub lines: Vec<LineInfo>,
2573}
2574
2575pub static SPAN_TRACK: AtomicRef<fn(LocalDefId)> = AtomicRef::new(&((|_| {}) as fn(_)));
2576
2577pub type FileLinesResult = Result<FileLines, SpanLinesError>;
2582
2583#[derive(Clone, PartialEq, Eq, Debug)]
2584pub enum SpanLinesError {
2585 DistinctSources(Box<DistinctSources>),
2586}
2587
2588#[derive(Clone, PartialEq, Eq, Debug)]
2589pub enum SpanSnippetError {
2590 IllFormedSpan(Span),
2591 DistinctSources(Box<DistinctSources>),
2592 MalformedForSourcemap(MalformedSourceMapPositions),
2593 SourceNotAvailable { filename: FileName },
2594}
2595
2596#[derive(Clone, PartialEq, Eq, Debug)]
2597pub struct DistinctSources {
2598 pub begin: (FileName, BytePos),
2599 pub end: (FileName, BytePos),
2600}
2601
2602#[derive(Clone, PartialEq, Eq, Debug)]
2603pub struct MalformedSourceMapPositions {
2604 pub name: FileName,
2605 pub source_len: usize,
2606 pub begin_pos: BytePos,
2607 pub end_pos: BytePos,
2608}
2609
2610#[derive(Copy, Clone, PartialEq, Eq, Debug)]
2612pub struct InnerSpan {
2613 pub start: usize,
2614 pub end: usize,
2615}
2616
2617impl InnerSpan {
2618 pub fn new(start: usize, end: usize) -> InnerSpan {
2619 InnerSpan { start, end }
2620 }
2621}
2622
2623pub trait HashStableContext {
2628 fn def_path_hash(&self, def_id: DefId) -> DefPathHash;
2629 fn hash_spans(&self) -> bool;
2630 fn unstable_opts_incremental_ignore_spans(&self) -> bool;
2633 fn def_span(&self, def_id: LocalDefId) -> Span;
2634 fn span_data_to_lines_and_cols(
2635 &mut self,
2636 span: &SpanData,
2637 ) -> Option<(StableSourceFileId, usize, BytePos, usize, BytePos)>;
2638 fn hashing_controls(&self) -> HashingControls;
2639}
2640
2641impl<CTX> HashStable<CTX> for Span
2642where
2643 CTX: HashStableContext,
2644{
2645 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
2656 const TAG_VALID_SPAN: u8 = 0;
2657 const TAG_INVALID_SPAN: u8 = 1;
2658 const TAG_RELATIVE_SPAN: u8 = 2;
2659
2660 if !ctx.hash_spans() {
2661 return;
2662 }
2663
2664 let span = self.data_untracked();
2665 span.ctxt.hash_stable(ctx, hasher);
2666 span.parent.hash_stable(ctx, hasher);
2667
2668 if span.is_dummy() {
2669 Hash::hash(&TAG_INVALID_SPAN, hasher);
2670 return;
2671 }
2672
2673 if let Some(parent) = span.parent {
2674 let def_span = ctx.def_span(parent).data_untracked();
2675 if def_span.contains(span) {
2676 Hash::hash(&TAG_RELATIVE_SPAN, hasher);
2678 (span.lo - def_span.lo).to_u32().hash_stable(ctx, hasher);
2679 (span.hi - def_span.lo).to_u32().hash_stable(ctx, hasher);
2680 return;
2681 }
2682 }
2683
2684 let Some((file, line_lo, col_lo, line_hi, col_hi)) = ctx.span_data_to_lines_and_cols(&span)
2688 else {
2689 Hash::hash(&TAG_INVALID_SPAN, hasher);
2690 return;
2691 };
2692
2693 Hash::hash(&TAG_VALID_SPAN, hasher);
2694 Hash::hash(&file, hasher);
2695
2696 let col_lo_trunc = (col_lo.0 as u64) & 0xFF;
2706 let line_lo_trunc = ((line_lo as u64) & 0xFF_FF_FF) << 8;
2707 let col_hi_trunc = (col_hi.0 as u64) & 0xFF << 32;
2708 let line_hi_trunc = ((line_hi as u64) & 0xFF_FF_FF) << 40;
2709 let col_line = col_lo_trunc | line_lo_trunc | col_hi_trunc | line_hi_trunc;
2710 let len = (span.hi - span.lo).0;
2711 Hash::hash(&col_line, hasher);
2712 Hash::hash(&len, hasher);
2713 }
2714}
2715
2716#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
2722#[derive(HashStable_Generic)]
2723pub struct ErrorGuaranteed(());
2724
2725impl ErrorGuaranteed {
2726 #[deprecated = "should only be used in `DiagCtxtInner::emit_diagnostic`"]
2728 pub fn unchecked_error_guaranteed() -> Self {
2729 ErrorGuaranteed(())
2730 }
2731
2732 pub fn raise_fatal(self) -> ! {
2733 FatalError.raise()
2734 }
2735}
2736
2737impl<E: rustc_serialize::Encoder> Encodable<E> for ErrorGuaranteed {
2738 #[inline]
2739 fn encode(&self, _e: &mut E) {
2740 panic!(
2741 "should never serialize an `ErrorGuaranteed`, as we do not write metadata or \
2742 incremental caches in case errors occurred"
2743 )
2744 }
2745}
2746impl<D: rustc_serialize::Decoder> Decodable<D> for ErrorGuaranteed {
2747 #[inline]
2748 fn decode(_d: &mut D) -> ErrorGuaranteed {
2749 panic!(
2750 "`ErrorGuaranteed` should never have been serialized to metadata or incremental caches"
2751 )
2752 }
2753}