Auto merge of #84373 - cjgillot:resolve-span, r=michaelwoerister,petrochenkov
Encode spans relative to the enclosing item The aim of this PR is to avoid recomputing queries when code is moved without modification. MCP at https://github.com/rust-lang/compiler-team/issues/443 This is achieved by : 1. storing the HIR owner LocalDefId information inside the span; 2. encoding and decoding spans relative to the enclosing item in the incremental on-disk cache; 3. marking a dependency to the `source_span(LocalDefId)` query when we translate a span from the short (`Span`) representation to its explicit (`SpanData`) representation. Since all client code uses `Span`, step 3 ensures that all manipulations of span byte positions actually create the dependency edge between the caller and the `source_span(LocalDefId)`. This query return the actual absolute span of the parent item. As a consequence, any source code motion that changes the absolute byte position of a node will either: - modify the distance to the parent's beginning, so change the relative span's hash; - dirty `source_span`, and trigger the incremental recomputation of all code that depends on the span's absolute byte position. With this scheme, I believe the dependency tracking to be accurate. For the moment, the spans are marked during lowering. I'd rather do this during def-collection, but the AST MutVisitor is not practical enough just yet. The only difference is that we attach macro-expanded spans to their expansion point instead of the macro itself.
This commit is contained in:
@@ -969,22 +969,12 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
|
||||
.iter_enumerated()
|
||||
.filter_map(|(def_id, hod)| {
|
||||
let def_path_hash = tcx.untracked_resolutions.definitions.def_path_hash(def_id);
|
||||
let mut hasher = StableHasher::new();
|
||||
hod.as_ref()?.hash_stable(&mut hcx, &mut hasher);
|
||||
AttributeMap { map: &tcx.untracked_crate.attrs, prefix: def_id }
|
||||
.hash_stable(&mut hcx, &mut hasher);
|
||||
Some((def_path_hash, hasher.finish()))
|
||||
let hash = hod.as_ref()?.hash;
|
||||
Some((def_path_hash, hash, def_id))
|
||||
})
|
||||
.collect();
|
||||
hir_body_nodes.sort_unstable_by_key(|bn| bn.0);
|
||||
|
||||
let node_hashes = hir_body_nodes.iter().fold(
|
||||
Fingerprint::ZERO,
|
||||
|combined_fingerprint, &(def_path_hash, fingerprint)| {
|
||||
combined_fingerprint.combine(def_path_hash.0.combine(fingerprint))
|
||||
},
|
||||
);
|
||||
|
||||
let upstream_crates = upstream_crates(tcx);
|
||||
|
||||
// We hash the final, remapped names of all local source files so we
|
||||
@@ -1004,7 +994,17 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
|
||||
source_file_names.sort_unstable();
|
||||
|
||||
let mut stable_hasher = StableHasher::new();
|
||||
node_hashes.hash_stable(&mut hcx, &mut stable_hasher);
|
||||
for (def_path_hash, fingerprint, def_id) in hir_body_nodes.iter() {
|
||||
def_path_hash.0.hash_stable(&mut hcx, &mut stable_hasher);
|
||||
fingerprint.hash_stable(&mut hcx, &mut stable_hasher);
|
||||
AttributeMap { map: &tcx.untracked_crate.attrs, prefix: *def_id }
|
||||
.hash_stable(&mut hcx, &mut stable_hasher);
|
||||
if tcx.sess.opts.debugging_opts.incremental_relative_spans {
|
||||
let span = tcx.untracked_resolutions.definitions.def_span(*def_id);
|
||||
debug_assert_eq!(span.parent(), None);
|
||||
span.hash_stable(&mut hcx, &mut stable_hasher);
|
||||
}
|
||||
}
|
||||
upstream_crates.hash_stable(&mut hcx, &mut stable_hasher);
|
||||
source_file_names.hash_stable(&mut hcx, &mut stable_hasher);
|
||||
tcx.sess.opts.dep_tracking_hash(true).hash_stable(&mut hcx, &mut stable_hasher);
|
||||
|
||||
@@ -153,6 +153,7 @@ pub fn provide(providers: &mut Providers) {
|
||||
index.parenting.get(&id).copied().unwrap_or(CRATE_HIR_ID)
|
||||
};
|
||||
providers.hir_attrs = |tcx, id| AttributeMap { map: &tcx.untracked_crate.attrs, prefix: id };
|
||||
providers.source_span = |tcx, def_id| tcx.resolutions(()).definitions.def_span(def_id);
|
||||
providers.def_span = |tcx, def_id| tcx.hir().span_if_local(def_id).unwrap_or(DUMMY_SP);
|
||||
providers.fn_arg_names = |tcx, id| {
|
||||
let hir = tcx.hir();
|
||||
|
||||
Reference in New Issue
Block a user