From de03a12675fe923a02589ce05afec8682194bfef Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 4 Jul 2020 19:01:21 +0300 Subject: [PATCH 1/4] rustc_metadata: Remove a bit of ancient profiling --- src/librustc_metadata/locator.rs | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index 1bdac1039b55a..54ab849bf1a42 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -234,7 +234,6 @@ use std::fs; use std::io::{self, Read}; use std::ops::Deref; use std::path::{Path, PathBuf}; -use std::time::Instant; use flate2::read::DeflateDecoder; @@ -940,19 +939,6 @@ impl<'a> CrateLocator<'a> { } } -// Just a small wrapper to time how long reading metadata takes. -fn get_metadata_section( - target: &Target, - flavor: CrateFlavor, - filename: &Path, - loader: &dyn MetadataLoader, -) -> Result { - let start = Instant::now(); - let ret = get_metadata_section_imp(target, flavor, filename, loader); - info!("reading {:?} => {:?}", filename.file_name().unwrap(), start.elapsed()); - ret -} - /// A trivial wrapper for `Mmap` that implements `StableDeref`. struct StableDerefMmap(memmap::Mmap); @@ -966,7 +952,7 @@ impl Deref for StableDerefMmap { unsafe impl stable_deref_trait::StableDeref for StableDerefMmap {} -fn get_metadata_section_imp( +fn get_metadata_section( target: &Target, flavor: CrateFlavor, filename: &Path, From 926ac5a2fd6cd4a0994b0c7cff5a43040c9c0e4c Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 4 Jul 2020 20:47:06 +0300 Subject: [PATCH 2/4] rustc_metadata: Remove some extra diagnostics for legacy plugins They are deprecated so doing extra work for error recovery doesn't make sense --- src/librustc_error_codes/error_codes.rs | 2 +- src/librustc_metadata/locator.rs | 33 ++----------------------- src/tools/tidy/src/error_codes_check.rs | 10 ++++---- 3 files changed, 8 insertions(+), 37 deletions(-) diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs index 6160450d76676..bbbd8359f0126 100644 --- a/src/librustc_error_codes/error_codes.rs +++ b/src/librustc_error_codes/error_codes.rs @@ -554,7 +554,7 @@ E0770: include_str!("./error_codes/E0770.md"), // E0420, merged into 532 // E0421, merged into 531 // E0427, merged into 530 - E0456, // plugin `..` is not available for triple `..` +// E0456, // plugin `..` is not available for triple `..` E0457, // plugin `..` only found in rlib format, but must be available... E0460, // found possibly newer version of crate `..` E0461, // couldn't find crate `..` with expected target triple .. diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index 54ab849bf1a42..dfdedc9f27538 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -1014,10 +1014,6 @@ pub fn find_plugin_registrar( name: Symbol, ) -> Option<(PathBuf, CrateDisambiguator)> { info!("find plugin registrar `{}`", name); - let target_triple = sess.opts.target_triple.clone(); - let host_triple = TargetTriple::from_triple(config::host_triple()); - let is_cross = target_triple != host_triple; - let mut target_only = false; let mut locator = CrateLocator::new( sess, metadata_loader, @@ -1032,36 +1028,11 @@ pub fn find_plugin_registrar( None, // is_proc_macro ); - let library = locator.maybe_load_library_crate().or_else(|| { - if !is_cross { - return None; - } - // Try loading from target crates. This will abort later if we - // try to load a plugin registrar function, - target_only = true; - - locator.target = &sess.target.target; - locator.triple = target_triple; - locator.filesearch = sess.target_filesearch(PathKind::Crate); - - locator.maybe_load_library_crate() - }); - let library = match library { - Some(l) => l, + let library = match locator.maybe_load_library_crate() { + Some(library) => library, None => locator.report_errs(), }; - if target_only { - let message = format!( - "plugin `{}` is not available for triple `{}` (only found {})", - name, - config::host_triple(), - sess.opts.target_triple - ); - struct_span_err!(sess, span, E0456, "{}", &message).emit(); - return None; - } - match library.source.dylib { Some(dylib) => Some((dylib.0, library.metadata.get_root().disambiguator())), None => { diff --git a/src/tools/tidy/src/error_codes_check.rs b/src/tools/tidy/src/error_codes_check.rs index 3af71f69d2457..51f135d376161 100644 --- a/src/tools/tidy/src/error_codes_check.rs +++ b/src/tools/tidy/src/error_codes_check.rs @@ -8,11 +8,11 @@ use std::path::Path; // A few of those error codes can't be tested but all the others can and *should* be tested! const EXEMPTED_FROM_TEST: &[&str] = &[ - "E0183", "E0227", "E0279", "E0280", "E0311", "E0313", "E0314", "E0315", "E0377", "E0456", - "E0461", "E0462", "E0464", "E0465", "E0472", "E0473", "E0474", "E0475", "E0476", "E0479", - "E0480", "E0481", "E0482", "E0483", "E0484", "E0485", "E0486", "E0487", "E0488", "E0489", - "E0514", "E0519", "E0523", "E0553", "E0554", "E0570", "E0629", "E0630", "E0640", "E0717", - "E0727", "E0729", + "E0183", "E0227", "E0279", "E0280", "E0311", "E0313", "E0314", "E0315", "E0377", "E0461", + "E0462", "E0464", "E0465", "E0472", "E0473", "E0474", "E0475", "E0476", "E0479", "E0480", + "E0481", "E0482", "E0483", "E0484", "E0485", "E0486", "E0487", "E0488", "E0489", "E0514", + "E0519", "E0523", "E0553", "E0554", "E0570", "E0629", "E0630", "E0640", "E0717", "E0727", + "E0729", ]; // Some error codes don't have any tests apparently... From 4044cbc559be2c00a4718a086c3443d429032446 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 4 Jul 2020 21:38:56 +0300 Subject: [PATCH 3/4] rustc_metadata: Refactor away `CrateLocator::(dy,static)libname` --- src/librustc_metadata/locator.rs | 46 +++++++++++++------------------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index dfdedc9f27538..ecb2548c7469f 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -495,7 +495,6 @@ impl<'a> CrateLocator<'a> { }; if !self.rejected_via_filename.is_empty() { - let dylibname = self.dylibname(); let mismatches = self.rejected_via_filename.iter(); for &CrateMismatch { ref path, .. } in mismatches { err.note(&format!( @@ -505,7 +504,7 @@ impl<'a> CrateLocator<'a> { )) .help(&format!( "file name should be lib*.rlib or {}*.{}", - dylibname.0, dylibname.1 + self.target.options.dll_prefix, self.target.options.dll_suffix )); } } @@ -520,13 +519,12 @@ impl<'a> CrateLocator<'a> { extra_prefix: &str, seen_paths: &mut FxHashSet, ) -> Option { - let dypair = self.dylibname(); - let staticpair = self.staticlibname(); - // want: crate_name.dir_part() + prefix + crate_name.file_part + "-" - let dylib_prefix = format!("{}{}{}", dypair.0, self.crate_name, extra_prefix); + let dylib_prefix = + format!("{}{}{}", self.target.options.dll_prefix, self.crate_name, extra_prefix); let rlib_prefix = format!("lib{}{}", self.crate_name, extra_prefix); - let staticlib_prefix = format!("{}{}{}", staticpair.0, self.crate_name, extra_prefix); + let staticlib_prefix = + format!("{}{}{}", self.target.options.staticlib_prefix, self.crate_name, extra_prefix); let mut candidates: FxHashMap<_, (FxHashMap<_, _>, FxHashMap<_, _>, FxHashMap<_, _>)> = Default::default(); @@ -554,10 +552,18 @@ impl<'a> CrateLocator<'a> { (&file[(rlib_prefix.len())..(file.len() - ".rlib".len())], CrateFlavor::Rlib) } else if file.starts_with(&rlib_prefix) && file.ends_with(".rmeta") { (&file[(rlib_prefix.len())..(file.len() - ".rmeta".len())], CrateFlavor::Rmeta) - } else if file.starts_with(&dylib_prefix) && file.ends_with(&dypair.1) { - (&file[(dylib_prefix.len())..(file.len() - dypair.1.len())], CrateFlavor::Dylib) + } else if file.starts_with(&dylib_prefix) + && file.ends_with(&self.target.options.dll_suffix) + { + ( + &file + [(dylib_prefix.len())..(file.len() - self.target.options.dll_suffix.len())], + CrateFlavor::Dylib, + ) } else { - if file.starts_with(&staticlib_prefix) && file.ends_with(&staticpair.1) { + if file.starts_with(&staticlib_prefix) + && file.ends_with(&self.target.options.staticlib_suffix) + { staticlibs .push(CrateMismatch { path: spf.path.clone(), got: "static".to_string() }); } @@ -859,32 +865,19 @@ impl<'a> CrateLocator<'a> { Some(hash) } - // Returns the corresponding (prefix, suffix) that files need to have for - // dynamic libraries - fn dylibname(&self) -> (String, String) { - let t = &self.target; - (t.options.dll_prefix.clone(), t.options.dll_suffix.clone()) - } - - // Returns the corresponding (prefix, suffix) that files need to have for - // static libraries - fn staticlibname(&self) -> (String, String) { - let t = &self.target; - (t.options.staticlib_prefix.clone(), t.options.staticlib_suffix.clone()) - } - fn find_commandline_library(&mut self) -> Option { // First, filter out all libraries that look suspicious. We only accept // files which actually exist that have the correct naming scheme for // rlibs/dylibs. let sess = self.sess; - let dylibname = self.dylibname(); let mut rlibs = FxHashMap::default(); let mut rmetas = FxHashMap::default(); let mut dylibs = FxHashMap::default(); { let crate_name = self.crate_name; let rejected_via_filename = &mut self.rejected_via_filename; + let dll_prefix = &self.target.options.dll_prefix; + let dll_suffix = &self.target.options.dll_suffix; let locs = self.exact_paths.iter().filter(|loc| { if !loc.exists() { sess.err(&format!( @@ -909,8 +902,7 @@ impl<'a> CrateLocator<'a> { { return true; } else { - let (ref prefix, ref suffix) = dylibname; - if file.starts_with(&prefix[..]) && file.ends_with(&suffix[..]) { + if file.starts_with(dll_prefix) && file.ends_with(dll_suffix) { return true; } } From 0a4217d09f41d64f8be076c26d16d3474ca66c03 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 5 Jul 2020 10:39:15 +0300 Subject: [PATCH 4/4] rustc_metadata: Make crate loading fully speculative --- src/librustc_metadata/creader.rs | 183 ++--- src/librustc_metadata/locator.rs | 673 ++++++++++-------- src/librustc_plugin_impl/load.rs | 12 +- src/librustc_resolve/diagnostics.rs | 4 +- src/librustc_resolve/late/diagnostics.rs | 9 +- src/librustc_resolve/lib.rs | 2 +- src/test/compile-fail/empty-extern-arg.rs | 2 +- src/test/ui-fulldeps/macro-crate-rlib.rs | 4 +- src/test/ui-fulldeps/macro-crate-rlib.stderr | 12 +- .../extern/extern-prelude-no-speculative.rs | 2 +- .../crate_name_nonascii_forbidden-1.rs | 1 - .../crate_name_nonascii_forbidden-1.stderr | 9 +- .../crate_name_nonascii_forbidden-2.rs | 2 - .../crate_name_nonascii_forbidden-2.stderr | 9 +- 14 files changed, 453 insertions(+), 471 deletions(-) diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 0563894e6348d..0d2101cb2cb08 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -1,6 +1,7 @@ //! Validates all used crates and extern libraries and loads their metadata -use crate::locator::{CrateLocator, CratePaths}; +use crate::dynamic_lib::DynamicLibrary; +use crate::locator::{CrateError, CrateLocator, CratePaths}; use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob}; use rustc_ast::expand::allocator::{global_allocator_spans, AllocatorKind}; @@ -8,15 +9,12 @@ use rustc_ast::{ast, attr}; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::Lrc; -use rustc_errors::struct_span_err; use rustc_expand::base::SyntaxExtension; use rustc_hir::def_id::{CrateNum, LocalDefId, LOCAL_CRATE}; use rustc_hir::definitions::Definitions; use rustc_index::vec::IndexVec; -use rustc_middle::middle::cstore::DepKind; -use rustc_middle::middle::cstore::{ - CrateSource, ExternCrate, ExternCrateSource, MetadataLoaderDyn, -}; +use rustc_middle::middle::cstore::{CrateSource, DepKind, ExternCrate}; +use rustc_middle::middle::cstore::{ExternCrateSource, MetadataLoaderDyn}; use rustc_middle::ty::TyCtxt; use rustc_session::config::{self, CrateType, ExternLocation}; use rustc_session::lint; @@ -31,7 +29,7 @@ use rustc_target::spec::{PanicStrategy, TargetTriple}; use log::{debug, info, log_enabled}; use proc_macro::bridge::client::ProcMacro; use std::path::Path; -use std::{cmp, fs}; +use std::{cmp, env, fs}; #[derive(Clone)] pub struct CStore { @@ -69,18 +67,6 @@ enum LoadResult { Loaded(Library), } -enum LoadError<'a> { - LocatorError(CrateLocator<'a>), -} - -impl<'a> LoadError<'a> { - fn report(self) -> ! { - match self { - LoadError::LocatorError(locator) => locator.report_errs(), - } - } -} - /// A reference to `CrateMetadata` that can also give access to whole crate store when necessary. #[derive(Clone, Copy)] crate struct CrateMetadataRef<'a> { @@ -280,60 +266,43 @@ impl<'a> CrateLoader<'a> { ret } - fn verify_no_symbol_conflicts(&self, span: Span, root: &CrateRoot<'_>) { + fn verify_no_symbol_conflicts(&self, root: &CrateRoot<'_>) -> Result<(), CrateError> { // Check for (potential) conflicts with the local crate if self.local_crate_name == root.name() && self.sess.local_crate_disambiguator() == root.disambiguator() { - struct_span_err!( - self.sess, - span, - E0519, - "the current crate is indistinguishable from one of its \ - dependencies: it has the same crate-name `{}` and was \ - compiled with the same `-C metadata` arguments. This \ - will result in symbol conflicts between the two.", - root.name() - ) - .emit() + return Err(CrateError::SymbolConflictsCurrent(root.name())); } // Check for conflicts with any crate loaded so far + let mut res = Ok(()); self.cstore.iter_crate_data(|_, other| { if other.name() == root.name() && // same crate-name - other.disambiguator() == root.disambiguator() && // same crate-disambiguator + other.disambiguator() == root.disambiguator() && // same crate-disambiguator other.hash() != root.hash() { // but different SVH - struct_span_err!( - self.sess, - span, - E0523, - "found two different crates with name `{}` that are \ - not distinguished by differing `-C metadata`. This \ - will result in symbol conflicts between the two.", - root.name() - ) - .emit(); + res = Err(CrateError::SymbolConflictsOthers(root.name())); } }); + + res } fn register_crate( &mut self, host_lib: Option, root: Option<&CratePaths>, - span: Span, lib: Library, dep_kind: DepKind, name: Symbol, - ) -> CrateNum { + ) -> Result { let _prof_timer = self.sess.prof.generic_activity("metadata_register_crate"); let Library { source, metadata } = lib; let crate_root = metadata.get_root(); let host_hash = host_lib.as_ref().map(|lib| lib.metadata.get_root().hash()); - self.verify_no_symbol_conflicts(span, &crate_root); + self.verify_no_symbol_conflicts(&crate_root)?; let private_dep = self.sess.opts.externs.get(&name.as_str()).map(|e| e.is_private_dep).unwrap_or(false); @@ -353,7 +322,7 @@ impl<'a> CrateLoader<'a> { &crate_paths }; - let cnum_map = self.resolve_crate_deps(root, &crate_root, &metadata, cnum, span, dep_kind); + let cnum_map = self.resolve_crate_deps(root, &crate_root, &metadata, cnum, dep_kind)?; let raw_proc_macros = if crate_root.is_proc_macro_crate() { let temp_root; @@ -365,7 +334,7 @@ impl<'a> CrateLoader<'a> { None => (&source, &crate_root), }; let dlsym_dylib = dlsym_source.dylib.as_ref().expect("no dylib for a proc-macro crate"); - Some(self.dlsym_proc_macros(&dlsym_dylib.0, dlsym_root.disambiguator(), span)) + Some(self.dlsym_proc_macros(&dlsym_dylib.0, dlsym_root.disambiguator())?) } else { None }; @@ -386,14 +355,14 @@ impl<'a> CrateLoader<'a> { ), ); - cnum + Ok(cnum) } fn load_proc_macro<'b>( &self, locator: &mut CrateLocator<'b>, path_kind: PathKind, - ) -> Option<(LoadResult, Option)> + ) -> Result)>, CrateError> where 'a: 'b, { @@ -408,8 +377,11 @@ impl<'a> CrateLoader<'a> { let (locator, target_result) = if self.sess.opts.debugging_opts.dual_proc_macros { proc_macro_locator.reset(); let result = match self.load(&mut proc_macro_locator)? { - LoadResult::Previous(cnum) => return Some((LoadResult::Previous(cnum), None)), - LoadResult::Loaded(library) => Some(LoadResult::Loaded(library)), + Some(LoadResult::Previous(cnum)) => { + return Ok(Some((LoadResult::Previous(cnum), None))); + } + Some(LoadResult::Loaded(library)) => Some(LoadResult::Loaded(library)), + None => return Ok(None), }; locator.hash = locator.host_hash; // Use the locator when looking for the host proc macro crate, as that is required @@ -427,9 +399,12 @@ impl<'a> CrateLoader<'a> { locator.triple = TargetTriple::from_triple(config::host_triple()); locator.filesearch = self.sess.host_filesearch(path_kind); - let host_result = self.load(locator)?; + let host_result = match self.load(locator)? { + Some(host_result) => host_result, + None => return Ok(None), + }; - Some(if self.sess.opts.debugging_opts.dual_proc_macros { + Ok(Some(if self.sess.opts.debugging_opts.dual_proc_macros { let host_result = match host_result { LoadResult::Previous(..) => { panic!("host and target proc macros must be loaded in lock-step") @@ -439,7 +414,7 @@ impl<'a> CrateLoader<'a> { (target_result.unwrap(), Some(host_result)) } else { (host_result, None) - }) + })) } fn resolve_crate<'b>( @@ -452,25 +427,20 @@ impl<'a> CrateLoader<'a> { if dep.is_none() { self.used_extern_options.insert(name); } - if !name.as_str().is_ascii() { - self.sess - .struct_span_err( - span, - &format!("cannot load a crate with a non-ascii name `{}`", name,), - ) - .emit(); - } - self.maybe_resolve_crate(name, span, dep_kind, dep).unwrap_or_else(|err| err.report()) + self.maybe_resolve_crate(name, dep_kind, dep) + .unwrap_or_else(|err| err.report(self.sess, span)) } fn maybe_resolve_crate<'b>( &'b mut self, name: Symbol, - span: Span, mut dep_kind: DepKind, dep: Option<(&'b CratePaths, &'b CrateDep)>, - ) -> Result> { + ) -> Result { info!("resolving crate `{}`", name); + if !name.as_str().is_ascii() { + return Err(CrateError::NonAsciiName(name)); + } let (root, hash, host_hash, extra_filename, path_kind) = match dep { Some((root, dep)) => ( Some(root), @@ -494,18 +464,20 @@ impl<'a> CrateLoader<'a> { extra_filename, false, // is_host path_kind, - span, root, Some(false), // is_proc_macro ); - self.load(&mut locator) - .map(|r| (r, None)) - .or_else(|| { + match self.load(&mut locator)? { + Some(res) => (res, None), + None => { dep_kind = DepKind::MacrosOnly; - self.load_proc_macro(&mut locator, path_kind) - }) - .ok_or_else(move || LoadError::LocatorError(locator))? + match self.load_proc_macro(&mut locator, path_kind)? { + Some(res) => res, + None => return Err(locator.into_error()), + } + } + } }; match result { @@ -518,14 +490,17 @@ impl<'a> CrateLoader<'a> { Ok(cnum) } (LoadResult::Loaded(library), host_library) => { - Ok(self.register_crate(host_library, root, span, library, dep_kind, name)) + self.register_crate(host_library, root, library, dep_kind, name) } _ => panic!(), } } - fn load(&self, locator: &mut CrateLocator<'_>) -> Option { - let library = locator.maybe_load_library_crate()?; + fn load(&self, locator: &mut CrateLocator<'_>) -> Result, CrateError> { + let library = match locator.maybe_load_library_crate()? { + Some(library) => library, + None => return Ok(None), + }; // In the case that we're loading a crate, but not matching // against a hash, we could load a crate which has the same hash @@ -536,7 +511,7 @@ impl<'a> CrateLoader<'a> { // don't want to match a host crate against an equivalent target one // already loaded. let root = library.metadata.get_root(); - if locator.triple == self.sess.opts.target_triple { + Ok(Some(if locator.triple == self.sess.opts.target_triple { let mut result = LoadResult::Loaded(library); self.cstore.iter_crate_data(|cnum, data| { if data.name() == root.name() && root.hash() == data.hash() { @@ -545,10 +520,10 @@ impl<'a> CrateLoader<'a> { result = LoadResult::Previous(cnum); } }); - Some(result) + result } else { - Some(LoadResult::Loaded(library)) - } + LoadResult::Loaded(library) + })) } fn update_extern_crate(&self, cnum: CrateNum, extern_crate: ExternCrate) { @@ -569,53 +544,51 @@ impl<'a> CrateLoader<'a> { crate_root: &CrateRoot<'_>, metadata: &MetadataBlob, krate: CrateNum, - span: Span, dep_kind: DepKind, - ) -> CrateNumMap { + ) -> Result { debug!("resolving deps of external crate"); if crate_root.is_proc_macro_crate() { - return CrateNumMap::new(); + return Ok(CrateNumMap::new()); } // The map from crate numbers in the crate we're resolving to local crate numbers. // We map 0 and all other holes in the map to our parent crate. The "additional" // self-dependencies should be harmless. - std::iter::once(krate) - .chain(crate_root.decode_crate_deps(metadata).map(|dep| { - info!( - "resolving dep crate {} hash: `{}` extra filename: `{}`", - dep.name, dep.hash, dep.extra_filename - ); - let dep_kind = match dep_kind { - DepKind::MacrosOnly => DepKind::MacrosOnly, - _ => dep.kind, - }; - self.resolve_crate(dep.name, span, dep_kind, Some((root, &dep))) - })) - .collect() + let deps = crate_root.decode_crate_deps(metadata); + let mut crate_num_map = CrateNumMap::with_capacity(1 + deps.len()); + crate_num_map.push(krate); + for dep in deps { + info!( + "resolving dep crate {} hash: `{}` extra filename: `{}`", + dep.name, dep.hash, dep.extra_filename + ); + let dep_kind = match dep_kind { + DepKind::MacrosOnly => DepKind::MacrosOnly, + _ => dep.kind, + }; + let cnum = self.maybe_resolve_crate(dep.name, dep_kind, Some((root, &dep)))?; + crate_num_map.push(cnum); + } + Ok(crate_num_map) } fn dlsym_proc_macros( &self, path: &Path, disambiguator: CrateDisambiguator, - span: Span, - ) -> &'static [ProcMacro] { - use crate::dynamic_lib::DynamicLibrary; - use std::env; - + ) -> 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(err) => self.sess.span_fatal(span, &err), + Err(s) => return Err(CrateError::DlOpen(s)), }; let sym = self.sess.generate_proc_macro_decls_symbol(disambiguator); let decls = unsafe { let sym = match lib.symbol(&sym) { Ok(f) => f, - Err(err) => self.sess.span_fatal(span, &err), + Err(s) => return Err(CrateError::DlSym(s)), }; *(sym as *const &[ProcMacro]) }; @@ -624,7 +597,7 @@ impl<'a> CrateLoader<'a> { // since the library can make things that will live arbitrarily long. std::mem::forget(lib); - decls + Ok(decls) } fn inject_panic_runtime(&mut self, krate: &ast::Crate) { @@ -952,7 +925,7 @@ impl<'a> CrateLoader<'a> { cnum } - pub fn maybe_process_path_extern(&mut self, name: Symbol, span: Span) -> Option { - self.maybe_resolve_crate(name, span, DepKind::Explicit, None).ok() + pub fn maybe_process_path_extern(&mut self, name: Symbol) -> Option { + self.maybe_resolve_crate(name, DepKind::Explicit, None).ok() } } diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index ecb2548c7469f..371ec4cd91148 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -216,9 +216,10 @@ use crate::creader::Library; use crate::rmeta::{rustc_version, MetadataBlob, METADATA_HEADER}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +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, DiagnosticBuilder}; +use rustc_errors::struct_span_err; use rustc_middle::middle::cstore::{CrateSource, MetadataLoader}; use rustc_session::config::{self, CrateType}; use rustc_session::filesearch::{FileDoesntMatch, FileMatches, FileSearch}; @@ -228,24 +229,12 @@ use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; use rustc_target::spec::{Target, TargetTriple}; -use std::cmp; -use std::fmt; -use std::fs; -use std::io::{self, Read}; -use std::ops::Deref; -use std::path::{Path, PathBuf}; - use flate2::read::DeflateDecoder; - -use rustc_data_structures::owning_ref::OwningRef; - use log::{debug, info, warn}; - -#[derive(Clone)] -struct CrateMismatch { - path: PathBuf, - got: String, -} +use std::io::{Read, Result as IoResult, Write}; +use std::ops::Deref; +use std::path::{Path, PathBuf}; +use std::{cmp, fmt, fs}; #[derive(Clone)] crate struct CrateLocator<'a> { @@ -262,7 +251,6 @@ crate struct CrateLocator<'a> { pub target: &'a Target, pub triple: TargetTriple, pub filesearch: FileSearch<'a>, - span: Span, root: Option<&'a CratePaths>, pub is_proc_macro: Option, @@ -274,6 +262,7 @@ crate struct CrateLocator<'a> { rejected_via_filename: Vec, } +#[derive(Clone)] crate struct CratePaths { name: Symbol, source: CrateSource, @@ -286,7 +275,7 @@ impl CratePaths { } #[derive(Copy, Clone, PartialEq)] -enum CrateFlavor { +crate enum CrateFlavor { Rlib, Rmeta, Dylib, @@ -312,7 +301,6 @@ impl<'a> CrateLocator<'a> { extra_filename: Option<&'a str>, is_host: bool, path_kind: PathKind, - span: Span, root: Option<&'a CratePaths>, is_proc_macro: Option, ) -> CrateLocator<'a> { @@ -348,7 +336,6 @@ impl<'a> CrateLocator<'a> { } else { sess.target_filesearch(path_kind) }, - span, root, is_proc_macro, rejected_via_hash: Vec::new(), @@ -367,158 +354,24 @@ impl<'a> CrateLocator<'a> { self.rejected_via_filename.clear(); } - crate fn maybe_load_library_crate(&mut self) -> Option { + crate fn maybe_load_library_crate(&mut self) -> Result, CrateError> { if !self.exact_paths.is_empty() { return self.find_commandline_library(); } let mut seen_paths = FxHashSet::default(); - match self.extra_filename { - Some(s) => self - .find_library_crate(s, &mut seen_paths) - .or_else(|| self.find_library_crate("", &mut seen_paths)), - None => self.find_library_crate("", &mut seen_paths), - } - } - - crate fn report_errs(self) -> ! { - let add = match self.root { - None => String::new(), - Some(r) => format!(" which `{}` depends on", r.name), - }; - let mut msg = "the following crate versions were found:".to_string(); - let mut err = if !self.rejected_via_hash.is_empty() { - let mut err = struct_span_err!( - self.sess, - self.span, - E0460, - "found possibly newer version of crate `{}`{}", - self.crate_name, - add - ); - err.note("perhaps that crate needs to be recompiled?"); - let mismatches = self.rejected_via_hash.iter(); - for &CrateMismatch { ref path, .. } in mismatches { - msg.push_str(&format!("\ncrate `{}`: {}", self.crate_name, path.display())); - } - match self.root { - None => {} - Some(r) => { - for path in r.source.paths() { - msg.push_str(&format!("\ncrate `{}`: {}", r.name, path.display())); - } - } - } - err.note(&msg); - err - } else if !self.rejected_via_triple.is_empty() { - let mut err = struct_span_err!( - self.sess, - self.span, - E0461, - "couldn't find crate `{}` \ - with expected target triple {}{}", - self.crate_name, - self.triple, - add - ); - let mismatches = self.rejected_via_triple.iter(); - for &CrateMismatch { ref path, ref got } in mismatches { - msg.push_str(&format!( - "\ncrate `{}`, target triple {}: {}", - self.crate_name, - got, - path.display() - )); - } - err.note(&msg); - err - } else if !self.rejected_via_kind.is_empty() { - let mut err = struct_span_err!( - self.sess, - self.span, - E0462, - "found staticlib `{}` instead of rlib or dylib{}", - self.crate_name, - add - ); - err.help("please recompile that crate using --crate-type lib"); - let mismatches = self.rejected_via_kind.iter(); - for &CrateMismatch { ref path, .. } in mismatches { - msg.push_str(&format!("\ncrate `{}`: {}", self.crate_name, path.display())); - } - err.note(&msg); - err - } else if !self.rejected_via_version.is_empty() { - let mut err = struct_span_err!( - self.sess, - self.span, - E0514, - "found crate `{}` compiled by an incompatible version \ - of rustc{}", - self.crate_name, - add - ); - err.help(&format!( - "please recompile that crate using this compiler ({})", - rustc_version() - )); - let mismatches = self.rejected_via_version.iter(); - for &CrateMismatch { ref path, ref got } in mismatches { - msg.push_str(&format!( - "\ncrate `{}` compiled by {}: {}", - self.crate_name, - got, - path.display() - )); - } - err.note(&msg); - err - } else { - let mut err = struct_span_err!( - self.sess, - self.span, - E0463, - "can't find crate for `{}`{}", - self.crate_name, - add - ); - - if (self.crate_name == sym::std || self.crate_name == sym::core) - && self.triple != TargetTriple::from_triple(config::host_triple()) - { - err.note(&format!("the `{}` target may not be installed", self.triple)); - } else if self.crate_name == sym::profiler_builtins { - err.note(&"the compiler may have been built without the profiler runtime"); - } - err.span_label(self.span, "can't find crate"); - err - }; - - if !self.rejected_via_filename.is_empty() { - let mismatches = self.rejected_via_filename.iter(); - for &CrateMismatch { ref path, .. } in mismatches { - err.note(&format!( - "extern location for {} is of an unknown type: {}", - self.crate_name, - path.display() - )) - .help(&format!( - "file name should be lib*.rlib or {}*.{}", - self.target.options.dll_prefix, self.target.options.dll_suffix - )); + if let Some(extra_filename) = self.extra_filename { + if let library @ Some(_) = self.find_library_crate(extra_filename, &mut seen_paths)? { + return Ok(library); } } - - err.emit(); - self.sess.abort_if_errors(); - unreachable!(); + self.find_library_crate("", &mut seen_paths) } fn find_library_crate( &mut self, extra_prefix: &str, seen_paths: &mut FxHashSet, - ) -> Option { + ) -> Result, CrateError> { // want: crate_name.dir_part() + prefix + crate_name.file_part + "-" let dylib_prefix = format!("{}{}{}", self.target.options.dll_prefix, self.crate_name, extra_prefix); @@ -572,9 +425,7 @@ impl<'a> CrateLocator<'a> { info!("lib candidate: {}", spf.path.display()); - let hash_str = hash.to_string(); - let slot = candidates.entry(hash_str).or_default(); - let (ref mut rlibs, ref mut rmetas, ref mut dylibs) = *slot; + let (rlibs, rmetas, dylibs) = candidates.entry(hash.to_string()).or_default(); fs::canonicalize(&spf.path) .map(|p| { if seen_paths.contains(&p) { @@ -582,16 +433,10 @@ impl<'a> CrateLocator<'a> { }; seen_paths.insert(p.clone()); match found_kind { - CrateFlavor::Rlib => { - rlibs.insert(p, kind); - } - CrateFlavor::Rmeta => { - rmetas.insert(p, kind); - } - CrateFlavor::Dylib => { - dylibs.insert(p, kind); - } - } + CrateFlavor::Rlib => rlibs.insert(p, kind), + CrateFlavor::Rmeta => rmetas.insert(p, kind), + CrateFlavor::Dylib => dylibs.insert(p, kind), + }; FileMatches }) .unwrap_or(FileDoesntMatch) @@ -608,7 +453,7 @@ impl<'a> CrateLocator<'a> { // search is being performed for. let mut libraries = FxHashMap::default(); for (_hash, (rlibs, rmetas, dylibs)) in candidates { - if let Some((svh, lib)) = self.extract_lib(rlibs, rmetas, dylibs) { + if let Some((svh, lib)) = self.extract_lib(rlibs, rmetas, dylibs)? { libraries.insert(svh, lib); } } @@ -617,39 +462,9 @@ impl<'a> CrateLocator<'a> { // what we've got and figure out if we found multiple candidates for // libraries or not. match libraries.len() { - 0 => None, - 1 => Some(libraries.into_iter().next().unwrap().1), - _ => { - let mut err = struct_span_err!( - self.sess, - self.span, - E0464, - "multiple matching crates for `{}`", - self.crate_name - ); - let candidates = libraries - .iter() - .filter_map(|(_, lib)| { - let crate_name = &lib.metadata.get_root().name().as_str(); - match &(&lib.source.dylib, &lib.source.rlib) { - &(&Some((ref pd, _)), &Some((ref pr, _))) => Some(format!( - "\ncrate `{}`: {}\n{:>padding$}", - crate_name, - pd.display(), - pr.display(), - padding = 8 + crate_name.len() - )), - &(&Some((ref p, _)), &None) | &(&None, &Some((ref p, _))) => { - Some(format!("\ncrate `{}`: {}", crate_name, p.display())) - } - &(&None, &None) => None, - } - }) - .collect::(); - err.note(&format!("candidates:{}", candidates)); - err.emit(); - None - } + 0 => Ok(None), + 1 => Ok(Some(libraries.into_iter().next().unwrap().1)), + _ => Err(CrateError::MultipleMatchingCrates(self.crate_name, libraries)), } } @@ -658,16 +473,16 @@ impl<'a> CrateLocator<'a> { rlibs: FxHashMap, rmetas: FxHashMap, dylibs: FxHashMap, - ) -> Option<(Svh, Library)> { + ) -> Result, CrateError> { let mut slot = None; // Order here matters, rmeta should come first. See comment in // `extract_one` below. let source = CrateSource { - rmeta: self.extract_one(rmetas, CrateFlavor::Rmeta, &mut slot), - rlib: self.extract_one(rlibs, CrateFlavor::Rlib, &mut slot), - dylib: self.extract_one(dylibs, CrateFlavor::Dylib, &mut slot), + rmeta: self.extract_one(rmetas, CrateFlavor::Rmeta, &mut slot)?, + rlib: self.extract_one(rlibs, CrateFlavor::Rlib, &mut slot)?, + dylib: self.extract_one(dylibs, CrateFlavor::Dylib, &mut slot)?, }; - slot.map(|(svh, metadata)| (svh, Library { source, metadata })) + Ok(slot.map(|(svh, metadata)| (svh, Library { source, metadata }))) } fn needs_crate_flavor(&self, flavor: CrateFlavor) -> bool { @@ -703,10 +518,7 @@ impl<'a> CrateLocator<'a> { m: FxHashMap, flavor: CrateFlavor, slot: &mut Option<(Svh, MetadataBlob)>, - ) -> Option<(PathBuf, PathKind)> { - let mut ret: Option<(PathBuf, PathKind)> = None; - let mut error = 0; - + ) -> Result, CrateError> { // If we are producing an rlib, and we've already loaded metadata, then // we should not attempt to discover further crate sources (unless we're // locating a proc macro; exact logic is in needs_crate_flavor). This means @@ -723,13 +535,14 @@ impl<'a> CrateLocator<'a> { // from the other crate sources. if slot.is_some() { if m.is_empty() || !self.needs_crate_flavor(flavor) { - return None; + return Ok(None); } else if m.len() == 1 { - return Some(m.into_iter().next().unwrap()); + return Ok(Some(m.into_iter().next().unwrap())); } } - let mut err: Option> = None; + let mut ret: Option<(PathBuf, PathKind)> = None; + let mut err_data: Option> = None; for (lib, kind) in m { info!("{} reading metadata from: {}", flavor, lib.display()); let (hash, metadata) = @@ -749,30 +562,18 @@ impl<'a> CrateLocator<'a> { }; // If we see multiple hashes, emit an error about duplicate candidates. if slot.as_ref().map_or(false, |s| s.0 != hash) { - let mut e = struct_span_err!( - self.sess, - self.span, - E0465, - "multiple {} candidates for `{}` found", - flavor, - self.crate_name - ); - e.span_note( - self.span, - &format!(r"candidate #1: {}", ret.as_ref().unwrap().0.display()), - ); - if let Some(ref mut e) = err { - e.emit(); + if let Some(candidates) = err_data { + return Err(CrateError::MultipleCandidates( + self.crate_name, + flavor, + candidates, + )); } - err = Some(e); - error = 1; + err_data = Some(vec![ret.as_ref().unwrap().0.clone()]); *slot = None; } - if error > 0 { - error += 1; - err.as_mut() - .unwrap() - .span_note(self.span, &format!(r"candidate #{}: {}", error, lib.display())); + if let Some(candidates) = &mut err_data { + candidates.push(lib); continue; } @@ -795,7 +596,7 @@ impl<'a> CrateLocator<'a> { // As a result, we favor the sysroot crate here. Note that the // candidates are all canonicalized, so we canonicalize the sysroot // as well. - if let Some((ref prev, _)) = ret { + if let Some((prev, _)) = &ret { let sysroot = &self.sess.sysroot; let sysroot = sysroot.canonicalize().unwrap_or_else(|_| sysroot.to_path_buf()); if prev.starts_with(&sysroot) { @@ -806,11 +607,10 @@ impl<'a> CrateLocator<'a> { ret = Some((lib, kind)); } - if error > 0 { - err.unwrap().emit(); - None + if let Some(candidates) = err_data { + Err(CrateError::MultipleCandidates(self.crate_name, flavor, candidates)) } else { - ret + Ok(ret) } } @@ -865,57 +665,29 @@ impl<'a> CrateLocator<'a> { Some(hash) } - fn find_commandline_library(&mut self) -> Option { + fn find_commandline_library(&mut self) -> Result, CrateError> { // First, filter out all libraries that look suspicious. We only accept // files which actually exist that have the correct naming scheme for // rlibs/dylibs. - let sess = self.sess; let mut rlibs = FxHashMap::default(); let mut rmetas = FxHashMap::default(); let mut dylibs = FxHashMap::default(); - { - let crate_name = self.crate_name; - let rejected_via_filename = &mut self.rejected_via_filename; - let dll_prefix = &self.target.options.dll_prefix; - let dll_suffix = &self.target.options.dll_suffix; - let locs = self.exact_paths.iter().filter(|loc| { - if !loc.exists() { - sess.err(&format!( - "extern location for {} does not exist: {}", - crate_name, - loc.display() - )); - return false; - } - let file = match loc.file_name().and_then(|s| s.to_str()) { - Some(file) => file, - None => { - sess.err(&format!( - "extern location for {} is not a file: {}", - crate_name, - loc.display() - )); - return false; - } - }; - if file.starts_with("lib") && (file.ends_with(".rlib") || file.ends_with(".rmeta")) - { - return true; - } else { - if file.starts_with(dll_prefix) && file.ends_with(dll_suffix) { - return true; - } + for loc in &self.exact_paths { + if !loc.exists() { + return Err(CrateError::ExternLocationNotExist(self.crate_name, loc.clone())); + } + let file = match loc.file_name().and_then(|s| s.to_str()) { + Some(file) => file, + None => { + return Err(CrateError::ExternLocationNotFile(self.crate_name, loc.clone())); } + }; - rejected_via_filename - .push(CrateMismatch { path: (*loc).clone(), got: String::new() }); - - false - }); - - // Now that we have an iterator of good candidates, make sure - // there's at most one rlib and at most one dylib. - for loc in locs { + if file.starts_with("lib") && (file.ends_with(".rlib") || file.ends_with(".rmeta")) + || file.starts_with(&self.target.options.dll_prefix) + && file.ends_with(&self.target.options.dll_suffix) + { + // Make sure there's at most one rlib and at most one dylib. if loc.file_name().unwrap().to_str().unwrap().ends_with(".rlib") { rlibs.insert(fs::canonicalize(&loc).unwrap(), PathKind::ExternFlag); } else if loc.file_name().unwrap().to_str().unwrap().ends_with(".rmeta") { @@ -923,11 +695,29 @@ impl<'a> CrateLocator<'a> { } else { dylibs.insert(fs::canonicalize(&loc).unwrap(), PathKind::ExternFlag); } + } else { + self.rejected_via_filename + .push(CrateMismatch { path: loc.clone(), got: String::new() }); } - }; + } // Extract the dylib/rlib/rmeta triple. - self.extract_lib(rlibs, rmetas, dylibs).map(|(_, lib)| lib) + Ok(self.extract_lib(rlibs, rmetas, dylibs)?.map(|(_, lib)| lib)) + } + + crate fn into_error(self) -> CrateError { + CrateError::LocatorCombined(CombinedLocatorError { + crate_name: self.crate_name, + root: self.root.cloned(), + triple: self.triple, + dll_prefix: self.target.options.dll_prefix.clone(), + dll_suffix: self.target.options.dll_suffix.clone(), + rejected_via_hash: self.rejected_via_hash, + rejected_via_triple: self.rejected_via_triple, + rejected_via_kind: self.rejected_via_kind, + rejected_via_version: self.rejected_via_version, + rejected_via_filename: self.rejected_via_filename, + }) } } @@ -1004,7 +794,18 @@ pub fn find_plugin_registrar( metadata_loader: &dyn MetadataLoader, span: Span, name: Symbol, -) -> Option<(PathBuf, CrateDisambiguator)> { +) -> (PathBuf, CrateDisambiguator) { + match find_plugin_registrar_impl(sess, metadata_loader, name) { + Ok(res) => res, + Err(err) => err.report(sess, span), + } +} + +fn find_plugin_registrar_impl<'a>( + sess: &'a Session, + metadata_loader: &dyn MetadataLoader, + name: Symbol, +) -> Result<(PathBuf, CrateDisambiguator), CrateError> { info!("find plugin registrar `{}`", name); let mut locator = CrateLocator::new( sess, @@ -1015,32 +816,16 @@ pub fn find_plugin_registrar( None, // extra_filename true, // is_host PathKind::Crate, - span, None, // root None, // is_proc_macro ); - let library = match locator.maybe_load_library_crate() { - Some(library) => library, - None => locator.report_errs(), - }; - - match library.source.dylib { - Some(dylib) => Some((dylib.0, library.metadata.get_root().disambiguator())), - None => { - struct_span_err!( - sess, - span, - E0457, - "plugin `{}` only found in rlib format, but must be available \ - in dylib format", - name - ) - .emit(); - // No need to abort because the loading code will just ignore this - // empty dylib. - None - } + match locator.maybe_load_library_crate()? { + Some(library) => match library.source.dylib { + Some(dylib) => Ok((dylib.0, library.metadata.get_root().disambiguator())), + None => Err(CrateError::NonDylibPlugin(name)), + }, + None => Err(locator.into_error()), } } @@ -1049,8 +834,8 @@ pub fn list_file_metadata( target: &Target, path: &Path, metadata_loader: &dyn MetadataLoader, - out: &mut dyn io::Write, -) -> io::Result<()> { + out: &mut dyn Write, +) -> IoResult<()> { let filename = path.file_name().unwrap().to_str().unwrap(); let flavor = if filename.ends_with(".rlib") { CrateFlavor::Rlib @@ -1064,3 +849,259 @@ pub fn list_file_metadata( Err(msg) => write!(out, "{}\n", msg), } } + +// ------------------------------------------ Error reporting ------------------------------------- + +#[derive(Clone)] +struct CrateMismatch { + path: PathBuf, + got: String, +} + +/// Candidate rejection reasons collected during crate search. +/// If no candidate is accepted, then these reasons are presented to the user, +/// otherwise they are ignored. +crate struct CombinedLocatorError { + crate_name: Symbol, + root: Option, + triple: TargetTriple, + dll_prefix: String, + dll_suffix: String, + rejected_via_hash: Vec, + rejected_via_triple: Vec, + rejected_via_kind: Vec, + rejected_via_version: Vec, + rejected_via_filename: Vec, +} + +crate enum CrateError { + NonAsciiName(Symbol), + ExternLocationNotExist(Symbol, PathBuf), + ExternLocationNotFile(Symbol, PathBuf), + MultipleCandidates(Symbol, CrateFlavor, Vec), + MultipleMatchingCrates(Symbol, FxHashMap), + SymbolConflictsCurrent(Symbol), + SymbolConflictsOthers(Symbol), + DlOpen(String), + DlSym(String), + LocatorCombined(CombinedLocatorError), + NonDylibPlugin(Symbol), +} + +impl CrateError { + crate fn report(self, sess: &Session, span: Span) -> ! { + let mut err = match self { + CrateError::NonAsciiName(crate_name) => sess.struct_span_err( + span, + &format!("cannot load a crate with a non-ascii name `{}`", crate_name), + ), + CrateError::ExternLocationNotExist(crate_name, loc) => sess.struct_span_err( + span, + &format!("extern location for {} does not exist: {}", crate_name, loc.display()), + ), + CrateError::ExternLocationNotFile(crate_name, loc) => sess.struct_span_err( + span, + &format!("extern location for {} is not a file: {}", crate_name, loc.display()), + ), + CrateError::MultipleCandidates(crate_name, flavor, candidates) => { + let mut err = struct_span_err!( + sess, + span, + E0465, + "multiple {} candidates for `{}` found", + flavor, + crate_name, + ); + for (i, candidate) in candidates.iter().enumerate() { + err.span_note(span, &format!("candidate #{}: {}", i + 1, candidate.display())); + } + err + } + CrateError::MultipleMatchingCrates(crate_name, libraries) => { + let mut err = struct_span_err!( + sess, + span, + E0464, + "multiple matching crates for `{}`", + crate_name + ); + let candidates = libraries + .iter() + .filter_map(|(_, lib)| { + let crate_name = &lib.metadata.get_root().name().as_str(); + match (&lib.source.dylib, &lib.source.rlib) { + (Some((pd, _)), Some((pr, _))) => Some(format!( + "\ncrate `{}`: {}\n{:>padding$}", + crate_name, + pd.display(), + pr.display(), + padding = 8 + crate_name.len() + )), + (Some((p, _)), None) | (None, Some((p, _))) => { + Some(format!("\ncrate `{}`: {}", crate_name, p.display())) + } + (None, None) => None, + } + }) + .collect::(); + err.note(&format!("candidates:{}", candidates)); + err + } + CrateError::SymbolConflictsCurrent(root_name) => struct_span_err!( + sess, + span, + E0519, + "the current crate is indistinguishable from one of its dependencies: it has the \ + same crate-name `{}` and was compiled with the same `-C metadata` arguments. \ + This will result in symbol conflicts between the two.", + root_name, + ), + CrateError::SymbolConflictsOthers(root_name) => struct_span_err!( + sess, + span, + E0523, + "found two different crates with name `{}` that are not distinguished by differing \ + `-C metadata`. This will result in symbol conflicts between the two.", + root_name, + ), + CrateError::DlOpen(s) | CrateError::DlSym(s) => sess.struct_span_err(span, &s), + CrateError::LocatorCombined(locator) => { + let crate_name = locator.crate_name; + let add = match &locator.root { + None => String::new(), + Some(r) => format!(" which `{}` depends on", r.name), + }; + let mut msg = "the following crate versions were found:".to_string(); + let mut err = if !locator.rejected_via_hash.is_empty() { + let mut err = struct_span_err!( + sess, + span, + E0460, + "found possibly newer version of crate `{}`{}", + crate_name, + add, + ); + err.note("perhaps that crate needs to be recompiled?"); + let mismatches = locator.rejected_via_hash.iter(); + for CrateMismatch { path, .. } in mismatches { + msg.push_str(&format!("\ncrate `{}`: {}", crate_name, path.display())); + } + if let Some(r) = locator.root { + for path in r.source.paths() { + msg.push_str(&format!("\ncrate `{}`: {}", r.name, path.display())); + } + } + err.note(&msg); + err + } else if !locator.rejected_via_triple.is_empty() { + let mut err = struct_span_err!( + sess, + span, + E0461, + "couldn't find crate `{}` with expected target triple {}{}", + crate_name, + locator.triple, + add, + ); + let mismatches = locator.rejected_via_triple.iter(); + for CrateMismatch { path, got } in mismatches { + msg.push_str(&format!( + "\ncrate `{}`, target triple {}: {}", + crate_name, + got, + path.display(), + )); + } + err.note(&msg); + err + } else if !locator.rejected_via_kind.is_empty() { + let mut err = struct_span_err!( + sess, + span, + E0462, + "found staticlib `{}` instead of rlib or dylib{}", + crate_name, + add, + ); + err.help("please recompile that crate using --crate-type lib"); + let mismatches = locator.rejected_via_kind.iter(); + for CrateMismatch { path, .. } in mismatches { + msg.push_str(&format!("\ncrate `{}`: {}", crate_name, path.display())); + } + err.note(&msg); + err + } else if !locator.rejected_via_version.is_empty() { + let mut err = struct_span_err!( + sess, + span, + E0514, + "found crate `{}` compiled by an incompatible version of rustc{}", + crate_name, + add, + ); + err.help(&format!( + "please recompile that crate using this compiler ({})", + rustc_version(), + )); + let mismatches = locator.rejected_via_version.iter(); + for CrateMismatch { path, got } in mismatches { + msg.push_str(&format!( + "\ncrate `{}` compiled by {}: {}", + crate_name, + got, + path.display(), + )); + } + err.note(&msg); + err + } else { + let mut err = struct_span_err!( + sess, + span, + E0463, + "can't find crate for `{}`{}", + crate_name, + add, + ); + + if (crate_name == sym::std || crate_name == sym::core) + && locator.triple != TargetTriple::from_triple(config::host_triple()) + { + err.note(&format!("the `{}` target may not be installed", locator.triple)); + } else if crate_name == sym::profiler_builtins { + err.note(&"the compiler may have been built without the profiler runtime"); + } + err.span_label(span, "can't find crate"); + err + }; + + if !locator.rejected_via_filename.is_empty() { + let mismatches = locator.rejected_via_filename.iter(); + for CrateMismatch { path, .. } in mismatches { + err.note(&format!( + "extern location for {} is of an unknown type: {}", + crate_name, + path.display(), + )) + .help(&format!( + "file name should be lib*.rlib or {}*.{}", + locator.dll_prefix, locator.dll_suffix + )); + } + } + err + } + CrateError::NonDylibPlugin(crate_name) => struct_span_err!( + sess, + span, + E0457, + "plugin `{}` only found in rlib format, but must be available in dylib format", + crate_name, + ), + }; + + err.emit(); + sess.abort_if_errors(); + unreachable!(); + } +} diff --git a/src/librustc_plugin_impl/load.rs b/src/librustc_plugin_impl/load.rs index c3a6016696888..62a87b47a2f74 100644 --- a/src/librustc_plugin_impl/load.rs +++ b/src/librustc_plugin_impl/load.rs @@ -55,13 +55,11 @@ fn load_plugin( metadata_loader: &dyn MetadataLoader, ident: Ident, ) { - let registrar = locator::find_plugin_registrar(sess, metadata_loader, ident.span, ident.name); - - if let Some((lib, disambiguator)) = registrar { - let symbol = sess.generate_plugin_registrar_symbol(disambiguator); - let fun = dylink_registrar(sess, ident.span, lib, symbol); - plugins.push(fun); - } + let (lib, disambiguator) = + locator::find_plugin_registrar(sess, metadata_loader, ident.span, ident.name); + let symbol = sess.generate_plugin_registrar_symbol(disambiguator); + let fun = dylink_registrar(sess, ident.span, lib, symbol); + plugins.push(fun); } // Dynamically link a registrar function into the compiler process. diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 575049c6bac2f..a7a005bdeb9f2 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -859,9 +859,7 @@ impl<'a> Resolver<'a> { // otherwise cause duplicate suggestions. continue; } - if let Some(crate_id) = - self.crate_loader.maybe_process_path_extern(ident.name, ident.span) - { + if let Some(crate_id) = self.crate_loader.maybe_process_path_extern(ident.name) { let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }); suggestions.extend(self.lookup_import_candidates_from_module( diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index 95888c38ba5e1..9323c15a94109 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -760,10 +760,8 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> { if !module.no_implicit_prelude { let extern_prelude = self.r.extern_prelude.clone(); names.extend(extern_prelude.iter().flat_map(|(ident, _)| { - self.r - .crate_loader - .maybe_process_path_extern(ident.name, ident.span) - .and_then(|crate_id| { + self.r.crate_loader.maybe_process_path_extern(ident.name).and_then( + |crate_id| { let crate_mod = Res::Def( DefKind::Mod, DefId { krate: crate_id, index: CRATE_DEF_INDEX }, @@ -774,7 +772,8 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> { } else { None } - }) + }, + ) })); if let Some(prelude) = self.r.prelude { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 686385e24ece8..da39f79efcd3b 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2957,7 +2957,7 @@ impl<'a> Resolver<'a> { let crate_id = if !speculative { self.crate_loader.process_path_extern(ident.name, ident.span) } else { - self.crate_loader.maybe_process_path_extern(ident.name, ident.span)? + self.crate_loader.maybe_process_path_extern(ident.name)? }; let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }); Some( diff --git a/src/test/compile-fail/empty-extern-arg.rs b/src/test/compile-fail/empty-extern-arg.rs index ae28fcad903be..d3cb5aaaeba89 100644 --- a/src/test/compile-fail/empty-extern-arg.rs +++ b/src/test/compile-fail/empty-extern-arg.rs @@ -1,4 +1,4 @@ // compile-flags: --extern std= -// error-pattern: can't find crate for `std` +// error-pattern: extern location for std does not exist fn main() {} diff --git a/src/test/ui-fulldeps/macro-crate-rlib.rs b/src/test/ui-fulldeps/macro-crate-rlib.rs index b5038a58249d2..1fd514c617329 100644 --- a/src/test/ui-fulldeps/macro-crate-rlib.rs +++ b/src/test/ui-fulldeps/macro-crate-rlib.rs @@ -1,10 +1,8 @@ // aux-build:rlib-crate-test.rs -// ignore-tidy-linelength // ignore-cross-compile gives a different error message #![feature(plugin)] #![plugin(rlib_crate_test)] -//~^ ERROR: plugin `rlib_crate_test` only found in rlib format, but must be available in dylib format -//~| WARN use of deprecated attribute `plugin`: compiler plugins are deprecated +//~^ ERROR: plugin `rlib_crate_test` only found in rlib format, but must be available in dylib fn main() {} diff --git a/src/test/ui-fulldeps/macro-crate-rlib.stderr b/src/test/ui-fulldeps/macro-crate-rlib.stderr index 342663312a853..7b31f28a26e7d 100644 --- a/src/test/ui-fulldeps/macro-crate-rlib.stderr +++ b/src/test/ui-fulldeps/macro-crate-rlib.stderr @@ -1,16 +1,8 @@ error[E0457]: plugin `rlib_crate_test` only found in rlib format, but must be available in dylib format - --> $DIR/macro-crate-rlib.rs:6:11 + --> $DIR/macro-crate-rlib.rs:5:11 | LL | #![plugin(rlib_crate_test)] | ^^^^^^^^^^^^^^^ -warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 - --> $DIR/macro-crate-rlib.rs:6:1 - | -LL | #![plugin(rlib_crate_test)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version - | - = note: `#[warn(deprecated)]` on by default - -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error diff --git a/src/test/ui/extern/extern-prelude-no-speculative.rs b/src/test/ui/extern/extern-prelude-no-speculative.rs index cc00737ab591d..3ba124159e000 100644 --- a/src/test/ui/extern/extern-prelude-no-speculative.rs +++ b/src/test/ui/extern/extern-prelude-no-speculative.rs @@ -1,6 +1,6 @@ // run-pass #![allow(unused_variables)] -// compile-flags: --extern LooksLikeExternCrate +// compile-flags: --extern LooksLikeExternCrate=/path/to/nowhere mod m { pub struct LooksLikeExternCrate; diff --git a/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.rs b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.rs index 3fb1cf9f557b2..310545b92d549 100644 --- a/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.rs +++ b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.rs @@ -1,6 +1,5 @@ #![feature(non_ascii_idents)] extern crate ьаг; //~ ERROR cannot load a crate with a non-ascii name `ьаг` -//~| ERROR can't find crate for `ьаг` fn main() {} diff --git a/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.stderr b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.stderr index 1e424237fd238..11108f2fb8678 100644 --- a/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.stderr +++ b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.stderr @@ -4,12 +4,5 @@ error: cannot load a crate with a non-ascii name `ьаг` LL | extern crate ьаг; | ^^^^^^^^^^^^^^^^^ -error[E0463]: can't find crate for `ьаг` - --> $DIR/crate_name_nonascii_forbidden-1.rs:3:1 - | -LL | extern crate ьаг; - | ^^^^^^^^^^^^^^^^^ can't find crate - -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0463`. diff --git a/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.rs b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.rs index e1acdbff06189..0249848b35ac0 100644 --- a/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.rs +++ b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.rs @@ -3,7 +3,5 @@ #![feature(non_ascii_idents)] use му_сгате::baz; //~ ERROR cannot load a crate with a non-ascii name `му_сгате` - //~| can't find crate for `му_сгате` - fn main() {} diff --git a/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.stderr b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.stderr index c06405ebb37ec..8d3548ed33dcf 100644 --- a/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.stderr +++ b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.stderr @@ -4,12 +4,5 @@ error: cannot load a crate with a non-ascii name `му_сгате` LL | use му_сгате::baz; | ^^^^^^^^ -error[E0463]: can't find crate for `му_сгате` - --> $DIR/crate_name_nonascii_forbidden-2.rs:5:5 - | -LL | use му_сгате::baz; - | ^^^^^^^^ can't find crate - -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0463`.