mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
Auto merge of #115507 - cjgillot:relative-source-file, r=oli-obk
Use relative positions inside a SourceFile. This allows to remove the normalization of start positions for hashing, and simplify allocation of global address space. cc `@Zoxc`
This commit is contained in:
commit
a991861ec9
@ -82,12 +82,9 @@ impl DebugContext {
|
||||
match tcx.sess.source_map().lookup_line(span.lo()) {
|
||||
Ok(SourceFileAndLine { sf: file, line }) => {
|
||||
let line_pos = file.lines(|lines| lines[line]);
|
||||
let col = file.relative_position(span.lo()) - line_pos;
|
||||
|
||||
(
|
||||
file,
|
||||
u64::try_from(line).unwrap() + 1,
|
||||
u64::from((span.lo() - line_pos).to_u32()) + 1,
|
||||
)
|
||||
(file, u64::try_from(line).unwrap() + 1, u64::from(col.to_u32()) + 1)
|
||||
}
|
||||
Err(file) => (file, 0, 0),
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ fn make_mir_scope<'ll, 'tcx>(
|
||||
let file = cx.sess().source_map().lookup_source_file(mir.span.lo());
|
||||
debug_context.scopes[scope] = DebugScope {
|
||||
file_start_pos: file.start_pos,
|
||||
file_end_pos: file.end_pos,
|
||||
file_end_pos: file.end_position(),
|
||||
..debug_context.scopes[scope]
|
||||
};
|
||||
instantiated.insert(scope);
|
||||
@ -120,7 +120,7 @@ fn make_mir_scope<'ll, 'tcx>(
|
||||
dbg_scope,
|
||||
inlined_at: inlined_at.or(parent_scope.inlined_at),
|
||||
file_start_pos: loc.file.start_pos,
|
||||
file_end_pos: loc.file.end_pos,
|
||||
file_end_pos: loc.file.end_position(),
|
||||
};
|
||||
instantiated.insert(scope);
|
||||
}
|
||||
|
@ -267,7 +267,7 @@ impl CodegenCx<'_, '_> {
|
||||
|
||||
// Use 1-based indexing.
|
||||
let line = (line + 1) as u32;
|
||||
let col = (pos - line_pos).to_u32() + 1;
|
||||
let col = (file.relative_position(pos) - line_pos).to_u32() + 1;
|
||||
|
||||
(file, line, col)
|
||||
}
|
||||
|
@ -1501,11 +1501,12 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
||||
|
||||
// We can't reuse an existing SourceFile, so allocate a new one
|
||||
// containing the information we need.
|
||||
let original_end_pos = source_file_to_import.end_position();
|
||||
let rustc_span::SourceFile {
|
||||
mut name,
|
||||
src_hash,
|
||||
start_pos,
|
||||
end_pos,
|
||||
start_pos: original_start_pos,
|
||||
source_len,
|
||||
lines,
|
||||
multibyte_chars,
|
||||
non_narrow_chars,
|
||||
@ -1547,35 +1548,32 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
||||
// on `try_to_translate_virtual_to_real`).
|
||||
try_to_translate_virtual_to_real(&mut name);
|
||||
|
||||
let source_length = (end_pos - start_pos).to_usize();
|
||||
|
||||
let local_version = sess.source_map().new_imported_source_file(
|
||||
name,
|
||||
src_hash,
|
||||
name_hash,
|
||||
source_length,
|
||||
source_len.to_u32(),
|
||||
self.cnum,
|
||||
lines,
|
||||
multibyte_chars,
|
||||
non_narrow_chars,
|
||||
normalized_pos,
|
||||
start_pos,
|
||||
source_file_index,
|
||||
);
|
||||
debug!(
|
||||
"CrateMetaData::imported_source_files alloc \
|
||||
source_file {:?} original (start_pos {:?} end_pos {:?}) \
|
||||
translated (start_pos {:?} end_pos {:?})",
|
||||
source_file {:?} original (start_pos {:?} source_len {:?}) \
|
||||
translated (start_pos {:?} source_len {:?})",
|
||||
local_version.name,
|
||||
start_pos,
|
||||
end_pos,
|
||||
original_start_pos,
|
||||
source_len,
|
||||
local_version.start_pos,
|
||||
local_version.end_pos
|
||||
local_version.source_len
|
||||
);
|
||||
|
||||
ImportedSourceFile {
|
||||
original_start_pos: start_pos,
|
||||
original_end_pos: end_pos,
|
||||
original_start_pos,
|
||||
original_end_pos,
|
||||
translated_source_file: local_version,
|
||||
}
|
||||
})
|
||||
|
@ -22,7 +22,7 @@ use rustc_span::hygiene::{
|
||||
ExpnId, HygieneDecodeContext, HygieneEncodeContext, SyntaxContext, SyntaxContextData,
|
||||
};
|
||||
use rustc_span::source_map::{SourceMap, StableSourceFileId};
|
||||
use rustc_span::{BytePos, ExpnData, ExpnHash, Pos, SourceFile, Span};
|
||||
use rustc_span::{BytePos, ExpnData, ExpnHash, Pos, RelativeBytePos, SourceFile, Span};
|
||||
use rustc_span::{CachingSourceMapView, Symbol};
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::io;
|
||||
@ -688,11 +688,12 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Span {
|
||||
|
||||
let file_lo_index = SourceFileIndex::decode(decoder);
|
||||
let line_lo = usize::decode(decoder);
|
||||
let col_lo = BytePos::decode(decoder);
|
||||
let col_lo = RelativeBytePos::decode(decoder);
|
||||
let len = BytePos::decode(decoder);
|
||||
|
||||
let file_lo = decoder.file_index_to_file(file_lo_index);
|
||||
let lo = file_lo.lines(|lines| lines[line_lo - 1] + col_lo);
|
||||
let lo = file_lo.absolute_position(lo);
|
||||
let hi = lo + len;
|
||||
|
||||
Span::new(lo, hi, ctxt, parent)
|
||||
|
@ -28,7 +28,7 @@ use rustc_middle::mir::{
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_span::def_id::DefId;
|
||||
use rustc_span::source_map::SourceMap;
|
||||
use rustc_span::{CharPos, ExpnKind, Pos, SourceFile, Span, Symbol};
|
||||
use rustc_span::{ExpnKind, SourceFile, Span, Symbol};
|
||||
|
||||
/// A simple error message wrapper for `coverage::Error`s.
|
||||
#[derive(Debug)]
|
||||
@ -314,8 +314,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
|
||||
};
|
||||
graphviz_data.add_bcb_coverage_span_with_counter(bcb, &covspan, &counter_kind);
|
||||
|
||||
let code_region =
|
||||
make_code_region(source_map, file_name, &self.source_file, span, body_span);
|
||||
let code_region = make_code_region(source_map, file_name, span, body_span);
|
||||
|
||||
inject_statement(
|
||||
self.mir_body,
|
||||
@ -510,40 +509,36 @@ fn inject_intermediate_expression(mir_body: &mut mir::Body<'_>, expression: Cove
|
||||
fn make_code_region(
|
||||
source_map: &SourceMap,
|
||||
file_name: Symbol,
|
||||
source_file: &Lrc<SourceFile>,
|
||||
span: Span,
|
||||
body_span: Span,
|
||||
) -> CodeRegion {
|
||||
debug!(
|
||||
"Called make_code_region(file_name={}, source_file={:?}, span={}, body_span={})",
|
||||
"Called make_code_region(file_name={}, span={}, body_span={})",
|
||||
file_name,
|
||||
source_file,
|
||||
source_map.span_to_diagnostic_string(span),
|
||||
source_map.span_to_diagnostic_string(body_span)
|
||||
);
|
||||
|
||||
let (start_line, mut start_col) = source_file.lookup_file_pos(span.lo());
|
||||
let (end_line, end_col) = if span.hi() == span.lo() {
|
||||
let (end_line, mut end_col) = (start_line, start_col);
|
||||
let (file, mut start_line, mut start_col, mut end_line, mut end_col) =
|
||||
source_map.span_to_location_info(span);
|
||||
if span.hi() == span.lo() {
|
||||
// Extend an empty span by one character so the region will be counted.
|
||||
let CharPos(char_pos) = start_col;
|
||||
if span.hi() == body_span.hi() {
|
||||
start_col = CharPos(char_pos.saturating_sub(1));
|
||||
start_col = start_col.saturating_sub(1);
|
||||
} else {
|
||||
end_col = CharPos(char_pos + 1);
|
||||
end_col = start_col + 1;
|
||||
}
|
||||
(end_line, end_col)
|
||||
} else {
|
||||
source_file.lookup_file_pos(span.hi())
|
||||
};
|
||||
let start_line = source_map.doctest_offset_line(&source_file.name, start_line);
|
||||
let end_line = source_map.doctest_offset_line(&source_file.name, end_line);
|
||||
if let Some(file) = file {
|
||||
start_line = source_map.doctest_offset_line(&file.name, start_line);
|
||||
end_line = source_map.doctest_offset_line(&file.name, end_line);
|
||||
}
|
||||
CodeRegion {
|
||||
file_name,
|
||||
start_line: start_line as u32,
|
||||
start_col: start_col.to_u32() + 1,
|
||||
start_col: start_col as u32,
|
||||
end_line: end_line as u32,
|
||||
end_col: end_col.to_u32() + 1,
|
||||
end_col: end_col as u32,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -132,7 +132,7 @@ fn maybe_source_file_to_parser(
|
||||
sess: &ParseSess,
|
||||
source_file: Lrc<SourceFile>,
|
||||
) -> Result<Parser<'_>, Vec<Diagnostic>> {
|
||||
let end_pos = source_file.end_pos;
|
||||
let end_pos = source_file.end_position();
|
||||
let stream = maybe_file_to_stream(sess, source_file, None)?;
|
||||
let mut parser = stream_to_parser(sess, stream, None);
|
||||
if parser.token == token::Eof {
|
||||
|
@ -5,7 +5,7 @@ use crate::ich::StableHashingContext;
|
||||
|
||||
use rustc_ast as ast;
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_span::{BytePos, NormalizedPos, SourceFile};
|
||||
use rustc_span::SourceFile;
|
||||
use std::assert_matches::assert_matches;
|
||||
|
||||
use smallvec::SmallVec;
|
||||
@ -67,8 +67,8 @@ impl<'a> HashStable<StableHashingContext<'a>> for SourceFile {
|
||||
src: _,
|
||||
ref src_hash,
|
||||
external_src: _,
|
||||
start_pos,
|
||||
end_pos: _,
|
||||
start_pos: _,
|
||||
source_len: _,
|
||||
lines: _,
|
||||
ref multibyte_chars,
|
||||
ref non_narrow_chars,
|
||||
@ -85,56 +85,30 @@ impl<'a> HashStable<StableHashingContext<'a>> for SourceFile {
|
||||
// We only hash the relative position within this source_file
|
||||
lines.len().hash_stable(hcx, hasher);
|
||||
for &line in lines.iter() {
|
||||
stable_byte_pos(line, start_pos).hash_stable(hcx, hasher);
|
||||
line.hash_stable(hcx, hasher);
|
||||
}
|
||||
});
|
||||
|
||||
// We only hash the relative position within this source_file
|
||||
multibyte_chars.len().hash_stable(hcx, hasher);
|
||||
for &char_pos in multibyte_chars.iter() {
|
||||
stable_multibyte_char(char_pos, start_pos).hash_stable(hcx, hasher);
|
||||
char_pos.hash_stable(hcx, hasher);
|
||||
}
|
||||
|
||||
non_narrow_chars.len().hash_stable(hcx, hasher);
|
||||
for &char_pos in non_narrow_chars.iter() {
|
||||
stable_non_narrow_char(char_pos, start_pos).hash_stable(hcx, hasher);
|
||||
char_pos.hash_stable(hcx, hasher);
|
||||
}
|
||||
|
||||
normalized_pos.len().hash_stable(hcx, hasher);
|
||||
for &char_pos in normalized_pos.iter() {
|
||||
stable_normalized_pos(char_pos, start_pos).hash_stable(hcx, hasher);
|
||||
char_pos.hash_stable(hcx, hasher);
|
||||
}
|
||||
|
||||
cnum.hash_stable(hcx, hasher);
|
||||
}
|
||||
}
|
||||
|
||||
fn stable_byte_pos(pos: BytePos, source_file_start: BytePos) -> u32 {
|
||||
pos.0 - source_file_start.0
|
||||
}
|
||||
|
||||
fn stable_multibyte_char(mbc: rustc_span::MultiByteChar, source_file_start: BytePos) -> (u32, u32) {
|
||||
let rustc_span::MultiByteChar { pos, bytes } = mbc;
|
||||
|
||||
(pos.0 - source_file_start.0, bytes as u32)
|
||||
}
|
||||
|
||||
fn stable_non_narrow_char(
|
||||
swc: rustc_span::NonNarrowChar,
|
||||
source_file_start: BytePos,
|
||||
) -> (u32, u32) {
|
||||
let pos = swc.pos();
|
||||
let width = swc.width();
|
||||
|
||||
(pos.0 - source_file_start.0, width as u32)
|
||||
}
|
||||
|
||||
fn stable_normalized_pos(np: NormalizedPos, source_file_start: BytePos) -> (u32, u32) {
|
||||
let NormalizedPos { pos, diff } = np;
|
||||
|
||||
(pos.0 - source_file_start.0, diff)
|
||||
}
|
||||
|
||||
impl<'tcx> HashStable<StableHashingContext<'tcx>> for rustc_feature::Features {
|
||||
fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) {
|
||||
// Unfortunately we cannot exhaustively list fields here, since the
|
||||
|
@ -11,26 +11,19 @@ mod tests;
|
||||
/// is detected at runtime.
|
||||
pub fn analyze_source_file(
|
||||
src: &str,
|
||||
source_file_start_pos: BytePos,
|
||||
) -> (Vec<BytePos>, Vec<MultiByteChar>, Vec<NonNarrowChar>) {
|
||||
let mut lines = vec![source_file_start_pos];
|
||||
) -> (Vec<RelativeBytePos>, Vec<MultiByteChar>, Vec<NonNarrowChar>) {
|
||||
let mut lines = vec![RelativeBytePos::from_u32(0)];
|
||||
let mut multi_byte_chars = vec![];
|
||||
let mut non_narrow_chars = vec![];
|
||||
|
||||
// Calls the right implementation, depending on hardware support available.
|
||||
analyze_source_file_dispatch(
|
||||
src,
|
||||
source_file_start_pos,
|
||||
&mut lines,
|
||||
&mut multi_byte_chars,
|
||||
&mut non_narrow_chars,
|
||||
);
|
||||
analyze_source_file_dispatch(src, &mut lines, &mut multi_byte_chars, &mut non_narrow_chars);
|
||||
|
||||
// The code above optimistically registers a new line *after* each \n
|
||||
// it encounters. If that point is already outside the source_file, remove
|
||||
// it again.
|
||||
if let Some(&last_line_start) = lines.last() {
|
||||
let source_file_end = source_file_start_pos + BytePos::from_usize(src.len());
|
||||
let source_file_end = RelativeBytePos::from_usize(src.len());
|
||||
assert!(source_file_end >= last_line_start);
|
||||
if last_line_start == source_file_end {
|
||||
lines.pop();
|
||||
@ -43,14 +36,12 @@ pub fn analyze_source_file(
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
|
||||
fn analyze_source_file_dispatch(src: &str,
|
||||
source_file_start_pos: BytePos,
|
||||
lines: &mut Vec<BytePos>,
|
||||
lines: &mut Vec<RelativeBytePos>,
|
||||
multi_byte_chars: &mut Vec<MultiByteChar>,
|
||||
non_narrow_chars: &mut Vec<NonNarrowChar>) {
|
||||
if is_x86_feature_detected!("sse2") {
|
||||
unsafe {
|
||||
analyze_source_file_sse2(src,
|
||||
source_file_start_pos,
|
||||
lines,
|
||||
multi_byte_chars,
|
||||
non_narrow_chars);
|
||||
@ -58,7 +49,7 @@ cfg_if::cfg_if! {
|
||||
} else {
|
||||
analyze_source_file_generic(src,
|
||||
src.len(),
|
||||
source_file_start_pos,
|
||||
RelativeBytePos::from_u32(0),
|
||||
lines,
|
||||
multi_byte_chars,
|
||||
non_narrow_chars);
|
||||
@ -72,8 +63,7 @@ cfg_if::cfg_if! {
|
||||
/// SSE2 intrinsics to quickly find all newlines.
|
||||
#[target_feature(enable = "sse2")]
|
||||
unsafe fn analyze_source_file_sse2(src: &str,
|
||||
output_offset: BytePos,
|
||||
lines: &mut Vec<BytePos>,
|
||||
lines: &mut Vec<RelativeBytePos>,
|
||||
multi_byte_chars: &mut Vec<MultiByteChar>,
|
||||
non_narrow_chars: &mut Vec<NonNarrowChar>) {
|
||||
#[cfg(target_arch = "x86")]
|
||||
@ -129,8 +119,7 @@ cfg_if::cfg_if! {
|
||||
if control_char_mask == newlines_mask {
|
||||
// All control characters are newlines, record them
|
||||
let mut newlines_mask = 0xFFFF0000 | newlines_mask as u32;
|
||||
let output_offset = output_offset +
|
||||
BytePos::from_usize(chunk_index * CHUNK_SIZE + 1);
|
||||
let output_offset = RelativeBytePos::from_usize(chunk_index * CHUNK_SIZE + 1);
|
||||
|
||||
loop {
|
||||
let index = newlines_mask.trailing_zeros();
|
||||
@ -140,7 +129,7 @@ cfg_if::cfg_if! {
|
||||
break
|
||||
}
|
||||
|
||||
lines.push(BytePos(index) + output_offset);
|
||||
lines.push(RelativeBytePos(index) + output_offset);
|
||||
|
||||
// Clear the bit, so we can find the next one.
|
||||
newlines_mask &= (!1) << index;
|
||||
@ -165,7 +154,7 @@ cfg_if::cfg_if! {
|
||||
intra_chunk_offset = analyze_source_file_generic(
|
||||
&src[scan_start .. ],
|
||||
CHUNK_SIZE - intra_chunk_offset,
|
||||
BytePos::from_usize(scan_start) + output_offset,
|
||||
RelativeBytePos::from_usize(scan_start),
|
||||
lines,
|
||||
multi_byte_chars,
|
||||
non_narrow_chars
|
||||
@ -177,7 +166,7 @@ cfg_if::cfg_if! {
|
||||
if tail_start < src.len() {
|
||||
analyze_source_file_generic(&src[tail_start ..],
|
||||
src.len() - tail_start,
|
||||
output_offset + BytePos::from_usize(tail_start),
|
||||
RelativeBytePos::from_usize(tail_start),
|
||||
lines,
|
||||
multi_byte_chars,
|
||||
non_narrow_chars);
|
||||
@ -187,13 +176,12 @@ cfg_if::cfg_if! {
|
||||
|
||||
// The target (or compiler version) does not support SSE2 ...
|
||||
fn analyze_source_file_dispatch(src: &str,
|
||||
source_file_start_pos: BytePos,
|
||||
lines: &mut Vec<BytePos>,
|
||||
lines: &mut Vec<RelativeBytePos>,
|
||||
multi_byte_chars: &mut Vec<MultiByteChar>,
|
||||
non_narrow_chars: &mut Vec<NonNarrowChar>) {
|
||||
analyze_source_file_generic(src,
|
||||
src.len(),
|
||||
source_file_start_pos,
|
||||
RelativeBytePos::from_u32(0),
|
||||
lines,
|
||||
multi_byte_chars,
|
||||
non_narrow_chars);
|
||||
@ -207,8 +195,8 @@ cfg_if::cfg_if! {
|
||||
fn analyze_source_file_generic(
|
||||
src: &str,
|
||||
scan_len: usize,
|
||||
output_offset: BytePos,
|
||||
lines: &mut Vec<BytePos>,
|
||||
output_offset: RelativeBytePos,
|
||||
lines: &mut Vec<RelativeBytePos>,
|
||||
multi_byte_chars: &mut Vec<MultiByteChar>,
|
||||
non_narrow_chars: &mut Vec<NonNarrowChar>,
|
||||
) -> usize {
|
||||
@ -230,11 +218,11 @@ fn analyze_source_file_generic(
|
||||
// This is an ASCII control character, it could be one of the cases
|
||||
// that are interesting to us.
|
||||
|
||||
let pos = BytePos::from_usize(i) + output_offset;
|
||||
let pos = RelativeBytePos::from_usize(i) + output_offset;
|
||||
|
||||
match byte {
|
||||
b'\n' => {
|
||||
lines.push(pos + BytePos(1));
|
||||
lines.push(pos + RelativeBytePos(1));
|
||||
}
|
||||
b'\t' => {
|
||||
non_narrow_chars.push(NonNarrowChar::Tab(pos));
|
||||
@ -250,7 +238,7 @@ fn analyze_source_file_generic(
|
||||
let c = src[i..].chars().next().unwrap();
|
||||
char_len = c.len_utf8();
|
||||
|
||||
let pos = BytePos::from_usize(i) + output_offset;
|
||||
let pos = RelativeBytePos::from_usize(i) + output_offset;
|
||||
|
||||
if char_len > 1 {
|
||||
assert!((2..=4).contains(&char_len));
|
||||
|
@ -3,29 +3,28 @@ use super::*;
|
||||
macro_rules! test {
|
||||
(case: $test_name:ident,
|
||||
text: $text:expr,
|
||||
source_file_start_pos: $source_file_start_pos:expr,
|
||||
lines: $lines:expr,
|
||||
multi_byte_chars: $multi_byte_chars:expr,
|
||||
non_narrow_chars: $non_narrow_chars:expr,) => {
|
||||
#[test]
|
||||
fn $test_name() {
|
||||
let (lines, multi_byte_chars, non_narrow_chars) =
|
||||
analyze_source_file($text, BytePos($source_file_start_pos));
|
||||
let (lines, multi_byte_chars, non_narrow_chars) = analyze_source_file($text);
|
||||
|
||||
let expected_lines: Vec<BytePos> = $lines.into_iter().map(BytePos).collect();
|
||||
let expected_lines: Vec<RelativeBytePos> =
|
||||
$lines.into_iter().map(RelativeBytePos).collect();
|
||||
|
||||
assert_eq!(lines, expected_lines);
|
||||
|
||||
let expected_mbcs: Vec<MultiByteChar> = $multi_byte_chars
|
||||
.into_iter()
|
||||
.map(|(pos, bytes)| MultiByteChar { pos: BytePos(pos), bytes })
|
||||
.map(|(pos, bytes)| MultiByteChar { pos: RelativeBytePos(pos), bytes })
|
||||
.collect();
|
||||
|
||||
assert_eq!(multi_byte_chars, expected_mbcs);
|
||||
|
||||
let expected_nncs: Vec<NonNarrowChar> = $non_narrow_chars
|
||||
.into_iter()
|
||||
.map(|(pos, width)| NonNarrowChar::new(BytePos(pos), width))
|
||||
.map(|(pos, width)| NonNarrowChar::new(RelativeBytePos(pos), width))
|
||||
.collect();
|
||||
|
||||
assert_eq!(non_narrow_chars, expected_nncs);
|
||||
@ -36,7 +35,6 @@ macro_rules! test {
|
||||
test!(
|
||||
case: empty_text,
|
||||
text: "",
|
||||
source_file_start_pos: 0,
|
||||
lines: vec![],
|
||||
multi_byte_chars: vec![],
|
||||
non_narrow_chars: vec![],
|
||||
@ -45,7 +43,6 @@ test!(
|
||||
test!(
|
||||
case: newlines_short,
|
||||
text: "a\nc",
|
||||
source_file_start_pos: 0,
|
||||
lines: vec![0, 2],
|
||||
multi_byte_chars: vec![],
|
||||
non_narrow_chars: vec![],
|
||||
@ -54,7 +51,6 @@ test!(
|
||||
test!(
|
||||
case: newlines_long,
|
||||
text: "012345678\nabcdef012345678\na",
|
||||
source_file_start_pos: 0,
|
||||
lines: vec![0, 10, 26],
|
||||
multi_byte_chars: vec![],
|
||||
non_narrow_chars: vec![],
|
||||
@ -63,7 +59,6 @@ test!(
|
||||
test!(
|
||||
case: newline_and_multi_byte_char_in_same_chunk,
|
||||
text: "01234β789\nbcdef0123456789abcdef",
|
||||
source_file_start_pos: 0,
|
||||
lines: vec![0, 11],
|
||||
multi_byte_chars: vec![(5, 2)],
|
||||
non_narrow_chars: vec![],
|
||||
@ -72,7 +67,6 @@ test!(
|
||||
test!(
|
||||
case: newline_and_control_char_in_same_chunk,
|
||||
text: "01234\u{07}6789\nbcdef0123456789abcdef",
|
||||
source_file_start_pos: 0,
|
||||
lines: vec![0, 11],
|
||||
multi_byte_chars: vec![],
|
||||
non_narrow_chars: vec![(5, 0)],
|
||||
@ -81,7 +75,6 @@ test!(
|
||||
test!(
|
||||
case: multi_byte_char_short,
|
||||
text: "aβc",
|
||||
source_file_start_pos: 0,
|
||||
lines: vec![0],
|
||||
multi_byte_chars: vec![(1, 2)],
|
||||
non_narrow_chars: vec![],
|
||||
@ -90,7 +83,6 @@ test!(
|
||||
test!(
|
||||
case: multi_byte_char_long,
|
||||
text: "0123456789abcΔf012345β",
|
||||
source_file_start_pos: 0,
|
||||
lines: vec![0],
|
||||
multi_byte_chars: vec![(13, 2), (22, 2)],
|
||||
non_narrow_chars: vec![],
|
||||
@ -99,7 +91,6 @@ test!(
|
||||
test!(
|
||||
case: multi_byte_char_across_chunk_boundary,
|
||||
text: "0123456789abcdeΔ123456789abcdef01234",
|
||||
source_file_start_pos: 0,
|
||||
lines: vec![0],
|
||||
multi_byte_chars: vec![(15, 2)],
|
||||
non_narrow_chars: vec![],
|
||||
@ -108,7 +99,6 @@ test!(
|
||||
test!(
|
||||
case: multi_byte_char_across_chunk_boundary_tail,
|
||||
text: "0123456789abcdeΔ....",
|
||||
source_file_start_pos: 0,
|
||||
lines: vec![0],
|
||||
multi_byte_chars: vec![(15, 2)],
|
||||
non_narrow_chars: vec![],
|
||||
@ -117,7 +107,6 @@ test!(
|
||||
test!(
|
||||
case: non_narrow_short,
|
||||
text: "0\t2",
|
||||
source_file_start_pos: 0,
|
||||
lines: vec![0],
|
||||
multi_byte_chars: vec![],
|
||||
non_narrow_chars: vec![(1, 4)],
|
||||
@ -126,7 +115,6 @@ test!(
|
||||
test!(
|
||||
case: non_narrow_long,
|
||||
text: "01\t3456789abcdef01234567\u{07}9",
|
||||
source_file_start_pos: 0,
|
||||
lines: vec![0],
|
||||
multi_byte_chars: vec![],
|
||||
non_narrow_chars: vec![(2, 4), (24, 0)],
|
||||
@ -135,8 +123,7 @@ test!(
|
||||
test!(
|
||||
case: output_offset_all,
|
||||
text: "01\t345\n789abcΔf01234567\u{07}9\nbcΔf",
|
||||
source_file_start_pos: 1000,
|
||||
lines: vec![0 + 1000, 7 + 1000, 27 + 1000],
|
||||
multi_byte_chars: vec![(13 + 1000, 2), (29 + 1000, 2)],
|
||||
non_narrow_chars: vec![(2 + 1000, 4), (24 + 1000, 0)],
|
||||
lines: vec![0, 7, 27],
|
||||
multi_byte_chars: vec![(13, 2), (29, 2)],
|
||||
non_narrow_chars: vec![(2, 4), (24, 0)],
|
||||
);
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::source_map::SourceMap;
|
||||
use crate::{BytePos, SourceFile, SpanData};
|
||||
use crate::{BytePos, Pos, RelativeBytePos, SourceFile, SpanData};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use std::ops::Range;
|
||||
|
||||
@ -37,6 +37,7 @@ impl CacheEntry {
|
||||
self.file_index = file_idx;
|
||||
}
|
||||
|
||||
let pos = self.file.relative_position(pos);
|
||||
let line_index = self.file.lookup_line(pos).unwrap();
|
||||
let line_bounds = self.file.line_bounds(line_index);
|
||||
self.line_number = line_index + 1;
|
||||
@ -79,7 +80,7 @@ impl<'sm> CachingSourceMapView<'sm> {
|
||||
pub fn byte_pos_to_line_and_col(
|
||||
&mut self,
|
||||
pos: BytePos,
|
||||
) -> Option<(Lrc<SourceFile>, usize, BytePos)> {
|
||||
) -> Option<(Lrc<SourceFile>, usize, RelativeBytePos)> {
|
||||
self.time_stamp += 1;
|
||||
|
||||
// Check if the position is in one of the cached lines
|
||||
@ -88,11 +89,8 @@ impl<'sm> CachingSourceMapView<'sm> {
|
||||
let cache_entry = &mut self.line_cache[cache_idx as usize];
|
||||
cache_entry.touch(self.time_stamp);
|
||||
|
||||
return Some((
|
||||
cache_entry.file.clone(),
|
||||
cache_entry.line_number,
|
||||
pos - cache_entry.line.start,
|
||||
));
|
||||
let col = RelativeBytePos(pos.to_u32() - cache_entry.line.start.to_u32());
|
||||
return Some((cache_entry.file.clone(), cache_entry.line_number, col));
|
||||
}
|
||||
|
||||
// No cache hit ...
|
||||
@ -108,7 +106,8 @@ impl<'sm> CachingSourceMapView<'sm> {
|
||||
let cache_entry = &mut self.line_cache[oldest];
|
||||
cache_entry.update(new_file_and_idx, pos, self.time_stamp);
|
||||
|
||||
Some((cache_entry.file.clone(), cache_entry.line_number, pos - cache_entry.line.start))
|
||||
let col = RelativeBytePos(pos.to_u32() - cache_entry.line.start.to_u32());
|
||||
Some((cache_entry.file.clone(), cache_entry.line_number, col))
|
||||
}
|
||||
|
||||
pub fn span_data_to_lines_and_cols(
|
||||
|
@ -1107,27 +1107,27 @@ impl fmt::Debug for SpanData {
|
||||
}
|
||||
|
||||
/// Identifies an offset of a multi-byte character in a `SourceFile`.
|
||||
#[derive(Copy, Clone, Encodable, Decodable, Eq, PartialEq, Debug)]
|
||||
#[derive(Copy, Clone, Encodable, Decodable, Eq, PartialEq, Debug, HashStable_Generic)]
|
||||
pub struct MultiByteChar {
|
||||
/// The absolute offset of the character in the `SourceMap`.
|
||||
pub pos: BytePos,
|
||||
/// The relative offset of the character in the `SourceFile`.
|
||||
pub pos: RelativeBytePos,
|
||||
/// The number of bytes, `>= 2`.
|
||||
pub bytes: u8,
|
||||
}
|
||||
|
||||
/// Identifies an offset of a non-narrow character in a `SourceFile`.
|
||||
#[derive(Copy, Clone, Encodable, Decodable, Eq, PartialEq, Debug)]
|
||||
#[derive(Copy, Clone, Encodable, Decodable, Eq, PartialEq, Debug, HashStable_Generic)]
|
||||
pub enum NonNarrowChar {
|
||||
/// Represents a zero-width character.
|
||||
ZeroWidth(BytePos),
|
||||
ZeroWidth(RelativeBytePos),
|
||||
/// Represents a wide (full-width) character.
|
||||
Wide(BytePos),
|
||||
Wide(RelativeBytePos),
|
||||
/// Represents a tab character, represented visually with a width of 4 characters.
|
||||
Tab(BytePos),
|
||||
Tab(RelativeBytePos),
|
||||
}
|
||||
|
||||
impl NonNarrowChar {
|
||||
fn new(pos: BytePos, width: usize) -> Self {
|
||||
fn new(pos: RelativeBytePos, width: usize) -> Self {
|
||||
match width {
|
||||
0 => NonNarrowChar::ZeroWidth(pos),
|
||||
2 => NonNarrowChar::Wide(pos),
|
||||
@ -1136,8 +1136,8 @@ impl NonNarrowChar {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the absolute offset of the character in the `SourceMap`.
|
||||
pub fn pos(&self) -> BytePos {
|
||||
/// Returns the relative offset of the character in the `SourceFile`.
|
||||
pub fn pos(&self) -> RelativeBytePos {
|
||||
match *self {
|
||||
NonNarrowChar::ZeroWidth(p) | NonNarrowChar::Wide(p) | NonNarrowChar::Tab(p) => p,
|
||||
}
|
||||
@ -1153,10 +1153,10 @@ impl NonNarrowChar {
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<BytePos> for NonNarrowChar {
|
||||
impl Add<RelativeBytePos> for NonNarrowChar {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: BytePos) -> Self {
|
||||
fn add(self, rhs: RelativeBytePos) -> Self {
|
||||
match self {
|
||||
NonNarrowChar::ZeroWidth(pos) => NonNarrowChar::ZeroWidth(pos + rhs),
|
||||
NonNarrowChar::Wide(pos) => NonNarrowChar::Wide(pos + rhs),
|
||||
@ -1165,10 +1165,10 @@ impl Add<BytePos> for NonNarrowChar {
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub<BytePos> for NonNarrowChar {
|
||||
impl Sub<RelativeBytePos> for NonNarrowChar {
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, rhs: BytePos) -> Self {
|
||||
fn sub(self, rhs: RelativeBytePos) -> Self {
|
||||
match self {
|
||||
NonNarrowChar::ZeroWidth(pos) => NonNarrowChar::ZeroWidth(pos - rhs),
|
||||
NonNarrowChar::Wide(pos) => NonNarrowChar::Wide(pos - rhs),
|
||||
@ -1178,10 +1178,10 @@ impl Sub<BytePos> for NonNarrowChar {
|
||||
}
|
||||
|
||||
/// Identifies an offset of a character that was normalized away from `SourceFile`.
|
||||
#[derive(Copy, Clone, Encodable, Decodable, Eq, PartialEq, Debug)]
|
||||
#[derive(Copy, Clone, Encodable, Decodable, Eq, PartialEq, Debug, HashStable_Generic)]
|
||||
pub struct NormalizedPos {
|
||||
/// The absolute offset of the character in the `SourceMap`.
|
||||
pub pos: BytePos,
|
||||
/// The relative offset of the character in the `SourceFile`.
|
||||
pub pos: RelativeBytePos,
|
||||
/// The difference between original and normalized string at position.
|
||||
pub diff: u32,
|
||||
}
|
||||
@ -1293,7 +1293,7 @@ impl SourceFileHash {
|
||||
#[derive(Clone)]
|
||||
pub enum SourceFileLines {
|
||||
/// The source file lines, in decoded (random-access) form.
|
||||
Lines(Vec<BytePos>),
|
||||
Lines(Vec<RelativeBytePos>),
|
||||
|
||||
/// The source file lines, in undecoded difference list form.
|
||||
Diffs(SourceFileDiffs),
|
||||
@ -1314,11 +1314,6 @@ impl SourceFileLines {
|
||||
/// small crates where very little of `std`'s metadata is used.
|
||||
#[derive(Clone)]
|
||||
pub struct SourceFileDiffs {
|
||||
/// Position of the first line. Note that this is always encoded as a
|
||||
/// `BytePos` because it is often much larger than any of the
|
||||
/// differences.
|
||||
line_start: BytePos,
|
||||
|
||||
/// Always 1, 2, or 4. Always as small as possible, while being big
|
||||
/// enough to hold the length of the longest line in the source file.
|
||||
/// The 1 case is by far the most common.
|
||||
@ -1351,8 +1346,8 @@ pub struct SourceFile {
|
||||
pub external_src: Lock<ExternalSource>,
|
||||
/// The start position of this source in the `SourceMap`.
|
||||
pub start_pos: BytePos,
|
||||
/// The end position of this source in the `SourceMap`.
|
||||
pub end_pos: BytePos,
|
||||
/// The byte length of this source.
|
||||
pub source_len: RelativeBytePos,
|
||||
/// Locations of lines beginnings in the source code.
|
||||
pub lines: Lock<SourceFileLines>,
|
||||
/// Locations of multi-byte characters in the source code.
|
||||
@ -1375,7 +1370,7 @@ impl Clone for SourceFile {
|
||||
src_hash: self.src_hash,
|
||||
external_src: Lock::new(self.external_src.borrow().clone()),
|
||||
start_pos: self.start_pos,
|
||||
end_pos: self.end_pos,
|
||||
source_len: self.source_len,
|
||||
lines: Lock::new(self.lines.borrow().clone()),
|
||||
multibyte_chars: self.multibyte_chars.clone(),
|
||||
non_narrow_chars: self.non_narrow_chars.clone(),
|
||||
@ -1390,8 +1385,8 @@ impl<S: Encoder> Encodable<S> for SourceFile {
|
||||
fn encode(&self, s: &mut S) {
|
||||
self.name.encode(s);
|
||||
self.src_hash.encode(s);
|
||||
self.start_pos.encode(s);
|
||||
self.end_pos.encode(s);
|
||||
// Do not encode `start_pos` as it's global state for this session.
|
||||
self.source_len.encode(s);
|
||||
|
||||
// We are always in `Lines` form by the time we reach here.
|
||||
assert!(self.lines.borrow().is_lines());
|
||||
@ -1422,7 +1417,7 @@ impl<S: Encoder> Encodable<S> for SourceFile {
|
||||
s.emit_u8(bytes_per_diff as u8);
|
||||
|
||||
// Encode the first element.
|
||||
lines[0].encode(s);
|
||||
assert_eq!(lines[0], RelativeBytePos(0));
|
||||
|
||||
// Encode the difference list.
|
||||
let diff_iter = lines.array_windows().map(|&[fst, snd]| snd - fst);
|
||||
@ -1465,26 +1460,17 @@ impl<D: Decoder> Decodable<D> for SourceFile {
|
||||
fn decode(d: &mut D) -> SourceFile {
|
||||
let name: FileName = Decodable::decode(d);
|
||||
let src_hash: SourceFileHash = Decodable::decode(d);
|
||||
let start_pos: BytePos = Decodable::decode(d);
|
||||
let end_pos: BytePos = Decodable::decode(d);
|
||||
let source_len: RelativeBytePos = Decodable::decode(d);
|
||||
let lines = {
|
||||
let num_lines: u32 = Decodable::decode(d);
|
||||
if num_lines > 0 {
|
||||
// Read the number of bytes used per diff.
|
||||
let bytes_per_diff = d.read_u8() as usize;
|
||||
|
||||
// Read the first element.
|
||||
let line_start: BytePos = Decodable::decode(d);
|
||||
|
||||
// Read the difference list.
|
||||
let num_diffs = num_lines as usize - 1;
|
||||
let raw_diffs = d.read_raw_bytes(bytes_per_diff * num_diffs).to_vec();
|
||||
SourceFileLines::Diffs(SourceFileDiffs {
|
||||
line_start,
|
||||
bytes_per_diff,
|
||||
num_diffs,
|
||||
raw_diffs,
|
||||
})
|
||||
SourceFileLines::Diffs(SourceFileDiffs { bytes_per_diff, num_diffs, raw_diffs })
|
||||
} else {
|
||||
SourceFileLines::Lines(vec![])
|
||||
}
|
||||
@ -1496,8 +1482,8 @@ impl<D: Decoder> Decodable<D> for SourceFile {
|
||||
let cnum: CrateNum = Decodable::decode(d);
|
||||
SourceFile {
|
||||
name,
|
||||
start_pos,
|
||||
end_pos,
|
||||
start_pos: BytePos::from_u32(0),
|
||||
source_len,
|
||||
src: None,
|
||||
src_hash,
|
||||
// Unused - the metadata decoder will construct
|
||||
@ -1523,63 +1509,58 @@ impl SourceFile {
|
||||
pub fn new(
|
||||
name: FileName,
|
||||
mut src: String,
|
||||
start_pos: BytePos,
|
||||
hash_kind: SourceFileHashAlgorithm,
|
||||
) -> Self {
|
||||
) -> Result<Self, OffsetOverflowError> {
|
||||
// Compute the file hash before any normalization.
|
||||
let src_hash = SourceFileHash::new(hash_kind, &src);
|
||||
let normalized_pos = normalize_src(&mut src, start_pos);
|
||||
let normalized_pos = normalize_src(&mut src);
|
||||
|
||||
let name_hash = {
|
||||
let mut hasher: StableHasher = StableHasher::new();
|
||||
name.hash(&mut hasher);
|
||||
hasher.finish()
|
||||
};
|
||||
let end_pos = start_pos.to_usize() + src.len();
|
||||
assert!(end_pos <= u32::MAX as usize);
|
||||
let source_len = src.len();
|
||||
let source_len = u32::try_from(source_len).map_err(|_| OffsetOverflowError)?;
|
||||
|
||||
let (lines, multibyte_chars, non_narrow_chars) =
|
||||
analyze_source_file::analyze_source_file(&src, start_pos);
|
||||
analyze_source_file::analyze_source_file(&src);
|
||||
|
||||
SourceFile {
|
||||
Ok(SourceFile {
|
||||
name,
|
||||
src: Some(Lrc::new(src)),
|
||||
src_hash,
|
||||
external_src: Lock::new(ExternalSource::Unneeded),
|
||||
start_pos,
|
||||
end_pos: Pos::from_usize(end_pos),
|
||||
start_pos: BytePos::from_u32(0),
|
||||
source_len: RelativeBytePos::from_u32(source_len),
|
||||
lines: Lock::new(SourceFileLines::Lines(lines)),
|
||||
multibyte_chars,
|
||||
non_narrow_chars,
|
||||
normalized_pos,
|
||||
name_hash,
|
||||
cnum: LOCAL_CRATE,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn lines<F, R>(&self, f: F) -> R
|
||||
where
|
||||
F: FnOnce(&[BytePos]) -> R,
|
||||
F: FnOnce(&[RelativeBytePos]) -> R,
|
||||
{
|
||||
let mut guard = self.lines.borrow_mut();
|
||||
match &*guard {
|
||||
SourceFileLines::Lines(lines) => f(lines),
|
||||
SourceFileLines::Diffs(SourceFileDiffs {
|
||||
mut line_start,
|
||||
bytes_per_diff,
|
||||
num_diffs,
|
||||
raw_diffs,
|
||||
}) => {
|
||||
SourceFileLines::Diffs(SourceFileDiffs { bytes_per_diff, num_diffs, raw_diffs }) => {
|
||||
// Convert from "diffs" form to "lines" form.
|
||||
let num_lines = num_diffs + 1;
|
||||
let mut lines = Vec::with_capacity(num_lines);
|
||||
let mut line_start = RelativeBytePos(0);
|
||||
lines.push(line_start);
|
||||
|
||||
assert_eq!(*num_diffs, raw_diffs.len() / bytes_per_diff);
|
||||
match bytes_per_diff {
|
||||
1 => {
|
||||
lines.extend(raw_diffs.into_iter().map(|&diff| {
|
||||
line_start = line_start + BytePos(diff as u32);
|
||||
line_start = line_start + RelativeBytePos(diff as u32);
|
||||
line_start
|
||||
}));
|
||||
}
|
||||
@ -1588,7 +1569,7 @@ impl SourceFile {
|
||||
let pos = bytes_per_diff * i;
|
||||
let bytes = [raw_diffs[pos], raw_diffs[pos + 1]];
|
||||
let diff = u16::from_le_bytes(bytes);
|
||||
line_start = line_start + BytePos(diff as u32);
|
||||
line_start = line_start + RelativeBytePos(diff as u32);
|
||||
line_start
|
||||
}));
|
||||
}
|
||||
@ -1602,7 +1583,7 @@ impl SourceFile {
|
||||
raw_diffs[pos + 3],
|
||||
];
|
||||
let diff = u32::from_le_bytes(bytes);
|
||||
line_start = line_start + BytePos(diff);
|
||||
line_start = line_start + RelativeBytePos(diff);
|
||||
line_start
|
||||
}));
|
||||
}
|
||||
@ -1617,8 +1598,10 @@ impl SourceFile {
|
||||
|
||||
/// Returns the `BytePos` of the beginning of the current line.
|
||||
pub fn line_begin_pos(&self, pos: BytePos) -> BytePos {
|
||||
let pos = self.relative_position(pos);
|
||||
let line_index = self.lookup_line(pos).unwrap();
|
||||
self.lines(|lines| lines[line_index])
|
||||
let line_start_pos = self.lines(|lines| lines[line_index]);
|
||||
self.absolute_position(line_start_pos)
|
||||
}
|
||||
|
||||
/// Add externally loaded source.
|
||||
@ -1643,7 +1626,7 @@ impl SourceFile {
|
||||
if let Some(mut src) = src {
|
||||
// The src_hash needs to be computed on the pre-normalized src.
|
||||
if self.src_hash.matches(&src) {
|
||||
normalize_src(&mut src, BytePos::from_usize(0));
|
||||
normalize_src(&mut src);
|
||||
*src_kind = ExternalSourceKind::Present(Lrc::new(src));
|
||||
return true;
|
||||
}
|
||||
@ -1676,8 +1659,7 @@ impl SourceFile {
|
||||
|
||||
let begin = {
|
||||
let line = self.lines(|lines| lines.get(line_number).copied())?;
|
||||
let begin: BytePos = line - self.start_pos;
|
||||
begin.to_usize()
|
||||
line.to_usize()
|
||||
};
|
||||
|
||||
if let Some(ref src) = self.src {
|
||||
@ -1703,25 +1685,41 @@ impl SourceFile {
|
||||
self.lines(|lines| lines.len())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn absolute_position(&self, pos: RelativeBytePos) -> BytePos {
|
||||
BytePos::from_u32(pos.to_u32() + self.start_pos.to_u32())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn relative_position(&self, pos: BytePos) -> RelativeBytePos {
|
||||
RelativeBytePos::from_u32(pos.to_u32() - self.start_pos.to_u32())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn end_position(&self) -> BytePos {
|
||||
self.absolute_position(self.source_len)
|
||||
}
|
||||
|
||||
/// Finds the line containing the given position. The return value is the
|
||||
/// index into the `lines` array of this `SourceFile`, not the 1-based line
|
||||
/// number. If the source_file is empty or the position is located before the
|
||||
/// first line, `None` is returned.
|
||||
pub fn lookup_line(&self, pos: BytePos) -> Option<usize> {
|
||||
pub fn lookup_line(&self, pos: RelativeBytePos) -> Option<usize> {
|
||||
self.lines(|lines| lines.partition_point(|x| x <= &pos).checked_sub(1))
|
||||
}
|
||||
|
||||
pub fn line_bounds(&self, line_index: usize) -> Range<BytePos> {
|
||||
if self.is_empty() {
|
||||
return self.start_pos..self.end_pos;
|
||||
return self.start_pos..self.start_pos;
|
||||
}
|
||||
|
||||
self.lines(|lines| {
|
||||
assert!(line_index < lines.len());
|
||||
if line_index == (lines.len() - 1) {
|
||||
lines[line_index]..self.end_pos
|
||||
self.absolute_position(lines[line_index])..self.end_position()
|
||||
} else {
|
||||
lines[line_index]..lines[line_index + 1]
|
||||
self.absolute_position(lines[line_index])
|
||||
..self.absolute_position(lines[line_index + 1])
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -1732,17 +1730,19 @@ impl SourceFile {
|
||||
/// returns true still contain one byte position according to this function.
|
||||
#[inline]
|
||||
pub fn contains(&self, byte_pos: BytePos) -> bool {
|
||||
byte_pos >= self.start_pos && byte_pos <= self.end_pos
|
||||
byte_pos >= self.start_pos && byte_pos <= self.end_position()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.start_pos == self.end_pos
|
||||
self.source_len.to_u32() == 0
|
||||
}
|
||||
|
||||
/// Calculates the original byte position relative to the start of the file
|
||||
/// based on the given byte position.
|
||||
pub fn original_relative_byte_pos(&self, pos: BytePos) -> BytePos {
|
||||
pub fn original_relative_byte_pos(&self, pos: BytePos) -> RelativeBytePos {
|
||||
let pos = self.relative_position(pos);
|
||||
|
||||
// Diff before any records is 0. Otherwise use the previously recorded
|
||||
// diff as that applies to the following characters until a new diff
|
||||
// is recorded.
|
||||
@ -1752,7 +1752,7 @@ impl SourceFile {
|
||||
Err(i) => self.normalized_pos[i - 1].diff,
|
||||
};
|
||||
|
||||
BytePos::from_u32(pos.0 - self.start_pos.0 + diff)
|
||||
RelativeBytePos::from_u32(pos.0 + diff)
|
||||
}
|
||||
|
||||
/// Calculates a normalized byte position from a byte offset relative to the
|
||||
@ -1777,8 +1777,8 @@ impl SourceFile {
|
||||
BytePos::from_u32(self.start_pos.0 + offset - diff)
|
||||
}
|
||||
|
||||
/// Converts an absolute `BytePos` to a `CharPos` relative to the `SourceFile`.
|
||||
pub fn bytepos_to_file_charpos(&self, bpos: BytePos) -> CharPos {
|
||||
/// Converts an relative `RelativeBytePos` to a `CharPos` relative to the `SourceFile`.
|
||||
fn bytepos_to_file_charpos(&self, bpos: RelativeBytePos) -> CharPos {
|
||||
// The number of extra bytes due to multibyte chars in the `SourceFile`.
|
||||
let mut total_extra_bytes = 0;
|
||||
|
||||
@ -1796,13 +1796,13 @@ impl SourceFile {
|
||||
}
|
||||
}
|
||||
|
||||
assert!(self.start_pos.to_u32() + total_extra_bytes <= bpos.to_u32());
|
||||
CharPos(bpos.to_usize() - self.start_pos.to_usize() - total_extra_bytes as usize)
|
||||
assert!(total_extra_bytes <= bpos.to_u32());
|
||||
CharPos(bpos.to_usize() - total_extra_bytes as usize)
|
||||
}
|
||||
|
||||
/// Looks up the file's (1-based) line number and (0-based `CharPos`) column offset, for a
|
||||
/// given `BytePos`.
|
||||
pub fn lookup_file_pos(&self, pos: BytePos) -> (usize, CharPos) {
|
||||
/// given `RelativeBytePos`.
|
||||
fn lookup_file_pos(&self, pos: RelativeBytePos) -> (usize, CharPos) {
|
||||
let chpos = self.bytepos_to_file_charpos(pos);
|
||||
match self.lookup_line(pos) {
|
||||
Some(a) => {
|
||||
@ -1823,6 +1823,7 @@ impl SourceFile {
|
||||
/// Looks up the file's (1-based) line number, (0-based `CharPos`) column offset, and (0-based)
|
||||
/// column offset when displayed, for a given `BytePos`.
|
||||
pub fn lookup_file_pos_with_col_display(&self, pos: BytePos) -> (usize, CharPos, usize) {
|
||||
let pos = self.relative_position(pos);
|
||||
let (line, col_or_chpos) = self.lookup_file_pos(pos);
|
||||
if line > 0 {
|
||||
let col = col_or_chpos;
|
||||
@ -1861,16 +1862,10 @@ impl SourceFile {
|
||||
}
|
||||
|
||||
/// Normalizes the source code and records the normalizations.
|
||||
fn normalize_src(src: &mut String, start_pos: BytePos) -> Vec<NormalizedPos> {
|
||||
fn normalize_src(src: &mut String) -> Vec<NormalizedPos> {
|
||||
let mut normalized_pos = vec![];
|
||||
remove_bom(src, &mut normalized_pos);
|
||||
normalize_newlines(src, &mut normalized_pos);
|
||||
|
||||
// Offset all the positions by start_pos to match the final file positions.
|
||||
for np in &mut normalized_pos {
|
||||
np.pos.0 += start_pos.0;
|
||||
}
|
||||
|
||||
normalized_pos
|
||||
}
|
||||
|
||||
@ -1878,7 +1873,7 @@ fn normalize_src(src: &mut String, start_pos: BytePos) -> Vec<NormalizedPos> {
|
||||
fn remove_bom(src: &mut String, normalized_pos: &mut Vec<NormalizedPos>) {
|
||||
if src.starts_with('\u{feff}') {
|
||||
src.drain(..3);
|
||||
normalized_pos.push(NormalizedPos { pos: BytePos(0), diff: 3 });
|
||||
normalized_pos.push(NormalizedPos { pos: RelativeBytePos(0), diff: 3 });
|
||||
}
|
||||
}
|
||||
|
||||
@ -1913,7 +1908,7 @@ fn normalize_newlines(src: &mut String, normalized_pos: &mut Vec<NormalizedPos>)
|
||||
cursor += idx - gap_len;
|
||||
gap_len += 1;
|
||||
normalized_pos.push(NormalizedPos {
|
||||
pos: BytePos::from_usize(cursor + 1),
|
||||
pos: RelativeBytePos::from_usize(cursor + 1),
|
||||
diff: original_gap + gap_len as u32,
|
||||
});
|
||||
}
|
||||
@ -2015,6 +2010,10 @@ impl_pos! {
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
|
||||
pub struct BytePos(pub u32);
|
||||
|
||||
/// A byte offset relative to file beginning.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
|
||||
pub struct RelativeBytePos(pub u32);
|
||||
|
||||
/// A character offset.
|
||||
///
|
||||
/// Because of multibyte UTF-8 characters, a byte offset
|
||||
@ -2036,6 +2035,24 @@ impl<D: Decoder> Decodable<D> for BytePos {
|
||||
}
|
||||
}
|
||||
|
||||
impl<H: HashStableContext> HashStable<H> for RelativeBytePos {
|
||||
fn hash_stable(&self, hcx: &mut H, hasher: &mut StableHasher) {
|
||||
self.0.hash_stable(hcx, hasher);
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Encoder> Encodable<S> for RelativeBytePos {
|
||||
fn encode(&self, s: &mut S) {
|
||||
s.emit_u32(self.0);
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Decoder> Decodable<D> for RelativeBytePos {
|
||||
fn decode(d: &mut D) -> RelativeBytePos {
|
||||
RelativeBytePos(d.read_u32())
|
||||
}
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
// Loc, SourceFileAndLine, SourceFileAndBytePos
|
||||
//
|
||||
|
@ -14,13 +14,10 @@ pub use crate::*;
|
||||
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::stable_hasher::{Hash128, Hash64, StableHasher};
|
||||
use rustc_data_structures::sync::{
|
||||
AtomicU32, IntoDynSyncSend, Lrc, MappedReadGuard, ReadGuard, RwLock,
|
||||
};
|
||||
use rustc_data_structures::sync::{IntoDynSyncSend, Lrc, MappedReadGuard, ReadGuard, RwLock};
|
||||
use std::cmp;
|
||||
use std::hash::Hash;
|
||||
use std::path::{self, Path, PathBuf};
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
use std::fs;
|
||||
use std::io;
|
||||
@ -187,9 +184,6 @@ pub(super) struct SourceMapFiles {
|
||||
}
|
||||
|
||||
pub struct SourceMap {
|
||||
/// The address space below this value is currently used by the files in the source map.
|
||||
used_address_space: AtomicU32,
|
||||
|
||||
files: RwLock<SourceMapFiles>,
|
||||
file_loader: IntoDynSyncSend<Box<dyn FileLoader + Sync + Send>>,
|
||||
// This is used to apply the file path remapping as specified via
|
||||
@ -215,7 +209,6 @@ impl SourceMap {
|
||||
hash_kind: SourceFileHashAlgorithm,
|
||||
) -> SourceMap {
|
||||
SourceMap {
|
||||
used_address_space: AtomicU32::new(0),
|
||||
files: Default::default(),
|
||||
file_loader: IntoDynSyncSend(file_loader),
|
||||
path_mapping,
|
||||
@ -267,26 +260,26 @@ impl SourceMap {
|
||||
self.files.borrow().stable_id_to_source_file.get(&stable_id).cloned()
|
||||
}
|
||||
|
||||
fn allocate_address_space(&self, size: usize) -> Result<usize, OffsetOverflowError> {
|
||||
let size = u32::try_from(size).map_err(|_| OffsetOverflowError)?;
|
||||
fn register_source_file(
|
||||
&self,
|
||||
file_id: StableSourceFileId,
|
||||
mut file: SourceFile,
|
||||
) -> Result<Lrc<SourceFile>, OffsetOverflowError> {
|
||||
let mut files = self.files.borrow_mut();
|
||||
|
||||
loop {
|
||||
let current = self.used_address_space.load(Ordering::Relaxed);
|
||||
let next = current
|
||||
.checked_add(size)
|
||||
// Add one so there is some space between files. This lets us distinguish
|
||||
// positions in the `SourceMap`, even in the presence of zero-length files.
|
||||
.and_then(|next| next.checked_add(1))
|
||||
.ok_or(OffsetOverflowError)?;
|
||||
file.start_pos = BytePos(if let Some(last_file) = files.source_files.last() {
|
||||
// Add one so there is some space between files. This lets us distinguish
|
||||
// positions in the `SourceMap`, even in the presence of zero-length files.
|
||||
last_file.end_position().0.checked_add(1).ok_or(OffsetOverflowError)?
|
||||
} else {
|
||||
0
|
||||
});
|
||||
|
||||
if self
|
||||
.used_address_space
|
||||
.compare_exchange(current, next, Ordering::Relaxed, Ordering::Relaxed)
|
||||
.is_ok()
|
||||
{
|
||||
return Ok(usize::try_from(current).unwrap());
|
||||
}
|
||||
}
|
||||
let file = Lrc::new(file);
|
||||
files.source_files.push(file.clone());
|
||||
files.stable_id_to_source_file.insert(file_id, file.clone());
|
||||
|
||||
Ok(file)
|
||||
}
|
||||
|
||||
/// Creates a new `SourceFile`.
|
||||
@ -310,32 +303,18 @@ impl SourceMap {
|
||||
let (filename, _) = self.path_mapping.map_filename_prefix(&filename);
|
||||
|
||||
let file_id = StableSourceFileId::new_from_name(&filename, LOCAL_CRATE);
|
||||
|
||||
let lrc_sf = match self.source_file_by_stable_id(file_id) {
|
||||
Some(lrc_sf) => lrc_sf,
|
||||
match self.source_file_by_stable_id(file_id) {
|
||||
Some(lrc_sf) => Ok(lrc_sf),
|
||||
None => {
|
||||
let start_pos = self.allocate_address_space(src.len())?;
|
||||
|
||||
let source_file = Lrc::new(SourceFile::new(
|
||||
filename,
|
||||
src,
|
||||
Pos::from_usize(start_pos),
|
||||
self.hash_kind,
|
||||
));
|
||||
let source_file = SourceFile::new(filename, src, self.hash_kind)?;
|
||||
|
||||
// Let's make sure the file_id we generated above actually matches
|
||||
// the ID we generate for the SourceFile we just created.
|
||||
debug_assert_eq!(StableSourceFileId::new(&source_file), file_id);
|
||||
|
||||
let mut files = self.files.borrow_mut();
|
||||
|
||||
files.source_files.push(source_file.clone());
|
||||
files.stable_id_to_source_file.insert(file_id, source_file.clone());
|
||||
|
||||
source_file
|
||||
self.register_source_file(file_id, source_file)
|
||||
}
|
||||
};
|
||||
Ok(lrc_sf)
|
||||
}
|
||||
}
|
||||
|
||||
/// Allocates a new `SourceFile` representing a source file from an external
|
||||
@ -347,53 +326,17 @@ impl SourceMap {
|
||||
filename: FileName,
|
||||
src_hash: SourceFileHash,
|
||||
name_hash: Hash128,
|
||||
source_len: usize,
|
||||
source_len: u32,
|
||||
cnum: CrateNum,
|
||||
file_local_lines: Lock<SourceFileLines>,
|
||||
mut file_local_multibyte_chars: Vec<MultiByteChar>,
|
||||
mut file_local_non_narrow_chars: Vec<NonNarrowChar>,
|
||||
mut file_local_normalized_pos: Vec<NormalizedPos>,
|
||||
original_start_pos: BytePos,
|
||||
multibyte_chars: Vec<MultiByteChar>,
|
||||
non_narrow_chars: Vec<NonNarrowChar>,
|
||||
normalized_pos: Vec<NormalizedPos>,
|
||||
metadata_index: u32,
|
||||
) -> Lrc<SourceFile> {
|
||||
let start_pos = self
|
||||
.allocate_address_space(source_len)
|
||||
.expect("not enough address space for imported source file");
|
||||
let source_len = RelativeBytePos::from_u32(source_len);
|
||||
|
||||
let end_pos = Pos::from_usize(start_pos + source_len);
|
||||
let start_pos = Pos::from_usize(start_pos);
|
||||
|
||||
// Translate these positions into the new global frame of reference,
|
||||
// now that the offset of the SourceFile is known.
|
||||
//
|
||||
// These are all unsigned values. `original_start_pos` may be larger or
|
||||
// smaller than `start_pos`, but `pos` is always larger than both.
|
||||
// Therefore, `(pos - original_start_pos) + start_pos` won't overflow
|
||||
// but `start_pos - original_start_pos` might. So we use the former
|
||||
// form rather than pre-computing the offset into a local variable. The
|
||||
// compiler backend can optimize away the repeated computations in a
|
||||
// way that won't trigger overflow checks.
|
||||
match &mut *file_local_lines.borrow_mut() {
|
||||
SourceFileLines::Lines(lines) => {
|
||||
for pos in lines {
|
||||
*pos = (*pos - original_start_pos) + start_pos;
|
||||
}
|
||||
}
|
||||
SourceFileLines::Diffs(SourceFileDiffs { line_start, .. }) => {
|
||||
*line_start = (*line_start - original_start_pos) + start_pos;
|
||||
}
|
||||
}
|
||||
for mbc in &mut file_local_multibyte_chars {
|
||||
mbc.pos = (mbc.pos - original_start_pos) + start_pos;
|
||||
}
|
||||
for swc in &mut file_local_non_narrow_chars {
|
||||
*swc = (*swc - original_start_pos) + start_pos;
|
||||
}
|
||||
for nc in &mut file_local_normalized_pos {
|
||||
nc.pos = (nc.pos - original_start_pos) + start_pos;
|
||||
}
|
||||
|
||||
let source_file = Lrc::new(SourceFile {
|
||||
let source_file = SourceFile {
|
||||
name: filename,
|
||||
src: None,
|
||||
src_hash,
|
||||
@ -401,24 +344,19 @@ impl SourceMap {
|
||||
kind: ExternalSourceKind::AbsentOk,
|
||||
metadata_index,
|
||||
}),
|
||||
start_pos,
|
||||
end_pos,
|
||||
start_pos: BytePos(0),
|
||||
source_len,
|
||||
lines: file_local_lines,
|
||||
multibyte_chars: file_local_multibyte_chars,
|
||||
non_narrow_chars: file_local_non_narrow_chars,
|
||||
normalized_pos: file_local_normalized_pos,
|
||||
multibyte_chars,
|
||||
non_narrow_chars,
|
||||
normalized_pos,
|
||||
name_hash,
|
||||
cnum,
|
||||
});
|
||||
};
|
||||
|
||||
let mut files = self.files.borrow_mut();
|
||||
|
||||
files.source_files.push(source_file.clone());
|
||||
files
|
||||
.stable_id_to_source_file
|
||||
.insert(StableSourceFileId::new(&source_file), source_file.clone());
|
||||
|
||||
source_file
|
||||
let file_id = StableSourceFileId::new(&source_file);
|
||||
self.register_source_file(file_id, source_file)
|
||||
.expect("not enough address space for imported source file")
|
||||
}
|
||||
|
||||
/// If there is a doctest offset, applies it to the line.
|
||||
@ -452,6 +390,7 @@ impl SourceMap {
|
||||
pub fn lookup_line(&self, pos: BytePos) -> Result<SourceFileAndLine, Lrc<SourceFile>> {
|
||||
let f = self.lookup_source_file(pos);
|
||||
|
||||
let pos = f.relative_position(pos);
|
||||
match f.lookup_line(pos) {
|
||||
Some(line) => Ok(SourceFileAndLine { sf: f, line }),
|
||||
None => Err(f),
|
||||
@ -547,7 +486,9 @@ impl SourceMap {
|
||||
return true;
|
||||
}
|
||||
let f = (*self.files.borrow().source_files)[lo].clone();
|
||||
f.lookup_line(sp.lo()) != f.lookup_line(sp.hi())
|
||||
let lo = f.relative_position(sp.lo());
|
||||
let hi = f.relative_position(sp.hi());
|
||||
f.lookup_line(lo) != f.lookup_line(hi)
|
||||
}
|
||||
|
||||
#[instrument(skip(self), level = "trace")]
|
||||
@ -627,7 +568,7 @@ impl SourceMap {
|
||||
|
||||
let start_index = local_begin.pos.to_usize();
|
||||
let end_index = local_end.pos.to_usize();
|
||||
let source_len = (local_begin.sf.end_pos - local_begin.sf.start_pos).to_usize();
|
||||
let source_len = local_begin.sf.source_len.to_usize();
|
||||
|
||||
if start_index > end_index || end_index > source_len {
|
||||
return Err(SpanSnippetError::MalformedForSourcemap(MalformedSourceMapPositions {
|
||||
@ -1034,7 +975,7 @@ impl SourceMap {
|
||||
return 1;
|
||||
}
|
||||
|
||||
let source_len = (local_begin.sf.end_pos - local_begin.sf.start_pos).to_usize();
|
||||
let source_len = local_begin.sf.source_len.to_usize();
|
||||
debug!("source_len=`{:?}`", source_len);
|
||||
// Ensure indexes are also not malformed.
|
||||
if start_index > end_index || end_index > source_len - 1 {
|
||||
|
@ -50,6 +50,7 @@ impl SourceMap {
|
||||
fn bytepos_to_file_charpos(&self, bpos: BytePos) -> CharPos {
|
||||
let idx = self.lookup_source_file_idx(bpos);
|
||||
let sf = &(*self.files.borrow().source_files)[idx];
|
||||
let bpos = sf.relative_position(bpos);
|
||||
sf.bytepos_to_file_charpos(bpos)
|
||||
}
|
||||
}
|
||||
@ -230,8 +231,7 @@ fn t10() {
|
||||
let SourceFile {
|
||||
name,
|
||||
src_hash,
|
||||
start_pos,
|
||||
end_pos,
|
||||
source_len,
|
||||
lines,
|
||||
multibyte_chars,
|
||||
non_narrow_chars,
|
||||
@ -244,13 +244,12 @@ fn t10() {
|
||||
name,
|
||||
src_hash,
|
||||
name_hash,
|
||||
(end_pos - start_pos).to_usize(),
|
||||
source_len.to_u32(),
|
||||
CrateNum::new(0),
|
||||
lines,
|
||||
multibyte_chars,
|
||||
non_narrow_chars,
|
||||
normalized_pos,
|
||||
start_pos,
|
||||
0,
|
||||
);
|
||||
|
||||
|
@ -3,24 +3,23 @@ use super::*;
|
||||
#[test]
|
||||
fn test_lookup_line() {
|
||||
let source = "abcdefghijklm\nabcdefghij\n...".to_owned();
|
||||
let sf = SourceFile::new(
|
||||
FileName::Anon(Hash64::ZERO),
|
||||
source,
|
||||
BytePos(3),
|
||||
SourceFileHashAlgorithm::Sha256,
|
||||
);
|
||||
sf.lines(|lines| assert_eq!(lines, &[BytePos(3), BytePos(17), BytePos(28)]));
|
||||
let mut sf =
|
||||
SourceFile::new(FileName::Anon(Hash64::ZERO), source, SourceFileHashAlgorithm::Sha256)
|
||||
.unwrap();
|
||||
sf.start_pos = BytePos(3);
|
||||
sf.lines(|lines| {
|
||||
assert_eq!(lines, &[RelativeBytePos(0), RelativeBytePos(14), RelativeBytePos(25)])
|
||||
});
|
||||
|
||||
assert_eq!(sf.lookup_line(BytePos(0)), None);
|
||||
assert_eq!(sf.lookup_line(BytePos(3)), Some(0));
|
||||
assert_eq!(sf.lookup_line(BytePos(4)), Some(0));
|
||||
assert_eq!(sf.lookup_line(RelativeBytePos(0)), Some(0));
|
||||
assert_eq!(sf.lookup_line(RelativeBytePos(1)), Some(0));
|
||||
|
||||
assert_eq!(sf.lookup_line(BytePos(16)), Some(0));
|
||||
assert_eq!(sf.lookup_line(BytePos(17)), Some(1));
|
||||
assert_eq!(sf.lookup_line(BytePos(18)), Some(1));
|
||||
assert_eq!(sf.lookup_line(RelativeBytePos(13)), Some(0));
|
||||
assert_eq!(sf.lookup_line(RelativeBytePos(14)), Some(1));
|
||||
assert_eq!(sf.lookup_line(RelativeBytePos(15)), Some(1));
|
||||
|
||||
assert_eq!(sf.lookup_line(BytePos(28)), Some(2));
|
||||
assert_eq!(sf.lookup_line(BytePos(29)), Some(2));
|
||||
assert_eq!(sf.lookup_line(RelativeBytePos(25)), Some(2));
|
||||
assert_eq!(sf.lookup_line(RelativeBytePos(26)), Some(2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -134,7 +134,7 @@ impl DocVisitor for SourceCollector<'_, '_> {
|
||||
let filename = span.filename(sess);
|
||||
let span = span.inner();
|
||||
let pos = sess.source_map().lookup_source_file(span.lo());
|
||||
let file_span = span.with_lo(pos.start_pos).with_hi(pos.end_pos);
|
||||
let file_span = span.with_lo(pos.start_pos).with_hi(pos.end_position());
|
||||
// If it turns out that we couldn't read this file, then we probably
|
||||
// can't read any of the files (generating html output from json or
|
||||
// something like that), so just don't include sources for the
|
||||
|
@ -73,7 +73,7 @@ pub(crate) struct SyntaxRange {
|
||||
impl SyntaxRange {
|
||||
fn new(span: rustc_span::Span, file: &SourceFile) -> Option<Self> {
|
||||
let get_pos = |bytepos: BytePos| file.original_relative_byte_pos(bytepos).0;
|
||||
let get_line = |bytepos: BytePos| file.lookup_line(bytepos);
|
||||
let get_line = |bytepos: BytePos| file.lookup_line(file.relative_position(bytepos));
|
||||
|
||||
Some(SyntaxRange {
|
||||
byte_span: (get_pos(span.lo()), get_pos(span.hi())),
|
||||
|
@ -12,7 +12,7 @@ use rustc_lexer::{tokenize, TokenKind};
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||
use rustc_span::{BytePos, Pos, Span, SyntaxContext};
|
||||
use rustc_span::{BytePos, Pos, RelativeBytePos, Span, SyntaxContext};
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
@ -514,7 +514,7 @@ fn item_has_safety_comment(cx: &LateContext<'_>, item: &hir::Item<'_>) -> HasSaf
|
||||
match text_has_safety_comment(
|
||||
src,
|
||||
&lines[comment_start_line.line + 1..=unsafe_line.line],
|
||||
unsafe_line.sf.start_pos.to_usize(),
|
||||
unsafe_line.sf.start_pos,
|
||||
) {
|
||||
Some(b) => HasSafetyComment::Yes(b),
|
||||
None => HasSafetyComment::No,
|
||||
@ -558,7 +558,7 @@ fn stmt_has_safety_comment(cx: &LateContext<'_>, span: Span, hir_id: HirId) -> H
|
||||
match text_has_safety_comment(
|
||||
src,
|
||||
&lines[comment_start_line.line + 1..=unsafe_line.line],
|
||||
unsafe_line.sf.start_pos.to_usize(),
|
||||
unsafe_line.sf.start_pos,
|
||||
) {
|
||||
Some(b) => HasSafetyComment::Yes(b),
|
||||
None => HasSafetyComment::No,
|
||||
@ -619,7 +619,7 @@ fn span_from_macro_expansion_has_safety_comment(cx: &LateContext<'_>, span: Span
|
||||
match text_has_safety_comment(
|
||||
src,
|
||||
&lines[macro_line.line + 1..=unsafe_line.line],
|
||||
unsafe_line.sf.start_pos.to_usize(),
|
||||
unsafe_line.sf.start_pos,
|
||||
) {
|
||||
Some(b) => HasSafetyComment::Yes(b),
|
||||
None => HasSafetyComment::No,
|
||||
@ -675,7 +675,7 @@ fn span_in_body_has_safety_comment(cx: &LateContext<'_>, span: Span) -> bool {
|
||||
body_line.line < unsafe_line.line && text_has_safety_comment(
|
||||
src,
|
||||
&lines[body_line.line + 1..=unsafe_line.line],
|
||||
unsafe_line.sf.start_pos.to_usize(),
|
||||
unsafe_line.sf.start_pos,
|
||||
).is_some()
|
||||
})
|
||||
} else {
|
||||
@ -688,13 +688,13 @@ fn span_in_body_has_safety_comment(cx: &LateContext<'_>, span: Span) -> bool {
|
||||
}
|
||||
|
||||
/// Checks if the given text has a safety comment for the immediately proceeding line.
|
||||
fn text_has_safety_comment(src: &str, line_starts: &[BytePos], offset: usize) -> Option<BytePos> {
|
||||
fn text_has_safety_comment(src: &str, line_starts: &[RelativeBytePos], start_pos: BytePos) -> Option<BytePos> {
|
||||
let mut lines = line_starts
|
||||
.array_windows::<2>()
|
||||
.rev()
|
||||
.map_while(|[start, end]| {
|
||||
let start = start.to_usize() - offset;
|
||||
let end = end.to_usize() - offset;
|
||||
let start = start.to_usize();
|
||||
let end = end.to_usize();
|
||||
let text = src.get(start..end)?;
|
||||
let trimmed = text.trim_start();
|
||||
Some((start + (text.len() - trimmed.len()), trimmed))
|
||||
@ -709,9 +709,7 @@ fn text_has_safety_comment(src: &str, line_starts: &[BytePos], offset: usize) ->
|
||||
let (mut line, mut line_start) = (line, line_start);
|
||||
loop {
|
||||
if line.to_ascii_uppercase().contains("SAFETY:") {
|
||||
return Some(BytePos(
|
||||
u32::try_from(line_start).unwrap() + u32::try_from(offset).unwrap(),
|
||||
));
|
||||
return Some(start_pos + BytePos(u32::try_from(line_start).unwrap()));
|
||||
}
|
||||
match lines.next() {
|
||||
Some((s, x)) if x.starts_with("//") => (line, line_start) = (x, s),
|
||||
@ -724,15 +722,13 @@ fn text_has_safety_comment(src: &str, line_starts: &[BytePos], offset: usize) ->
|
||||
let (mut line_start, mut line) = (line_start, line);
|
||||
loop {
|
||||
if line.starts_with("/*") {
|
||||
let src = &src[line_start..line_starts.last().unwrap().to_usize() - offset];
|
||||
let src = &src[line_start..line_starts.last().unwrap().to_usize()];
|
||||
let mut tokens = tokenize(src);
|
||||
return (src[..tokens.next().unwrap().len as usize]
|
||||
.to_ascii_uppercase()
|
||||
.contains("SAFETY:")
|
||||
&& tokens.all(|t| t.kind == TokenKind::Whitespace))
|
||||
.then_some(BytePos(
|
||||
u32::try_from(line_start).unwrap() + u32::try_from(offset).unwrap(),
|
||||
));
|
||||
.then_some(start_pos + BytePos(u32::try_from(line_start).unwrap()));
|
||||
}
|
||||
match lines.next() {
|
||||
Some(x) => (line_start, line) = x,
|
||||
|
@ -8,7 +8,7 @@ use rustc_hir::{BlockCheckMode, Expr, ExprKind, UnsafeSource};
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::source_map::{original_sp, SourceMap};
|
||||
use rustc_span::{hygiene, BytePos, Pos, SourceFile, Span, SpanData, SyntaxContext, DUMMY_SP};
|
||||
use rustc_span::{hygiene, BytePos, SourceFileAndLine, Pos, SourceFile, Span, SpanData, SyntaxContext, DUMMY_SP};
|
||||
use std::borrow::Cow;
|
||||
use std::ops::Range;
|
||||
|
||||
@ -117,9 +117,9 @@ fn first_char_in_first_line<T: LintContext>(cx: &T, span: Span) -> Option<BytePo
|
||||
/// ```
|
||||
fn line_span<T: LintContext>(cx: &T, span: Span) -> Span {
|
||||
let span = original_sp(span, DUMMY_SP);
|
||||
let source_map_and_line = cx.sess().source_map().lookup_line(span.lo()).unwrap();
|
||||
let line_no = source_map_and_line.line;
|
||||
let line_start = source_map_and_line.sf.lines(|lines| lines[line_no]);
|
||||
let SourceFileAndLine { sf, line } = cx.sess().source_map().lookup_line(span.lo()).unwrap();
|
||||
let line_start = sf.lines(|lines| lines[line]);
|
||||
let line_start = sf.absolute_position(line_start);
|
||||
span.with_lo(line_start)
|
||||
}
|
||||
|
||||
|
@ -268,7 +268,7 @@ impl ParseSess {
|
||||
let source_file = self.parse_sess.source_map().lookup_char_pos(span.lo()).file;
|
||||
SnippetProvider::new(
|
||||
source_file.start_pos,
|
||||
source_file.end_pos,
|
||||
source_file.end_position(),
|
||||
Lrc::clone(source_file.src.as_ref().unwrap()),
|
||||
)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user