]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #75137 - Aaron1011:fix/hygiene-skip-expndata, r=petrochenkov
authorbors <bors@rust-lang.org>
Sun, 9 Aug 2020 18:19:34 +0000 (18:19 +0000)
committerbors <bors@rust-lang.org>
Sun, 9 Aug 2020 18:19:34 +0000 (18:19 +0000)
Don't serialize ExpnData for foreign crates

When we encode an ExpnId into the crate metadata, we write out the
CrateNum of the crate that 'owns' the corresponding `ExpnData`, which
is later used to decode the `ExpnData` from its owning crate.

However, we current serialize the `ExpnData` for all `ExpnIds` that we
serialize, even if the `ExpnData` was already serialized into a foreign
crate. This commit skips encoding this kind of `ExpnData`, which should
hopefully speed up metadata encoding and reduce the total metadata size.

src/librustc_metadata/rmeta/encoder.rs
src/librustc_span/hygiene.rs

index 3f92226e5480d879c46b4b0396023f514bea8e07..f75f0b74a0e1e19eed3290bd55e477826e1e6f50 100644 (file)
@@ -279,6 +279,10 @@ fn specialized_encode(&mut self, span: &Span) -> Result<(), Self::Error> {
         // cross-crate inconsistencies (getting one behavior in the same
         // crate, and a different behavior in another crate) due to the
         // limited surface that proc-macros can expose.
+        //
+        // IMPORTANT: If this is ever changed, be sure to update
+        // `rustc_span::hygiene::raw_encode_expn_id` to handle
+        // encoding `ExpnData` for proc-macro crates.
         if self.is_proc_macro {
             SyntaxContext::root().encode(self)?;
         } else {
index 4e21d566071ef609da18d9c34dcf87fb7a452b01..f52b2195c2f6e25d6bc797e24511808c43a08374 100644 (file)
@@ -1172,13 +1172,30 @@ pub fn raw_encode_expn_id<E: Encoder>(
     mode: ExpnDataEncodeMode,
     e: &mut E,
 ) -> Result<(), E::Error> {
-    if !context.serialized_expns.lock().contains(&expn) {
-        context.latest_expns.lock().insert(expn);
-    }
+    // Record the fact that we need to serialize the corresponding
+    // `ExpnData`
+    let needs_data = || {
+        if !context.serialized_expns.lock().contains(&expn) {
+            context.latest_expns.lock().insert(expn);
+        }
+    };
+
     match mode {
-        ExpnDataEncodeMode::IncrComp => expn.0.encode(e),
+        ExpnDataEncodeMode::IncrComp => {
+            // Always serialize the `ExpnData` in incr comp mode
+            needs_data();
+            expn.0.encode(e)
+        }
         ExpnDataEncodeMode::Metadata => {
             let data = expn.expn_data();
+            // 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.
+            if data.krate == LOCAL_CRATE {
+                needs_data();
+            }
             data.orig_id.expect("Missing orig_id").encode(e)?;
             data.krate.encode(e)
         }