summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_metadata/src/rmeta/encoder.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_metadata/src/rmeta/encoder.rs')
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs191
1 files changed, 86 insertions, 105 deletions
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 2042863d1..ad3fea65e 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1,49 +1,37 @@
-use crate::errors::{FailCreateFileEncoder, FailSeekFile, FailWriteFile};
-use crate::rmeta::def_path_hash_map::DefPathHashMapRef;
-use crate::rmeta::table::TableBuilder;
+use crate::errors::{FailCreateFileEncoder, FailWriteFile};
use crate::rmeta::*;
-use rustc_ast::expand::StrippedCfgItem;
use rustc_ast::Attribute;
use rustc_data_structures::fingerprint::Fingerprint;
-use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
+use rustc_data_structures::fx::FxIndexSet;
use rustc_data_structures::memmap::{Mmap, MmapMut};
use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher};
use rustc_data_structures::sync::{join, par_for_each_in, Lrc};
use rustc_data_structures::temp_dir::MaybeTempDir;
use rustc_hir as hir;
-use rustc_hir::def::DefKind;
-use rustc_hir::def_id::{
- CrateNum, DefId, DefIndex, LocalDefId, LocalDefIdSet, CRATE_DEF_ID, CRATE_DEF_INDEX,
- LOCAL_CRATE,
-};
+use rustc_hir::def_id::{LocalDefId, LocalDefIdSet, CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc_hir::definitions::DefPathData;
-use rustc_hir::lang_items::LangItem;
use rustc_hir_pretty::id_to_string;
-use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
use rustc_middle::middle::dependency_format::Linkage;
-use rustc_middle::middle::exported_symbols::{
- metadata_symbol_name, ExportedSymbol, SymbolExportInfo,
-};
+use rustc_middle::middle::exported_symbols::metadata_symbol_name;
use rustc_middle::mir::interpret;
use rustc_middle::query::LocalCrate;
use rustc_middle::query::Providers;
use rustc_middle::traits::specialization_graph;
use rustc_middle::ty::codec::TyEncoder;
-use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams};
-use rustc_middle::ty::{self, AssocItemContainer, SymbolName, Ty, TyCtxt};
+use rustc_middle::ty::fast_reject::{self, TreatParams};
+use rustc_middle::ty::{AssocItemContainer, SymbolName};
use rustc_middle::util::common::to_readable_str;
use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder};
use rustc_session::config::{CrateType, OptLevel};
-use rustc_session::cstore::{ForeignModule, LinkagePreference, NativeLib};
-use rustc_span::hygiene::{ExpnIndex, HygieneEncodeContext, MacroKind};
-use rustc_span::symbol::{sym, Symbol};
-use rustc_span::{self, ExternalSource, FileName, SourceFile, Span, SpanData, SyntaxContext};
+use rustc_span::hygiene::HygieneEncodeContext;
+use rustc_span::symbol::sym;
+use rustc_span::{ExternalSource, FileName, SourceFile, SpanData, SyntaxContext};
use std::borrow::Borrow;
use std::collections::hash_map::Entry;
+use std::fs::File;
use std::hash::Hash;
use std::io::{Read, Seek, Write};
-use std::num::NonZeroUsize;
use std::path::{Path, PathBuf};
pub(super) struct EncodeContext<'a, 'tcx> {
@@ -159,7 +147,7 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for ExpnIndex {
impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for SyntaxContext {
fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
- rustc_span::hygiene::raw_encode_syntax_context(*self, &s.hygiene_ctxt, s);
+ rustc_span::hygiene::raw_encode_syntax_context(*self, s.hygiene_ctxt, s);
}
}
@@ -656,10 +644,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
let debugger_visualizers =
stat!("debugger-visualizers", || self.encode_debugger_visualizers());
- // Encode exported symbols info. This is prefetched in `encode_metadata` so we encode
- // this as late as possible to give the prefetching as much time as possible to complete.
+ // Encode exported symbols info. This is prefetched in `encode_metadata`.
let exported_symbols = stat!("exported-symbols", || {
- self.encode_exported_symbols(&tcx.exported_symbols(LOCAL_CRATE))
+ self.encode_exported_symbols(tcx.exported_symbols(LOCAL_CRATE))
});
// Encode the hygiene data.
@@ -693,15 +680,15 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
has_global_allocator: tcx.has_global_allocator(LOCAL_CRATE),
has_alloc_error_handler: tcx.has_alloc_error_handler(LOCAL_CRATE),
has_panic_handler: tcx.has_panic_handler(LOCAL_CRATE),
- has_default_lib_allocator: attr::contains_name(&attrs, sym::default_lib_allocator),
+ has_default_lib_allocator: attr::contains_name(attrs, sym::default_lib_allocator),
proc_macro_data,
debugger_visualizers,
- 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: 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),
symbol_mangling_version: tcx.sess.opts.get_symbol_mangling_version(),
crate_deps,
@@ -855,8 +842,7 @@ fn should_encode_span(def_kind: DefKind) -> bool {
| DefKind::OpaqueTy
| DefKind::Field
| DefKind::Impl { .. }
- | DefKind::Closure
- | DefKind::Coroutine => true,
+ | DefKind::Closure => true,
DefKind::ForeignMod | DefKind::GlobalAsm => false,
}
}
@@ -896,8 +882,7 @@ fn should_encode_attrs(def_kind: DefKind) -> bool {
| DefKind::InlineConst
| DefKind::OpaqueTy
| DefKind::LifetimeParam
- | DefKind::GlobalAsm
- | DefKind::Coroutine => false,
+ | DefKind::GlobalAsm => false,
}
}
@@ -932,8 +917,7 @@ fn should_encode_expn_that_defined(def_kind: DefKind) -> bool {
| DefKind::Field
| DefKind::LifetimeParam
| DefKind::GlobalAsm
- | DefKind::Closure
- | DefKind::Coroutine => false,
+ | DefKind::Closure => false,
}
}
@@ -968,7 +952,6 @@ fn should_encode_visibility(def_kind: DefKind) -> bool {
| DefKind::GlobalAsm
| DefKind::Impl { .. }
| DefKind::Closure
- | DefKind::Coroutine
| DefKind::ExternCrate => false,
}
}
@@ -1004,7 +987,6 @@ fn should_encode_stability(def_kind: DefKind) -> bool {
| DefKind::InlineConst
| DefKind::GlobalAsm
| DefKind::Closure
- | DefKind::Coroutine
| DefKind::ExternCrate => false,
}
}
@@ -1047,6 +1029,8 @@ fn should_encode_mir(
| DefKind::AssocConst
| DefKind::Static(..)
| DefKind::Const => (true, false),
+ // Coroutines require optimized MIR to compute layout.
+ DefKind::Closure if tcx.is_coroutine(def_id.to_def_id()) => (false, true),
// Full-fledged functions + closures
DefKind::AssocFn | DefKind::Fn | DefKind::Closure => {
let generics = tcx.generics_of(def_id);
@@ -1060,8 +1044,6 @@ fn should_encode_mir(
|| tcx.is_const_default_method(def_id.to_def_id());
(is_const_fn, opt)
}
- // Coroutines require optimized MIR to compute layout.
- DefKind::Coroutine => (false, true),
// The others don't have MIR.
_ => (false, false),
}
@@ -1097,7 +1079,6 @@ fn should_encode_variances<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, def_kind: Def
| DefKind::InlineConst
| DefKind::GlobalAsm
| DefKind::Closure
- | DefKind::Coroutine
| DefKind::ExternCrate => false,
DefKind::TyAlias => tcx.type_alias_is_lazy(def_id),
}
@@ -1126,8 +1107,7 @@ fn should_encode_generics(def_kind: DefKind) -> bool {
| DefKind::Impl { .. }
| DefKind::Field
| DefKind::TyParam
- | DefKind::Closure
- | DefKind::Coroutine => true,
+ | DefKind::Closure => true,
DefKind::Mod
| DefKind::ForeignMod
| DefKind::ConstParam
@@ -1156,7 +1136,6 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) ->
| DefKind::AssocFn
| DefKind::AssocConst
| DefKind::Closure
- | DefKind::Coroutine
| DefKind::ConstParam
| DefKind::AnonConst
| DefKind::InlineConst => true,
@@ -1165,7 +1144,7 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) ->
let origin = tcx.opaque_type_origin(def_id);
if let hir::OpaqueTyOrigin::FnReturn(fn_def_id)
| hir::OpaqueTyOrigin::AsyncFn(fn_def_id) = origin
- && let hir::Node::TraitItem(trait_item) = tcx.hir().get_by_def_id(fn_def_id)
+ && let hir::Node::TraitItem(trait_item) = tcx.hir_node_by_def_id(fn_def_id)
&& let (_, hir::TraitFn::Required(..)) = trait_item.expect_fn()
{
false
@@ -1182,7 +1161,7 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) ->
}
}
DefKind::TyParam => {
- let hir::Node::GenericParam(param) = tcx.hir().get_by_def_id(def_id) else { bug!() };
+ let hir::Node::GenericParam(param) = tcx.hir_node_by_def_id(def_id) else { bug!() };
let hir::GenericParamKind::Type { default, .. } = param.kind else { bug!() };
default.is_some()
}
@@ -1217,7 +1196,6 @@ fn should_encode_fn_sig(def_kind: DefKind) -> bool {
| DefKind::Impl { .. }
| DefKind::AssocConst
| DefKind::Closure
- | DefKind::Coroutine
| DefKind::ConstParam
| DefKind::AnonConst
| DefKind::InlineConst
@@ -1256,7 +1234,6 @@ fn should_encode_constness(def_kind: DefKind) -> bool {
| DefKind::OpaqueTy
| DefKind::Impl { of_trait: false }
| DefKind::ForeignTy
- | DefKind::Coroutine
| DefKind::ConstParam
| DefKind::InlineConst
| DefKind::AssocTy
@@ -1291,7 +1268,6 @@ fn should_encode_const(def_kind: DefKind) -> bool {
| DefKind::Impl { .. }
| DefKind::AssocFn
| DefKind::Closure
- | DefKind::Coroutine
| DefKind::ConstParam
| DefKind::AssocTy
| DefKind::TyParam
@@ -1353,9 +1329,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
for local_id in tcx.iter_local_def_id() {
let def_id = local_id.to_def_id();
- let def_kind = tcx.opt_def_kind(local_id);
- let Some(def_kind) = def_kind else { continue };
- self.tables.opt_def_kind.set_some(def_id.index, def_kind);
+ let def_kind = tcx.def_kind(local_id);
+ self.tables.def_kind.set_some(def_id.index, def_kind);
if should_encode_span(def_kind) {
let def_span = tcx.def_span(local_id);
record!(self.tables.def_span[def_id] <- def_span);
@@ -1392,7 +1367,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
if should_encode_fn_sig(def_kind) {
record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
}
- if should_encode_generics(def_kind) {
+ // FIXME: Some anonymous constants produced by `#[rustc_legacy_const_generics]`
+ // do not have corresponding HIR nodes, so some queries usually making sense for
+ // anonymous constants will not work on them and panic. It's not clear whether it
+ // can cause any observable issues or not.
+ let anon_const_without_hir = def_kind == DefKind::AnonConst
+ && tcx.opt_hir_node(tcx.local_def_id_to_hir_id(local_id)).is_none();
+ if should_encode_generics(def_kind) && !anon_const_without_hir {
let g = tcx.generics_of(def_id);
record!(self.tables.generics_of[def_id] <- g);
record!(self.tables.explicit_predicates_of[def_id] <- self.tcx.explicit_predicates_of(def_id));
@@ -1406,7 +1387,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
}
}
}
- if should_encode_type(tcx, local_id, def_kind) {
+ if should_encode_type(tcx, local_id, def_kind) && !anon_const_without_hir {
record!(self.tables.type_of[def_id] <- self.tcx.type_of(def_id));
}
if should_encode_constness(def_kind) {
@@ -1446,8 +1427,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
self.encode_info_for_assoc_item(def_id);
}
}
- if let DefKind::Coroutine = def_kind {
- let data = self.tcx.coroutine_kind(def_id).unwrap();
+ if def_kind == DefKind::Closure
+ && let Some(data) = self.tcx.coroutine_kind(def_id)
+ {
record!(self.tables.coroutine_kind[def_id] <- data);
}
if let DefKind::Enum | DefKind::Struct | DefKind::Union = def_kind {
@@ -1629,7 +1611,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
record!(self.tables.closure_saved_names_of_captured_variables[def_id.to_def_id()]
<- tcx.closure_saved_names_of_captured_variables(def_id));
- if let DefKind::Coroutine = self.tcx.def_kind(def_id)
+ if self.tcx.is_coroutine(def_id.to_def_id())
&& let Some(witnesses) = tcx.mir_coroutine_witnesses(def_id)
{
record!(self.tables.mir_coroutine_witnesses[def_id.to_def_id()] <- witnesses);
@@ -1656,7 +1638,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
}
record!(self.tables.promoted_mir[def_id.to_def_id()] <- tcx.promoted_mir(def_id));
- if let DefKind::Coroutine = self.tcx.def_kind(def_id)
+ if self.tcx.is_coroutine(def_id.to_def_id())
&& let Some(witnesses) = tcx.mir_coroutine_witnesses(def_id)
{
record!(self.tables.mir_coroutine_witnesses[def_id.to_def_id()] <- witnesses);
@@ -1727,9 +1709,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
fn encode_info_for_macro(&mut self, def_id: LocalDefId) {
let tcx = self.tcx;
- let hir::ItemKind::Macro(ref macro_def, _) = tcx.hir().expect_item(def_id).kind else {
- bug!()
- };
+ let hir::ItemKind::Macro(macro_def, _) = tcx.hir().expect_item(def_id).kind else { bug!() };
self.tables.is_macro_rules.set(def_id.local_def_index, macro_def.macro_rules);
record!(self.tables.macro_definition[def_id.to_def_id()] <- &*macro_def.body);
}
@@ -1786,7 +1766,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
self.tables.proc_macro_quoted_spans.set_some(i, span);
}
- self.tables.opt_def_kind.set_some(LOCAL_CRATE.as_def_id().index, DefKind::Mod);
+ self.tables.def_kind.set_some(LOCAL_CRATE.as_def_id().index, DefKind::Mod);
record!(self.tables.def_span[LOCAL_CRATE.as_def_id()] <- tcx.def_span(LOCAL_CRATE.as_def_id()));
self.encode_attrs(LOCAL_CRATE.as_def_id().expect_local());
let vis = tcx.local_visibility(CRATE_DEF_ID).map_id(|def_id| def_id.local_def_index);
@@ -1807,7 +1787,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
// so we manually encode just the information that we need
for &proc_macro in &tcx.resolutions(()).proc_macros {
let id = proc_macro;
- let proc_macro = hir.local_def_id_to_hir_id(proc_macro);
+ let proc_macro = tcx.local_def_id_to_hir_id(proc_macro);
let mut name = hir.name(proc_macro);
let span = hir.span(proc_macro);
// Proc-macros may have attributes like `#[allow_internal_unstable]`,
@@ -1834,7 +1814,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
def_key.disambiguated_data.data = DefPathData::MacroNs(name);
let def_id = id.to_def_id();
- self.tables.opt_def_kind.set_some(def_id.index, DefKind::Macro(macro_kind));
+ self.tables.def_kind.set_some(def_id.index, DefKind::Macro(macro_kind));
self.tables.proc_macro.set_some(def_id.index, macro_kind);
self.encode_attrs(id);
record!(self.tables.def_keys[def_id] <- def_key);
@@ -1902,10 +1882,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
self.lazy_array(deps.iter().map(|(_, dep)| dep))
}
- fn encode_lib_features(&mut self) -> LazyArray<(Symbol, Option<Symbol>)> {
+ fn encode_lib_features(&mut self) -> LazyArray<(Symbol, FeatureStability)> {
empty_proc_macro!(self);
let tcx = self.tcx;
- let lib_features = tcx.lib_features(());
+ let lib_features = tcx.lib_features(LOCAL_CRATE);
self.lazy_array(lib_features.to_vec())
}
@@ -2198,27 +2178,19 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
// there's no need to do dep-graph tracking for any of it.
tcx.dep_graph.assert_ignored();
- join(
- || encode_metadata_impl(tcx, path),
- || {
- if tcx.sess.threads() == 1 {
- return;
- }
- // Prefetch some queries used by metadata encoding.
- // This is not necessary for correctness, but is only done for performance reasons.
- // It can be removed if it turns out to cause trouble or be detrimental to performance.
- join(|| prefetch_mir(tcx), || tcx.exported_symbols(LOCAL_CRATE));
- },
- );
-}
+ if tcx.sess.threads() != 1 {
+ // Prefetch some queries used by metadata encoding.
+ // This is not necessary for correctness, but is only done for performance reasons.
+ // It can be removed if it turns out to cause trouble or be detrimental to performance.
+ join(|| prefetch_mir(tcx), || tcx.exported_symbols(LOCAL_CRATE));
+ }
-fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) {
let mut encoder = opaque::FileEncoder::new(path)
.unwrap_or_else(|err| tcx.sess.emit_fatal(FailCreateFileEncoder { err }));
encoder.emit_raw_bytes(METADATA_HEADER);
// Will be filled with the root position after encoding everything.
- encoder.emit_raw_bytes(&[0, 0, 0, 0]);
+ encoder.emit_raw_bytes(&0u64.to_le_bytes());
let source_map_files = tcx.sess.source_map().files();
let source_file_cache = (source_map_files[0].clone(), 0);
@@ -2251,29 +2223,34 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) {
// culminating in the `CrateRoot` which points to all of it.
let root = ecx.encode_crate_root();
- ecx.opaque.flush();
+ // Make sure we report any errors from writing to the file.
+ // If we forget this, compilation can succeed with an incomplete rmeta file,
+ // causing an ICE when the rmeta file is read by another compilation.
+ if let Err((path, err)) = ecx.opaque.finish() {
+ tcx.sess.emit_err(FailWriteFile { path: &path, err });
+ }
+
+ let file = ecx.opaque.file();
+ if let Err(err) = encode_root_position(file, root.position.get()) {
+ tcx.sess.emit_err(FailWriteFile { path: ecx.opaque.path(), err });
+ }
+
+ // Record metadata size for self-profiling
+ tcx.prof.artifact_size("crate_metadata", "crate_metadata", file.metadata().unwrap().len());
+}
- let mut file = ecx.opaque.file();
+fn encode_root_position(mut file: &File, pos: usize) -> Result<(), std::io::Error> {
// We will return to this position after writing the root position.
let pos_before_seek = file.stream_position().unwrap();
// Encode the root position.
let header = METADATA_HEADER.len();
- file.seek(std::io::SeekFrom::Start(header as u64))
- .unwrap_or_else(|err| tcx.sess.emit_fatal(FailSeekFile { err }));
- let pos = root.position.get();
- file.write_all(&[(pos >> 24) as u8, (pos >> 16) as u8, (pos >> 8) as u8, (pos >> 0) as u8])
- .unwrap_or_else(|err| tcx.sess.emit_fatal(FailWriteFile { err }));
+ file.seek(std::io::SeekFrom::Start(header as u64))?;
+ file.write_all(&pos.to_le_bytes())?;
// Return to the position where we are before writing the root position.
- file.seek(std::io::SeekFrom::Start(pos_before_seek)).unwrap();
-
- // Record metadata size for self-profiling
- tcx.prof.artifact_size(
- "crate_metadata",
- "crate_metadata",
- file.metadata().unwrap().len() as u64,
- );
+ file.seek(std::io::SeekFrom::Start(pos_before_seek))?;
+ Ok(())
}
pub fn provide(providers: &mut Providers) {
@@ -2396,8 +2373,10 @@ pub fn rendered_const<'tcx>(tcx: TyCtxt<'tcx>, body: hir::BodyId) -> String {
// * character escapes
//
// FIXME: This passes through `-/*spacer*/0` verbatim.
- Literal if !value.span.from_expansion()
- && let Ok(snippet) = tcx.sess.source_map().span_to_snippet(value.span) => {
+ Literal
+ if !value.span.from_expansion()
+ && let Ok(snippet) = tcx.sess.source_map().span_to_snippet(value.span) =>
+ {
snippet
}
@@ -2408,10 +2387,12 @@ pub fn rendered_const<'tcx>(tcx: TyCtxt<'tcx>, body: hir::BodyId) -> String {
// FIXME: Omit the curly braces if the enclosing expression is an array literal
// with a repeated element (an `ExprKind::Repeat`) as in such case it
// would not actually need any disambiguation.
- Complex => if tcx.def_kind(hir.body_owner_def_id(body).to_def_id()) == DefKind::AnonConst {
- "{ _ }".to_owned()
- } else {
- "_".to_owned()
+ Complex => {
+ if tcx.def_kind(hir.body_owner_def_id(body).to_def_id()) == DefKind::AnonConst {
+ "{ _ }".to_owned()
+ } else {
+ "_".to_owned()
+ }
}
}
}