]> 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.

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

index 3f92226e5480d879c46b4b0396023f514bea8e07,6872693a66cb84f2d5b696a623f12406839874ff..f75f0b74a0e1e19eed3290bd55e477826e1e6f50
@@@ -3,6 -3,7 +3,6 @@@ use crate::rmeta::*
  
  use log::{debug, trace};
  use rustc_ast::ast;
 -use rustc_ast::attr;
  use rustc_data_structures::fingerprint::Fingerprint;
  use rustc_data_structures::fx::{FxHashMap, FxHashSet};
  use rustc_data_structures::stable_hasher::StableHasher;
@@@ -161,7 -162,7 +161,7 @@@ impl<'a, 'tcx> SpecializedEncoder<ExpnI
      fn specialized_encode(&mut self, expn: &ExpnId) -> Result<(), Self::Error> {
          rustc_span::hygiene::raw_encode_expn_id(
              *expn,
 -            &mut self.hygiene_ctxt,
 +            &self.hygiene_ctxt,
              ExpnDataEncodeMode::Metadata,
              self,
          )
@@@ -279,6 -280,10 +279,10 @@@ impl<'a, 'tcx> SpecializedEncoder<Span
          // 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 {
@@@ -632,7 -637,7 +636,7 @@@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> 
          let source_map_bytes = self.position() - i;
  
          let attrs = tcx.hir().krate_attrs();
 -        let has_default_lib_allocator = attr::contains_name(&attrs, sym::default_lib_allocator);
 +        let has_default_lib_allocator = tcx.sess.contains_name(&attrs, sym::default_lib_allocator);
  
          let root = self.lazy(CrateRoot {
              name: tcx.crate_name(LOCAL_CRATE),
              } else {
                  None
              },
 -            compiler_builtins: attr::contains_name(&attrs, sym::compiler_builtins),
 -            needs_allocator: attr::contains_name(&attrs, sym::needs_allocator),
 -            needs_panic_runtime: attr::contains_name(&attrs, sym::needs_panic_runtime),
 -            no_builtins: attr::contains_name(&attrs, sym::no_builtins),
 -            panic_runtime: attr::contains_name(&attrs, sym::panic_runtime),
 -            profiler_runtime: attr::contains_name(&attrs, sym::profiler_runtime),
 +            compiler_builtins: tcx.sess.contains_name(&attrs, sym::compiler_builtins),
 +            needs_allocator: tcx.sess.contains_name(&attrs, sym::needs_allocator),
 +            needs_panic_runtime: tcx.sess.contains_name(&attrs, sym::needs_panic_runtime),
 +            no_builtins: tcx.sess.contains_name(&attrs, sym::no_builtins),
 +            panic_runtime: tcx.sess.contains_name(&attrs, sym::panic_runtime),
 +            profiler_runtime: tcx.sess.contains_name(&attrs, sym::profiler_runtime),
              symbol_mangling_version: tcx.sess.opts.debugging_opts.symbol_mangling_version,
  
              crate_deps,
@@@ -1133,11 -1138,8 +1137,11 @@@ impl EncodeContext<'a, 'tcx> 
          debug!("EntryBuilder::encode_mir({:?})", def_id);
          if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) {
              record!(self.tables.mir[def_id.to_def_id()] <- self.tcx.optimized_mir(def_id));
 -            record!(self.tables.unused_generic_params[def_id.to_def_id()] <-
 -                    self.tcx.unused_generic_params(def_id));
 +
 +            let unused = self.tcx.unused_generic_params(def_id);
 +            if !unused.is_empty() {
 +                record!(self.tables.unused_generic_params[def_id.to_def_id()] <- unused);
 +            }
          }
      }
  
              .into_iter()
              .map(|(trait_def_id, mut impls)| {
                  // Bring everything into deterministic order for hashing
 -                impls.sort_by_cached_key(|&index| {
 +                impls.sort_by_cached_key(|&(index, _)| {
                      tcx.hir().definitions().def_path_hash(LocalDefId { local_def_index: index })
                  });
  
@@@ -1851,7 -1853,7 +1855,7 @@@ impl EncodeContext<'a, 'tcx> 
  
  struct ImplVisitor<'tcx> {
      tcx: TyCtxt<'tcx>,
 -    impls: FxHashMap<DefId, Vec<DefIndex>>,
 +    impls: FxHashMap<DefId, Vec<(DefIndex, Option<ty::fast_reject::SimplifiedType>)>>,
  }
  
  impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'tcx> {
          if let hir::ItemKind::Impl { .. } = item.kind {
              let impl_id = self.tcx.hir().local_def_id(item.hir_id);
              if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_id.to_def_id()) {
 -                self.impls.entry(trait_ref.def_id).or_default().push(impl_id.local_def_index);
 +                let simplified_self_ty =
 +                    ty::fast_reject::simplify_type(self.tcx, trait_ref.self_ty(), false);
 +
 +                self.impls
 +                    .entry(trait_ref.def_id)
 +                    .or_default()
 +                    .push((impl_id.local_def_index, simplified_self_ty));
              }
          }
      }
index 4e21d566071ef609da18d9c34dcf87fb7a452b01,74dc904b6e614b3df65fec50fa932801917d4de8..f52b2195c2f6e25d6bc797e24511808c43a08374
@@@ -80,6 -80,8 +80,6 @@@ pub enum Transparency 
      Opaque,
  }
  
 -pub(crate) const NUM_TRANSPARENCIES: usize = 3;
 -
  impl ExpnId {
      pub fn fresh(expn_data: Option<ExpnData>) -> Self {
          HygieneData::with(|data| data.fresh_expn(expn_data))
@@@ -616,11 -618,6 +616,11 @@@ impl SyntaxContext 
          HygieneData::with(|data| data.expn_data(data.outer_expn(self)).clone())
      }
  
 +    #[inline]
 +    pub fn outer_mark(self) -> (ExpnId, Transparency) {
 +        HygieneData::with(|data| data.outer_mark(self))
 +    }
 +
      #[inline]
      pub fn outer_mark_with_data(self) -> (ExpnId, Transparency, ExpnData) {
          HygieneData::with(|data| {
@@@ -670,6 -667,7 +670,6 @@@ pub struct ExpnData 
      /// The kind of this expansion - macro or compiler desugaring.
      pub kind: ExpnKind,
      /// The expansion that produced this expansion.
 -    #[stable_hasher(ignore)]
      pub parent: ExpnId,
      /// The location of the actual macro invocation or syntax sugar , e.g.
      /// `let x = foo!();` or `if let Some(y) = x {}`
@@@ -1032,7 -1030,7 +1032,7 @@@ pub fn decode_expn_id
          drop(expns);
          expn_id
      });
 -    return Ok(expn_id);
 +    Ok(expn_id)
  }
  
  // Decodes `SyntaxContext`, using the provided `HygieneDecodeContext`
@@@ -1105,7 -1103,7 +1105,7 @@@ pub fn decode_syntax_context
          assert_eq!(dummy.dollar_crate_name, kw::Invalid);
      });
  
 -    return Ok(new_ctxt);
 +    Ok(new_ctxt)
  }
  
  pub fn num_syntax_ctxts() -> usize {
@@@ -1172,13 -1170,30 +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)
          }