Rollup merge of #89476 - cjgillot:expn-id, r=petrochenkov
Correct decoding of foreign expansions during incr. comp.
Fixes https://github.com/rust-lang/rust/issues/74946
The original issue was due to a wrong assertion in `expn_hash_to_expn_id`.
The secondary issue was due to a mismatch between the encoding and decoding paths for expansions that are created after the TyCtxt is created.
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index c7d0f59..89bb579 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -1632,7 +1632,7 @@ fn def_path_hash_to_def_index(&self, hash: DefPathHash) -> DefIndex {
self.def_path_hash_map.def_path_hash_to_def_index(&hash)
}
- fn expn_hash_to_expn_id(&self, index_guess: u32, hash: ExpnHash) -> ExpnId {
+ fn expn_hash_to_expn_id(&self, sess: &Session, index_guess: u32, hash: ExpnHash) -> ExpnId {
debug_assert_eq!(ExpnId::from_hash(hash), None);
let index_guess = ExpnIndex::from_u32(index_guess);
let old_hash = self.root.expn_hashes.get(self, index_guess).map(|lazy| lazy.decode(self));
@@ -1654,8 +1654,6 @@ fn expn_hash_to_expn_id(&self, index_guess: u32, hash: ExpnHash) -> ExpnId {
let i = ExpnIndex::from_u32(i);
if let Some(hash) = self.root.expn_hashes.get(self, i) {
map.insert(hash.decode(self), i);
- } else {
- panic!("Missing expn_hash entry for {:?}", i);
}
}
map
@@ -1663,7 +1661,7 @@ fn expn_hash_to_expn_id(&self, index_guess: u32, hash: ExpnHash) -> ExpnId {
map[&hash]
};
- let data = self.root.expn_data.get(self, index).unwrap().decode(self);
+ let data = self.root.expn_data.get(self, index).unwrap().decode((self, sess));
rustc_span::hygiene::register_expn_id(self.cnum, index, data, hash)
}
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 292ef03..4e7f85d 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -506,7 +506,13 @@ fn def_path_hash_to_def_id(&self, cnum: CrateNum, hash: DefPathHash) -> DefId {
DefId { krate: cnum, index: def_index }
}
- fn expn_hash_to_expn_id(&self, cnum: CrateNum, index_guess: u32, hash: ExpnHash) -> ExpnId {
- self.get_crate_data(cnum).expn_hash_to_expn_id(index_guess, hash)
+ fn expn_hash_to_expn_id(
+ &self,
+ sess: &Session,
+ cnum: CrateNum,
+ index_guess: u32,
+ hash: ExpnHash,
+ ) -> ExpnId {
+ self.get_crate_data(cnum).expn_hash_to_expn_id(sess, index_guess, hash)
}
}
diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs
index d8cff0b..48eb488 100644
--- a/compiler/rustc_query_impl/src/on_disk_cache.rs
+++ b/compiler/rustc_query_impl/src/on_disk_cache.rs
@@ -664,22 +664,32 @@ fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
let data: ExpnData = decoder
.with_position(pos.to_usize(), |decoder| decode_tagged(decoder, TAG_EXPN_DATA))?;
- rustc_span::hygiene::register_local_expn_id(data, hash)
+ let expn_id = rustc_span::hygiene::register_local_expn_id(data, hash);
+
+ #[cfg(debug_assertions)]
+ {
+ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+ let mut hcx = decoder.tcx.create_stable_hashing_context();
+ let mut hasher = StableHasher::new();
+ hcx.while_hashing_spans(true, |hcx| {
+ expn_id.expn_data().hash_stable(hcx, &mut hasher)
+ });
+ let local_hash: u64 = hasher.finish();
+ debug_assert_eq!(hash.local_hash(), local_hash);
+ }
+
+ expn_id
} else {
let index_guess = decoder.foreign_expn_data[&hash];
- decoder.tcx.cstore_untracked().expn_hash_to_expn_id(krate, index_guess, hash)
+ decoder.tcx.cstore_untracked().expn_hash_to_expn_id(
+ decoder.tcx.sess,
+ krate,
+ index_guess,
+ hash,
+ )
};
- #[cfg(debug_assertions)]
- {
- use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
- let mut hcx = decoder.tcx.create_stable_hashing_context();
- let mut hasher = StableHasher::new();
- hcx.while_hashing_spans(true, |hcx| expn_id.expn_data().hash_stable(hcx, &mut hasher));
- let local_hash: u64 = hasher.finish();
- debug_assert_eq!(hash.local_hash(), local_hash);
- }
-
+ debug_assert_eq!(expn_id.krate, krate);
Ok(expn_id)
}
}
diff --git a/compiler/rustc_session/src/cstore.rs b/compiler/rustc_session/src/cstore.rs
index 9d6bd20..59e7abc 100644
--- a/compiler/rustc_session/src/cstore.rs
+++ b/compiler/rustc_session/src/cstore.rs
@@ -4,6 +4,7 @@
use crate::search_paths::PathKind;
use crate::utils::NativeLibKind;
+use crate::Session;
use rustc_ast as ast;
use rustc_data_structures::sync::{self, MetadataRef};
use rustc_hir::def_id::{CrateNum, DefId, StableCrateId, LOCAL_CRATE};
@@ -193,7 +194,13 @@ pub trait CrateStore: std::fmt::Debug {
/// Fetch a DefId from a DefPathHash for a foreign crate.
fn def_path_hash_to_def_id(&self, cnum: CrateNum, hash: DefPathHash) -> DefId;
- fn expn_hash_to_expn_id(&self, cnum: CrateNum, index_guess: u32, hash: ExpnHash) -> ExpnId;
+ fn expn_hash_to_expn_id(
+ &self,
+ sess: &Session,
+ cnum: CrateNum,
+ index_guess: u32,
+ hash: ExpnHash,
+ ) -> ExpnId;
}
pub type CrateStoreDyn = dyn CrateStore + sync::Sync;
diff --git a/src/test/incremental/mir-opt.rs b/src/test/incremental/mir-opt.rs
new file mode 100644
index 0000000..5bd8634
--- /dev/null
+++ b/src/test/incremental/mir-opt.rs
@@ -0,0 +1,11 @@
+// MIR optimizations can create expansions after the TyCtxt has been created.
+// This test verifies that those expansions can be decoded correctly.
+
+// revisions:rpass1 rpass2
+// compile-flags: -Z query-dep-graph -Z mir-opt-level=3
+
+fn main() {
+ if std::env::var("a").is_ok() {
+ println!("b");
+ }
+}