1//! Types for tracking pieces of source code within a crate.
2//!
3//! The [`SourceMap`] tracks all the source code used within a single crate, mapping
4//! from integer byte positions to the original source code location. Each bit
5//! of source parsed during crate parsing (typically files, in-memory strings,
6//! or various bits of macro expansion) cover a continuous range of bytes in the
7//! `SourceMap` and are represented by [`SourceFile`]s. Byte positions are stored in
8//! [`Span`] and used pervasively in the compiler. They are absolute positions
9//! within the `SourceMap`, which upon request can be converted to line and column
10//! information, source code snippets, etc.
1112use std::fs::File;
13use std::io::{self, BorrowedBuf, Read};
14use std::{fs, path};
1516use rustc_data_structures::sync::{IntoDynSyncSend, MappedReadGuard, ReadGuard, RwLock};
17use rustc_data_structures::unhash::UnhashMap;
18use tracing::{debug, instrument, trace};
1920use crate::*;
2122#[cfg(test)]
23mod tests;
2425/// Returns the span itself if it doesn't come from a macro expansion,
26/// otherwise return the call site span up to the `enclosing_sp` by
27/// following the `expn_data` chain.
28pub fn original_sp(sp: Span, enclosing_sp: Span) -> Span {
29let ctxt = sp.ctxt();
30if ctxt.is_root() {
31return sp;
32 }
3334let enclosing_ctxt = enclosing_sp.ctxt();
35let expn_data1 = ctxt.outer_expn_data();
36if !enclosing_ctxt.is_root()
37 && expn_data1.call_site == enclosing_ctxt.outer_expn_data().call_site
38 {
39sp40 } else {
41original_sp(expn_data1.call_site, enclosing_sp)
42 }
43}
4445mod monotonic {
46use std::ops::{Deref, DerefMut};
4748/// A `MonotonicVec` is a `Vec` which can only be grown.
49 /// Once inserted, an element can never be removed or swapped,
50 /// guaranteeing that any indices into a `MonotonicVec` are stable
51// This is declared in its own module to ensure that the private
52 // field is inaccessible
53pub struct MonotonicVec<T>(Vec<T>);
54impl<T> MonotonicVec<T> {
55pub(super) fn push(&mut self, val: T) {
56self.0.push(val);
57 }
58 }
5960impl<T> Defaultfor MonotonicVec<T> {
61fn default() -> Self {
62MonotonicVec(::alloc::vec::Vec::new()vec![])
63 }
64 }
6566impl<T> Dereffor MonotonicVec<T> {
67type Target = Vec<T>;
68fn deref(&self) -> &Self::Target {
69&self.0
70}
71 }
7273impl<T> !DerefMutfor MonotonicVec<T> {}
74}
7576// _____________________________________________________________________________
77// SourceFile, MultiByteChar, FileName, FileLines
78//
7980/// An abstraction over the fs operations used by the Parser.
81pub trait FileLoader {
82/// Query the existence of a file.
83fn file_exists(&self, path: &Path) -> bool;
8485/// Read the contents of a UTF-8 file into memory.
86 /// This function must return a String because we normalize
87 /// source files, which may require resizing.
88fn read_file(&self, path: &Path) -> io::Result<String>;
8990/// Read the contents of a potentially non-UTF-8 file into memory.
91 /// We don't normalize binary files, so we can start in an Arc.
92fn read_binary_file(&self, path: &Path) -> io::Result<Arc<[u8]>>;
9394/// Current working directory
95fn current_directory(&self) -> io::Result<PathBuf>;
96}
9798/// A FileLoader that uses std::fs to load real files.
99pub struct RealFileLoader;
100101impl FileLoaderfor RealFileLoader {
102fn file_exists(&self, path: &Path) -> bool {
103path.exists()
104 }
105106fn read_file(&self, path: &Path) -> io::Result<String> {
107let mut file = File::open(path)?;
108let size = file.metadata().map(|metadata| metadata.len()).ok().unwrap_or(0);
109110if size > SourceFile::MAX_FILE_SIZE.into() {
111return Err(io::Error::other(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("text files larger than {0} bytes are unsupported",
SourceFile::MAX_FILE_SIZE))
})format!(
112"text files larger than {} bytes are unsupported",
113 SourceFile::MAX_FILE_SIZE
114 )));
115 }
116let mut contents = String::new();
117file.read_to_string(&mut contents)?;
118Ok(contents)
119 }
120121fn read_binary_file(&self, path: &Path) -> io::Result<Arc<[u8]>> {
122let mut file = fs::File::open(path)?;
123let len = file.metadata()?.len();
124125let mut bytes = Arc::new_uninit_slice(lenas usize);
126let mut buf = BorrowedBuf::from(Arc::get_mut(&mut bytes).unwrap());
127match file.read_buf_exact(buf.unfilled()) {
128Ok(()) => {}
129Err(e) if e.kind() == io::ErrorKind::UnexpectedEof => {
130drop(bytes);
131return fs::read(path).map(Vec::into);
132 }
133Err(e) => return Err(e),
134 }
135// SAFETY: If the read_buf_exact call returns Ok(()), then we have
136 // read len bytes and initialized the buffer.
137let bytes = unsafe { bytes.assume_init() };
138139// At this point, we've read all the bytes that filesystem metadata reported exist.
140 // But we are not guaranteed to be at the end of the file, because we did not attempt to do
141 // a read with a non-zero-sized buffer and get Ok(0).
142 // So we do small read to a fixed-size buffer. If the read returns no bytes then we're
143 // already done, and we just return the Arc we built above.
144 // If the read returns bytes however, we just fall back to reading into a Vec then turning
145 // that into an Arc, losing our nice peak memory behavior. This fallback code path should
146 // be rarely exercised.
147148let mut probe = [0u8; 32];
149let n = loop {
150match file.read(&mut probe) {
151Ok(0) => return Ok(bytes),
152Err(e) if e.kind() == io::ErrorKind::Interrupted => continue,
153Err(e) => return Err(e),
154Ok(n) => break n,
155 }
156 };
157let mut bytes: Vec<u8> = bytes.iter().copied().chain(probe[..n].iter().copied()).collect();
158file.read_to_end(&mut bytes)?;
159Ok(bytes.into())
160 }
161162fn current_directory(&self) -> io::Result<PathBuf> {
163 std::env::current_dir()
164 }
165}
166167// _____________________________________________________________________________
168// SourceMap
169//
170171#[derive(#[automatically_derived]
impl ::core::default::Default for SourceMapFiles {
#[inline]
fn default() -> SourceMapFiles {
SourceMapFiles {
source_files: ::core::default::Default::default(),
stable_id_to_source_file: ::core::default::Default::default(),
}
}
}Default)]
172struct SourceMapFiles {
173 source_files: monotonic::MonotonicVec<Arc<SourceFile>>,
174 stable_id_to_source_file: UnhashMap<StableSourceFileId, Arc<SourceFile>>,
175}
176177/// Used to construct a `SourceMap` with `SourceMap::with_inputs`.
178pub struct SourceMapInputs {
179pub file_loader: Box<dyn FileLoader + Send + Sync>,
180pub path_mapping: FilePathMapping,
181pub hash_kind: SourceFileHashAlgorithm,
182pub checksum_hash_kind: Option<SourceFileHashAlgorithm>,
183}
184185pub struct SourceMap {
186 files: RwLock<SourceMapFiles>,
187 file_loader: IntoDynSyncSend<Box<dyn FileLoader + Sync + Send>>,
188189// This is used to apply the file path remapping as specified via
190 // `--remap-path-prefix` to all `SourceFile`s allocated within this `SourceMap`.
191path_mapping: FilePathMapping,
192193/// Current working directory
194working_dir: RealFileName,
195196/// The algorithm used for hashing the contents of each source file.
197hash_kind: SourceFileHashAlgorithm,
198199/// Similar to `hash_kind`, however this algorithm is used for checksums to determine if a crate is fresh.
200 /// `cargo` is the primary user of these.
201 ///
202 /// If this is equal to `hash_kind` then the checksum won't be computed twice.
203checksum_hash_kind: Option<SourceFileHashAlgorithm>,
204}
205206impl SourceMap {
207pub fn new(path_mapping: FilePathMapping) -> SourceMap {
208Self::with_inputs(SourceMapInputs {
209 file_loader: Box::new(RealFileLoader),
210path_mapping,
211 hash_kind: SourceFileHashAlgorithm::Md5,
212 checksum_hash_kind: None,
213 })
214 }
215216pub fn with_inputs(
217SourceMapInputs { file_loader, path_mapping, hash_kind, checksum_hash_kind }: SourceMapInputs,
218 ) -> SourceMap {
219let cwd = file_loader220 .current_directory()
221 .expect("expecting a current working directory to exist");
222let working_dir = path_mapping.to_real_filename(&RealFileName::empty(), &cwd);
223{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_span/src/source_map.rs:223",
"rustc_span::source_map", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_span/src/source_map.rs"),
::tracing_core::__macro_support::Option::Some(223u32),
::tracing_core::__macro_support::Option::Some("rustc_span::source_map"),
::tracing_core::field::FieldSet::new(&["working_dir"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&working_dir)
as &dyn Value))])
});
} else { ; }
};debug!(?working_dir);
224SourceMap {
225 files: Default::default(),
226working_dir,
227 file_loader: IntoDynSyncSend(file_loader),
228path_mapping,
229hash_kind,
230checksum_hash_kind,
231 }
232 }
233234pub fn path_mapping(&self) -> &FilePathMapping {
235&self.path_mapping
236 }
237238pub fn working_dir(&self) -> &RealFileName {
239&self.working_dir
240 }
241242pub fn file_exists(&self, path: &Path) -> bool {
243self.file_loader.file_exists(path)
244 }
245246pub fn load_file(&self, path: &Path) -> io::Result<Arc<SourceFile>> {
247let src = self.file_loader.read_file(path)?;
248let filename = FileName::Real(self.path_mapping.to_real_filename(&self.working_dir, path));
249Ok(self.new_source_file(filename, src))
250 }
251252/// Loads source file as a binary blob.
253 ///
254 /// Unlike `load_file`, guarantees that no normalization like BOM-removal
255 /// takes place.
256pub fn load_binary_file(&self, path: &Path) -> io::Result<(Arc<[u8]>, Span)> {
257let bytes = self.file_loader.read_binary_file(path)?;
258259// We need to add file to the `SourceMap`, so that it is present
260 // in dep-info. There's also an edge case that file might be both
261 // loaded as a binary via `include_bytes!` and as proper `SourceFile`
262 // via `mod`, so we try to use real file contents and not just an
263 // empty string.
264let text = std::str::from_utf8(&bytes).unwrap_or("").to_string();
265let filename = FileName::Real(self.path_mapping.to_real_filename(&self.working_dir, path));
266let file = self.new_source_file(filename, text);
267Ok((
268bytes,
269Span::new(
270file.start_pos,
271BytePos(file.start_pos.0 + file.normalized_source_len.0),
272SyntaxContext::root(),
273None,
274 ),
275 ))
276 }
277278// By returning a `MonotonicVec`, we ensure that consumers cannot invalidate
279 // any existing indices pointing into `files`.
280pub fn files(&self) -> MappedReadGuard<'_, monotonic::MonotonicVec<Arc<SourceFile>>> {
281ReadGuard::map(self.files.borrow(), |files| &files.source_files)
282 }
283284pub fn source_file_by_stable_id(
285&self,
286 stable_id: StableSourceFileId,
287 ) -> Option<Arc<SourceFile>> {
288self.files.borrow().stable_id_to_source_file.get(&stable_id).cloned()
289 }
290291fn register_source_file(
292&self,
293 file_id: StableSourceFileId,
294mut file: SourceFile,
295 ) -> Result<Arc<SourceFile>, OffsetOverflowError> {
296let mut files = self.files.borrow_mut();
297298file.start_pos = BytePos(if let Some(last_file) = files.source_files.last() {
299// Add one so there is some space between files. This lets us distinguish
300 // positions in the `SourceMap`, even in the presence of zero-length files.
301last_file.end_position().0.checked_add(1).ok_or(OffsetOverflowError)?
302} else {
3030
304});
305306let file = Arc::new(file);
307files.source_files.push(Arc::clone(&file));
308files.stable_id_to_source_file.insert(file_id, Arc::clone(&file));
309310Ok(file)
311 }
312313/// Creates a new `SourceFile`.
314 /// If a file already exists in the `SourceMap` with the same ID, that file is returned
315 /// unmodified.
316pub fn new_source_file(&self, filename: FileName, src: String) -> Arc<SourceFile> {
317self.try_new_source_file(filename, src).unwrap_or_else(|OffsetOverflowError| {
318{
::std::io::_eprint(format_args!("fatal error: rustc does not support text files larger than {0} bytes\n",
SourceFile::MAX_FILE_SIZE));
};eprintln!(
319"fatal error: rustc does not support text files larger than {} bytes",
320 SourceFile::MAX_FILE_SIZE
321 );
322crate::fatal_error::FatalError.raise()
323 })
324 }
325326fn try_new_source_file(
327&self,
328 filename: FileName,
329 src: String,
330 ) -> Result<Arc<SourceFile>, OffsetOverflowError> {
331// Note that filename may not be a valid path, eg it may be `<anon>` etc,
332 // but this is okay because the directory determined by `path.pop()` will
333 // be empty, so the working directory will be used.
334335let stable_id = StableSourceFileId::from_filename_in_current_crate(&filename);
336match self.source_file_by_stable_id(stable_id) {
337Some(lrc_sf) => Ok(lrc_sf),
338None => {
339let source_file =
340SourceFile::new(filename, src, self.hash_kind, self.checksum_hash_kind)?;
341342// Let's make sure the file_id we generated above actually matches
343 // the ID we generate for the SourceFile we just created.
344if true {
match (&source_file.stable_id, &stable_id) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
};
};debug_assert_eq!(source_file.stable_id, stable_id);
345346self.register_source_file(stable_id, source_file)
347 }
348 }
349 }
350351/// Allocates a new `SourceFile` representing a source file from an external
352 /// crate. The source code of such an "imported `SourceFile`" is not available,
353 /// but we still know enough to generate accurate debuginfo location
354 /// information for things inlined from other crates.
355pub fn new_imported_source_file(
356&self,
357 filename: FileName,
358 src_hash: SourceFileHash,
359 checksum_hash: Option<SourceFileHash>,
360 stable_id: StableSourceFileId,
361 normalized_source_len: u32,
362 unnormalized_source_len: u32,
363 cnum: CrateNum,
364 file_local_lines: FreezeLock<SourceFileLines>,
365 multibyte_chars: Vec<MultiByteChar>,
366 normalized_pos: Vec<NormalizedPos>,
367 metadata_index: u32,
368 ) -> Arc<SourceFile> {
369let normalized_source_len = RelativeBytePos::from_u32(normalized_source_len);
370371let source_file = SourceFile {
372 name: filename,
373 src: None,
374src_hash,
375checksum_hash,
376 external_src: FreezeLock::new(ExternalSource::Foreign {
377 kind: ExternalSourceKind::AbsentOk,
378metadata_index,
379 }),
380 start_pos: BytePos(0),
381normalized_source_len,
382unnormalized_source_len,
383 lines: file_local_lines,
384multibyte_chars,
385normalized_pos,
386stable_id,
387cnum,
388 };
389390self.register_source_file(stable_id, source_file)
391 .expect("not enough address space for imported source file")
392 }
393394/// If there is a doctest offset, applies it to the line.
395pub fn doctest_offset_line(&self, file: &FileName, orig: usize) -> usize {
396match file {
397 FileName::DocTest(_, offset) => {
398if *offset < 0 {
399orig - (-(*offset)) as usize400 } else {
401orig + *offsetas usize402 }
403 }
404_ => orig,
405 }
406 }
407408/// Return the SourceFile that contains the given `BytePos`
409pub fn lookup_source_file(&self, pos: BytePos) -> Arc<SourceFile> {
410let idx = self.lookup_source_file_idx(pos);
411Arc::clone(&(*self.files.borrow().source_files)[idx])
412 }
413414/// Looks up source information about a `BytePos`.
415pub fn lookup_char_pos(&self, pos: BytePos) -> Loc {
416let sf = self.lookup_source_file(pos);
417let (line, col, col_display) = sf.lookup_file_pos_with_col_display(pos);
418Loc { file: sf, line, col, col_display }
419 }
420421/// If the corresponding `SourceFile` is empty, does not return a line number.
422pub fn lookup_line(&self, pos: BytePos) -> Result<SourceFileAndLine, Arc<SourceFile>> {
423let f = self.lookup_source_file(pos);
424425let pos = f.relative_position(pos);
426match f.lookup_line(pos) {
427Some(line) => Ok(SourceFileAndLine { sf: f, line }),
428None => Err(f),
429 }
430 }
431432pub fn span_to_string(&self, sp: Span, display_scope: RemapPathScopeComponents) -> String {
433self.span_to_string_ext(sp, display_scope, false)
434 }
435436pub fn span_to_short_string(
437&self,
438 sp: Span,
439 display_scope: RemapPathScopeComponents,
440 ) -> String {
441self.span_to_string_ext(sp, display_scope, true)
442 }
443444fn span_to_string_ext(
445&self,
446 sp: Span,
447 display_scope: RemapPathScopeComponents,
448 short: bool,
449 ) -> String {
450let (source_file, lo_line, lo_col, hi_line, hi_col) = self.span_to_location_info(sp);
451452let file_name = match source_file {
453Some(sf) => {
454if short { sf.name.short() } else { sf.name.display(display_scope) }.to_string()
455 }
456None => return "no-location".to_string(),
457 };
458459::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{1}:{2}:{3}{0}",
if short {
String::new()
} else {
::alloc::__export::must_use({
::alloc::fmt::format(format_args!(": {0}:{1}", hi_line,
hi_col))
})
}, file_name, lo_line, lo_col))
})format!(
460"{file_name}:{lo_line}:{lo_col}{}",
461if short { String::new() } else { format!(": {hi_line}:{hi_col}") }
462 )463 }
464465pub fn span_to_location_info(
466&self,
467 sp: Span,
468 ) -> (Option<Arc<SourceFile>>, usize, usize, usize, usize) {
469if self.files.borrow().source_files.is_empty() || sp.is_dummy() {
470return (None, 0, 0, 0, 0);
471 }
472473let lo = self.lookup_char_pos(sp.lo());
474let hi = self.lookup_char_pos(sp.hi());
475 (Some(lo.file), lo.line, lo.col.to_usize() + 1, hi.line, hi.col.to_usize() + 1)
476 }
477478/// Format the span location to be printed in diagnostics. Must not be emitted
479 /// to build artifacts as this may leak local file paths. Use span_to_embeddable_string
480 /// for string suitable for embedding.
481pub fn span_to_diagnostic_string(&self, sp: Span) -> String {
482self.span_to_string(sp, RemapPathScopeComponents::DIAGNOSTICS)
483 }
484485pub fn span_to_filename(&self, sp: Span) -> FileName {
486self.lookup_char_pos(sp.lo()).file.name.clone()
487 }
488489pub fn filename_for_diagnostics<'a>(&self, filename: &'a FileName) -> FileNameDisplay<'a> {
490filename.display(RemapPathScopeComponents::DIAGNOSTICS)
491 }
492493pub fn is_multiline(&self, sp: Span) -> bool {
494let lo = self.lookup_source_file_idx(sp.lo());
495let hi = self.lookup_source_file_idx(sp.hi());
496if lo != hi {
497return true;
498 }
499let f = Arc::clone(&(*self.files.borrow().source_files)[lo]);
500let lo = f.relative_position(sp.lo());
501let hi = f.relative_position(sp.hi());
502f.lookup_line(lo) != f.lookup_line(hi)
503 }
504505#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("is_valid_span",
"rustc_span::source_map", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_span/src/source_map.rs"),
::tracing_core::__macro_support::Option::Some(505u32),
::tracing_core::__macro_support::Option::Some("rustc_span::source_map"),
::tracing_core::field::FieldSet::new(&["sp"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&sp)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
Result<(Loc, Loc), SpanLinesError> = loop {};
return __tracing_attr_fake_return;
}
{
let lo = self.lookup_char_pos(sp.lo());
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_span/src/source_map.rs:508",
"rustc_span::source_map", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_span/src/source_map.rs"),
::tracing_core::__macro_support::Option::Some(508u32),
::tracing_core::__macro_support::Option::Some("rustc_span::source_map"),
::tracing_core::field::FieldSet::new(&["lo"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&lo) as
&dyn Value))])
});
} else { ; }
};
let hi = self.lookup_char_pos(sp.hi());
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_span/src/source_map.rs:510",
"rustc_span::source_map", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_span/src/source_map.rs"),
::tracing_core::__macro_support::Option::Some(510u32),
::tracing_core::__macro_support::Option::Some("rustc_span::source_map"),
::tracing_core::field::FieldSet::new(&["hi"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&hi) as
&dyn Value))])
});
} else { ; }
};
if lo.file.start_pos != hi.file.start_pos {
return Err(SpanLinesError::DistinctSources(Box::new(DistinctSources {
begin: (lo.file.name.clone(), lo.file.start_pos),
end: (hi.file.name.clone(), hi.file.start_pos),
})));
}
Ok((lo, hi))
}
}
}#[instrument(skip(self), level = "trace")]506pub fn is_valid_span(&self, sp: Span) -> Result<(Loc, Loc), SpanLinesError> {
507let lo = self.lookup_char_pos(sp.lo());
508trace!(?lo);
509let hi = self.lookup_char_pos(sp.hi());
510trace!(?hi);
511if lo.file.start_pos != hi.file.start_pos {
512return Err(SpanLinesError::DistinctSources(Box::new(DistinctSources {
513 begin: (lo.file.name.clone(), lo.file.start_pos),
514 end: (hi.file.name.clone(), hi.file.start_pos),
515 })));
516 }
517Ok((lo, hi))
518 }
519520pub fn is_line_before_span_empty(&self, sp: Span) -> bool {
521match self.span_to_prev_source(sp) {
522Ok(s) => s.rsplit_once('\n').unwrap_or(("", &s)).1.trim_start().is_empty(),
523Err(_) => false,
524 }
525 }
526527pub fn span_to_lines(&self, sp: Span) -> FileLinesResult {
528{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_span/src/source_map.rs:528",
"rustc_span::source_map", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_span/src/source_map.rs"),
::tracing_core::__macro_support::Option::Some(528u32),
::tracing_core::__macro_support::Option::Some("rustc_span::source_map"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("span_to_lines(sp={0:?})",
sp) as &dyn Value))])
});
} else { ; }
};debug!("span_to_lines(sp={:?})", sp);
529let (lo, hi) = self.is_valid_span(sp)?;
530if !(hi.line >= lo.line) {
::core::panicking::panic("assertion failed: hi.line >= lo.line")
};assert!(hi.line >= lo.line);
531532if sp.is_dummy() {
533return Ok(FileLines { file: lo.file, lines: Vec::new() });
534 }
535536let mut lines = Vec::with_capacity(hi.line - lo.line + 1);
537538// The span starts partway through the first line,
539 // but after that it starts from offset 0.
540let mut start_col = lo.col;
541542// For every line but the last, it extends from `start_col`
543 // and to the end of the line. Be careful because the line
544 // numbers in Loc are 1-based, so we subtract 1 to get 0-based
545 // lines.
546 //
547 // FIXME: now that we handle DUMMY_SP up above, we should consider
548 // asserting that the line numbers here are all indeed 1-based.
549let hi_line = hi.line.saturating_sub(1);
550for line_index in lo.line.saturating_sub(1)..hi_line {
551let line_len = lo.file.get_line(line_index).map_or(0, |s| s.chars().count());
552 lines.push(LineInfo { line_index, start_col, end_col: CharPos::from_usize(line_len) });
553 start_col = CharPos::from_usize(0);
554 }
555556// For the last line, it extends from `start_col` to `hi.col`:
557lines.push(LineInfo { line_index: hi_line, start_col, end_col: hi.col });
558559Ok(FileLines { file: lo.file, lines })
560 }
561562/// Extracts the source surrounding the given `Span` using the `extract_source` function. The
563 /// extract function takes three arguments: a string slice containing the source, an index in
564 /// the slice for the beginning of the span and an index in the slice for the end of the span.
565pub fn span_to_source<F, T>(&self, sp: Span, extract_source: F) -> Result<T, SpanSnippetError>
566where
567F: Fn(&str, usize, usize) -> Result<T, SpanSnippetError>,
568 {
569let local_begin = self.lookup_byte_offset(sp.lo());
570let local_end = self.lookup_byte_offset(sp.hi());
571572if local_begin.sf.start_pos != local_end.sf.start_pos {
573Err(SpanSnippetError::DistinctSources(Box::new(DistinctSources {
574 begin: (local_begin.sf.name.clone(), local_begin.sf.start_pos),
575 end: (local_end.sf.name.clone(), local_end.sf.start_pos),
576 })))
577 } else {
578self.ensure_source_file_source_present(&local_begin.sf);
579580let start_index = local_begin.pos.to_usize();
581let end_index = local_end.pos.to_usize();
582let source_len = local_begin.sf.normalized_source_len.to_usize();
583584if start_index > end_index || end_index > source_len {
585return Err(SpanSnippetError::MalformedForSourcemap(MalformedSourceMapPositions {
586 name: local_begin.sf.name.clone(),
587source_len,
588 begin_pos: local_begin.pos,
589 end_pos: local_end.pos,
590 }));
591 }
592593if let Some(ref src) = local_begin.sf.src {
594extract_source(src, start_index, end_index)
595 } else if let Some(src) = local_begin.sf.external_src.read().get_source() {
596extract_source(src, start_index, end_index)
597 } else {
598Err(SpanSnippetError::SourceNotAvailable { filename: local_begin.sf.name.clone() })
599 }
600 }
601 }
602603pub fn is_span_accessible(&self, sp: Span) -> bool {
604self.span_to_source(sp, |src, start_index, end_index| {
605Ok(src.get(start_index..end_index).is_some())
606 })
607 .is_ok_and(|is_accessible| is_accessible)
608 }
609610/// Returns the source snippet as `String` corresponding to the given `Span`.
611pub fn span_to_snippet(&self, sp: Span) -> Result<String, SpanSnippetError> {
612self.span_to_source(sp, |src, start_index, end_index| {
613src.get(start_index..end_index)
614 .map(|s| s.to_string())
615 .ok_or(SpanSnippetError::IllFormedSpan(sp))
616 })
617 }
618619pub fn span_to_margin(&self, sp: Span) -> Option<usize> {
620Some(self.indentation_before(sp)?.len())
621 }
622623pub fn indentation_before(&self, sp: Span) -> Option<String> {
624self.span_to_source(sp, |src, start_index, _| {
625let before = &src[..start_index];
626let last_line = before.rsplit_once('\n').map_or(before, |(_, last)| last);
627Ok(last_line628 .split_once(|c: char| !c.is_whitespace())
629 .map_or(last_line, |(indent, _)| indent)
630 .to_string())
631 })
632 .ok()
633 }
634635/// Returns the source snippet as `String` before the given `Span`.
636pub fn span_to_prev_source(&self, sp: Span) -> Result<String, SpanSnippetError> {
637self.span_to_source(sp, |src, start_index, _| {
638src.get(..start_index).map(|s| s.to_string()).ok_or(SpanSnippetError::IllFormedSpan(sp))
639 })
640 }
641642/// Extends the given `Span` to just after the previous occurrence of `c`. Return the same span
643 /// if no character could be found or if an error occurred while retrieving the code snippet.
644pub fn span_extend_to_prev_char(&self, sp: Span, c: char, accept_newlines: bool) -> Span {
645if let Ok(prev_source) = self.span_to_prev_source(sp) {
646let prev_source = prev_source.rsplit(c).next().unwrap_or("");
647if !prev_source.is_empty() && (accept_newlines || !prev_source.contains('\n')) {
648return sp.with_lo(BytePos(sp.lo().0 - prev_source.len() as u32));
649 }
650 }
651652sp653 }
654655/// Extends the given `Span` to just before the previous occurrence of `c`. Return the same span
656 /// if an error occurred while retrieving the code snippet.
657pub fn span_extend_to_prev_char_before(
658&self,
659 sp: Span,
660 c: char,
661 accept_newlines: bool,
662 ) -> Span {
663if let Ok(prev_source) = self.span_to_prev_source(sp) {
664let prev_source = prev_source.rsplit(c).next().unwrap_or("");
665if accept_newlines || !prev_source.contains('\n') {
666return sp.with_lo(BytePos(sp.lo().0 - prev_source.len() as u32 - 1_u32));
667 }
668 }
669670sp671 }
672673/// Extends the given `Span` to just after the previous occurrence of `pat` when surrounded by
674 /// whitespace. Returns None if the pattern could not be found or if an error occurred while
675 /// retrieving the code snippet.
676pub fn span_extend_to_prev_str(
677&self,
678 sp: Span,
679 pat: &str,
680 accept_newlines: bool,
681 include_whitespace: bool,
682 ) -> Option<Span> {
683// assure that the pattern is delimited, to avoid the following
684 // fn my_fn()
685 // ^^^^ returned span without the check
686 // ---------- correct span
687let prev_source = self.span_to_prev_source(sp).ok()?;
688for ws in &[" ", "\t", "\n"] {
689let pat = pat.to_owned() + ws;
690if let Some(pat_pos) = prev_source.rfind(&pat) {
691let just_after_pat_pos = pat_pos + pat.len() - 1;
692let just_after_pat_plus_ws = if include_whitespace {
693 just_after_pat_pos
694 + prev_source[just_after_pat_pos..]
695 .find(|c: char| !c.is_whitespace())
696 .unwrap_or(0)
697 } else {
698 just_after_pat_pos
699 };
700let len = prev_source.len() - just_after_pat_plus_ws;
701let prev_source = &prev_source[just_after_pat_plus_ws..];
702if accept_newlines || !prev_source.trim_start().contains('\n') {
703return Some(sp.with_lo(BytePos(sp.lo().0 - len as u32)));
704 }
705 }
706 }
707708None709 }
710711/// Returns the source snippet as `String` after the given `Span`.
712pub fn span_to_next_source(&self, sp: Span) -> Result<String, SpanSnippetError> {
713self.span_to_source(sp, |src, _, end_index| {
714src.get(end_index..).map(|s| s.to_string()).ok_or(SpanSnippetError::IllFormedSpan(sp))
715 })
716 }
717718/// Extends the given `Span` while the next character matches the predicate
719pub fn span_extend_while(
720&self,
721 span: Span,
722 f: impl Fn(char) -> bool,
723 ) -> Result<Span, SpanSnippetError> {
724self.span_to_source(span, |s, _start, end| {
725let n = s[end..].char_indices().find(|&(_, c)| !f(c)).map_or(s.len() - end, |(i, _)| i);
726Ok(span.with_hi(span.hi() + BytePos(nas u32)))
727 })
728 }
729730/// Extends the span to include any trailing whitespace, or returns the original
731 /// span if a `SpanSnippetError` was encountered.
732pub fn span_extend_while_whitespace(&self, span: Span) -> Span {
733self.span_extend_while(span, char::is_whitespace).unwrap_or(span)
734 }
735736/// Extends the given `Span` to previous character while the previous character matches the predicate
737pub fn span_extend_prev_while(
738&self,
739 span: Span,
740 f: impl Fn(char) -> bool,
741 ) -> Result<Span, SpanSnippetError> {
742self.span_to_source(span, |s, start, _end| {
743let n = s[..start]
744 .char_indices()
745 .rfind(|&(_, c)| !f(c))
746 .map_or(start, |(i, _)| start - i - 1);
747Ok(span.with_lo(span.lo() - BytePos(nas u32)))
748 })
749 }
750751/// Extends the given `Span` to just before the next occurrence of `c`.
752pub fn span_extend_to_next_char(&self, sp: Span, c: char, accept_newlines: bool) -> Span {
753if let Ok(next_source) = self.span_to_next_source(sp) {
754let next_source = next_source.split(c).next().unwrap_or("");
755if !next_source.is_empty() && (accept_newlines || !next_source.contains('\n')) {
756return sp.with_hi(BytePos(sp.hi().0 + next_source.len() as u32));
757 }
758 }
759760sp761 }
762763/// Extends the given `Span` to contain the entire line it is on.
764pub fn span_extend_to_line(&self, sp: Span) -> Span {
765self.span_extend_to_prev_char(self.span_extend_to_next_char(sp, '\n', true), '\n', true)
766 }
767768/// Given a `Span`, tries to get a shorter span ending before the first occurrence of `char`
769 /// `c`.
770pub fn span_until_char(&self, sp: Span, c: char) -> Span {
771match self.span_to_snippet(sp) {
772Ok(snippet) => {
773let snippet = snippet.split(c).next().unwrap_or("").trim_end();
774if !snippet.is_empty() && !snippet.contains('\n') {
775sp.with_hi(BytePos(sp.lo().0 + snippet.len() as u32))
776 } else {
777sp778 }
779 }
780_ => sp,
781 }
782 }
783784/// Given a 'Span', tries to tell if it's wrapped by "<>" or "()"
785 /// the algorithm searches if the next character is '>' or ')' after skipping white space
786 /// then searches the previous character to match '<' or '(' after skipping white space
787 /// return true if wrapped by '<>' or '()'
788pub fn span_wrapped_by_angle_or_parentheses(&self, span: Span) -> bool {
789self.span_to_source(span, |src, start_index, end_index| {
790if src.get(start_index..end_index).is_none() {
791return Ok(false);
792 }
793// test the right side to match '>' after skipping white space
794let end_src = &src[end_index..];
795let mut i = 0;
796let mut found_right_parentheses = false;
797let mut found_right_angle = false;
798while let Some(cc) = end_src.chars().nth(i) {
799if cc == ' ' {
800 i = i + 1;
801 } else if cc == '>' {
802// found > in the right;
803found_right_angle = true;
804break;
805 } else if cc == ')' {
806 found_right_parentheses = true;
807break;
808 } else {
809// failed to find '>' return false immediately
810return Ok(false);
811 }
812 }
813// test the left side to match '<' after skipping white space
814i = start_index;
815let start_src = &src[0..start_index];
816while let Some(cc) = start_src.chars().nth(i) {
817if cc == ' ' {
818if i == 0 {
819return Ok(false);
820 }
821 i = i - 1;
822 } else if cc == '<' {
823// found < in the left
824if !found_right_angle {
825// skip something like "(< )>"
826return Ok(false);
827 }
828break;
829 } else if cc == '(' {
830if !found_right_parentheses {
831// skip something like "<(>)"
832return Ok(false);
833 }
834break;
835 } else {
836// failed to find '<' return false immediately
837return Ok(false);
838 }
839 }
840Ok(true)
841 })
842 .is_ok_and(|is_accessible| is_accessible)
843 }
844845/// Given a `Span`, tries to get a shorter span ending just after the first occurrence of `char`
846 /// `c`.
847pub fn span_through_char(&self, sp: Span, c: char) -> Span {
848if let Ok(snippet) = self.span_to_snippet(sp)
849 && let Some(offset) = snippet.find(c)
850 {
851return sp.with_hi(BytePos(sp.lo().0 + (offset + c.len_utf8()) as u32));
852 }
853sp854 }
855856/// Given a `Span`, gets a new `Span` covering the first token and all its trailing whitespace
857 /// or the original `Span`.
858 ///
859 /// If `sp` points to `"let mut x"`, then a span pointing at `"let "` will be returned.
860pub fn span_until_non_whitespace(&self, sp: Span) -> Span {
861let mut whitespace_found = false;
862863self.span_take_while(sp, |c| {
864if !whitespace_found && c.is_whitespace() {
865whitespace_found = true;
866 }
867868 !whitespace_found || c.is_whitespace()
869 })
870 }
871872/// Given a `Span`, gets a new `Span` covering the first token without its trailing whitespace
873 /// or the original `Span` in case of error.
874 ///
875 /// If `sp` points to `"let mut x"`, then a span pointing at `"let"` will be returned.
876pub fn span_until_whitespace(&self, sp: Span) -> Span {
877self.span_take_while(sp, |c| !c.is_whitespace())
878 }
879880/// Given a `Span`, gets a shorter one until `predicate` yields `false`.
881pub fn span_take_while<P>(&self, sp: Span, predicate: P) -> Span882where
883P: for<'r> FnMut(&'r char) -> bool,
884 {
885if let Ok(snippet) = self.span_to_snippet(sp) {
886let offset = snippet.chars().take_while(predicate).map(|c| c.len_utf8()).sum::<usize>();
887888sp.with_hi(BytePos(sp.lo().0 + (offsetas u32)))
889 } else {
890sp891 }
892 }
893894/// Given a `Span`, return a span ending in the closest `{`. This is useful when you have a
895 /// `Span` enclosing a whole item but we need to point at only the head (usually the first
896 /// line) of that item.
897 ///
898 /// *Only suitable for diagnostics.*
899pub fn guess_head_span(&self, sp: Span) -> Span {
900// FIXME: extend the AST items to have a head span, or replace callers with pointing at
901 // the item's ident when appropriate.
902self.span_until_char(sp, '{')
903 }
904905/// Returns a new span representing just the first character of the given span.
906pub fn start_point(&self, sp: Span) -> Span {
907let width = {
908let sp = sp.data();
909let local_begin = self.lookup_byte_offset(sp.lo);
910let start_index = local_begin.pos.to_usize();
911let src = local_begin.sf.external_src.read();
912913let snippet = if let Some(ref src) = local_begin.sf.src {
914Some(&src[start_index..])
915 } else {
916src.get_source().map(|src| &src[start_index..])
917 };
918919match snippet {
920None => 1,
921Some(snippet) => match snippet.chars().next() {
922None => 1,
923Some(c) => c.len_utf8(),
924 },
925 }
926 };
927928sp.with_hi(BytePos(sp.lo().0 + widthas u32))
929 }
930931/// Returns a new span representing just the last character of this span.
932pub fn end_point(&self, sp: Span) -> Span {
933let sp = sp.data();
934let pos = sp.hi.0;
935936let width = self.find_width_of_character_at_span(sp, false);
937let corrected_end_position = pos.checked_sub(width).unwrap_or(pos);
938939let end_point = BytePos(cmp::max(corrected_end_position, sp.lo.0));
940sp.with_lo(end_point)
941 }
942943/// Returns a new span representing the next character after the end-point of this span.
944 /// Special cases:
945 /// - if span is a dummy one, returns the same span
946 /// - if next_point reached the end of source, return a span exceeding the end of source,
947 /// which means sm.span_to_snippet(next_point) will get `Err`
948 /// - respect multi-byte characters
949pub fn next_point(&self, sp: Span) -> Span {
950if sp.is_dummy() {
951return sp;
952 }
953954let sp = sp.data();
955let start_of_next_point = sp.hi.0;
956let width = self.find_width_of_character_at_span(sp, true);
957// If the width is 1, then the next span should only contain the next char besides current ending.
958 // However, in the case of a multibyte character, where the width != 1, the next span should
959 // span multiple bytes to include the whole character.
960let end_of_next_point =
961start_of_next_point.checked_add(width).unwrap_or(start_of_next_point);
962963let end_of_next_point = BytePos(cmp::max(start_of_next_point + 1, end_of_next_point));
964Span::new(BytePos(start_of_next_point), end_of_next_point, sp.ctxt, None)
965 }
966967/// Check whether span is followed by some specified expected string in limit scope
968pub fn span_look_ahead(&self, span: Span, expect: &str, limit: Option<usize>) -> Option<Span> {
969let mut sp = span;
970for _ in 0..limit.unwrap_or(100_usize) {
971 sp = self.next_point(sp);
972if let Ok(ref snippet) = self.span_to_snippet(sp) {
973if snippet == expect {
974return Some(sp);
975 }
976if snippet.chars().any(|c| !c.is_whitespace()) {
977break;
978 }
979 }
980 }
981None982 }
983984/// Finds the width of the character, either before or after the end of provided span,
985 /// depending on the `forwards` parameter.
986#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::INFO <= ::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::INFO <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("find_width_of_character_at_span",
"rustc_span::source_map", ::tracing::Level::INFO,
::tracing_core::__macro_support::Option::Some("compiler/rustc_span/src/source_map.rs"),
::tracing_core::__macro_support::Option::Some(986u32),
::tracing_core::__macro_support::Option::Some("rustc_span::source_map"),
::tracing_core::field::FieldSet::new(&["forwards"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::INFO <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::INFO <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&forwards as
&dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: u32 = loop {};
return __tracing_attr_fake_return;
}
{
if sp.lo == sp.hi && !forwards {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_span/src/source_map.rs:989",
"rustc_span::source_map", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_span/src/source_map.rs"),
::tracing_core::__macro_support::Option::Some(989u32),
::tracing_core::__macro_support::Option::Some("rustc_span::source_map"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("early return empty span")
as &dyn Value))])
});
} else { ; }
};
return 1;
}
let local_begin = self.lookup_byte_offset(sp.lo);
let local_end = self.lookup_byte_offset(sp.hi);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_span/src/source_map.rs:995",
"rustc_span::source_map", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_span/src/source_map.rs"),
::tracing_core::__macro_support::Option::Some(995u32),
::tracing_core::__macro_support::Option::Some("rustc_span::source_map"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("local_begin=`{0:?}`, local_end=`{1:?}`",
local_begin, local_end) as &dyn Value))])
});
} else { ; }
};
if local_begin.sf.start_pos != local_end.sf.start_pos {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_span/src/source_map.rs:998",
"rustc_span::source_map", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_span/src/source_map.rs"),
::tracing_core::__macro_support::Option::Some(998u32),
::tracing_core::__macro_support::Option::Some("rustc_span::source_map"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("begin and end are in different files")
as &dyn Value))])
});
} else { ; }
};
return 1;
}
let start_index = local_begin.pos.to_usize();
let end_index = local_end.pos.to_usize();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_span/src/source_map.rs:1004",
"rustc_span::source_map", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_span/src/source_map.rs"),
::tracing_core::__macro_support::Option::Some(1004u32),
::tracing_core::__macro_support::Option::Some("rustc_span::source_map"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("start_index=`{0:?}`, end_index=`{1:?}`",
start_index, end_index) as &dyn Value))])
});
} else { ; }
};
if (!forwards && end_index == usize::MIN) ||
(forwards && start_index == usize::MAX) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_span/src/source_map.rs:1009",
"rustc_span::source_map", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_span/src/source_map.rs"),
::tracing_core::__macro_support::Option::Some(1009u32),
::tracing_core::__macro_support::Option::Some("rustc_span::source_map"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("start or end of span, cannot be multibyte")
as &dyn Value))])
});
} else { ; }
};
return 1;
}
let source_len = local_begin.sf.normalized_source_len.to_usize();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_span/src/source_map.rs:1014",
"rustc_span::source_map", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_span/src/source_map.rs"),
::tracing_core::__macro_support::Option::Some(1014u32),
::tracing_core::__macro_support::Option::Some("rustc_span::source_map"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("source_len=`{0:?}`",
source_len) as &dyn Value))])
});
} else { ; }
};
if start_index > end_index || end_index > source_len - 1 {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_span/src/source_map.rs:1017",
"rustc_span::source_map", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_span/src/source_map.rs"),
::tracing_core::__macro_support::Option::Some(1017u32),
::tracing_core::__macro_support::Option::Some("rustc_span::source_map"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("source indexes are malformed")
as &dyn Value))])
});
} else { ; }
};
return 1;
}
let src = local_begin.sf.external_src.read();
let snippet =
if let Some(src) = &local_begin.sf.src {
src
} else if let Some(src) = src.get_source() {
src
} else { return 1; };
if forwards {
(snippet.ceil_char_boundary(end_index + 1) - end_index) as u32
} else {
(end_index - snippet.floor_char_boundary(end_index - 1)) as
u32
}
}
}
}#[instrument(skip(self, sp))]987fn find_width_of_character_at_span(&self, sp: SpanData, forwards: bool) -> u32 {
988if sp.lo == sp.hi && !forwards {
989debug!("early return empty span");
990return 1;
991 }
992993let local_begin = self.lookup_byte_offset(sp.lo);
994let local_end = self.lookup_byte_offset(sp.hi);
995debug!("local_begin=`{:?}`, local_end=`{:?}`", local_begin, local_end);
996997if local_begin.sf.start_pos != local_end.sf.start_pos {
998debug!("begin and end are in different files");
999return 1;
1000 }
10011002let start_index = local_begin.pos.to_usize();
1003let end_index = local_end.pos.to_usize();
1004debug!("start_index=`{:?}`, end_index=`{:?}`", start_index, end_index);
10051006// Disregard indexes that are at the start or end of their spans, they can't fit bigger
1007 // characters.
1008if (!forwards && end_index == usize::MIN) || (forwards && start_index == usize::MAX) {
1009debug!("start or end of span, cannot be multibyte");
1010return 1;
1011 }
10121013let source_len = local_begin.sf.normalized_source_len.to_usize();
1014debug!("source_len=`{:?}`", source_len);
1015// Ensure indexes are also not malformed.
1016if start_index > end_index || end_index > source_len - 1 {
1017debug!("source indexes are malformed");
1018return 1;
1019 }
10201021let src = local_begin.sf.external_src.read();
10221023let snippet = if let Some(src) = &local_begin.sf.src {
1024 src
1025 } else if let Some(src) = src.get_source() {
1026 src
1027 } else {
1028return 1;
1029 };
10301031if forwards {
1032 (snippet.ceil_char_boundary(end_index + 1) - end_index) as u32
1033 } else {
1034 (end_index - snippet.floor_char_boundary(end_index - 1)) as u32
1035 }
1036 }
10371038pub fn get_source_file(&self, filename: &FileName) -> Option<Arc<SourceFile>> {
1039for sf in self.files.borrow().source_files.iter() {
1040if *filename == sf.name {
1041return Some(Arc::clone(&sf));
1042 }
1043 }
1044None1045 }
10461047/// For a global `BytePos`, computes the local offset within the containing `SourceFile`.
1048pub fn lookup_byte_offset(&self, bpos: BytePos) -> SourceFileAndBytePos {
1049let idx = self.lookup_source_file_idx(bpos);
1050let sf = Arc::clone(&(*self.files.borrow().source_files)[idx]);
1051let offset = bpos - sf.start_pos;
1052SourceFileAndBytePos { sf, pos: offset }
1053 }
10541055/// Returns the index of the [`SourceFile`] (in `self.files`) that contains `pos`.
1056 /// This index is guaranteed to be valid for the lifetime of this `SourceMap`,
1057 /// since `source_files` is a `MonotonicVec`
1058pub fn lookup_source_file_idx(&self, pos: BytePos) -> usize {
1059self.files.borrow().source_files.partition_point(|x| x.start_pos <= pos) - 1
1060}
10611062pub fn count_lines(&self) -> usize {
1063self.files().iter().fold(0, |a, f| a + f.count_lines())
1064 }
10651066pub fn ensure_source_file_source_present(&self, source_file: &SourceFile) -> bool {
1067source_file.add_external_src(|| {
1068let FileName::Real(ref name) = source_file.name else {
1069return None;
1070 };
10711072let local_path: Cow<'_, Path> = match name.local_path() {
1073Some(local) => local.into(),
1074None => {
1075// The compiler produces better error messages if the sources of dependencies
1076 // are available. Attempt to undo any path mapping so we can find remapped
1077 // dependencies.
1078 //
1079 // We can only use the heuristic because `add_external_src` checks the file
1080 // content hash.
1081let maybe_remapped_path = name.path(RemapPathScopeComponents::DIAGNOSTICS);
1082self.path_mapping
1083 .reverse_map_prefix_heuristically(maybe_remapped_path)
1084 .map(Cow::from)
1085 .unwrap_or(maybe_remapped_path.into())
1086 }
1087 };
10881089self.file_loader.read_file(&local_path).ok()
1090 })
1091 }
10921093pub fn is_imported(&self, sp: Span) -> bool {
1094let source_file_index = self.lookup_source_file_idx(sp.lo());
1095let source_file = &self.files()[source_file_index];
1096source_file.is_imported()
1097 }
10981099/// Gets the span of a statement. If the statement is a macro expansion, the
1100 /// span in the context of the block span is found. The trailing semicolon is included
1101 /// on a best-effort basis.
1102pub fn stmt_span(&self, stmt_span: Span, block_span: Span) -> Span {
1103if !stmt_span.from_expansion() {
1104return stmt_span;
1105 }
1106let mac_call = original_sp(stmt_span, block_span);
1107self.mac_call_stmt_semi_span(mac_call).map_or(mac_call, |s| mac_call.with_hi(s.hi()))
1108 }
11091110/// Tries to find the span of the semicolon of a macro call statement.
1111 /// The input must be the *call site* span of a statement from macro expansion.
1112 /// ```ignore (illustrative)
1113 /// // v output
1114 /// mac!();
1115 /// // ^^^^^^ input
1116 /// ```
1117pub fn mac_call_stmt_semi_span(&self, mac_call: Span) -> Option<Span> {
1118let span = self.span_extend_while_whitespace(mac_call);
1119let span = self.next_point(span);
1120if self.span_to_snippet(span).as_deref() == Ok(";") { Some(span) } else { None }
1121 }
1122}
11231124pub fn get_source_map() -> Option<Arc<SourceMap>> {
1125with_session_globals(|session_globals| session_globals.source_map.clone())
1126}
11271128#[derive(#[automatically_derived]
impl ::core::clone::Clone for FilePathMapping {
#[inline]
fn clone(&self) -> FilePathMapping {
FilePathMapping {
mapping: ::core::clone::Clone::clone(&self.mapping),
filename_remapping_scopes: ::core::clone::Clone::clone(&self.filename_remapping_scopes),
}
}
}Clone)]
1129pub struct FilePathMapping {
1130 mapping: Vec<(PathBuf, PathBuf)>,
1131 filename_remapping_scopes: RemapPathScopeComponents,
1132}
11331134impl FilePathMapping {
1135pub fn empty() -> FilePathMapping {
1136FilePathMapping::new(Vec::new(), RemapPathScopeComponents::empty())
1137 }
11381139pub fn new(
1140 mapping: Vec<(PathBuf, PathBuf)>,
1141 filename_remapping_scopes: RemapPathScopeComponents,
1142 ) -> FilePathMapping {
1143FilePathMapping { mapping, filename_remapping_scopes }
1144 }
11451146/// Applies any path prefix substitution as defined by the mapping.
1147 /// The return value is the remapped path and a boolean indicating whether
1148 /// the path was affected by the mapping.
1149fn map_prefix<'a>(&'a self, path: impl Into<Cow<'a, Path>>) -> (Cow<'a, Path>, bool) {
1150let path = path.into();
1151if path.as_os_str().is_empty() {
1152// Exit early if the path is empty and therefore there's nothing to remap.
1153 // This is mostly to reduce spam for `RUSTC_LOG=[remap_path_prefix]`.
1154return (path, false);
1155 }
11561157return remap_path_prefix(&self.mapping, path);
11581159x;#[instrument(level = "debug", skip(mapping), ret)]1160fn remap_path_prefix<'a>(
1161 mapping: &'a [(PathBuf, PathBuf)],
1162 path: Cow<'a, Path>,
1163 ) -> (Cow<'a, Path>, bool) {
1164// NOTE: We are iterating over the mapping entries from last to first
1165 // because entries specified later on the command line should
1166 // take precedence.
1167for (from, to) in mapping.iter().rev() {
1168debug!("Trying to apply {from:?} => {to:?}");
11691170if let Ok(rest) = path.strip_prefix(from) {
1171let remapped = if rest.as_os_str().is_empty() {
1172// This is subtle, joining an empty path onto e.g. `foo/bar` will
1173 // result in `foo/bar/`, that is, there'll be an additional directory
1174 // separator at the end. This can lead to duplicated directory separators
1175 // in remapped paths down the line.
1176 // So, if we have an exact match, we just return that without a call
1177 // to `Path::join()`.
1178to.into()
1179 } else {
1180 to.join(rest).into()
1181 };
1182debug!("Match - remapped");
11831184return (remapped, true);
1185 } else {
1186debug!("No match - prefix {from:?} does not match");
1187 }
1188 }
11891190debug!("not remapped");
1191 (path, false)
1192 }
1193 }
11941195/// Applies any path prefix substitution as defined by the mapping.
1196 ///
1197 /// The returned filename contains the a remapped path representing the remapped
1198 /// part if any remapping was performed.
1199pub fn to_real_filename<'a>(
1200&self,
1201 working_directory: &RealFileName,
1202 local_path: impl Into<Cow<'a, Path>>,
1203 ) -> RealFileName {
1204let local_path = local_path.into();
12051206let (remapped_path, mut was_remapped) = self.map_prefix(&*local_path);
1207{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_span/src/source_map.rs:1207",
"rustc_span::source_map", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_span/src/source_map.rs"),
::tracing_core::__macro_support::Option::Some(1207u32),
::tracing_core::__macro_support::Option::Some("rustc_span::source_map"),
::tracing_core::field::FieldSet::new(&["local_path",
"remapped_path", "was_remapped",
"self.filename_remapping_scopes"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&local_path)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&remapped_path)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&was_remapped)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&self.filename_remapping_scopes)
as &dyn Value))])
});
} else { ; }
};debug!(?local_path, ?remapped_path, ?was_remapped, ?self.filename_remapping_scopes);
12081209// Always populate the local part, even if we just remapped it and the scopes are
1210 // total, so that places that load the file from disk still have access to it.
1211let local = InnerRealFileName {
1212 name: local_path.to_path_buf(),
1213 working_directory: working_directory1214 .local_path()
1215 .expect("working directory should be local")
1216 .to_path_buf(),
1217 embeddable_name: if local_path.is_absolute() {
1218local_path.to_path_buf()
1219 } else {
1220working_directory1221 .local_path()
1222 .expect("working directory should be local")
1223 .to_path_buf()
1224 .join(&local_path)
1225 },
1226 };
12271228RealFileName {
1229 maybe_remapped: InnerRealFileName {
1230 working_directory: working_directory.maybe_remapped.name.clone(),
1231 embeddable_name: if remapped_path.is_absolute() || was_remapped {
1232// The current directory may have been remapped so we take that
1233 // into account, otherwise we'll forget to include the scopes
1234was_remapped = was_remapped || working_directory.was_remapped();
12351236remapped_path.to_path_buf()
1237 } else {
1238// Create an absolute path and remap it as well.
1239let (abs_path, abs_was_remapped) = self.map_prefix(
1240working_directory.maybe_remapped.name.clone().join(&remapped_path),
1241 );
12421243// If either the embeddable name or the working directory was
1244 // remapped, then the filename was remapped
1245was_remapped = abs_was_remapped || working_directory.was_remapped();
12461247abs_path.to_path_buf()
1248 },
1249 name: remapped_path.to_path_buf(),
1250 },
1251 local: Some(local),
1252 scopes: if was_remapped {
1253self.filename_remapping_scopes
1254 } else {
1255RemapPathScopeComponents::empty()
1256 },
1257 }
1258 }
12591260/// Attempts to (heuristically) reverse a prefix mapping.
1261 ///
1262 /// Returns [`Some`] if there is exactly one mapping where the "to" part is
1263 /// a prefix of `path` and has at least one non-empty
1264 /// [`Normal`](path::Component::Normal) component. The component
1265 /// restriction exists to avoid reverse mapping overly generic paths like
1266 /// `/` or `.`).
1267 ///
1268 /// This is a heuristic and not guaranteed to return the actual original
1269 /// path! Do not rely on the result unless you have other means to verify
1270 /// that the mapping is correct (e.g. by checking the file content hash).
1271x;#[instrument(level = "debug", skip(self), ret)]1272fn reverse_map_prefix_heuristically(&self, path: &Path) -> Option<PathBuf> {
1273let mut found = None;
12741275for (from, to) in self.mapping.iter() {
1276let has_normal_component = to.components().any(|c| match c {
1277 path::Component::Normal(s) => !s.is_empty(),
1278_ => false,
1279 });
12801281if !has_normal_component {
1282continue;
1283 }
12841285let Ok(rest) = path.strip_prefix(to) else {
1286continue;
1287 };
12881289if found.is_some() {
1290return None;
1291 }
12921293 found = Some(from.join(rest));
1294 }
12951296 found
1297 }
1298}