1
Fork 0

Auto merge of #88414 - Aaron1011:guess-foreign-head-span, r=estebank

Don't use `guess_head_span` in `predicates_of` for foreign span

Previously, the result of `predicates_of` for a foreign trait
would depend on the *current* state of the corresponding source
file in the foreign crate. This could lead to ICEs during incremental
compilation, since the on-disk contents of the upstream source file
could potentially change without the upstream crate being recompiled.

Additionally, this ensure that that the metadata we produce for a crate
only depends on its *compiled* upstream dependencies (e.g an rlib or
rmeta file), *not* the current on-disk state of the upstream crate
source files.
This commit is contained in:
bors 2021-08-31 03:34:22 +00:00
commit 1e37e83dc0
9 changed files with 97 additions and 15 deletions

View file

@ -567,6 +567,17 @@ impl SourceMap {
}
}
/// Returns whether or not this span points into a file
/// in the current crate. This may be `false` for spans
/// produced by a macro expansion, or for spans associated
/// with the definition of an item in a foreign crate
pub fn is_local_span(&self, sp: Span) -> bool {
let local_begin = self.lookup_byte_offset(sp.lo());
let local_end = self.lookup_byte_offset(sp.hi());
// This might be a weird span that covers multiple files
local_begin.sf.src.is_some() && local_end.sf.src.is_some()
}
/// Returns the source snippet as `String` corresponding to the given `Span`.
pub fn span_to_snippet(&self, sp: Span) -> Result<String, SpanSnippetError> {
self.span_to_source(sp, |src, start_index, end_index| {

View file

@ -2002,7 +2002,16 @@ fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
// prove that the trait applies to the types that were
// used, and adding the predicate into this list ensures
// that this is done.
let span = tcx.sess.source_map().guess_head_span(tcx.def_span(def_id));
let mut span = tcx.def_span(def_id);
if tcx.sess.source_map().is_local_span(span) {
// `guess_head_span` reads the actual source file from
// disk to try to determine the 'head' snippet of the span.
// Don't do this for a span that comes from a file outside
// of our crate, since this would make our query output
// (and overall crate metadata) dependent on the
// *current* state of an external file.
span = tcx.sess.source_map().guess_head_span(span);
}
result.predicates =
tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(std::iter::once((
ty::TraitRef::identity(tcx, def_id).without_const().to_predicate(tcx),