diff options
Diffstat (limited to 'compiler/rustc_metadata')
-rw-r--r-- | compiler/rustc_metadata/Cargo.toml | 1 | ||||
-rw-r--r-- | compiler/rustc_metadata/messages.ftl (renamed from compiler/rustc_metadata/locales/en-US.ftl) | 0 | ||||
-rw-r--r-- | compiler/rustc_metadata/src/creader.rs | 131 | ||||
-rw-r--r-- | compiler/rustc_metadata/src/fs.rs | 26 | ||||
-rw-r--r-- | compiler/rustc_metadata/src/lib.rs | 5 | ||||
-rw-r--r-- | compiler/rustc_metadata/src/locator.rs | 46 | ||||
-rw-r--r-- | compiler/rustc_metadata/src/native_libs.rs | 76 | ||||
-rw-r--r-- | compiler/rustc_metadata/src/rmeta/decoder.rs | 204 | ||||
-rw-r--r-- | compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs | 111 | ||||
-rw-r--r-- | compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs | 14 | ||||
-rw-r--r-- | compiler/rustc_metadata/src/rmeta/encoder.rs | 402 | ||||
-rw-r--r-- | compiler/rustc_metadata/src/rmeta/mod.rs | 21 | ||||
-rw-r--r-- | compiler/rustc_metadata/src/rmeta/table.rs | 27 |
13 files changed, 541 insertions, 523 deletions
diff --git a/compiler/rustc_metadata/Cargo.toml b/compiler/rustc_metadata/Cargo.toml index bee5c8541..4d7c133e0 100644 --- a/compiler/rustc_metadata/Cargo.toml +++ b/compiler/rustc_metadata/Cargo.toml @@ -18,6 +18,7 @@ rustc_attr = { path = "../rustc_attr" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_feature = { path = "../rustc_feature" } +rustc_fs_util = { path = "../rustc_fs_util" } rustc_hir = { path = "../rustc_hir" } rustc_hir_pretty = { path = "../rustc_hir_pretty" } rustc_target = { path = "../rustc_target" } diff --git a/compiler/rustc_metadata/locales/en-US.ftl b/compiler/rustc_metadata/messages.ftl index 79b8b4172..79b8b4172 100644 --- a/compiler/rustc_metadata/locales/en-US.ftl +++ b/compiler/rustc_metadata/messages.ftl diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index b05626311..23aceca06 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -6,11 +6,11 @@ use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob use rustc_ast::expand::allocator::AllocatorKind; use rustc_ast::{self as ast, *}; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::svh::Svh; -use rustc_data_structures::sync::MappedReadGuard; +use rustc_data_structures::sync::{MappedReadGuard, MappedWriteGuard, ReadGuard, WriteGuard}; use rustc_expand::base::SyntaxExtension; -use rustc_hir::def_id::{CrateNum, LocalDefId, StableCrateId, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, LocalDefId, StableCrateId, StableCrateIdMap, LOCAL_CRATE}; use rustc_hir::definitions::Definitions; use rustc_index::vec::IndexVec; use rustc_middle::ty::TyCtxt; @@ -46,9 +46,8 @@ pub struct CStore { /// This crate has a `#[alloc_error_handler]` item. has_alloc_error_handler: bool, - /// This map is used to verify we get no hash conflicts between - /// `StableCrateId` values. - pub(crate) stable_crate_ids: FxHashMap<StableCrateId, CrateNum>, + /// The interned [StableCrateId]s. + pub(crate) stable_crate_ids: StableCrateIdMap, /// Unused externs of the crate unused_externs: Vec<Symbol>, @@ -133,14 +132,32 @@ impl<'a> std::fmt::Debug for CrateDump<'a> { impl CStore { pub fn from_tcx(tcx: TyCtxt<'_>) -> MappedReadGuard<'_, CStore> { - MappedReadGuard::map(tcx.cstore_untracked(), |c| { - c.as_any().downcast_ref::<CStore>().expect("`tcx.cstore` is not a `CStore`") + ReadGuard::map(tcx.untracked().cstore.read(), |cstore| { + cstore.as_any().downcast_ref::<CStore>().expect("`tcx.cstore` is not a `CStore`") }) } - fn alloc_new_crate_num(&mut self) -> CrateNum { - self.metas.push(None); - CrateNum::new(self.metas.len() - 1) + pub fn from_tcx_mut(tcx: TyCtxt<'_>) -> MappedWriteGuard<'_, CStore> { + WriteGuard::map(tcx.untracked().cstore.write(), |cstore| { + cstore.untracked_as_any().downcast_mut().expect("`tcx.cstore` is not a `CStore`") + }) + } + + fn intern_stable_crate_id(&mut self, root: &CrateRoot) -> Result<CrateNum, CrateError> { + assert_eq!(self.metas.len(), self.stable_crate_ids.len()); + let num = CrateNum::new(self.stable_crate_ids.len()); + if let Some(&existing) = self.stable_crate_ids.get(&root.stable_crate_id()) { + let crate_name0 = root.name(); + if let Some(crate_name1) = self.metas[existing].as_ref().map(|data| data.name()) { + Err(CrateError::StableCrateIdCollision(crate_name0, crate_name1)) + } else { + Err(CrateError::SymbolConflictsCurrent(crate_name0)) + } + } else { + self.metas.push(None); + self.stable_crate_ids.insert(root.stable_crate_id(), num); + Ok(num) + } } pub fn has_crate_data(&self, cnum: CrateNum) -> bool { @@ -168,7 +185,7 @@ impl CStore { fn push_dependencies_in_postorder(&self, deps: &mut Vec<CrateNum>, cnum: CrateNum) { if !deps.contains(&cnum) { let data = self.get_crate_data(cnum); - for &dep in data.dependencies().iter() { + for dep in data.dependencies() { if dep != cnum { self.push_dependencies_in_postorder(deps, dep); } @@ -241,7 +258,7 @@ impl CStore { } pub fn new(sess: &Session) -> CStore { - let mut stable_crate_ids = FxHashMap::default(); + let mut stable_crate_ids = StableCrateIdMap::default(); stable_crate_ids.insert(sess.local_stable_crate_id(), LOCAL_CRATE); CStore { // We add an empty entry for LOCAL_CRATE (which maps to zero) in @@ -268,9 +285,6 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { ) -> Self { CrateLoader { tcx, cstore, used_extern_options } } - pub fn cstore(&self) -> &CStore { - &self.cstore - } fn existing_match(&self, name: Symbol, hash: Option<Svh>, kind: PathKind) -> Option<CrateNum> { for (cnum, data) in self.cstore.iter_crate_data() { @@ -339,42 +353,6 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { None } - fn verify_no_symbol_conflicts(&self, root: &CrateRoot) -> Result<(), CrateError> { - // Check for (potential) conflicts with the local crate - if self.sess.local_stable_crate_id() == root.stable_crate_id() { - return Err(CrateError::SymbolConflictsCurrent(root.name())); - } - - // Check for conflicts with any crate loaded so far - for (_, other) in self.cstore.iter_crate_data() { - // Same stable crate id but different SVH - if other.stable_crate_id() == root.stable_crate_id() && other.hash() != root.hash() { - bug!( - "Previously returned E0523 here. \ - See https://github.com/rust-lang/rust/pull/100599 for additional discussion.\ - root.name() = {}.", - root.name() - ); - } - } - - Ok(()) - } - - fn verify_no_stable_crate_id_hash_conflicts( - &mut self, - root: &CrateRoot, - cnum: CrateNum, - ) -> Result<(), CrateError> { - if let Some(existing) = self.cstore.stable_crate_ids.insert(root.stable_crate_id(), cnum) { - let crate_name0 = root.name(); - let crate_name1 = self.cstore.get_crate_data(existing).name(); - return Err(CrateError::StableCrateIdCollision(crate_name0, crate_name1)); - } - - Ok(()) - } - fn register_crate( &mut self, host_lib: Option<Library>, @@ -393,7 +371,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { self.sess.opts.externs.get(name.as_str()).map_or(false, |e| e.is_private_dep); // Claim this crate number and cache it - let cnum = self.cstore.alloc_new_crate_num(); + let cnum = self.cstore.intern_stable_crate_id(&crate_root)?; info!( "register crate `{}` (cnum = {}. private_dep = {})", @@ -429,14 +407,6 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { None }; - // Perform some verification *after* resolve_crate_deps() above is - // known to have been successful. It seems that - in error cases - the - // cstore can be in a temporarily invalid state between cnum allocation - // and dependency resolution and the verification code would produce - // ICEs in that case (see #83045). - self.verify_no_symbol_conflicts(&crate_root)?; - self.verify_no_stable_crate_id_hash_conflicts(&crate_root, cnum)?; - let crate_metadata = CrateMetadata::new( self.sess, &self.cstore, @@ -635,7 +605,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { if cmeta.update_extern_crate(extern_crate) { // Propagate the extern crate info to dependencies if it was updated. let extern_crate = ExternCrate { dependency_of: cnum, ..extern_crate }; - for &dep_cnum in cmeta.dependencies().iter() { + for dep_cnum in cmeta.dependencies() { self.update_extern_crate(dep_cnum, extern_crate); } } @@ -717,8 +687,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // compilation mode also comes into play. let desired_strategy = self.sess.panic_strategy(); let mut runtime_found = false; - let mut needs_panic_runtime = - self.sess.contains_name(&krate.attrs, sym::needs_panic_runtime); + let mut needs_panic_runtime = attr::contains_name(&krate.attrs, sym::needs_panic_runtime); for (cnum, data) in self.cstore.iter_crate_data() { needs_panic_runtime = needs_panic_runtime || data.needs_panic_runtime(); @@ -786,7 +755,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { info!("loading profiler"); 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) { + if name == sym::profiler_builtins && attr::contains_name(&krate.attrs, sym::no_core) { self.sess.emit_err(errors::ProfilerBuiltinsNeedsCore); } @@ -800,14 +769,14 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } fn inject_allocator_crate(&mut self, krate: &ast::Crate) { - self.cstore.has_global_allocator = match &*global_allocator_spans(&self.sess, krate) { + self.cstore.has_global_allocator = match &*global_allocator_spans(krate) { [span1, span2, ..] => { self.sess.emit_err(errors::NoMultipleGlobalAlloc { span2: *span2, span1: *span1 }); true } spans => !spans.is_empty(), }; - self.cstore.has_alloc_error_handler = match &*alloc_error_handler_spans(&self.sess, krate) { + self.cstore.has_alloc_error_handler = match &*alloc_error_handler_spans(krate) { [span1, span2, ..] => { self.sess .emit_err(errors::NoMultipleAllocErrorHandler { span2: *span2, span1: *span1 }); @@ -819,7 +788,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // Check to see if we actually need an allocator. This desire comes // about through the `#![needs_allocator]` attribute and is typically // written down in liballoc. - if !self.sess.contains_name(&krate.attrs, sym::needs_allocator) + if !attr::contains_name(&krate.attrs, sym::needs_allocator) && !self.cstore.iter_crate_data().any(|(_, data)| data.needs_allocator()) { return; @@ -878,7 +847,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // allocator. At this point our allocator request is typically fulfilled // by the standard library, denoted by the `#![default_lib_allocator]` // attribute. - if !self.sess.contains_name(&krate.attrs, sym::default_lib_allocator) + if !attr::contains_name(&krate.attrs, sym::default_lib_allocator) && !self.cstore.iter_crate_data().any(|(_, data)| data.has_default_lib_allocator()) { self.sess.emit_err(errors::GlobalAllocRequired); @@ -1000,7 +969,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } None => item.ident.name, }; - let dep_kind = if self.sess.contains_name(&item.attrs, sym::no_link) { + let dep_kind = if attr::contains_name(&item.attrs, sym::no_link) { CrateDepKind::MacrosOnly } else { CrateDepKind::Explicit @@ -1046,16 +1015,15 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } } -fn global_allocator_spans(sess: &Session, krate: &ast::Crate) -> Vec<Span> { - struct Finder<'a> { - sess: &'a Session, +fn global_allocator_spans(krate: &ast::Crate) -> Vec<Span> { + struct Finder { name: Symbol, spans: Vec<Span>, } - impl<'ast, 'a> visit::Visitor<'ast> for Finder<'a> { + impl<'ast> visit::Visitor<'ast> for Finder { fn visit_item(&mut self, item: &'ast ast::Item) { if item.ident.name == self.name - && self.sess.contains_name(&item.attrs, sym::rustc_std_internal_symbol) + && attr::contains_name(&item.attrs, sym::rustc_std_internal_symbol) { self.spans.push(item.span); } @@ -1064,21 +1032,20 @@ fn global_allocator_spans(sess: &Session, krate: &ast::Crate) -> Vec<Span> { } let name = Symbol::intern(&AllocatorKind::Global.fn_name(sym::alloc)); - let mut f = Finder { sess, name, spans: Vec::new() }; + let mut f = Finder { name, spans: Vec::new() }; visit::walk_crate(&mut f, krate); f.spans } -fn alloc_error_handler_spans(sess: &Session, krate: &ast::Crate) -> Vec<Span> { - struct Finder<'a> { - sess: &'a Session, +fn alloc_error_handler_spans(krate: &ast::Crate) -> Vec<Span> { + struct Finder { name: Symbol, spans: Vec<Span>, } - impl<'ast, 'a> visit::Visitor<'ast> for Finder<'a> { + impl<'ast> visit::Visitor<'ast> for Finder { fn visit_item(&mut self, item: &'ast ast::Item) { if item.ident.name == self.name - && self.sess.contains_name(&item.attrs, sym::rustc_std_internal_symbol) + && attr::contains_name(&item.attrs, sym::rustc_std_internal_symbol) { self.spans.push(item.span); } @@ -1087,7 +1054,7 @@ fn alloc_error_handler_spans(sess: &Session, krate: &ast::Crate) -> Vec<Span> { } let name = Symbol::intern(&AllocatorKind::Global.fn_name(sym::oom)); - let mut f = Finder { sess, name, spans: Vec::new() }; + let mut f = Finder { name, spans: Vec::new() }; visit::walk_crate(&mut f, krate); f.spans } diff --git a/compiler/rustc_metadata/src/fs.rs b/compiler/rustc_metadata/src/fs.rs index f64318997..08de828fb 100644 --- a/compiler/rustc_metadata/src/fs.rs +++ b/compiler/rustc_metadata/src/fs.rs @@ -6,9 +6,9 @@ use crate::{encode_metadata, EncodedMetadata}; use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_hir::def_id::LOCAL_CRATE; use rustc_middle::ty::TyCtxt; -use rustc_session::config::{CrateType, OutputType}; +use rustc_session::config::OutputType; use rustc_session::output::filename_for_metadata; -use rustc_session::Session; +use rustc_session::{MetadataKind, Session}; use tempfile::Builder as TempFileBuilder; use std::fs; @@ -39,27 +39,6 @@ pub fn emit_wrapper_file( } pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) { - #[derive(PartialEq, Eq, PartialOrd, Ord)] - enum MetadataKind { - None, - Uncompressed, - Compressed, - } - - let metadata_kind = tcx - .sess - .crate_types() - .iter() - .map(|ty| match *ty { - CrateType::Executable | CrateType::Staticlib | CrateType::Cdylib => MetadataKind::None, - - CrateType::Rlib => MetadataKind::Uncompressed, - - CrateType::Dylib | CrateType::ProcMacro => MetadataKind::Compressed, - }) - .max() - .unwrap_or(MetadataKind::None); - let crate_name = tcx.crate_name(LOCAL_CRATE); let out_filename = filename_for_metadata(tcx.sess, crate_name, tcx.output_filenames(())); // To avoid races with another rustc process scanning the output directory, @@ -76,6 +55,7 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) { // Always create a file at `metadata_filename`, even if we have nothing to write to it. // This simplifies the creation of the output `out_filename` when requested. + let metadata_kind = tcx.sess.metadata_kind(); match metadata_kind { MetadataKind::None => { std::fs::File::create(&metadata_filename).unwrap_or_else(|err| { diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index 6f6d3731c..81e62eccb 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -4,7 +4,6 @@ #![feature(generators)] #![feature(iter_from_generator)] #![feature(let_chains)] -#![feature(once_cell)] #![feature(proc_macro_internals)] #![feature(macro_metavar_expr)] #![feature(min_specialization)] @@ -23,8 +22,6 @@ extern crate proc_macro; extern crate rustc_macros; #[macro_use] extern crate rustc_middle; -#[macro_use] -extern crate rustc_data_structures; #[macro_use] extern crate tracing; @@ -47,4 +44,4 @@ pub use fs::{emit_wrapper_file, METADATA_FILENAME}; pub use native_libs::find_native_static_library; pub use rmeta::{encode_metadata, EncodedMetadata, METADATA_HEADER}; -fluent_messages! { "../locales/en-US.ftl" } +fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 755a24253..c6af8d632 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -218,10 +218,11 @@ use crate::rmeta::{rustc_version, MetadataBlob, METADATA_HEADER}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::memmap::Mmap; -use rustc_data_structures::owning_ref::OwningRef; +use rustc_data_structures::owned_slice::slice_owned; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::MetadataRef; use rustc_errors::{DiagnosticArgValue, FatalError, IntoDiagnosticArg}; +use rustc_fs_util::try_canonicalize; use rustc_session::config::{self, CrateType}; use rustc_session::cstore::{CrateSource, MetadataLoader}; use rustc_session::filesearch::FileSearch; @@ -235,8 +236,9 @@ use rustc_target::spec::{Target, TargetTriple}; use snap::read::FrameDecoder; use std::borrow::Cow; use std::io::{Read, Result as IoResult, Write}; +use std::ops::Deref; use std::path::{Path, PathBuf}; -use std::{cmp, fmt, fs}; +use std::{cmp, fmt}; #[derive(Clone)] pub(crate) struct CrateLocator<'a> { @@ -441,7 +443,7 @@ impl<'a> CrateLocator<'a> { info!("lib candidate: {}", spf.path.display()); let (rlibs, rmetas, dylibs) = candidates.entry(hash.to_string()).or_default(); - let path = fs::canonicalize(&spf.path).unwrap_or_else(|_| spf.path.clone()); + let path = try_canonicalize(&spf.path).unwrap_or_else(|_| spf.path.clone()); if seen_paths.contains(&path) { continue; }; @@ -636,7 +638,7 @@ impl<'a> CrateLocator<'a> { // as well. if let Some((prev, _)) = &ret { let sysroot = self.sysroot; - let sysroot = sysroot.canonicalize().unwrap_or_else(|_| sysroot.to_path_buf()); + let sysroot = try_canonicalize(sysroot).unwrap_or_else(|_| sysroot.to_path_buf()); if prev.starts_with(&sysroot) { continue; } @@ -760,14 +762,14 @@ impl<'a> CrateLocator<'a> { } pub(crate) fn into_error(self, root: Option<CratePaths>) -> CrateError { - CrateError::LocatorCombined(CombinedLocatorError { + CrateError::LocatorCombined(Box::new(CombinedLocatorError { crate_name: self.crate_name, root, triple: self.triple, dll_prefix: self.target.dll_prefix.to_string(), dll_suffix: self.target.dll_suffix.to_string(), crate_rejections: self.crate_rejections, - }) + })) } } @@ -789,6 +791,9 @@ fn get_metadata_section<'p>( loader.get_dylib_metadata(target, filename).map_err(MetadataError::LoadFailure)?; // The header is uncompressed let header_len = METADATA_HEADER.len(); + // header + u32 length of data + let data_start = header_len + 4; + debug!("checking {} bytes of metadata-version stamp", header_len); let header = &buf[..cmp::min(header_len, buf.len())]; if header != METADATA_HEADER { @@ -798,21 +803,26 @@ fn get_metadata_section<'p>( ))); } + // Length of the compressed stream - this allows linkers to pad the section if they want + let Ok(len_bytes) = <[u8; 4]>::try_from(&buf[header_len..cmp::min(data_start, buf.len())]) else { + return Err(MetadataError::LoadFailure("invalid metadata length found".to_string())); + }; + let compressed_len = u32::from_be_bytes(len_bytes) as usize; + // Header is okay -> inflate the actual metadata - let compressed_bytes = &buf[header_len..]; + let compressed_bytes = &buf[data_start..(data_start + compressed_len)]; debug!("inflating {} bytes of compressed metadata", compressed_bytes.len()); // Assume the decompressed data will be at least the size of the compressed data, so we // don't have to grow the buffer as much. let mut inflated = Vec::with_capacity(compressed_bytes.len()); - match FrameDecoder::new(compressed_bytes).read_to_end(&mut inflated) { - Ok(_) => rustc_erase_owner!(OwningRef::new(inflated).map_owner_box()), - Err(_) => { - return Err(MetadataError::LoadFailure(format!( - "failed to decompress metadata: {}", - filename.display() - ))); - } - } + FrameDecoder::new(compressed_bytes).read_to_end(&mut inflated).map_err(|_| { + MetadataError::LoadFailure(format!( + "failed to decompress metadata: {}", + filename.display() + )) + })?; + + slice_owned(inflated, Deref::deref) } CrateFlavor::Rmeta => { // mmap the file, because only a small fraction of it is read. @@ -830,7 +840,7 @@ fn get_metadata_section<'p>( )) })?; - rustc_erase_owner!(OwningRef::new(mmap).map_owner_box()) + slice_owned(mmap, Deref::deref) } }; let blob = MetadataBlob::new(raw_bytes); @@ -948,7 +958,7 @@ pub(crate) enum CrateError { StableCrateIdCollision(Symbol, Symbol), DlOpen(String), DlSym(String), - LocatorCombined(CombinedLocatorError), + LocatorCombined(Box<CombinedLocatorError>), NonDylibPlugin(Symbol), } diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index d6f68b2e1..b855c8e43 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -46,7 +46,7 @@ pub fn find_native_static_library( } fn find_bundled_library( - name: Option<Symbol>, + name: Symbol, verbatim: Option<bool>, kind: NativeLibKind, has_cfg: bool, @@ -58,7 +58,7 @@ fn find_bundled_library( { let verbatim = verbatim.unwrap_or(false); let search_paths = &sess.target_filesearch(PathKind::Native).search_path_dirs(); - return find_native_static_library(name.unwrap().as_str(), verbatim, search_paths, sess) + return find_native_static_library(name.as_str(), verbatim, search_paths, sess) .file_name() .and_then(|s| s.to_str()) .map(Symbol::intern); @@ -336,10 +336,16 @@ impl<'tcx> Collector<'tcx> { if name.is_some() || kind.is_some() || modifiers.is_some() || cfg.is_some() { sess.emit_err(errors::IncompatibleWasmLink { span }); } - } else if name.is_none() { - sess.emit_err(errors::LinkRequiresName { span: m.span }); } + if wasm_import_module.is_some() { + (name, kind) = (wasm_import_module, Some(NativeLibKind::WasmImportModule)); + } + let Some((name, name_span)) = name else { + sess.emit_err(errors::LinkRequiresName { span: m.span }); + continue; + }; + // 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) { @@ -349,8 +355,8 @@ impl<'tcx> Collector<'tcx> { let dll_imports = match kind { Some(NativeLibKind::RawDylib) => { - if let Some((name, span)) = name && name.as_str().contains('\0') { - sess.emit_err(errors::RawDylibNoNul { span }); + if name.as_str().contains('\0') { + sess.emit_err(errors::RawDylibNoNul { span: name_span }); } foreign_mod_items .iter() @@ -389,7 +395,6 @@ impl<'tcx> Collector<'tcx> { } }; - let name = name.map(|(name, _)| name); let kind = kind.unwrap_or(NativeLibKind::Unspecified); let filename = find_bundled_library(name, verbatim, kind, cfg.is_some(), sess); self.libs.push(NativeLib { @@ -398,7 +403,6 @@ impl<'tcx> Collector<'tcx> { kind, cfg, foreign_module: Some(it.owner_id.to_def_id()), - wasm_import_module: wasm_import_module.map(|(name, _)| name), verbatim, dll_imports, }); @@ -415,11 +419,7 @@ impl<'tcx> Collector<'tcx> { self.tcx.sess.emit_err(errors::LibFrameworkApple); } if let Some(ref new_name) = lib.new_name { - let any_duplicate = self - .libs - .iter() - .filter_map(|lib| lib.name.as_ref()) - .any(|n| n.as_str() == lib.name); + let any_duplicate = self.libs.iter().any(|n| n.name.as_str() == lib.name); if new_name.is_empty() { self.tcx.sess.emit_err(errors::EmptyRenamingTarget { lib_name: &lib.name }); } else if !any_duplicate { @@ -444,33 +444,28 @@ impl<'tcx> Collector<'tcx> { let mut existing = self .libs .drain_filter(|lib| { - if let Some(lib_name) = lib.name { - if lib_name.as_str() == passed_lib.name { - // FIXME: This whole logic is questionable, whether modifiers are - // involved or not, library reordering and kind overriding without - // explicit `:rename` in particular. - if lib.has_modifiers() || passed_lib.has_modifiers() { - match lib.foreign_module { - Some(def_id) => { - self.tcx.sess.emit_err(errors::NoLinkModOverride { - span: Some(self.tcx.def_span(def_id)), - }) - } - None => self - .tcx - .sess - .emit_err(errors::NoLinkModOverride { span: None }), - }; - } - if passed_lib.kind != NativeLibKind::Unspecified { - lib.kind = passed_lib.kind; - } - if let Some(new_name) = &passed_lib.new_name { - lib.name = Some(Symbol::intern(new_name)); - } - lib.verbatim = passed_lib.verbatim; - return true; + if lib.name.as_str() == passed_lib.name { + // FIXME: This whole logic is questionable, whether modifiers are + // involved or not, library reordering and kind overriding without + // explicit `:rename` in particular. + if lib.has_modifiers() || passed_lib.has_modifiers() { + match lib.foreign_module { + Some(def_id) => self.tcx.sess.emit_err(errors::NoLinkModOverride { + span: Some(self.tcx.def_span(def_id)), + }), + None => { + self.tcx.sess.emit_err(errors::NoLinkModOverride { span: None }) + } + }; + } + if passed_lib.kind != NativeLibKind::Unspecified { + lib.kind = passed_lib.kind; + } + if let Some(new_name) = &passed_lib.new_name { + lib.name = Symbol::intern(new_name); } + lib.verbatim = passed_lib.verbatim; + return true; } false }) @@ -478,7 +473,7 @@ 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 name = 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, false, sess); @@ -488,7 +483,6 @@ impl<'tcx> Collector<'tcx> { kind: passed_lib.kind, cfg: None, foreign_module: None, - wasm_import_module: None, verbatim: passed_lib.verbatim, dll_imports: Vec::new(), }); diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index b1e59b0a4..9f41dc92f 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1,13 +1,14 @@ // Decoding metadata from a single crate's metadata use crate::creader::{CStore, CrateMetadataRef}; +use crate::rmeta::table::IsDefault; use crate::rmeta::*; use rustc_ast as ast; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::svh::Svh; -use rustc_data_structures::sync::{Lock, LockGuard, Lrc, OnceCell}; +use rustc_data_structures::sync::{AppendOnlyVec, Lock, Lrc, OnceCell}; use rustc_data_structures::unhash::UnhashMap; use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind}; use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, DeriveProcMacro}; @@ -30,7 +31,6 @@ use rustc_session::cstore::{ }; use rustc_session::Session; use rustc_span::hygiene::ExpnIndex; -use rustc_span::source_map::{respan, Spanned}; use rustc_span::symbol::{kw, Ident, Symbol}; use rustc_span::{self, BytePos, ExpnId, Pos, Span, SyntaxContext, DUMMY_SP}; @@ -52,12 +52,6 @@ mod cstore_impl; #[derive(Clone)] pub(crate) struct MetadataBlob(Lrc<MetadataRef>); -// This is needed so we can create an OwningRef into the blob. -// The data behind a `MetadataBlob` has a stable address because it is -// contained within an Rc/Arc. -unsafe impl rustc_data_structures::owning_ref::StableAddress for MetadataBlob {} - -// This is needed so we can create an OwningRef into the blob. impl std::ops::Deref for MetadataBlob { type Target = [u8]; @@ -110,7 +104,7 @@ pub(crate) struct CrateMetadata { /// IDs as they are seen from the current compilation session. cnum_map: CrateNumMap, /// Same ID set as `cnum_map` plus maybe some injected crates like panic runtime. - dependencies: Lock<Vec<CrateNum>>, + dependencies: AppendOnlyVec<CrateNum>, /// How to link (or not link) this crate to the currently compiled crate. dep_kind: Lock<CrateDepKind>, /// Filesystem location of this crate. @@ -311,8 +305,11 @@ impl<T: ParameterizedOverTcx> LazyArray<T> { impl<'a, 'tcx> DecodeContext<'a, 'tcx> { #[inline] fn tcx(&self) -> TyCtxt<'tcx> { - debug_assert!(self.tcx.is_some(), "missing TyCtxt in DecodeContext"); - self.tcx.unwrap() + let Some(tcx) = self.tcx else { + bug!("No TyCtxt found for decoding. \ + You need to explicitly pass `(crate_metadata_ref, tcx)` to `decode` instead of just `crate_metadata_ref`."); + }; + tcx } #[inline] @@ -454,7 +451,12 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for ast::AttrId { impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for SyntaxContext { fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> SyntaxContext { let cdata = decoder.cdata(); - let sess = decoder.sess.unwrap(); + + let Some(sess) = decoder.sess else { + bug!("Cannot decode SyntaxContext without Session.\ + You need to explicitly pass `(crate_metadata_ref, tcx)` to `decode` instead of just `crate_metadata_ref`."); + }; + let cname = cdata.root.name; rustc_span::hygiene::decode_syntax_context(decoder, &cdata.hygiene_context, |_, id| { debug!("SpecializedDecoder<SyntaxContext>: decoding {}", id); @@ -471,7 +473,11 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for SyntaxContext { impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for ExpnId { fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> ExpnId { let local_cdata = decoder.cdata(); - let sess = decoder.sess.unwrap(); + + let Some(sess) = decoder.sess else { + bug!("Cannot decode ExpnId without Session. \ + You need to explicitly pass `(crate_metadata_ref, tcx)` to `decode` instead of just `crate_metadata_ref`."); + }; let cnum = CrateNum::decode(decoder); let index = u32::decode(decoder); @@ -520,7 +526,8 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span { let hi = lo + len; let Some(sess) = decoder.sess else { - bug!("Cannot decode Span without Session.") + bug!("Cannot decode Span without Session. \ + You need to explicitly pass `(crate_metadata_ref, tcx)` to `decode` instead of just `crate_metadata_ref`.") }; // Index of the file in the corresponding crate's list of encoded files. @@ -743,6 +750,10 @@ impl CrateRoot { } impl<'a, 'tcx> CrateMetadataRef<'a> { + fn missing(self, descr: &str, id: DefIndex) -> ! { + bug!("missing `{descr}` for {:?}", self.local_def_id(id)) + } + fn raw_proc_macro(self, id: DefIndex) -> &'a ProcMacro { // DefIndex's in root.proc_macro_data have a one-to-one correspondence // with items in 'raw_proc_macros'. @@ -776,8 +787,13 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { fn opt_item_ident(self, item_index: DefIndex, sess: &Session) -> Option<Ident> { let name = self.opt_item_name(item_index)?; - let span = - self.root.tables.def_ident_span.get(self, item_index).unwrap().decode((self, sess)); + let span = self + .root + .tables + .def_ident_span + .get(self, item_index) + .unwrap_or_else(|| self.missing("def_ident_span", item_index)) + .decode((self, sess)); Some(Ident::new(name, span)) } @@ -806,7 +822,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .tables .def_span .get(self, index) - .unwrap_or_else(|| panic!("Missing span for {index:?}")) + .unwrap_or_else(|| self.missing("def_span", index)) .decode((self, sess)) } @@ -841,7 +857,12 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { ) } - fn get_variant(self, kind: &DefKind, index: DefIndex, parent_did: DefId) -> ty::VariantDef { + fn get_variant( + self, + kind: DefKind, + index: DefIndex, + parent_did: DefId, + ) -> (VariantIdx, ty::VariantDef) { let adt_kind = match kind { DefKind::Variant => ty::AdtKind::Enum, DefKind::Struct => ty::AdtKind::Struct, @@ -855,27 +876,30 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { if adt_kind == ty::AdtKind::Enum { Some(self.local_def_id(index)) } else { None }; let ctor = data.ctor.map(|(kind, index)| (kind, self.local_def_id(index))); - ty::VariantDef::new( - self.item_name(index), - variant_did, - ctor, - data.discr, - self.root - .tables - .children - .get(self, index) - .expect("fields are not encoded for a variant") - .decode(self) - .map(|index| ty::FieldDef { - did: self.local_def_id(index), - name: self.item_name(index), - vis: self.get_visibility(index), - }) - .collect(), - adt_kind, - parent_did, - false, - data.is_non_exhaustive, + ( + data.idx, + ty::VariantDef::new( + self.item_name(index), + variant_did, + ctor, + data.discr, + self.root + .tables + .children + .get(self, index) + .expect("fields are not encoded for a variant") + .decode(self) + .map(|index| ty::FieldDef { + did: self.local_def_id(index), + name: self.item_name(index), + vis: self.get_visibility(index), + }) + .collect(), + adt_kind, + parent_did, + false, + data.is_non_exhaustive, + ), ) } @@ -891,7 +915,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { }; let repr = self.root.tables.repr_options.get(self, item_id).unwrap().decode(self); - let variants = if let ty::AdtKind::Enum = adt_kind { + let mut variants: Vec<_> = if let ty::AdtKind::Enum = adt_kind { self.root .tables .children @@ -902,27 +926,30 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { let kind = self.def_kind(index); match kind { DefKind::Ctor(..) => None, - _ => Some(self.get_variant(&kind, index, did)), + _ => Some(self.get_variant(kind, index, did)), } }) .collect() } else { - std::iter::once(self.get_variant(&kind, item_id, did)).collect() + std::iter::once(self.get_variant(kind, item_id, did)).collect() }; - tcx.mk_adt_def(did, adt_kind, variants, repr) - } + variants.sort_by_key(|(idx, _)| *idx); - fn get_generics(self, item_id: DefIndex, sess: &Session) -> ty::Generics { - self.root.tables.generics_of.get(self, item_id).unwrap().decode((self, sess)) + tcx.mk_adt_def( + did, + adt_kind, + variants.into_iter().map(|(_, variant)| variant).collect(), + repr, + ) } - fn get_visibility(self, id: DefIndex) -> ty::Visibility<DefId> { + fn get_visibility(self, id: DefIndex) -> Visibility<DefId> { self.root .tables .visibility .get(self, id) - .unwrap() + .unwrap_or_else(|| self.missing("visibility", id)) .decode(self) .map_id(|index| self.local_def_id(index)) } @@ -932,7 +959,12 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } fn get_expn_that_defined(self, id: DefIndex, sess: &Session) -> ExpnId { - self.root.tables.expn_that_defined.get(self, id).unwrap().decode((self, sess)) + self.root + .tables + .expn_that_defined + .get(self, id) + .unwrap_or_else(|| self.missing("expn_that_defined", id)) + .decode((self, sess)) } fn get_debugger_visualizers(self) -> Vec<rustc_span::DebuggerVisualizerFile> { @@ -979,17 +1011,11 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { fn get_mod_child(self, id: DefIndex, sess: &Session) -> ModChild { let ident = self.item_ident(id, sess); - let kind = self.def_kind(id); - let def_id = self.local_def_id(id); - let res = Res::Def(kind, def_id); + let res = Res::Def(self.def_kind(id), self.local_def_id(id)); let vis = self.get_visibility(id); let span = self.get_span(id, sess); - let macro_rules = match kind { - DefKind::Macro(..) => self.root.tables.is_macro_rules.get(self, id), - _ => false, - }; - ModChild { ident, res, vis, span, macro_rules } + ModChild { ident, res, vis, span, reexport_chain: Default::default() } } /// Iterates over all named children of the given module, @@ -1013,10 +1039,14 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } else { // Iterate over all children. for child_index in self.root.tables.children.get(self, id).unwrap().decode(self) { - yield self.get_mod_child(child_index, sess); + // FIXME: Do not encode RPITITs as a part of this list. + if self.root.tables.opt_rpitit_info.get(self, child_index).is_none() { + yield self.get_mod_child(child_index, sess); + } } - if let Some(reexports) = self.root.tables.module_reexports.get(self, id) { + let reexports = self.root.tables.module_children_reexports.get(self, id); + if !reexports.is_default() { for reexport in reexports.decode((self, sess)) { yield reexport; } @@ -1033,13 +1063,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { self.root.tables.optimized_mir.get(self, id).is_some() } - fn module_expansion(self, id: DefIndex, sess: &Session) -> ExpnId { - 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, sess: &'a Session) -> bool { self.root .tables @@ -1066,8 +1089,11 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } fn get_associated_item(self, id: DefIndex, sess: &'a Session) -> ty::AssocItem { - let name = self.item_name(id); - + let name = if self.root.tables.opt_rpitit_info.get(self, id).is_some() { + kw::Empty + } else { + self.item_name(id) + }; let (kind, has_self) = match self.def_kind(id) { DefKind::AssocConst => (ty::AssocKind::Const, false), DefKind::AssocFn => (ty::AssocKind::Fn, self.get_fn_has_self_parameter(id, sess)), @@ -1075,6 +1101,8 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { _ => bug!("cannot get associated-item of `{:?}`", self.def_key(id)), }; let container = self.root.tables.assoc_container.get(self, id).unwrap(); + let opt_rpitit_info = + self.root.tables.opt_rpitit_info.get(self, id).map(|d| d.decode(self)); ty::AssocItem { name, @@ -1083,6 +1111,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { trait_item_def_id: self.get_trait_item_def_id(id), container, fn_has_self_parameter: has_self, + opt_rpitit_info, } } @@ -1121,33 +1150,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .decode((self, sess)) } - fn get_struct_field_names( - self, - id: DefIndex, - sess: &'a Session, - ) -> impl Iterator<Item = Spanned<Symbol>> + 'a { - self.root - .tables - .children - .get(self, id) - .expect("fields not encoded for a struct") - .decode(self) - .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<DefId>> + 'a { - self.root - .tables - .children - .get(self, id) - .expect("fields not encoded for a struct") - .decode(self) - .map(move |field_index| self.get_visibility(field_index)) - } - fn get_inherent_implementations_for_type( self, tcx: TyCtxt<'tcx>, @@ -1612,7 +1614,7 @@ impl CrateMetadata { .collect(); let alloc_decoding_state = AllocDecodingState::new(root.interpret_alloc_index.decode(&blob).collect()); - let dependencies = Lock::new(cnum_map.iter().cloned().collect()); + let dependencies = cnum_map.iter().copied().collect(); // Pre-decode the DefPathHash->DefIndex table. This is a cheap operation // that does not copy any data. It just does some data verification. @@ -1652,12 +1654,12 @@ impl CrateMetadata { cdata } - pub(crate) fn dependencies(&self) -> LockGuard<'_, Vec<CrateNum>> { - self.dependencies.borrow() + pub(crate) fn dependencies(&self) -> impl Iterator<Item = CrateNum> + '_ { + self.dependencies.iter() } pub(crate) fn add_dependency(&self, cnum: CrateNum) { - self.dependencies.borrow_mut().push(cnum); + self.dependencies.push(cnum); } pub(crate) fn update_extern_crate(&self, new_extern_crate: ExternCrate) -> bool { @@ -1721,10 +1723,6 @@ impl CrateMetadata { self.root.name } - pub(crate) fn stable_crate_id(&self) -> StableCrateId { - self.root.stable_crate_id - } - pub(crate) fn hash(&self) -> Svh { self.root.hash } diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 83a0e833e..31798afb8 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -13,14 +13,15 @@ use rustc_middle::arena::ArenaAllocatable; use rustc_middle::metadata::ModChild; use rustc_middle::middle::exported_symbols::ExportedSymbol; use rustc_middle::middle::stability::DeprecationEntry; +use rustc_middle::query::LocalCrate; 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_middle::ty::{self, TyCtxt}; +use rustc_session::cstore::CrateStore; use rustc_session::{Session, StableCrateId}; use rustc_span::hygiene::{ExpnHash, ExpnId}; -use rustc_span::source_map::{Span, Spanned}; use rustc_span::symbol::{kw, Symbol}; +use rustc_span::Span; use rustc_data_structures::sync::Lrc; use std::any::Any; @@ -226,7 +227,7 @@ provide! { tcx, def_id, other, cdata, lookup_default_body_stability => { table } lookup_deprecation_entry => { table } params_in_repr => { table } - unused_generic_params => { table } + unused_generic_params => { cdata.root.tables.unused_generic_params.get(cdata, def_id.index) } opt_def_kind => { table_direct } impl_parent => { table } impl_polarity => { table_direct } @@ -252,9 +253,21 @@ provide! { tcx, def_id, other, cdata, .get(cdata, def_id.index) .map(|lazy| lazy.decode((cdata, tcx))) .process_decoded(tcx, || panic!("{def_id:?} does not have trait_impl_trait_tys"))) - } + } + implied_predicates_of => { + cdata + .root + .tables + .implied_predicates_of + .get(cdata, def_id.index) + .map(|lazy| lazy.decode((cdata, tcx))) + .unwrap_or_else(|| { + debug_assert_eq!(tcx.def_kind(def_id), DefKind::Trait); + tcx.super_predicates_of(def_id) + }) + } - associated_items_for_impl_trait_in_trait => { table_defaulted_array } + associated_types_for_impl_traits_in_associated_fn => { table_defaulted_array } visibility => { cdata.get_visibility(def_id.index) } adt_def => { cdata.get_adt_def(def_id.index, tcx) } @@ -367,10 +380,7 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) { *providers = Providers { allocator_kind: |tcx, ()| CStore::from_tcx(tcx).allocator_kind(), alloc_error_handler_kind: |tcx, ()| CStore::from_tcx(tcx).alloc_error_handler_kind(), - is_private_dep: |_tcx, cnum| { - assert_eq!(cnum, LOCAL_CRATE); - false - }, + is_private_dep: |_tcx, LocalCrate| false, native_library: |tcx, id| { tcx.native_libraries(id.krate) .iter() @@ -386,12 +396,8 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) { .contains(&id) }) }, - native_libraries: |tcx, cnum| { - assert_eq!(cnum, LOCAL_CRATE); - native_libs::collect(tcx) - }, - foreign_modules: |tcx, cnum| { - assert_eq!(cnum, LOCAL_CRATE); + native_libraries: |tcx, LocalCrate| native_libs::collect(tcx), + foreign_modules: |tcx, LocalCrate| { foreign_modules::collect(tcx).into_iter().map(|m| (m.def_id, m)).collect() }, @@ -489,47 +495,27 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) { }, dependency_formats: |tcx, ()| Lrc::new(crate::dependency_format::calculate(tcx)), - has_global_allocator: |tcx, cnum| { - assert_eq!(cnum, LOCAL_CRATE); - CStore::from_tcx(tcx).has_global_allocator() - }, - has_alloc_error_handler: |tcx, cnum| { - assert_eq!(cnum, LOCAL_CRATE); - CStore::from_tcx(tcx).has_alloc_error_handler() - }, + has_global_allocator: |tcx, LocalCrate| CStore::from_tcx(tcx).has_global_allocator(), + has_alloc_error_handler: |tcx, LocalCrate| CStore::from_tcx(tcx).has_alloc_error_handler(), postorder_cnums: |tcx, ()| { tcx.arena .alloc_slice(&CStore::from_tcx(tcx).crate_dependencies_in_postorder(LOCAL_CRATE)) }, - crates: |tcx, ()| tcx.arena.alloc_from_iter(CStore::from_tcx(tcx).crates_untracked()), + crates: |tcx, ()| { + // The list of loaded crates is now frozen in query cache, + // so make sure cstore is not mutably accessed from here on. + tcx.untracked().cstore.leak(); + tcx.arena.alloc_from_iter(CStore::from_tcx(tcx).iter_crate_data().map(|(cnum, _)| cnum)) + }, ..*providers }; } impl CStore { - pub fn struct_field_names_untracked<'a>( - &'a self, - def: DefId, - sess: &'a Session, - ) -> impl Iterator<Item = Spanned<Symbol>> + 'a { - self.get_crate_data(def.krate).get_struct_field_names(def.index, sess) - } - - pub fn struct_field_visibilities_untracked( - &self, - def: DefId, - ) -> impl Iterator<Item = Visibility<DefId>> + '_ { - self.get_crate_data(def.krate).get_struct_field_visibilities(def.index) - } - pub fn ctor_untracked(&self, def: DefId) -> Option<(CtorKind, DefId)> { self.get_crate_data(def.krate).get_ctor(def.index) } - pub fn visibility_untracked(&self, def: DefId) -> Visibility<DefId> { - self.get_crate_data(def.krate).get_visibility(def.index) - } - pub fn module_children_untracked<'a>( &'a self, def_id: DefId, @@ -566,32 +552,16 @@ impl CStore { ) } - 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> { - self.get_crate_data(cnum).source.clone() - } - - pub fn get_span_untracked(&self, def_id: DefId, sess: &Session) -> Span { + pub fn def_span_untracked(&self, def_id: DefId, sess: &Session) -> Span { self.get_crate_data(def_id.krate).get_span(def_id.index, sess) } - pub fn def_kind(&self, def: DefId) -> DefKind { + pub fn def_kind_untracked(&self, def: DefId) -> DefKind { self.get_crate_data(def.krate).def_kind(def.index) } - pub fn crates_untracked(&self) -> impl Iterator<Item = CrateNum> + '_ { - self.iter_crate_data().map(|(cnum, _)| cnum) - } - - pub fn item_generics_num_lifetimes(&self, def_id: DefId, sess: &Session) -> usize { - self.get_crate_data(def_id.krate).get_generics(def_id.index, sess).own_counts().lifetimes - } - - pub fn module_expansion_untracked(&self, def_id: DefId, sess: &Session) -> ExpnId { - self.get_crate_data(def_id.krate).module_expansion(def_id.index, sess) + pub fn expn_that_defined_untracked(&self, def_id: DefId, sess: &Session) -> ExpnId { + self.get_crate_data(def_id.krate).get_expn_that_defined(def_id.index, sess) } /// Only public-facing way to traverse all the definitions in a non-local crate. @@ -601,14 +571,6 @@ impl CStore { self.get_crate_data(cnum).num_def_ids() } - pub fn item_attrs_untracked<'a>( - &'a self, - def_id: DefId, - sess: &'a Session, - ) -> impl Iterator<Item = ast::Attribute> + 'a { - self.get_crate_data(def_id.krate).get_item_attrs(def_id.index, sess) - } - pub fn get_proc_macro_quoted_span_untracked( &self, cnum: CrateNum, @@ -636,7 +598,10 @@ impl CrateStore for CStore { } fn stable_crate_id_to_crate_num(&self, stable_crate_id: StableCrateId) -> CrateNum { - self.stable_crate_ids[&stable_crate_id] + *self + .stable_crate_ids + .get(&stable_crate_id) + .unwrap_or_else(|| bug!("uninterned StableCrateId: {stable_crate_id:?}")) } /// Returns the `DefKey` for a given `DefId`. This indicates the diff --git a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs index a6133f1b4..02cab561b 100644 --- a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs +++ b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs @@ -1,14 +1,14 @@ use crate::rmeta::DecodeContext; use crate::rmeta::EncodeContext; -use crate::rmeta::MetadataBlob; -use rustc_data_structures::owning_ref::OwningRef; +use rustc_data_structures::owned_slice::slice_owned; +use rustc_data_structures::owned_slice::OwnedSlice; use rustc_hir::def_path_hash_map::{Config as HashMapConfig, DefPathHashMap}; use rustc_middle::parameterized_over_tcx; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_span::def_id::{DefIndex, DefPathHash}; pub(crate) enum DefPathHashMapRef<'tcx> { - OwnedFromMetadata(odht::HashTable<HashMapConfig, OwningRef<MetadataBlob, [u8]>>), + OwnedFromMetadata(odht::HashTable<HashMapConfig, OwnedSlice>), BorrowedFromTcx(&'tcx DefPathHashMap), } @@ -50,11 +50,11 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for DefPathHashMapRef<'static> let len = d.read_usize(); let pos = d.position(); - let o = OwningRef::new(d.blob().clone()).map(|x| &x[pos..pos + len]); + let o = slice_owned(d.blob().clone(), |blob| &blob[pos..pos + len]); - // Although we already have the data we need via the OwningRef, we still need - // to advance the DecodeContext's position so it's in a valid state after - // the method. We use read_raw_bytes() for that. + // Although we already have the data we need via the `OwnedSlice`, we still need + // to advance the `DecodeContext`'s position so it's in a valid state after + // the method. We use `read_raw_bytes()` for that. let _ = d.read_raw_bytes(len); let inner = odht::HashTable::from_raw_bytes(o).unwrap_or_else(|e| { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 3ab01f780..e44b133a9 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -24,6 +24,7 @@ use rustc_middle::middle::exported_symbols::{ metadata_symbol_name, ExportedSymbol, SymbolExportInfo, }; use rustc_middle::mir::interpret; +use rustc_middle::query::LocalCrate; use rustc_middle::traits::specialization_graph; use rustc_middle::ty::codec::TyEncoder; use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams}; @@ -42,7 +43,6 @@ 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}; @@ -111,8 +111,6 @@ impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> { emit_i8(i8); emit_bool(bool); - emit_f64(f64); - emit_f32(f32); emit_char(char); emit_str(&str); emit_raw_bytes(&[u8]); @@ -457,7 +455,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } fn encode_info_for_items(&mut self) { - self.encode_info_for_mod(CRATE_DEF_ID, self.tcx.hir().root_module()); + self.encode_info_for_mod(CRATE_DEF_ID); // Proc-macro crates only export proc-macro items, which are looked // up using `proc_macro_data` @@ -609,10 +607,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { _ = stat!("mir", || self.encode_mir()); - _ = stat!("items", || { - self.encode_def_ids(); - self.encode_info_for_items(); - }); + _ = stat!("def-ids", || self.encode_def_ids()); + + _ = stat!("items", || self.encode_info_for_items()); let interpret_alloc_index = stat!("interpret-alloc-index", || { let mut interpret_alloc_index = Vec::new(); @@ -681,17 +678,15 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { has_global_allocator: tcx.has_global_allocator(LOCAL_CRATE), has_alloc_error_handler: tcx.has_alloc_error_handler(LOCAL_CRATE), has_panic_handler: tcx.has_panic_handler(LOCAL_CRATE), - has_default_lib_allocator: tcx - .sess - .contains_name(&attrs, sym::default_lib_allocator), + has_default_lib_allocator: attr::contains_name(&attrs, sym::default_lib_allocator), proc_macro_data, debugger_visualizers, - compiler_builtins: 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), + compiler_builtins: attr::contains_name(&attrs, sym::compiler_builtins), + needs_allocator: attr::contains_name(&attrs, sym::needs_allocator), + needs_panic_runtime: attr::contains_name(&attrs, sym::needs_panic_runtime), + no_builtins: attr::contains_name(&attrs, sym::no_builtins), + panic_runtime: attr::contains_name(&attrs, sym::panic_runtime), + profiler_runtime: attr::contains_name(&attrs, sym::profiler_runtime), symbol_mangling_version: tcx.sess.opts.get_symbol_mangling_version(), crate_deps, @@ -815,7 +810,7 @@ fn analyze_attr(attr: &Attribute, state: &mut AnalyzeAttrState) -> bool { should_encode } -fn should_encode_visibility(def_kind: DefKind) -> bool { +fn should_encode_span(def_kind: DefKind) -> bool { match def_kind { DefKind::Mod | DefKind::Struct @@ -827,25 +822,136 @@ fn should_encode_visibility(def_kind: DefKind) -> bool { | DefKind::ForeignTy | DefKind::TraitAlias | DefKind::AssocTy + | DefKind::TyParam + | DefKind::ConstParam + | DefKind::LifetimeParam | DefKind::Fn | DefKind::Const - | DefKind::Static(..) + | DefKind::Static(_) | DefKind::Ctor(..) | DefKind::AssocFn | DefKind::AssocConst - | DefKind::Macro(..) + | DefKind::Macro(_) + | DefKind::AnonConst + | DefKind::InlineConst + | DefKind::OpaqueTy + | DefKind::Field + | DefKind::Impl { .. } + | DefKind::Closure + | DefKind::Generator => true, + DefKind::ExternCrate | DefKind::Use | DefKind::ForeignMod + | DefKind::ImplTraitPlaceholder + | DefKind::GlobalAsm => false, + } +} + +fn should_encode_attrs(def_kind: DefKind) -> bool { + match def_kind { + DefKind::Mod + | DefKind::Struct + | DefKind::Union + | DefKind::Enum + | DefKind::Variant + | DefKind::Trait + | DefKind::TyAlias + | DefKind::ForeignTy + | DefKind::TraitAlias + | DefKind::AssocTy + | DefKind::Fn + | DefKind::Const + | DefKind::Static(_) + | DefKind::AssocFn + | DefKind::AssocConst + | DefKind::Macro(_) + | DefKind::Field + | DefKind::Impl { .. } => true, + DefKind::TyParam + | DefKind::ConstParam + | DefKind::Ctor(..) + | DefKind::ExternCrate + | DefKind::Use + | DefKind::ForeignMod + | DefKind::AnonConst + | DefKind::InlineConst | DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder - | DefKind::Impl { .. } + | DefKind::LifetimeParam + | DefKind::GlobalAsm + | DefKind::Closure + | DefKind::Generator => false, + } +} + +fn should_encode_expn_that_defined(def_kind: DefKind) -> bool { + match def_kind { + DefKind::Mod + | DefKind::Struct + | DefKind::Union + | DefKind::Enum + | DefKind::Variant + | DefKind::Trait + | DefKind::Impl { .. } => true, + DefKind::TyAlias + | DefKind::ForeignTy + | DefKind::TraitAlias + | DefKind::AssocTy + | DefKind::TyParam + | DefKind::Fn + | DefKind::Const + | DefKind::ConstParam + | DefKind::Static(_) + | DefKind::Ctor(..) + | DefKind::AssocFn + | DefKind::AssocConst + | DefKind::Macro(_) + | DefKind::ExternCrate + | DefKind::Use + | DefKind::ForeignMod + | DefKind::AnonConst + | DefKind::InlineConst + | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder + | DefKind::Field + | DefKind::LifetimeParam + | DefKind::GlobalAsm + | DefKind::Closure + | DefKind::Generator => false, + } +} + +fn should_encode_visibility(def_kind: DefKind) -> bool { + match def_kind { + DefKind::Mod + | DefKind::Struct + | DefKind::Union + | DefKind::Enum + | DefKind::Variant + | DefKind::Trait + | DefKind::TyAlias + | DefKind::ForeignTy + | DefKind::TraitAlias + | DefKind::AssocTy + | DefKind::Fn + | DefKind::Const + | DefKind::Static(..) + | DefKind::Ctor(..) + | DefKind::AssocFn + | DefKind::AssocConst + | DefKind::Macro(..) | DefKind::Field => true, - DefKind::TyParam + DefKind::Use + | DefKind::ForeignMod + | DefKind::TyParam | DefKind::ConstParam | DefKind::LifetimeParam | DefKind::AnonConst | DefKind::InlineConst + | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::GlobalAsm + | DefKind::Impl { .. } | DefKind::Closure | DefKind::Generator | DefKind::ExternCrate => false, @@ -1016,7 +1122,6 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) -> | DefKind::Const | DefKind::Static(..) | DefKind::TyAlias - | DefKind::OpaqueTy | DefKind::ForeignTy | DefKind::Impl { .. } | DefKind::AssocFn @@ -1027,8 +1132,20 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) -> | DefKind::AnonConst | DefKind::InlineConst => true, + DefKind::OpaqueTy => { + let opaque = tcx.hir().expect_item(def_id).expect_opaque_ty(); + if let hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id) = opaque.origin + && let hir::Node::TraitItem(trait_item) = tcx.hir().get_by_def_id(fn_def_id) + && let (_, hir::TraitFn::Required(..)) = trait_item.expect_fn() + { + false + } else { + true + } + } + DefKind::ImplTraitPlaceholder => { - let parent_def_id = tcx.impl_trait_in_trait_parent(def_id.to_def_id()); + let parent_def_id = tcx.impl_trait_in_trait_parent_fn(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 @@ -1044,7 +1161,13 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) -> 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(), + // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty) always encode RPITITs, + // since we need to be able to "project" from an RPITIT associated item + // to an opaque when installing the default projection predicates in + // default trait methods with RPITITs. + ty::AssocItemContainer::TraitContainer => { + assoc_item.defaultness(tcx).has_value() || assoc_item.opt_rpitit_info.is_some() + } } } DefKind::TyParam => { @@ -1104,7 +1227,7 @@ fn should_encode_const(def_kind: DefKind) -> bool { // We only encode impl trait in trait when using `lower-impl-trait-in-trait-to-assoc-ty` unstable // option. fn should_encode_fn_impl_trait_in_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool { - if tcx.sess.opts.unstable_opts.lower_impl_trait_in_trait_to_assoc_ty + if tcx.lower_impl_trait_in_trait_to_assoc_ty() && let Some(assoc_item) = tcx.opt_associated_item(def_id) && assoc_item.container == ty::AssocItemContainer::TraitContainer && assoc_item.kind == ty::AssocKind::Fn @@ -1147,11 +1270,17 @@ 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_some(def_id.index, def_kind); - 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) { + if should_encode_span(def_kind) { + let def_span = tcx.def_span(local_id); + record!(self.tables.def_span[def_id] <- def_span); + } + if should_encode_attrs(def_kind) { + self.encode_attrs(local_id); + } + if should_encode_expn_that_defined(def_kind) { + record!(self.tables.expn_that_defined[def_id] <- self.tcx.expn_that_defined(def_id)); + } + if should_encode_span(def_kind) && let Some(ident_span) = tcx.def_ident_span(def_id) { record!(self.tables.def_ident_span[def_id] <- ident_span); } if def_kind.has_codegen_attrs() { @@ -1186,11 +1315,15 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { 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 { + if let DefKind::Trait = def_kind { record!(self.tables.super_predicates_of[def_id] <- self.tcx.super_predicates_of(def_id)); } + if let DefKind::TraitAlias = def_kind { + record!(self.tables.super_predicates_of[def_id] <- self.tcx.super_predicates_of(def_id)); + record!(self.tables.implied_predicates_of[def_id] <- self.tcx.implied_predicates_of(def_id)); + } if let DefKind::Enum | DefKind::Struct | DefKind::Union = def_kind { - self.encode_info_for_adt(def_id); + self.encode_info_for_adt(local_id); } if tcx.impl_method_has_trait_impl_trait_tys(def_id) && let Ok(table) = self.tcx.collect_return_position_impl_trait_in_trait_tys(def_id) @@ -1198,8 +1331,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record!(self.tables.trait_impl_trait_tys[def_id] <- table); } if should_encode_fn_impl_trait_in_trait(tcx, def_id) { - let table = tcx.associated_items_for_impl_trait_in_trait(def_id); - record_defaulted_array!(self.tables.associated_items_for_impl_trait_in_trait[def_id] <- table); + let table = tcx.associated_types_for_impl_traits_in_associated_fn(def_id); + record_defaulted_array!(self.tables.associated_types_for_impl_traits_in_associated_fn[def_id] <- table); } } @@ -1223,7 +1356,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } #[instrument(level = "trace", skip(self))] - fn encode_info_for_adt(&mut self, def_id: DefId) { + fn encode_info_for_adt(&mut self, local_def_id: LocalDefId) { + let def_id = local_def_id.to_def_id(); let tcx = self.tcx; let adt_def = tcx.adt_def(def_id); record!(self.tables.repr_options[def_id] <- adt_def.repr()); @@ -1232,15 +1366,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record!(self.tables.params_in_repr[def_id] <- params_in_repr); if adt_def.is_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; - } - } - )); + let module_children = tcx.module_children_non_reexports(local_def_id); + record_array!(self.tables.children[def_id] <- + module_children.iter().map(|def_id| def_id.local_def_index)); } else { // For non-enum, there is only one variant, and its def_id is the adt's. debug_assert_eq!(adt_def.variants().len(), 1); @@ -1248,9 +1376,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // Therefore, the loop over variants will encode its fields as the adt's children. } - for variant in adt_def.variants().iter() { + for (idx, variant) in adt_def.variants().iter_enumerated() { let data = VariantData { discr: variant.discr, + idx, ctor: variant.ctor.map(|(kind, def_id)| (kind, def_id.index)), is_non_exhaustive: variant.is_field_list_non_exhaustive(), }; @@ -1272,7 +1401,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } } - fn encode_info_for_mod(&mut self, local_def_id: LocalDefId, md: &hir::Mod<'_>) { + fn encode_info_for_mod(&mut self, local_def_id: LocalDefId) { let tcx = self.tcx; let def_id = local_def_id.to_def_id(); debug!("EncodeContext::encode_info_for_mod({:?})", def_id); @@ -1286,38 +1415,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // 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)); } else { - record_array!(self.tables.children[def_id] <- iter::from_generator(|| { - for item_id in md.item_ids { - match tcx.hir().item(*item_id).kind { - // Foreign items are planted into their parent modules - // from name resolution point of view. - hir::ItemKind::ForeignMod { items, .. } => { - for foreign_item in items { - 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, - 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_def_id) = vdata.ctor_def_id() { - yield ctor_def_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, - } - } - })); + let non_reexports = tcx.module_children_non_reexports(local_def_id); + record_array!(self.tables.children[def_id] <- + non_reexports.iter().map(|def_id| def_id.local_def_index)); - if let Some(reexports) = tcx.module_reexports(local_def_id) { - assert!(!reexports.is_empty()); - record_array!(self.tables.module_reexports[def_id] <- reexports); - } + record_defaulted_array!(self.tables.module_children_reexports[def_id] <- + tcx.module_children_reexports(local_def_id)); } } @@ -1350,19 +1453,24 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if trait_item.kind == ty::AssocKind::Fn { record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id)); } + if let Some(rpitit_info) = trait_item.opt_rpitit_info { + let rpitit_info = self.lazy(rpitit_info); + self.tables.opt_rpitit_info.set_some(def_id.index, rpitit_info); + } } fn encode_info_for_impl_item(&mut self, def_id: DefId) { debug!("EncodeContext::encode_info_for_impl_item({:?})", def_id); let tcx = self.tcx; - let ast_item = self.tcx.hir().expect_impl_item(def_id.expect_local()); - self.tables.impl_defaultness.set_some(def_id.index, ast_item.defaultness); + let defaultness = self.tcx.impl_defaultness(def_id.expect_local()); + self.tables.impl_defaultness.set_some(def_id.index, defaultness); let impl_item = self.tcx.associated_item(def_id); self.tables.assoc_container.set_some(def_id.index, impl_item.container); match impl_item.kind { ty::AssocKind::Fn => { + let ast_item = self.tcx.hir().expect_impl_item(def_id.expect_local()); let hir::ImplItemKind::Fn(ref sig, body) = ast_item.kind else { bug!() }; self.tables.asyncness.set_some(def_id.index, sig.header.asyncness); record_array!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body)); @@ -1383,6 +1491,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id)); self.tables.is_intrinsic.set(def_id.index, tcx.is_intrinsic(def_id)); } + if let Some(rpitit_info) = impl_item.opt_rpitit_info { + let rpitit_info = self.lazy(rpitit_info); + self.tables.opt_rpitit_info.set_some(def_id.index, rpitit_info); + } } fn encode_mir(&mut self) { @@ -1431,9 +1543,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let instance = ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id.to_def_id())); let unused = tcx.unused_generic_params(instance); - if !unused.all_used() { - record!(self.tables.unused_generic_params[def_id.to_def_id()] <- unused); - } + self.tables.unused_generic_params.set(def_id.local_def_index, unused); } // Encode all the deduced parameter attributes for everything that has MIR, even for items @@ -1503,23 +1613,32 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { }) } - fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item<'tcx>) { + fn encode_info_for_item(&mut self, item: &'tcx hir::Item<'tcx>) { let tcx = self.tcx; - + let def_id = item.owner_id.to_def_id(); debug!("EncodeContext::encode_info_for_item({:?})", def_id); + let record_associated_item_def_ids = |this: &mut Self, def_ids: &[DefId]| { + record_array!(this.tables.children[def_id] <- def_ids.iter().map(|&def_id| { + assert!(def_id.is_local()); + def_id.index + })) + }; + match item.kind { hir::ItemKind::Fn(ref sig, .., body) => { self.tables.asyncness.set_some(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_some(def_id.index, sig.header.constness); + record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id)); + self.tables.is_intrinsic.set(def_id.index, tcx.is_intrinsic(def_id)); } hir::ItemKind::Macro(ref macro_def, _) => { self.tables.is_macro_rules.set(def_id.index, macro_def.macro_rules); record!(self.tables.macro_definition[def_id] <- &*macro_def.body); } - hir::ItemKind::Mod(ref m) => { - return self.encode_info_for_mod(item.owner_id.def_id, m); + hir::ItemKind::Mod(..) => { + self.encode_info_for_mod(item.owner_id.def_id); } hir::ItemKind::OpaqueTy(ref opaque) => { self.encode_explicit_item_bounds(def_id); @@ -1530,9 +1649,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { hir::ItemKind::Impl(hir::Impl { defaultness, constness, .. }) => { self.tables.impl_defaultness.set_some(def_id.index, *defaultness); self.tables.constness.set_some(def_id.index, *constness); + self.tables.impl_polarity.set_some(def_id.index, self.tcx.impl_polarity(def_id)); + + if let Some(trait_ref) = self.tcx.impl_trait_ref(def_id) { + record!(self.tables.impl_trait_ref[def_id] <- trait_ref); - let trait_ref = self.tcx.impl_trait_ref(def_id); - if let Some(trait_ref) = trait_ref { let trait_ref = trait_ref.skip_binder(); let trait_def = self.tcx.trait_def(trait_ref.def_id); if let Ok(mut an) = trait_def.ancestors(self.tcx, def_id) { @@ -1550,21 +1671,27 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } } - let polarity = self.tcx.impl_polarity(def_id); - self.tables.impl_polarity.set_some(def_id.index, polarity); + let associated_item_def_ids = self.tcx.associated_item_def_ids(def_id); + record_associated_item_def_ids(self, associated_item_def_ids); + for &trait_item_def_id in associated_item_def_ids { + self.encode_info_for_impl_item(trait_item_def_id); + } } hir::ItemKind::Trait(..) => { - let trait_def = self.tcx.trait_def(def_id); - record!(self.tables.trait_def[def_id] <- trait_def); + record!(self.tables.trait_def[def_id] <- self.tcx.trait_def(def_id)); + + let associated_item_def_ids = self.tcx.associated_item_def_ids(def_id); + record_associated_item_def_ids(self, associated_item_def_ids); + for &item_def_id in associated_item_def_ids { + self.encode_info_for_trait_item(item_def_id); + } } hir::ItemKind::TraitAlias(..) => { - let trait_def = self.tcx.trait_def(def_id); - record!(self.tables.trait_def[def_id] <- trait_def); + record!(self.tables.trait_def[def_id] <- self.tcx.trait_def(def_id)); } - hir::ItemKind::ExternCrate(_) | hir::ItemKind::Use(..) => { - bug!("cannot encode info for item {:?}", item) - } - hir::ItemKind::Static(..) + hir::ItemKind::ExternCrate(_) + | hir::ItemKind::Use(..) + | hir::ItemKind::Static(..) | hir::ItemKind::Const(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Struct(..) @@ -1572,49 +1699,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { | hir::ItemKind::ForeignMod { .. } | hir::ItemKind::GlobalAsm(..) | hir::ItemKind::TyAlias(..) => {} - }; - // FIXME(eddyb) there should be a nicer way to do this. - match item.kind { - hir::ItemKind::Impl { .. } | hir::ItemKind::Trait(..) => { - let associated_item_def_ids = self.tcx.associated_item_def_ids(def_id); - record_array!(self.tables.children[def_id] <- - associated_item_def_ids.iter().map(|&def_id| { - assert!(def_id.is_local()); - def_id.index - }) - ); - } - _ => {} - } - if let hir::ItemKind::Fn(..) = item.kind { - record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id)); - self.tables.is_intrinsic.set(def_id.index, tcx.is_intrinsic(def_id)); - } - if let hir::ItemKind::Impl { .. } = item.kind { - if let Some(trait_ref) = self.tcx.impl_trait_ref(def_id) { - 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::Impl { .. } => { - for &trait_item_def_id in - 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.owner_id.to_def_id()).iter() - { - self.encode_info_for_trait_item(item_def_id); - } - } - _ => {} } } @@ -1690,8 +1774,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let stability = tcx.lookup_stability(CRATE_DEF_ID); let macros = self.lazy_array(tcx.resolutions(()).proc_macros.iter().map(|p| p.local_def_index)); - let spans = self.tcx.sess.parse_sess.proc_macro_quoted_spans(); - for (i, span) in spans.into_iter().enumerate() { + for (i, span) in self.tcx.sess.parse_sess.proc_macro_quoted_spans() { let span = self.lazy(span); self.tables.proc_macro_quoted_spans.set_some(i, span); } @@ -1723,11 +1806,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // Proc-macros may have attributes like `#[allow_internal_unstable]`, // so downstream crates need access to them. let attrs = hir.attrs(proc_macro); - let macro_kind = if tcx.sess.contains_name(attrs, sym::proc_macro) { + let macro_kind = if attr::contains_name(attrs, sym::proc_macro) { MacroKind::Bang - } else if tcx.sess.contains_name(attrs, sym::proc_macro_attribute) { + } else if attr::contains_name(attrs, sym::proc_macro_attribute) { MacroKind::Attr - } else if let Some(attr) = tcx.sess.find_by_name(attrs, sym::proc_macro_derive) { + } else if let Some(attr) = attr::find_by_name(attrs, sym::proc_macro_derive) { // This unwrap chain should have been checked by the proc-macro harness. name = attr.meta_item_list().unwrap()[0] .meta_item() @@ -1858,7 +1941,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let simplified_self_ty = fast_reject::simplify_type( self.tcx, trait_ref.self_ty(), - TreatParams::AsInfer, + TreatParams::AsCandidateKey, ); fx_hash_map @@ -2001,10 +2084,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EncodeContext<'a, 'tcx> { } 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.owner_id.to_def_id(), item), - } + self.encode_info_for_item(item); } fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem<'tcx>) { intravisit::walk_foreign_item(self, ni); @@ -2050,13 +2130,13 @@ fn prefetch_mir(tcx: TyCtxt<'_>) { let (encode_const, encode_opt) = should_encode_mir(tcx, def_id); if encode_const { - tcx.ensure().mir_for_ctfe(def_id); + tcx.ensure_with_value().mir_for_ctfe(def_id); } if encode_opt { - tcx.ensure().optimized_mir(def_id); + tcx.ensure_with_value().optimized_mir(def_id); } if encode_opt || encode_const { - tcx.ensure().promoted_mir(def_id); + tcx.ensure_with_value().promoted_mir(def_id); } }) } @@ -2224,18 +2304,16 @@ pub fn provide(providers: &mut Providers) { doc_link_resolutions: |tcx, def_id| { tcx.resolutions(()) .doc_link_resolutions - .get(&def_id.expect_local()) + .get(&def_id) .expect("no resolutions for a doc link") }, doc_link_traits_in_scope: |tcx, def_id| { tcx.resolutions(()) .doc_link_traits_in_scope - .get(&def_id.expect_local()) + .get(&def_id) .expect("no traits in scope for a doc link") }, - traits_in_crate: |tcx, cnum| { - assert_eq!(cnum, LOCAL_CRATE); - + traits_in_crate: |tcx, LocalCrate| { let mut traits = Vec::new(); for id in tcx.hir().items() { if matches!(tcx.def_kind(id.owner_id), DefKind::Trait | DefKind::TraitAlias) { @@ -2247,9 +2325,7 @@ pub fn provide(providers: &mut Providers) { traits.sort_by_cached_key(|&def_id| tcx.def_path_hash(def_id)); tcx.arena.alloc_slice(&traits) }, - trait_impls_in_crate: |tcx, cnum| { - assert_eq!(cnum, LOCAL_CRATE); - + trait_impls_in_crate: |tcx, LocalCrate| { let mut trait_impls = Vec::new(); for id in tcx.hir().items() { if matches!(tcx.def_kind(id.owner_id), DefKind::Impl { .. }) diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index a7ec2d790..67710054c 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -31,6 +31,7 @@ use rustc_span::edition::Edition; use rustc_span::hygiene::{ExpnIndex, MacroKind}; use rustc_span::symbol::{Ident, Symbol}; use rustc_span::{self, ExpnData, ExpnHash, ExpnId, Span}; +use rustc_target::abi::VariantIdx; use rustc_target::spec::{PanicStrategy, TargetTriple}; use std::marker::PhantomData; @@ -55,13 +56,13 @@ pub(crate) fn rustc_version() -> String { /// Metadata encoding version. /// N.B., increment this if you change the format of metadata such that /// the rustc version can't be found to compare with `rustc_version()`. -const METADATA_VERSION: u8 = 6; +const METADATA_VERSION: u8 = 7; /// Metadata header which includes `METADATA_VERSION`. /// -/// This header is followed by the position of the `CrateRoot`, -/// which is encoded as a 32-bit big-endian unsigned integer, -/// and further followed by the rustc version string. +/// This header is followed by the length of the compressed data, then +/// the position of the `CrateRoot`, which is encoded as a 32-bit big-endian +/// unsigned integer, and further followed by the rustc version string. pub const METADATA_HEADER: &[u8] = &[b'r', b'u', b's', b't', 0, 0, 0, METADATA_VERSION]; /// A value of type T referred to by its absolute position @@ -354,7 +355,10 @@ define_tables! { explicit_item_bounds: Table<DefIndex, LazyArray<(ty::Predicate<'static>, Span)>>, inferred_outlives_of: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>, inherent_impls: Table<DefIndex, LazyArray<DefIndex>>, - associated_items_for_impl_trait_in_trait: Table<DefIndex, LazyArray<DefId>>, + associated_types_for_impl_traits_in_associated_fn: Table<DefIndex, LazyArray<DefId>>, + opt_rpitit_info: Table<DefIndex, Option<LazyValue<ty::ImplTraitInTraitData>>>, + unused_generic_params: Table<DefIndex, UnusedGenericParams>, + module_children_reexports: Table<DefIndex, LazyArray<ModChild>>, - optional: attributes: Table<DefIndex, LazyArray<ast::Attribute>>, @@ -370,6 +374,9 @@ define_tables! { explicit_predicates_of: Table<DefIndex, LazyValue<ty::GenericPredicates<'static>>>, generics_of: Table<DefIndex, LazyValue<ty::Generics>>, super_predicates_of: Table<DefIndex, LazyValue<ty::GenericPredicates<'static>>>, + // As an optimization, we only store this for trait aliases, + // since it's identical to super_predicates_of for traits. + implied_predicates_of: Table<DefIndex, LazyValue<ty::GenericPredicates<'static>>>, type_of: Table<DefIndex, LazyValue<ty::EarlyBinder<Ty<'static>>>>, variances_of: Table<DefIndex, LazyArray<ty::Variance>>, fn_sig: Table<DefIndex, LazyValue<ty::EarlyBinder<ty::PolyFnSig<'static>>>>, @@ -381,7 +388,6 @@ define_tables! { mir_for_ctfe: Table<DefIndex, LazyValue<mir::Body<'static>>>, mir_generator_witnesses: Table<DefIndex, LazyValue<mir::GeneratorLayout<'static>>>, promoted_mir: Table<DefIndex, LazyValue<IndexVec<mir::Promoted, mir::Body<'static>>>>, - // FIXME(compiler-errors): Why isn't this a LazyArray? thir_abstract_const: Table<DefIndex, LazyValue<ty::Const<'static>>>, impl_parent: Table<DefIndex, RawDefId>, impl_polarity: Table<DefIndex, ty::ImplPolarity>, @@ -397,7 +403,6 @@ define_tables! { trait_def: Table<DefIndex, LazyValue<ty::TraitDef>>, trait_item_def_id: Table<DefIndex, RawDefId>, expn_that_defined: Table<DefIndex, LazyValue<ExpnId>>, - unused_generic_params: Table<DefIndex, LazyValue<UnusedGenericParams>>, 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 @@ -411,7 +416,6 @@ define_tables! { assoc_container: Table<DefIndex, ty::AssocItemContainer>, macro_definition: Table<DefIndex, LazyValue<ast::DelimArgs>>, 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>>>>, doc_link_resolutions: Table<DefIndex, LazyValue<DocLinkResMap>>, @@ -420,6 +424,7 @@ define_tables! { #[derive(TyEncodable, TyDecodable)] struct VariantData { + idx: VariantIdx, discr: ty::VariantDiscr, /// If this is unit or tuple-variant/struct, then this is the index of the ctor id. ctor: Option<(CtorKind, DefIndex)>, diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index b89d48ec1..364fa74ab 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -3,7 +3,7 @@ use crate::rmeta::*; use rustc_data_structures::fingerprint::Fingerprint; use rustc_hir::def::{CtorKind, CtorOf}; use rustc_index::vec::Idx; -use rustc_middle::ty::ParameterizedOverTcx; +use rustc_middle::ty::{ParameterizedOverTcx, UnusedGenericParams}; use rustc_serialize::opaque::FileEncoder; use rustc_serialize::Encoder as _; use rustc_span::hygiene::MacroKind; @@ -50,6 +50,16 @@ impl IsDefault for DefPathHash { } } +impl IsDefault for UnusedGenericParams { + fn is_default(&self) -> bool { + // UnusedGenericParams encodes the *un*usedness as a bitset. + // This means that 0 corresponds to all bits used, which is indeed the default. + let is_default = self.bits() == 0; + debug_assert_eq!(is_default, self.all_used()); + is_default + } +} + /// Helper trait, for encoding to, and decoding from, a fixed number of bytes. /// Used mainly for Lazy positions and lengths. /// Unchecked invariant: `Self::default()` should encode as `[0; BYTE_LEN]`, @@ -271,6 +281,21 @@ impl FixedSizeEncoding for bool { } } +impl FixedSizeEncoding for UnusedGenericParams { + type ByteArray = [u8; 4]; + + #[inline] + fn from_bytes(b: &[u8; 4]) -> Self { + let x: u32 = u32::from_bytes(b); + UnusedGenericParams::from_bits(x) + } + + #[inline] + fn write_to_bytes(self, b: &mut [u8; 4]) { + self.bits().write_to_bytes(b); + } +} + // NOTE(eddyb) there could be an impl for `usize`, which would enable a more // generic `LazyValue<T>` impl, but in the general case we might not need / want // to fit every `usize` in `u32`. |