1
Fork 0

Encode spans relative to their parent.

This commit is contained in:
Camille GILLOT 2021-04-18 14:27:28 +02:00
parent 00485e0c0e
commit e85ddeb474
5 changed files with 76 additions and 16 deletions

View file

@ -165,6 +165,8 @@ struct LoweringContext<'a, 'hir: 'a> {
pub trait ResolverAstLowering { pub trait ResolverAstLowering {
fn def_key(&mut self, id: DefId) -> DefKey; fn def_key(&mut self, id: DefId) -> DefKey;
fn def_span(&self, id: LocalDefId) -> Span;
fn item_generics_num_lifetimes(&self, def: DefId) -> usize; fn item_generics_num_lifetimes(&self, def: DefId) -> usize;
fn legacy_const_generic_args(&mut self, expr: &Expr) -> Option<Vec<usize>>; fn legacy_const_generic_args(&mut self, expr: &Expr) -> Option<Vec<usize>>;
@ -215,6 +217,11 @@ impl<'a> rustc_span::HashStableContext for LoweringHasher<'a> {
true true
} }
#[inline]
fn def_span(&self, id: LocalDefId) -> Span {
self.resolver.def_span(id)
}
#[inline] #[inline]
fn def_path_hash(&self, def_id: DefId) -> DefPathHash { fn def_path_hash(&self, def_id: DefId) -> DefPathHash {
self.resolver.def_path_hash(def_id) self.resolver.def_path_hash(def_id)

View file

@ -12,7 +12,7 @@ use rustc_hir::definitions::{DefPathHash, Definitions};
use rustc_session::Session; use rustc_session::Session;
use rustc_span::source_map::SourceMap; use rustc_span::source_map::SourceMap;
use rustc_span::symbol::Symbol; use rustc_span::symbol::Symbol;
use rustc_span::{BytePos, CachingSourceMapView, SourceFile, SpanData}; use rustc_span::{BytePos, CachingSourceMapView, SourceFile, Span, SpanData};
use smallvec::SmallVec; use smallvec::SmallVec;
use std::cmp::Ord; use std::cmp::Ord;
@ -229,6 +229,11 @@ impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> {
self.def_path_hash(def_id) self.def_path_hash(def_id)
} }
#[inline]
fn def_span(&self, def_id: LocalDefId) -> Span {
self.definitions.def_span(def_id)
}
fn span_data_to_lines_and_cols( fn span_data_to_lines_and_cols(
&mut self, &mut self,
span: &SpanData, span: &SpanData,

View file

@ -23,7 +23,7 @@ use rustc_span::hygiene::{
}; };
use rustc_span::source_map::{SourceMap, StableSourceFileId}; use rustc_span::source_map::{SourceMap, StableSourceFileId};
use rustc_span::CachingSourceMapView; use rustc_span::CachingSourceMapView;
use rustc_span::{BytePos, ExpnData, ExpnHash, SourceFile, Span, DUMMY_SP}; use rustc_span::{BytePos, ExpnData, ExpnHash, Pos, SourceFile, Span};
use std::collections::hash_map::Entry; use std::collections::hash_map::Entry;
use std::mem; use std::mem;
@ -33,6 +33,7 @@ const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE;
const TAG_FULL_SPAN: u8 = 0; const TAG_FULL_SPAN: u8 = 0;
// A partial span with no location information, encoded only with a `SyntaxContext` // A partial span with no location information, encoded only with a `SyntaxContext`
const TAG_PARTIAL_SPAN: u8 = 1; const TAG_PARTIAL_SPAN: u8 = 1;
const TAG_RELATIVE_SPAN: u8 = 2;
const TAG_SYNTAX_CONTEXT: u8 = 0; const TAG_SYNTAX_CONTEXT: u8 = 0;
const TAG_EXPN_DATA: u8 = 1; const TAG_EXPN_DATA: u8 = 1;
@ -829,11 +830,25 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for ExpnId {
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Span { impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Span {
fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> { fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
let ctxt = SyntaxContext::decode(decoder)?;
let parent = Option::<LocalDefId>::decode(decoder)?;
let tag: u8 = Decodable::decode(decoder)?; let tag: u8 = Decodable::decode(decoder)?;
if tag == TAG_PARTIAL_SPAN { if tag == TAG_PARTIAL_SPAN {
let ctxt = SyntaxContext::decode(decoder)?; return Ok(Span::new(BytePos(0), BytePos(0), ctxt, parent));
return Ok(DUMMY_SP.with_ctxt(ctxt)); } else if tag == TAG_RELATIVE_SPAN {
let dlo = u32::decode(decoder)?;
let dto = u32::decode(decoder)?;
let enclosing = decoder.tcx.definitions_untracked().def_span(parent.unwrap()).data();
let span = Span::new(
enclosing.lo + BytePos::from_u32(dlo),
enclosing.lo + BytePos::from_u32(dto),
ctxt,
parent,
);
return Ok(span);
} else { } else {
debug_assert_eq!(tag, TAG_FULL_SPAN); debug_assert_eq!(tag, TAG_FULL_SPAN);
} }
@ -842,13 +857,12 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Span {
let line_lo = usize::decode(decoder)?; let line_lo = usize::decode(decoder)?;
let col_lo = BytePos::decode(decoder)?; let col_lo = BytePos::decode(decoder)?;
let len = BytePos::decode(decoder)?; let len = BytePos::decode(decoder)?;
let ctxt = SyntaxContext::decode(decoder)?;
let file_lo = decoder.file_index_to_file(file_lo_index); let file_lo = decoder.file_index_to_file(file_lo_index);
let lo = file_lo.lines[line_lo - 1] + col_lo; let lo = file_lo.lines[line_lo - 1] + col_lo;
let hi = lo + len; let hi = lo + len;
Ok(Span::new(lo, hi, ctxt, None)) Ok(Span::new(lo, hi, ctxt, parent))
} }
} }
@ -1009,9 +1023,21 @@ where
{ {
fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> { fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
let span_data = self.data(); let span_data = self.data();
if self.is_dummy() { span_data.ctxt.encode(s)?;
TAG_PARTIAL_SPAN.encode(s)?; span_data.parent.encode(s)?;
return span_data.ctxt.encode(s);
if span_data.is_dummy() {
return TAG_PARTIAL_SPAN.encode(s);
}
if let Some(parent) = span_data.parent {
let enclosing = s.tcx.definitions_untracked().def_span(parent).data();
if enclosing.contains(span_data) {
TAG_RELATIVE_SPAN.encode(s)?;
(span_data.lo - enclosing.lo).to_u32().encode(s)?;
(span_data.hi - enclosing.lo).to_u32().encode(s)?;
return Ok(());
}
} }
let pos = s.source_map.byte_pos_to_line_and_col(span_data.lo); let pos = s.source_map.byte_pos_to_line_and_col(span_data.lo);
@ -1021,8 +1047,7 @@ where
}; };
if partial_span { if partial_span {
TAG_PARTIAL_SPAN.encode(s)?; return TAG_PARTIAL_SPAN.encode(s);
return span_data.ctxt.encode(s);
} }
let (file_lo, line_lo, col_lo) = pos.unwrap(); let (file_lo, line_lo, col_lo) = pos.unwrap();
@ -1035,8 +1060,7 @@ where
source_file_index.encode(s)?; source_file_index.encode(s)?;
line_lo.encode(s)?; line_lo.encode(s)?;
col_lo.encode(s)?; col_lo.encode(s)?;
len.encode(s)?; len.encode(s)
span_data.ctxt.encode(s)
} }
} }

View file

@ -1114,6 +1114,11 @@ impl ResolverAstLowering for Resolver<'_> {
} }
} }
#[inline]
fn def_span(&self, id: LocalDefId) -> Span {
self.definitions.def_span(id)
}
fn item_generics_num_lifetimes(&self, def_id: DefId) -> usize { fn item_generics_num_lifetimes(&self, def_id: DefId) -> usize {
if let Some(def_id) = def_id.as_local() { if let Some(def_id) = def_id.as_local() {
self.item_generics_num_lifetimes[&def_id] self.item_generics_num_lifetimes[&def_id]
@ -1221,6 +1226,11 @@ impl<'a, 'b> rustc_span::HashStableContext for ExpandHasher<'a, 'b> {
true true
} }
#[inline]
fn def_span(&self, id: LocalDefId) -> Span {
self.resolver.def_span(id)
}
#[inline] #[inline]
fn def_path_hash(&self, def_id: DefId) -> DefPathHash { fn def_path_hash(&self, def_id: DefId) -> DefPathHash {
self.resolver.def_path_hash(def_id) self.resolver.def_path_hash(def_id)

View file

@ -2001,6 +2001,7 @@ impl InnerSpan {
pub trait HashStableContext { pub trait HashStableContext {
fn def_path_hash(&self, def_id: DefId) -> DefPathHash; fn def_path_hash(&self, def_id: DefId) -> DefPathHash;
fn hash_spans(&self) -> bool; fn hash_spans(&self) -> bool;
fn def_span(&self, def_id: LocalDefId) -> Span;
fn span_data_to_lines_and_cols( fn span_data_to_lines_and_cols(
&mut self, &mut self,
span: &SpanData, span: &SpanData,
@ -2024,22 +2025,35 @@ where
fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
const TAG_VALID_SPAN: u8 = 0; const TAG_VALID_SPAN: u8 = 0;
const TAG_INVALID_SPAN: u8 = 1; const TAG_INVALID_SPAN: u8 = 1;
const TAG_RELATIVE_SPAN: u8 = 2;
if !ctx.hash_spans() { if !ctx.hash_spans() {
return; return;
} }
self.ctxt().hash_stable(ctx, hasher); let span = self.data();
span.ctxt.hash_stable(ctx, hasher);
span.parent.hash_stable(ctx, hasher);
if self.is_dummy() { if span.is_dummy() {
Hash::hash(&TAG_INVALID_SPAN, hasher); Hash::hash(&TAG_INVALID_SPAN, hasher);
return; return;
} }
if let Some(parent) = span.parent {
let def_span = ctx.def_span(parent).data();
if def_span.contains(span) {
// This span is enclosed in a definition: only hash the relative position.
Hash::hash(&TAG_RELATIVE_SPAN, hasher);
(span.lo - def_span.lo).to_u32().hash_stable(ctx, hasher);
(span.hi - def_span.lo).to_u32().hash_stable(ctx, hasher);
return;
}
}
// If this is not an empty or invalid span, we want to hash the last // If this is not an empty or invalid span, we want to hash the last
// position that belongs to it, as opposed to hashing the first // position that belongs to it, as opposed to hashing the first
// position past it. // position past it.
let span = self.data();
let (file, line_lo, col_lo, line_hi, col_hi) = match ctx.span_data_to_lines_and_cols(&span) let (file, line_lo, col_lo, line_hi, col_hi) = match ctx.span_data_to_lines_and_cols(&span)
{ {
Some(pos) => pos, Some(pos) => pos,