Choose encoding format in caller code.

This commit is contained in:
Camille GILLOT 2021-06-27 10:38:06 +02:00
parent 078dd37f88
commit 2fe37c5bd1
4 changed files with 55 additions and 85 deletions

View File

@ -377,7 +377,11 @@ fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result<ExpnId, String> {
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<ExpnId, String> {
.unwrap()
.decode((&crate_data, sess));
(expn_data, expn_hash)
})
});
Ok(expn_id)
}
}

View File

@ -182,7 +182,15 @@ fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> 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)
}
}

View File

@ -794,25 +794,26 @@ fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for ExpnId {
fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
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<CacheEncoder<'a, 'tcx, E>> 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)
}
}

View File

@ -261,6 +261,8 @@ pub struct HygieneData {
/// first and then resolved later), so we use an `Option` here.
local_expn_data: IndexVec<LocalExpnId, Option<ExpnData>>,
local_expn_hashes: IndexVec<LocalExpnId, ExpnHash>,
/// 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<ExpnId, ExpnData>,
foreign_expn_hashes: FxHashMap<ExpnId, ExpnHash>,
expn_hash_to_expn_id: UnhashMap<ExpnHash, ExpnId>,
@ -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<T, R>(
&self,
encoder: &mut T,
@ -1186,15 +1195,13 @@ pub struct HygieneDecodeContext {
remapped_expns: Lock<Vec<Option<LocalExpnId>>>,
}
pub fn decode_expn_id_incrcomp<D: Decoder>(
d: &mut D,
pub fn decode_expn_id_incrcomp<E>(
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<ExpnId, D::Error> {
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<ExpnId, E> {
// 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<D: Decoder>(
}
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<D: Decoder>(
// 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<D: Decoder>(
Ok(expn_id)
}
pub fn decode_expn_id<D: Decoder>(
d: &mut D,
decode_data: impl FnOnce(CrateNum, ExpnIndex) -> (ExpnData, ExpnHash),
) -> Result<ExpnId, D::Error> {
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<D: Decoder>(
// 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<D: Decoder>(
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<E: Encoder>(
ctxt.0.encode(e)
}
pub fn raw_encode_expn_id_incrcomp<E: Encoder>(
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<E: Encoder>(
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<Span>` 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<E: Encoder> Encodable<E> for SyntaxContext {
default fn encode(&self, _: &mut E) -> Result<(), E::Error> {
panic!("cannot encode `SyntaxContext` with `{}`", std::any::type_name::<E>());