diff options
Diffstat (limited to 'compiler/rustc_metadata/src/rmeta/encoder.rs')
-rw-r--r-- | compiler/rustc_metadata/src/rmeta/encoder.rs | 191 |
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() + } } } } |