about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libcore/hint.rs3
-rw-r--r--src/libcore/intrinsics.rs1
-rw-r--r--src/libcore/lib.rs1
-rw-r--r--src/libcore/task/mod.rs4
-rw-r--r--src/libcore/task/ready.rs60
-rw-r--r--src/librustc_codegen_ssa/back/linker.rs4
-rw-r--r--src/librustc_error_codes/error_codes.rs2
-rw-r--r--src/librustc_metadata/creader.rs183
-rw-r--r--src/librustc_metadata/locator.rs754
-rw-r--r--src/librustc_mir/interpret/intrinsics.rs1
-rw-r--r--src/librustc_plugin_impl/load.rs12
-rw-r--r--src/librustc_resolve/diagnostics.rs4
-rw-r--r--src/librustc_resolve/late/diagnostics.rs9
-rw-r--r--src/librustc_resolve/lib.rs2
-rw-r--r--src/libstd/ffi/c_str.rs38
-rw-r--r--src/libstd/keyword_docs.rs183
-rw-r--r--src/libstd/lib.rs1
-rw-r--r--src/test/compile-fail/empty-extern-arg.rs2
-rw-r--r--src/test/ui-fulldeps/macro-crate-rlib.rs4
-rw-r--r--src/test/ui-fulldeps/macro-crate-rlib.stderr12
-rw-r--r--src/test/ui/const-generics/issues/issue-62878.rs11
-rw-r--r--src/test/ui/const-generics/issues/issue-62878.stderr37
-rw-r--r--src/test/ui/consts/const_unsafe_unreachable.rs17
-rw-r--r--src/test/ui/consts/const_unsafe_unreachable_ub.rs20
-rw-r--r--src/test/ui/consts/const_unsafe_unreachable_ub.stderr44
-rw-r--r--src/test/ui/extern/extern-prelude-no-speculative.rs2
-rw-r--r--src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.rs1
-rw-r--r--src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.stderr9
-rw-r--r--src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.rs2
-rw-r--r--src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.stderr9
-rw-r--r--src/tools/tidy/src/error_codes_check.rs10
31 files changed, 892 insertions, 550 deletions
diff --git a/src/libcore/hint.rs b/src/libcore/hint.rs
index 9ebcde79b63..3116815f5d6 100644
--- a/src/libcore/hint.rs
+++ b/src/libcore/hint.rs
@@ -45,7 +45,8 @@ use crate::intrinsics;
 /// ```
 #[inline]
 #[stable(feature = "unreachable", since = "1.27.0")]
-pub unsafe fn unreachable_unchecked() -> ! {
+#[rustc_const_unstable(feature = "const_unreachable_unchecked", issue = "53188")]
+pub const unsafe fn unreachable_unchecked() -> ! {
     // SAFETY: the safety contract for `intrinsics::unreachable` must
     // be upheld by the caller.
     unsafe { intrinsics::unreachable() }
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index 080760aa81f..8f0cf4361e7 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -932,6 +932,7 @@ extern "rust-intrinsic" {
     ///
     /// The stabilized version of this intrinsic is
     /// [`std::hint::unreachable_unchecked`](../../std/hint/fn.unreachable_unchecked.html).
+    #[rustc_const_unstable(feature = "const_unreachable_unchecked", issue = "53188")]
     pub fn unreachable() -> !;
 
     /// Informs the optimizer that a condition is always true.
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 1621cf79751..2e443064706 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -92,6 +92,7 @@
 #![feature(const_slice_ptr_len)]
 #![feature(const_type_name)]
 #![feature(const_likely)]
+#![feature(const_unreachable_unchecked)]
 #![feature(custom_inner_attributes)]
 #![feature(decl_macro)]
 #![feature(doc_cfg)]
diff --git a/src/libcore/task/mod.rs b/src/libcore/task/mod.rs
index 27760749c1d..3d6f4f5971a 100644
--- a/src/libcore/task/mod.rs
+++ b/src/libcore/task/mod.rs
@@ -9,3 +9,7 @@ pub use self::poll::Poll;
 mod wake;
 #[stable(feature = "futures_api", since = "1.36.0")]
 pub use self::wake::{Context, RawWaker, RawWakerVTable, Waker};
+
+mod ready;
+#[unstable(feature = "ready_macro", issue = "70922")]
+pub use ready::ready;
diff --git a/src/libcore/task/ready.rs b/src/libcore/task/ready.rs
new file mode 100644
index 00000000000..d4e733eb2bc
--- /dev/null
+++ b/src/libcore/task/ready.rs
@@ -0,0 +1,60 @@
+/// Extracts the successful type of a `Poll<T>`.
+///
+/// This macro bakes in propagation of `Pending` signals by returning early.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(future_readiness_fns)]
+/// #![feature(ready_macro)]
+///
+/// use core::task::{ready, Context, Poll};
+/// use core::future::{self, Future};
+/// use core::pin::Pin;
+///
+/// pub fn do_poll(cx: &mut Context<'_>) -> Poll<()> {
+///     let mut fut = future::ready(42);
+///     let fut = Pin::new(&mut fut);
+///
+///     let num = ready!(fut.poll(cx));
+///     # drop(num);
+///     // ... use num
+///
+///     Poll::Ready(())
+/// }
+/// ```
+///
+/// The `ready!` call expands to:
+///
+/// ```
+/// # #![feature(future_readiness_fns)]
+/// # #![feature(ready_macro)]
+/// #
+/// # use core::task::{Context, Poll};
+/// # use core::future::{self, Future};
+/// # use core::pin::Pin;
+/// #
+/// # pub fn do_poll(cx: &mut Context<'_>) -> Poll<()> {
+///     # let mut fut = future::ready(42);
+///     # let fut = Pin::new(&mut fut);
+///     #
+/// let num = match fut.poll(cx) {
+///     Poll::Ready(t) => t,
+///     Poll::Pending => return Poll::Pending,
+/// };
+///     # drop(num);
+///     # // ... use num
+///     #
+///     # Poll::Ready(())
+/// # }
+/// ```
+#[unstable(feature = "ready_macro", issue = "70922")]
+#[rustc_macro_transparency = "semitransparent"]
+pub macro ready($e:expr) {
+    match $e {
+        $crate::task::Poll::Ready(t) => t,
+        $crate::task::Poll::Pending => {
+            return $crate::task::Poll::Pending;
+        }
+    }
+}
diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs
index 6f40aac83eb..e64aafa599f 100644
--- a/src/librustc_codegen_ssa/back/linker.rs
+++ b/src/librustc_codegen_ssa/back/linker.rs
@@ -28,9 +28,7 @@ use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor};
 pub fn disable_localization(linker: &mut Command) {
     // No harm in setting both env vars simultaneously.
     // Unix-style linkers.
-    // We use an UTF-8 locale, as the generic C locale disables support for non-ASCII
-    // bytes in filenames on some platforms.
-    linker.env("LC_ALL", "en_US.UTF-8");
+    linker.env("LC_ALL", "C");
     // MSVC's `link.exe`.
     linker.env("VSLANG", "1033");
 }
diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs
index 6160450d766..bbbd8359f01 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/creader.rs b/src/librustc_metadata/creader.rs
index 0563894e634..0d2101cb2cb 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<Library>,
         root: Option<&CratePaths>,
-        span: Span,
         lib: Library,
         dep_kind: DepKind,
         name: Symbol,
-    ) -> CrateNum {
+    ) -> Result<CrateNum, CrateError> {
         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<Library>)>
+    ) -> Result<Option<(LoadResult, Option<Library>)>, 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<CrateNum, LoadError<'b>> {
+    ) -> Result<CrateNum, CrateError> {
         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<LoadResult> {
-        let library = locator.maybe_load_library_crate()?;
+    fn load(&self, locator: &mut CrateLocator<'_>) -> Result<Option<LoadResult>, 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<CrateNumMap, CrateError> {
         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<CrateNum> {
-        self.maybe_resolve_crate(name, span, DepKind::Explicit, None).ok()
+    pub fn maybe_process_path_extern(&mut self, name: Symbol) -> Option<CrateNum> {
+        self.maybe_resolve_crate(name, DepKind::Explicit, None).ok()
     }
 }
diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs
index 1bdac1039b5..371ec4cd911 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,25 +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 std::time::Instant;
-
 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> {
@@ -263,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<bool>,
 
@@ -275,6 +262,7 @@ crate struct CrateLocator<'a> {
     rejected_via_filename: Vec<CrateMismatch>,
 }
 
+#[derive(Clone)]
 crate struct CratePaths {
     name: Symbol,
     source: CrateSource,
@@ -287,7 +275,7 @@ impl CratePaths {
 }
 
 #[derive(Copy, Clone, PartialEq)]
-enum CrateFlavor {
+crate enum CrateFlavor {
     Rlib,
     Rmeta,
     Dylib,
@@ -313,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<bool>,
     ) -> CrateLocator<'a> {
@@ -349,7 +336,6 @@ impl<'a> CrateLocator<'a> {
             } else {
                 sess.target_filesearch(path_kind)
             },
-            span,
             root,
             is_proc_macro,
             rejected_via_hash: Vec::new(),
@@ -368,166 +354,30 @@ impl<'a> CrateLocator<'a> {
         self.rejected_via_filename.clear();
     }
 
-    crate fn maybe_load_library_crate(&mut self) -> Option<Library> {
+    crate fn maybe_load_library_crate(&mut self) -> Result<Option<Library>, 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 dylibname = self.dylibname();
-            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 {}*.{}",
-                    dylibname.0, dylibname.1
-                ));
+        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<PathBuf>,
-    ) -> Option<Library> {
-        let dypair = self.dylibname();
-        let staticpair = self.staticlibname();
-
+    ) -> Result<Option<Library>, CrateError> {
         // 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();
@@ -555,10 +405,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() });
                 }
@@ -567,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) {
@@ -577,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)
@@ -603,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);
             }
         }
@@ -612,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::<String>();
-                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)),
         }
     }
 
@@ -653,16 +473,16 @@ impl<'a> CrateLocator<'a> {
         rlibs: FxHashMap<PathBuf, PathKind>,
         rmetas: FxHashMap<PathBuf, PathKind>,
         dylibs: FxHashMap<PathBuf, PathKind>,
-    ) -> Option<(Svh, Library)> {
+    ) -> Result<Option<(Svh, Library)>, 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 {
@@ -698,10 +518,7 @@ impl<'a> CrateLocator<'a> {
         m: FxHashMap<PathBuf, PathKind>,
         flavor: CrateFlavor,
         slot: &mut Option<(Svh, MetadataBlob)>,
-    ) -> Option<(PathBuf, PathKind)> {
-        let mut ret: Option<(PathBuf, PathKind)> = None;
-        let mut error = 0;
-
+    ) -> Result<Option<(PathBuf, PathKind)>, 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
@@ -718,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<DiagnosticBuilder<'_>> = None;
+        let mut ret: Option<(PathBuf, PathKind)> = None;
+        let mut err_data: Option<Vec<PathBuf>> = None;
         for (lib, kind) in m {
             info!("{} reading metadata from: {}", flavor, lib.display());
             let (hash, metadata) =
@@ -744,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;
             }
 
@@ -790,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) {
@@ -801,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)
         }
     }
 
@@ -860,71 +665,29 @@ 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<Library> {
+    fn find_commandline_library(&mut self) -> Result<Option<Library>, 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 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 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 {
-                    let (ref prefix, ref suffix) = dylibname;
-                    if file.starts_with(&prefix[..]) && file.ends_with(&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") {
@@ -932,25 +695,30 @@ 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))
     }
-}
 
-// 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<MetadataBlob, String> {
-    let start = Instant::now();
-    let ret = get_metadata_section_imp(target, flavor, filename, loader);
-    info!("reading {:?} => {:?}", filename.file_name().unwrap(), start.elapsed());
-    ret
+    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,
+        })
+    }
 }
 
 /// A trivial wrapper for `Mmap` that implements `StableDeref`.
@@ -966,7 +734,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,
@@ -1026,12 +794,19 @@ 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 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,
@@ -1041,57 +816,16 @@ pub fn find_plugin_registrar(
         None, // extra_filename
         true, // is_host
         PathKind::Crate,
-        span,
         None, // root
         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,
-        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 => {
-            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()),
     }
 }
 
@@ -1100,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
@@ -1115,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<CratePaths>,
+    triple: TargetTriple,
+    dll_prefix: String,
+    dll_suffix: String,
+    rejected_via_hash: Vec<CrateMismatch>,
+    rejected_via_triple: Vec<CrateMismatch>,
+    rejected_via_kind: Vec<CrateMismatch>,
+    rejected_via_version: Vec<CrateMismatch>,
+    rejected_via_filename: Vec<CrateMismatch>,
+}
+
+crate enum CrateError {
+    NonAsciiName(Symbol),
+    ExternLocationNotExist(Symbol, PathBuf),
+    ExternLocationNotFile(Symbol, PathBuf),
+    MultipleCandidates(Symbol, CrateFlavor, Vec<PathBuf>),
+    MultipleMatchingCrates(Symbol, FxHashMap<Svh, Library>),
+    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::<String>();
+                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_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index 85186264022..5836fc9c95a 100644
--- a/src/librustc_mir/interpret/intrinsics.rs
+++ b/src/librustc_mir/interpret/intrinsics.rs
@@ -95,6 +95,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         let (dest, ret) = match ret {
             None => match intrinsic_name {
                 sym::transmute => throw_ub_format!("transmuting to uninhabited type"),
+                sym::unreachable => throw_ub!(Unreachable),
                 sym::abort => M::abort(self)?,
                 // Unsupported diverging intrinsic.
                 _ => return Ok(false),
diff --git a/src/librustc_plugin_impl/load.rs b/src/librustc_plugin_impl/load.rs
index c3a60166968..62a87b47a2f 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 575049c6bac..a7a005bdeb9 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 95888c38ba5..9323c15a941 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 686385e24ec..da39f79efcd 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/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs
index dca1fdde482..da25a0ede72 100644
--- a/src/libstd/ffi/c_str.rs
+++ b/src/libstd/ffi/c_str.rs
@@ -1551,6 +1551,27 @@ impl ops::Index<ops::RangeFull> for CString {
     }
 }
 
+#[stable(feature = "cstr_range_from", since = "1.47.0")]
+impl ops::Index<ops::RangeFrom<usize>> for CStr {
+    type Output = CStr;
+
+    fn index(&self, index: ops::RangeFrom<usize>) -> &CStr {
+        let bytes = self.to_bytes_with_nul();
+        // we need to manually check the starting index to account for the null
+        // byte, since otherwise we could get an empty string that doesn't end
+        // in a null.
+        if index.start < bytes.len() {
+            unsafe { CStr::from_bytes_with_nul_unchecked(&bytes[index.start..]) }
+        } else {
+            panic!(
+                "index out of bounds: the len is {} but the index is {}",
+                bytes.len(),
+                index.start
+            );
+        }
+    }
+}
+
 #[stable(feature = "cstring_asref", since = "1.7.0")]
 impl AsRef<CStr> for CStr {
     #[inline]
@@ -1747,4 +1768,21 @@ mod tests {
 
         assert_eq!(CSTR.to_str().unwrap(), "Hello, world!");
     }
+
+    #[test]
+    fn cstr_index_from() {
+        let original = b"Hello, world!\0";
+        let cstr = CStr::from_bytes_with_nul(original).unwrap();
+        let result = CStr::from_bytes_with_nul(&original[7..]).unwrap();
+
+        assert_eq!(&cstr[7..], result);
+    }
+
+    #[test]
+    #[should_panic]
+    fn cstr_index_from_empty() {
+        let original = b"Hello, world!\0";
+        let cstr = CStr::from_bytes_with_nul(original).unwrap();
+        let _ = &cstr[original.len()..];
+    }
 }
diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs
index a53e7f5cf57..d985f10ccb4 100644
--- a/src/libstd/keyword_docs.rs
+++ b/src/libstd/keyword_docs.rs
@@ -1497,11 +1497,188 @@ mod super_keyword {}
 
 #[doc(keyword = "trait")]
 //
-/// A common interface for a class of types.
+/// A common interface for a group of types.
 ///
-/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+/// A `trait` is like an interface that data types can implement. When a type
+/// implements a trait it can be treated abstractly as that trait using generics
+/// or trait objects.
 ///
-/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+/// Traits can be made up of three varieties of associated items:
+///
+/// - functions and methods
+/// - types
+/// - constants
+///
+/// Traits may also contain additional type parameters. Those type parameters
+/// or the trait itself can be constrained by other traits.
+///
+/// Traits can serve as markers or carry other logical semantics that
+/// aren't expressed through their items. When a type implements that
+/// trait it is promising to uphold its contract. [`Send`] and [`Sync`] are two
+/// such marker traits present in the standard library.
+///
+/// See the [Reference][Ref-Traits] for a lot more information on traits.
+///
+/// # Examples
+///
+/// Traits are declared using the `trait` keyword. Types can implement them
+/// using [`impl`] `Trait` [`for`] `Type`:
+///
+/// ```rust
+/// trait Zero {
+///     const ZERO: Self;
+///     fn is_zero(&self) -> bool;
+/// }
+///
+/// impl Zero for i32 {
+///     const ZERO: Self = 0;
+///
+///     fn is_zero(&self) -> bool {
+///         *self == Self::ZERO
+///     }
+/// }
+///
+/// assert_eq!(i32::ZERO, 0);
+/// assert!(i32::ZERO.is_zero());
+/// assert!(!4.is_zero());
+/// ```
+///
+/// With an associated type:
+///
+/// ```rust
+/// trait Builder {
+///     type Built;
+///
+///     fn build(&self) -> Self::Built;
+/// }
+/// ```
+///
+/// Traits can be generic, with constraints or without:
+///
+/// ```rust
+/// trait MaybeFrom<T> {
+///     fn maybe_from(value: T) -> Option<Self>
+///     where
+///         Self: Sized;
+/// }
+/// ```
+///
+/// Traits can build upon the requirements of other traits. In the example
+/// below `Iterator` is a **supertrait** and `ThreeIterator` is a **subtrait**:
+///
+/// ```rust
+/// trait ThreeIterator: std::iter::Iterator {
+///     fn next_three(&mut self) -> Option<[Self::Item; 3]>;
+/// }
+/// ```
+///
+/// Traits can be used in functions, as parameters:
+///
+/// ```rust
+/// # #![allow(dead_code)]
+/// fn debug_iter<I: Iterator>(it: I) where I::Item: std::fmt::Debug {
+///     for elem in it {
+///         println!("{:#?}", elem);
+///     }
+/// }
+///
+/// // u8_len_1, u8_len_2 and u8_len_3 are equivalent
+///
+/// fn u8_len_1(val: impl Into<Vec<u8>>) -> usize {
+///     val.into().len()
+/// }
+///
+/// fn u8_len_2<T: Into<Vec<u8>>>(val: T) -> usize {
+///     val.into().len()
+/// }
+///
+/// fn u8_len_3<T>(val: T) -> usize
+/// where
+///     T: Into<Vec<u8>>,
+/// {
+///     val.into().len()
+/// }
+/// ```
+///
+/// Or as return types:
+///
+/// ```rust
+/// # #![allow(dead_code)]
+/// fn from_zero_to(v: u8) -> impl Iterator<Item = u8> {
+///     (0..v).into_iter()
+/// }
+/// ```
+///
+/// The use of the [`impl`] keyword in this position allows the function writer
+/// to hide the concrete type as an implementation detail which can change
+/// without breaking user's code.
+///
+/// # Trait objects
+///
+/// A *trait object* is an opaque value of another type that implements a set of
+/// traits. A trait object implements all specified traits as well as their
+/// supertraits (if any).
+///
+/// The syntax is the following: `dyn BaseTrait + AutoTrait1 + ... AutoTraitN`.
+/// Only one `BaseTrait` can be used so this will not compile:
+///
+/// ```rust,compile_fail,E0225
+/// trait A {}
+/// trait B {}
+///
+/// let _: Box<dyn A + B>;
+/// ```
+///
+/// Neither will this, which is a syntax error:
+///
+/// ```rust,compile_fail
+/// trait A {}
+/// trait B {}
+///
+/// let _: Box<dyn A + dyn B>;
+/// ```
+///
+/// On the other hand, this is correct:
+///
+/// ```rust
+/// trait A {}
+///
+/// let _: Box<dyn A + Send + Sync>;
+/// ```
+///
+/// The [Reference][Ref-Trait-Objects] has more information about trait objects,
+/// their limitations and the differences between editions.
+///
+/// # Unsafe traits
+///
+/// Some traits may be unsafe to implement. Using the [`unsafe`] keyword in
+/// front of the trait's declaration is used to mark this:
+///
+/// ```rust
+/// unsafe trait UnsafeTrait {}
+///
+/// unsafe impl UnsafeTrait for i32 {}
+/// ```
+///
+/// # Differences between the 2015 and 2018 editions
+///
+/// In the 2015 edition parameters pattern where not needed for traits:
+///
+/// ```rust,edition2015
+/// trait Tr {
+///     fn f(i32);
+/// }
+/// ```
+///
+/// This behavior is no longer valid in edition 2018.
+///
+/// [`for`]: keyword.for.html
+/// [`impl`]: keyword.impl.html
+/// [`unsafe`]: keyword.unsafe.html
+/// [`Send`]: marker/trait.Send.html
+/// [`Sync`]: marker/trait.Sync.html
+/// [Ref-Traits]: ../reference/items/traits.html
+/// [Ref-Trait-Objects]: ../reference/types/trait-object.html
 mod trait_keyword {}
 
 #[doc(keyword = "true")]
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 0397153098c..11b8f953be4 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -305,6 +305,7 @@
 #![feature(ptr_internals)]
 #![feature(raw)]
 #![feature(raw_ref_macros)]
+#![feature(ready_macro)]
 #![feature(renamed_spin_loop)]
 #![feature(rustc_attrs)]
 #![feature(rustc_private)]
diff --git a/src/test/compile-fail/empty-extern-arg.rs b/src/test/compile-fail/empty-extern-arg.rs
index ae28fcad903..d3cb5aaaeba 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 b5038a58249..1fd514c6173 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 342663312a8..7b31f28a26e 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/const-generics/issues/issue-62878.rs b/src/test/ui/const-generics/issues/issue-62878.rs
new file mode 100644
index 00000000000..ccc05fdf100
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-62878.rs
@@ -0,0 +1,11 @@
+#![feature(const_generics)] //~ WARN the feature `const_generics` is incomplete
+
+fn foo<const N: usize, const A: [u8; N]>() {}
+//~^ ERROR the type of const parameters must not
+
+fn main() {
+    foo::<_, {[1]}>();
+    //~^ ERROR wrong number of const arguments
+    //~| ERROR wrong number of type arguments
+    //~| ERROR mismatched types
+}
diff --git a/src/test/ui/const-generics/issues/issue-62878.stderr b/src/test/ui/const-generics/issues/issue-62878.stderr
new file mode 100644
index 00000000000..fe0990d8241
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-62878.stderr
@@ -0,0 +1,37 @@
+error[E0770]: the type of const parameters must not depend on other generic parameters
+  --> $DIR/issue-62878.rs:3:38
+   |
+LL | fn foo<const N: usize, const A: [u8; N]>() {}
+   |                                      ^ the type must not depend on the parameter `N`
+
+warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-62878.rs:1:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
+
+error[E0107]: wrong number of const arguments: expected 2, found 1
+  --> $DIR/issue-62878.rs:7:5
+   |
+LL |     foo::<_, {[1]}>();
+   |     ^^^^^^^^^^^^^^^ expected 2 const arguments
+
+error[E0107]: wrong number of type arguments: expected 0, found 1
+  --> $DIR/issue-62878.rs:7:11
+   |
+LL |     foo::<_, {[1]}>();
+   |           ^ unexpected type argument
+
+error[E0308]: mismatched types
+  --> $DIR/issue-62878.rs:7:15
+   |
+LL |     foo::<_, {[1]}>();
+   |               ^^^ expected `usize`, found array `[{integer}; 1]`
+
+error: aborting due to 4 previous errors; 1 warning emitted
+
+Some errors have detailed explanations: E0107, E0308, E0770.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/src/test/ui/consts/const_unsafe_unreachable.rs b/src/test/ui/consts/const_unsafe_unreachable.rs
new file mode 100644
index 00000000000..cfed6e5deb9
--- /dev/null
+++ b/src/test/ui/consts/const_unsafe_unreachable.rs
@@ -0,0 +1,17 @@
+// run-pass
+
+#![feature(const_fn)]
+#![feature(const_unreachable_unchecked)]
+
+const unsafe fn foo(x: bool) -> bool {
+    match x {
+        true => true,
+        false => std::hint::unreachable_unchecked(),
+    }
+}
+
+const BAR: bool = unsafe { foo(true) };
+
+fn main() {
+  assert_eq!(BAR, true);
+}
diff --git a/src/test/ui/consts/const_unsafe_unreachable_ub.rs b/src/test/ui/consts/const_unsafe_unreachable_ub.rs
new file mode 100644
index 00000000000..11920d852e0
--- /dev/null
+++ b/src/test/ui/consts/const_unsafe_unreachable_ub.rs
@@ -0,0 +1,20 @@
+// build-fail
+
+#![feature(const_fn)]
+#![feature(const_unreachable_unchecked)]
+
+const unsafe fn foo(x: bool) -> bool {
+    match x {
+        true => true,
+        false => std::hint::unreachable_unchecked(),
+    }
+}
+
+#[warn(const_err)]
+const BAR: bool = unsafe { foo(false) };
+
+fn main() {
+  assert_eq!(BAR, true);
+  //~^ ERROR E0080
+  //~| ERROR erroneous constant
+}
diff --git a/src/test/ui/consts/const_unsafe_unreachable_ub.stderr b/src/test/ui/consts/const_unsafe_unreachable_ub.stderr
new file mode 100644
index 00000000000..3ef8043a54d
--- /dev/null
+++ b/src/test/ui/consts/const_unsafe_unreachable_ub.stderr
@@ -0,0 +1,44 @@
+warning: any use of this value will cause an error
+  --> $SRC_DIR/libcore/hint.rs:LL:COL
+   |
+LL |     unsafe { intrinsics::unreachable() }
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |              |
+   |              entering unreachable code
+   |              inside `std::hint::unreachable_unchecked` at $SRC_DIR/libcore/hint.rs:LL:COL
+   |              inside `foo` at $DIR/const_unsafe_unreachable_ub.rs:9:18
+   |              inside `BAR` at $DIR/const_unsafe_unreachable_ub.rs:14:28
+   | 
+  ::: $DIR/const_unsafe_unreachable_ub.rs:14:1
+   |
+LL | const BAR: bool = unsafe { foo(false) };
+   | ----------------------------------------
+   |
+note: the lint level is defined here
+  --> $DIR/const_unsafe_unreachable_ub.rs:13:8
+   |
+LL | #[warn(const_err)]
+   |        ^^^^^^^^^
+
+error[E0080]: evaluation of constant expression failed
+  --> $DIR/const_unsafe_unreachable_ub.rs:17:3
+   |
+LL |   assert_eq!(BAR, true);
+   |   ^^^^^^^^^^^---^^^^^^^^
+   |              |
+   |              referenced constant has errors
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: erroneous constant used
+  --> $DIR/const_unsafe_unreachable_ub.rs:17:3
+   |
+LL |   assert_eq!(BAR, true);
+   |   ^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/extern/extern-prelude-no-speculative.rs b/src/test/ui/extern/extern-prelude-no-speculative.rs
index cc00737ab59..3ba124159e0 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 3fb1cf9f557..310545b92d5 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 1e424237fd2..11108f2fb86 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 e1acdbff061..0249848b35a 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 c06405ebb37..8d3548ed33d 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`.
diff --git a/src/tools/tidy/src/error_codes_check.rs b/src/tools/tidy/src/error_codes_check.rs
index 3af71f69d24..51f135d3761 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...