From 2fe37c5bd1cc7d6cfa176f408c2b834e1b2617bf Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 27 Jun 2021 10:38:06 +0200 Subject: [PATCH] Choose encoding format in caller code. --- compiler/rustc_metadata/src/rmeta/decoder.rs | 9 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 10 +- .../src/ty/query/on_disk_cache.rs | 23 +++-- compiler/rustc_span/src/hygiene.rs | 98 +++++-------------- 4 files changed, 55 insertions(+), 85 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 4b72ac86957..8b8ca987b38 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -377,7 +377,11 @@ fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result { let local_cdata = decoder.cdata(); let sess = decoder.sess.unwrap(); - rustc_span::hygiene::decode_expn_id(decoder, |cnum, index| { + let cnum = CrateNum::decode(decoder)?; + let index = u32::decode(decoder)?; + + let expn_id = rustc_span::hygiene::decode_expn_id(cnum, index, |expn_id| { + let ExpnId { krate: cnum, local_id: index } = expn_id; // Lookup local `ExpnData`s in our own crate data. Foreign `ExpnData`s // are stored in the owning crate, to avoid duplication. debug_assert_ne!(cnum, LOCAL_CRATE); @@ -399,7 +403,8 @@ fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result { .unwrap() .decode((&crate_data, sess)); (expn_data, expn_hash) - }) + }); + Ok(expn_id) } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 4684daef4a1..6877d6ef542 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -182,7 +182,15 @@ fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult { impl<'a, 'tcx> Encodable> for ExpnId { fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult { - rustc_span::hygiene::raw_encode_expn_id(*self, &s.hygiene_ctxt, s) + if self.krate == LOCAL_CRATE { + // We will only write details for local expansions. Non-local expansions will fetch + // data from the corresponding crate's metadata. + // FIXME(#43047) FIXME(#74731) We may eventually want to avoid relying on external + // metadata from proc-macro crates. + s.hygiene_ctxt.schedule_expn_data_for_encoding(*self); + } + self.krate.encode(s)?; + self.local_id.encode(s) } } diff --git a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs index 358d016368e..685cb3a61ec 100644 --- a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs @@ -794,25 +794,26 @@ fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result { impl<'a, 'tcx> Decodable> for ExpnId { fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result { + let krate = CrateNum::decode(decoder)?; + let index = u32::decode(decoder)?; + let expn_data = decoder.expn_data; + let tcx = decoder.tcx; rustc_span::hygiene::decode_expn_id_incrcomp( - decoder, + krate, + index, decoder.hygiene_context, - |this, index| { + |index| -> Result<(ExpnData, ExpnHash), _> { // This closure is invoked if we haven't already decoded the data for the `ExpnId` we are deserializing. // We look up the position of the associated `ExpnData` and decode it. let pos = expn_data .get(&index) .unwrap_or_else(|| panic!("Bad index {:?} (map {:?})", index, expn_data)); - this.with_position(pos.to_usize(), |decoder| { - let data: (ExpnData, ExpnHash) = decode_tagged(decoder, TAG_EXPN_DATA)?; - Ok(data) - }) - }, - |this, expn_id| { - Ok(this.tcx.untracked_resolutions.cstore.decode_expn_data(this.tcx.sess, expn_id)) + decoder + .with_position(pos.to_usize(), |decoder| decode_tagged(decoder, TAG_EXPN_DATA)) }, + |expn_id| tcx.untracked_resolutions.cstore.decode_expn_data(tcx.sess, expn_id), ) } } @@ -988,7 +989,9 @@ impl<'a, 'tcx, E> Encodable> for ExpnId E: 'a + OpaqueEncoder, { fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> { - rustc_span::hygiene::raw_encode_expn_id_incrcomp(*self, s.hygiene_context, s) + s.hygiene_context.schedule_expn_data_for_encoding(*self); + self.krate.encode(s)?; + self.local_id.as_u32().encode(s) } } diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 138ec061423..198bb588142 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -261,6 +261,8 @@ pub struct HygieneData { /// first and then resolved later), so we use an `Option` here. local_expn_data: IndexVec>, local_expn_hashes: IndexVec, + /// Data and hash information from external crates. We may eventually want to remove these + /// maps, and fetch the information directly from the other crate's metadata like DefIds do. foreign_expn_data: FxHashMap, foreign_expn_hashes: FxHashMap, expn_hash_to_expn_id: UnhashMap, @@ -1130,6 +1132,13 @@ pub struct HygieneEncodeContext { } impl HygieneEncodeContext { + /// Record the fact that we need to serialize the corresponding `ExpnData`. + pub fn schedule_expn_data_for_encoding(&self, expn: ExpnId) { + if !self.serialized_expns.lock().contains(&expn) { + self.latest_expns.lock().insert(expn); + } + } + pub fn encode( &self, encoder: &mut T, @@ -1186,15 +1195,13 @@ pub struct HygieneDecodeContext { remapped_expns: Lock>>, } -pub fn decode_expn_id_incrcomp( - d: &mut D, +pub fn decode_expn_id_incrcomp( + krate: CrateNum, + index: u32, context: &HygieneDecodeContext, - decode_data: impl FnOnce(&mut D, u32) -> Result<(ExpnData, ExpnHash), D::Error>, - decode_foreign: impl FnOnce(&mut D, ExpnId) -> Result<(ExpnData, ExpnHash), D::Error>, -) -> Result { - let krate = CrateNum::decode(d)?; - let index = u32::decode(d)?; - + decode_data: impl FnOnce(u32) -> Result<(ExpnData, ExpnHash), E>, + decode_foreign: impl FnOnce(ExpnId) -> (ExpnData, ExpnHash), +) -> Result { // Do this after decoding, so that we decode a `CrateNum` // if necessary if index == 0 { @@ -1203,23 +1210,7 @@ pub fn decode_expn_id_incrcomp( } if krate != LOCAL_CRATE { - let expn_id = ExpnId { krate, local_id: ExpnIndex::from_u32(index) }; - if HygieneData::with(|hygiene_data| hygiene_data.foreign_expn_data.contains_key(&expn_id)) { - return Ok(expn_id); - } - let (expn_data, hash) = decode_foreign(d, expn_id)?; - debug_assert_eq!(krate, expn_data.krate); - debug_assert_eq!(expn_data.orig_id, Some(index)); - let expn_id = HygieneData::with(|hygiene_data| { - debug_assert_eq!(expn_data.orig_id, Some(index)); - let _old_data = hygiene_data.foreign_expn_data.insert(expn_id, expn_data); - debug_assert!(_old_data.is_none()); - let _old_hash = hygiene_data.foreign_expn_hashes.insert(expn_id, hash); - debug_assert!(_old_hash.is_none()); - let _old_id = hygiene_data.expn_hash_to_expn_id.insert(hash, expn_id); - debug_assert!(_old_id.is_none()); - expn_id - }); + let expn_id = decode_expn_id(krate, index, decode_foreign); return Ok(expn_id); } @@ -1234,7 +1225,7 @@ pub fn decode_expn_id_incrcomp( // Don't decode the data inside `HygieneData::with`, since we need to recursively decode // other ExpnIds - let (mut expn_data, hash) = decode_data(d, index)?; + let (mut expn_data, hash) = decode_data(index)?; debug_assert_eq!(krate, expn_data.krate); let expn_id = HygieneData::with(|hygiene_data| { @@ -1269,18 +1260,14 @@ pub fn decode_expn_id_incrcomp( Ok(expn_id) } -pub fn decode_expn_id( - d: &mut D, - decode_data: impl FnOnce(CrateNum, ExpnIndex) -> (ExpnData, ExpnHash), -) -> Result { - let krate = CrateNum::decode(d)?; - let index = u32::decode(d)?; - - // Do this after decoding, so that we decode a `CrateNum` - // if necessary +pub fn decode_expn_id( + krate: CrateNum, + index: u32, + decode_data: impl FnOnce(ExpnId) -> (ExpnData, ExpnHash), +) -> ExpnId { if index == 0 { debug!("decode_expn_id: deserialized root"); - return Ok(ExpnId::root()); + return ExpnId::root(); } let index = ExpnIndex::from_u32(index); @@ -1291,12 +1278,12 @@ pub fn decode_expn_id( // Fast path if the expansion has already been decoded. if HygieneData::with(|hygiene_data| hygiene_data.foreign_expn_data.contains_key(&expn_id)) { - return Ok(expn_id); + return expn_id; } // Don't decode the data inside `HygieneData::with`, since we need to recursively decode // other ExpnIds - let (expn_data, hash) = decode_data(krate, index); + let (expn_data, hash) = decode_data(expn_id); debug_assert_eq!(krate, expn_data.krate); debug_assert_eq!(Some(index.as_u32()), expn_data.orig_id); @@ -1309,7 +1296,7 @@ pub fn decode_expn_id( debug_assert!(_old_id.is_none()); }); - Ok(expn_id) + expn_id } // Decodes `SyntaxContext`, using the provided `HygieneDecodeContext` @@ -1448,39 +1435,6 @@ pub fn raw_encode_syntax_context( ctxt.0.encode(e) } -pub fn raw_encode_expn_id_incrcomp( - expn: ExpnId, - context: &HygieneEncodeContext, - e: &mut E, -) -> Result<(), E::Error> { - // Record the fact that we need to serialize the corresponding `ExpnData` - if !context.serialized_expns.lock().contains(&expn) { - context.latest_expns.lock().insert(expn); - } - expn.krate.encode(e)?; - expn.local_id.as_u32().encode(e) -} - -pub fn raw_encode_expn_id( - expn: ExpnId, - context: &HygieneEncodeContext, - e: &mut E, -) -> Result<(), E::Error> { - // We only need to serialize the ExpnData - // if it comes from this crate. - // We currently don't serialize any hygiene information data for - // proc-macro crates: see the `SpecializedEncoder` impl - // for crate metadata. - // Record the fact that we need to serialize the corresponding `ExpnData` - if expn.krate == LOCAL_CRATE { - if !context.serialized_expns.lock().contains(&expn) { - context.latest_expns.lock().insert(expn); - } - } - expn.krate.encode(e)?; - expn.local_id.as_u32().encode(e) -} - impl Encodable for SyntaxContext { default fn encode(&self, _: &mut E) -> Result<(), E::Error> { panic!("cannot encode `SyntaxContext` with `{}`", std::any::type_name::());