Skip to content

Commit 6805b01

Browse files
committed
Auto merge of #46338 - michaelwoerister:lazy-diagnostics, r=nikomatsakis
incr.comp.: Load cached diagnostics lazily and allow more things in the cache. This PR implements makes two changes: 1. Diagnostics are loaded lazily from the incr. comp. cache now. This turned out to be necessary for correctness because diagnostics contain `Span` values and deserializing those requires that the source file they point to is still around in the current compilation session. Obviously this isn't always the case. Loading them lazily allows for never touching diagnostics that are not valid anymore. 2. The compiler can now deal with there being no cache entry for a given query invocation. Before, all query results of a cacheable query were always expected to be present in the cache. Now, the compiler can fall back to re-computing the result if there is no cache entry found. This allows for caching things that we cannot force from dep-node (like the `symbol_name` query). In such a case we'll just have a "best effort" caching strategy. ~~This PR is based on #46301 (=first 2 commits), so please don't merge until that has landed. The rest of the commits are ready for review though.~~ r? @nikomatsakis
2 parents e3ed212 + 966eead commit 6805b01

File tree

11 files changed

+476
-226
lines changed

11 files changed

+476
-226
lines changed

src/librustc/dep_graph/graph.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -461,10 +461,10 @@ impl DepGraph {
461461
self.data.as_ref().and_then(|data| data.colors.borrow().get(dep_node).cloned())
462462
}
463463

464-
pub fn try_mark_green(&self,
465-
tcx: TyCtxt,
466-
dep_node: &DepNode)
467-
-> Option<DepNodeIndex> {
464+
pub fn try_mark_green<'tcx>(&self,
465+
tcx: TyCtxt<'_, 'tcx, 'tcx>,
466+
dep_node: &DepNode)
467+
-> Option<DepNodeIndex> {
468468
debug!("try_mark_green({:?}) - BEGIN", dep_node);
469469
let data = self.data.as_ref().unwrap();
470470

@@ -621,7 +621,7 @@ impl DepGraph {
621621
// ... emitting any stored diagnostic ...
622622
{
623623
let diagnostics = tcx.on_disk_query_result_cache
624-
.load_diagnostics(prev_dep_node_index);
624+
.load_diagnostics(tcx, prev_dep_node_index);
625625

626626
if diagnostics.len() > 0 {
627627
let handle = tcx.sess.diagnostic();

src/librustc/ich/hcx.rs

+33-44
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use syntax::attr;
2828
use syntax::codemap::CodeMap;
2929
use syntax::ext::hygiene::SyntaxContext;
3030
use syntax::symbol::Symbol;
31-
use syntax_pos::Span;
31+
use syntax_pos::{Span, DUMMY_SP};
3232

3333
use rustc_data_structures::stable_hasher::{HashStable, StableHashingContextProvider,
3434
StableHasher, StableHasherResult,
@@ -362,64 +362,53 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for Span {
362362
fn hash_stable<W: StableHasherResult>(&self,
363363
hcx: &mut StableHashingContext<'gcx>,
364364
hasher: &mut StableHasher<W>) {
365-
use syntax_pos::Pos;
365+
const TAG_VALID_SPAN: u8 = 0;
366+
const TAG_INVALID_SPAN: u8 = 1;
367+
const TAG_EXPANSION: u8 = 0;
368+
const TAG_NO_EXPANSION: u8 = 1;
366369

367370
if !hcx.hash_spans {
368371
return
369372
}
370373

374+
if *self == DUMMY_SP {
375+
return std_hash::Hash::hash(&TAG_INVALID_SPAN, hasher);
376+
}
377+
371378
// If this is not an empty or invalid span, we want to hash the last
372379
// position that belongs to it, as opposed to hashing the first
373380
// position past it.
374381
let span = self.data();
375-
let span_hi = if span.hi > span.lo {
376-
// We might end up in the middle of a multibyte character here,
377-
// but that's OK, since we are not trying to decode anything at
378-
// this position.
379-
span.hi - ::syntax_pos::BytePos(1)
380-
} else {
381-
span.hi
382-
};
383382

384-
{
385-
let loc1 = hcx.codemap().byte_pos_to_line_and_col(span.lo);
386-
let loc1 = loc1.as_ref()
387-
.map(|&(ref fm, line, col)| (&fm.name[..], line, col.to_usize()))
388-
.unwrap_or(("???", 0, 0));
389-
390-
let loc2 = hcx.codemap().byte_pos_to_line_and_col(span_hi);
391-
let loc2 = loc2.as_ref()
392-
.map(|&(ref fm, line, col)| (&fm.name[..], line, col.to_usize()))
393-
.unwrap_or(("???", 0, 0));
394-
395-
if loc1.0 == loc2.0 {
396-
std_hash::Hash::hash(&0u8, hasher);
397-
398-
std_hash::Hash::hash(loc1.0, hasher);
399-
std_hash::Hash::hash(&loc1.1, hasher);
400-
std_hash::Hash::hash(&loc1.2, hasher);
401-
402-
// Do not hash the file name twice
403-
std_hash::Hash::hash(&loc2.1, hasher);
404-
std_hash::Hash::hash(&loc2.2, hasher);
405-
} else {
406-
std_hash::Hash::hash(&1u8, hasher);
407-
408-
std_hash::Hash::hash(loc1.0, hasher);
409-
std_hash::Hash::hash(&loc1.1, hasher);
410-
std_hash::Hash::hash(&loc1.2, hasher);
411-
412-
std_hash::Hash::hash(loc2.0, hasher);
413-
std_hash::Hash::hash(&loc2.1, hasher);
414-
std_hash::Hash::hash(&loc2.2, hasher);
383+
if span.hi < span.lo {
384+
return std_hash::Hash::hash(&TAG_INVALID_SPAN, hasher);
385+
}
386+
387+
let (file_lo, line_lo, col_lo) = match hcx.codemap()
388+
.byte_pos_to_line_and_col(span.lo) {
389+
Some(pos) => pos,
390+
None => {
391+
return std_hash::Hash::hash(&TAG_INVALID_SPAN, hasher);
415392
}
393+
};
394+
395+
if !file_lo.contains(span.hi) {
396+
return std_hash::Hash::hash(&TAG_INVALID_SPAN, hasher);
416397
}
417398

399+
let len = span.hi - span.lo;
400+
401+
std_hash::Hash::hash(&TAG_VALID_SPAN, hasher);
402+
std_hash::Hash::hash(&file_lo.name, hasher);
403+
std_hash::Hash::hash(&line_lo, hasher);
404+
std_hash::Hash::hash(&col_lo, hasher);
405+
std_hash::Hash::hash(&len, hasher);
406+
418407
if span.ctxt == SyntaxContext::empty() {
419-
0u8.hash_stable(hcx, hasher);
408+
TAG_NO_EXPANSION.hash_stable(hcx, hasher);
420409
} else {
421-
1u8.hash_stable(hcx, hasher);
422-
self.source_callsite().hash_stable(hcx, hasher);
410+
TAG_EXPANSION.hash_stable(hcx, hasher);
411+
span.ctxt.outer().expn_info().hash_stable(hcx, hasher);
423412
}
424413
}
425414
}

src/librustc/ich/impls_syntax.rs

+24
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,30 @@ impl_stable_hash_for!(enum ::syntax::ast::MetaItemKind {
347347
NameValue(lit)
348348
});
349349

350+
impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnInfo {
351+
call_site,
352+
callee
353+
});
354+
355+
impl_stable_hash_for!(struct ::syntax_pos::hygiene::NameAndSpan {
356+
format,
357+
allow_internal_unstable,
358+
allow_internal_unsafe,
359+
span
360+
});
361+
362+
impl_stable_hash_for!(enum ::syntax_pos::hygiene::ExpnFormat {
363+
MacroAttribute(sym),
364+
MacroBang(sym),
365+
CompilerDesugaring(kind)
366+
});
367+
368+
impl_stable_hash_for!(enum ::syntax_pos::hygiene::CompilerDesugaringKind {
369+
BackArrow,
370+
DotFill,
371+
QuestionMark
372+
});
373+
350374
impl<'gcx> HashStable<StableHashingContext<'gcx>> for FileMap {
351375
fn hash_stable<W: StableHasherResult>(&self,
352376
hcx: &mut StableHashingContext<'gcx>,

src/librustc/ty/context.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1235,7 +1235,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
12351235
-> Result<(), E::Error>
12361236
where E: ty::codec::TyEncoder
12371237
{
1238-
self.on_disk_query_result_cache.serialize(self.global_tcx(), self.cstore, encoder)
1238+
self.on_disk_query_result_cache.serialize(self.global_tcx(), encoder)
12391239
}
12401240

12411241
}

src/librustc/ty/maps/config.rs

+9-7
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ pub(super) trait QueryDescription<'tcx>: QueryConfig {
3131
false
3232
}
3333

34-
fn load_from_disk<'a>(_: TyCtxt<'a, 'tcx, 'tcx>,
34+
fn try_load_from_disk(_: TyCtxt<'_, 'tcx, 'tcx>,
3535
_: SerializedDepNodeIndex)
36-
-> Self::Value {
36+
-> Option<Self::Value> {
3737
bug!("QueryDescription::load_from_disk() called for unsupport query.")
3838
}
3939
}
@@ -556,12 +556,14 @@ impl<'tcx> QueryDescription<'tcx> for queries::typeck_tables_of<'tcx> {
556556
def_id.is_local()
557557
}
558558

559-
fn load_from_disk<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
559+
fn try_load_from_disk(tcx: TyCtxt<'_, 'tcx, 'tcx>,
560560
id: SerializedDepNodeIndex)
561-
-> Self::Value {
562-
let typeck_tables: ty::TypeckTables<'tcx> = tcx.on_disk_query_result_cache
563-
.load_query_result(tcx, id);
564-
tcx.alloc_tables(typeck_tables)
561+
-> Option<Self::Value> {
562+
let typeck_tables: Option<ty::TypeckTables<'tcx>> = tcx
563+
.on_disk_query_result_cache
564+
.try_load_query_result(tcx, id);
565+
566+
typeck_tables.map(|tables| tcx.alloc_tables(tables))
565567
}
566568
}
567569

0 commit comments

Comments
 (0)