diff options
Diffstat (limited to 'compiler/rustc_metadata')
-rw-r--r-- | compiler/rustc_metadata/Cargo.toml | 1 | ||||
-rw-r--r-- | compiler/rustc_metadata/src/errors.rs | 384 | ||||
-rw-r--r-- | compiler/rustc_metadata/src/foreign_modules.rs | 6 | ||||
-rw-r--r-- | compiler/rustc_metadata/src/lib.rs | 2 | ||||
-rw-r--r-- | compiler/rustc_metadata/src/native_libs.rs | 41 | ||||
-rw-r--r-- | compiler/rustc_metadata/src/rmeta/decoder.rs | 79 | ||||
-rw-r--r-- | compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs | 27 | ||||
-rw-r--r-- | compiler/rustc_metadata/src/rmeta/encoder.rs | 518 | ||||
-rw-r--r-- | compiler/rustc_metadata/src/rmeta/mod.rs | 10 |
9 files changed, 564 insertions, 504 deletions
diff --git a/compiler/rustc_metadata/Cargo.toml b/compiler/rustc_metadata/Cargo.toml index 2c5db9d8b..6d85103c9 100644 --- a/compiler/rustc_metadata/Cargo.toml +++ b/compiler/rustc_metadata/Cargo.toml @@ -4,7 +4,6 @@ version = "0.0.0" edition = "2021" [lib] -doctest = false [dependencies] libloading = "0.7.1" diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index 7d63fad32..7c387b9a9 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -3,137 +3,137 @@ use std::{ path::{Path, PathBuf}, }; -use rustc_errors::{error_code, ErrorGuaranteed}; -use rustc_macros::SessionDiagnostic; -use rustc_session::{config, SessionDiagnostic}; +use rustc_errors::{error_code, ErrorGuaranteed, IntoDiagnostic}; +use rustc_macros::Diagnostic; +use rustc_session::config; use rustc_span::{sym, Span, Symbol}; use rustc_target::spec::{PanicStrategy, TargetTriple}; use crate::locator::CrateFlavor; -#[derive(SessionDiagnostic)] -#[diag(metadata::rlib_required)] +#[derive(Diagnostic)] +#[diag(metadata_rlib_required)] pub struct RlibRequired { pub crate_name: Symbol, } -#[derive(SessionDiagnostic)] -#[diag(metadata::lib_required)] +#[derive(Diagnostic)] +#[diag(metadata_lib_required)] pub struct LibRequired<'a> { pub crate_name: Symbol, pub kind: &'a str, } -#[derive(SessionDiagnostic)] -#[diag(metadata::crate_dep_multiple)] +#[derive(Diagnostic)] +#[diag(metadata_crate_dep_multiple)] #[help] pub struct CrateDepMultiple { pub crate_name: Symbol, } -#[derive(SessionDiagnostic)] -#[diag(metadata::two_panic_runtimes)] +#[derive(Diagnostic)] +#[diag(metadata_two_panic_runtimes)] pub struct TwoPanicRuntimes { pub prev_name: Symbol, pub cur_name: Symbol, } -#[derive(SessionDiagnostic)] -#[diag(metadata::bad_panic_strategy)] +#[derive(Diagnostic)] +#[diag(metadata_bad_panic_strategy)] pub struct BadPanicStrategy { pub runtime: Symbol, pub strategy: PanicStrategy, } -#[derive(SessionDiagnostic)] -#[diag(metadata::required_panic_strategy)] +#[derive(Diagnostic)] +#[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)] +#[derive(Diagnostic)] +#[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)] +#[derive(Diagnostic)] +#[diag(metadata_multiple_names_in_link)] pub struct MultipleNamesInLink { #[primary_span] pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(metadata::multiple_kinds_in_link)] +#[derive(Diagnostic)] +#[diag(metadata_multiple_kinds_in_link)] pub struct MultipleKindsInLink { #[primary_span] pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(metadata::link_name_form)] +#[derive(Diagnostic)] +#[diag(metadata_link_name_form)] pub struct LinkNameForm { #[primary_span] pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(metadata::link_kind_form)] +#[derive(Diagnostic)] +#[diag(metadata_link_kind_form)] pub struct LinkKindForm { #[primary_span] pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(metadata::link_modifiers_form)] +#[derive(Diagnostic)] +#[diag(metadata_link_modifiers_form)] pub struct LinkModifiersForm { #[primary_span] pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(metadata::link_cfg_form)] +#[derive(Diagnostic)] +#[diag(metadata_link_cfg_form)] pub struct LinkCfgForm { #[primary_span] pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(metadata::wasm_import_form)] +#[derive(Diagnostic)] +#[diag(metadata_wasm_import_form)] pub struct WasmImportForm { #[primary_span] pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(metadata::empty_link_name, code = "E0454")] +#[derive(Diagnostic)] +#[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")] +#[derive(Diagnostic)] +#[diag(metadata_link_framework_apple, code = "E0455")] pub struct LinkFrameworkApple { #[primary_span] pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(metadata::framework_only_windows, code = "E0455")] +#[derive(Diagnostic)] +#[diag(metadata_framework_only_windows, code = "E0455")] pub struct FrameworkOnlyWindows { #[primary_span] pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(metadata::unknown_link_kind, code = "E0458")] +#[derive(Diagnostic)] +#[diag(metadata_unknown_link_kind, code = "E0458")] pub struct UnknownLinkKind<'a> { #[primary_span] #[label] @@ -141,269 +141,303 @@ pub struct UnknownLinkKind<'a> { pub kind: &'a str, } -#[derive(SessionDiagnostic)] -#[diag(metadata::multiple_link_modifiers)] +#[derive(Diagnostic)] +#[diag(metadata_multiple_link_modifiers)] pub struct MultipleLinkModifiers { #[primary_span] pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(metadata::multiple_cfgs)] +#[derive(Diagnostic)] +#[diag(metadata_multiple_cfgs)] pub struct MultipleCfgs { #[primary_span] pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(metadata::link_cfg_single_predicate)] +#[derive(Diagnostic)] +#[diag(metadata_link_cfg_single_predicate)] pub struct LinkCfgSinglePredicate { #[primary_span] pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(metadata::multiple_wasm_import)] +#[derive(Diagnostic)] +#[diag(metadata_multiple_wasm_import)] pub struct MultipleWasmImport { #[primary_span] pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(metadata::unexpected_link_arg)] +#[derive(Diagnostic)] +#[diag(metadata_unexpected_link_arg)] pub struct UnexpectedLinkArg { #[primary_span] pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(metadata::invalid_link_modifier)] +#[derive(Diagnostic)] +#[diag(metadata_invalid_link_modifier)] pub struct InvalidLinkModifier { #[primary_span] pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(metadata::multiple_modifiers)] +#[derive(Diagnostic)] +#[diag(metadata_multiple_modifiers)] pub struct MultipleModifiers<'a> { #[primary_span] pub span: Span, pub modifier: &'a str, } -#[derive(SessionDiagnostic)] -#[diag(metadata::bundle_needs_static)] +#[derive(Diagnostic)] +#[diag(metadata_bundle_needs_static)] pub struct BundleNeedsStatic { #[primary_span] pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(metadata::whole_archive_needs_static)] +#[derive(Diagnostic)] +#[diag(metadata_whole_archive_needs_static)] pub struct WholeArchiveNeedsStatic { #[primary_span] pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(metadata::as_needed_compatibility)] +#[derive(Diagnostic)] +#[diag(metadata_as_needed_compatibility)] pub struct AsNeededCompatibility { #[primary_span] pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(metadata::unknown_link_modifier)] +#[derive(Diagnostic)] +#[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)] +#[derive(Diagnostic)] +#[diag(metadata_incompatible_wasm_link)] pub struct IncompatibleWasmLink { #[primary_span] pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(metadata::link_requires_name, code = "E0459")] +#[derive(Diagnostic)] +#[diag(metadata_link_requires_name, code = "E0459")] pub struct LinkRequiresName { #[primary_span] #[label] pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(metadata::raw_dylib_no_nul)] +#[derive(Diagnostic)] +#[diag(metadata_raw_dylib_no_nul)] pub struct RawDylibNoNul { #[primary_span] pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(metadata::link_ordinal_raw_dylib)] +#[derive(Diagnostic)] +#[diag(metadata_link_ordinal_raw_dylib)] pub struct LinkOrdinalRawDylib { #[primary_span] pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(metadata::lib_framework_apple)] +#[derive(Diagnostic)] +#[diag(metadata_lib_framework_apple)] pub struct LibFrameworkApple; -#[derive(SessionDiagnostic)] -#[diag(metadata::empty_renaming_target)] +#[derive(Diagnostic)] +#[diag(metadata_empty_renaming_target)] pub struct EmptyRenamingTarget<'a> { pub lib_name: &'a str, } -#[derive(SessionDiagnostic)] -#[diag(metadata::renaming_no_link)] +#[derive(Diagnostic)] +#[diag(metadata_renaming_no_link)] pub struct RenamingNoLink<'a> { pub lib_name: &'a str, } -#[derive(SessionDiagnostic)] -#[diag(metadata::multiple_renamings)] +#[derive(Diagnostic)] +#[diag(metadata_multiple_renamings)] pub struct MultipleRenamings<'a> { pub lib_name: &'a str, } -#[derive(SessionDiagnostic)] -#[diag(metadata::no_link_mod_override)] +#[derive(Diagnostic)] +#[diag(metadata_no_link_mod_override)] pub struct NoLinkModOverride { #[primary_span] pub span: Option<Span>, } -#[derive(SessionDiagnostic)] -#[diag(metadata::unsupported_abi_i686)] +#[derive(Diagnostic)] +#[diag(metadata_unsupported_abi_i686)] pub struct UnsupportedAbiI686 { #[primary_span] pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(metadata::unsupported_abi)] +#[derive(Diagnostic)] +#[diag(metadata_unsupported_abi)] pub struct UnsupportedAbi { #[primary_span] pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(metadata::fail_create_file_encoder)] +#[derive(Diagnostic)] +#[diag(metadata_fail_create_file_encoder)] pub struct FailCreateFileEncoder { pub err: Error, } -#[derive(SessionDiagnostic)] -#[diag(metadata::fail_seek_file)] +#[derive(Diagnostic)] +#[diag(metadata_fail_seek_file)] pub struct FailSeekFile { pub err: Error, } -#[derive(SessionDiagnostic)] -#[diag(metadata::fail_write_file)] +#[derive(Diagnostic)] +#[diag(metadata_fail_write_file)] pub struct FailWriteFile { pub err: Error, } -#[derive(SessionDiagnostic)] -#[diag(metadata::crate_not_panic_runtime)] +#[derive(Diagnostic)] +#[diag(metadata_crate_not_panic_runtime)] pub struct CrateNotPanicRuntime { pub crate_name: Symbol, } -#[derive(SessionDiagnostic)] -#[diag(metadata::no_panic_strategy)] +#[derive(Diagnostic)] +#[diag(metadata_no_panic_strategy)] pub struct NoPanicStrategy { pub crate_name: Symbol, pub strategy: PanicStrategy, } -#[derive(SessionDiagnostic)] -#[diag(metadata::profiler_builtins_needs_core)] +#[derive(Diagnostic)] +#[diag(metadata_profiler_builtins_needs_core)] pub struct ProfilerBuiltinsNeedsCore; -#[derive(SessionDiagnostic)] -#[diag(metadata::not_profiler_runtime)] +#[derive(Diagnostic)] +#[diag(metadata_not_profiler_runtime)] pub struct NotProfilerRuntime { pub crate_name: Symbol, } -#[derive(SessionDiagnostic)] -#[diag(metadata::no_multiple_global_alloc)] +#[derive(Diagnostic)] +#[diag(metadata_no_multiple_global_alloc)] pub struct NoMultipleGlobalAlloc { #[primary_span] #[label] pub span2: Span, - #[label(metadata::prev_global_alloc)] + #[label(metadata_prev_global_alloc)] pub span1: Span, } -#[derive(SessionDiagnostic)] -#[diag(metadata::conflicting_global_alloc)] +#[derive(Diagnostic)] +#[diag(metadata_conflicting_global_alloc)] pub struct ConflictingGlobalAlloc { pub crate_name: Symbol, pub other_crate_name: Symbol, } -#[derive(SessionDiagnostic)] -#[diag(metadata::global_alloc_required)] +#[derive(Diagnostic)] +#[diag(metadata_global_alloc_required)] pub struct GlobalAllocRequired; -#[derive(SessionDiagnostic)] -#[diag(metadata::no_transitive_needs_dep)] +#[derive(Diagnostic)] +#[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)] +#[derive(Diagnostic)] +#[diag(metadata_failed_write_error)] pub struct FailedWriteError { pub filename: PathBuf, pub err: Error, } -#[derive(SessionDiagnostic)] -#[diag(metadata::missing_native_library)] +#[derive(Diagnostic)] +#[diag(metadata_missing_native_library)] pub struct MissingNativeLibrary<'a> { - pub libname: &'a str, + libname: &'a str, + #[subdiagnostic] + suggest_name: Option<SuggestLibraryName<'a>>, +} + +impl<'a> MissingNativeLibrary<'a> { + pub fn new(libname: &'a str, verbatim: bool) -> Self { + // if it looks like the user has provided a complete filename rather just the bare lib name, + // then provide a note that they might want to try trimming the name + let suggested_name = if !verbatim { + if let Some(libname) = libname.strip_prefix("lib") && let Some(libname) = libname.strip_suffix(".a") { + // this is a unix style filename so trim prefix & suffix + Some(libname) + } else if let Some(libname) = libname.strip_suffix(".lib") { + // this is a Windows style filename so just trim the suffix + Some(libname) + } else { + None + } + } else { + None + }; + + Self { + libname, + suggest_name: suggested_name + .map(|suggested_name| SuggestLibraryName { suggested_name }), + } + } +} + +#[derive(Subdiagnostic)] +#[help(metadata_only_provide_library_name)] +pub struct SuggestLibraryName<'a> { + suggested_name: &'a str, } -#[derive(SessionDiagnostic)] -#[diag(metadata::failed_create_tempdir)] +#[derive(Diagnostic)] +#[diag(metadata_failed_create_tempdir)] pub struct FailedCreateTempdir { pub err: Error, } -#[derive(SessionDiagnostic)] -#[diag(metadata::failed_create_file)] +#[derive(Diagnostic)] +#[diag(metadata_failed_create_file)] pub struct FailedCreateFile<'a> { pub filename: &'a Path, pub err: Error, } -#[derive(SessionDiagnostic)] -#[diag(metadata::failed_create_encoded_metadata)] +#[derive(Diagnostic)] +#[diag(metadata_failed_create_encoded_metadata)] pub struct FailedCreateEncodedMetadata { pub err: Error, } -#[derive(SessionDiagnostic)] -#[diag(metadata::non_ascii_name)] +#[derive(Diagnostic)] +#[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)] +#[derive(Diagnostic)] +#[diag(metadata_extern_location_not_exist)] pub struct ExternLocationNotExist<'a> { #[primary_span] pub span: Span, @@ -411,8 +445,8 @@ pub struct ExternLocationNotExist<'a> { pub location: &'a Path, } -#[derive(SessionDiagnostic)] -#[diag(metadata::extern_location_not_file)] +#[derive(Diagnostic)] +#[diag(metadata_extern_location_not_file)] pub struct ExternLocationNotFile<'a> { #[primary_span] pub span: Span, @@ -427,12 +461,12 @@ pub(crate) struct MultipleCandidates { pub candidates: Vec<PathBuf>, } -impl SessionDiagnostic<'_> for MultipleCandidates { +impl IntoDiagnostic<'_> 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); + 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)); @@ -444,8 +478,8 @@ impl SessionDiagnostic<'_> for MultipleCandidates { } } -#[derive(SessionDiagnostic)] -#[diag(metadata::multiple_matching_crates, code = "E0464")] +#[derive(Diagnostic)] +#[diag(metadata_multiple_matching_crates, code = "E0464")] #[note] pub struct MultipleMatchingCrates { #[primary_span] @@ -454,24 +488,24 @@ pub struct MultipleMatchingCrates { pub candidates: String, } -#[derive(SessionDiagnostic)] -#[diag(metadata::symbol_conflicts_current, code = "E0519")] +#[derive(Diagnostic)] +#[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")] +#[derive(Diagnostic)] +#[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)] +#[derive(Diagnostic)] +#[diag(metadata_stable_crate_id_collision)] pub struct StableCrateIdCollision { #[primary_span] pub span: Span, @@ -479,18 +513,18 @@ pub struct StableCrateIdCollision { pub crate_name1: Symbol, } -#[derive(SessionDiagnostic)] -#[diag(metadata::dl_error)] +#[derive(Diagnostic)] +#[diag(metadata_dl_error)] pub struct DlError { #[primary_span] pub span: Span, pub err: String, } -#[derive(SessionDiagnostic)] -#[diag(metadata::newer_crate_version, code = "E0460")] +#[derive(Diagnostic)] +#[diag(metadata_newer_crate_version, code = "E0460")] #[note] -#[note(metadata::found_crate_versions)] +#[note(metadata_found_crate_versions)] pub struct NewerCrateVersion { #[primary_span] pub span: Span, @@ -499,9 +533,9 @@ pub struct NewerCrateVersion { pub found_crates: String, } -#[derive(SessionDiagnostic)] -#[diag(metadata::no_crate_with_triple, code = "E0461")] -#[note(metadata::found_crate_versions)] +#[derive(Diagnostic)] +#[diag(metadata_no_crate_with_triple, code = "E0461")] +#[note(metadata_found_crate_versions)] pub struct NoCrateWithTriple<'a> { #[primary_span] pub span: Span, @@ -511,9 +545,9 @@ pub struct NoCrateWithTriple<'a> { pub found_crates: String, } -#[derive(SessionDiagnostic)] -#[diag(metadata::found_staticlib, code = "E0462")] -#[note(metadata::found_crate_versions)] +#[derive(Diagnostic)] +#[diag(metadata_found_staticlib, code = "E0462")] +#[note(metadata_found_crate_versions)] #[help] pub struct FoundStaticlib { #[primary_span] @@ -523,9 +557,9 @@ pub struct FoundStaticlib { pub found_crates: String, } -#[derive(SessionDiagnostic)] -#[diag(metadata::incompatible_rustc, code = "E0514")] -#[note(metadata::found_crate_versions)] +#[derive(Diagnostic)] +#[diag(metadata_incompatible_rustc, code = "E0514")] +#[note(metadata_found_crate_versions)] #[help] pub struct IncompatibleRustc { #[primary_span] @@ -543,12 +577,12 @@ pub struct InvalidMetadataFiles { pub crate_rejections: Vec<String>, } -impl SessionDiagnostic<'_> for InvalidMetadataFiles { +impl IntoDiagnostic<'_> 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); + 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)); @@ -571,12 +605,12 @@ pub struct CannotFindCrate { pub locator_triple: TargetTriple, } -impl SessionDiagnostic<'_> for CannotFindCrate { +impl IntoDiagnostic<'_> 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); + 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); @@ -587,54 +621,54 @@ impl SessionDiagnostic<'_> for CannotFindCrate { && self.locator_triple != TargetTriple::from_triple(config::host_triple()) { if self.missing_core { - diag.note(rustc_errors::fluent::metadata::target_not_installed); + diag.note(rustc_errors::fluent::metadata_target_not_installed); } else { - diag.note(rustc_errors::fluent::metadata::target_no_std_support); + 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); + 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); + diag.note(rustc_errors::fluent::metadata_std_required); } if self.is_nightly_build { - diag.help(rustc_errors::fluent::metadata::consider_building_std); + 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); + 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.help(rustc_errors::fluent::metadata_install_missing_components); } - diag.span_label(self.span, rustc_errors::fluent::metadata::cant_find_crate); + diag.span_label(self.span, rustc_errors::fluent::metadata_cant_find_crate); diag } } -#[derive(SessionDiagnostic)] -#[diag(metadata::no_dylib_plugin, code = "E0457")] +#[derive(Diagnostic)] +#[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)] +#[derive(Diagnostic)] +#[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)] +#[derive(Diagnostic)] +#[diag(metadata_lib_filename_form)] pub struct LibFilenameForm<'a> { #[primary_span] pub span: Span, @@ -642,37 +676,37 @@ pub struct LibFilenameForm<'a> { pub dll_suffix: &'a str, } -#[derive(SessionDiagnostic)] -#[diag(metadata::multiple_import_name_type)] +#[derive(Diagnostic)] +#[diag(metadata_multiple_import_name_type)] pub struct MultipleImportNameType { #[primary_span] pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(metadata::import_name_type_form)] +#[derive(Diagnostic)] +#[diag(metadata_import_name_type_form)] pub struct ImportNameTypeForm { #[primary_span] pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(metadata::import_name_type_x86)] +#[derive(Diagnostic)] +#[diag(metadata_import_name_type_x86)] pub struct ImportNameTypeX86 { #[primary_span] pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(metadata::unknown_import_name_type)] +#[derive(Diagnostic)] +#[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)] +#[derive(Diagnostic)] +#[diag(metadata_import_name_type_raw)] pub struct ImportNameTypeRaw { #[primary_span] pub span: Span, diff --git a/compiler/rustc_metadata/src/foreign_modules.rs b/compiler/rustc_metadata/src/foreign_modules.rs index 2ca4cd17f..d1c2f3104 100644 --- a/compiler/rustc_metadata/src/foreign_modules.rs +++ b/compiler/rustc_metadata/src/foreign_modules.rs @@ -6,13 +6,13 @@ use rustc_session::cstore::ForeignModule; pub(crate) fn collect(tcx: TyCtxt<'_>) -> Vec<ForeignModule> { let mut modules = Vec::new(); for id in tcx.hir().items() { - if !matches!(tcx.def_kind(id.def_id), DefKind::ForeignMod) { + if !matches!(tcx.def_kind(id.owner_id), DefKind::ForeignMod) { continue; } let item = tcx.hir().item(id); if let hir::ItemKind::ForeignMod { items, .. } = item.kind { - let foreign_items = items.iter().map(|it| it.id.def_id.to_def_id()).collect(); - modules.push(ForeignModule { foreign_items, def_id: id.def_id.to_def_id() }); + let foreign_items = items.iter().map(|it| it.id.owner_id.to_def_id()).collect(); + modules.push(ForeignModule { foreign_items, def_id: id.owner_id.to_def_id() }); } } modules diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index 6f5604b7e..98cf6fef5 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -2,10 +2,8 @@ #![feature(decl_macro)] #![feature(drain_filter)] #![feature(generators)] -#![cfg_attr(bootstrap, feature(generic_associated_types))] #![feature(iter_from_generator)] #![feature(let_chains)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(once_cell)] #![feature(proc_macro_internals)] #![feature(macro_metavar_expr)] diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 257741c13..20a2e7829 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -33,29 +33,26 @@ pub fn find_native_static_library( 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() + let formats = if verbatim.unwrap_or(false) { + vec![("".into(), "".into())] } else { - format!("{}{}{}", sess.target.staticlib_prefix, name, sess.target.staticlib_suffix) + let os = (sess.target.staticlib_prefix.clone(), sess.target.staticlib_suffix.clone()); + // On Windows, static libraries sometimes show up as libfoo.a and other + // times show up as foo.lib + let unix = ("lib".into(), ".a".into()); + if os == unix { vec![os] } else { vec![os, unix] } }; - 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); + for (prefix, suffix) in &formats { + let test = path.join(format!("{}{}{}", prefix, name, suffix)); if test.exists() { return test; } } } - sess.emit_fatal(MissingNativeLibrary { libname: name }); + + sess.emit_fatal(MissingNativeLibrary::new(name, verbatim.unwrap_or(false))); } fn find_bundled_library( @@ -101,7 +98,7 @@ struct Collector<'tcx> { impl<'tcx> Collector<'tcx> { fn process_item(&mut self, id: rustc_hir::ItemId) { - if !matches!(self.tcx.def_kind(id.def_id), DefKind::ForeignMod) { + if !matches!(self.tcx.def_kind(id.owner_id), DefKind::ForeignMod) { return; } @@ -375,17 +372,17 @@ impl<'tcx> Collector<'tcx> { } _ => { for child_item in foreign_mod_items { - if self.tcx.def_kind(child_item.id.def_id).has_codegen_attrs() + if self.tcx.def_kind(child_item.id.owner_id).has_codegen_attrs() && self .tcx - .codegen_fn_attrs(child_item.id.def_id) + .codegen_fn_attrs(child_item.id.owner_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)) + .attrs(child_item.id.owner_id.into()) .iter() .find(|a| a.has_name(sym::link_ordinal)) .unwrap(); @@ -405,7 +402,7 @@ impl<'tcx> Collector<'tcx> { filename, kind, cfg, - foreign_module: Some(it.def_id.to_def_id()), + foreign_module: Some(it.owner_id.to_def_id()), wasm_import_module: wasm_import_module.map(|(name, _)| name), verbatim, dll_imports, @@ -508,7 +505,7 @@ impl<'tcx> Collector<'tcx> { fn i686_arg_list_size(&self, item: &hir::ForeignItemRef) -> usize { let argument_types: &List<Ty<'_>> = self.tcx.erase_late_bound_regions( self.tcx - .type_of(item.id.def_id) + .type_of(item.id.owner_id) .fn_sig(self.tcx) .inputs() .map_bound(|slice| self.tcx.mk_type_list(slice.iter())), @@ -560,7 +557,7 @@ impl<'tcx> Collector<'tcx> { } }; - let codegen_fn_attrs = self.tcx.codegen_fn_attrs(item.id.def_id); + let codegen_fn_attrs = self.tcx.codegen_fn_attrs(item.id.owner_id); let import_name_type = codegen_fn_attrs .link_ordinal .map_or(import_name_type, |ord| Some(PeImportNameType::Ordinal(ord))); @@ -570,7 +567,7 @@ impl<'tcx> Collector<'tcx> { import_name_type, calling_convention, span: item.span, - is_fn: self.tcx.def_kind(item.id.def_id).is_fn_like(), + is_fn: self.tcx.def_kind(item.id.owner_id).is_fn_like(), } } } diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 830417eea..691e3d0f8 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -773,7 +773,15 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } fn opt_item_name(self, item_index: DefIndex) -> Option<Symbol> { - self.def_key(item_index).disambiguated_data.data.get_opt_name() + let def_key = self.def_key(item_index); + def_key.disambiguated_data.data.get_opt_name().or_else(|| { + if def_key.disambiguated_data.data == DefPathData::Ctor { + let parent_index = def_key.parent.expect("no parent for a constructor"); + self.def_key(parent_index).disambiguated_data.data.get_opt_name() + } else { + None + } + }) } fn item_name(self, item_index: DefIndex) -> Symbol { @@ -905,7 +913,13 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .get(self, item_id) .unwrap_or_else(LazyArray::empty) .decode(self) - .map(|index| self.get_variant(&self.def_kind(index), index, did)) + .filter_map(|index| { + let kind = self.def_kind(index); + match kind { + DefKind::Ctor(..) => None, + _ => Some(self.get_variant(&kind, index, did)), + } + }) .collect() } else { std::iter::once(self.get_variant(&kind, item_id, did)).collect() @@ -1029,50 +1043,27 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { callback(ModChild { ident, res, vis, span, macro_rules }); - // For non-re-export structs and variants add their constructors to children. - // Re-export lists automatically contain constructors when necessary. - match kind { - DefKind::Struct => { - if let Some((ctor_def_id, ctor_kind)) = - self.get_ctor_def_id_and_kind(child_index) - { - let ctor_res = - Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id); - let vis = self.get_visibility(ctor_def_id.index); - callback(ModChild { - ident, - res: ctor_res, - vis, - span, - macro_rules: false, - }); - } - } - DefKind::Variant => { - // Braced variants, unlike structs, generate unusable names in - // value namespace, they are reserved for possible future use. - // It's ok to use the variant's id as a ctor id since an - // error will be reported on any use of such resolution anyway. - let (ctor_def_id, ctor_kind) = self - .get_ctor_def_id_and_kind(child_index) - .unwrap_or((def_id, CtorKind::Fictive)); - let ctor_res = - Res::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id); - let mut vis = self.get_visibility(ctor_def_id.index); - if ctor_def_id == def_id && vis.is_public() { - // For non-exhaustive variants lower the constructor visibility to - // within the crate. We only need this for fictive constructors, - // for other constructors correct visibilities - // were already encoded in metadata. - let mut attrs = self.get_item_attrs(def_id.index, sess); - if attrs.any(|item| item.has_name(sym::non_exhaustive)) { - let crate_def_id = self.local_def_id(CRATE_DEF_INDEX); - vis = ty::Visibility::Restricted(crate_def_id); - } + // For non-reexport variants add their fictive constructors to children. + // Braced variants, unlike structs, generate unusable names in value namespace, + // they are reserved for possible future use. It's ok to use the variant's id as + // a ctor id since an error will be reported on any use of such resolution anyway. + // Reexport lists automatically contain such constructors when necessary. + if kind == DefKind::Variant && self.get_ctor_def_id_and_kind(child_index).is_none() + { + let ctor_res = + Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Fictive), def_id); + let mut vis = vis; + if vis.is_public() { + // For non-exhaustive variants lower the constructor visibility to + // within the crate. We only need this for fictive constructors, + // for other constructors correct visibilities + // were already encoded in metadata. + let mut attrs = self.get_item_attrs(def_id.index, sess); + if attrs.any(|item| item.has_name(sym::non_exhaustive)) { + vis = ty::Visibility::Restricted(self.local_def_id(CRATE_DEF_INDEX)); } - callback(ModChild { ident, res: ctor_res, vis, span, macro_rules: false }); } - _ => {} + callback(ModChild { ident, res: ctor_res, vis, span, macro_rules: false }); } } } diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index dede1b212..a0a085525 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -15,7 +15,6 @@ use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::query::{ExternProviders, Providers}; use rustc_middle::ty::{self, TyCtxt, Visibility}; use rustc_session::cstore::{CrateSource, CrateStore}; -use rustc_session::utils::NativeLibKind; use rustc_session::{Session, StableCrateId}; use rustc_span::hygiene::{ExpnHash, ExpnId}; use rustc_span::source_map::{Span, Spanned}; @@ -210,6 +209,7 @@ provide! { tcx, def_id, other, cdata, lookup_const_stability => { table } lookup_default_body_stability => { table } lookup_deprecation_entry => { table } + params_in_repr => { table } unused_generic_params => { table } opt_def_kind => { table_direct } impl_parent => { table } @@ -223,6 +223,16 @@ provide! { tcx, def_id, other, cdata, fn_arg_names => { table } generator_kind => { table } trait_def => { table } + deduced_param_attrs => { table } + collect_trait_impl_trait_tys => { + Ok(cdata + .root + .tables + .trait_impl_trait_tys + .get(cdata, def_id.index) + .map(|lazy| lazy.decode((cdata, tcx))) + .process_decoded(tcx, || panic!("{:?} does not have trait_impl_trait_tys", def_id))) + } visibility => { cdata.get_visibility(def_id.index) } adt_def => { cdata.get_adt_def(def_id.index, tcx) } @@ -329,20 +339,10 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) { // resolve! Does this work? Unsure! That's what the issue is about *providers = Providers { allocator_kind: |tcx, ()| CStore::from_tcx(tcx).allocator_kind(), - is_dllimport_foreign_item: |tcx, id| match tcx.native_library_kind(id) { - Some( - NativeLibKind::Dylib { .. } | NativeLibKind::RawDylib | NativeLibKind::Unspecified, - ) => true, - _ => false, - }, - is_statically_included_foreign_item: |tcx, id| { - matches!(tcx.native_library_kind(id), Some(NativeLibKind::Static { .. })) - }, is_private_dep: |_tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); false }, - native_library_kind: |tcx, id| tcx.native_library(id).map(|l| l.kind), native_library: |tcx, id| { tcx.native_libraries(id.krate) .iter() @@ -587,11 +587,6 @@ impl CStore { self.get_crate_data(cnum).get_proc_macro_quoted_span(id, sess) } - /// Decodes all traits in the crate (for rustdoc). - pub fn traits_in_crate_untracked(&self, cnum: CrateNum) -> impl Iterator<Item = DefId> + '_ { - self.get_crate_data(cnum).get_traits() - } - /// Decodes all trait impls in the crate (for rustdoc). pub fn trait_impls_in_crate_untracked( &self, diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 5a60ea794..049514ec7 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -3,6 +3,7 @@ use crate::rmeta::def_path_hash_map::DefPathHashMapRef; use crate::rmeta::table::TableBuilder; use crate::rmeta::*; +use rustc_ast::Attribute; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_data_structures::memmap::{Mmap, MmapMut}; @@ -28,8 +29,9 @@ use rustc_middle::ty::codec::TyEncoder; use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt}; +use rustc_middle::util::common::to_readable_str; use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder}; -use rustc_session::config::CrateType; +use rustc_session::config::{CrateType, OptLevel}; use rustc_session::cstore::{ForeignModule, LinkagePreference, NativeLib}; use rustc_span::hygiene::{ExpnIndex, HygieneEncodeContext, MacroKind}; use rustc_span::symbol::{sym, Symbol}; @@ -261,10 +263,10 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span { // 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, 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 - // we write into the metadata. This allows `imported_source_files` to binary + // 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 we write into the metadata. This allows `imported_source_files` to binary // search through the 'foreign' crate's source map information, using the // deserialized 'lo' and 'hi' values directly. // @@ -554,78 +556,56 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_crate_root(&mut self) -> LazyValue<CrateRoot> { let tcx = self.tcx; - let mut i = 0; - let preamble_bytes = self.position() - i; - - // Encode the crate deps - i = self.position(); - let crate_deps = self.encode_crate_deps(); - let dylib_dependency_formats = self.encode_dylib_dependency_formats(); - let dep_bytes = self.position() - i; - - // Encode the lib features. - i = self.position(); - let lib_features = self.encode_lib_features(); - let lib_feature_bytes = self.position() - i; - - // Encode the stability implications. - i = self.position(); - let stability_implications = self.encode_stability_implications(); - let stability_implications_bytes = self.position() - i; - - // Encode the language items. - i = self.position(); - let lang_items = self.encode_lang_items(); - let lang_items_missing = self.encode_lang_items_missing(); - let lang_item_bytes = self.position() - i; - - // Encode the diagnostic items. - i = self.position(); - let diagnostic_items = self.encode_diagnostic_items(); - let diagnostic_item_bytes = self.position() - i; - - // Encode the native libraries used - i = self.position(); - let native_libraries = self.encode_native_libraries(); - let native_lib_bytes = self.position() - i; - - i = self.position(); - let foreign_modules = self.encode_foreign_modules(); - let foreign_modules_bytes = self.position() - i; - - // Encode DefPathTable - i = self.position(); - self.encode_def_path_table(); - let def_path_table_bytes = self.position() - i; + let mut stats: Vec<(&'static str, usize)> = Vec::with_capacity(32); + + macro_rules! stat { + ($label:literal, $f:expr) => {{ + let orig_pos = self.position(); + let res = $f(); + stats.push(($label, self.position() - orig_pos)); + res + }}; + } + + // We have already encoded some things. Get their combined size from the current position. + stats.push(("preamble", self.position())); + + let (crate_deps, dylib_dependency_formats) = + stat!("dep", || (self.encode_crate_deps(), self.encode_dylib_dependency_formats())); + + let lib_features = stat!("lib-features", || self.encode_lib_features()); + + let stability_implications = + stat!("stability-implications", || self.encode_stability_implications()); + + let (lang_items, lang_items_missing) = stat!("lang-items", || { + (self.encode_lang_items(), self.encode_lang_items_missing()) + }); + + let diagnostic_items = stat!("diagnostic-items", || self.encode_diagnostic_items()); + + let native_libraries = stat!("native-libs", || self.encode_native_libraries()); + + let foreign_modules = stat!("foreign-modules", || self.encode_foreign_modules()); + + _ = stat!("def-path-table", || self.encode_def_path_table()); // Encode the def IDs of traits, for rustdoc and diagnostics. - i = self.position(); - let traits = self.encode_traits(); - let traits_bytes = self.position() - i; + let traits = stat!("traits", || self.encode_traits()); // Encode the def IDs of impls, for coherence checking. - i = self.position(); - let impls = self.encode_impls(); - let impls_bytes = self.position() - i; - - i = self.position(); - let incoherent_impls = self.encode_incoherent_impls(); - let incoherent_impls_bytes = self.position() - i; - - // Encode MIR. - i = self.position(); - self.encode_mir(); - let mir_bytes = self.position() - i; - - // Encode the items. - i = self.position(); - self.encode_def_ids(); - self.encode_info_for_items(); - let item_bytes = self.position() - i; - - // Encode the allocation index - i = self.position(); - let interpret_alloc_index = { + let impls = stat!("impls", || self.encode_impls()); + + let incoherent_impls = stat!("incoherent-impls", || self.encode_incoherent_impls()); + + _ = stat!("mir", || self.encode_mir()); + + _ = stat!("items", || { + self.encode_def_ids(); + self.encode_info_for_items(); + }); + + let interpret_alloc_index = stat!("interpret-alloc-index", || { let mut interpret_alloc_index = Vec::new(); let mut n = 0; trace!("beginning to encode alloc ids"); @@ -646,126 +626,90 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { n = new_n; } self.lazy_array(interpret_alloc_index) - }; - let interpret_alloc_index_bytes = self.position() - i; + }); - // Encode the proc macro data. This affects 'tables', - // so we need to do this before we encode the tables. - // This overwrites def_keys, so it must happen after encode_def_path_table. - i = self.position(); - let proc_macro_data = self.encode_proc_macros(); - let proc_macro_data_bytes = self.position() - i; + // Encode the proc macro data. This affects `tables`, so we need to do this before we + // encode the tables. This overwrites def_keys, so it must happen after + // encode_def_path_table. + let proc_macro_data = stat!("proc-macro-data", || self.encode_proc_macros()); - i = self.position(); - let tables = self.tables.encode(&mut self.opaque); - let tables_bytes = self.position() - i; + let tables = stat!("tables", || self.tables.encode(&mut self.opaque)); - i = self.position(); - let debugger_visualizers = self.encode_debugger_visualizers(); - let debugger_visualizers_bytes = self.position() - i; + let debugger_visualizers = + stat!("debugger-visualizers", || self.encode_debugger_visualizers()); // Encode exported symbols info. This is prefetched in `encode_metadata` so we encode // this as late as possible to give the prefetching as much time as possible to complete. - i = self.position(); - let exported_symbols = tcx.exported_symbols(LOCAL_CRATE); - let exported_symbols = self.encode_exported_symbols(&exported_symbols); - let exported_symbols_bytes = self.position() - i; - - // Encode the hygiene data, - // IMPORTANT: this *must* be the last thing that we encode (other than `SourceMap`). The process - // of encoding other items (e.g. `optimized_mir`) may cause us to load - // data from the incremental cache. If this causes us to deserialize a `Span`, - // then we may load additional `SyntaxContext`s into the global `HygieneData`. - // Therefore, we need to encode the hygiene data last to ensure that we encode - // any `SyntaxContext`s that might be used. - i = self.position(); - let (syntax_contexts, expn_data, expn_hashes) = self.encode_hygiene(); - let hygiene_bytes = self.position() - i; - - i = self.position(); - let def_path_hash_map = self.encode_def_path_hash_map(); - let def_path_hash_map_bytes = self.position() - i; - - // Encode source_map. This needs to be done last, - // since encoding `Span`s tells us which `SourceFiles` we actually - // need to encode. - i = self.position(); - let source_map = self.encode_source_map(); - let source_map_bytes = self.position() - i; - - i = self.position(); - let attrs = tcx.hir().krate_attrs(); - let has_default_lib_allocator = tcx.sess.contains_name(&attrs, sym::default_lib_allocator); - let root = self.lazy(CrateRoot { - name: tcx.crate_name(LOCAL_CRATE), - extra_filename: tcx.sess.opts.cg.extra_filename.clone(), - triple: tcx.sess.opts.target_triple.clone(), - hash: tcx.crate_hash(LOCAL_CRATE), - stable_crate_id: tcx.def_path_hash(LOCAL_CRATE.as_def_id()).stable_crate_id(), - required_panic_strategy: tcx.required_panic_strategy(LOCAL_CRATE), - panic_in_drop_strategy: tcx.sess.opts.unstable_opts.panic_in_drop, - edition: tcx.sess.edition(), - has_global_allocator: tcx.has_global_allocator(LOCAL_CRATE), - has_panic_handler: tcx.has_panic_handler(LOCAL_CRATE), - has_default_lib_allocator, - proc_macro_data, - debugger_visualizers, - compiler_builtins: tcx.sess.contains_name(&attrs, sym::compiler_builtins), - needs_allocator: tcx.sess.contains_name(&attrs, sym::needs_allocator), - needs_panic_runtime: tcx.sess.contains_name(&attrs, sym::needs_panic_runtime), - no_builtins: tcx.sess.contains_name(&attrs, sym::no_builtins), - panic_runtime: tcx.sess.contains_name(&attrs, sym::panic_runtime), - profiler_runtime: tcx.sess.contains_name(&attrs, sym::profiler_runtime), - symbol_mangling_version: tcx.sess.opts.get_symbol_mangling_version(), - - crate_deps, - dylib_dependency_formats, - lib_features, - stability_implications, - lang_items, - diagnostic_items, - lang_items_missing, - native_libraries, - foreign_modules, - source_map, - traits, - impls, - incoherent_impls, - exported_symbols, - interpret_alloc_index, - tables, - syntax_contexts, - expn_data, - expn_hashes, - def_path_hash_map, + let exported_symbols = stat!("exported-symbols", || { + self.encode_exported_symbols(&tcx.exported_symbols(LOCAL_CRATE)) + }); + + // Encode the hygiene data. + // IMPORTANT: this *must* be the last thing that we encode (other than `SourceMap`). The + // process of encoding other items (e.g. `optimized_mir`) may cause us to load data from + // the incremental cache. If this causes us to deserialize a `Span`, then we may load + // additional `SyntaxContext`s into the global `HygieneData`. Therefore, we need to encode + // the hygiene data last to ensure that we encode any `SyntaxContext`s that might be used. + let (syntax_contexts, expn_data, expn_hashes) = stat!("hygiene", || self.encode_hygiene()); + + let def_path_hash_map = stat!("def-path-hash-map", || self.encode_def_path_hash_map()); + + // Encode source_map. This needs to be done last, because encoding `Span`s tells us which + // `SourceFiles` we actually need to encode. + let source_map = stat!("source-map", || self.encode_source_map()); + + let root = stat!("final", || { + let attrs = tcx.hir().krate_attrs(); + self.lazy(CrateRoot { + name: tcx.crate_name(LOCAL_CRATE), + extra_filename: tcx.sess.opts.cg.extra_filename.clone(), + triple: tcx.sess.opts.target_triple.clone(), + hash: tcx.crate_hash(LOCAL_CRATE), + stable_crate_id: tcx.def_path_hash(LOCAL_CRATE.as_def_id()).stable_crate_id(), + required_panic_strategy: tcx.required_panic_strategy(LOCAL_CRATE), + panic_in_drop_strategy: tcx.sess.opts.unstable_opts.panic_in_drop, + edition: tcx.sess.edition(), + has_global_allocator: tcx.has_global_allocator(LOCAL_CRATE), + has_panic_handler: tcx.has_panic_handler(LOCAL_CRATE), + has_default_lib_allocator: tcx + .sess + .contains_name(&attrs, sym::default_lib_allocator), + proc_macro_data, + debugger_visualizers, + compiler_builtins: tcx.sess.contains_name(&attrs, sym::compiler_builtins), + needs_allocator: tcx.sess.contains_name(&attrs, sym::needs_allocator), + needs_panic_runtime: tcx.sess.contains_name(&attrs, sym::needs_panic_runtime), + no_builtins: tcx.sess.contains_name(&attrs, sym::no_builtins), + panic_runtime: tcx.sess.contains_name(&attrs, sym::panic_runtime), + profiler_runtime: tcx.sess.contains_name(&attrs, sym::profiler_runtime), + symbol_mangling_version: tcx.sess.opts.get_symbol_mangling_version(), + + crate_deps, + dylib_dependency_formats, + lib_features, + stability_implications, + lang_items, + diagnostic_items, + lang_items_missing, + native_libraries, + foreign_modules, + source_map, + traits, + impls, + incoherent_impls, + exported_symbols, + interpret_alloc_index, + tables, + syntax_contexts, + expn_data, + expn_hashes, + def_path_hash_map, + }) }); - let final_bytes = self.position() - i; let total_bytes = self.position(); - let computed_total_bytes = preamble_bytes - + dep_bytes - + lib_feature_bytes - + stability_implications_bytes - + lang_item_bytes - + diagnostic_item_bytes - + native_lib_bytes - + foreign_modules_bytes - + def_path_table_bytes - + traits_bytes - + impls_bytes - + incoherent_impls_bytes - + mir_bytes - + item_bytes - + interpret_alloc_index_bytes - + proc_macro_data_bytes - + tables_bytes - + debugger_visualizers_bytes - + exported_symbols_bytes - + hygiene_bytes - + def_path_hash_map_bytes - + source_map_bytes - + final_bytes; + let computed_total_bytes: usize = stats.iter().map(|(_, size)| size).sum(); assert_eq!(total_bytes, computed_total_bytes); if tcx.sess.meta_stats() { @@ -783,48 +727,77 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } assert_eq!(self.opaque.file().stream_position().unwrap(), pos_before_rewind); + stats.sort_by_key(|&(_, usize)| usize); + + let prefix = "meta-stats"; let perc = |bytes| (bytes * 100) as f64 / total_bytes as f64; - let p = |label, bytes| { - eprintln!("{:>21}: {:>8} bytes ({:4.1}%)", label, bytes, perc(bytes)); - }; - eprintln!(""); + eprintln!("{} METADATA STATS", prefix); + eprintln!("{} {:<23}{:>10}", prefix, "Section", "Size"); + eprintln!( + "{} ----------------------------------------------------------------", + prefix + ); + for (label, size) in stats { + eprintln!( + "{} {:<23}{:>10} ({:4.1}%)", + prefix, + label, + to_readable_str(size), + perc(size) + ); + } + eprintln!( + "{} ----------------------------------------------------------------", + prefix + ); eprintln!( - "{} metadata bytes, of which {} bytes ({:.1}%) are zero", - total_bytes, - zero_bytes, + "{} {:<23}{:>10} (of which {:.1}% are zero bytes)", + prefix, + "Total", + to_readable_str(total_bytes), perc(zero_bytes) ); - p("preamble", preamble_bytes); - p("dep", dep_bytes); - p("lib feature", lib_feature_bytes); - p("stability_implications", stability_implications_bytes); - p("lang item", lang_item_bytes); - p("diagnostic item", diagnostic_item_bytes); - p("native lib", native_lib_bytes); - p("foreign modules", foreign_modules_bytes); - p("def-path table", def_path_table_bytes); - p("traits", traits_bytes); - p("impls", impls_bytes); - p("incoherent_impls", incoherent_impls_bytes); - p("mir", mir_bytes); - p("item", item_bytes); - p("interpret_alloc_index", interpret_alloc_index_bytes); - p("proc-macro-data", proc_macro_data_bytes); - p("tables", tables_bytes); - p("debugger visualizers", debugger_visualizers_bytes); - p("exported symbols", exported_symbols_bytes); - p("hygiene", hygiene_bytes); - p("def-path hashes", def_path_hash_map_bytes); - p("source_map", source_map_bytes); - p("final", final_bytes); - eprintln!(""); + eprintln!("{}", prefix); } root } } +/// Returns whether an attribute needs to be recorded in metadata, that is, if it's usable and +/// useful in downstream crates. Local-only attributes are an obvious example, but some +/// rustdoc-specific attributes can equally be of use while documenting the current crate only. +/// +/// Removing these superfluous attributes speeds up compilation by making the metadata smaller. +/// +/// Note: the `is_def_id_public` parameter is used to cache whether the given `DefId` has a public +/// visibility: this is a piece of data that can be computed once per defid, and not once per +/// attribute. Some attributes would only be usable downstream if they are public. +#[inline] +fn should_encode_attr( + tcx: TyCtxt<'_>, + attr: &Attribute, + def_id: LocalDefId, + is_def_id_public: &mut Option<bool>, +) -> bool { + if rustc_feature::is_builtin_only_local(attr.name_or_empty()) { + // Attributes marked local-only don't need to be encoded for downstream crates. + false + } else if attr.doc_str().is_some() { + // We keep all public doc comments because they might be "imported" into downstream crates + // if they use `#[doc(inline)]` to copy an item's documentation into their own. + *is_def_id_public + .get_or_insert_with(|| tcx.effective_visibilities(()).effective_vis(def_id).is_some()) + } else if attr.has_name(sym::doc) { + // If this is a `doc` attribute, and it's marked `inline` (as in `#[doc(inline)]`), we can + // remove it. It won't be inlinable in downstream crates. + attr.meta_item_list().map(|l| l.iter().any(|l| !l.has_name(sym::inline))).unwrap_or(false) + } else { + true + } +} + fn should_encode_visibility(def_kind: DefKind) -> bool { match def_kind { DefKind::Mod @@ -1120,14 +1093,44 @@ fn should_encode_const(def_kind: DefKind) -> bool { } } +fn should_encode_trait_impl_trait_tys<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool { + if tcx.def_kind(def_id) != DefKind::AssocFn { + return false; + } + + let Some(item) = tcx.opt_associated_item(def_id) else { return false; }; + if item.container != ty::AssocItemContainer::ImplContainer { + return false; + } + + let Some(trait_item_def_id) = item.trait_item_def_id else { return false; }; + + // FIXME(RPITIT): This does a somewhat manual walk through the signature + // of the trait fn to look for any RPITITs, but that's kinda doing a lot + // of work. We can probably remove this when we refactor RPITITs to be + // associated types. + tcx.fn_sig(trait_item_def_id).skip_binder().output().walk().any(|arg| { + if let ty::GenericArgKind::Type(ty) = arg.unpack() + && let ty::Projection(data) = ty.kind() + && tcx.def_kind(data.item_def_id) == DefKind::ImplTraitPlaceholder + { + true + } else { + false + } + }) +} + impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_attrs(&mut self, def_id: LocalDefId) { - let mut attrs = self - .tcx + let tcx = self.tcx; + let mut is_public: Option<bool> = None; + + let mut attrs = tcx .hir() - .attrs(self.tcx.hir().local_def_id_to_hir_id(def_id)) + .attrs(tcx.hir().local_def_id_to_hir_id(def_id)) .iter() - .filter(|attr| !rustc_feature::is_builtin_only_local(attr.name_or_empty())); + .filter(move |attr| should_encode_attr(tcx, attr, def_id, &mut is_public)); record_array!(self.tables.attributes[def_id.to_def_id()] <- attrs.clone()); if attrs.any(|attr| attr.may_have_doc_links()) { @@ -1189,6 +1192,15 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if let DefKind::Trait | DefKind::TraitAlias = def_kind { record!(self.tables.super_predicates_of[def_id] <- self.tcx.super_predicates_of(def_id)); } + if let DefKind::Enum | DefKind::Struct | DefKind::Union = def_kind { + let params_in_repr = self.tcx.params_in_repr(def_id); + record!(self.tables.params_in_repr[def_id] <- params_in_repr); + } + if should_encode_trait_impl_trait_tys(tcx, def_id) + && let Ok(table) = self.tcx.collect_trait_impl_trait_tys(def_id) + { + record!(self.tables.trait_impl_trait_tys[def_id] <- table); + } } let inherent_impls = tcx.crate_inherent_impls(()); for (def_id, implementations) in inherent_impls.inherent_impls.iter() { @@ -1278,14 +1290,21 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // from name resolution point of view. hir::ItemKind::ForeignMod { items, .. } => { for foreign_item in items { - yield foreign_item.id.def_id.local_def_index; + yield foreign_item.id.owner_id.def_id.local_def_index; } } // Only encode named non-reexport children, reexports are encoded // separately and unnamed items are not used by name resolution. hir::ItemKind::ExternCrate(..) => continue, - _ if tcx.def_key(item_id.def_id.to_def_id()).get_opt_name().is_some() => { - yield item_id.def_id.local_def_index; + hir::ItemKind::Struct(ref vdata, _) => { + yield item_id.owner_id.def_id.local_def_index; + // Encode constructors which take a separate slot in value namespace. + if let Some(ctor_hir_id) = vdata.ctor_hir_id() { + yield tcx.hir().local_def_id(ctor_hir_id).local_def_index; + } + } + _ if tcx.def_key(item_id.owner_id.to_def_id()).get_opt_name().is_some() => { + yield item_id.owner_id.def_id.local_def_index; } _ => continue, } @@ -1436,6 +1455,21 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record!(self.tables.unused_generic_params[def_id.to_def_id()] <- unused); } } + + // Encode all the deduced parameter attributes for everything that has MIR, even for items + // that can't be inlined. But don't if we aren't optimizing in non-incremental mode, to + // save the query traffic. + if tcx.sess.opts.output_types.should_codegen() + && tcx.sess.opts.optimize != OptLevel::No + && tcx.sess.opts.incremental.is_none() + { + for &local_def_id in tcx.mir_keys(()) { + if let DefKind::AssocFn | DefKind::Fn = tcx.def_kind(local_def_id) { + record_array!(self.tables.deduced_param_attrs[local_def_id.to_def_id()] <- + self.tcx.deduced_param_attrs(local_def_id.to_def_id())); + } + } + } } fn encode_stability(&mut self, def_id: DefId) { @@ -1507,7 +1541,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { 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); + return self.encode_info_for_mod(item.owner_id.def_id, m); } hir::ItemKind::OpaqueTy(..) => { self.encode_explicit_item_bounds(def_id); @@ -1592,12 +1626,17 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { }; // FIXME(eddyb) there should be a nicer way to do this. match item.kind { - hir::ItemKind::Enum(..) => record_array!(self.tables.children[def_id] <- - self.tcx.adt_def(def_id).variants().iter().map(|v| { - assert!(v.def_id.is_local()); - v.def_id.index - }) - ), + hir::ItemKind::Enum(..) => { + record_array!(self.tables.children[def_id] <- iter::from_generator(|| + for variant in tcx.adt_def(def_id).variants() { + yield variant.def_id.index; + // Encode constructors which take a separate slot in value namespace. + if let Some(ctor_def_id) = variant.ctor_def_id { + yield ctor_def_id.index; + } + } + )) + } hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => { record_array!(self.tables.children[def_id] <- self.tcx.adt_def(def_id).non_enum_variant().fields.iter().map(|f| { @@ -1634,7 +1673,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // normally in the visitor walk. match item.kind { hir::ItemKind::Enum(..) => { - let def = self.tcx.adt_def(item.def_id.to_def_id()); + let def = self.tcx.adt_def(item.owner_id.to_def_id()); for (i, variant) in def.variants().iter_enumerated() { self.encode_enum_variant_info(def, i); @@ -1644,7 +1683,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } } hir::ItemKind::Struct(ref struct_def, _) => { - let def = self.tcx.adt_def(item.def_id.to_def_id()); + let def = self.tcx.adt_def(item.owner_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); @@ -1653,13 +1692,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } hir::ItemKind::Impl { .. } => { for &trait_item_def_id in - self.tcx.associated_item_def_ids(item.def_id.to_def_id()).iter() + self.tcx.associated_item_def_ids(item.owner_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() + for &item_def_id in + self.tcx.associated_item_def_ids(item.owner_id.to_def_id()).iter() { self.encode_info_for_trait_item(item_def_id); } @@ -1900,8 +1940,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { FxHashMap::default(); for id in tcx.hir().items() { - if matches!(tcx.def_kind(id.def_id), DefKind::Impl) { - if let Some(trait_ref) = tcx.impl_trait_ref(id.def_id.to_def_id()) { + if matches!(tcx.def_kind(id.owner_id), DefKind::Impl) { + if let Some(trait_ref) = tcx.impl_trait_ref(id.owner_id) { let simplified_self_ty = fast_reject::simplify_type( self.tcx, trait_ref.self_ty(), @@ -1911,7 +1951,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fx_hash_map .entry(trait_ref.def_id) .or_default() - .push((id.def_id.local_def_index, simplified_self_ty)); + .push((id.owner_id.def_id.local_def_index, simplified_self_ty)); } } } @@ -2052,12 +2092,12 @@ impl<'a, 'tcx> Visitor<'tcx> for EncodeContext<'a, '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_info_for_item(item.owner_id.to_def_id(), item), } } fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem<'tcx>) { intravisit::walk_foreign_item(self, ni); - self.encode_info_for_foreign_item(ni.def_id.to_def_id(), ni); + self.encode_info_for_foreign_item(ni.owner_id.to_def_id(), ni); } fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) { intravisit::walk_generics(self, generics); @@ -2276,8 +2316,8 @@ pub fn provide(providers: &mut Providers) { let mut traits = Vec::new(); for id in tcx.hir().items() { - if matches!(tcx.def_kind(id.def_id), DefKind::Trait | DefKind::TraitAlias) { - traits.push(id.def_id.to_def_id()) + if matches!(tcx.def_kind(id.owner_id), DefKind::Trait | DefKind::TraitAlias) { + traits.push(id.owner_id.to_def_id()) } } diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 748b3afec..27dc8ff16 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -1,6 +1,7 @@ use crate::creader::CrateMetadataRef; use decoder::Metadata; use def_path_hash_map::DefPathHashMapRef; +use rustc_data_structures::fx::FxHashMap; use table::TableBuilder; use rustc_ast as ast; @@ -12,7 +13,8 @@ use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::def_id::{CrateNum, DefId, DefIndex, DefPathHash, StableCrateId}; use rustc_hir::definitions::DefKey; use rustc_hir::lang_items; -use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec}; +use rustc_index::bit_set::{BitSet, FiniteBitSet}; +use rustc_index::vec::IndexVec; use rustc_middle::metadata::ModChild; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; @@ -21,7 +23,7 @@ use rustc_middle::mir; use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, ReprOptions, Ty}; -use rustc_middle::ty::{GeneratorDiagnosticData, ParameterizedOverTcx, TyCtxt}; +use rustc_middle::ty::{DeducedParamAttrs, GeneratorDiagnosticData, ParameterizedOverTcx, TyCtxt}; use rustc_serialize::opaque::FileEncoder; use rustc_session::config::SymbolManglingVersion; use rustc_session::cstore::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib}; @@ -382,6 +384,7 @@ define_tables! { inherent_impls: Table<DefIndex, LazyArray<DefIndex>>, expn_that_defined: Table<DefIndex, LazyValue<ExpnId>>, unused_generic_params: Table<DefIndex, LazyValue<FiniteBitSet<u32>>>, + params_in_repr: Table<DefIndex, LazyValue<BitSet<u32>>>, repr_options: Table<DefIndex, LazyValue<ReprOptions>>, // `def_keys` and `def_path_hashes` represent a lazy version of a // `DefPathTable`. This allows us to avoid deserializing an entire @@ -399,6 +402,9 @@ define_tables! { macro_definition: Table<DefIndex, LazyValue<ast::MacArgs>>, proc_macro: Table<DefIndex, MacroKind>, module_reexports: Table<DefIndex, LazyArray<ModChild>>, + deduced_param_attrs: Table<DefIndex, LazyArray<DeducedParamAttrs>>, + + trait_impl_trait_tys: Table<DefIndex, LazyValue<FxHashMap<DefId, Ty<'static>>>>, } #[derive(TyEncodable, TyDecodable)] |