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