diff options
Diffstat (limited to '')
-rw-r--r-- | compiler/rustc_metadata/src/creader.rs | 56 | ||||
-rw-r--r-- | compiler/rustc_metadata/src/dependency_format.rs | 79 | ||||
-rw-r--r-- | compiler/rustc_metadata/src/errors.rs | 679 | ||||
-rw-r--r-- | compiler/rustc_metadata/src/fs.rs | 25 | ||||
-rw-r--r-- | compiler/rustc_metadata/src/lib.rs | 11 | ||||
-rw-r--r-- | compiler/rustc_metadata/src/locator.rs | 329 | ||||
-rw-r--r-- | compiler/rustc_metadata/src/native_libs.rs | 346 | ||||
-rw-r--r-- | compiler/rustc_metadata/src/rmeta/decoder.rs | 402 | ||||
-rw-r--r-- | compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs | 47 | ||||
-rw-r--r-- | compiler/rustc_metadata/src/rmeta/encoder.rs | 683 | ||||
-rw-r--r-- | compiler/rustc_metadata/src/rmeta/mod.rs | 54 | ||||
-rw-r--r-- | compiler/rustc_metadata/src/rmeta/table.rs | 19 |
12 files changed, 1675 insertions, 1055 deletions
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 708d0b1fd..cfcceecbe 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -1,5 +1,9 @@ //! Validates all used crates and extern libraries and loads their metadata +use crate::errors::{ + ConflictingGlobalAlloc, CrateNotPanicRuntime, GlobalAllocRequired, NoMultipleGlobalAlloc, + NoPanicStrategy, NoTransitiveNeedsDep, NotProfilerRuntime, ProfilerBuiltinsNeedsCore, +}; use crate::locator::{CrateError, CrateLocator, CratePaths}; use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob}; @@ -29,7 +33,6 @@ use proc_macro::bridge::client::ProcMacro; use std::ops::Fn; use std::path::Path; use std::{cmp, env}; -use tracing::{debug, info}; #[derive(Clone)] pub struct CStore { @@ -263,7 +266,7 @@ impl<'a> CrateLoader<'a> { fn existing_match(&self, name: Symbol, hash: Option<Svh>, kind: PathKind) -> Option<CrateNum> { for (cnum, data) in self.cstore.iter_crate_data() { if data.name() != name { - tracing::trace!("{} did not match {}", data.name(), name); + trace!("{} did not match {}", data.name(), name); continue; } @@ -746,15 +749,10 @@ impl<'a> CrateLoader<'a> { // Sanity check the loaded crate to ensure it is indeed a panic runtime // and the panic strategy is indeed what we thought it was. if !data.is_panic_runtime() { - self.sess.err(&format!("the crate `{}` is not a panic runtime", name)); + self.sess.emit_err(CrateNotPanicRuntime { crate_name: name }); } if data.required_panic_strategy() != Some(desired_strategy) { - self.sess.err(&format!( - "the crate `{}` does not have the panic \ - strategy `{}`", - name, - desired_strategy.desc() - )); + self.sess.emit_err(NoPanicStrategy { crate_name: name, strategy: desired_strategy }); } self.cstore.injected_panic_runtime = Some(cnum); @@ -774,10 +772,7 @@ impl<'a> CrateLoader<'a> { let name = Symbol::intern(&self.sess.opts.unstable_opts.profiler_runtime); if name == sym::profiler_builtins && self.sess.contains_name(&krate.attrs, sym::no_core) { - self.sess.err( - "`profiler_builtins` crate (required by compiler options) \ - is not compatible with crate attribute `#![no_core]`", - ); + self.sess.emit_err(ProfilerBuiltinsNeedsCore); } let Some(cnum) = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit) else { return; }; @@ -785,18 +780,14 @@ impl<'a> CrateLoader<'a> { // Sanity check the loaded crate to ensure it is indeed a profiler runtime if !data.is_profiler_runtime() { - self.sess.err(&format!("the crate `{}` is not a profiler runtime", name)); + self.sess.emit_err(NotProfilerRuntime { crate_name: name }); } } fn inject_allocator_crate(&mut self, krate: &ast::Crate) { self.cstore.has_global_allocator = match &*global_allocator_spans(&self.sess, krate) { [span1, span2, ..] => { - self.sess - .struct_span_err(*span2, "cannot define multiple global allocators") - .span_label(*span2, "cannot define a new global allocator") - .span_label(*span1, "previous global allocator defined here") - .emit(); + self.sess.emit_err(NoMultipleGlobalAlloc { span2: *span2, span1: *span1 }); true } spans => !spans.is_empty(), @@ -832,11 +823,10 @@ impl<'a> CrateLoader<'a> { if data.has_global_allocator() { match global_allocator { Some(other_crate) => { - self.sess.err(&format!( - "the `#[global_allocator]` in {} conflicts with global allocator in: {}", - other_crate, - data.name() - )); + self.sess.emit_err(ConflictingGlobalAlloc { + crate_name: data.name(), + other_crate_name: other_crate, + }); } None => global_allocator = Some(data.name()), } @@ -855,10 +845,7 @@ impl<'a> CrateLoader<'a> { if !self.sess.contains_name(&krate.attrs, sym::default_lib_allocator) && !self.cstore.iter_crate_data().any(|(_, data)| data.has_default_lib_allocator()) { - self.sess.err( - "no global memory allocator found but one is required; link to std or add \ - `#[global_allocator]` to a static item that implements the GlobalAlloc trait", - ); + self.sess.emit_err(GlobalAllocRequired); } self.cstore.allocator_kind = Some(AllocatorKind::Default); } @@ -882,14 +869,11 @@ impl<'a> CrateLoader<'a> { for dep in self.cstore.crate_dependencies_in_reverse_postorder(krate) { let data = self.cstore.get_crate_data(dep); if needs_dep(&data) { - self.sess.err(&format!( - "the crate `{}` cannot depend \ - on a crate that needs {}, but \ - it depends on `{}`", - self.cstore.get_crate_data(krate).name(), - what, - data.name() - )); + self.sess.emit_err(NoTransitiveNeedsDep { + crate_name: self.cstore.get_crate_data(krate).name(), + needs_crate_name: what, + deps_crate_name: data.name(), + }); } } diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs index b765c34f8..6112ec9e4 100644 --- a/compiler/rustc_metadata/src/dependency_format.rs +++ b/compiler/rustc_metadata/src/dependency_format.rs @@ -52,6 +52,10 @@ //! than finding a number of solutions (there are normally quite a few). use crate::creader::CStore; +use crate::errors::{ + BadPanicStrategy, CrateDepMultiple, IncompatiblePanicInDropStrategy, LibRequired, + RequiredPanicStrategy, RlibRequired, TwoPanicRuntimes, +}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::CrateNum; @@ -136,11 +140,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { if src.rlib.is_some() { continue; } - sess.err(&format!( - "crate `{}` required to be available in rlib format, \ - but was not found in this form", - tcx.crate_name(cnum) - )); + sess.emit_err(RlibRequired { crate_name: tcx.crate_name(cnum) }); } return Vec::new(); } @@ -158,11 +158,11 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { let name = tcx.crate_name(cnum); let src = tcx.used_crate_source(cnum); if src.dylib.is_some() { - tracing::info!("adding dylib: {}", name); + info!("adding dylib: {}", name); add_library(tcx, cnum, RequireDynamic, &mut formats); let deps = tcx.dylib_dependency_formats(cnum); for &(depnum, style) in deps.iter() { - tracing::info!("adding {:?}: {}", style, tcx.crate_name(depnum)); + info!("adding {:?}: {}", style, tcx.crate_name(depnum)); add_library(tcx, depnum, style, &mut formats); } } @@ -190,7 +190,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { && tcx.dep_kind(cnum) == CrateDepKind::Explicit { assert!(src.rlib.is_some() || src.rmeta.is_some()); - tracing::info!("adding staticlib: {}", tcx.crate_name(cnum)); + info!("adding staticlib: {}", tcx.crate_name(cnum)); add_library(tcx, cnum, RequireStatic, &mut formats); ret[cnum.as_usize() - 1] = Linkage::Static; } @@ -224,12 +224,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { Linkage::Static => "rlib", _ => "dylib", }; - sess.err(&format!( - "crate `{}` required to be available in {} format, \ - but was not found in this form", - tcx.crate_name(cnum), - kind - )); + sess.emit_err(LibRequired { crate_name: tcx.crate_name(cnum), kind: kind }); } } } @@ -253,17 +248,7 @@ fn add_library( // This error is probably a little obscure, but I imagine that it // can be refined over time. if link2 != link || link == RequireStatic { - tcx.sess - .struct_err(&format!( - "cannot satisfy dependencies so `{}` only \ - shows up once", - tcx.crate_name(cnum) - )) - .help( - "having upstream crates all available in one format \ - will likely make this go away", - ) - .emit(); + tcx.sess.emit_err(CrateDepMultiple { crate_name: tcx.crate_name(cnum) }); } } None => { @@ -360,11 +345,7 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) { if let Some((prev, _)) = panic_runtime { let prev_name = tcx.crate_name(prev); let cur_name = tcx.crate_name(cnum); - sess.err(&format!( - "cannot link together two \ - panic runtimes: {} and {}", - prev_name, cur_name - )); + sess.emit_err(TwoPanicRuntimes { prev_name, cur_name }); } panic_runtime = Some(( cnum, @@ -384,13 +365,10 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) { // First up, validate that our selected panic runtime is indeed exactly // our same strategy. if found_strategy != desired_strategy { - sess.err(&format!( - "the linked panic runtime `{}` is \ - not compiled with this crate's \ - panic strategy `{}`", - tcx.crate_name(runtime_cnum), - desired_strategy.desc() - )); + sess.emit_err(BadPanicStrategy { + runtime: tcx.crate_name(runtime_cnum), + strategy: desired_strategy, + }); } // Next up, verify that all other crates are compatible with this panic @@ -407,28 +385,19 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) { } if let Some(found_strategy) = tcx.required_panic_strategy(cnum) && desired_strategy != found_strategy { - sess.err(&format!( - "the crate `{}` requires \ - panic strategy `{}` which is \ - incompatible with this crate's \ - strategy of `{}`", - tcx.crate_name(cnum), - found_strategy.desc(), - desired_strategy.desc() - )); + sess.emit_err(RequiredPanicStrategy { + crate_name: tcx.crate_name(cnum), + found_strategy, + desired_strategy}); } let found_drop_strategy = tcx.panic_in_drop_strategy(cnum); if tcx.sess.opts.unstable_opts.panic_in_drop != found_drop_strategy { - sess.err(&format!( - "the crate `{}` is compiled with the \ - panic-in-drop strategy `{}` which is \ - incompatible with this crate's \ - strategy of `{}`", - tcx.crate_name(cnum), - found_drop_strategy.desc(), - tcx.sess.opts.unstable_opts.panic_in_drop.desc() - )); + sess.emit_err(IncompatiblePanicInDropStrategy { + crate_name: tcx.crate_name(cnum), + found_strategy: found_drop_strategy, + desired_strategy: tcx.sess.opts.unstable_opts.panic_in_drop, + }); } } } diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs new file mode 100644 index 000000000..7d63fad32 --- /dev/null +++ b/compiler/rustc_metadata/src/errors.rs @@ -0,0 +1,679 @@ +use std::{ + io::Error, + path::{Path, PathBuf}, +}; + +use rustc_errors::{error_code, ErrorGuaranteed}; +use rustc_macros::SessionDiagnostic; +use rustc_session::{config, SessionDiagnostic}; +use rustc_span::{sym, Span, Symbol}; +use rustc_target::spec::{PanicStrategy, TargetTriple}; + +use crate::locator::CrateFlavor; + +#[derive(SessionDiagnostic)] +#[diag(metadata::rlib_required)] +pub struct RlibRequired { + pub crate_name: Symbol, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::lib_required)] +pub struct LibRequired<'a> { + pub crate_name: Symbol, + pub kind: &'a str, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::crate_dep_multiple)] +#[help] +pub struct CrateDepMultiple { + pub crate_name: Symbol, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::two_panic_runtimes)] +pub struct TwoPanicRuntimes { + pub prev_name: Symbol, + pub cur_name: Symbol, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::bad_panic_strategy)] +pub struct BadPanicStrategy { + pub runtime: Symbol, + pub strategy: PanicStrategy, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::required_panic_strategy)] +pub struct RequiredPanicStrategy { + pub crate_name: Symbol, + pub found_strategy: PanicStrategy, + pub desired_strategy: PanicStrategy, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::incompatible_panic_in_drop_strategy)] +pub struct IncompatiblePanicInDropStrategy { + pub crate_name: Symbol, + pub found_strategy: PanicStrategy, + pub desired_strategy: PanicStrategy, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::multiple_names_in_link)] +pub struct MultipleNamesInLink { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::multiple_kinds_in_link)] +pub struct MultipleKindsInLink { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::link_name_form)] +pub struct LinkNameForm { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::link_kind_form)] +pub struct LinkKindForm { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::link_modifiers_form)] +pub struct LinkModifiersForm { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::link_cfg_form)] +pub struct LinkCfgForm { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::wasm_import_form)] +pub struct WasmImportForm { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::empty_link_name, code = "E0454")] +pub struct EmptyLinkName { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::link_framework_apple, code = "E0455")] +pub struct LinkFrameworkApple { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::framework_only_windows, code = "E0455")] +pub struct FrameworkOnlyWindows { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::unknown_link_kind, code = "E0458")] +pub struct UnknownLinkKind<'a> { + #[primary_span] + #[label] + pub span: Span, + pub kind: &'a str, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::multiple_link_modifiers)] +pub struct MultipleLinkModifiers { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::multiple_cfgs)] +pub struct MultipleCfgs { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::link_cfg_single_predicate)] +pub struct LinkCfgSinglePredicate { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::multiple_wasm_import)] +pub struct MultipleWasmImport { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::unexpected_link_arg)] +pub struct UnexpectedLinkArg { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::invalid_link_modifier)] +pub struct InvalidLinkModifier { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::multiple_modifiers)] +pub struct MultipleModifiers<'a> { + #[primary_span] + pub span: Span, + pub modifier: &'a str, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::bundle_needs_static)] +pub struct BundleNeedsStatic { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::whole_archive_needs_static)] +pub struct WholeArchiveNeedsStatic { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::as_needed_compatibility)] +pub struct AsNeededCompatibility { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::unknown_link_modifier)] +pub struct UnknownLinkModifier<'a> { + #[primary_span] + pub span: Span, + pub modifier: &'a str, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::incompatible_wasm_link)] +pub struct IncompatibleWasmLink { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::link_requires_name, code = "E0459")] +pub struct LinkRequiresName { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::raw_dylib_no_nul)] +pub struct RawDylibNoNul { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::link_ordinal_raw_dylib)] +pub struct LinkOrdinalRawDylib { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::lib_framework_apple)] +pub struct LibFrameworkApple; + +#[derive(SessionDiagnostic)] +#[diag(metadata::empty_renaming_target)] +pub struct EmptyRenamingTarget<'a> { + pub lib_name: &'a str, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::renaming_no_link)] +pub struct RenamingNoLink<'a> { + pub lib_name: &'a str, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::multiple_renamings)] +pub struct MultipleRenamings<'a> { + pub lib_name: &'a str, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::no_link_mod_override)] +pub struct NoLinkModOverride { + #[primary_span] + pub span: Option<Span>, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::unsupported_abi_i686)] +pub struct UnsupportedAbiI686 { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::unsupported_abi)] +pub struct UnsupportedAbi { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::fail_create_file_encoder)] +pub struct FailCreateFileEncoder { + pub err: Error, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::fail_seek_file)] +pub struct FailSeekFile { + pub err: Error, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::fail_write_file)] +pub struct FailWriteFile { + pub err: Error, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::crate_not_panic_runtime)] +pub struct CrateNotPanicRuntime { + pub crate_name: Symbol, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::no_panic_strategy)] +pub struct NoPanicStrategy { + pub crate_name: Symbol, + pub strategy: PanicStrategy, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::profiler_builtins_needs_core)] +pub struct ProfilerBuiltinsNeedsCore; + +#[derive(SessionDiagnostic)] +#[diag(metadata::not_profiler_runtime)] +pub struct NotProfilerRuntime { + pub crate_name: Symbol, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::no_multiple_global_alloc)] +pub struct NoMultipleGlobalAlloc { + #[primary_span] + #[label] + pub span2: Span, + #[label(metadata::prev_global_alloc)] + pub span1: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::conflicting_global_alloc)] +pub struct ConflictingGlobalAlloc { + pub crate_name: Symbol, + pub other_crate_name: Symbol, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::global_alloc_required)] +pub struct GlobalAllocRequired; + +#[derive(SessionDiagnostic)] +#[diag(metadata::no_transitive_needs_dep)] +pub struct NoTransitiveNeedsDep<'a> { + pub crate_name: Symbol, + pub needs_crate_name: &'a str, + pub deps_crate_name: Symbol, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::failed_write_error)] +pub struct FailedWriteError { + pub filename: PathBuf, + pub err: Error, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::missing_native_library)] +pub struct MissingNativeLibrary<'a> { + pub libname: &'a str, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::failed_create_tempdir)] +pub struct FailedCreateTempdir { + pub err: Error, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::failed_create_file)] +pub struct FailedCreateFile<'a> { + pub filename: &'a Path, + pub err: Error, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::failed_create_encoded_metadata)] +pub struct FailedCreateEncodedMetadata { + pub err: Error, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::non_ascii_name)] +pub struct NonAsciiName { + #[primary_span] + pub span: Span, + pub crate_name: Symbol, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::extern_location_not_exist)] +pub struct ExternLocationNotExist<'a> { + #[primary_span] + pub span: Span, + pub crate_name: Symbol, + pub location: &'a Path, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::extern_location_not_file)] +pub struct ExternLocationNotFile<'a> { + #[primary_span] + pub span: Span, + pub crate_name: Symbol, + pub location: &'a Path, +} + +pub(crate) struct MultipleCandidates { + pub span: Span, + pub flavor: CrateFlavor, + pub crate_name: Symbol, + pub candidates: Vec<PathBuf>, +} + +impl SessionDiagnostic<'_> for MultipleCandidates { + fn into_diagnostic( + self, + handler: &'_ rustc_errors::Handler, + ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { + let mut diag = handler.struct_err(rustc_errors::fluent::metadata::multiple_candidates); + diag.set_arg("crate_name", self.crate_name); + diag.set_arg("flavor", self.flavor); + diag.code(error_code!(E0465)); + diag.set_span(self.span); + for (i, candidate) in self.candidates.iter().enumerate() { + diag.span_note(self.span, &format!("candidate #{}: {}", i + 1, candidate.display())); + } + diag + } +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::multiple_matching_crates, code = "E0464")] +#[note] +pub struct MultipleMatchingCrates { + #[primary_span] + pub span: Span, + pub crate_name: Symbol, + pub candidates: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::symbol_conflicts_current, code = "E0519")] +pub struct SymbolConflictsCurrent { + #[primary_span] + pub span: Span, + pub crate_name: Symbol, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::symbol_conflicts_others, code = "E0523")] +pub struct SymbolConflictsOthers { + #[primary_span] + pub span: Span, + pub crate_name: Symbol, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::stable_crate_id_collision)] +pub struct StableCrateIdCollision { + #[primary_span] + pub span: Span, + pub crate_name0: Symbol, + pub crate_name1: Symbol, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::dl_error)] +pub struct DlError { + #[primary_span] + pub span: Span, + pub err: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::newer_crate_version, code = "E0460")] +#[note] +#[note(metadata::found_crate_versions)] +pub struct NewerCrateVersion { + #[primary_span] + pub span: Span, + pub crate_name: Symbol, + pub add_info: String, + pub found_crates: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::no_crate_with_triple, code = "E0461")] +#[note(metadata::found_crate_versions)] +pub struct NoCrateWithTriple<'a> { + #[primary_span] + pub span: Span, + pub crate_name: Symbol, + pub locator_triple: &'a str, + pub add_info: String, + pub found_crates: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::found_staticlib, code = "E0462")] +#[note(metadata::found_crate_versions)] +#[help] +pub struct FoundStaticlib { + #[primary_span] + pub span: Span, + pub crate_name: Symbol, + pub add_info: String, + pub found_crates: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::incompatible_rustc, code = "E0514")] +#[note(metadata::found_crate_versions)] +#[help] +pub struct IncompatibleRustc { + #[primary_span] + pub span: Span, + pub crate_name: Symbol, + pub add_info: String, + pub found_crates: String, + pub rustc_version: String, +} + +pub struct InvalidMetadataFiles { + pub span: Span, + pub crate_name: Symbol, + pub add_info: String, + pub crate_rejections: Vec<String>, +} + +impl SessionDiagnostic<'_> for InvalidMetadataFiles { + fn into_diagnostic( + self, + handler: &'_ rustc_errors::Handler, + ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { + let mut diag = handler.struct_err(rustc_errors::fluent::metadata::invalid_meta_files); + diag.set_arg("crate_name", self.crate_name); + diag.set_arg("add_info", self.add_info); + diag.code(error_code!(E0786)); + diag.set_span(self.span); + for crate_rejection in self.crate_rejections { + diag.note(crate_rejection); + } + diag + } +} + +pub struct CannotFindCrate { + pub span: Span, + pub crate_name: Symbol, + pub add_info: String, + pub missing_core: bool, + pub current_crate: String, + pub is_nightly_build: bool, + pub profiler_runtime: Symbol, + pub locator_triple: TargetTriple, +} + +impl SessionDiagnostic<'_> for CannotFindCrate { + fn into_diagnostic( + self, + handler: &'_ rustc_errors::Handler, + ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { + let mut diag = handler.struct_err(rustc_errors::fluent::metadata::cannot_find_crate); + diag.set_arg("crate_name", self.crate_name); + diag.set_arg("current_crate", self.current_crate); + diag.set_arg("add_info", self.add_info); + diag.set_arg("locator_triple", self.locator_triple.triple()); + diag.code(error_code!(E0463)); + diag.set_span(self.span); + if (self.crate_name == sym::std || self.crate_name == sym::core) + && self.locator_triple != TargetTriple::from_triple(config::host_triple()) + { + if self.missing_core { + diag.note(rustc_errors::fluent::metadata::target_not_installed); + } else { + diag.note(rustc_errors::fluent::metadata::target_no_std_support); + } + // NOTE: this suggests using rustup, even though the user may not have it installed. + // That's because they could choose to install it; or this may give them a hint which + // target they need to install from their distro. + if self.missing_core { + diag.help(rustc_errors::fluent::metadata::consider_downloading_target); + } + // Suggest using #![no_std]. #[no_core] is unstable and not really supported anyway. + // NOTE: this is a dummy span if `extern crate std` was injected by the compiler. + // If it's not a dummy, that means someone added `extern crate std` explicitly and + // `#![no_std]` won't help. + if !self.missing_core && self.span.is_dummy() { + diag.note(rustc_errors::fluent::metadata::std_required); + } + if self.is_nightly_build { + diag.help(rustc_errors::fluent::metadata::consider_building_std); + } + } else if self.crate_name == self.profiler_runtime { + diag.note(rustc_errors::fluent::metadata::compiler_missing_profiler); + } else if self.crate_name.as_str().starts_with("rustc_") { + diag.help(rustc_errors::fluent::metadata::install_missing_components); + } + diag.span_label(self.span, rustc_errors::fluent::metadata::cant_find_crate); + diag + } +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::no_dylib_plugin, code = "E0457")] +pub struct NoDylibPlugin { + #[primary_span] + pub span: Span, + pub crate_name: Symbol, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::crate_location_unknown_type)] +pub struct CrateLocationUnknownType<'a> { + #[primary_span] + pub span: Span, + pub path: &'a Path, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::lib_filename_form)] +pub struct LibFilenameForm<'a> { + #[primary_span] + pub span: Span, + pub dll_prefix: &'a str, + pub dll_suffix: &'a str, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::multiple_import_name_type)] +pub struct MultipleImportNameType { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::import_name_type_form)] +pub struct ImportNameTypeForm { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::import_name_type_x86)] +pub struct ImportNameTypeX86 { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::unknown_import_name_type)] +pub struct UnknownImportNameType<'a> { + #[primary_span] + pub span: Span, + pub import_name_type: &'a str, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::import_name_type_raw)] +pub struct ImportNameTypeRaw { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_metadata/src/fs.rs b/compiler/rustc_metadata/src/fs.rs index e6072901a..f360a5864 100644 --- a/compiler/rustc_metadata/src/fs.rs +++ b/compiler/rustc_metadata/src/fs.rs @@ -1,3 +1,6 @@ +use crate::errors::{ + FailedCreateEncodedMetadata, FailedCreateFile, FailedCreateTempdir, FailedWriteError, +}; use crate::{encode_metadata, EncodedMetadata}; use rustc_data_structures::temp_dir::MaybeTempDir; @@ -23,8 +26,8 @@ pub fn emit_metadata(sess: &Session, metadata: &[u8], tmpdir: &MaybeTempDir) -> let out_filename = tmpdir.as_ref().join(METADATA_FILENAME); let result = fs::write(&out_filename, metadata); - if let Err(e) = result { - sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e)); + if let Err(err) = result { + sess.emit_fatal(FailedWriteError { filename: out_filename, err }); } out_filename @@ -65,7 +68,7 @@ pub fn encode_and_write_metadata( let metadata_tmpdir = TempFileBuilder::new() .prefix("rmeta") .tempdir_in(out_filename.parent().unwrap_or_else(|| Path::new(""))) - .unwrap_or_else(|err| tcx.sess.fatal(&format!("couldn't create a temp dir: {}", err))); + .unwrap_or_else(|err| tcx.sess.emit_fatal(FailedCreateTempdir { err })); let metadata_tmpdir = MaybeTempDir::new(metadata_tmpdir, tcx.sess.opts.cg.save_temps); let metadata_filename = metadata_tmpdir.as_ref().join(METADATA_FILENAME); @@ -73,12 +76,8 @@ pub fn encode_and_write_metadata( // This simplifies the creation of the output `out_filename` when requested. match metadata_kind { MetadataKind::None => { - std::fs::File::create(&metadata_filename).unwrap_or_else(|e| { - tcx.sess.fatal(&format!( - "failed to create the file {}: {}", - metadata_filename.display(), - e - )) + std::fs::File::create(&metadata_filename).unwrap_or_else(|err| { + tcx.sess.emit_fatal(FailedCreateFile { filename: &metadata_filename, err }); }); } MetadataKind::Uncompressed | MetadataKind::Compressed => { @@ -93,8 +92,8 @@ pub fn encode_and_write_metadata( // this file always exists. let need_metadata_file = tcx.sess.opts.output_types.contains_key(&OutputType::Metadata); let (metadata_filename, metadata_tmpdir) = if need_metadata_file { - if let Err(e) = non_durable_rename(&metadata_filename, &out_filename) { - tcx.sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e)); + if let Err(err) = non_durable_rename(&metadata_filename, &out_filename) { + tcx.sess.emit_fatal(FailedWriteError { filename: out_filename, err }); } if tcx.sess.opts.json_artifact_notifications { tcx.sess @@ -109,8 +108,8 @@ pub fn encode_and_write_metadata( // Load metadata back to memory: codegen may need to include it in object files. let metadata = - EncodedMetadata::from_path(metadata_filename, metadata_tmpdir).unwrap_or_else(|e| { - tcx.sess.fatal(&format!("failed to create encoded metadata from file: {}", e)) + EncodedMetadata::from_path(metadata_filename, metadata_tmpdir).unwrap_or_else(|err| { + tcx.sess.emit_fatal(FailedCreateEncodedMetadata { err }); }); let need_metadata_module = metadata_kind == MetadataKind::Compressed; diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index 6440f3e39..6f5604b7e 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -2,10 +2,10 @@ #![feature(decl_macro)] #![feature(drain_filter)] #![feature(generators)] -#![feature(generic_associated_types)] +#![cfg_attr(bootstrap, feature(generic_associated_types))] #![feature(iter_from_generator)] #![feature(let_chains)] -#![feature(let_else)] +#![cfg_attr(bootstrap, feature(let_else))] #![feature(once_cell)] #![feature(proc_macro_internals)] #![feature(macro_metavar_expr)] @@ -16,6 +16,8 @@ #![feature(never_type)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] extern crate proc_macro; @@ -26,6 +28,9 @@ extern crate rustc_middle; #[macro_use] extern crate rustc_data_structures; +#[macro_use] +extern crate tracing; + pub use rmeta::{provide, provide_extern}; mod dependency_format; @@ -34,8 +39,10 @@ mod native_libs; mod rmeta; pub mod creader; +pub mod errors; pub mod fs; pub mod locator; pub use fs::{emit_metadata, METADATA_FILENAME}; +pub use native_libs::find_native_static_library; pub use rmeta::{encode_metadata, EncodedMetadata, METADATA_HEADER}; diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 2c1c84b0b..35f9ef92a 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -213,6 +213,13 @@ //! metadata::locator or metadata::creader for all the juicy details! use crate::creader::Library; +use crate::errors::{ + CannotFindCrate, CrateLocationUnknownType, DlError, ExternLocationNotExist, + ExternLocationNotFile, FoundStaticlib, IncompatibleRustc, InvalidMetadataFiles, + LibFilenameForm, MultipleCandidates, MultipleMatchingCrates, NewerCrateVersion, + NoCrateWithTriple, NoDylibPlugin, NonAsciiName, StableCrateIdCollision, SymbolConflictsCurrent, + SymbolConflictsOthers, +}; use crate::rmeta::{rustc_version, MetadataBlob, METADATA_HEADER}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -220,23 +227,23 @@ use rustc_data_structures::memmap::Mmap; use rustc_data_structures::owning_ref::OwningRef; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::MetadataRef; -use rustc_errors::{struct_span_err, FatalError}; +use rustc_errors::{DiagnosticArgValue, FatalError, IntoDiagnosticArg}; use rustc_session::config::{self, CrateType}; use rustc_session::cstore::{CrateSource, MetadataLoader}; use rustc_session::filesearch::FileSearch; use rustc_session::search_paths::PathKind; use rustc_session::utils::CanonicalizedPath; use rustc_session::Session; -use rustc_span::symbol::{sym, Symbol}; +use rustc_span::symbol::Symbol; use rustc_span::Span; use rustc_target::spec::{Target, TargetTriple}; use snap::read::FrameDecoder; +use std::borrow::Cow; use std::fmt::Write as _; use std::io::{Read, Result as IoResult, Write}; use std::path::{Path, PathBuf}; use std::{cmp, fmt, fs}; -use tracing::{debug, info}; #[derive(Clone)] pub(crate) struct CrateLocator<'a> { @@ -288,6 +295,16 @@ impl fmt::Display for CrateFlavor { } } +impl IntoDiagnosticArg for CrateFlavor { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + match self { + CrateFlavor::Rlib => DiagnosticArgValue::Str(Cow::Borrowed("rlib")), + CrateFlavor::Rmeta => DiagnosticArgValue::Str(Cow::Borrowed("rmeta")), + CrateFlavor::Dylib => DiagnosticArgValue::Str(Cow::Borrowed("dylib")), + } + } +} + impl<'a> CrateLocator<'a> { pub(crate) fn new( sess: &'a Session, @@ -938,41 +955,20 @@ impl fmt::Display for MetadataError<'_> { impl CrateError { pub(crate) fn report(self, sess: &Session, span: Span, missing_core: bool) { - let mut diag = match self { - CrateError::NonAsciiName(crate_name) => sess.struct_span_err( - span, - &format!("cannot load a crate with a non-ascii name `{}`", crate_name), - ), - CrateError::ExternLocationNotExist(crate_name, loc) => sess.struct_span_err( - span, - &format!("extern location for {} does not exist: {}", crate_name, loc.display()), - ), - CrateError::ExternLocationNotFile(crate_name, loc) => sess.struct_span_err( - span, - &format!("extern location for {} is not a file: {}", crate_name, loc.display()), - ), + match self { + CrateError::NonAsciiName(crate_name) => { + sess.emit_err(NonAsciiName { span, crate_name }); + } + CrateError::ExternLocationNotExist(crate_name, loc) => { + sess.emit_err(ExternLocationNotExist { span, crate_name, location: &loc }); + } + CrateError::ExternLocationNotFile(crate_name, loc) => { + sess.emit_err(ExternLocationNotFile { span, crate_name, location: &loc }); + } CrateError::MultipleCandidates(crate_name, flavor, candidates) => { - let mut err = struct_span_err!( - sess, - span, - E0465, - "multiple {} candidates for `{}` found", - flavor, - crate_name, - ); - for (i, candidate) in candidates.iter().enumerate() { - err.span_note(span, &format!("candidate #{}: {}", i + 1, candidate.display())); - } - err + sess.emit_err(MultipleCandidates { span, flavor: flavor, crate_name, candidates }); } CrateError::MultipleMatchingCrates(crate_name, libraries) => { - let mut err = struct_span_err!( - sess, - span, - E0464, - "multiple matching crates for `{}`", - crate_name - ); let mut libraries: Vec<_> = libraries.into_values().collect(); // Make ordering of candidates deterministic. // This has to `clone()` to work around lifetime restrictions with `sort_by_key()`. @@ -1000,223 +996,142 @@ impl CrateError { s }) .collect::<String>(); - err.note(&format!("candidates:{}", candidates)); - err + sess.emit_err(MultipleMatchingCrates { span, crate_name, candidates }); + } + CrateError::SymbolConflictsCurrent(root_name) => { + sess.emit_err(SymbolConflictsCurrent { span, crate_name: root_name }); + } + CrateError::SymbolConflictsOthers(root_name) => { + sess.emit_err(SymbolConflictsOthers { span, crate_name: root_name }); } - CrateError::SymbolConflictsCurrent(root_name) => struct_span_err!( - sess, - span, - E0519, - "the current crate is indistinguishable from one of its dependencies: it has the \ - same crate-name `{}` and was compiled with the same `-C metadata` arguments. \ - This will result in symbol conflicts between the two.", - root_name, - ), - CrateError::SymbolConflictsOthers(root_name) => struct_span_err!( - sess, - span, - E0523, - "found two different crates with name `{}` that are not distinguished by differing \ - `-C metadata`. This will result in symbol conflicts between the two.", - root_name, - ), CrateError::StableCrateIdCollision(crate_name0, crate_name1) => { - let msg = format!( - "found crates (`{}` and `{}`) with colliding StableCrateId values.", - crate_name0, crate_name1 - ); - sess.struct_span_err(span, &msg) + sess.emit_err(StableCrateIdCollision { + span, + crate_name0: crate_name0, + crate_name1: crate_name1, + }); + } + CrateError::DlOpen(s) | CrateError::DlSym(s) => { + sess.emit_err(DlError { span, err: s }); } - CrateError::DlOpen(s) | CrateError::DlSym(s) => sess.struct_span_err(span, &s), CrateError::LocatorCombined(locator) => { let crate_name = locator.crate_name; - let add = match &locator.root { + let add_info = match &locator.root { None => String::new(), Some(r) => format!(" which `{}` depends on", r.name), }; - let mut msg = "the following crate versions were found:".to_string(); - let mut err = if !locator.crate_rejections.via_hash.is_empty() { - let mut err = struct_span_err!( - sess, - span, - E0460, - "found possibly newer version of crate `{}`{}", - crate_name, - add, - ); - err.note("perhaps that crate needs to be recompiled?"); + // FIXME: There are no tests for CrateLocationUnknownType or LibFilenameForm + if !locator.crate_rejections.via_filename.is_empty() { + let mismatches = locator.crate_rejections.via_filename.iter(); + for CrateMismatch { path, .. } in mismatches { + sess.emit_err(CrateLocationUnknownType { span, path: &path }); + sess.emit_err(LibFilenameForm { + span, + dll_prefix: &locator.dll_prefix, + dll_suffix: &locator.dll_suffix, + }); + } + } + let mut found_crates = String::new(); + if !locator.crate_rejections.via_hash.is_empty() { let mismatches = locator.crate_rejections.via_hash.iter(); for CrateMismatch { path, .. } in mismatches { - msg.push_str(&format!("\ncrate `{}`: {}", crate_name, path.display())); + found_crates.push_str(&format!( + "\ncrate `{}`: {}", + crate_name, + path.display() + )); } if let Some(r) = locator.root { for path in r.source.paths() { - msg.push_str(&format!("\ncrate `{}`: {}", r.name, path.display())); + found_crates.push_str(&format!( + "\ncrate `{}`: {}", + r.name, + path.display() + )); } } - err.note(&msg); - err - } else if !locator.crate_rejections.via_triple.is_empty() { - let mut err = struct_span_err!( - sess, + sess.emit_err(NewerCrateVersion { span, - E0461, - "couldn't find crate `{}` with expected target triple {}{}", - crate_name, - locator.triple, - add, - ); + crate_name: crate_name, + add_info, + found_crates, + }); + } else if !locator.crate_rejections.via_triple.is_empty() { let mismatches = locator.crate_rejections.via_triple.iter(); for CrateMismatch { path, got } in mismatches { - msg.push_str(&format!( + found_crates.push_str(&format!( "\ncrate `{}`, target triple {}: {}", crate_name, got, path.display(), )); } - err.note(&msg); - err - } else if !locator.crate_rejections.via_kind.is_empty() { - let mut err = struct_span_err!( - sess, + sess.emit_err(NoCrateWithTriple { span, - E0462, - "found staticlib `{}` instead of rlib or dylib{}", - crate_name, - add, - ); - err.help("please recompile that crate using --crate-type lib"); + crate_name: crate_name, + locator_triple: locator.triple.triple(), + add_info, + found_crates, + }); + } else if !locator.crate_rejections.via_kind.is_empty() { let mismatches = locator.crate_rejections.via_kind.iter(); for CrateMismatch { path, .. } in mismatches { - msg.push_str(&format!("\ncrate `{}`: {}", crate_name, path.display())); + found_crates.push_str(&format!( + "\ncrate `{}`: {}", + crate_name, + path.display() + )); } - err.note(&msg); - err + sess.emit_err(FoundStaticlib { span, crate_name, add_info, found_crates }); } else if !locator.crate_rejections.via_version.is_empty() { - let mut err = struct_span_err!( - sess, - span, - E0514, - "found crate `{}` compiled by an incompatible version of rustc{}", - crate_name, - add, - ); - err.help(&format!( - "please recompile that crate using this compiler ({}) \ - (consider running `cargo clean` first)", - rustc_version(), - )); let mismatches = locator.crate_rejections.via_version.iter(); for CrateMismatch { path, got } in mismatches { - msg.push_str(&format!( + found_crates.push_str(&format!( "\ncrate `{}` compiled by {}: {}", crate_name, got, path.display(), )); } - err.note(&msg); - err - } else if !locator.crate_rejections.via_invalid.is_empty() { - let mut err = struct_span_err!( - sess, + sess.emit_err(IncompatibleRustc { span, - E0786, - "found invalid metadata files for crate `{}`{}", crate_name, - add, - ); + add_info, + found_crates, + rustc_version: rustc_version(), + }); + } else if !locator.crate_rejections.via_invalid.is_empty() { + let mut crate_rejections = Vec::new(); for CrateMismatch { path: _, got } in locator.crate_rejections.via_invalid { - err.note(&got); + crate_rejections.push(got); } - err + sess.emit_err(InvalidMetadataFiles { + span, + crate_name, + add_info, + crate_rejections, + }); } else { - let mut err = struct_span_err!( - sess, + sess.emit_err(CannotFindCrate { span, - E0463, - "can't find crate for `{}`{}", crate_name, - add, - ); - - if (crate_name == sym::std || crate_name == sym::core) - && locator.triple != TargetTriple::from_triple(config::host_triple()) - { - if missing_core { - err.note(&format!( - "the `{}` target may not be installed", - locator.triple - )); - } else { - err.note(&format!( - "the `{}` target may not support the standard library", - locator.triple - )); - } - // NOTE: this suggests using rustup, even though the user may not have it installed. - // That's because they could choose to install it; or this may give them a hint which - // target they need to install from their distro. - if missing_core { - err.help(&format!( - "consider downloading the target with `rustup target add {}`", - locator.triple - )); - } - // Suggest using #![no_std]. #[no_core] is unstable and not really supported anyway. - // NOTE: this is a dummy span if `extern crate std` was injected by the compiler. - // If it's not a dummy, that means someone added `extern crate std` explicitly and `#![no_std]` won't help. - if !missing_core && span.is_dummy() { - let current_crate = - sess.opts.crate_name.as_deref().unwrap_or("<unknown>"); - err.note(&format!( - "`std` is required by `{}` because it does not declare `#![no_std]`", - current_crate - )); - } - if sess.is_nightly_build() { - err.help("consider building the standard library from source with `cargo build -Zbuild-std`"); - } - } else if crate_name - == Symbol::intern(&sess.opts.unstable_opts.profiler_runtime) - { - err.note("the compiler may have been built without the profiler runtime"); - } else if crate_name.as_str().starts_with("rustc_") { - err.help( - "maybe you need to install the missing components with: \ - `rustup component add rust-src rustc-dev llvm-tools-preview`", - ); - } - err.span_label(span, "can't find crate"); - err - }; - - if !locator.crate_rejections.via_filename.is_empty() { - let mismatches = locator.crate_rejections.via_filename.iter(); - for CrateMismatch { path, .. } in mismatches { - err.note(&format!( - "extern location for {} is of an unknown type: {}", - crate_name, - path.display(), - )) - .help(&format!( - "file name should be lib*.rlib or {}*.{}", - locator.dll_prefix, locator.dll_suffix - )); - } + add_info, + missing_core, + current_crate: sess + .opts + .crate_name + .clone() + .unwrap_or("<unknown>".to_string()), + is_nightly_build: sess.is_nightly_build(), + profiler_runtime: Symbol::intern(&sess.opts.unstable_opts.profiler_runtime), + locator_triple: locator.triple, + }); } - err } - CrateError::NonDylibPlugin(crate_name) => struct_span_err!( - sess, - span, - E0457, - "plugin `{}` only found in rlib format, but must be available in dylib format", - crate_name, - ), - }; - - diag.emit(); + CrateError::NonDylibPlugin(crate_name) => { + sess.emit_err(NoDylibPlugin { span, crate_name }); + } + } } } diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 9f6079ecb..257741c13 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -1,17 +1,83 @@ use rustc_ast::{NestedMetaItem, CRATE_NODE_ID}; use rustc_attr as attr; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_middle::ty::{List, ParamEnv, ParamEnvAnd, Ty, TyCtxt}; -use rustc_session::cstore::{DllCallingConvention, DllImport, NativeLib}; +use rustc_session::config::CrateType; +use rustc_session::cstore::{DllCallingConvention, DllImport, NativeLib, PeImportNameType}; use rustc_session::parse::feature_err; +use rustc_session::search_paths::PathKind; use rustc_session::utils::NativeLibKind; use rustc_session::Session; use rustc_span::symbol::{sym, Symbol}; use rustc_target::spec::abi::Abi; +use crate::errors::{ + AsNeededCompatibility, BundleNeedsStatic, EmptyLinkName, EmptyRenamingTarget, + FrameworkOnlyWindows, ImportNameTypeForm, ImportNameTypeRaw, ImportNameTypeX86, + IncompatibleWasmLink, InvalidLinkModifier, LibFrameworkApple, LinkCfgForm, + LinkCfgSinglePredicate, LinkFrameworkApple, LinkKindForm, LinkModifiersForm, LinkNameForm, + LinkOrdinalRawDylib, LinkRequiresName, MissingNativeLibrary, MultipleCfgs, + MultipleImportNameType, MultipleKindsInLink, MultipleLinkModifiers, MultipleModifiers, + MultipleNamesInLink, MultipleRenamings, MultipleWasmImport, NoLinkModOverride, RawDylibNoNul, + RenamingNoLink, UnexpectedLinkArg, UnknownImportNameType, UnknownLinkKind, UnknownLinkModifier, + UnsupportedAbi, UnsupportedAbiI686, WasmImportForm, WholeArchiveNeedsStatic, +}; + +use std::path::PathBuf; + +pub fn find_native_static_library( + name: &str, + verbatim: Option<bool>, + search_paths: &[PathBuf], + sess: &Session, +) -> PathBuf { + let verbatim = verbatim.unwrap_or(false); + // On Windows, static libraries sometimes show up as libfoo.a and other + // times show up as foo.lib + let oslibname = if verbatim { + name.to_string() + } else { + format!("{}{}{}", sess.target.staticlib_prefix, name, sess.target.staticlib_suffix) + }; + let unixlibname = format!("lib{}.a", name); + + for path in search_paths { + let test = path.join(&oslibname); + if test.exists() { + return test; + } + if oslibname != unixlibname { + let test = path.join(&unixlibname); + if test.exists() { + return test; + } + } + } + sess.emit_fatal(MissingNativeLibrary { libname: name }); +} + +fn find_bundled_library( + name: Option<Symbol>, + verbatim: Option<bool>, + kind: NativeLibKind, + sess: &Session, +) -> Option<Symbol> { + if sess.opts.unstable_opts.packed_bundled_libs && + sess.crate_types().iter().any(|ct| ct == &CrateType::Rlib || ct == &CrateType::Staticlib) && + let NativeLibKind::Static { bundle: Some(true) | None, .. } = kind { + find_native_static_library( + name.unwrap().as_str(), + verbatim, + &sess.target_filesearch(PathKind::Native).search_path_dirs(), + sess, + ).file_name().and_then(|s| s.to_str()).map(Symbol::intern) + } else { + None + } +} + pub(crate) fn collect(tcx: TyCtxt<'_>) -> Vec<NativeLib> { let mut collector = Collector { tcx, libs: Vec::new() }; for id in tcx.hir().items() { @@ -61,36 +127,31 @@ impl<'tcx> Collector<'tcx> { let mut modifiers = None; let mut cfg = None; let mut wasm_import_module = None; + let mut import_name_type = None; for item in items.iter() { match item.name_or_empty() { sym::name => { if name.is_some() { - let msg = "multiple `name` arguments in a single `#[link]` attribute"; - sess.span_err(item.span(), msg); + sess.emit_err(MultipleNamesInLink { span: item.span() }); continue; } let Some(link_name) = item.value_str() else { - let msg = "link name must be of the form `name = \"string\"`"; - sess.span_err(item.span(), msg); + sess.emit_err(LinkNameForm { span: item.span() }); continue; }; let span = item.name_value_literal_span().unwrap(); if link_name.is_empty() { - struct_span_err!(sess, span, E0454, "link name must not be empty") - .span_label(span, "empty link name") - .emit(); + sess.emit_err(EmptyLinkName { span }); } name = Some((link_name, span)); } sym::kind => { if kind.is_some() { - let msg = "multiple `kind` arguments in a single `#[link]` attribute"; - sess.span_err(item.span(), msg); + sess.emit_err(MultipleKindsInLink { span: item.span() }); continue; } let Some(link_kind) = item.value_str() else { - let msg = "link kind must be of the form `kind = \"string\"`"; - sess.span_err(item.span(), msg); + sess.emit_err(LinkKindForm { span: item.span() }); continue; }; @@ -100,44 +161,26 @@ impl<'tcx> Collector<'tcx> { "dylib" => NativeLibKind::Dylib { as_needed: None }, "framework" => { if !sess.target.is_like_osx { - struct_span_err!( - sess, - span, - E0455, - "link kind `framework` is only supported on Apple targets" - ) - .emit(); + sess.emit_err(LinkFrameworkApple { span }); } NativeLibKind::Framework { as_needed: None } } "raw-dylib" => { if !sess.target.is_like_windows { - struct_span_err!( - sess, - span, - E0455, - "link kind `raw-dylib` is only supported on Windows targets" - ) - .emit(); - } else if !features.raw_dylib { + sess.emit_err(FrameworkOnlyWindows { span }); + } else if !features.raw_dylib && sess.target.arch == "x86" { feature_err( &sess.parse_sess, sym::raw_dylib, span, - "link kind `raw-dylib` is unstable", + "link kind `raw-dylib` is unstable on x86", ) .emit(); } NativeLibKind::RawDylib } kind => { - let msg = format!( - "unknown link kind `{kind}`, expected one of: \ - static, dylib, framework, raw-dylib" - ); - struct_span_err!(sess, span, E0458, "{}", msg) - .span_label(span, "unknown link kind") - .emit(); + sess.emit_err(UnknownLinkKind { span, kind }); continue; } }; @@ -145,32 +188,26 @@ impl<'tcx> Collector<'tcx> { } sym::modifiers => { if modifiers.is_some() { - let msg = - "multiple `modifiers` arguments in a single `#[link]` attribute"; - sess.span_err(item.span(), msg); + sess.emit_err(MultipleLinkModifiers { span: item.span() }); continue; } let Some(link_modifiers) = item.value_str() else { - let msg = "link modifiers must be of the form `modifiers = \"string\"`"; - sess.span_err(item.span(), msg); + sess.emit_err(LinkModifiersForm { span: item.span() }); continue; }; modifiers = Some((link_modifiers, item.name_value_literal_span().unwrap())); } sym::cfg => { if cfg.is_some() { - let msg = "multiple `cfg` arguments in a single `#[link]` attribute"; - sess.span_err(item.span(), msg); + sess.emit_err(MultipleCfgs { span: item.span() }); continue; } let Some(link_cfg) = item.meta_item_list() else { - let msg = "link cfg must be of the form `cfg(/* predicate */)`"; - sess.span_err(item.span(), msg); + sess.emit_err(LinkCfgForm { span: item.span() }); continue; }; let [NestedMetaItem::MetaItem(link_cfg)] = link_cfg else { - let msg = "link cfg must have a single predicate argument"; - sess.span_err(item.span(), msg); + sess.emit_err(LinkCfgSinglePredicate { span: item.span() }); continue; }; if !features.link_cfg { @@ -186,23 +223,55 @@ impl<'tcx> Collector<'tcx> { } sym::wasm_import_module => { if wasm_import_module.is_some() { - let msg = "multiple `wasm_import_module` arguments \ - in a single `#[link]` attribute"; - sess.span_err(item.span(), msg); + sess.emit_err(MultipleWasmImport { span: item.span() }); continue; } let Some(link_wasm_import_module) = item.value_str() else { - let msg = "wasm import module must be of the form \ - `wasm_import_module = \"string\"`"; - sess.span_err(item.span(), msg); + sess.emit_err(WasmImportForm { span: item.span() }); continue; }; wasm_import_module = Some((link_wasm_import_module, item.span())); } + sym::import_name_type => { + if import_name_type.is_some() { + sess.emit_err(MultipleImportNameType { span: item.span() }); + continue; + } + let Some(link_import_name_type) = item.value_str() else { + sess.emit_err(ImportNameTypeForm { span: item.span() }); + continue; + }; + if self.tcx.sess.target.arch != "x86" { + sess.emit_err(ImportNameTypeX86 { span: item.span() }); + continue; + } + + let link_import_name_type = match link_import_name_type.as_str() { + "decorated" => PeImportNameType::Decorated, + "noprefix" => PeImportNameType::NoPrefix, + "undecorated" => PeImportNameType::Undecorated, + import_name_type => { + sess.emit_err(UnknownImportNameType { + span: item.span(), + import_name_type, + }); + continue; + } + }; + if !features.raw_dylib { + let span = item.name_value_literal_span().unwrap(); + feature_err( + &sess.parse_sess, + sym::raw_dylib, + span, + "import name type is unstable", + ) + .emit(); + } + import_name_type = Some((link_import_name_type, item.span())); + } _ => { - let msg = "unexpected `#[link]` argument, expected one of: \ - name, kind, modifiers, cfg, wasm_import_module"; - sess.span_err(item.span(), msg); + sess.emit_err(UnexpectedLinkArg { span: item.span() }); } } } @@ -214,11 +283,7 @@ impl<'tcx> Collector<'tcx> { let (modifier, value) = match modifier.strip_prefix(&['+', '-']) { Some(m) => (m, modifier.starts_with('+')), None => { - sess.span_err( - span, - "invalid linking modifier syntax, expected '+' or '-' prefix \ - before one of: bundle, verbatim, whole-archive, as-needed", - ); + sess.emit_err(InvalidLinkModifier { span }); continue; } }; @@ -236,10 +301,7 @@ impl<'tcx> Collector<'tcx> { } let assign_modifier = |dst: &mut Option<bool>| { if dst.is_some() { - let msg = format!( - "multiple `{modifier}` modifiers in a single `modifiers` argument" - ); - sess.span_err(span, &msg); + sess.emit_err(MultipleModifiers { span, modifier }); } else { *dst = Some(value); } @@ -249,11 +311,7 @@ impl<'tcx> Collector<'tcx> { assign_modifier(bundle) } ("bundle", _) => { - sess.span_err( - span, - "linking modifier `bundle` is only compatible with \ - `static` linking kind", - ); + sess.emit_err(BundleNeedsStatic { span }); } ("verbatim", _) => { @@ -265,11 +323,7 @@ impl<'tcx> Collector<'tcx> { assign_modifier(whole_archive) } ("whole-archive", _) => { - sess.span_err( - span, - "linking modifier `whole-archive` is only compatible with \ - `static` linking kind", - ); + sess.emit_err(WholeArchiveNeedsStatic { span }); } ("as-needed", Some(NativeLibKind::Dylib { as_needed })) @@ -278,21 +332,11 @@ impl<'tcx> Collector<'tcx> { assign_modifier(as_needed) } ("as-needed", _) => { - sess.span_err( - span, - "linking modifier `as-needed` is only compatible with \ - `dylib` and `framework` linking kinds", - ); + sess.emit_err(AsNeededCompatibility { span }); } _ => { - sess.span_err( - span, - format!( - "unknown linking modifier `{modifier}`, expected one of: \ - bundle, verbatim, whole-archive, as-needed" - ), - ); + sess.emit_err(UnknownLinkModifier { span, modifier }); } } } @@ -300,39 +344,66 @@ impl<'tcx> Collector<'tcx> { if let Some((_, span)) = wasm_import_module { if name.is_some() || kind.is_some() || modifiers.is_some() || cfg.is_some() { - let msg = "`wasm_import_module` is incompatible with \ - other arguments in `#[link]` attributes"; - sess.span_err(span, msg); + sess.emit_err(IncompatibleWasmLink { span }); } } else if name.is_none() { - struct_span_err!( - sess, - m.span, - E0459, - "`#[link]` attribute requires a `name = \"string\"` argument" - ) - .span_label(m.span, "missing `name` argument") - .emit(); + sess.emit_err(LinkRequiresName { span: m.span }); + } + + // Do this outside of the loop so that `import_name_type` can be specified before `kind`. + if let Some((_, span)) = import_name_type { + if kind != Some(NativeLibKind::RawDylib) { + sess.emit_err(ImportNameTypeRaw { span }); + } } let dll_imports = match kind { Some(NativeLibKind::RawDylib) => { if let Some((name, span)) = name && name.as_str().contains('\0') { - sess.span_err( - span, - "link name must not contain NUL characters if link kind is `raw-dylib`", - ); + sess.emit_err(RawDylibNoNul { span }); } foreign_mod_items .iter() - .map(|child_item| self.build_dll_import(abi, child_item)) + .map(|child_item| { + self.build_dll_import( + abi, + import_name_type.map(|(import_name_type, _)| import_name_type), + child_item, + ) + }) .collect() } - _ => Vec::new(), + _ => { + for child_item in foreign_mod_items { + if self.tcx.def_kind(child_item.id.def_id).has_codegen_attrs() + && self + .tcx + .codegen_fn_attrs(child_item.id.def_id) + .link_ordinal + .is_some() + { + let link_ordinal_attr = self + .tcx + .hir() + .attrs(self.tcx.hir().local_def_id_to_hir_id(child_item.id.def_id)) + .iter() + .find(|a| a.has_name(sym::link_ordinal)) + .unwrap(); + sess.emit_err(LinkOrdinalRawDylib { span: link_ordinal_attr.span }); + } + } + + Vec::new() + } }; + + let name = name.map(|(name, _)| name); + let kind = kind.unwrap_or(NativeLibKind::Unspecified); + let filename = find_bundled_library(name, verbatim, kind, sess); self.libs.push(NativeLib { - name: name.map(|(name, _)| name), - kind: kind.unwrap_or(NativeLibKind::Unspecified), + name, + filename, + kind, cfg, foreign_module: Some(it.def_id.to_def_id()), wasm_import_module: wasm_import_module.map(|(name, _)| name), @@ -349,7 +420,7 @@ impl<'tcx> Collector<'tcx> { for lib in &self.tcx.sess.opts.libs { if let NativeLibKind::Framework { .. } = lib.kind && !self.tcx.sess.target.is_like_osx { // Cannot check this when parsing options because the target is not yet available. - self.tcx.sess.err("library kind `framework` is only supported on Apple targets"); + self.tcx.sess.emit_err(LibFrameworkApple); } if let Some(ref new_name) = lib.new_name { let any_duplicate = self @@ -358,23 +429,11 @@ impl<'tcx> Collector<'tcx> { .filter_map(|lib| lib.name.as_ref()) .any(|n| n.as_str() == lib.name); if new_name.is_empty() { - self.tcx.sess.err(format!( - "an empty renaming target was specified for library `{}`", - lib.name - )); + self.tcx.sess.emit_err(EmptyRenamingTarget { lib_name: &lib.name }); } else if !any_duplicate { - self.tcx.sess.err(format!( - "renaming of the library `{}` was specified, \ - however this crate contains no `#[link(...)]` \ - attributes referencing this library", - lib.name - )); + self.tcx.sess.emit_err(RenamingNoLink { lib_name: &lib.name }); } else if !renames.insert(&lib.name) { - self.tcx.sess.err(format!( - "multiple renamings were \ - specified for library `{}`", - lib.name - )); + self.tcx.sess.emit_err(MultipleRenamings { lib_name: &lib.name }); } } } @@ -399,10 +458,13 @@ impl<'tcx> Collector<'tcx> { // involved or not, library reordering and kind overriding without // explicit `:rename` in particular. if lib.has_modifiers() || passed_lib.has_modifiers() { - let msg = "overriding linking modifiers from command line is not supported"; match lib.foreign_module { - Some(def_id) => self.tcx.sess.span_err(self.tcx.def_span(def_id), msg), - None => self.tcx.sess.err(msg), + Some(def_id) => self.tcx.sess.emit_err(NoLinkModOverride { + span: Some(self.tcx.def_span(def_id)), + }), + None => { + self.tcx.sess.emit_err(NoLinkModOverride { span: None }) + } }; } if passed_lib.kind != NativeLibKind::Unspecified { @@ -421,8 +483,13 @@ impl<'tcx> Collector<'tcx> { if existing.is_empty() { // Add if not found let new_name: Option<&str> = passed_lib.new_name.as_deref(); + let name = Some(Symbol::intern(new_name.unwrap_or(&passed_lib.name))); + let sess = self.tcx.sess; + let filename = + find_bundled_library(name, passed_lib.verbatim, passed_lib.kind, sess); self.libs.push(NativeLib { - name: Some(Symbol::intern(new_name.unwrap_or(&passed_lib.name))), + name, + filename, kind: passed_lib.kind, cfg: None, foreign_module: None, @@ -462,7 +529,12 @@ impl<'tcx> Collector<'tcx> { .sum() } - fn build_dll_import(&self, abi: Abi, item: &hir::ForeignItemRef) -> DllImport { + fn build_dll_import( + &self, + abi: Abi, + import_name_type: Option<PeImportNameType>, + item: &hir::ForeignItemRef, + ) -> DllImport { let calling_convention = if self.tcx.sess.target.arch == "x86" { match abi { Abi::C { .. } | Abi::Cdecl { .. } => DllCallingConvention::C, @@ -476,29 +548,29 @@ impl<'tcx> Collector<'tcx> { DllCallingConvention::Vectorcall(self.i686_arg_list_size(item)) } _ => { - self.tcx.sess.span_fatal( - item.span, - r#"ABI not supported by `#[link(kind = "raw-dylib")]` on i686"#, - ); + self.tcx.sess.emit_fatal(UnsupportedAbiI686 { span: item.span }); } } } else { match abi { Abi::C { .. } | Abi::Win64 { .. } | Abi::System { .. } => DllCallingConvention::C, _ => { - self.tcx.sess.span_fatal( - item.span, - r#"ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture"#, - ); + self.tcx.sess.emit_fatal(UnsupportedAbi { span: item.span }); } } }; + let codegen_fn_attrs = self.tcx.codegen_fn_attrs(item.id.def_id); + let import_name_type = codegen_fn_attrs + .link_ordinal + .map_or(import_name_type, |ord| Some(PeImportNameType::Ordinal(ord))); + DllImport { - name: item.ident.name, - ordinal: self.tcx.codegen_fn_attrs(item.id.def_id).link_ordinal, + name: codegen_fn_attrs.link_name.unwrap_or(item.ident.name), + import_name_type, calling_convention, span: item.span, + is_fn: self.tcx.def_kind(item.id.def_id).is_fn_like(), } } } diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 40dc4fb05..830417eea 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -4,7 +4,6 @@ use crate::creader::{CStore, CrateMetadataRef}; use crate::rmeta::*; use rustc_ast as ast; -use rustc_ast::ptr::P; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::svh::Svh; @@ -33,7 +32,7 @@ use rustc_session::cstore::{ use rustc_session::Session; use rustc_span::hygiene::{ExpnIndex, MacroKind}; use rustc_span::source_map::{respan, Spanned}; -use rustc_span::symbol::{sym, Ident, Symbol}; +use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{self, BytePos, ExpnId, Pos, Span, SyntaxContext, DUMMY_SP}; use proc_macro::bridge::client::ProcMacro; @@ -42,7 +41,6 @@ use std::iter::TrustedLen; use std::mem; use std::num::NonZeroUsize; use std::path::Path; -use tracing::debug; pub(super) use cstore_impl::provide; pub use cstore_impl::provide_extern; @@ -99,7 +97,7 @@ pub(crate) struct CrateMetadata { /// Proc macro descriptions for this crate, if it's a proc macro crate. raw_proc_macros: Option<&'static [ProcMacro]>, /// Source maps for code from the crate. - source_map_import_info: OnceCell<Vec<ImportedSourceFile>>, + source_map_import_info: Lock<Vec<Option<ImportedSourceFile>>>, /// For every definition in this crate, maps its `DefPathHash` to its `DefIndex`. def_path_hash_map: DefPathHashMapRef<'static>, /// Likewise for ExpnHash. @@ -143,7 +141,8 @@ pub(crate) struct CrateMetadata { } /// Holds information about a rustc_span::SourceFile imported from another crate. -/// See `imported_source_files()` for more information. +/// See `imported_source_file()` for more information. +#[derive(Clone)] struct ImportedSourceFile { /// This SourceFile's byte-offset within the source_map of its original crate original_start_pos: rustc_span::BytePos, @@ -160,9 +159,6 @@ pub(super) struct DecodeContext<'a, 'tcx> { sess: Option<&'tcx Session>, tcx: Option<TyCtxt<'tcx>>, - // Cache the last used source_file for translating spans as an optimization. - last_source_file_index: usize, - lazy_state: LazyState, // Used for decoding interpret::AllocIds in a cached & thread-safe manner. @@ -191,7 +187,6 @@ pub(super) trait Metadata<'a, 'tcx>: Copy { blob: self.blob(), sess: self.sess().or(tcx.map(|tcx| tcx.sess)), tcx, - last_source_file_index: 0, lazy_state: LazyState::NoNode, alloc_decoding_session: self .cdata() @@ -455,6 +450,13 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for ExpnIndex { } } +impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for ast::AttrId { + fn decode(d: &mut DecodeContext<'a, 'tcx>) -> ast::AttrId { + let sess = d.sess.expect("can't decode AttrId without Session"); + sess.parse_sess.attr_id_generator.mk_attr_id() + } +} + impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for SyntaxContext { fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> SyntaxContext { let cdata = decoder.cdata(); @@ -527,6 +529,9 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span { bug!("Cannot decode Span without Session.") }; + // Index of the file in the corresponding crate's list of encoded files. + let metadata_index = u32::decode(decoder); + // There are two possibilities here: // 1. This is a 'local span', which is located inside a `SourceFile` // that came from this crate. In this case, we use the source map data @@ -553,10 +558,10 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span { // to be based on the *foreign* crate (e.g. crate C), not the crate // we are writing metadata for (e.g. crate B). This allows us to // treat the 'local' and 'foreign' cases almost identically during deserialization: - // we can call `imported_source_files` for the proper crate, and binary search + // we can call `imported_source_file` for the proper crate, and binary search // through the returned slice using our span. - let imported_source_files = if tag == TAG_VALID_SPAN_LOCAL { - decoder.cdata().imported_source_files(sess) + let source_file = if tag == TAG_VALID_SPAN_LOCAL { + decoder.cdata().imported_source_file(metadata_index, sess) } else { // When we encode a proc-macro crate, all `Span`s should be encoded // with `TAG_VALID_SPAN_LOCAL` @@ -577,66 +582,69 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span { cnum ); - // Decoding 'foreign' spans should be rare enough that it's - // not worth it to maintain a per-CrateNum cache for `last_source_file_index`. - // We just set it to 0, to ensure that we don't try to access something out - // of bounds for our initial 'guess' - decoder.last_source_file_index = 0; - let foreign_data = decoder.cdata().cstore.get_crate_data(cnum); - foreign_data.imported_source_files(sess) - }; - - let source_file = { - // Optimize for the case that most spans within a translated item - // originate from the same source_file. - let last_source_file = &imported_source_files[decoder.last_source_file_index]; - - if lo >= last_source_file.original_start_pos && lo <= last_source_file.original_end_pos - { - last_source_file - } else { - let index = imported_source_files - .binary_search_by_key(&lo, |source_file| source_file.original_start_pos) - .unwrap_or_else(|index| index - 1); - - // Don't try to cache the index for foreign spans, - // as this would require a map from CrateNums to indices - if tag == TAG_VALID_SPAN_LOCAL { - decoder.last_source_file_index = index; - } - &imported_source_files[index] - } + foreign_data.imported_source_file(metadata_index, sess) }; - // Make sure our binary search above is correct. + // Make sure our span is well-formed. debug_assert!( - lo >= source_file.original_start_pos && lo <= source_file.original_end_pos, - "Bad binary search: lo={:?} source_file.original_start_pos={:?} source_file.original_end_pos={:?}", + lo + source_file.original_start_pos <= source_file.original_end_pos, + "Malformed encoded span: lo={:?} source_file.original_start_pos={:?} source_file.original_end_pos={:?}", lo, source_file.original_start_pos, source_file.original_end_pos ); - // Make sure we correctly filtered out invalid spans during encoding + // Make sure we correctly filtered out invalid spans during encoding. debug_assert!( - hi >= source_file.original_start_pos && hi <= source_file.original_end_pos, - "Bad binary search: hi={:?} source_file.original_start_pos={:?} source_file.original_end_pos={:?}", + hi + source_file.original_start_pos <= source_file.original_end_pos, + "Malformed encoded span: hi={:?} source_file.original_start_pos={:?} source_file.original_end_pos={:?}", hi, source_file.original_start_pos, source_file.original_end_pos ); - let lo = - (lo + source_file.translated_source_file.start_pos) - source_file.original_start_pos; - let hi = - (hi + source_file.translated_source_file.start_pos) - source_file.original_start_pos; + let lo = lo + source_file.translated_source_file.start_pos; + let hi = hi + source_file.translated_source_file.start_pos; // Do not try to decode parent for foreign spans. Span::new(lo, hi, ctxt, None) } } +impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Symbol { + fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Self { + let tag = d.read_u8(); + + match tag { + SYMBOL_STR => { + let s = d.read_str(); + Symbol::intern(s) + } + SYMBOL_OFFSET => { + // read str offset + let pos = d.read_usize(); + let old_pos = d.opaque.position(); + + // move to str ofset and read + d.opaque.set_position(pos); + let s = d.read_str(); + let sym = Symbol::intern(s); + + // restore position + d.opaque.set_position(old_pos); + + sym + } + SYMBOL_PREINTERNED => { + let symbol_index = d.read_u32(); + Symbol::new_from_decoded(symbol_index) + } + _ => unreachable!(), + } + } +} + impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for &'tcx [ty::abstract_const::Node<'tcx>] { fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Self { ty::codec::RefDecodable::decode(d) @@ -783,26 +791,11 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { self.opt_item_ident(item_index, sess).expect("no encoded ident for item") } - fn maybe_kind(self, item_id: DefIndex) -> Option<EntryKind> { - self.root.tables.kind.get(self, item_id).map(|k| k.decode(self)) - } - #[inline] pub(super) fn map_encoded_cnum_to_current(self, cnum: CrateNum) -> CrateNum { if cnum == LOCAL_CRATE { self.cnum } else { self.cnum_map[cnum] } } - fn kind(self, item_id: DefIndex) -> EntryKind { - self.maybe_kind(item_id).unwrap_or_else(|| { - bug!( - "CrateMetadata::kind({:?}): id not found, in crate {:?} with number {}", - item_id, - self.root.name, - self.cnum, - ) - }) - } - fn def_kind(self, item_id: DefIndex) -> DefKind { self.root.tables.opt_def_kind.get(self, item_id).unwrap_or_else(|| { bug!( @@ -854,21 +847,16 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { ) } - fn get_variant(self, kind: &EntryKind, index: DefIndex, parent_did: DefId) -> ty::VariantDef { - let data = match kind { - EntryKind::Variant(data) | EntryKind::Struct(data) | EntryKind::Union(data) => { - data.decode(self) - } - _ => bug!(), - }; - + fn get_variant(self, kind: &DefKind, index: DefIndex, parent_did: DefId) -> ty::VariantDef { let adt_kind = match kind { - EntryKind::Variant(_) => ty::AdtKind::Enum, - EntryKind::Struct(..) => ty::AdtKind::Struct, - EntryKind::Union(..) => ty::AdtKind::Union, + DefKind::Variant => ty::AdtKind::Enum, + DefKind::Struct => ty::AdtKind::Struct, + DefKind::Union => ty::AdtKind::Union, _ => bug!(), }; + let data = self.root.tables.variant_data.get(self, index).unwrap().decode(self); + let variant_did = if adt_kind == ty::AdtKind::Enum { Some(self.local_def_id(index)) } else { None }; let ctor_did = data.ctor.map(|index| self.local_def_id(index)); @@ -899,13 +887,13 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } fn get_adt_def(self, item_id: DefIndex, tcx: TyCtxt<'tcx>) -> ty::AdtDef<'tcx> { - let kind = self.kind(item_id); + let kind = self.def_kind(item_id); let did = self.local_def_id(item_id); let adt_kind = match kind { - EntryKind::Enum => ty::AdtKind::Enum, - EntryKind::Struct(_) => ty::AdtKind::Struct, - EntryKind::Union(_) => ty::AdtKind::Union, + DefKind::Enum => ty::AdtKind::Enum, + DefKind::Struct => ty::AdtKind::Struct, + DefKind::Union => ty::AdtKind::Union, _ => bug!("get_adt_def called on a non-ADT {:?}", did), }; let repr = self.root.tables.repr_options.get(self, item_id).unwrap().decode(self); @@ -917,7 +905,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .get(self, item_id) .unwrap_or_else(LazyArray::empty) .decode(self) - .map(|index| self.get_variant(&self.kind(index), index, did)) + .map(|index| self.get_variant(&self.def_kind(index), index, did)) .collect() } else { std::iter::once(self.get_variant(&kind, item_id, did)).collect() @@ -930,8 +918,14 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { self.root.tables.generics_of.get(self, item_id).unwrap().decode((self, sess)) } - fn get_visibility(self, id: DefIndex) -> ty::Visibility { - self.root.tables.visibility.get(self, id).unwrap().decode(self) + fn get_visibility(self, id: DefIndex) -> ty::Visibility<DefId> { + self.root + .tables + .visibility + .get(self, id) + .unwrap() + .decode(self) + .map_id(|index| self.local_def_id(index)) } fn get_trait_item_def_id(self, id: DefIndex) -> Option<DefId> { @@ -1027,10 +1021,9 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { let vis = self.get_visibility(child_index); let span = self.get_span(child_index, sess); let macro_rules = match kind { - DefKind::Macro(..) => match self.kind(child_index) { - EntryKind::MacroDef(_, macro_rules) => macro_rules, - _ => unreachable!(), - }, + DefKind::Macro(..) => { + self.root.tables.macro_rules.get(self, child_index).is_some() + } _ => false, }; @@ -1084,14 +1077,10 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } } - match self.kind(id) { - EntryKind::Mod(exports) => { - for exp in exports.decode((self, sess)) { - callback(exp); - } + if let Some(exports) = self.root.tables.module_reexports.get(self, id) { + for exp in exports.decode((self, sess)) { + callback(exp); } - EntryKind::Enum | EntryKind::Trait => {} - _ => bug!("`for_each_module_child` is called on a non-module: {:?}", self.def_kind(id)), } } @@ -1104,19 +1093,21 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } fn module_expansion(self, id: DefIndex, sess: &Session) -> ExpnId { - match self.kind(id) { - EntryKind::Mod(_) | EntryKind::Enum | EntryKind::Trait => { - self.get_expn_that_defined(id, sess) - } + match self.def_kind(id) { + DefKind::Mod | DefKind::Enum | DefKind::Trait => self.get_expn_that_defined(id, sess), _ => panic!("Expected module, found {:?}", self.local_def_id(id)), } } - fn get_fn_has_self_parameter(self, id: DefIndex) -> bool { - match self.kind(id) { - EntryKind::AssocFn { has_self, .. } => has_self, - _ => false, - } + fn get_fn_has_self_parameter(self, id: DefIndex, sess: &'a Session) -> bool { + self.root + .tables + .fn_arg_names + .get(self, id) + .unwrap_or_else(LazyArray::empty) + .decode((self, sess)) + .nth(0) + .map_or(false, |ident| ident.name == kw::SelfLower) } fn get_associated_item_def_ids( @@ -1133,15 +1124,17 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .map(move |child_index| self.local_def_id(child_index)) } - fn get_associated_item(self, id: DefIndex) -> ty::AssocItem { + fn get_associated_item(self, id: DefIndex, sess: &'a Session) -> ty::AssocItem { let name = self.item_name(id); - let (kind, container, has_self) = match self.kind(id) { - EntryKind::AssocConst(container) => (ty::AssocKind::Const, container, false), - EntryKind::AssocFn { container, has_self } => (ty::AssocKind::Fn, container, has_self), - EntryKind::AssocType(container) => (ty::AssocKind::Type, container, false), - _ => bug!("cannot get associated-item of `{:?}`", id), + let kind = match self.def_kind(id) { + DefKind::AssocConst => ty::AssocKind::Const, + DefKind::AssocFn => ty::AssocKind::Fn, + DefKind::AssocTy => ty::AssocKind::Type, + _ => bug!("cannot get associated-item of `{:?}`", self.def_key(id)), }; + let has_self = self.get_fn_has_self_parameter(id, sess); + let container = self.root.tables.assoc_container.get(self, id).unwrap(); ty::AssocItem { name, @@ -1154,9 +1147,9 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } fn get_ctor_def_id_and_kind(self, node_id: DefIndex) -> Option<(DefId, CtorKind)> { - match self.kind(node_id) { - EntryKind::Struct(data) | EntryKind::Variant(data) => { - let vdata = data.decode(self); + match self.def_kind(node_id) { + DefKind::Struct | DefKind::Variant => { + let vdata = self.root.tables.variant_data.get(self, node_id).unwrap().decode(self); vdata.ctor.map(|index| (self.local_def_id(index), vdata.ctor_kind)) } _ => None, @@ -1202,7 +1195,10 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .map(move |index| respan(self.get_span(index, sess), self.item_name(index))) } - fn get_struct_field_visibilities(self, id: DefIndex) -> impl Iterator<Item = Visibility> + 'a { + fn get_struct_field_visibilities( + self, + id: DefIndex, + ) -> impl Iterator<Item = Visibility<DefId>> + 'a { self.root .tables .children @@ -1344,18 +1340,22 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } fn get_macro(self, id: DefIndex, sess: &Session) -> ast::MacroDef { - match self.kind(id) { - EntryKind::MacroDef(mac_args, macro_rules) => { - ast::MacroDef { body: P(mac_args.decode((self, sess))), macro_rules } + match self.def_kind(id) { + DefKind::Macro(_) => { + let macro_rules = self.root.tables.macro_rules.get(self, id).is_some(); + let body = + self.root.tables.macro_definition.get(self, id).unwrap().decode((self, sess)); + ast::MacroDef { macro_rules, body: ast::ptr::P(body) } } _ => bug!(), } } fn is_foreign_item(self, id: DefIndex) -> bool { - match self.kind(id) { - EntryKind::ForeignStatic | EntryKind::ForeignFn => true, - _ => false, + if let Some(parent) = self.def_key(id).parent { + matches!(self.def_kind(parent), DefKind::ForeignMod) + } else { + false } } @@ -1453,7 +1453,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { /// /// Proc macro crates don't currently export spans, so this function does not have /// to work for them. - fn imported_source_files(self, sess: &Session) -> &'a [ImportedSourceFile] { + fn imported_source_file(self, source_file_index: u32, sess: &Session) -> ImportedSourceFile { fn filter<'a>(sess: &Session, path: Option<&'a Path>) -> Option<&'a Path> { path.filter(|_| { // Only spend time on further checks if we have what to translate *to*. @@ -1541,90 +1541,96 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } }; - self.cdata.source_map_import_info.get_or_init(|| { - let external_source_map = self.root.source_map.decode(self); - - external_source_map - .map(|source_file_to_import| { - // We can't reuse an existing SourceFile, so allocate a new one - // containing the information we need. - let rustc_span::SourceFile { - mut name, - src_hash, - start_pos, - end_pos, - lines, - multibyte_chars, - non_narrow_chars, - normalized_pos, - name_hash, - .. - } = source_file_to_import; - - // If this file is under $sysroot/lib/rustlib/src/ but has not been remapped - // during rust bootstrapping by `remap-debuginfo = true`, and the user - // wish to simulate that behaviour by -Z simulate-remapped-rust-src-base, - // then we change `name` to a similar state as if the rust was bootstrapped - // with `remap-debuginfo = true`. - // This is useful for testing so that tests about the effects of - // `try_to_translate_virtual_to_real` don't have to worry about how the - // compiler is bootstrapped. - if let Some(virtual_dir) = - &sess.opts.unstable_opts.simulate_remapped_rust_src_base - { - if let Some(real_dir) = &sess.opts.real_rust_source_base_dir { - if let rustc_span::FileName::Real(ref mut old_name) = name { - if let rustc_span::RealFileName::LocalPath(local) = old_name { - if let Ok(rest) = local.strip_prefix(real_dir) { - *old_name = rustc_span::RealFileName::Remapped { - local_path: None, - virtual_name: virtual_dir.join(rest), - }; - } + let mut import_info = self.cdata.source_map_import_info.lock(); + for _ in import_info.len()..=(source_file_index as usize) { + import_info.push(None); + } + import_info[source_file_index as usize] + .get_or_insert_with(|| { + let source_file_to_import = self + .root + .source_map + .get(self, source_file_index) + .expect("missing source file") + .decode(self); + + // We can't reuse an existing SourceFile, so allocate a new one + // containing the information we need. + let rustc_span::SourceFile { + mut name, + src_hash, + start_pos, + end_pos, + lines, + multibyte_chars, + non_narrow_chars, + normalized_pos, + name_hash, + .. + } = source_file_to_import; + + // If this file is under $sysroot/lib/rustlib/src/ but has not been remapped + // during rust bootstrapping by `remap-debuginfo = true`, and the user + // wish to simulate that behaviour by -Z simulate-remapped-rust-src-base, + // then we change `name` to a similar state as if the rust was bootstrapped + // with `remap-debuginfo = true`. + // This is useful for testing so that tests about the effects of + // `try_to_translate_virtual_to_real` don't have to worry about how the + // compiler is bootstrapped. + if let Some(virtual_dir) = &sess.opts.unstable_opts.simulate_remapped_rust_src_base + { + if let Some(real_dir) = &sess.opts.real_rust_source_base_dir { + if let rustc_span::FileName::Real(ref mut old_name) = name { + if let rustc_span::RealFileName::LocalPath(local) = old_name { + if let Ok(rest) = local.strip_prefix(real_dir) { + *old_name = rustc_span::RealFileName::Remapped { + local_path: None, + virtual_name: virtual_dir.join(rest), + }; } } } } + } - // If this file's path has been remapped to `/rustc/$hash`, - // we might be able to reverse that (also see comments above, - // on `try_to_translate_virtual_to_real`). - try_to_translate_virtual_to_real(&mut name); - - let source_length = (end_pos - start_pos).to_usize(); - - let local_version = sess.source_map().new_imported_source_file( - name, - src_hash, - name_hash, - source_length, - self.cnum, - lines, - multibyte_chars, - non_narrow_chars, - normalized_pos, - start_pos, - end_pos, - ); - debug!( - "CrateMetaData::imported_source_files alloc \ + // If this file's path has been remapped to `/rustc/$hash`, + // we might be able to reverse that (also see comments above, + // on `try_to_translate_virtual_to_real`). + try_to_translate_virtual_to_real(&mut name); + + let source_length = (end_pos - start_pos).to_usize(); + + let local_version = sess.source_map().new_imported_source_file( + name, + src_hash, + name_hash, + source_length, + self.cnum, + lines, + multibyte_chars, + non_narrow_chars, + normalized_pos, + start_pos, + source_file_index, + ); + debug!( + "CrateMetaData::imported_source_files alloc \ source_file {:?} original (start_pos {:?} end_pos {:?}) \ translated (start_pos {:?} end_pos {:?})", - local_version.name, - start_pos, - end_pos, - local_version.start_pos, - local_version.end_pos - ); + local_version.name, + start_pos, + end_pos, + local_version.start_pos, + local_version.end_pos + ); - ImportedSourceFile { - original_start_pos: start_pos, - original_end_pos: end_pos, - translated_source_file: local_version, - } - }) - .collect() - }) + ImportedSourceFile { + original_start_pos: start_pos, + original_end_pos: end_pos, + translated_source_file: local_version, + } + }) + .clone() } fn get_generator_diagnostic_data( @@ -1687,7 +1693,7 @@ impl CrateMetadata { trait_impls, incoherent_impls: Default::default(), raw_proc_macros, - source_map_import_info: OnceCell::new(), + source_map_import_info: Lock::new(Vec::new()), def_path_hash_map, expn_hash_map: Default::default(), alloc_decoding_state, diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 38ce50e83..dede1b212 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -76,9 +76,9 @@ impl ProcessQueryValue<'_, Option<DeprecationEntry>> for Option<Deprecation> { } macro_rules! provide_one { - (<$lt:tt> $tcx:ident, $def_id:ident, $other:ident, $cdata:ident, $name:ident => { table }) => { + ($tcx:ident, $def_id:ident, $other:ident, $cdata:ident, $name:ident => { table }) => { provide_one! { - <$lt> $tcx, $def_id, $other, $cdata, $name => { + $tcx, $def_id, $other, $cdata, $name => { $cdata .root .tables @@ -89,9 +89,9 @@ macro_rules! provide_one { } } }; - (<$lt:tt> $tcx:ident, $def_id:ident, $other:ident, $cdata:ident, $name:ident => { table_direct }) => { + ($tcx:ident, $def_id:ident, $other:ident, $cdata:ident, $name:ident => { table_direct }) => { provide_one! { - <$lt> $tcx, $def_id, $other, $cdata, $name => { + $tcx, $def_id, $other, $cdata, $name => { // We don't decode `table_direct`, since it's not a Lazy, but an actual value $cdata .root @@ -102,11 +102,11 @@ macro_rules! provide_one { } } }; - (<$lt:tt> $tcx:ident, $def_id:ident, $other:ident, $cdata:ident, $name:ident => $compute:block) => { - fn $name<$lt>( - $tcx: TyCtxt<$lt>, - def_id_arg: ty::query::query_keys::$name<$lt>, - ) -> ty::query::query_values::$name<$lt> { + ($tcx:ident, $def_id:ident, $other:ident, $cdata:ident, $name:ident => $compute:block) => { + fn $name<'tcx>( + $tcx: TyCtxt<'tcx>, + def_id_arg: ty::query::query_keys::$name<'tcx>, + ) -> ty::query::query_values::$name<'tcx> { let _prof_timer = $tcx.prof.generic_activity(concat!("metadata_decode_entry_", stringify!($name))); @@ -130,11 +130,11 @@ macro_rules! provide_one { } macro_rules! provide { - (<$lt:tt> $tcx:ident, $def_id:ident, $other:ident, $cdata:ident, + ($tcx:ident, $def_id:ident, $other:ident, $cdata:ident, $($name:ident => { $($compute:tt)* })*) => { pub fn provide_extern(providers: &mut ExternProviders) { $(provide_one! { - <$lt> $tcx, $def_id, $other, $cdata, $name => { $($compute)* } + $tcx, $def_id, $other, $cdata, $name => { $($compute)* } })* *providers = ExternProviders { @@ -187,7 +187,7 @@ impl IntoArgs for (CrateNum, SimplifiedType) { } } -provide! { <'tcx> tcx, def_id, other, cdata, +provide! { tcx, def_id, other, cdata, explicit_item_bounds => { table } explicit_predicates_of => { table } generics_of => { table } @@ -199,6 +199,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, codegen_fn_attrs => { table } impl_trait_ref => { table } const_param_default => { table } + object_lifetime_default => { table } thir_abstract_const => { table } optimized_mir => { table } mir_for_ctfe => { table } @@ -207,8 +208,8 @@ provide! { <'tcx> tcx, def_id, other, cdata, def_ident_span => { table } lookup_stability => { table } lookup_const_stability => { table } + lookup_default_body_stability => { table } lookup_deprecation_entry => { table } - visibility => { table } unused_generic_params => { table } opt_def_kind => { table_direct } impl_parent => { table } @@ -223,6 +224,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, generator_kind => { table } trait_def => { table } + visibility => { cdata.get_visibility(def_id.index) } adt_def => { cdata.get_adt_def(def_id.index, tcx) } adt_destructor => { let _ = cdata; @@ -231,7 +233,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, associated_item_def_ids => { tcx.arena.alloc_from_iter(cdata.get_associated_item_def_ids(def_id.index, tcx.sess)) } - associated_item => { cdata.get_associated_item(def_id.index) } + associated_item => { cdata.get_associated_item(def_id.index, tcx.sess) } inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) } is_foreign_item => { cdata.is_foreign_item(def_id.index) } item_attrs => { tcx.arena.alloc_from_iter(cdata.get_item_attrs(def_id.index, tcx.sess)) } @@ -340,7 +342,8 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) { assert_eq!(cnum, LOCAL_CRATE); false }, - native_library_kind: |tcx, id| { + native_library_kind: |tcx, id| tcx.native_library(id).map(|l| l.kind), + native_library: |tcx, id| { tcx.native_libraries(id.krate) .iter() .filter(|lib| native_libs::relevant_lib(&tcx.sess, lib)) @@ -354,7 +357,6 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) { .foreign_items .contains(&id) }) - .map(|l| l.kind) }, native_libraries: |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); @@ -483,7 +485,7 @@ impl CStore { pub fn struct_field_visibilities_untracked( &self, def: DefId, - ) -> impl Iterator<Item = Visibility> + '_ { + ) -> impl Iterator<Item = Visibility<DefId>> + '_ { self.get_crate_data(def.krate).get_struct_field_visibilities(def.index) } @@ -491,7 +493,7 @@ impl CStore { self.get_crate_data(def.krate).get_ctor_def_id_and_kind(def.index) } - pub fn visibility_untracked(&self, def: DefId) -> Visibility { + pub fn visibility_untracked(&self, def: DefId) -> Visibility<DefId> { self.get_crate_data(def.krate).get_visibility(def.index) } @@ -533,8 +535,8 @@ impl CStore { ) } - pub fn fn_has_self_parameter_untracked(&self, def: DefId) -> bool { - self.get_crate_data(def.krate).get_fn_has_self_parameter(def.index) + pub fn fn_has_self_parameter_untracked(&self, def: DefId, sess: &Session) -> bool { + self.get_crate_data(def.krate).get_fn_has_self_parameter(def.index, sess) } pub fn crate_source_untracked(&self, cnum: CrateNum) -> Lrc<CrateSource> { @@ -675,6 +677,9 @@ impl CrateStore for CStore { } fn import_source_files(&self, sess: &Session, cnum: CrateNum) { - self.get_crate_data(cnum).imported_source_files(sess); + let cdata = self.get_crate_data(cnum); + for file_index in 0..cdata.root.source_map.size() { + cdata.imported_source_file(file_index as u32, sess); + } } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 33278367c..5a60ea794 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1,3 +1,4 @@ +use crate::errors::{FailCreateFileEncoder, FailSeekFile, FailWriteFile}; use crate::rmeta::def_path_hash_map::DefPathHashMapRef; use crate::rmeta::table::TableBuilder; use crate::rmeta::*; @@ -16,8 +17,6 @@ use rustc_hir::def_id::{ use rustc_hir::definitions::DefPathData; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::lang_items; -use rustc_hir::{AnonConst, GenericParamKind}; -use rustc_index::bit_set::GrowableBitSet; use rustc_middle::hir::nested_filter; use rustc_middle::middle::dependency_format::Linkage; use rustc_middle::middle::exported_symbols::{ @@ -39,12 +38,12 @@ use rustc_span::{ }; use rustc_target::abi::VariantIdx; use std::borrow::Borrow; +use std::collections::hash_map::Entry; use std::hash::Hash; use std::io::{Read, Seek, Write}; use std::iter; use std::num::NonZeroUsize; use std::path::{Path, PathBuf}; -use tracing::{debug, trace}; pub(super) struct EncodeContext<'a, 'tcx> { opaque: opaque::FileEncoder, @@ -66,15 +65,13 @@ pub(super) struct EncodeContext<'a, 'tcx> { // The indices (into the `SourceMap`'s `MonotonicVec`) // of all of the `SourceFiles` that we need to serialize. // When we serialize a `Span`, we insert the index of its - // `SourceFile` into the `GrowableBitSet`. - // - // This needs to be a `GrowableBitSet` and not a - // regular `BitSet` because we may actually import new `SourceFiles` - // during metadata encoding, due to executing a query - // with a result containing a foreign `Span`. - required_source_files: Option<GrowableBitSet<usize>>, + // `SourceFile` into the `FxIndexSet`. + // The order inside the `FxIndexSet` is used as on-disk + // order of `SourceFiles`, and encoded inside `Span`s. + required_source_files: Option<FxIndexSet<usize>>, is_proc_macro: bool, hygiene_ctxt: &'a HygieneEncodeContext, + symbol_table: FxHashMap<Symbol, usize>, } /// If the current crate is a proc-macro, returns early with `Lazy:empty()`. @@ -238,17 +235,15 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span { s.source_file_cache = (source_map.files()[source_file_index].clone(), source_file_index); } + let (ref source_file, source_file_index) = s.source_file_cache; + debug_assert!(source_file.contains(span.lo)); - if !s.source_file_cache.0.contains(span.hi) { + if !source_file.contains(span.hi) { // Unfortunately, macro expansion still sometimes generates Spans // that malformed in this way. return TAG_PARTIAL_SPAN.encode(s); } - let source_files = s.required_source_files.as_mut().expect("Already encoded SourceMap!"); - // Record the fact that we need to encode the data for this `SourceFile` - source_files.insert(s.source_file_cache.1); - // There are two possible cases here: // 1. This span comes from a 'foreign' crate - e.g. some crate upstream of the // crate we are writing metadata for. When the metadata for *this* crate gets @@ -265,7 +260,7 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span { // if we're a proc-macro crate. // This allows us to avoid loading the dependencies of proc-macro crates: all of // the information we need to decode `Span`s is stored in the proc-macro crate. - let (tag, lo, hi) = if s.source_file_cache.0.is_imported() && !s.is_proc_macro { + let (tag, metadata_index) = if source_file.is_imported() && !s.is_proc_macro { // To simplify deserialization, we 'rebase' this span onto the crate it originally came from // (the crate that 'owns' the file it references. These rebased 'lo' and 'hi' values // are relative to the source map information for the 'foreign' crate whose CrateNum @@ -275,29 +270,41 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span { // // All of this logic ensures that the final result of deserialization is a 'normal' // Span that can be used without any additional trouble. - let external_start_pos = { + let metadata_index = { // Introduce a new scope so that we drop the 'lock()' temporary - match &*s.source_file_cache.0.external_src.lock() { - ExternalSource::Foreign { original_start_pos, .. } => *original_start_pos, + match &*source_file.external_src.lock() { + ExternalSource::Foreign { metadata_index, .. } => *metadata_index, src => panic!("Unexpected external source {:?}", src), } }; - let lo = (span.lo - s.source_file_cache.0.start_pos) + external_start_pos; - let hi = (span.hi - s.source_file_cache.0.start_pos) + external_start_pos; - (TAG_VALID_SPAN_FOREIGN, lo, hi) + (TAG_VALID_SPAN_FOREIGN, metadata_index) } else { - (TAG_VALID_SPAN_LOCAL, span.lo, span.hi) + // Record the fact that we need to encode the data for this `SourceFile` + let source_files = + s.required_source_files.as_mut().expect("Already encoded SourceMap!"); + let (metadata_index, _) = source_files.insert_full(source_file_index); + let metadata_index: u32 = + metadata_index.try_into().expect("cannot export more than U32_MAX files"); + + (TAG_VALID_SPAN_LOCAL, metadata_index) }; - tag.encode(s); - lo.encode(s); + // Encode the start position relative to the file start, so we profit more from the + // variable-length integer encoding. + let lo = span.lo - source_file.start_pos; // Encode length which is usually less than span.hi and profits more // from the variable-length integer encoding that we use. - let len = hi - lo; + let len = span.hi - span.lo; + + tag.encode(s); + lo.encode(s); len.encode(s); + // Encode the index of the `SourceFile` for the span, in order to make decoding faster. + metadata_index.encode(s); + if tag == TAG_VALID_SPAN_FOREIGN { // This needs to be two lines to avoid holding the `s.source_file_cache` // while calling `cnum.encode(s)` @@ -307,6 +314,31 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span { } } +impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Symbol { + fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) { + // if symbol preinterned, emit tag and symbol index + if self.is_preinterned() { + s.opaque.emit_u8(SYMBOL_PREINTERNED); + s.opaque.emit_u32(self.as_u32()); + } else { + // otherwise write it as string or as offset to it + match s.symbol_table.entry(*self) { + Entry::Vacant(o) => { + s.opaque.emit_u8(SYMBOL_STR); + let pos = s.opaque.position(); + o.insert(pos); + s.emit_str(self.as_str()); + } + Entry::Occupied(o) => { + let x = o.get().clone(); + s.emit_u8(SYMBOL_OFFSET); + s.emit_usize(x); + } + } + } + } +} + impl<'a, 'tcx> TyEncoder for EncodeContext<'a, 'tcx> { const CLEAR_CROSS_CRATE: bool = true; @@ -449,7 +481,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.lazy(DefPathHashMapRef::BorrowedFromTcx(self.tcx.def_path_hash_to_def_index_map())) } - fn encode_source_map(&mut self) -> LazyArray<rustc_span::SourceFile> { + fn encode_source_map(&mut self) -> LazyTable<u32, LazyValue<rustc_span::SourceFile>> { let source_map = self.tcx.sess.source_map(); let all_source_files = source_map.files(); @@ -460,66 +492,64 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let working_directory = &self.tcx.sess.opts.working_dir; - let adapted = all_source_files - .iter() - .enumerate() - .filter(|(idx, source_file)| { - // Only serialize `SourceFile`s that were used - // during the encoding of a `Span` - required_source_files.contains(*idx) && - // Don't serialize imported `SourceFile`s, unless - // we're in a proc-macro crate. - (!source_file.is_imported() || self.is_proc_macro) - }) - .map(|(_, source_file)| { - // At export time we expand all source file paths to absolute paths because - // downstream compilation sessions can have a different compiler working - // directory, so relative paths from this or any other upstream crate - // won't be valid anymore. - // - // At this point we also erase the actual on-disk path and only keep - // the remapped version -- as is necessary for reproducible builds. - match source_file.name { - FileName::Real(ref original_file_name) => { - let adapted_file_name = - source_map.path_mapping().to_embeddable_absolute_path( - original_file_name.clone(), - working_directory, - ); - - if adapted_file_name != *original_file_name { - let mut adapted: SourceFile = (**source_file).clone(); - adapted.name = FileName::Real(adapted_file_name); - adapted.name_hash = { - let mut hasher: StableHasher = StableHasher::new(); - adapted.name.hash(&mut hasher); - hasher.finish::<u128>() - }; - Lrc::new(adapted) - } else { - // Nothing to adapt - source_file.clone() - } + let mut adapted = TableBuilder::default(); + + // Only serialize `SourceFile`s that were used during the encoding of a `Span`. + // + // The order in which we encode source files is important here: the on-disk format for + // `Span` contains the index of the corresponding `SourceFile`. + for (on_disk_index, &source_file_index) in required_source_files.iter().enumerate() { + let source_file = &all_source_files[source_file_index]; + // Don't serialize imported `SourceFile`s, unless we're in a proc-macro crate. + assert!(!source_file.is_imported() || self.is_proc_macro); + + // At export time we expand all source file paths to absolute paths because + // downstream compilation sessions can have a different compiler working + // directory, so relative paths from this or any other upstream crate + // won't be valid anymore. + // + // At this point we also erase the actual on-disk path and only keep + // the remapped version -- as is necessary for reproducible builds. + let mut source_file = match source_file.name { + FileName::Real(ref original_file_name) => { + let adapted_file_name = source_map + .path_mapping() + .to_embeddable_absolute_path(original_file_name.clone(), working_directory); + + if adapted_file_name != *original_file_name { + let mut adapted: SourceFile = (**source_file).clone(); + adapted.name = FileName::Real(adapted_file_name); + adapted.name_hash = { + let mut hasher: StableHasher = StableHasher::new(); + adapted.name.hash(&mut hasher); + hasher.finish::<u128>() + }; + Lrc::new(adapted) + } else { + // Nothing to adapt + source_file.clone() } - // expanded code, not from a file - _ => source_file.clone(), - } - }) - .map(|mut source_file| { - // We're serializing this `SourceFile` into our crate metadata, - // so mark it as coming from this crate. - // This also ensures that we don't try to deserialize the - // `CrateNum` for a proc-macro dependency - since proc macro - // dependencies aren't loaded when we deserialize a proc-macro, - // trying to remap the `CrateNum` would fail. - if self.is_proc_macro { - Lrc::make_mut(&mut source_file).cnum = LOCAL_CRATE; } - source_file - }) - .collect::<Vec<_>>(); + // expanded code, not from a file + _ => source_file.clone(), + }; + + // We're serializing this `SourceFile` into our crate metadata, + // so mark it as coming from this crate. + // This also ensures that we don't try to deserialize the + // `CrateNum` for a proc-macro dependency - since proc macro + // dependencies aren't loaded when we deserialize a proc-macro, + // trying to remap the `CrateNum` would fail. + if self.is_proc_macro { + Lrc::make_mut(&mut source_file).cnum = LOCAL_CRATE; + } + + let on_disk_index: u32 = + on_disk_index.try_into().expect("cannot export more than U32_MAX files"); + adapted.set(on_disk_index, self.lazy(source_file)); + } - self.lazy_array(adapted.iter().map(|rc| &**rc)) + adapted.encode(&mut self.opaque) } fn encode_crate_root(&mut self) -> LazyValue<CrateRoot> { @@ -817,6 +847,7 @@ fn should_encode_visibility(def_kind: DefKind) -> bool { | DefKind::Use | DefKind::ForeignMod | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::Impl | DefKind::Field => true, DefKind::TyParam @@ -849,6 +880,7 @@ fn should_encode_stability(def_kind: DefKind) -> bool { | DefKind::ForeignMod | DefKind::TyAlias | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::Enum | DefKind::Union | DefKind::Impl @@ -937,6 +969,7 @@ fn should_encode_variances(def_kind: DefKind) -> bool { | DefKind::ForeignMod | DefKind::TyAlias | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::Impl | DefKind::Trait | DefKind::TraitAlias @@ -973,6 +1006,7 @@ fn should_encode_generics(def_kind: DefKind) -> bool { | DefKind::AnonConst | DefKind::InlineConst | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::Impl | DefKind::Field | DefKind::TyParam @@ -989,6 +1023,103 @@ fn should_encode_generics(def_kind: DefKind) -> bool { } } +fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) -> bool { + match def_kind { + DefKind::Struct + | DefKind::Union + | DefKind::Enum + | DefKind::Variant + | DefKind::Ctor(..) + | DefKind::Field + | DefKind::Fn + | DefKind::Const + | DefKind::Static(..) + | DefKind::TyAlias + | DefKind::OpaqueTy + | DefKind::ForeignTy + | DefKind::Impl + | DefKind::AssocFn + | DefKind::AssocConst + | DefKind::Closure + | DefKind::Generator + | DefKind::ConstParam + | DefKind::AnonConst + | DefKind::InlineConst => true, + + DefKind::ImplTraitPlaceholder => { + let parent_def_id = tcx.impl_trait_in_trait_parent(def_id.to_def_id()); + let assoc_item = tcx.associated_item(parent_def_id); + match assoc_item.container { + // Always encode an RPIT in an impl fn, since it always has a body + ty::AssocItemContainer::ImplContainer => true, + ty::AssocItemContainer::TraitContainer => { + // Encode an RPIT for a trait only if the trait has a default body + assoc_item.defaultness(tcx).has_value() + } + } + } + + DefKind::AssocTy => { + let assoc_item = tcx.associated_item(def_id); + match assoc_item.container { + ty::AssocItemContainer::ImplContainer => true, + ty::AssocItemContainer::TraitContainer => assoc_item.defaultness(tcx).has_value(), + } + } + DefKind::TyParam => { + let hir::Node::GenericParam(param) = tcx.hir().get_by_def_id(def_id) else { bug!() }; + let hir::GenericParamKind::Type { default, .. } = param.kind else { bug!() }; + default.is_some() + } + + DefKind::Trait + | DefKind::TraitAlias + | DefKind::Mod + | DefKind::ForeignMod + | DefKind::Macro(..) + | DefKind::Use + | DefKind::LifetimeParam + | DefKind::GlobalAsm + | DefKind::ExternCrate => false, + } +} + +fn should_encode_const(def_kind: DefKind) -> bool { + match def_kind { + DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => true, + + DefKind::Struct + | DefKind::Union + | DefKind::Enum + | DefKind::Variant + | DefKind::Ctor(..) + | DefKind::Field + | DefKind::Fn + | DefKind::Static(..) + | DefKind::TyAlias + | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder + | DefKind::ForeignTy + | DefKind::Impl + | DefKind::AssocFn + | DefKind::Closure + | DefKind::Generator + | DefKind::ConstParam + | DefKind::InlineConst + | DefKind::AssocTy + | DefKind::TyParam + | DefKind::Trait + | DefKind::TraitAlias + | DefKind::Mod + | DefKind::ForeignMod + | DefKind::Macro(..) + | DefKind::Use + | DefKind::LifetimeParam + | DefKind::GlobalAsm + | DefKind::ExternCrate => false, + } +} + impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_attrs(&mut self, def_id: LocalDefId) { let mut attrs = self @@ -1014,7 +1145,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let def_kind = tcx.opt_def_kind(local_id); let Some(def_kind) = def_kind else { continue }; self.tables.opt_def_kind.set(def_id.index, def_kind); - record!(self.tables.def_span[def_id] <- tcx.def_span(def_id)); + let def_span = tcx.def_span(local_id); + record!(self.tables.def_span[def_id] <- def_span); self.encode_attrs(local_id); record!(self.tables.expn_that_defined[def_id] <- self.tcx.expn_that_defined(def_id)); if let Some(ident_span) = tcx.def_ident_span(def_id) { @@ -1024,11 +1156,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record!(self.tables.codegen_fn_attrs[def_id] <- self.tcx.codegen_fn_attrs(def_id)); } if should_encode_visibility(def_kind) { - record!(self.tables.visibility[def_id] <- self.tcx.visibility(def_id)); + let vis = + self.tcx.local_visibility(local_id).map_id(|def_id| def_id.local_def_index); + record!(self.tables.visibility[def_id] <- vis); } if should_encode_stability(def_kind) { self.encode_stability(def_id); self.encode_const_stability(def_id); + self.encode_default_body_stability(def_id); self.encode_deprecation(def_id); } if should_encode_variances(def_kind) { @@ -1044,6 +1179,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record_array!(self.tables.inferred_outlives_of[def_id] <- inferred_outlives); } } + if should_encode_type(tcx, local_id, def_kind) { + record!(self.tables.type_of[def_id] <- self.tcx.type_of(def_id)); + } + if let DefKind::TyParam = def_kind { + let default = self.tcx.object_lifetime_default(def_id); + record!(self.tables.object_lifetime_default[def_id] <- default); + } if let DefKind::Trait | DefKind::TraitAlias = def_kind { record!(self.tables.super_predicates_of[def_id] <- self.tcx.super_predicates_of(def_id)); } @@ -1060,11 +1202,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } } - fn encode_item_type(&mut self, def_id: DefId) { - debug!("EncodeContext::encode_item_type({:?})", def_id); - record!(self.tables.type_of[def_id] <- self.tcx.type_of(def_id)); - } - fn encode_enum_variant_info(&mut self, def: ty::AdtDef<'tcx>, index: VariantIdx) { let tcx = self.tcx; let variant = &def.variant(index); @@ -1078,13 +1215,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { is_non_exhaustive: variant.is_field_list_non_exhaustive(), }; - record!(self.tables.kind[def_id] <- EntryKind::Variant(self.lazy(data))); + record!(self.tables.variant_data[def_id] <- data); self.tables.constness.set(def_id.index, hir::Constness::Const); record_array!(self.tables.children[def_id] <- variant.fields.iter().map(|f| { assert!(f.did.is_local()); f.did.index })); - self.encode_item_type(def_id); if variant.ctor_kind == CtorKind::Fn { // FIXME(eddyb) encode signature only in `encode_enum_variant_ctor`. if let Some(ctor_def_id) = variant.ctor_def_id { @@ -1107,9 +1243,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { is_non_exhaustive: variant.is_field_list_non_exhaustive(), }; - record!(self.tables.kind[def_id] <- EntryKind::Variant(self.lazy(data))); + record!(self.tables.variant_data[def_id] <- data); self.tables.constness.set(def_id.index, hir::Constness::Const); - self.encode_item_type(def_id); if variant.ctor_kind == CtorKind::Fn { record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id)); } @@ -1126,15 +1261,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // code uses it). However, we skip encoding anything relating to child // items - we encode information about proc-macros later on. let reexports = if !self.is_proc_macro { - match tcx.module_reexports(local_def_id) { - Some(exports) => self.lazy_array(exports), - _ => LazyArray::empty(), - } + tcx.module_reexports(local_def_id).unwrap_or(&[]) } else { - LazyArray::empty() + &[] }; - record!(self.tables.kind[def_id] <- EntryKind::Mod(reexports)); + record_array!(self.tables.module_reexports[def_id] <- reexports); if self.is_proc_macro { // Encode this here because we don't do it in encode_def_ids. record!(self.tables.expn_that_defined[def_id] <- tcx.expn_that_defined(local_def_id)); @@ -1162,22 +1294,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } } - fn encode_field( - &mut self, - adt_def: ty::AdtDef<'tcx>, - variant_index: VariantIdx, - field_index: usize, - ) { - let variant = &adt_def.variant(variant_index); - let field = &variant.fields[field_index]; - - let def_id = field.did; - debug!("EncodeContext::encode_field({:?})", def_id); - - record!(self.tables.kind[def_id] <- EntryKind::Field); - self.encode_item_type(def_id); - } - fn encode_struct_ctor(&mut self, adt_def: ty::AdtDef<'tcx>, def_id: DefId) { debug!("EncodeContext::encode_struct_ctor({:?})", def_id); let tcx = self.tcx; @@ -1191,9 +1307,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { }; record!(self.tables.repr_options[def_id] <- adt_def.repr()); + record!(self.tables.variant_data[def_id] <- data); self.tables.constness.set(def_id.index, hir::Constness::Const); - record!(self.tables.kind[def_id] <- EntryKind::Struct(self.lazy(data))); - self.encode_item_type(def_id); if variant.ctor_kind == CtorKind::Fn { record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id)); } @@ -1214,18 +1329,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let ast_item = tcx.hir().expect_trait_item(def_id.expect_local()); self.tables.impl_defaultness.set(def_id.index, ast_item.defaultness); let trait_item = tcx.associated_item(def_id); + self.tables.assoc_container.set(def_id.index, trait_item.container); match trait_item.kind { - ty::AssocKind::Const => { - let rendered = rustc_hir_pretty::to_string( - &(&self.tcx.hir() as &dyn intravisit::Map<'_>), - |s| s.print_trait_item(ast_item), - ); - - record!(self.tables.kind[def_id] <- EntryKind::AssocConst(ty::AssocItemContainer::TraitContainer)); - record!(self.tables.mir_const_qualif[def_id] <- mir::ConstQualifs::default()); - record!(self.tables.rendered_const[def_id] <- rendered); - } + ty::AssocKind::Const => {} ty::AssocKind::Fn => { let hir::TraitItemKind::Fn(m_sig, m) = &ast_item.kind else { bug!() }; match *m { @@ -1238,24 +1345,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { }; self.tables.asyncness.set(def_id.index, m_sig.header.asyncness); self.tables.constness.set(def_id.index, hir::Constness::NotConst); - record!(self.tables.kind[def_id] <- EntryKind::AssocFn { - container: ty::AssocItemContainer::TraitContainer, - has_self: trait_item.fn_has_self_parameter, - }); } ty::AssocKind::Type => { self.encode_explicit_item_bounds(def_id); - record!(self.tables.kind[def_id] <- EntryKind::AssocType(ty::AssocItemContainer::TraitContainer)); - } - } - match trait_item.kind { - ty::AssocKind::Const | ty::AssocKind::Fn => { - self.encode_item_type(def_id); - } - ty::AssocKind::Type => { - if ast_item.defaultness.has_value() { - self.encode_item_type(def_id); - } } } if trait_item.kind == ty::AssocKind::Fn { @@ -1270,20 +1362,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let ast_item = self.tcx.hir().expect_impl_item(def_id.expect_local()); self.tables.impl_defaultness.set(def_id.index, ast_item.defaultness); let impl_item = self.tcx.associated_item(def_id); + self.tables.assoc_container.set(def_id.index, impl_item.container); match impl_item.kind { - ty::AssocKind::Const => { - if let hir::ImplItemKind::Const(_, body_id) = ast_item.kind { - let qualifs = self.tcx.at(ast_item.span).mir_const_qualif(def_id); - let const_data = self.encode_rendered_const_for_body(body_id); - - record!(self.tables.kind[def_id] <- EntryKind::AssocConst(ty::AssocItemContainer::ImplContainer)); - record!(self.tables.mir_const_qualif[def_id] <- qualifs); - record!(self.tables.rendered_const[def_id] <- const_data); - } else { - bug!() - } - } ty::AssocKind::Fn => { let hir::ImplItemKind::Fn(ref sig, body) = ast_item.kind else { bug!() }; self.tables.asyncness.set(def_id.index, sig.header.asyncness); @@ -1295,16 +1376,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { hir::Constness::NotConst }; self.tables.constness.set(def_id.index, constness); - record!(self.tables.kind[def_id] <- EntryKind::AssocFn { - container: ty::AssocItemContainer::ImplContainer, - has_self: impl_item.fn_has_self_parameter, - }); - } - ty::AssocKind::Type => { - record!(self.tables.kind[def_id] <- EntryKind::AssocType(ty::AssocItemContainer::ImplContainer)); } + ty::AssocKind::Const | ty::AssocKind::Type => {} } - self.encode_item_type(def_id); if let Some(trait_item_def_id) = impl_item.trait_item_def_id { self.tables.trait_item_def_id.set(def_id.index, trait_item_def_id.into()); } @@ -1321,40 +1395,43 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { return; } - let keys_and_jobs = self - .tcx - .mir_keys(()) - .iter() - .filter_map(|&def_id| { - let (encode_const, encode_opt) = should_encode_mir(self.tcx, def_id); - if encode_const || encode_opt { - Some((def_id, encode_const, encode_opt)) - } else { - None - } - }) - .collect::<Vec<_>>(); - for (def_id, encode_const, encode_opt) in keys_and_jobs.into_iter() { + let tcx = self.tcx; + + let keys_and_jobs = tcx.mir_keys(()).iter().filter_map(|&def_id| { + let (encode_const, encode_opt) = should_encode_mir(tcx, def_id); + if encode_const || encode_opt { Some((def_id, encode_const, encode_opt)) } else { None } + }); + for (def_id, encode_const, encode_opt) in keys_and_jobs { debug_assert!(encode_const || encode_opt); debug!("EntryBuilder::encode_mir({:?})", def_id); if encode_opt { - record!(self.tables.optimized_mir[def_id.to_def_id()] <- self.tcx.optimized_mir(def_id)); + record!(self.tables.optimized_mir[def_id.to_def_id()] <- tcx.optimized_mir(def_id)); } if encode_const { - record!(self.tables.mir_for_ctfe[def_id.to_def_id()] <- self.tcx.mir_for_ctfe(def_id)); + record!(self.tables.mir_for_ctfe[def_id.to_def_id()] <- tcx.mir_for_ctfe(def_id)); // FIXME(generic_const_exprs): this feels wrong to have in `encode_mir` - let abstract_const = self.tcx.thir_abstract_const(def_id); + let abstract_const = tcx.thir_abstract_const(def_id); if let Ok(Some(abstract_const)) = abstract_const { record!(self.tables.thir_abstract_const[def_id.to_def_id()] <- abstract_const); } + + if should_encode_const(tcx.def_kind(def_id)) { + let qualifs = tcx.mir_const_qualif(def_id); + record!(self.tables.mir_const_qualif[def_id.to_def_id()] <- qualifs); + let body_id = tcx.hir().maybe_body_owned_by(def_id); + if let Some(body_id) = body_id { + let const_data = self.encode_rendered_const_for_body(body_id); + record!(self.tables.rendered_const[def_id.to_def_id()] <- const_data); + } + } } - record!(self.tables.promoted_mir[def_id.to_def_id()] <- self.tcx.promoted_mir(def_id)); + record!(self.tables.promoted_mir[def_id.to_def_id()] <- tcx.promoted_mir(def_id)); let instance = ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id.to_def_id())); - let unused = self.tcx.unused_generic_params(instance); + let unused = tcx.unused_generic_params(instance); if !unused.is_empty() { record!(self.tables.unused_generic_params[def_id.to_def_id()] <- unused); } @@ -1385,6 +1462,18 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } } + fn encode_default_body_stability(&mut self, def_id: DefId) { + debug!("EncodeContext::encode_default_body_stability({:?})", def_id); + + // The query lookup can take a measurable amount of time in crates with many items. Check if + // the stability attributes are even enabled before using their queries. + if self.feat.staged_api || self.tcx.sess.opts.unstable_opts.force_unstable_if_unmarked { + if let Some(stab) = self.tcx.lookup_default_body_stability(def_id) { + record!(self.tables.lookup_default_body_stability[def_id] <- stab) + } + } + } + fn encode_deprecation(&mut self, def_id: DefId) { debug!("EncodeContext::encode_deprecation({:?})", def_id); if let Some(depr) = self.tcx.lookup_deprecation(def_id) { @@ -1405,38 +1494,27 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { debug!("EncodeContext::encode_info_for_item({:?})", def_id); - let entry_kind = match item.kind { - hir::ItemKind::Static(..) => EntryKind::Static, - hir::ItemKind::Const(_, body_id) => { - let qualifs = self.tcx.at(item.span).mir_const_qualif(def_id); - let const_data = self.encode_rendered_const_for_body(body_id); - record!(self.tables.mir_const_qualif[def_id] <- qualifs); - record!(self.tables.rendered_const[def_id] <- const_data); - EntryKind::Const - } + match item.kind { hir::ItemKind::Fn(ref sig, .., body) => { self.tables.asyncness.set(def_id.index, sig.header.asyncness); record_array!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body)); self.tables.constness.set(def_id.index, sig.header.constness); - EntryKind::Fn } hir::ItemKind::Macro(ref macro_def, _) => { - EntryKind::MacroDef(self.lazy(&*macro_def.body), macro_def.macro_rules) + if macro_def.macro_rules { + self.tables.macro_rules.set(def_id.index, ()); + } + record!(self.tables.macro_definition[def_id] <- &*macro_def.body); } hir::ItemKind::Mod(ref m) => { return self.encode_info_for_mod(item.def_id, m); } - hir::ItemKind::ForeignMod { .. } => EntryKind::ForeignMod, - hir::ItemKind::GlobalAsm(..) => EntryKind::GlobalAsm, - hir::ItemKind::TyAlias(..) => EntryKind::Type, hir::ItemKind::OpaqueTy(..) => { self.encode_explicit_item_bounds(def_id); - EntryKind::OpaqueTy } hir::ItemKind::Enum(..) => { let adt_def = self.tcx.adt_def(def_id); record!(self.tables.repr_options[def_id] <- adt_def.repr()); - EntryKind::Enum } hir::ItemKind::Struct(ref struct_def, _) => { let adt_def = self.tcx.adt_def(def_id); @@ -1451,24 +1529,24 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { .map(|ctor_hir_id| self.tcx.hir().local_def_id(ctor_hir_id).local_def_index); let variant = adt_def.non_enum_variant(); - EntryKind::Struct(self.lazy(VariantData { + record!(self.tables.variant_data[def_id] <- VariantData { ctor_kind: variant.ctor_kind, discr: variant.discr, ctor, is_non_exhaustive: variant.is_field_list_non_exhaustive(), - })) + }); } hir::ItemKind::Union(..) => { let adt_def = self.tcx.adt_def(def_id); record!(self.tables.repr_options[def_id] <- adt_def.repr()); let variant = adt_def.non_enum_variant(); - EntryKind::Union(self.lazy(VariantData { + record!(self.tables.variant_data[def_id] <- VariantData { ctor_kind: variant.ctor_kind, discr: variant.discr, ctor: None, is_non_exhaustive: variant.is_field_list_non_exhaustive(), - })) + }); } hir::ItemKind::Impl(hir::Impl { defaultness, constness, .. }) => { self.tables.impl_defaultness.set(def_id.index, *defaultness); @@ -1494,26 +1572,24 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let polarity = self.tcx.impl_polarity(def_id); self.tables.impl_polarity.set(def_id.index, polarity); - - EntryKind::Impl } hir::ItemKind::Trait(..) => { let trait_def = self.tcx.trait_def(def_id); record!(self.tables.trait_def[def_id] <- trait_def); - - EntryKind::Trait } hir::ItemKind::TraitAlias(..) => { let trait_def = self.tcx.trait_def(def_id); record!(self.tables.trait_def[def_id] <- trait_def); - - EntryKind::TraitAlias } hir::ItemKind::ExternCrate(_) | hir::ItemKind::Use(..) => { bug!("cannot encode info for item {:?}", item) } + hir::ItemKind::Static(..) + | hir::ItemKind::Const(..) + | hir::ItemKind::ForeignMod { .. } + | hir::ItemKind::GlobalAsm(..) + | hir::ItemKind::TyAlias(..) => {} }; - record!(self.tables.kind[def_id] <- entry_kind); // FIXME(eddyb) there should be a nicer way to do this. match item.kind { hir::ItemKind::Enum(..) => record_array!(self.tables.children[def_id] <- @@ -1541,18 +1617,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } _ => {} } - match item.kind { - hir::ItemKind::Static(..) - | hir::ItemKind::Const(..) - | hir::ItemKind::Fn(..) - | hir::ItemKind::TyAlias(..) - | hir::ItemKind::OpaqueTy(..) - | hir::ItemKind::Enum(..) - | hir::ItemKind::Struct(..) - | hir::ItemKind::Union(..) - | hir::ItemKind::Impl { .. } => self.encode_item_type(def_id), - _ => {} - } if let hir::ItemKind::Fn(..) = item.kind { record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id)); if tcx.is_intrinsic(def_id) { @@ -1564,12 +1628,43 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record!(self.tables.impl_trait_ref[def_id] <- trait_ref); } } - } + // In some cases, along with the item itself, we also + // encode some sub-items. Usually we want some info from the item + // so it's easier to do that here then to wait until we would encounter + // normally in the visitor walk. + match item.kind { + hir::ItemKind::Enum(..) => { + let def = self.tcx.adt_def(item.def_id.to_def_id()); + for (i, variant) in def.variants().iter_enumerated() { + self.encode_enum_variant_info(def, i); - fn encode_info_for_generic_param(&mut self, def_id: DefId, kind: EntryKind, encode_type: bool) { - record!(self.tables.kind[def_id] <- kind); - if encode_type { - self.encode_item_type(def_id); + if let Some(_ctor_def_id) = variant.ctor_def_id { + self.encode_enum_variant_ctor(def, i); + } + } + } + hir::ItemKind::Struct(ref struct_def, _) => { + let def = self.tcx.adt_def(item.def_id.to_def_id()); + // If the struct has a constructor, encode it. + if let Some(ctor_hir_id) = struct_def.ctor_hir_id() { + let ctor_def_id = self.tcx.hir().local_def_id(ctor_hir_id); + self.encode_struct_ctor(def, ctor_def_id.to_def_id()); + } + } + hir::ItemKind::Impl { .. } => { + for &trait_item_def_id in + self.tcx.associated_item_def_ids(item.def_id.to_def_id()).iter() + { + self.encode_info_for_impl_item(trait_item_def_id); + } + } + hir::ItemKind::Trait(..) => { + for &item_def_id in self.tcx.associated_item_def_ids(item.def_id.to_def_id()).iter() + { + self.encode_info_for_trait_item(item_def_id); + } + } + _ => {} } } @@ -1584,34 +1679,16 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { ty::Generator(..) => { let data = self.tcx.generator_kind(def_id).unwrap(); let generator_diagnostic_data = typeck_result.get_generator_diagnostic_data(); - record!(self.tables.kind[def_id.to_def_id()] <- EntryKind::Generator); record!(self.tables.generator_kind[def_id.to_def_id()] <- data); record!(self.tables.generator_diagnostic_data[def_id.to_def_id()] <- generator_diagnostic_data); } - ty::Closure(..) => { - record!(self.tables.kind[def_id.to_def_id()] <- EntryKind::Closure); + ty::Closure(_, substs) => { + record!(self.tables.fn_sig[def_id.to_def_id()] <- substs.as_closure().sig()); } _ => bug!("closure that is neither generator nor closure"), } - self.encode_item_type(def_id.to_def_id()); - if let ty::Closure(def_id, substs) = *ty.kind() { - record!(self.tables.fn_sig[def_id] <- substs.as_closure().sig()); - } - } - - fn encode_info_for_anon_const(&mut self, id: hir::HirId) { - let def_id = self.tcx.hir().local_def_id(id); - debug!("EncodeContext::encode_info_for_anon_const({:?})", def_id); - let body_id = self.tcx.hir().body_owned_by(def_id); - let const_data = self.encode_rendered_const_for_body(body_id); - let qualifs = self.tcx.mir_const_qualif(def_id); - - record!(self.tables.kind[def_id.to_def_id()] <- EntryKind::AnonConst); - record!(self.tables.mir_const_qualif[def_id.to_def_id()] <- qualifs); - record!(self.tables.rendered_const[def_id.to_def_id()] <- const_data); - self.encode_item_type(def_id.to_def_id()); } fn encode_native_libraries(&mut self) -> LazyArray<NativeLib> { @@ -1670,7 +1747,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.tables.opt_def_kind.set(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()); - record!(self.tables.visibility[LOCAL_CRATE.as_def_id()] <- tcx.visibility(LOCAL_CRATE.as_def_id())); + let vis = tcx.local_visibility(CRATE_DEF_ID).map_id(|def_id| def_id.local_def_index); + record!(self.tables.visibility[LOCAL_CRATE.as_def_id()] <- vis); if let Some(stability) = stability { record!(self.tables.lookup_stability[LOCAL_CRATE.as_def_id()] <- stability); } @@ -1709,7 +1787,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let def_id = id.to_def_id(); self.tables.opt_def_kind.set(def_id.index, DefKind::Macro(macro_kind)); - record!(self.tables.kind[def_id] <- EntryKind::ProcMacro(macro_kind)); + self.tables.proc_macro.set(def_id.index, macro_kind); self.encode_attrs(id); record!(self.tables.def_keys[def_id] <- def_key); record!(self.tables.def_ident_span[def_id] <- span); @@ -1947,18 +2025,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { hir::Constness::NotConst }; self.tables.constness.set(def_id.index, constness); - record!(self.tables.kind[def_id] <- EntryKind::ForeignFn); - } - hir::ForeignItemKind::Static(..) => { - record!(self.tables.kind[def_id] <- EntryKind::ForeignStatic); - } - hir::ForeignItemKind::Type => { - record!(self.tables.kind[def_id] <- EntryKind::ForeignType); + record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id)); } + hir::ForeignItemKind::Static(..) | hir::ForeignItemKind::Type => {} } - self.encode_item_type(def_id); if let hir::ForeignItemKind::Fn(..) = nitem.kind { - record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id)); if tcx.is_intrinsic(def_id) { self.tables.is_intrinsic.set(def_id.index, ()); } @@ -1977,17 +2048,12 @@ impl<'a, 'tcx> Visitor<'tcx> for EncodeContext<'a, 'tcx> { intravisit::walk_expr(self, ex); self.encode_info_for_expr(ex); } - fn visit_anon_const(&mut self, c: &'tcx AnonConst) { - intravisit::walk_anon_const(self, c); - self.encode_info_for_anon_const(c.hir_id); - } fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { intravisit::walk_item(self, item); match item.kind { hir::ItemKind::ExternCrate(_) | hir::ItemKind::Use(..) => {} // ignore these _ => self.encode_info_for_item(item.def_id.to_def_id(), item), } - self.encode_addl_info_for_item(item); } fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem<'tcx>) { intravisit::walk_foreign_item(self, ni); @@ -2000,29 +2066,13 @@ impl<'a, 'tcx> Visitor<'tcx> for EncodeContext<'a, 'tcx> { } impl<'a, 'tcx> EncodeContext<'a, 'tcx> { - fn encode_fields(&mut self, adt_def: ty::AdtDef<'tcx>) { - for (variant_index, variant) in adt_def.variants().iter_enumerated() { - for (field_index, _field) in variant.fields.iter().enumerate() { - self.encode_field(adt_def, variant_index, field_index); - } - } - } - fn encode_info_for_generics(&mut self, generics: &hir::Generics<'tcx>) { for param in generics.params { let def_id = self.tcx.hir().local_def_id(param.hir_id); match param.kind { - GenericParamKind::Lifetime { .. } => continue, - GenericParamKind::Type { default, .. } => { - self.encode_info_for_generic_param( - def_id.to_def_id(), - EntryKind::TypeParam, - default.is_some(), - ); - } - GenericParamKind::Const { ref default, .. } => { + hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. } => {} + hir::GenericParamKind::Const { ref default, .. } => { let def_id = def_id.to_def_id(); - self.encode_info_for_generic_param(def_id, EntryKind::ConstParam, true); if default.is_some() { record!(self.tables.const_param_default[def_id] <- self.tcx.const_param_default(def_id)) } @@ -2036,68 +2086,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.encode_info_for_closure(expr.hir_id); } } - - /// In some cases, along with the item itself, we also - /// encode some sub-items. Usually we want some info from the item - /// so it's easier to do that here then to wait until we would encounter - /// normally in the visitor walk. - fn encode_addl_info_for_item(&mut self, item: &hir::Item<'_>) { - match item.kind { - hir::ItemKind::Static(..) - | hir::ItemKind::Const(..) - | hir::ItemKind::Fn(..) - | hir::ItemKind::Macro(..) - | hir::ItemKind::Mod(..) - | hir::ItemKind::ForeignMod { .. } - | hir::ItemKind::GlobalAsm(..) - | hir::ItemKind::ExternCrate(..) - | hir::ItemKind::Use(..) - | hir::ItemKind::TyAlias(..) - | hir::ItemKind::OpaqueTy(..) - | hir::ItemKind::TraitAlias(..) => { - // no sub-item recording needed in these cases - } - hir::ItemKind::Enum(..) => { - let def = self.tcx.adt_def(item.def_id.to_def_id()); - self.encode_fields(def); - - for (i, variant) in def.variants().iter_enumerated() { - self.encode_enum_variant_info(def, i); - - if let Some(_ctor_def_id) = variant.ctor_def_id { - self.encode_enum_variant_ctor(def, i); - } - } - } - hir::ItemKind::Struct(ref struct_def, _) => { - let def = self.tcx.adt_def(item.def_id.to_def_id()); - self.encode_fields(def); - - // If the struct has a constructor, encode it. - if let Some(ctor_hir_id) = struct_def.ctor_hir_id() { - let ctor_def_id = self.tcx.hir().local_def_id(ctor_hir_id); - self.encode_struct_ctor(def, ctor_def_id.to_def_id()); - } - } - hir::ItemKind::Union(..) => { - let def = self.tcx.adt_def(item.def_id.to_def_id()); - self.encode_fields(def); - } - hir::ItemKind::Impl { .. } => { - for &trait_item_def_id in - self.tcx.associated_item_def_ids(item.def_id.to_def_id()).iter() - { - self.encode_info_for_impl_item(trait_item_def_id); - } - } - hir::ItemKind::Trait(..) => { - for &item_def_id in self.tcx.associated_item_def_ids(item.def_id.to_def_id()).iter() - { - self.encode_info_for_trait_item(item_def_id); - } - } - } - } } /// Used to prefetch queries which will be needed later by metadata encoding. @@ -2220,7 +2208,7 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) { fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) { let mut encoder = opaque::FileEncoder::new(path) - .unwrap_or_else(|err| tcx.sess.fatal(&format!("failed to create file encoder: {}", err))); + .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. @@ -2228,7 +2216,7 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) { let source_map_files = tcx.sess.source_map().files(); let source_file_cache = (source_map_files[0].clone(), 0); - let required_source_files = Some(GrowableBitSet::with_capacity(source_map_files.len())); + let required_source_files = Some(FxIndexSet::default()); drop(source_map_files); let hygiene_ctxt = HygieneEncodeContext::default(); @@ -2246,6 +2234,7 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) { required_source_files, is_proc_macro: tcx.sess.crate_types().contains(&CrateType::ProcMacro), hygiene_ctxt: &hygiene_ctxt, + symbol_table: Default::default(), }; // Encode the rustc version string in a predictable location. @@ -2264,10 +2253,10 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) { // Encode the root position. let header = METADATA_HEADER.len(); file.seek(std::io::SeekFrom::Start(header as u64)) - .unwrap_or_else(|err| tcx.sess.fatal(&format!("failed to seek the file: {}", err))); + .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.fatal(&format!("failed to write to the file: {}", err))); + .unwrap_or_else(|err| tcx.sess.emit_fatal(FailWriteFile { err })); // Return to the position where we are before writing the root position. file.seek(std::io::SeekFrom::Start(pos_before_seek)).unwrap(); diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 66bdecc30..748b3afec 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -16,6 +16,7 @@ use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec}; use rustc_middle::metadata::ModChild; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; +use rustc_middle::middle::resolve_lifetime::ObjectLifetimeDefault; use rustc_middle::mir; use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::query::Providers; @@ -249,7 +250,7 @@ pub(crate) struct CrateRoot { def_path_hash_map: LazyValue<DefPathHashMapRef<'static>>, - source_map: LazyArray<rustc_span::SourceFile>, + source_map: LazyTable<u32, LazyValue<rustc_span::SourceFile>>, compiler_builtins: bool, needs_allocator: bool, @@ -333,16 +334,16 @@ macro_rules! define_tables { } define_tables! { - kind: Table<DefIndex, LazyValue<EntryKind>>, attributes: Table<DefIndex, LazyArray<ast::Attribute>>, children: Table<DefIndex, LazyArray<DefIndex>>, opt_def_kind: Table<DefIndex, DefKind>, - visibility: Table<DefIndex, LazyValue<ty::Visibility>>, + visibility: Table<DefIndex, LazyValue<ty::Visibility<DefIndex>>>, def_span: Table<DefIndex, LazyValue<Span>>, def_ident_span: Table<DefIndex, LazyValue<Span>>, lookup_stability: Table<DefIndex, LazyValue<attr::Stability>>, lookup_const_stability: Table<DefIndex, LazyValue<attr::ConstStability>>, + lookup_default_body_stability: Table<DefIndex, LazyValue<attr::DefaultBodyStability>>, lookup_deprecation_entry: Table<DefIndex, LazyValue<attr::Deprecation>>, // As an optimization, a missing entry indicates an empty `&[]`. explicit_item_bounds: Table<DefIndex, LazyArray<(ty::Predicate<'static>, Span)>>, @@ -357,6 +358,7 @@ define_tables! { codegen_fn_attrs: Table<DefIndex, LazyValue<CodegenFnAttrs>>, impl_trait_ref: Table<DefIndex, LazyValue<ty::TraitRef<'static>>>, const_param_default: Table<DefIndex, LazyValue<rustc_middle::ty::Const<'static>>>, + object_lifetime_default: Table<DefIndex, LazyValue<ObjectLifetimeDefault>>, optimized_mir: Table<DefIndex, LazyValue<mir::Body<'static>>>, mir_for_ctfe: Table<DefIndex, LazyValue<mir::Body<'static>>>, promoted_mir: Table<DefIndex, LazyValue<IndexVec<mir::Promoted, mir::Body<'static>>>>, @@ -390,39 +392,13 @@ define_tables! { proc_macro_quoted_spans: Table<usize, LazyValue<Span>>, generator_diagnostic_data: Table<DefIndex, LazyValue<GeneratorDiagnosticData<'static>>>, may_have_doc_links: Table<DefIndex, ()>, -} - -#[derive(Copy, Clone, MetadataEncodable, MetadataDecodable)] -enum EntryKind { - AnonConst, - Const, - Static, - ForeignStatic, - ForeignMod, - ForeignType, - GlobalAsm, - Type, - TypeParam, - ConstParam, - OpaqueTy, - Enum, - Field, - Variant(LazyValue<VariantData>), - Struct(LazyValue<VariantData>), - Union(LazyValue<VariantData>), - Fn, - ForeignFn, - Mod(LazyArray<ModChild>), - MacroDef(LazyValue<ast::MacArgs>, /*macro_rules*/ bool), - ProcMacro(MacroKind), - Closure, - Generator, - Trait, - Impl, - AssocFn { container: ty::AssocItemContainer, has_self: bool }, - AssocType(ty::AssocItemContainer), - AssocConst(ty::AssocItemContainer), - TraitAlias, + variant_data: Table<DefIndex, LazyValue<VariantData>>, + assoc_container: Table<DefIndex, ty::AssocItemContainer>, + // Slot is full when macro is macro_rules. + macro_rules: Table<DefIndex, ()>, + macro_definition: Table<DefIndex, LazyValue<ast::MacArgs>>, + proc_macro: Table<DefIndex, MacroKind>, + module_reexports: Table<DefIndex, LazyArray<ModChild>>, } #[derive(TyEncodable, TyDecodable)] @@ -444,6 +420,11 @@ const TAG_VALID_SPAN_LOCAL: u8 = 0; const TAG_VALID_SPAN_FOREIGN: u8 = 1; const TAG_PARTIAL_SPAN: u8 = 2; +// Tags for encoding Symbol's +const SYMBOL_STR: u8 = 0; +const SYMBOL_OFFSET: u8 = 1; +const SYMBOL_PREINTERNED: u8 = 2; + pub fn provide(providers: &mut Providers) { encoder::provide(providers); decoder::provide(providers); @@ -451,7 +432,6 @@ pub fn provide(providers: &mut Providers) { trivially_parameterized_over_tcx! { VariantData, - EntryKind, RawDefId, TraitImpls, IncoherentImpls, diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index 21841ae25..e7c1abd12 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -10,7 +10,6 @@ use rustc_span::hygiene::MacroKind; use std::convert::TryInto; use std::marker::PhantomData; use std::num::NonZeroUsize; -use tracing::debug; /// Helper trait, for encoding to, and decoding from, a fixed number of bytes. /// Used mainly for Lazy positions and lengths. @@ -51,7 +50,7 @@ macro_rules! fixed_size_enum { } match b[0] - 1 { $(${index()} => Some($($pat)*),)* - _ => panic!("Unexpected ImplPolarity code: {:?}", b[0]), + _ => panic!("Unexpected {} code: {:?}", stringify!($ty), b[0]), } } @@ -91,6 +90,7 @@ fixed_size_enum! { ( AnonConst ) ( InlineConst ) ( OpaqueTy ) + ( ImplTraitPlaceholder ) ( Field ) ( LifetimeParam ) ( GlobalAsm ) @@ -141,6 +141,21 @@ fixed_size_enum! { } } +fixed_size_enum! { + ty::AssocItemContainer { + ( TraitContainer ) + ( ImplContainer ) + } +} + +fixed_size_enum! { + MacroKind { + ( Attr ) + ( Bang ) + ( Derive ) + } +} + // We directly encode `DefPathHash` because a `LazyValue` would incur a 25% cost. impl FixedSizeEncoding for Option<DefPathHash> { type ByteArray = [u8; 16]; |