diff options
Diffstat (limited to 'compiler/rustc_metadata/src')
| -rw-r--r-- | compiler/rustc_metadata/src/creader.rs | 221 | ||||
| -rw-r--r-- | compiler/rustc_metadata/src/dynamic_lib.rs | 194 | ||||
| -rw-r--r-- | compiler/rustc_metadata/src/dynamic_lib/tests.rs | 18 | ||||
| -rw-r--r-- | compiler/rustc_metadata/src/foreign_modules.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_metadata/src/lib.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_metadata/src/locator.rs | 117 | ||||
| -rw-r--r-- | compiler/rustc_metadata/src/native_libs.rs | 15 | ||||
| -rw-r--r-- | compiler/rustc_metadata/src/rmeta/decoder.rs | 661 | ||||
| -rw-r--r-- | compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs | 143 | ||||
| -rw-r--r-- | compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs | 12 | ||||
| -rw-r--r-- | compiler/rustc_metadata/src/rmeta/encoder.rs | 200 | ||||
| -rw-r--r-- | compiler/rustc_metadata/src/rmeta/mod.rs | 38 | ||||
| -rw-r--r-- | compiler/rustc_metadata/src/rmeta/table.rs | 4 | 
13 files changed, 735 insertions, 892 deletions
| diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 95b74fd5306..36a1798cd6a 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -1,6 +1,5 @@ //! Validates all used crates and extern libraries and loads their metadata -use crate::dynamic_lib::DynamicLibrary; use crate::locator::{CrateError, CrateLocator, CratePaths}; use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob}; @@ -29,6 +28,7 @@ use rustc_target::spec::{PanicStrategy, TargetTriple}; use proc_macro::bridge::client::ProcMacro; use std::collections::BTreeMap; +use std::ops::Fn; use std::path::Path; use std::{cmp, env}; use tracing::{debug, info}; @@ -102,30 +102,23 @@ struct CrateDump<'a>(&'a CStore); impl<'a> std::fmt::Debug for CrateDump<'a> { fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { writeln!(fmt, "resolved crates:")?; - // `iter_crate_data` does not allow returning values. Thus we use a mutable variable here - // that aggregates the value (and any errors that could happen). - let mut res = Ok(()); - self.0.iter_crate_data(|cnum, data| { - res = res.and( - try { - writeln!(fmt, " name: {}", data.name())?; - writeln!(fmt, " cnum: {}", cnum)?; - writeln!(fmt, " hash: {}", data.hash())?; - writeln!(fmt, " reqd: {:?}", data.dep_kind())?; - let CrateSource { dylib, rlib, rmeta } = data.source(); - if let Some(dylib) = dylib { - writeln!(fmt, " dylib: {}", dylib.0.display())?; - } - if let Some(rlib) = rlib { - writeln!(fmt, " rlib: {}", rlib.0.display())?; - } - if let Some(rmeta) = rmeta { - writeln!(fmt, " rmeta: {}", rmeta.0.display())?; - } - }, - ); - }); - res + for (cnum, data) in self.0.iter_crate_data() { + writeln!(fmt, " name: {}", data.name())?; + writeln!(fmt, " cnum: {}", cnum)?; + writeln!(fmt, " hash: {}", data.hash())?; + writeln!(fmt, " reqd: {:?}", data.dep_kind())?; + let CrateSource { dylib, rlib, rmeta } = data.source(); + if let Some(dylib) = dylib { + writeln!(fmt, " dylib: {}", dylib.0.display())?; + } + if let Some(rlib) = rlib { + writeln!(fmt, " rlib: {}", rlib.0.display())?; + } + if let Some(rmeta) = rmeta { + writeln!(fmt, " rmeta: {}", rmeta.0.display())?; + } + } + Ok(()) } } @@ -154,12 +147,10 @@ impl CStore { self.metas[cnum] = Some(Lrc::new(data)); } - crate fn iter_crate_data(&self, mut f: impl FnMut(CrateNum, &CrateMetadata)) { - for (cnum, data) in self.metas.iter_enumerated() { - if let Some(data) = data { - f(cnum, data); - } - } + crate fn iter_crate_data(&self) -> impl Iterator<Item = (CrateNum, &CrateMetadata)> { + self.metas + .iter_enumerated() + .filter_map(|(cnum, data)| data.as_ref().map(|data| (cnum, &**data))) } fn push_dependencies_in_postorder(&self, deps: &mut Vec<CrateNum>, cnum: CrateNum) { @@ -178,7 +169,9 @@ impl CStore { crate fn crate_dependencies_in_postorder(&self, cnum: CrateNum) -> Vec<CrateNum> { let mut deps = Vec::new(); if cnum == LOCAL_CRATE { - self.iter_crate_data(|cnum, _| self.push_dependencies_in_postorder(&mut deps, cnum)); + for (cnum, _) in self.iter_crate_data() { + self.push_dependencies_in_postorder(&mut deps, cnum); + } } else { self.push_dependencies_in_postorder(&mut deps, cnum); } @@ -263,21 +256,17 @@ impl<'a> CrateLoader<'a> { } fn existing_match(&self, name: Symbol, hash: Option<Svh>, kind: PathKind) -> Option<CrateNum> { - let mut ret = None; - self.cstore.iter_crate_data(|cnum, data| { + for (cnum, data) in self.cstore.iter_crate_data() { if data.name() != name { tracing::trace!("{} did not match {}", data.name(), name); - return; + continue; } match hash { - Some(hash) if hash == data.hash() => { - ret = Some(cnum); - return; - } + Some(hash) if hash == data.hash() => return Some(cnum), Some(hash) => { debug!("actual hash {} did not match expected {}", hash, data.hash()); - return; + continue; } None => {} } @@ -292,7 +281,7 @@ impl<'a> CrateLoader<'a> { // `source` stores paths which are normalized which may be different // from the strings on the command line. let source = self.cstore.get_crate_data(cnum).cdata.source(); - if let Some(entry) = self.sess.opts.externs.get(&name.as_str()) { + if let Some(entry) = self.sess.opts.externs.get(name.as_str()) { // Only use `--extern crate_name=path` here, not `--extern crate_name`. if let Some(mut files) = entry.files() { if files.any(|l| { @@ -301,10 +290,10 @@ impl<'a> CrateLoader<'a> { || source.rlib.as_ref().map(|(p, _)| p) == Some(l) || source.rmeta.as_ref().map(|(p, _)| p) == Some(l) }) { - ret = Some(cnum); + return Some(cnum); } } - return; + continue; } // Alright, so we've gotten this far which means that `data` has the @@ -321,15 +310,16 @@ impl<'a> CrateLoader<'a> { .expect("No sources for crate") .1; if kind.matches(prev_kind) { - ret = Some(cnum); + return Some(cnum); } else { debug!( "failed to load existing crate {}; kind {:?} did not match prev_kind {:?}", name, kind, prev_kind ); } - }); - ret + } + + None } fn verify_no_symbol_conflicts(&self, root: &CrateRoot<'_>) -> Result<(), CrateError> { @@ -339,17 +329,14 @@ impl<'a> CrateLoader<'a> { } // Check for conflicts with any crate loaded so far - let mut res = Ok(()); - self.cstore.iter_crate_data(|_, other| { - if other.stable_crate_id() == root.stable_crate_id() && // same stable crate id - other.hash() != root.hash() - { - // but different SVH - res = Err(CrateError::SymbolConflictsOthers(root.name())); + 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() { + return Err(CrateError::SymbolConflictsOthers(root.name())); } - }); + } - res + Ok(()) } fn verify_no_stable_crate_id_hash_conflicts( @@ -381,7 +368,7 @@ impl<'a> CrateLoader<'a> { let host_hash = host_lib.as_ref().map(|lib| lib.metadata.get_root().hash()); let private_dep = - self.sess.opts.externs.get(&name.as_str()).map_or(false, |e| e.is_private_dep); + 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(); @@ -511,13 +498,17 @@ impl<'a> CrateLoader<'a> { name: Symbol, span: Span, dep_kind: CrateDepKind, - ) -> CrateNum { + ) -> Option<CrateNum> { self.used_extern_options.insert(name); - self.maybe_resolve_crate(name, dep_kind, None).unwrap_or_else(|err| { - let missing_core = - self.maybe_resolve_crate(sym::core, CrateDepKind::Explicit, None).is_err(); - err.report(&self.sess, span, missing_core) - }) + match self.maybe_resolve_crate(name, dep_kind, None) { + Ok(cnum) => Some(cnum), + Err(err) => { + let missing_core = + self.maybe_resolve_crate(sym::core, CrateDepKind::Explicit, None).is_err(); + err.report(&self.sess, span, missing_core); + None + } + } } fn maybe_resolve_crate<'b>( @@ -603,13 +594,14 @@ impl<'a> CrateLoader<'a> { locator.triple == self.sess.opts.target_triple || locator.is_proc_macro; Ok(Some(if can_reuse_cratenum { let mut result = LoadResult::Loaded(library); - self.cstore.iter_crate_data(|cnum, data| { + for (cnum, data) in self.cstore.iter_crate_data() { if data.name() == root.name() && root.hash() == data.hash() { assert!(locator.hash.is_none()); info!("load success, going to previous cnum: {}", cnum); result = LoadResult::Previous(cnum); + break; } - }); + } result } else { LoadResult::Loaded(library) @@ -671,25 +663,19 @@ impl<'a> CrateLoader<'a> { ) -> Result<&'static [ProcMacro], CrateError> { // Make sure the path contains a / or the linker will search for it. let path = env::current_dir().unwrap().join(path); - let lib = match DynamicLibrary::open(&path) { - Ok(lib) => lib, - Err(s) => return Err(CrateError::DlOpen(s)), - }; + let lib = unsafe { libloading::Library::new(path) } + .map_err(|err| CrateError::DlOpen(err.to_string()))?; - let sym = self.sess.generate_proc_macro_decls_symbol(stable_crate_id); - let decls = unsafe { - let sym = match lib.symbol(&sym) { - Ok(f) => f, - Err(s) => return Err(CrateError::DlSym(s)), - }; - *(sym as *const &[ProcMacro]) - }; + let sym_name = self.sess.generate_proc_macro_decls_symbol(stable_crate_id); + let sym = unsafe { lib.get::<*const &[ProcMacro]>(sym_name.as_bytes()) } + .map_err(|err| CrateError::DlSym(err.to_string()))?; // Intentionally leak the dynamic library. We can't ever unload it // since the library can make things that will live arbitrarily long. + let sym = unsafe { sym.into_raw() }; std::mem::forget(lib); - Ok(decls) + Ok(unsafe { **sym }) } fn inject_panic_runtime(&mut self, krate: &ast::Crate) { @@ -713,7 +699,7 @@ impl<'a> CrateLoader<'a> { let mut needs_panic_runtime = self.sess.contains_name(&krate.attrs, sym::needs_panic_runtime); - self.cstore.iter_crate_data(|cnum, data| { + for (cnum, data) in self.cstore.iter_crate_data() { needs_panic_runtime = needs_panic_runtime || data.needs_panic_runtime(); if data.is_panic_runtime() { // Inject a dependency from all #![needs_panic_runtime] to this @@ -723,7 +709,7 @@ impl<'a> CrateLoader<'a> { }); runtime_found = runtime_found || data.dep_kind() == CrateDepKind::Explicit; } - }); + } // If an explicitly linked and matching panic runtime was found, or if // we just don't need one at all, then we're done here and there's @@ -750,7 +736,7 @@ impl<'a> CrateLoader<'a> { }; info!("panic runtime not found -- loading {}", name); - let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit); + let Some(cnum) = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit) else { return; }; let data = self.cstore.get_crate_data(cnum); // Sanity check the loaded crate to ensure it is indeed a panic runtime @@ -790,7 +776,7 @@ impl<'a> CrateLoader<'a> { ); } - let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit); + let Some(cnum) = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit) else { return; }; let data = self.cstore.get_crate_data(cnum); // Sanity check the loaded crate to ensure it is indeed a profiler runtime @@ -815,11 +801,9 @@ impl<'a> CrateLoader<'a> { // 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. - let mut needs_allocator = self.sess.contains_name(&krate.attrs, sym::needs_allocator); - self.cstore.iter_crate_data(|_, data| { - needs_allocator = needs_allocator || data.needs_allocator(); - }); - if !needs_allocator { + if !self.sess.contains_name(&krate.attrs, sym::needs_allocator) + && !self.cstore.iter_crate_data().any(|(_, data)| data.needs_allocator()) + { return; } @@ -840,23 +824,19 @@ impl<'a> CrateLoader<'a> { // global allocator. let mut global_allocator = self.cstore.has_global_allocator.then(|| Symbol::intern("this crate")); - self.cstore.iter_crate_data(|_, data| { - if !data.has_global_allocator() { - return; - } - match global_allocator { - Some(other_crate) => { - self.sess.err(&format!( - "the `#[global_allocator]` in {} \ - conflicts with global \ - allocator in: {}", + for (_, data) in self.cstore.iter_crate_data() { + if data.has_global_allocator() { + match global_allocator { + Some(other_crate) => self.sess.err(&format!( + "the `#[global_allocator]` in {} conflicts with global allocator in: {}", other_crate, data.name() - )); + )), + None => global_allocator = Some(data.name()), } - None => global_allocator = Some(data.name()), } - }); + } + if global_allocator.is_some() { self.cstore.allocator_kind = Some(AllocatorKind::Global); return; @@ -866,19 +846,12 @@ impl<'a> CrateLoader<'a> { // allocator. At this point our allocator request is typically fulfilled // by the standard library, denoted by the `#![default_lib_allocator]` // attribute. - let mut has_default = self.sess.contains_name(&krate.attrs, sym::default_lib_allocator); - self.cstore.iter_crate_data(|_, data| { - if data.has_default_lib_allocator() { - has_default = true; - } - }); - - if !has_default { + if !self.sess.contains_name(&krate.attrs, sym::default_lib_allocator) + && !self.cstore.iter_crate_data().any(|(_, data)| data.has_default_lib_allocator()) + { self.sess.err( - "no global memory allocator found but one is \ - required; link to std or \ - add `#[global_allocator]` to a static item \ - that implements the GlobalAlloc trait", + "no global memory allocator found but one is required; link to std or add \ + `#[global_allocator]` to a static item that implements the GlobalAlloc trait", ); } self.cstore.allocator_kind = Some(AllocatorKind::Default); @@ -918,14 +891,12 @@ impl<'a> CrateLoader<'a> { // crate provided for this compile, but in order for this compilation to // be successfully linked we need to inject a dependency (to order the // crates on the command line correctly). - self.cstore.iter_crate_data(|cnum, data| { - if !needs_dep(data) { - return; + for (cnum, data) in self.cstore.iter_crate_data() { + if needs_dep(data) { + info!("injecting a dep from {} to {}", cnum, krate); + data.add_dependency(krate); } - - info!("injecting a dep from {} to {}", cnum, krate); - data.add_dependency(krate); - }); + } } fn report_unused_deps(&mut self, krate: &ast::Crate) { @@ -990,7 +961,7 @@ impl<'a> CrateLoader<'a> { item: &ast::Item, definitions: &Definitions, def_id: LocalDefId, - ) -> CrateNum { + ) -> Option<CrateNum> { match item.kind { ast::ItemKind::ExternCrate(orig_name) => { debug!( @@ -999,7 +970,7 @@ impl<'a> CrateLoader<'a> { ); let name = match orig_name { Some(orig_name) => { - validate_crate_name(self.sess, &orig_name.as_str(), Some(item.span)); + validate_crate_name(self.sess, orig_name.as_str(), Some(item.span)); orig_name } None => item.ident.name, @@ -1010,7 +981,7 @@ impl<'a> CrateLoader<'a> { CrateDepKind::Explicit }; - let cnum = self.resolve_crate(name, item.span, dep_kind); + let cnum = self.resolve_crate(name, item.span, dep_kind)?; let path_len = definitions.def_path(def_id).data.len(); self.update_extern_crate( @@ -1022,14 +993,14 @@ impl<'a> CrateLoader<'a> { dependency_of: LOCAL_CRATE, }, ); - cnum + Some(cnum) } _ => bug!(), } } - pub fn process_path_extern(&mut self, name: Symbol, span: Span) -> CrateNum { - let cnum = self.resolve_crate(name, span, CrateDepKind::Explicit); + pub fn process_path_extern(&mut self, name: Symbol, span: Span) -> Option<CrateNum> { + let cnum = self.resolve_crate(name, span, CrateDepKind::Explicit)?; self.update_extern_crate( cnum, @@ -1042,7 +1013,7 @@ impl<'a> CrateLoader<'a> { }, ); - cnum + Some(cnum) } pub fn maybe_process_path_extern(&mut self, name: Symbol) -> Option<CrateNum> { diff --git a/compiler/rustc_metadata/src/dynamic_lib.rs b/compiler/rustc_metadata/src/dynamic_lib.rs deleted file mode 100644 index e8929cd5c02..00000000000 --- a/compiler/rustc_metadata/src/dynamic_lib.rs +++ /dev/null @@ -1,194 +0,0 @@ -//! Dynamic library facilities. -//! -//! A simple wrapper over the platform's dynamic library facilities - -use std::ffi::CString; -use std::path::Path; - -pub struct DynamicLibrary { - handle: *mut u8, -} - -impl Drop for DynamicLibrary { - fn drop(&mut self) { - unsafe { dl::close(self.handle) } - } -} - -impl DynamicLibrary { - /// Lazily open a dynamic library. - pub fn open(filename: &Path) -> Result<DynamicLibrary, String> { - let maybe_library = dl::open(filename.as_os_str()); - - // The dynamic library must not be constructed if there is - // an error opening the library so the destructor does not - // run. - match maybe_library { - Err(err) => Err(err), - Ok(handle) => Ok(DynamicLibrary { handle }), - } - } - - /// Accesses the value at the symbol of the dynamic library. - pub unsafe fn symbol<T>(&self, symbol: &str) -> Result<*mut T, String> { - // This function should have a lifetime constraint of 'a on - // T but that feature is still unimplemented - - let raw_string = CString::new(symbol).unwrap(); - let maybe_symbol_value = dl::symbol(self.handle, raw_string.as_ptr()); - - // The value must not be constructed if there is an error so - // the destructor does not run. - match maybe_symbol_value { - Err(err) => Err(err), - Ok(symbol_value) => Ok(symbol_value as *mut T), - } - } -} - -#[cfg(test)] -mod tests; - -#[cfg(unix)] -mod dl { - use std::ffi::{CString, OsStr}; - use std::os::unix::prelude::*; - - // As of the 2017 revision of the POSIX standard (IEEE 1003.1-2017), it is - // implementation-defined whether `dlerror` is thread-safe (in which case it returns the most - // recent error in the calling thread) or not thread-safe (in which case it returns the most - // recent error in *any* thread). - // - // There's no easy way to tell what strategy is used by a given POSIX implementation, so we - // lock around all calls that can modify `dlerror` in this module lest we accidentally read an - // error from a different thread. This is bulletproof when we are the *only* code using the - // dynamic library APIs at a given point in time. However, it's still possible for us to race - // with other code (see #74469) on platforms where `dlerror` is not thread-safe. - mod error { - use std::ffi::CStr; - use std::lazy::SyncLazy; - use std::sync::{Mutex, MutexGuard}; - - pub fn lock() -> MutexGuard<'static, Guard> { - static LOCK: SyncLazy<Mutex<Guard>> = SyncLazy::new(|| Mutex::new(Guard)); - LOCK.lock().unwrap() - } - - #[non_exhaustive] - pub struct Guard; - - impl Guard { - pub fn get(&mut self) -> Result<(), String> { - let msg = unsafe { libc::dlerror() }; - if msg.is_null() { - Ok(()) - } else { - let msg = unsafe { CStr::from_ptr(msg as *const _) }; - Err(msg.to_string_lossy().into_owned()) - } - } - - pub fn clear(&mut self) { - let _ = unsafe { libc::dlerror() }; - } - } - } - - pub(super) fn open(filename: &OsStr) -> Result<*mut u8, String> { - let s = CString::new(filename.as_bytes()).unwrap(); - - let mut dlerror = error::lock(); - let ret = unsafe { libc::dlopen(s.as_ptr(), libc::RTLD_LAZY | libc::RTLD_LOCAL) }; - - if !ret.is_null() { - return Ok(ret.cast()); - } - - // A null return from `dlopen` indicates that an error has definitely occurred, so if - // nothing is in `dlerror`, we are racing with another thread that has stolen our error - // message. See the explanation on the `dl::error` module for more information. - dlerror.get().and_then(|()| Err("Unknown error".to_string())) - } - - pub(super) unsafe fn symbol( - handle: *mut u8, - symbol: *const libc::c_char, - ) -> Result<*mut u8, String> { - let mut dlerror = error::lock(); - - // Unlike `dlopen`, it's possible for `dlsym` to return null without overwriting `dlerror`. - // Because of this, we clear `dlerror` before calling `dlsym` to avoid picking up a stale - // error message by accident. - dlerror.clear(); - - let ret = libc::dlsym(handle as *mut libc::c_void, symbol); - - if !ret.is_null() { - return Ok(ret.cast()); - } - - // If `dlsym` returns null but there is nothing in `dlerror` it means one of two things: - // - We tried to load a symbol mapped to address 0. This is not technically an error but is - // unlikely to occur in practice and equally unlikely to be handled correctly by calling - // code. Therefore we treat it as an error anyway. - // - An error has occurred, but we are racing with another thread that has stolen our error - // message. See the explanation on the `dl::error` module for more information. - dlerror.get().and_then(|()| Err("Tried to load symbol mapped to address 0".to_string())) - } - - pub(super) unsafe fn close(handle: *mut u8) { - libc::dlclose(handle as *mut libc::c_void); - } -} - -#[cfg(windows)] -mod dl { - use std::ffi::OsStr; - use std::io; - use std::os::windows::prelude::*; - use std::ptr; - - use winapi::shared::minwindef::HMODULE; - use winapi::um::errhandlingapi::SetThreadErrorMode; - use winapi::um::libloaderapi::{FreeLibrary, GetProcAddress, LoadLibraryW}; - use winapi::um::winbase::SEM_FAILCRITICALERRORS; - - pub(super) fn open(filename: &OsStr) -> Result<*mut u8, String> { - // disable "dll load failed" error dialog. - let prev_error_mode = unsafe { - let new_error_mode = SEM_FAILCRITICALERRORS; - let mut prev_error_mode = 0; - let result = SetThreadErrorMode(new_error_mode, &mut prev_error_mode); - if result == 0 { - return Err(io::Error::last_os_error().to_string()); - } - prev_error_mode - }; - - let filename_str: Vec<_> = filename.encode_wide().chain(Some(0)).collect(); - let result = unsafe { LoadLibraryW(filename_str.as_ptr()) } as *mut u8; - let result = ptr_result(result); - - unsafe { - SetThreadErrorMode(prev_error_mode, ptr::null_mut()); - } - - result - } - - pub(super) unsafe fn symbol( - handle: *mut u8, - symbol: *const libc::c_char, - ) -> Result<*mut u8, String> { - let ptr = GetProcAddress(handle as HMODULE, symbol) as *mut u8; - ptr_result(ptr) - } - - pub(super) unsafe fn close(handle: *mut u8) { - FreeLibrary(handle as HMODULE); - } - - fn ptr_result<T>(ptr: *mut T) -> Result<*mut T, String> { - if ptr.is_null() { Err(io::Error::last_os_error().to_string()) } else { Ok(ptr) } - } -} diff --git a/compiler/rustc_metadata/src/dynamic_lib/tests.rs b/compiler/rustc_metadata/src/dynamic_lib/tests.rs deleted file mode 100644 index 7090bbf61c7..00000000000 --- a/compiler/rustc_metadata/src/dynamic_lib/tests.rs +++ /dev/null @@ -1,18 +0,0 @@ -use super::*; - -#[test] -fn test_errors_do_not_crash() { - use std::path::Path; - - if !cfg!(unix) { - return; - } - - // Open /dev/null as a library to get an error, and make sure - // that only causes an error, and not a crash. - let path = Path::new("/dev/null"); - match DynamicLibrary::open(&path) { - Err(_) => {} - Ok(_) => panic!("Successfully opened the empty library."), - } -} diff --git a/compiler/rustc_metadata/src/foreign_modules.rs b/compiler/rustc_metadata/src/foreign_modules.rs index 5b42f48a7d4..c70a6914520 100644 --- a/compiler/rustc_metadata/src/foreign_modules.rs +++ b/compiler/rustc_metadata/src/foreign_modules.rs @@ -13,7 +13,7 @@ struct Collector { modules: Vec<ForeignModule>, } -impl ItemLikeVisitor<'tcx> for Collector { +impl<'tcx> ItemLikeVisitor<'tcx> for Collector { fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) { let items = match it.kind { hir::ItemKind::ForeignMod { items, .. } => items, diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index 6cf0dd8b1ad..918c3b9daf1 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -1,7 +1,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(crate_visibility_modifier)] #![feature(drain_filter)] -#![feature(in_band_lifetimes)] #![feature(let_else)] #![feature(nll)] #![feature(once_cell)] @@ -28,7 +27,6 @@ mod native_libs; mod rmeta; pub mod creader; -pub mod dynamic_lib; pub mod locator; pub use rmeta::{encode_metadata, EncodedMetadata, METADATA_HEADER}; diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 8db2291dfcf..13ea089e245 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -220,7 +220,7 @@ use rustc_data_structures::memmap::Mmap; use rustc_data_structures::owning_ref::OwningRef; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::MetadataRef; -use rustc_errors::struct_span_err; +use rustc_errors::{struct_span_err, FatalError}; use rustc_session::config::{self, CrateType}; use rustc_session::cstore::{CrateSource, MetadataLoader}; use rustc_session::filesearch::{FileDoesntMatch, FileMatches, FileSearch}; @@ -315,7 +315,7 @@ impl<'a> CrateLocator<'a> { exact_paths: if hash.is_none() { sess.opts .externs - .get(&crate_name.as_str()) + .get(crate_name.as_str()) .into_iter() .filter_map(|entry| entry.files()) .flatten() @@ -350,6 +350,7 @@ impl<'a> CrateLocator<'a> { self.crate_rejections.via_kind.clear(); self.crate_rejections.via_version.clear(); self.crate_rejections.via_filename.clear(); + self.crate_rejections.via_invalid.clear(); } crate fn maybe_load_library_crate(&mut self) -> Result<Option<Library>, CrateError> { @@ -548,7 +549,17 @@ impl<'a> CrateLocator<'a> { continue; } } - Err(err) => { + Err(MetadataError::LoadFailure(err)) => { + info!("no metadata found: {}", err); + // The file was present and created by the same compiler version, but we + // couldn't load it for some reason. Give a hard error instead of silently + // ignoring it, but only if we would have given an error anyway. + self.crate_rejections + .via_invalid + .push(CrateMismatch { path: lib, got: err }); + continue; + } + Err(err @ MetadataError::NotPresent(_)) => { info!("no metadata found: {}", err); continue; } @@ -723,28 +734,31 @@ impl<'a> CrateLocator<'a> { } } -fn get_metadata_section( +fn get_metadata_section<'p>( target: &Target, flavor: CrateFlavor, - filename: &Path, + filename: &'p Path, loader: &dyn MetadataLoader, -) -> Result<MetadataBlob, String> { +) -> Result<MetadataBlob, MetadataError<'p>> { if !filename.exists() { - return Err(format!("no such file: '{}'", filename.display())); + return Err(MetadataError::NotPresent(filename)); } let raw_bytes: MetadataRef = match flavor { - CrateFlavor::Rlib => loader.get_rlib_metadata(target, filename)?, + CrateFlavor::Rlib => { + loader.get_rlib_metadata(target, filename).map_err(MetadataError::LoadFailure)? + } CrateFlavor::Dylib => { - let buf = loader.get_dylib_metadata(target, filename)?; + let buf = + loader.get_dylib_metadata(target, filename).map_err(MetadataError::LoadFailure)?; // The header is uncompressed let header_len = METADATA_HEADER.len(); debug!("checking {} bytes of metadata-version stamp", header_len); let header = &buf[..cmp::min(header_len, buf.len())]; if header != METADATA_HEADER { - return Err(format!( - "incompatible metadata version found: '{}'", + return Err(MetadataError::LoadFailure(format!( + "invalid metadata version found: {}", filename.display() - )); + ))); } // Header is okay -> inflate the actual metadata @@ -756,17 +770,28 @@ fn get_metadata_section( match FrameDecoder::new(compressed_bytes).read_to_end(&mut inflated) { Ok(_) => rustc_erase_owner!(OwningRef::new(inflated).map_owner_box()), Err(_) => { - return Err(format!("failed to decompress metadata: {}", filename.display())); + return Err(MetadataError::LoadFailure(format!( + "failed to decompress metadata: {}", + filename.display() + ))); } } } CrateFlavor::Rmeta => { // mmap the file, because only a small fraction of it is read. - let file = std::fs::File::open(filename) - .map_err(|_| format!("failed to open rmeta metadata: '{}'", filename.display()))?; + let file = std::fs::File::open(filename).map_err(|_| { + MetadataError::LoadFailure(format!( + "failed to open rmeta metadata: '{}'", + filename.display() + )) + })?; let mmap = unsafe { Mmap::map(file) }; - let mmap = mmap - .map_err(|_| format!("failed to mmap rmeta metadata: '{}'", filename.display()))?; + let mmap = mmap.map_err(|_| { + MetadataError::LoadFailure(format!( + "failed to mmap rmeta metadata: '{}'", + filename.display() + )) + })?; rustc_erase_owner!(OwningRef::new(mmap).map_owner_box()) } @@ -775,7 +800,10 @@ fn get_metadata_section( if blob.is_compatible() { Ok(blob) } else { - Err(format!("incompatible metadata version found: '{}'", filename.display())) + Err(MetadataError::LoadFailure(format!( + "invalid metadata version found: {}", + filename.display() + ))) } } @@ -786,11 +814,11 @@ pub fn find_plugin_registrar( span: Span, name: Symbol, ) -> PathBuf { - match find_plugin_registrar_impl(sess, metadata_loader, name) { - Ok(res) => res, + find_plugin_registrar_impl(sess, metadata_loader, name).unwrap_or_else(|err| { // `core` is always available if we got as far as loading plugins. - Err(err) => err.report(sess, span, false), - } + err.report(sess, span, false); + FatalError.raise() + }) } fn find_plugin_registrar_impl<'a>( @@ -854,6 +882,7 @@ struct CrateRejections { via_kind: Vec<CrateMismatch>, via_version: Vec<CrateMismatch>, via_filename: Vec<CrateMismatch>, + via_invalid: Vec<CrateMismatch>, } /// Candidate rejection reasons collected during crate search. @@ -883,9 +912,27 @@ crate enum CrateError { NonDylibPlugin(Symbol), } +enum MetadataError<'a> { + /// The file was missing. + NotPresent(&'a Path), + /// The file was present and invalid. + LoadFailure(String), +} + +impl fmt::Display for MetadataError<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + MetadataError::NotPresent(filename) => { + f.write_str(&format!("no such file: '{}'", filename.display())) + } + MetadataError::LoadFailure(msg) => f.write_str(msg), + } + } +} + impl CrateError { - crate fn report(self, sess: &Session, span: Span, missing_core: bool) -> ! { - let mut err = match self { + crate fn report(self, sess: &Session, span: Span, missing_core: bool) { + let mut diag = match self { CrateError::NonAsciiName(crate_name) => sess.struct_span_err( span, &format!("cannot load a crate with a non-ascii name `{}`", crate_name), @@ -929,7 +976,8 @@ impl CrateError { let candidates = libraries .iter() .map(|lib| { - let crate_name = &lib.metadata.get_root().name().as_str(); + let crate_name = lib.metadata.get_root().name(); + let crate_name = crate_name.as_str(); let mut paths = lib.source.paths(); // This `unwrap()` should be okay because there has to be at least one @@ -1064,6 +1112,19 @@ impl CrateError { } err.note(&msg); err + } else if !locator.crate_rejections.via_invalid.is_empty() { + let mut err = struct_span_err!( + sess, + span, + E0786, + "found invalid metadata files for crate `{}`{}", + crate_name, + add, + ); + for CrateMismatch { path: _, got } in locator.crate_rejections.via_invalid { + err.note(&got); + } + err } else { let mut err = struct_span_err!( sess, @@ -1114,7 +1175,7 @@ impl CrateError { } else if crate_name == Symbol::intern(&sess.opts.debugging_opts.profiler_runtime) { - err.note(&"the compiler may have been built without the profiler runtime"); + err.note("the compiler may have been built without the profiler runtime"); } else if crate_name.as_str().starts_with("rustc_") { err.help( "maybe you need to install the missing components with: \ @@ -1150,8 +1211,6 @@ impl CrateError { ), }; - err.emit(); - sess.abort_if_errors(); - unreachable!(); + diag.emit(); } } diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 2431b819a3f..13cd8e4a046 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -31,7 +31,7 @@ struct Collector<'tcx> { libs: Vec<NativeLib>, } -impl ItemLikeVisitor<'tcx> for Collector<'tcx> { +impl<'tcx> ItemLikeVisitor<'tcx> for Collector<'tcx> { fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) { let (abi, foreign_mod_items) = match it.kind { hir::ItemKind::ForeignMod { abi, items } => (abi, items), @@ -67,7 +67,7 @@ impl ItemLikeVisitor<'tcx> for Collector<'tcx> { Some(name) => name, None => continue, // skip like historical compilers }; - lib.kind = match &*kind.as_str() { + lib.kind = match kind.as_str() { "static" => NativeLibKind::Static { bundle: None, whole_archive: None }, "static-nobundle" => { sess.struct_span_warn( @@ -132,7 +132,7 @@ impl ItemLikeVisitor<'tcx> for Collector<'tcx> { if let Some(modifiers) = item.value_str() { let span = item.name_value_literal_span().unwrap(); for modifier in modifiers.as_str().split(',') { - let (modifier, value) = match modifier.strip_prefix(&['+', '-'][..]) { + let (modifier, value) = match modifier.strip_prefix(&['+', '-']) { Some(m) => (m, modifier.starts_with('+')), None => { sess.span_err( @@ -223,7 +223,7 @@ impl ItemLikeVisitor<'tcx> for Collector<'tcx> { fn visit_foreign_item(&mut self, _it: &'tcx hir::ForeignItem<'tcx>) {} } -impl Collector<'tcx> { +impl Collector<'_> { fn register_native_lib(&mut self, span: Option<Span>, lib: NativeLib) { if lib.name.as_ref().map_or(false, |&s| s == kw::Empty) { match span { @@ -274,11 +274,6 @@ impl Collector<'tcx> { span, "`#[link(...)]` with `kind = \"raw-dylib\"` only supported on Windows", ); - } else if !self.tcx.sess.target.options.is_like_msvc { - self.tcx.sess.span_warn( - span, - "`#[link(...)]` with `kind = \"raw-dylib\"` not supported on windows-gnu", - ); } if lib_name.as_str().contains('\0') { @@ -309,7 +304,7 @@ impl Collector<'tcx> { .libs .iter() .filter_map(|lib| lib.name.as_ref()) - .any(|n| &n.as_str() == &lib.name); + .any(|n| n.as_str() == lib.name); if new_name.is_empty() { self.tcx.sess.err(&format!( "an empty renaming target was specified for library `{}`", diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 5e90aec003e..fb1c71fb8cd 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -21,12 +21,13 @@ use rustc_hir::definitions::{DefKey, DefPath, DefPathData, DefPathHash}; use rustc_hir::diagnostic_items::DiagnosticItems; use rustc_hir::lang_items; use rustc_index::vec::{Idx, IndexVec}; -use rustc_middle::hir::exports::Export; +use rustc_middle::metadata::ModChild; use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState}; use rustc_middle::mir::{self, Body, Promoted}; use rustc_middle::thir; use rustc_middle::ty::codec::TyDecoder; +use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::{self, Ty, TyCtxt, Visibility}; use rustc_serialize::{opaque, Decodable, Decoder}; use rustc_session::cstore::{ @@ -45,7 +46,8 @@ use std::num::NonZeroUsize; use std::path::Path; use tracing::debug; -pub use cstore_impl::{provide, provide_extern}; +pub(super) use cstore_impl::provide; +pub use cstore_impl::provide_extern; use rustc_span::hygiene::HygieneDecodeContext; mod cstore_impl; @@ -91,8 +93,7 @@ crate struct CrateMetadata { /// Trait impl data. /// FIXME: Used only from queries and can use query cache, /// so pre-decoding can probably be avoided. - trait_impls: - FxHashMap<(u32, DefIndex), Lazy<[(DefIndex, Option<ty::fast_reject::SimplifiedType>)]>>, + trait_impls: FxHashMap<(u32, DefIndex), Lazy<[(DefIndex, Option<SimplifiedType>)]>>, /// Proc macro descriptions for this crate, if it's a proc macro crate. raw_proc_macros: Option<&'static [ProcMacro]>, /// Source maps for code from the crate. @@ -217,40 +218,40 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a MetadataBlob, &'tcx Session) { } } -impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a CrateMetadataRef<'a> { +impl<'a, 'tcx> Metadata<'a, 'tcx> for CrateMetadataRef<'a> { #[inline] fn blob(self) -> &'a MetadataBlob { - &self.blob + &self.cdata.blob } #[inline] fn cdata(self) -> Option<CrateMetadataRef<'a>> { - Some(*self) + Some(self) } } -impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadataRef<'a>, &'tcx Session) { +impl<'a, 'tcx> Metadata<'a, 'tcx> for (CrateMetadataRef<'a>, &'tcx Session) { #[inline] fn blob(self) -> &'a MetadataBlob { - &self.0.blob + &self.0.cdata.blob } #[inline] fn cdata(self) -> Option<CrateMetadataRef<'a>> { - Some(*self.0) + Some(self.0) } #[inline] fn sess(self) -> Option<&'tcx Session> { - Some(&self.1) + Some(self.1) } } -impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadataRef<'a>, TyCtxt<'tcx>) { +impl<'a, 'tcx> Metadata<'a, 'tcx> for (CrateMetadataRef<'a>, TyCtxt<'tcx>) { #[inline] fn blob(self) -> &'a MetadataBlob { - &self.0.blob + &self.0.cdata.blob } #[inline] fn cdata(self) -> Option<CrateMetadataRef<'a>> { - Some(*self.0) + Some(self.0) } #[inline] fn tcx(self) -> Option<TyCtxt<'tcx>> { @@ -262,7 +263,7 @@ impl<'a, 'tcx, T: Decodable<DecodeContext<'a, 'tcx>>> Lazy<T> { fn decode<M: Metadata<'a, 'tcx>>(self, metadata: M) -> T { let mut dcx = metadata.decoder(self.position.get()); dcx.lazy_state = LazyState::NodeStart(self.position); - T::decode(&mut dcx).unwrap() + T::decode(&mut dcx) } } @@ -273,7 +274,7 @@ impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable<DecodeContext<'a, 'tcx>>> Lazy<[T]> { ) -> impl ExactSizeIterator<Item = T> + Captures<'a> + Captures<'tcx> + 'x { let mut dcx = metadata.decoder(self.position.get()); dcx.lazy_state = LazyState::NodeStart(self.position); - (0..self.meta).map(move |_| T::decode(&mut dcx).unwrap()) + (0..self.meta).map(move |_| T::decode(&mut dcx)) } } @@ -299,23 +300,19 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> { if cnum == LOCAL_CRATE { self.cdata().cnum } else { self.cdata().cnum_map[cnum] } } - fn read_lazy_with_meta<T: ?Sized + LazyMeta>( - &mut self, - meta: T::Meta, - ) -> Result<Lazy<T>, <Self as Decoder>::Error> { - let min_size = T::min_size(meta); - let distance = self.read_usize()?; + fn read_lazy_with_meta<T: ?Sized + LazyMeta>(&mut self, meta: T::Meta) -> Lazy<T> { + let distance = self.read_usize(); let position = match self.lazy_state { LazyState::NoNode => bug!("read_lazy_with_meta: outside of a metadata node"), LazyState::NodeStart(start) => { let start = start.get(); - assert!(distance + min_size <= start); - start - distance - min_size + assert!(distance <= start); + start - distance } - LazyState::Previous(last_min_end) => last_min_end.get() + distance, + LazyState::Previous(last_pos) => last_pos.get() + distance, }; - self.lazy_state = LazyState::Previous(NonZeroUsize::new(position + min_size).unwrap()); - Ok(Lazy::from_position_and_meta(NonZeroUsize::new(position).unwrap(), meta)) + self.lazy_state = LazyState::Previous(NonZeroUsize::new(position).unwrap()); + Lazy::from_position_and_meta(NonZeroUsize::new(position).unwrap(), meta) } #[inline] @@ -342,25 +339,21 @@ impl<'a, 'tcx> TyDecoder<'tcx> for DecodeContext<'a, 'tcx> { self.opaque.position() } - fn cached_ty_for_shorthand<F>( - &mut self, - shorthand: usize, - or_insert_with: F, - ) -> Result<Ty<'tcx>, Self::Error> + fn cached_ty_for_shorthand<F>(&mut self, shorthand: usize, or_insert_with: F) -> Ty<'tcx> where - F: FnOnce(&mut Self) -> Result<Ty<'tcx>, Self::Error>, + F: FnOnce(&mut Self) -> Ty<'tcx>, { let tcx = self.tcx(); let key = ty::CReaderCacheKey { cnum: Some(self.cdata().cnum), pos: shorthand }; if let Some(&ty) = tcx.ty_rcache.borrow().get(&key) { - return Ok(ty); + return ty; } - let ty = or_insert_with(self)?; + let ty = or_insert_with(self); tcx.ty_rcache.borrow_mut().insert(key, ty); - Ok(ty) + ty } fn with_position<F, R>(&mut self, pos: usize, f: F) -> R @@ -376,7 +369,7 @@ impl<'a, 'tcx> TyDecoder<'tcx> for DecodeContext<'a, 'tcx> { r } - fn decode_alloc_id(&mut self) -> Result<rustc_middle::mir::interpret::AllocId, Self::Error> { + fn decode_alloc_id(&mut self) -> rustc_middle::mir::interpret::AllocId { if let Some(alloc_decoding_session) = self.alloc_decoding_session { alloc_decoding_session.decode_alloc_id(self) } else { @@ -386,48 +379,48 @@ impl<'a, 'tcx> TyDecoder<'tcx> for DecodeContext<'a, 'tcx> { } impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for CrateNum { - fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Result<CrateNum, String> { - let cnum = CrateNum::from_u32(d.read_u32()?); - Ok(d.map_encoded_cnum_to_current(cnum)) + fn decode(d: &mut DecodeContext<'a, 'tcx>) -> CrateNum { + let cnum = CrateNum::from_u32(d.read_u32()); + d.map_encoded_cnum_to_current(cnum) } } impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for DefIndex { - fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Result<DefIndex, String> { - Ok(DefIndex::from_u32(d.read_u32()?)) + fn decode(d: &mut DecodeContext<'a, 'tcx>) -> DefIndex { + DefIndex::from_u32(d.read_u32()) } } impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for ExpnIndex { - fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Result<ExpnIndex, String> { - Ok(ExpnIndex::from_u32(d.read_u32()?)) + fn decode(d: &mut DecodeContext<'a, 'tcx>) -> ExpnIndex { + ExpnIndex::from_u32(d.read_u32()) } } impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for SyntaxContext { - fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result<SyntaxContext, String> { + fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> SyntaxContext { let cdata = decoder.cdata(); let sess = decoder.sess.unwrap(); let cname = cdata.root.name; rustc_span::hygiene::decode_syntax_context(decoder, &cdata.hygiene_context, |_, id| { debug!("SpecializedDecoder<SyntaxContext>: decoding {}", id); - Ok(cdata + cdata .root .syntax_contexts - .get(&cdata, id) + .get(cdata, id) .unwrap_or_else(|| panic!("Missing SyntaxContext {:?} for crate {:?}", id, cname)) - .decode((&cdata, sess))) + .decode((cdata, sess)) }) } } impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for ExpnId { - fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result<ExpnId, String> { + fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> ExpnId { let local_cdata = decoder.cdata(); let sess = decoder.sess.unwrap(); - let cnum = CrateNum::decode(decoder)?; - let index = u32::decode(decoder)?; + let cnum = CrateNum::decode(decoder); + let index = u32::decode(decoder); let expn_id = rustc_span::hygiene::decode_expn_id(cnum, index, |expn_id| { let ExpnId { krate: cnum, local_id: index } = expn_id; @@ -442,34 +435,34 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for ExpnId { let expn_data = crate_data .root .expn_data - .get(&crate_data, index) + .get(crate_data, index) .unwrap() - .decode((&crate_data, sess)); + .decode((crate_data, sess)); let expn_hash = crate_data .root .expn_hashes - .get(&crate_data, index) + .get(crate_data, index) .unwrap() - .decode((&crate_data, sess)); + .decode((crate_data, sess)); (expn_data, expn_hash) }); - Ok(expn_id) + expn_id } } impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span { - fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result<Span, String> { - let ctxt = SyntaxContext::decode(decoder)?; - let tag = u8::decode(decoder)?; + fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Span { + let ctxt = SyntaxContext::decode(decoder); + let tag = u8::decode(decoder); if tag == TAG_PARTIAL_SPAN { - return Ok(DUMMY_SP.with_ctxt(ctxt)); + return DUMMY_SP.with_ctxt(ctxt); } debug_assert!(tag == TAG_VALID_SPAN_LOCAL || tag == TAG_VALID_SPAN_FOREIGN); - let lo = BytePos::decode(decoder)?; - let len = BytePos::decode(decoder)?; + let lo = BytePos::decode(decoder); + let len = BytePos::decode(decoder); let hi = lo + len; let Some(sess) = decoder.sess else { @@ -512,7 +505,7 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span { if decoder.cdata().root.is_proc_macro_crate() { // Decode `CrateNum` as u32 - using `CrateNum::decode` will ICE // since we don't have `cnum_map` populated. - let cnum = u32::decode(decoder)?; + let cnum = u32::decode(decoder); panic!( "Decoding of crate {:?} tried to access proc-macro dep {:?}", decoder.cdata().root.name, @@ -520,7 +513,7 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span { ); } // tag is TAG_VALID_SPAN_FOREIGN, checked by `debug_assert` above - let cnum = CrateNum::decode(decoder)?; + let cnum = CrateNum::decode(decoder); debug!( "SpecializedDecoder<Span>::specialized_decode: loading source files from cnum {:?}", cnum @@ -582,18 +575,18 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span { (hi + source_file.translated_source_file.start_pos) - source_file.original_start_pos; // Do not try to decode parent for foreign spans. - Ok(Span::new(lo, hi, ctxt, None)) + Span::new(lo, hi, ctxt, None) } } impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for &'tcx [thir::abstract_const::Node<'tcx>] { - fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Result<Self, String> { + fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Self { ty::codec::RefDecodable::decode(d) } } impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for &'tcx [(ty::Predicate<'tcx>, Span)] { - fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Result<Self, String> { + fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Self { ty::codec::RefDecodable::decode(d) } } @@ -601,7 +594,7 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for &'tcx [(ty::Predicate<'tcx impl<'a, 'tcx, T: Decodable<DecodeContext<'a, 'tcx>>> Decodable<DecodeContext<'a, 'tcx>> for Lazy<T> { - fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result<Self, String> { + fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Self { decoder.read_lazy_with_meta(()) } } @@ -609,9 +602,9 @@ impl<'a, 'tcx, T: Decodable<DecodeContext<'a, 'tcx>>> Decodable<DecodeContext<'a impl<'a, 'tcx, T: Decodable<DecodeContext<'a, 'tcx>>> Decodable<DecodeContext<'a, 'tcx>> for Lazy<[T]> { - fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result<Self, String> { - let len = decoder.read_usize()?; - if len == 0 { Ok(Lazy::empty()) } else { decoder.read_lazy_with_meta(len) } + fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Self { + let len = decoder.read_usize(); + if len == 0 { Lazy::empty() } else { decoder.read_lazy_with_meta(len) } } } @@ -620,15 +613,15 @@ impl<'a, 'tcx, I: Idx, T: Decodable<DecodeContext<'a, 'tcx>>> Decodable<DecodeCo where Option<T>: FixedSizeEncoding, { - fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result<Self, String> { - let len = decoder.read_usize()?; + fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Self { + let len = decoder.read_usize(); decoder.read_lazy_with_meta(len) } } implement_ty_decoder!(DecodeContext<'a, 'tcx>); -impl MetadataBlob { +impl<'tcx> MetadataBlob { crate fn new(metadata_ref: MetadataRef) -> MetadataBlob { MetadataBlob(Lrc::new(metadata_ref)) } @@ -697,7 +690,7 @@ impl CrateRoot<'_> { &self.triple } - crate fn decode_crate_deps( + crate fn decode_crate_deps<'a>( &self, metadata: &'a MetadataBlob, ) -> impl ExactSizeIterator<Item = CrateDep> + Captures<'a> { @@ -706,7 +699,7 @@ impl CrateRoot<'_> { } impl<'a, 'tcx> CrateMetadataRef<'a> { - fn raw_proc_macro(&self, id: DefIndex) -> &ProcMacro { + 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'. let pos = self @@ -721,32 +714,31 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { &self.raw_proc_macros.unwrap()[pos] } - fn try_item_ident(&self, item_index: DefIndex, sess: &Session) -> Result<Ident, String> { - let name = self - .def_key(item_index) - .disambiguated_data - .data - .get_opt_name() - .ok_or_else(|| format!("Missing opt name for {:?}", item_index))?; - let span = self - .root - .tables - .ident_span - .get(self, item_index) - .ok_or_else(|| format!("Missing ident span for {:?} ({:?})", name, item_index))? - .decode((self, sess)); - Ok(Ident::new(name, span)) + fn opt_item_ident(self, item_index: DefIndex, sess: &Session) -> Option<Ident> { + let name = self.def_key(item_index).disambiguated_data.data.get_opt_name()?; + let span = match self.root.tables.ident_span.get(self, item_index) { + Some(lazy_span) => lazy_span.decode((self, sess)), + None => { + // FIXME: this weird case of a name with no span is specific to `extern crate` + // items, which are supposed to be treated like `use` items and only be encoded + // to metadata as `Export`s, return `None` because that's what all the callers + // expect in this case. + assert_eq!(self.def_kind(item_index), DefKind::ExternCrate); + return None; + } + }; + Some(Ident::new(name, span)) } - fn item_ident(&self, item_index: DefIndex, sess: &Session) -> Ident { - self.try_item_ident(item_index, sess).unwrap() + fn item_ident(self, item_index: DefIndex, sess: &Session) -> Ident { + self.opt_item_ident(item_index, sess).expect("no encoded ident for item") } - fn maybe_kind(&self, item_id: DefIndex) -> Option<EntryKind> { + fn maybe_kind(self, item_id: DefIndex) -> Option<EntryKind> { self.root.tables.kind.get(self, item_id).map(|k| k.decode(self)) } - fn kind(&self, item_id: DefIndex) -> EntryKind { + fn kind(self, item_id: DefIndex) -> EntryKind { self.maybe_kind(item_id).unwrap_or_else(|| { bug!( "CrateMetadata::kind({:?}): id not found, in crate {:?} with number {}", @@ -757,7 +749,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { }) } - fn def_kind(&self, item_id: DefIndex) -> DefKind { + fn def_kind(self, item_id: DefIndex) -> DefKind { self.root.tables.def_kind.get(self, item_id).map(|k| k.decode(self)).unwrap_or_else(|| { bug!( "CrateMetadata::def_kind({:?}): id not found, in crate {:?} with number {}", @@ -768,7 +760,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { }) } - fn get_span(&self, index: DefIndex, sess: &Session) -> Span { + fn get_span(self, index: DefIndex, sess: &Session) -> Span { self.root .tables .span @@ -777,7 +769,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .decode((self, sess)) } - fn load_proc_macro(&self, id: DefIndex, sess: &Session) -> SyntaxExtension { + fn load_proc_macro(self, id: DefIndex, sess: &Session) -> SyntaxExtension { let (name, kind, helper_attrs) = match *self.raw_proc_macro(id) { ProcMacro::CustomDerive { trait_name, attributes, client } => { let helper_attrs = @@ -808,7 +800,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { ) } - fn get_trait_def(&self, item_id: DefIndex, sess: &Session) -> ty::TraitDef { + fn get_trait_def(self, item_id: DefIndex, sess: &Session) -> ty::TraitDef { match self.kind(item_id) { EntryKind::Trait(data) => { let data = data.decode((self, sess)); @@ -821,6 +813,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { data.skip_array_during_method_dispatch, data.specialization_kind, self.def_path_hash(item_id), + data.must_implement_one_of, ) } EntryKind::TraitAlias => ty::TraitDef::new( @@ -832,13 +825,14 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { false, ty::trait_def::TraitSpecializationKind::None, self.def_path_hash(item_id), + None, ), _ => bug!("def-index does not refer to trait or trait alias"), } } fn get_variant( - &self, + self, kind: &EntryKind, index: DefIndex, parent_did: DefId, @@ -863,7 +857,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { let ctor_did = data.ctor.map(|index| self.local_def_id(index)); ty::VariantDef::new( - self.item_ident(index, sess), + self.item_ident(index, sess).name, variant_did, ctor_did, data.discr, @@ -875,7 +869,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .decode(self) .map(|index| ty::FieldDef { did: self.local_def_id(index), - ident: self.item_ident(index, sess), + name: self.item_ident(index, sess).name, vis: self.get_visibility(index), }) .collect(), @@ -887,7 +881,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { ) } - fn get_adt_def(&self, item_id: DefIndex, tcx: TyCtxt<'tcx>) -> &'tcx ty::AdtDef { + fn get_adt_def(self, item_id: DefIndex, tcx: TyCtxt<'tcx>) -> &'tcx ty::AdtDef { let kind = self.kind(item_id); let did = self.local_def_id(item_id); @@ -915,7 +909,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } fn get_explicit_predicates( - &self, + self, item_id: DefIndex, tcx: TyCtxt<'tcx>, ) -> ty::GenericPredicates<'tcx> { @@ -923,7 +917,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } fn get_inferred_outlives( - &self, + self, item_id: DefIndex, tcx: TyCtxt<'tcx>, ) -> &'tcx [(ty::Predicate<'tcx>, Span)] { @@ -936,7 +930,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } fn get_super_predicates( - &self, + self, item_id: DefIndex, tcx: TyCtxt<'tcx>, ) -> ty::GenericPredicates<'tcx> { @@ -944,7 +938,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } fn get_explicit_item_bounds( - &self, + self, item_id: DefIndex, tcx: TyCtxt<'tcx>, ) -> &'tcx [(ty::Predicate<'tcx>, Span)] { @@ -956,11 +950,11 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .unwrap_or_default() } - fn get_generics(&self, item_id: DefIndex, sess: &Session) -> ty::Generics { + fn get_generics(self, item_id: DefIndex, sess: &Session) -> ty::Generics { self.root.tables.generics.get(self, item_id).unwrap().decode((self, sess)) } - fn get_type(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + fn get_type(self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { self.root .tables .ty @@ -969,59 +963,63 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .decode((self, tcx)) } - fn get_stability(&self, id: DefIndex) -> Option<attr::Stability> { + fn get_stability(self, id: DefIndex) -> Option<attr::Stability> { self.root.tables.stability.get(self, id).map(|stab| stab.decode(self)) } - fn get_const_stability(&self, id: DefIndex) -> Option<attr::ConstStability> { + fn get_const_stability(self, id: DefIndex) -> Option<attr::ConstStability> { self.root.tables.const_stability.get(self, id).map(|stab| stab.decode(self)) } - fn get_deprecation(&self, id: DefIndex) -> Option<attr::Deprecation> { + fn get_deprecation(self, id: DefIndex) -> Option<attr::Deprecation> { self.root.tables.deprecation.get(self, id).map(|depr| depr.decode(self)) } - fn get_visibility(&self, id: DefIndex) -> ty::Visibility { + fn get_visibility(self, id: DefIndex) -> ty::Visibility { self.root.tables.visibility.get(self, id).unwrap().decode(self) } - fn get_impl_data(&self, id: DefIndex) -> ImplData { + fn get_impl_data(self, id: DefIndex) -> ImplData { match self.kind(id) { EntryKind::Impl(data) => data.decode(self), _ => bug!(), } } - fn get_parent_impl(&self, id: DefIndex) -> Option<DefId> { + fn get_parent_impl(self, id: DefIndex) -> Option<DefId> { self.get_impl_data(id).parent_impl } - fn get_impl_polarity(&self, id: DefIndex) -> ty::ImplPolarity { + fn get_impl_polarity(self, id: DefIndex) -> ty::ImplPolarity { self.get_impl_data(id).polarity } - fn get_impl_defaultness(&self, id: DefIndex) -> hir::Defaultness { + fn get_impl_defaultness(self, id: DefIndex) -> hir::Defaultness { self.get_impl_data(id).defaultness } - fn get_impl_constness(&self, id: DefIndex) -> hir::Constness { + fn get_impl_constness(self, id: DefIndex) -> hir::Constness { self.get_impl_data(id).constness } - fn get_coerce_unsized_info(&self, id: DefIndex) -> Option<ty::adjustment::CoerceUnsizedInfo> { + fn get_trait_item_def_id(self, id: DefIndex) -> Option<DefId> { + self.root.tables.trait_item_def_id.get(self, id).map(|d| d.decode(self)) + } + + fn get_coerce_unsized_info(self, id: DefIndex) -> Option<ty::adjustment::CoerceUnsizedInfo> { self.get_impl_data(id).coerce_unsized_info } - fn get_impl_trait(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Option<ty::TraitRef<'tcx>> { + fn get_impl_trait(self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Option<ty::TraitRef<'tcx>> { self.root.tables.impl_trait_ref.get(self, id).map(|tr| tr.decode((self, tcx))) } - fn get_expn_that_defined(&self, id: DefIndex, sess: &Session) -> ExpnId { + fn get_expn_that_defined(self, id: DefIndex, sess: &Session) -> ExpnId { self.root.tables.expn_that_defined.get(self, id).unwrap().decode((self, sess)) } fn get_const_param_default( - &self, + self, tcx: TyCtxt<'tcx>, id: DefIndex, ) -> rustc_middle::ty::Const<'tcx> { @@ -1029,144 +1027,96 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } /// Iterates over all the stability attributes in the given crate. - fn get_lib_features(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(Symbol, Option<Symbol>)] { - // FIXME: For a proc macro crate, not sure whether we should return the "host" - // features or an empty Vec. Both don't cause ICEs. + fn get_lib_features(self, tcx: TyCtxt<'tcx>) -> &'tcx [(Symbol, Option<Symbol>)] { tcx.arena.alloc_from_iter(self.root.lib_features.decode(self)) } /// Iterates over the language items in the given crate. - fn get_lang_items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, usize)] { - if self.root.is_proc_macro_crate() { - // Proc macro crates do not export any lang-items to the target. - &[] - } else { - tcx.arena.alloc_from_iter( - self.root - .lang_items - .decode(self) - .map(|(def_index, index)| (self.local_def_id(def_index), index)), - ) - } + fn get_lang_items(self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, usize)] { + tcx.arena.alloc_from_iter( + self.root + .lang_items + .decode(self) + .map(|(def_index, index)| (self.local_def_id(def_index), index)), + ) } /// Iterates over the diagnostic items in the given crate. - fn get_diagnostic_items(&self) -> DiagnosticItems { - if self.root.is_proc_macro_crate() { - // Proc macro crates do not export any diagnostic-items to the target. - Default::default() - } else { - let mut id_to_name = FxHashMap::default(); - let name_to_id = self - .root - .diagnostic_items - .decode(self) - .map(|(name, def_index)| { - let id = self.local_def_id(def_index); - id_to_name.insert(id, name); - (name, id) - }) - .collect(); - DiagnosticItems { id_to_name, name_to_id } - } + fn get_diagnostic_items(self) -> DiagnosticItems { + let mut id_to_name = FxHashMap::default(); + let name_to_id = self + .root + .diagnostic_items + .decode(self) + .map(|(name, def_index)| { + let id = self.local_def_id(def_index); + id_to_name.insert(id, name); + (name, id) + }) + .collect(); + DiagnosticItems { id_to_name, name_to_id } } - /// Iterates over each child of the given item. - fn each_child_of_item(&self, id: DefIndex, mut callback: impl FnMut(Export), sess: &Session) { + /// Iterates over all named children of the given module, + /// including both proper items and reexports. + /// Module here is understood in name resolution sense - it can be a `mod` item, + /// or a crate root, or an enum, or a trait. + fn for_each_module_child( + self, + id: DefIndex, + mut callback: impl FnMut(ModChild), + sess: &Session, + ) { if let Some(data) = &self.root.proc_macro_data { - /* If we are loading as a proc macro, we want to return the view of this crate - * as a proc macro crate. - */ + // If we are loading as a proc macro, we want to return + // the view of this crate as a proc macro crate. if id == CRATE_DEF_INDEX { - let macros = data.macros.decode(self); - for def_index in macros { + for def_index in data.macros.decode(self) { let raw_macro = self.raw_proc_macro(def_index); let res = Res::Def( DefKind::Macro(macro_kind(raw_macro)), self.local_def_id(def_index), ); let ident = self.item_ident(def_index, sess); - callback(Export { ident, res, vis: ty::Visibility::Public, span: ident.span }); + callback(ModChild { + ident, + res, + vis: ty::Visibility::Public, + span: ident.span, + }); } } return; } - // Find the item. - let kind = match self.maybe_kind(id) { - None => return, - Some(kind) => kind, - }; - // Iterate over all children. - let macros_only = self.dep_kind.lock().macros_only(); - if !macros_only { - let children = self.root.tables.children.get(self, id).unwrap_or_else(Lazy::empty); - + if let Some(children) = self.root.tables.children.get(self, id) { for child_index in children.decode((self, sess)) { - // Get the item. - let child_kind = match self.maybe_kind(child_index) { - Some(child_kind) => child_kind, - None => continue, - }; - - // Hand off the item to the callback. - match child_kind { - // FIXME(eddyb) Don't encode these in children. - EntryKind::ForeignMod => { - let child_children = self - .root - .tables - .children - .get(self, child_index) - .unwrap_or_else(Lazy::empty); - for child_index in child_children.decode((self, sess)) { - let kind = self.def_kind(child_index); - callback(Export { - res: Res::Def(kind, self.local_def_id(child_index)), - ident: self.item_ident(child_index, sess), - vis: self.get_visibility(child_index), - span: self - .root - .tables - .span - .get(self, child_index) - .unwrap() - .decode((self, sess)), - }); - } + if let Some(ident) = self.opt_item_ident(child_index, sess) { + let kind = self.def_kind(child_index); + if matches!(kind, DefKind::Macro(..)) { + // FIXME: Macros are currently encoded twice, once as items and once as + // reexports. We ignore the items here and only use the reexports. continue; } - EntryKind::Impl(_) => continue, - - _ => {} - } - - let def_key = self.def_key(child_index); - if def_key.disambiguated_data.data.get_opt_name().is_some() { - let span = self.get_span(child_index, sess); - let kind = self.def_kind(child_index); - let ident = self.item_ident(child_index, sess); - let vis = self.get_visibility(child_index); let def_id = self.local_def_id(child_index); let res = Res::Def(kind, def_id); + let vis = self.get_visibility(child_index); + let span = self.get_span(child_index, sess); - // FIXME: Macros are currently encoded twice, once as items and once as - // reexports. We ignore the items here and only use the reexports. - if !matches!(kind, DefKind::Macro(..)) { - callback(Export { res, ident, vis, span }); - } + callback(ModChild { ident, res, vis, span }); // 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) = self.get_ctor_def_id(child_index) { - let ctor_kind = self.get_ctor_kind(child_index); + 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(Export { res: ctor_res, vis, ident, span }); + callback(ModChild { ident, res: ctor_res, vis, span }); } } DefKind::Variant => { @@ -1174,12 +1124,13 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { // 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 = self.get_ctor_def_id(child_index).unwrap_or(def_id); - let ctor_kind = self.get_ctor_kind(child_index); + 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 == ty::Visibility::Public { + 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 @@ -1190,7 +1141,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { vis = ty::Visibility::Restricted(crate_def_id); } } - callback(Export { res: ctor_res, ident, vis, span }); + callback(ModChild { ident, res: ctor_res, vis, span }); } _ => {} } @@ -1198,27 +1149,26 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } } - if let EntryKind::Mod(exports) = kind { - for exp in exports.decode((self, sess)) { - match exp.res { - Res::Def(DefKind::Macro(..), _) => {} - _ if macros_only => continue, - _ => {} + match self.kind(id) { + EntryKind::Mod(exports) => { + for exp in exports.decode((self, sess)) { + callback(exp); } - callback(exp); } + EntryKind::Enum(..) | EntryKind::Trait(..) => {} + _ => bug!("`for_each_module_child` is called on a non-module: {:?}", self.def_kind(id)), } } - fn is_ctfe_mir_available(&self, id: DefIndex) -> bool { + fn is_ctfe_mir_available(self, id: DefIndex) -> bool { self.root.tables.mir_for_ctfe.get(self, id).is_some() } - fn is_item_mir_available(&self, id: DefIndex) -> bool { + fn is_item_mir_available(self, id: DefIndex) -> bool { self.root.tables.mir.get(self, id).is_some() } - fn module_expansion(&self, id: DefIndex, sess: &Session) -> ExpnId { + fn module_expansion(self, id: DefIndex, sess: &Session) -> ExpnId { match self.kind(id) { EntryKind::Mod(_) | EntryKind::Enum(_) | EntryKind::Trait(_) => { self.get_expn_that_defined(id, sess) @@ -1227,7 +1177,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } } - fn get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> { + fn get_optimized_mir(self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> { self.root .tables .mir @@ -1238,7 +1188,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .decode((self, tcx)) } - fn get_mir_for_ctfe(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> { + fn get_mir_for_ctfe(self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> { self.root .tables .mir_for_ctfe @@ -1250,7 +1200,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } fn get_thir_abstract_const( - &self, + self, tcx: TyCtxt<'tcx>, id: DefIndex, ) -> Result<Option<&'tcx [thir::abstract_const::Node<'tcx>]>, ErrorReported> { @@ -1261,7 +1211,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .map_or(Ok(None), |v| Ok(Some(v.decode((self, tcx))))) } - fn get_unused_generic_params(&self, id: DefIndex) -> FiniteBitSet<u32> { + fn get_unused_generic_params(self, id: DefIndex) -> FiniteBitSet<u32> { self.root .tables .unused_generic_params @@ -1270,7 +1220,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .unwrap_or_default() } - fn get_promoted_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> IndexVec<Promoted, Body<'tcx>> { + fn get_promoted_mir(self, tcx: TyCtxt<'tcx>, id: DefIndex) -> IndexVec<Promoted, Body<'tcx>> { self.root .tables .promoted_mir @@ -1281,7 +1231,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .decode((self, tcx)) } - fn mir_const_qualif(&self, id: DefIndex) -> mir::ConstQualifs { + fn mir_const_qualif(self, id: DefIndex) -> mir::ConstQualifs { match self.kind(id) { EntryKind::AnonConst(qualif, _) | EntryKind::Const(qualif, _) @@ -1296,7 +1246,24 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } } - fn get_associated_item(&self, id: DefIndex, sess: &Session) -> ty::AssocItem { + fn get_fn_has_self_parameter(self, id: DefIndex) -> bool { + match self.kind(id) { + EntryKind::AssocFn(data) => data.decode(self).has_self, + _ => false, + } + } + + fn get_associated_item_def_ids(self, tcx: TyCtxt<'tcx>, id: DefIndex) -> &'tcx [DefId] { + if let Some(children) = self.root.tables.children.get(self, id) { + tcx.arena.alloc_from_iter( + children.decode((self, tcx.sess)).map(|child_index| self.local_def_id(child_index)), + ) + } else { + &[] + } + } + + fn get_associated_item(self, id: DefIndex, sess: &Session) -> ty::AssocItem { let def_key = self.def_key(id); let parent = self.local_def_id(def_key.parent.unwrap()); let ident = self.item_ident(id, sess); @@ -1312,88 +1279,82 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { }; ty::AssocItem { - ident, + name: ident.name, kind, vis: self.get_visibility(id), defaultness: container.defaultness(), def_id: self.local_def_id(id), + trait_item_def_id: self.get_trait_item_def_id(id), container: container.with_def_id(parent), fn_has_self_parameter: has_self, } } - fn get_item_variances(&'a self, id: DefIndex) -> impl Iterator<Item = ty::Variance> + 'a { + fn get_item_variances(self, id: DefIndex) -> impl Iterator<Item = ty::Variance> + 'a { self.root.tables.variances.get(self, id).unwrap_or_else(Lazy::empty).decode(self) } - fn get_ctor_kind(&self, node_id: DefIndex) -> CtorKind { - match self.kind(node_id) { - EntryKind::Struct(data, _) | EntryKind::Union(data, _) | EntryKind::Variant(data) => { - data.decode(self).ctor_kind - } - _ => CtorKind::Fictive, - } - } - - fn get_ctor_def_id(&self, node_id: DefIndex) -> Option<DefId> { + fn get_ctor_def_id_and_kind(self, node_id: DefIndex) -> Option<(DefId, CtorKind)> { match self.kind(node_id) { - EntryKind::Struct(data, _) => { - data.decode(self).ctor.map(|index| self.local_def_id(index)) - } - EntryKind::Variant(data) => { - data.decode(self).ctor.map(|index| self.local_def_id(index)) + EntryKind::Struct(data, _) | EntryKind::Variant(data) => { + let vdata = data.decode(self); + vdata.ctor.map(|index| (self.local_def_id(index), vdata.ctor_kind)) } _ => None, } } fn get_item_attrs( - &'a self, - node_id: DefIndex, + self, + id: DefIndex, sess: &'a Session, ) -> impl Iterator<Item = ast::Attribute> + 'a { - // The attributes for a tuple struct/variant are attached to the definition, not the ctor; - // we assume that someone passing in a tuple struct ctor is actually wanting to - // look at the definition - let def_key = self.def_key(node_id); - let item_id = if def_key.disambiguated_data.data == DefPathData::Ctor { - def_key.parent.unwrap() - } else { - node_id - }; - self.root .tables .attributes - .get(self, item_id) - .unwrap_or_else(Lazy::empty) + .get(self, id) + .unwrap_or_else(|| { + // Structure and variant constructors don't have any attributes encoded for them, + // but we assume that someone passing a constructor ID actually wants to look at + // the attributes on the corresponding struct or variant. + let def_key = self.def_key(id); + assert_eq!(def_key.disambiguated_data.data, DefPathData::Ctor); + let parent_id = def_key.parent.expect("no parent for a constructor"); + self.root + .tables + .attributes + .get(self, parent_id) + .expect("no encoded attributes for a structure or variant") + }) .decode((self, sess)) } - fn get_struct_field_names(&self, id: DefIndex, sess: &Session) -> Vec<Spanned<Symbol>> { + fn get_struct_field_names( + self, + id: DefIndex, + sess: &'a Session, + ) -> impl Iterator<Item = Spanned<Symbol>> + 'a { self.root .tables .children .get(self, id) .unwrap_or_else(Lazy::empty) .decode(self) - .map(|index| respan(self.get_span(index, sess), self.item_ident(index, sess).name)) - .collect() + .map(move |index| respan(self.get_span(index, sess), self.item_ident(index, sess).name)) } - fn get_struct_field_visibilities(&self, id: DefIndex) -> Vec<Visibility> { + fn get_struct_field_visibilities(self, id: DefIndex) -> impl Iterator<Item = Visibility> + 'a { self.root .tables .children .get(self, id) .unwrap_or_else(Lazy::empty) .decode(self) - .map(|field_index| self.get_visibility(field_index)) - .collect() + .map(move |field_index| self.get_visibility(field_index)) } fn get_inherent_implementations_for_type( - &self, + self, tcx: TyCtxt<'tcx>, id: DefIndex, ) -> &'tcx [DefId] { @@ -1408,43 +1369,50 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { ) } - fn get_implementations_for_trait( - &self, + fn get_traits(self) -> impl Iterator<Item = DefId> + 'a { + self.root.traits.decode(self).map(move |index| self.local_def_id(index)) + } + + fn get_trait_impls(self) -> impl Iterator<Item = (DefId, DefId, Option<SimplifiedType>)> + 'a { + self.cdata.trait_impls.iter().flat_map(move |((trait_cnum_raw, trait_index), impls)| { + let trait_def_id = DefId { + krate: self.cnum_map[CrateNum::from_u32(*trait_cnum_raw)], + index: *trait_index, + }; + impls.decode(self).map(move |(impl_index, simplified_self_ty)| { + (trait_def_id, self.local_def_id(impl_index), simplified_self_ty) + }) + }) + } + + fn get_implementations_of_trait( + self, tcx: TyCtxt<'tcx>, - filter: Option<DefId>, - ) -> &'tcx [(DefId, Option<ty::fast_reject::SimplifiedType>)] { - if self.root.is_proc_macro_crate() { - // proc-macro crates export no trait impls. + trait_def_id: DefId, + ) -> &'tcx [(DefId, Option<SimplifiedType>)] { + if self.trait_impls.is_empty() { return &[]; } - if let Some(def_id) = filter { - // Do a reverse lookup beforehand to avoid touching the crate_num - // hash map in the loop below. - let filter = match self.reverse_translate_def_id(def_id) { - Some(def_id) => (def_id.krate.as_u32(), def_id.index), - None => return &[], - }; + // Do a reverse lookup beforehand to avoid touching the crate_num + // hash map in the loop below. + let key = match self.reverse_translate_def_id(trait_def_id) { + Some(def_id) => (def_id.krate.as_u32(), def_id.index), + None => return &[], + }; - if let Some(impls) = self.trait_impls.get(&filter) { - tcx.arena.alloc_from_iter( - impls.decode(self).map(|(idx, simplified_self_ty)| { - (self.local_def_id(idx), simplified_self_ty) - }), - ) - } else { - &[] - } - } else { - tcx.arena.alloc_from_iter(self.trait_impls.values().flat_map(|impls| { + if let Some(impls) = self.trait_impls.get(&key) { + tcx.arena.alloc_from_iter( impls .decode(self) - .map(|(idx, simplified_self_ty)| (self.local_def_id(idx), simplified_self_ty)) - })) + .map(|(idx, simplified_self_ty)| (self.local_def_id(idx), simplified_self_ty)), + ) + } else { + &[] } } - fn get_trait_of_item(&self, id: DefIndex) -> Option<DefId> { + fn get_trait_of_item(self, id: DefIndex) -> Option<DefId> { let def_key = self.def_key(id); match def_key.disambiguated_data.data { DefPathData::TypeNs(..) | DefPathData::ValueNs(..) => (), @@ -1457,16 +1425,11 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { }) } - fn get_native_libraries(&self, sess: &Session) -> Vec<NativeLib> { - if self.root.is_proc_macro_crate() { - // Proc macro crates do not have any *target* native libraries. - vec![] - } else { - self.root.native_libraries.decode((self, sess)).collect() - } + fn get_native_libraries(self, sess: &'a Session) -> impl Iterator<Item = NativeLib> + 'a { + self.root.native_libraries.decode((self, sess)) } - fn get_proc_macro_quoted_span(&self, index: usize, sess: &Session) -> Span { + fn get_proc_macro_quoted_span(self, index: usize, sess: &Session) -> Span { self.root .tables .proc_macro_quoted_spans @@ -1475,19 +1438,12 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .decode((self, sess)) } - fn get_foreign_modules(&self, tcx: TyCtxt<'tcx>) -> Lrc<FxHashMap<DefId, ForeignModule>> { - if self.root.is_proc_macro_crate() { - // Proc macro crates do not have any *target* foreign modules. - Lrc::new(FxHashMap::default()) - } else { - let modules: FxHashMap<DefId, ForeignModule> = - self.root.foreign_modules.decode((self, tcx.sess)).map(|m| (m.def_id, m)).collect(); - Lrc::new(modules) - } + fn get_foreign_modules(self, sess: &'a Session) -> impl Iterator<Item = ForeignModule> + '_ { + self.root.foreign_modules.decode((self, sess)) } fn get_dylib_dependency_formats( - &self, + self, tcx: TyCtxt<'tcx>, ) -> &'tcx [(CrateNum, LinkagePreference)] { tcx.arena.alloc_from_iter( @@ -1498,16 +1454,11 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { ) } - fn get_missing_lang_items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [lang_items::LangItem] { - if self.root.is_proc_macro_crate() { - // Proc macro crates do not depend on any target weak lang-items. - &[] - } else { - tcx.arena.alloc_from_iter(self.root.lang_items_missing.decode(self)) - } + fn get_missing_lang_items(self, tcx: TyCtxt<'tcx>) -> &'tcx [lang_items::LangItem] { + tcx.arena.alloc_from_iter(self.root.lang_items_missing.decode(self)) } - fn get_fn_param_names(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> &'tcx [Ident] { + fn get_fn_param_names(self, tcx: TyCtxt<'tcx>, id: DefIndex) -> &'tcx [Ident] { let param_names = match self.kind(id) { EntryKind::Fn(data) | EntryKind::ForeignFn(data) => data.decode(self).param_names, EntryKind::AssocFn(data) => data.decode(self).fn_data.param_names, @@ -1517,19 +1468,13 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } fn exported_symbols( - &self, + self, tcx: TyCtxt<'tcx>, ) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportLevel)] { - if self.root.is_proc_macro_crate() { - // If this crate is a custom derive crate, then we're not even going to - // link those in so we skip those crates. - &[] - } else { - tcx.arena.alloc_from_iter(self.root.exported_symbols.decode((self, tcx))) - } + tcx.arena.alloc_from_iter(self.root.exported_symbols.decode((self, tcx))) } - fn get_rendered_const(&self, id: DefIndex) -> String { + fn get_rendered_const(self, id: DefIndex) -> String { match self.kind(id) { EntryKind::AnonConst(_, data) | EntryKind::Const(_, data) @@ -1538,7 +1483,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } } - fn get_macro(&self, id: DefIndex, sess: &Session) -> MacroDef { + fn get_macro(self, id: DefIndex, sess: &Session) -> MacroDef { match self.kind(id) { EntryKind::MacroDef(macro_def) => macro_def.decode((self, sess)), _ => bug!(), @@ -1547,7 +1492,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { // This replicates some of the logic of the crate-local `is_const_fn_raw` query, because we // don't serialize constness for tuple variant and tuple struct constructors. - fn is_const_fn_raw(&self, id: DefIndex) -> bool { + fn is_const_fn_raw(self, id: DefIndex) -> bool { let constness = match self.kind(id) { EntryKind::AssocFn(data) => data.decode(self).fn_data.constness, EntryKind::Fn(data) => data.decode(self).constness, @@ -1558,7 +1503,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { constness == hir::Constness::Const } - fn asyncness(&self, id: DefIndex) -> hir::IsAsync { + fn asyncness(self, id: DefIndex) -> hir::IsAsync { match self.kind(id) { EntryKind::Fn(data) => data.decode(self).asyncness, EntryKind::AssocFn(data) => data.decode(self).fn_data.asyncness, @@ -1567,7 +1512,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } } - fn is_foreign_item(&self, id: DefIndex) -> bool { + fn is_foreign_item(self, id: DefIndex) -> bool { match self.kind(id) { EntryKind::ForeignImmStatic | EntryKind::ForeignMutStatic | EntryKind::ForeignFn(_) => { true @@ -1576,7 +1521,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } } - fn static_mutability(&self, id: DefIndex) -> Option<hir::Mutability> { + fn static_mutability(self, id: DefIndex) -> Option<hir::Mutability> { match self.kind(id) { EntryKind::ImmStatic | EntryKind::ForeignImmStatic => Some(hir::Mutability::Not), EntryKind::MutStatic | EntryKind::ForeignMutStatic => Some(hir::Mutability::Mut), @@ -1584,19 +1529,19 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } } - fn generator_kind(&self, id: DefIndex) -> Option<hir::GeneratorKind> { + fn generator_kind(self, id: DefIndex) -> Option<hir::GeneratorKind> { match self.kind(id) { EntryKind::Generator(data) => Some(data), _ => None, } } - fn fn_sig(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> { + fn fn_sig(self, id: DefIndex, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> { self.root.tables.fn_sig.get(self, id).unwrap().decode((self, tcx)) } #[inline] - fn def_key(&self, index: DefIndex) -> DefKey { + fn def_key(self, index: DefIndex) -> DefKey { *self .def_key_cache .lock() @@ -1605,13 +1550,13 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } // Returns the path leading to the thing with this `id`. - fn def_path(&self, id: DefIndex) -> DefPath { + fn def_path(self, id: DefIndex) -> DefPath { debug!("def_path(cnum={:?}, id={:?})", self.cnum, id); DefPath::make(self.cnum, id, |parent| self.def_key(parent)) } fn def_path_hash_unlocked( - &self, + self, index: DefIndex, def_path_hashes: &mut FxHashMap<DefIndex, DefPathHash>, ) -> DefPathHash { @@ -1621,17 +1566,17 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } #[inline] - fn def_path_hash(&self, index: DefIndex) -> DefPathHash { + fn def_path_hash(self, index: DefIndex) -> DefPathHash { let mut def_path_hashes = self.def_path_hash_cache.lock(); self.def_path_hash_unlocked(index, &mut def_path_hashes) } #[inline] - fn def_path_hash_to_def_index(&self, hash: DefPathHash) -> DefIndex { + fn def_path_hash_to_def_index(self, hash: DefPathHash) -> DefIndex { self.def_path_hash_map.def_path_hash_to_def_index(&hash) } - fn expn_hash_to_expn_id(&self, sess: &Session, index_guess: u32, hash: ExpnHash) -> ExpnId { + fn expn_hash_to_expn_id(self, sess: &Session, index_guess: u32, hash: ExpnHash) -> ExpnId { debug_assert_eq!(ExpnId::from_hash(hash), None); let index_guess = ExpnIndex::from_u32(index_guess); let old_hash = self.root.expn_hashes.get(self, index_guess).map(|lazy| lazy.decode(self)); @@ -1689,7 +1634,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { /// /// Proc macro crates don't currently export spans, so this function does not have /// to work for them. - fn imported_source_files(&self, sess: &Session) -> &'a [ImportedSourceFile] { + fn imported_source_files(self, sess: &Session) -> &'a [ImportedSourceFile] { // Translate the virtual `/rustc/$hash` prefix back to a real directory // that should hold actual sources, where possible. // diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 7ea004b16f2..2f8e35648ec 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -4,12 +4,13 @@ use crate::native_libs; use rustc_ast as ast; use rustc_data_structures::stable_map::FxHashMap; -use rustc_hir::def::{CtorKind, DefKind}; +use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::definitions::{DefKey, DefPath, DefPathHash}; -use rustc_middle::hir::exports::Export; +use rustc_middle::metadata::ModChild; use rustc_middle::middle::exported_symbols::ExportedSymbol; use rustc_middle::middle::stability::DeprecationEntry; +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, ForeignModule}; @@ -17,7 +18,7 @@ use rustc_session::utils::NativeLibKind; use rustc_session::{Session, StableCrateId}; use rustc_span::hygiene::{ExpnHash, ExpnId}; use rustc_span::source_map::{Span, Spanned}; -use rustc_span::symbol::Symbol; +use rustc_span::symbol::{kw, Symbol}; use rustc_data_structures::sync::Lrc; use smallvec::SmallVec; @@ -83,7 +84,7 @@ impl IntoArgs for (CrateNum, DefId) { } } -impl IntoArgs for ty::InstanceDef<'tcx> { +impl<'tcx> IntoArgs for ty::InstanceDef<'tcx> { fn into_args(self) -> (DefId, DefId) { (self.def_id(), self.def_id()) } @@ -103,12 +104,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, tcx.calculate_dtor(def_id, |_,_| Ok(())) } variances_of => { tcx.arena.alloc_from_iter(cdata.get_item_variances(def_id.index)) } - associated_item_def_ids => { - let mut result = SmallVec::<[_; 8]>::new(); - cdata.each_child_of_item(def_id.index, - |child| result.push(child.res.def_id()), tcx.sess); - tcx.arena.alloc_slice(&result) - } + associated_item_def_ids => { cdata.get_associated_item_def_ids(tcx, def_id.index) } associated_item => { cdata.get_associated_item(def_id.index, tcx.sess) } impl_trait_ref => { cdata.get_impl_trait(def_id.index, tcx) } impl_polarity => { cdata.get_impl_polarity(def_id.index) } @@ -133,9 +129,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, generator_kind => { cdata.generator_kind(def_id.index) } opt_def_kind => { Some(cdata.def_kind(def_id.index)) } def_span => { cdata.get_span(def_id.index, &tcx.sess) } - def_ident_span => { - cdata.try_item_ident(def_id.index, &tcx.sess).ok().map(|ident| ident.span) - } + def_ident_span => { cdata.opt_item_ident(def_id.index, &tcx.sess).map(|ident| ident.span) } lookup_stability => { cdata.get_stability(def_id.index).map(|s| tcx.intern_stability(s)) } @@ -145,9 +139,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, lookup_deprecation_entry => { cdata.get_deprecation(def_id.index).map(DeprecationEntry::external) } - item_attrs => { tcx.arena.alloc_from_iter( - cdata.get_item_attrs(def_id.index, tcx.sess) - ) } + item_attrs => { tcx.arena.alloc_from_iter(cdata.get_item_attrs(def_id.index, tcx.sess)) } fn_arg_names => { cdata.get_fn_param_names(tcx, def_id.index) } rendered_const => { cdata.get_rendered_const(def_id.index) } impl_parent => { cdata.get_parent_impl(def_id.index) } @@ -187,30 +179,27 @@ provide! { <'tcx> tcx, def_id, other, cdata, reachable_non_generics } - native_libraries => { Lrc::new(cdata.get_native_libraries(tcx.sess)) } - foreign_modules => { cdata.get_foreign_modules(tcx) } + native_libraries => { Lrc::new(cdata.get_native_libraries(tcx.sess).collect()) } + foreign_modules => { + Lrc::new(cdata.get_foreign_modules(tcx.sess).map(|m| (m.def_id, m)).collect()) + } crate_hash => { cdata.root.hash } crate_host_hash => { cdata.host_hash } crate_name => { cdata.root.name } extra_filename => { cdata.root.extra_filename.clone() } - implementations_of_trait => { - cdata.get_implementations_for_trait(tcx, Some(other)) - } - - all_trait_implementations => { - cdata.get_implementations_for_trait(tcx, None) - } + traits_in_crate => { tcx.arena.alloc_from_iter(cdata.get_traits()) } + implementations_of_trait => { cdata.get_implementations_of_trait(tcx, other) } visibility => { cdata.get_visibility(def_id.index) } dep_kind => { let r = *cdata.dep_kind.lock(); r } - item_children => { + module_children => { let mut result = SmallVec::<[_; 8]>::new(); - cdata.each_child_of_item(def_id.index, |child| result.push(child), tcx.sess); + cdata.for_each_module_child(def_id.index, |child| result.push(child), tcx.sess); tcx.arena.alloc_slice(&result) } defined_lib_features => { cdata.get_lib_features(tcx) } @@ -239,7 +228,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, expn_that_defined => { cdata.get_expn_that_defined(def_id.index, tcx.sess) } } -pub fn provide(providers: &mut Providers) { +pub(in crate::rmeta) fn provide(providers: &mut Providers) { // FIXME(#44234) - almost all of these queries have no sub-queries and // therefore no actual inputs, they're just reading tables calculated in // resolve! Does this work? Unsure! That's what the issue is about @@ -295,6 +284,10 @@ pub fn provide(providers: &mut Providers) { use std::collections::vec_deque::VecDeque; let mut visible_parent_map: DefIdMap<DefId> = Default::default(); + // This is a secondary visible_parent_map, storing the DefId of parents that re-export + // the child as `_`. Since we prefer parents that don't do this, merge this map at the + // end, only if we're missing any keys from the former. + let mut fallback_map: DefIdMap<DefId> = Default::default(); // Issue 46112: We want the map to prefer the shortest // paths when reporting the path to an item. Therefore we @@ -317,35 +310,51 @@ pub fn provide(providers: &mut Providers) { bfs_queue.push_back(DefId { krate: cnum, index: CRATE_DEF_INDEX }); } - let mut add_child = |bfs_queue: &mut VecDeque<_>, child: &Export, parent: DefId| { - if child.vis != ty::Visibility::Public { + let mut add_child = |bfs_queue: &mut VecDeque<_>, child: &ModChild, parent: DefId| { + if !child.vis.is_public() { return; } - if let Some(child) = child.res.opt_def_id() { - match visible_parent_map.entry(child) { + if let Some(def_id) = child.res.opt_def_id() { + if child.ident.name == kw::Underscore { + fallback_map.insert(def_id, parent); + return; + } + + match visible_parent_map.entry(def_id) { Entry::Occupied(mut entry) => { // If `child` is defined in crate `cnum`, ensure // that it is mapped to a parent in `cnum`. - if child.is_local() && entry.get().is_local() { + if def_id.is_local() && entry.get().is_local() { entry.insert(parent); } } Entry::Vacant(entry) => { entry.insert(parent); - bfs_queue.push_back(child); + if matches!( + child.res, + Res::Def(DefKind::Mod | DefKind::Enum | DefKind::Trait, _) + ) { + bfs_queue.push_back(def_id); + } } } } }; while let Some(def) = bfs_queue.pop_front() { - for child in tcx.item_children(def).iter() { + for child in tcx.module_children(def).iter() { add_child(bfs_queue, child, def); } } - visible_parent_map + // Fill in any missing entries with the (less preferable) path ending in `::_`. + // We still use this path in a diagnostic that suggests importing `::*`. + for (child, parent) in fallback_map { + visible_parent_map.entry(child).or_insert(parent); + } + + Lrc::new(visible_parent_map) }, dependency_formats: |tcx, ()| Lrc::new(crate::dependency_format::calculate(tcx)), @@ -357,34 +366,39 @@ pub fn provide(providers: &mut Providers) { tcx.arena .alloc_slice(&CStore::from_tcx(tcx).crate_dependencies_in_postorder(LOCAL_CRATE)) }, - crates: |tcx, ()| tcx.arena.alloc_slice(&CStore::from_tcx(tcx).crates_untracked()), + crates: |tcx, ()| tcx.arena.alloc_from_iter(CStore::from_tcx(tcx).crates_untracked()), ..*providers }; } impl CStore { - pub fn struct_field_names_untracked(&self, def: DefId, sess: &Session) -> Vec<Spanned<Symbol>> { + 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) -> Vec<Visibility> { + pub fn struct_field_visibilities_untracked( + &self, + def: DefId, + ) -> impl Iterator<Item = Visibility> + '_ { self.get_crate_data(def.krate).get_struct_field_visibilities(def.index) } pub fn ctor_def_id_and_kind_untracked(&self, def: DefId) -> Option<(DefId, CtorKind)> { - self.get_crate_data(def.krate).get_ctor_def_id(def.index).map(|ctor_def_id| { - (ctor_def_id, self.get_crate_data(def.krate).get_ctor_kind(def.index)) - }) + self.get_crate_data(def.krate).get_ctor_def_id_and_kind(def.index) } pub fn visibility_untracked(&self, def: DefId) -> Visibility { self.get_crate_data(def.krate).get_visibility(def.index) } - pub fn item_children_untracked(&self, def_id: DefId, sess: &Session) -> Vec<Export> { + pub fn module_children_untracked(&self, def_id: DefId, sess: &Session) -> Vec<ModChild> { let mut result = vec![]; - self.get_crate_data(def_id.krate).each_child_of_item( + self.get_crate_data(def_id.krate).for_each_module_child( def_id.index, |child| result.push(child), sess, @@ -402,16 +416,12 @@ impl CStore { let span = data.get_span(id.index, sess); - let attrs = data.get_item_attrs(id.index, sess).collect(); - - let ident = data.item_ident(id.index, sess); - LoadedMacro::MacroDef( ast::Item { - ident, + ident: data.item_ident(id.index, sess), id: ast::DUMMY_NODE_ID, span, - attrs, + attrs: data.get_item_attrs(id.index, sess).collect(), kind: ast::ItemKind::MacroDef(data.get_macro(id.index, sess)), vis: ast::Visibility { span: span.shrink_to_lo(), @@ -424,8 +434,8 @@ impl CStore { ) } - pub fn associated_item_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::AssocItem { - self.get_crate_data(def.krate).get_associated_item(def.index, sess) + pub fn fn_has_self_parameter_untracked(&self, def: DefId) -> bool { + self.get_crate_data(def.krate).get_fn_has_self_parameter(def.index) } pub fn crate_source_untracked(&self, cnum: CrateNum) -> CrateSource { @@ -440,10 +450,8 @@ impl CStore { self.get_crate_data(def.krate).def_kind(def.index) } - pub fn crates_untracked(&self) -> Vec<CrateNum> { - let mut result = vec![]; - self.iter_crate_data(|cnum, _| result.push(cnum)); - result + 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 { @@ -461,8 +469,12 @@ impl CStore { self.get_crate_data(cnum).num_def_ids() } - pub fn item_attrs(&self, def_id: DefId, sess: &Session) -> Vec<ast::Attribute> { - self.get_crate_data(def_id.krate).get_item_attrs(def_id.index, sess).collect() + 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( @@ -473,6 +485,17 @@ impl CStore { ) -> Span { self.get_crate_data(cnum).get_proc_macro_quoted_span(id, sess) } + + pub fn traits_in_crate_untracked(&self, cnum: CrateNum) -> impl Iterator<Item = DefId> + '_ { + self.get_crate_data(cnum).get_traits() + } + + pub fn trait_impls_in_crate_untracked( + &self, + cnum: CrateNum, + ) -> impl Iterator<Item = (DefId, DefId, Option<SimplifiedType>)> + '_ { + self.get_crate_data(cnum).get_trait_impls() + } } impl CrateStore for CStore { @@ -521,4 +544,8 @@ impl CrateStore for CStore { ) -> ExpnId { self.get_crate_data(cnum).expn_hash_to_expn_id(sess, index_guess, hash) } + + fn import_source_files(&self, sess: &Session, cnum: CrateNum) { + self.get_crate_data(cnum).imported_source_files(sess); + } } 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 d6435bb649d..d66f2b031a8 100644 --- a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs +++ b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs @@ -11,7 +11,7 @@ crate enum DefPathHashMapRef<'tcx> { BorrowedFromTcx(&'tcx DefPathHashMap), } -impl DefPathHashMapRef<'tcx> { +impl DefPathHashMapRef<'_> { #[inline] pub fn def_path_hash_to_def_index(&self, def_path_hash: &DefPathHash) -> DefIndex { match *self { @@ -39,11 +39,11 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for DefPathHashMapRef<'tcx> { } impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for DefPathHashMapRef<'static> { - fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Result<DefPathHashMapRef<'static>, String> { + fn decode(d: &mut DecodeContext<'a, 'tcx>) -> DefPathHashMapRef<'static> { // Import TyDecoder so we can access the DecodeContext::position() method use crate::rustc_middle::ty::codec::TyDecoder; - let len = d.read_usize()?; + let len = d.read_usize(); let pos = d.position(); let o = OwningRef::new(d.blob().clone()).map(|x| &x[pos..pos + len]); @@ -52,7 +52,9 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for DefPathHashMapRef<'static> // the method. We use read_raw_bytes() for that. let _ = d.read_raw_bytes(len); - let inner = odht::HashTable::from_raw_bytes(o).map_err(|e| format!("{}", e))?; - Ok(DefPathHashMapRef::OwnedFromMetadata(inner)) + let inner = odht::HashTable::from_raw_bytes(o).unwrap_or_else(|e| { + panic!("decode error: {}", e); + }); + DefPathHashMapRef::OwnedFromMetadata(inner) } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 0dbef66ac37..3fae652ee2e 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -11,13 +11,13 @@ use rustc_hir::def_id::{ CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE, }; use rustc_hir::definitions::DefPathData; -use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; +use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::lang_items; use rustc_hir::{AnonConst, GenericParamKind}; use rustc_index::bit_set::GrowableBitSet; use rustc_index::vec::Idx; -use rustc_middle::hir::map::Map; +use rustc_middle::hir::nested_filter; use rustc_middle::middle::dependency_format::Linkage; use rustc_middle::middle::exported_symbols::{ metadata_symbol_name, ExportedSymbol, SymbolExportLevel, @@ -26,6 +26,8 @@ use rustc_middle::mir::interpret; use rustc_middle::thir; use rustc_middle::traits::specialization_graph; use rustc_middle::ty::codec::TyEncoder; +use rustc_middle::ty::fast_reject::{self, SimplifiedType, SimplifyParams, StripReferences}; +use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt}; use rustc_serialize::{opaque, Encodable, Encoder}; use rustc_session::config::CrateType; @@ -402,24 +404,24 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { &mut self, lazy: Lazy<T>, ) -> Result<(), <Self as Encoder>::Error> { - let min_end = lazy.position.get() + T::min_size(lazy.meta); + let pos = lazy.position.get(); let distance = match self.lazy_state { LazyState::NoNode => bug!("emit_lazy_distance: outside of a metadata node"), LazyState::NodeStart(start) => { let start = start.get(); - assert!(min_end <= start); - start - min_end + assert!(pos <= start); + start - pos } - LazyState::Previous(last_min_end) => { + LazyState::Previous(last_pos) => { assert!( - last_min_end <= lazy.position, + last_pos <= lazy.position, "make sure that the calls to `lazy*` \ are in the same order as the metadata fields", ); - lazy.position.get() - last_min_end.get() + lazy.position.get() - last_pos.get() } }; - self.lazy_state = LazyState::Previous(NonZeroUsize::new(min_end).unwrap()); + self.lazy_state = LazyState::Previous(NonZeroUsize::new(pos).unwrap()); self.emit_usize(distance) } @@ -434,7 +436,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let meta = value.encode_contents_for_lazy(self); self.lazy_state = LazyState::NoNode; - assert!(pos.get() + <T>::min_size(meta) <= self.position()); + assert!(pos.get() <= self.position()); Lazy::from_position_and_meta(pos, meta) } @@ -611,10 +613,15 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.encode_def_path_table(); let def_path_table_bytes = self.position() - i; + // Encode the def IDs of traits, for rustdoc and diagnostics. + i = self.position(); + let traits = self.encode_traits(); + let traits_bytes = self.position() - i; + // Encode the def IDs of impls, for coherence checking. i = self.position(); let impls = self.encode_impls(); - let impl_bytes = self.position() - i; + let impls_bytes = self.position() - i; let tcx = self.tcx; @@ -714,7 +721,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { 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.debugging_opts.get_symbol_mangling_version(), + symbol_mangling_version: tcx.sess.opts.get_symbol_mangling_version(), crate_deps, dylib_dependency_formats, @@ -725,6 +732,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { native_libraries, foreign_modules, source_map, + traits, impls, exported_symbols, interpret_alloc_index, @@ -752,7 +760,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { eprintln!(" diagnostic item bytes: {}", diagnostic_item_bytes); eprintln!(" native bytes: {}", native_lib_bytes); eprintln!(" source_map bytes: {}", source_map_bytes); - eprintln!(" impl bytes: {}", impl_bytes); + eprintln!(" traits bytes: {}", traits_bytes); + eprintln!(" impls bytes: {}", impls_bytes); eprintln!(" exp. symbols bytes: {}", exported_symbols_bytes); eprintln!(" def-path table bytes: {}", def_path_table_bytes); eprintln!(" def-path hashes bytes: {}", def_path_hash_map_bytes); @@ -797,6 +806,7 @@ fn should_encode_visibility(def_kind: DefKind) -> bool { | DefKind::ConstParam | DefKind::LifetimeParam | DefKind::AnonConst + | DefKind::InlineConst | DefKind::GlobalAsm | DefKind::Closure | DefKind::Generator @@ -832,6 +842,7 @@ fn should_encode_stability(def_kind: DefKind) -> bool { DefKind::Use | DefKind::LifetimeParam | DefKind::AnonConst + | DefKind::InlineConst | DefKind::GlobalAsm | DefKind::Closure | DefKind::Generator @@ -856,17 +867,20 @@ fn should_encode_mir(tcx: TyCtxt<'_>, def_id: LocalDefId) -> (bool, bool) { (true, mir_opt_base) } // Constants - DefKind::AnonConst | DefKind::AssocConst | DefKind::Static | DefKind::Const => { - (true, false) - } + DefKind::AnonConst + | DefKind::InlineConst + | DefKind::AssocConst + | DefKind::Static + | DefKind::Const => (true, false), // Full-fledged functions DefKind::AssocFn | DefKind::Fn => { let generics = tcx.generics_of(def_id); let needs_inline = (generics.requires_monomorphization(tcx) || tcx.codegen_fn_attrs(def_id).requests_inline()) && tcx.sess.opts.output_types.should_codegen(); - // Only check the presence of the `const` modifier. - let is_const_fn = tcx.is_const_fn_raw(def_id.to_def_id()); + // The function has a `const` modifier or is annotated with `default_method_body_is_const`. + let is_const_fn = tcx.is_const_fn_raw(def_id.to_def_id()) + || tcx.has_attr(def_id.to_def_id(), sym::default_method_body_is_const); let always_encode_mir = tcx.sess.opts.debugging_opts.always_encode_mir; (is_const_fn, needs_inline || always_encode_mir) } @@ -914,6 +928,7 @@ fn should_encode_variances(def_kind: DefKind) -> bool { | DefKind::Use | DefKind::LifetimeParam | DefKind::AnonConst + | DefKind::InlineConst | DefKind::GlobalAsm | DefKind::Closure | DefKind::Generator @@ -939,6 +954,7 @@ fn should_encode_generics(def_kind: DefKind) -> bool { | DefKind::AssocFn | DefKind::AssocConst | DefKind::AnonConst + | DefKind::InlineConst | DefKind::OpaqueTy | DefKind::Impl | DefKind::Field @@ -956,7 +972,7 @@ fn should_encode_generics(def_kind: DefKind) -> bool { } } -impl EncodeContext<'a, 'tcx> { +impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_def_ids(&mut self) { if self.is_proc_macro { return; @@ -1036,7 +1052,7 @@ impl EncodeContext<'a, 'tcx> { assert!(f.did.is_local()); f.did.index })); - self.encode_ident_span(def_id, variant.ident); + self.encode_ident_span(def_id, variant.ident(tcx)); self.encode_item_type(def_id); if variant.ctor_kind == CtorKind::Fn { // FIXME(eddyb) encode signature only in `encode_enum_variant_ctor`. @@ -1078,7 +1094,7 @@ impl EncodeContext<'a, 'tcx> { // code uses it). However, we skip encoding anything relating to child // items - we encode information about proc-macros later on. let reexports = if !self.is_proc_macro { - match tcx.module_exports(local_def_id) { + match tcx.module_reexports(local_def_id) { Some(exports) => self.lazy(exports), _ => Lazy::empty(), } @@ -1088,13 +1104,24 @@ impl EncodeContext<'a, 'tcx> { record!(self.tables.kind[def_id] <- EntryKind::Mod(reexports)); if self.is_proc_macro { - record!(self.tables.children[def_id] <- &[]); // 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!(self.tables.children[def_id] <- md.item_ids.iter().map(|item_id| { - item_id.def_id.local_def_index - })); + let direct_children = md.item_ids.iter().map(|item_id| item_id.def_id.local_def_index); + // Foreign items are planted into their parent modules from name resolution point of view. + let tcx = self.tcx; + let foreign_item_children = md + .item_ids + .iter() + .filter_map(|item_id| match tcx.hir().item(*item_id).kind { + hir::ItemKind::ForeignMod { items, .. } => { + Some(items.iter().map(|fi_ref| fi_ref.id.def_id.local_def_index)) + } + _ => None, + }) + .flatten(); + + record!(self.tables.children[def_id] <- direct_children.chain(foreign_item_children)); } } @@ -1111,7 +1138,7 @@ impl EncodeContext<'a, 'tcx> { debug!("EncodeContext::encode_field({:?})", def_id); record!(self.tables.kind[def_id] <- EntryKind::Field); - self.encode_ident_span(def_id, field.ident); + self.encode_ident_span(def_id, field.ident(self.tcx)); self.encode_item_type(def_id); } @@ -1146,8 +1173,7 @@ impl EncodeContext<'a, 'tcx> { debug!("EncodeContext::encode_info_for_trait_item({:?})", def_id); let tcx = self.tcx; - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); - let ast_item = tcx.hir().expect_trait_item(hir_id); + let ast_item = tcx.hir().expect_trait_item(def_id.expect_local()); let trait_item = tcx.associated_item(def_id); let container = match trait_item.defaultness { @@ -1215,8 +1241,7 @@ impl EncodeContext<'a, 'tcx> { debug!("EncodeContext::encode_info_for_impl_item({:?})", def_id); let tcx = self.tcx; - let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); - let ast_item = self.tcx.hir().expect_impl_item(hir_id); + let ast_item = self.tcx.hir().expect_impl_item(def_id.expect_local()); let impl_item = self.tcx.associated_item(def_id); let container = match impl_item.defaultness { @@ -1266,8 +1291,11 @@ impl EncodeContext<'a, 'tcx> { record!(self.tables.kind[def_id] <- EntryKind::AssocType(container)); } } - self.encode_ident_span(def_id, impl_item.ident); + self.encode_ident_span(def_id, impl_item.ident(self.tcx)); self.encode_item_type(def_id); + if let Some(trait_item_def_id) = impl_item.trait_item_def_id { + record!(self.tables.trait_item_def_id[def_id] <- trait_item_def_id); + } if impl_item.kind == ty::AssocKind::Fn { record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id)); } @@ -1286,7 +1314,7 @@ impl EncodeContext<'a, 'tcx> { return; } - let mut keys_and_jobs = self + let keys_and_jobs = self .tcx .mir_keys(()) .iter() @@ -1299,8 +1327,6 @@ impl EncodeContext<'a, 'tcx> { } }) .collect::<Vec<_>>(); - // Sort everything to ensure a stable order for diagnotics. - keys_and_jobs.sort_by_key(|&(def_id, _, _)| def_id); for (def_id, encode_const, encode_opt) in keys_and_jobs.into_iter() { debug_assert!(encode_const || encode_opt); @@ -1485,6 +1511,7 @@ impl EncodeContext<'a, 'tcx> { is_marker: trait_def.is_marker, skip_array_during_method_dispatch: trait_def.skip_array_during_method_dispatch, specialization_kind: trait_def.specialization_kind, + must_implement_one_of: trait_def.must_implement_one_of.clone(), }; EntryKind::Trait(self.lazy(data)) @@ -1497,11 +1524,6 @@ impl EncodeContext<'a, 'tcx> { record!(self.tables.kind[def_id] <- entry_kind); // FIXME(eddyb) there should be a nicer way to do this. match item.kind { - hir::ItemKind::ForeignMod { items, .. } => record!(self.tables.children[def_id] <- - items - .iter() - .map(|foreign_item| foreign_item.id.def_id.local_def_index) - ), hir::ItemKind::Enum(..) => record!(self.tables.children[def_id] <- self.tcx.adt_def(def_id).variants.iter().map(|v| { assert!(v.def_id.is_local()); @@ -1556,12 +1578,12 @@ impl EncodeContext<'a, 'tcx> { } } - fn encode_info_for_closure(&mut self, def_id: LocalDefId) { + fn encode_info_for_closure(&mut self, hir_id: hir::HirId) { + let def_id = self.tcx.hir().local_def_id(hir_id); debug!("EncodeContext::encode_info_for_closure({:?})", def_id); // NOTE(eddyb) `tcx.type_of(def_id)` isn't used because it's fully generic, // including on the signature, which is inferred in `typeck. - let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); let ty = self.tcx.typeck(def_id).node_type(hir_id); match ty.kind() { @@ -1582,9 +1604,9 @@ impl EncodeContext<'a, 'tcx> { } } - fn encode_info_for_anon_const(&mut self, def_id: LocalDefId) { + fn encode_info_for_anon_const(&mut self, id: hir::HirId) { + let def_id = self.tcx.hir().local_def_id(id); debug!("EncodeContext::encode_info_for_anon_const({:?})", def_id); - let id = self.tcx.hir().local_def_id_to_hir_id(def_id); let body_id = self.tcx.hir().body_owned_by(id); let const_data = self.encode_rendered_const_for_body(body_id); let qualifs = self.tcx.mir_const_qualif(def_id); @@ -1745,7 +1767,7 @@ impl EncodeContext<'a, 'tcx> { fn encode_lib_features(&mut self) -> Lazy<[(Symbol, Option<Symbol>)]> { empty_proc_macro!(self); let tcx = self.tcx; - let lib_features = tcx.lib_features(); + let lib_features = tcx.lib_features(()); self.lazy(lib_features.to_vec()) } @@ -1777,12 +1799,17 @@ impl EncodeContext<'a, 'tcx> { self.lazy(&tcx.lang_items().missing) } + fn encode_traits(&mut self) -> Lazy<[DefIndex]> { + empty_proc_macro!(self); + self.lazy(self.tcx.traits_in_crate(LOCAL_CRATE).iter().map(|def_id| def_id.index)) + } + /// Encodes an index, mapping each trait to its (local) implementations. fn encode_impls(&mut self) -> Lazy<[TraitImpls]> { + debug!("EncodeContext::encode_traits_and_impls()"); empty_proc_macro!(self); - debug!("EncodeContext::encode_impls()"); let tcx = self.tcx; - let mut visitor = ImplVisitor { tcx, impls: FxHashMap::default() }; + let mut visitor = ImplsVisitor { tcx, impls: FxHashMap::default() }; tcx.hir().visit_all_item_likes(&mut visitor); let mut all_impls: Vec<_> = visitor.impls.into_iter().collect(); @@ -1888,11 +1915,11 @@ impl EncodeContext<'a, 'tcx> { } // FIXME(eddyb) make metadata encoding walk over all definitions, instead of HIR. -impl Visitor<'tcx> for EncodeContext<'a, 'tcx> { - type Map = Map<'tcx>; +impl<'a, 'tcx> Visitor<'tcx> for EncodeContext<'a, 'tcx> { + type NestedFilter = nested_filter::OnlyBodies; - fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { - NestedVisitorMap::OnlyBodies(self.tcx.hir()) + fn nested_visit_map(&mut self) -> Self::Map { + self.tcx.hir() } fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) { intravisit::walk_expr(self, ex); @@ -1900,8 +1927,7 @@ impl Visitor<'tcx> for EncodeContext<'a, 'tcx> { } fn visit_anon_const(&mut self, c: &'tcx AnonConst) { intravisit::walk_anon_const(self, c); - let def_id = self.tcx.hir().local_def_id(c.hir_id); - self.encode_info_for_anon_const(def_id); + self.encode_info_for_anon_const(c.hir_id); } fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { intravisit::walk_item(self, item); @@ -1921,7 +1947,7 @@ impl Visitor<'tcx> for EncodeContext<'a, 'tcx> { } } -impl EncodeContext<'a, 'tcx> { +impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_fields(&mut self, adt_def: &ty::AdtDef) { for (variant_index, variant) in adt_def.variants.iter_enumerated() { for (field_index, _field) in variant.fields.iter().enumerate() { @@ -1955,8 +1981,7 @@ impl EncodeContext<'a, 'tcx> { fn encode_info_for_expr(&mut self, expr: &hir::Expr<'_>) { if let hir::ExprKind::Closure(..) = expr.kind { - let def_id = self.tcx.hir().local_def_id(expr.hir_id); - self.encode_info_for_closure(def_id); + self.encode_info_for_closure(expr.hir_id); } } @@ -2027,23 +2052,30 @@ impl EncodeContext<'a, 'tcx> { } } -struct ImplVisitor<'tcx> { +struct ImplsVisitor<'tcx> { tcx: TyCtxt<'tcx>, - impls: FxHashMap<DefId, Vec<(DefIndex, Option<ty::fast_reject::SimplifiedType>)>>, + impls: FxHashMap<DefId, Vec<(DefIndex, Option<SimplifiedType>)>>, } -impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'tcx> { +impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplsVisitor<'tcx> { fn visit_item(&mut self, item: &hir::Item<'_>) { - if let hir::ItemKind::Impl { .. } = item.kind { - if let Some(trait_ref) = self.tcx.impl_trait_ref(item.def_id.to_def_id()) { - let simplified_self_ty = - ty::fast_reject::simplify_type(self.tcx, trait_ref.self_ty(), false); + match item.kind { + hir::ItemKind::Impl(..) => { + if let Some(trait_ref) = self.tcx.impl_trait_ref(item.def_id.to_def_id()) { + let simplified_self_ty = fast_reject::simplify_type( + self.tcx, + trait_ref.self_ty(), + SimplifyParams::No, + StripReferences::No, + ); - self.impls - .entry(trait_ref.def_id) - .or_default() - .push((item.def_id.local_def_index, simplified_self_ty)); + self.impls + .entry(trait_ref.def_id) + .or_default() + .push((item.def_id.local_def_index, simplified_self_ty)); + } } + _ => {} } } @@ -2115,7 +2147,7 @@ impl EncodedMetadata { #[inline] pub fn raw_data(&self) -> &[u8] { - &self.raw_data[..] + &self.raw_data } } @@ -2187,5 +2219,39 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>) -> EncodedMetadata { result[header + 2] = (pos >> 8) as u8; result[header + 3] = (pos >> 0) as u8; + // Record metadata size for self-profiling + tcx.prof.artifact_size("crate_metadata", "crate_metadata", result.len() as u64); + EncodedMetadata { raw_data: result } } + +pub fn provide(providers: &mut Providers) { + *providers = Providers { + traits_in_crate: |tcx, cnum| { + assert_eq!(cnum, LOCAL_CRATE); + + #[derive(Default)] + struct TraitsVisitor { + traits: Vec<DefId>, + } + impl ItemLikeVisitor<'_> for TraitsVisitor { + fn visit_item(&mut self, item: &hir::Item<'_>) { + if let hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) = item.kind { + self.traits.push(item.def_id.to_def_id()); + } + } + fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {} + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {} + fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {} + } + + let mut visitor = TraitsVisitor::default(); + tcx.hir().visit_all_item_likes(&mut visitor); + // Bring everything into deterministic order. + visitor.traits.sort_by_cached_key(|&def_id| tcx.def_path_hash(def_id)); + tcx.arena.alloc_slice(&visitor.traits) + }, + + ..*providers + }; +} diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 4e09d23169a..8424a31d59f 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -12,10 +12,12 @@ use rustc_hir::def_id::{DefId, DefIndex, DefPathHash, StableCrateId}; use rustc_hir::definitions::DefKey; use rustc_hir::lang_items; use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec}; -use rustc_middle::hir::exports::Export; +use rustc_middle::metadata::ModChild; use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; use rustc_middle::mir; use rustc_middle::thir; +use rustc_middle::ty::fast_reject::SimplifiedType; +use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, ReprOptions, Ty}; use rustc_serialize::opaque::Encoder; use rustc_session::config::SymbolManglingVersion; @@ -29,8 +31,8 @@ use rustc_target::spec::{PanicStrategy, TargetTriple}; use std::marker::PhantomData; use std::num::NonZeroUsize; +pub use decoder::provide_extern; use decoder::DecodeContext; -pub use decoder::{provide, provide_extern}; crate use decoder::{CrateMetadata, CrateNumMap, MetadataBlob}; use encoder::EncodeContext; pub use encoder::{encode_metadata, EncodedMetadata}; @@ -48,7 +50,7 @@ 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 = 5; +const METADATA_VERSION: u8 = 6; /// Metadata header which includes `METADATA_VERSION`. /// @@ -61,27 +63,14 @@ pub const METADATA_HEADER: &[u8] = &[b'r', b'u', b's', b't', 0, 0, 0, METADATA_V /// e.g. for `Lazy<[T]>`, this is the length (count of `T` values). trait LazyMeta { type Meta: Copy + 'static; - - /// Returns the minimum encoded size. - // FIXME(eddyb) Give better estimates for certain types. - fn min_size(meta: Self::Meta) -> usize; } impl<T> LazyMeta for T { type Meta = (); - - fn min_size(_: ()) -> usize { - assert_ne!(std::mem::size_of::<T>(), 0); - 1 - } } impl<T> LazyMeta for [T] { type Meta = usize; - - fn min_size(len: usize) -> usize { - len * T::min_size(()) - } } /// A value of type T referred to by its absolute position @@ -159,8 +148,7 @@ enum LazyState { NodeStart(NonZeroUsize), /// Inside a metadata node, with a previous `Lazy`. - /// The position is a conservative estimate of where that - /// previous `Lazy` would end (see their comments). + /// The position is where that previous `Lazy` would start. Previous(NonZeroUsize), } @@ -222,6 +210,7 @@ crate struct CrateRoot<'tcx> { diagnostic_items: Lazy<[(Symbol, DefIndex)]>, native_libraries: Lazy<[NativeLib]>, foreign_modules: Lazy<[ForeignModule]>, + traits: Lazy<[DefIndex]>, impls: Lazy<[TraitImpls]>, interpret_alloc_index: Lazy<[u32]>, proc_macro_data: Option<ProcMacroData>, @@ -259,7 +248,7 @@ crate struct CrateDep { #[derive(MetadataEncodable, MetadataDecodable)] crate struct TraitImpls { trait_id: (u32, DefIndex), - impls: Lazy<[(DefIndex, Option<ty::fast_reject::SimplifiedType>)]>, + impls: Lazy<[(DefIndex, Option<SimplifiedType>)]>, } /// Define `LazyTables` and `TableBuilders` at the same time. @@ -275,7 +264,7 @@ macro_rules! define_tables { $($name: TableBuilder<$IDX, $T>),+ } - impl TableBuilders<'tcx> { + impl<'tcx> TableBuilders<'tcx> { fn encode(&self, buf: &mut Encoder) -> LazyTables<'tcx> { LazyTables { $($name: self.$name.encode(buf)),+ @@ -299,6 +288,7 @@ define_tables! { ty: Table<DefIndex, Lazy!(Ty<'tcx>)>, fn_sig: Table<DefIndex, Lazy!(ty::PolyFnSig<'tcx>)>, impl_trait_ref: Table<DefIndex, Lazy!(ty::TraitRef<'tcx>)>, + trait_item_def_id: Table<DefIndex, Lazy<DefId>>, inherent_impls: Table<DefIndex, Lazy<[DefIndex]>>, variances: Table<DefIndex, Lazy<[ty::Variance]>>, generics: Table<DefIndex, Lazy<ty::Generics>>, @@ -346,7 +336,7 @@ enum EntryKind { Union(Lazy<VariantData>, ReprOptions), Fn(Lazy<FnData>), ForeignFn(Lazy<FnData>), - Mod(Lazy<[Export]>), + Mod(Lazy<[ModChild]>), MacroDef(Lazy<MacroDef>), ProcMacro(MacroKind), Closure, @@ -388,6 +378,7 @@ struct TraitData { is_marker: bool, skip_array_during_method_dispatch: bool, specialization_kind: ty::trait_def::TraitSpecializationKind, + must_implement_one_of: Option<Box<[Ident]>>, } #[derive(TyEncodable, TyDecodable)] @@ -453,3 +444,8 @@ struct GeneratorData<'tcx> { const TAG_VALID_SPAN_LOCAL: u8 = 0; const TAG_VALID_SPAN_FOREIGN: u8 = 1; const TAG_PARTIAL_SPAN: u8 = 2; + +pub fn provide(providers: &mut Providers) { + encoder::provide(providers); + decoder::provide(providers); +} diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index 4dfefda490b..265ca5a6d8d 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -183,10 +183,6 @@ where Option<T>: FixedSizeEncoding, { type Meta = usize; - - fn min_size(len: usize) -> usize { - len - } } impl<I: Idx, T> Lazy<Table<I, T>> | 
