about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNathan Stocks <cleancut@github.com>2022-08-26 14:39:59 -0600
committerNathan Stocks <cleancut@github.com>2022-08-31 10:56:42 -0600
commit0d65819d529f222e47164f6c8132d8134909f2a4 (patch)
tree273a58e5e2ff576a688e8186142ed1faad81d12b
parentd0ba1fbaa4f73b6edf27346817b1f74fb352945e (diff)
downloadrust-0d65819d529f222e47164f6c8132d8134909f2a4.tar.gz
rust-0d65819d529f222e47164f6c8132d8134909f2a4.zip
respond to review feedback: mainly eliminate as many conversions as possible...
- ... when creating diagnostics in rustc_metadata
-  use the error_code! macro
- pass macro output to diag.code()
- use fluent from within manual implementation of SessionDiagnostic
- emit the untested errors in case they occur in the wild
- stop panicking in the probably-not-dead code, add fixme to write test
-rw-r--r--Cargo.lock1
-rw-r--r--compiler/rustc_error_messages/locales/en-US/metadata.ftl30
-rw-r--r--compiler/rustc_errors/Cargo.toml5
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs7
-rw-r--r--compiler/rustc_metadata/src/creader.rs19
-rw-r--r--compiler/rustc_metadata/src/dependency_format.rs30
-rw-r--r--compiler/rustc_metadata/src/errors.rs215
-rw-r--r--compiler/rustc_metadata/src/fs.rs27
-rw-r--r--compiler/rustc_metadata/src/locator.rs102
-rw-r--r--compiler/rustc_metadata/src/native_libs.rs18
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs6
11 files changed, 234 insertions, 226 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 002d73be7d1..0ce329ff070 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3514,6 +3514,7 @@ dependencies = [
  "rustc_macros",
  "rustc_serialize",
  "rustc_span",
+ "rustc_target",
  "serde",
  "serde_json",
  "termcolor",
diff --git a/compiler/rustc_error_messages/locales/en-US/metadata.ftl b/compiler/rustc_error_messages/locales/en-US/metadata.ftl
index e3e58cf8bed..dee01bcad4b 100644
--- a/compiler/rustc_error_messages/locales/en-US/metadata.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/metadata.ftl
@@ -225,3 +225,33 @@ metadata_cannot_find_crate =
 
 metadata_no_dylib_plugin =
     plugin `{$crate_name}` only found in rlib format, but must be available in dylib format
+
+metadata_target_not_installed =
+    the `{$locator_triple}` target may not be installed
+
+metadata_target_no_std_support =
+    the `{$locator_triple}` target may not support the standard library
+
+metadata_consider_downloading_target =
+    consider downloading the target with `rustup target add {$locator_triple}`
+
+metadata_std_required =
+    `std` is required by `{$current_crate}` because it does not declare `#![no_std]`
+
+metadata_consider_building_std =
+    consider building the standard library from source with `cargo build -Zbuild-std`
+
+metadata_compiler_missing_profiler =
+    the compiler may have been built without the profiler runtime
+
+metadata_install_missing_components =
+    maybe you need to install the missing components with: `rustup component add rust-src rustc-dev llvm-tools-preview`
+
+metadata_cant_find_crate =
+    can't find crate
+
+metadata_crate_location_unknown_type =
+    extern location for {$crate_name} is of an unknown type: {$path}
+
+metadata_lib_filename_form =
+    file name should be lib*.rlib or {dll_prefix}*.{dll_suffix}
diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml
index 36805aa874f..4d207fd17fb 100644
--- a/compiler/rustc_errors/Cargo.toml
+++ b/compiler/rustc_errors/Cargo.toml
@@ -15,13 +15,14 @@ rustc_macros = { path = "../rustc_macros" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_lint_defs = { path = "../rustc_lint_defs" }
+rustc_target = { path = "../rustc_target" }
 unicode-width = "0.1.4"
 atty = "0.2"
 termcolor = "1.0"
 annotate-snippets = "0.9"
 termize = "0.1.1"
-serde = { version = "1.0.125", features = ["derive"] }
+serde = { version = "1.0.125", features = [ "derive" ] }
 serde_json = "1.0.59"
 
 [target.'cfg(windows)'.dependencies]
-winapi = { version = "0.3", features = ["handleapi", "synchapi", "winbase"] }
+winapi = { version = "0.3", features = [ "handleapi", "synchapi", "winbase" ] }
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index f75e2596f36..b569ef4fc2c 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -10,6 +10,7 @@ use rustc_lint_defs::{Applicability, LintExpectationId};
 use rustc_span::edition::LATEST_STABLE_EDITION;
 use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent, Symbol};
 use rustc_span::{edition::Edition, Span, DUMMY_SP};
+use rustc_target::spec::PanicStrategy;
 use std::borrow::Cow;
 use std::fmt;
 use std::hash::{Hash, Hasher};
@@ -144,6 +145,12 @@ impl IntoDiagnosticArg for usize {
     }
 }
 
+impl IntoDiagnosticArg for PanicStrategy {
+    fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+        DiagnosticArgValue::Str(Cow::Owned(self.desc().to_string()))
+    }
+}
+
 impl<'source> Into<FluentValue<'source>> for DiagnosticArgValue<'source> {
     fn into(self) -> FluentValue<'source> {
         match self {
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index f9aa3733f6a..edffec8ab55 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -750,13 +750,10 @@ impl<'a> CrateLoader<'a> {
         // Sanity check the loaded crate to ensure it is indeed a panic runtime
         // and the panic strategy is indeed what we thought it was.
         if !data.is_panic_runtime() {
-            self.sess.emit_err(CrateNotPanicRuntime { crate_name: name.to_string() });
+            self.sess.emit_err(CrateNotPanicRuntime { crate_name: name });
         }
         if data.required_panic_strategy() != Some(desired_strategy) {
-            self.sess.emit_err(NoPanicStrategy {
-                crate_name: name.to_string(),
-                strategy: desired_strategy.desc().to_string(),
-            });
+            self.sess.emit_err(NoPanicStrategy { crate_name: name, strategy: desired_strategy });
         }
 
         self.cstore.injected_panic_runtime = Some(cnum);
@@ -784,7 +781,7 @@ impl<'a> CrateLoader<'a> {
 
         // Sanity check the loaded crate to ensure it is indeed a profiler runtime
         if !data.is_profiler_runtime() {
-            self.sess.emit_err(NotProfilerRuntime { crate_name: name.to_string() });
+            self.sess.emit_err(NotProfilerRuntime { crate_name: name });
         }
     }
 
@@ -828,8 +825,8 @@ impl<'a> CrateLoader<'a> {
                 match global_allocator {
                     Some(other_crate) => {
                         self.sess.emit_err(ConflictingGlobalAlloc {
-                            crate_name: data.name().to_string(),
-                            other_crate_name: other_crate.to_string(),
+                            crate_name: data.name(),
+                            other_crate_name: other_crate,
                         });
                     }
                     None => global_allocator = Some(data.name()),
@@ -874,9 +871,9 @@ impl<'a> CrateLoader<'a> {
             let data = self.cstore.get_crate_data(dep);
             if needs_dep(&data) {
                 self.sess.emit_err(NoTransitiveNeedsDep {
-                    crate_name: self.cstore.get_crate_data(krate).name().to_string(),
-                    needs_crate_name: what.to_string(),
-                    deps_crate_name: data.name().to_string(),
+                    crate_name: self.cstore.get_crate_data(krate).name(),
+                    needs_crate_name: what,
+                    deps_crate_name: data.name(),
                 });
             }
         }
diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs
index 5d1082acc0b..9ad0099ad25 100644
--- a/compiler/rustc_metadata/src/dependency_format.rs
+++ b/compiler/rustc_metadata/src/dependency_format.rs
@@ -140,7 +140,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
                 if src.rlib.is_some() {
                     continue;
                 }
-                sess.emit_err(RlibRequired { crate_name: tcx.crate_name(cnum).to_string() });
+                sess.emit_err(RlibRequired { crate_name: tcx.crate_name(cnum) });
             }
             return Vec::new();
         }
@@ -224,10 +224,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
                     Linkage::Static => "rlib",
                     _ => "dylib",
                 };
-                sess.emit_err(LibRequired {
-                    crate_name: tcx.crate_name(cnum).to_string(),
-                    kind: kind.to_string(),
-                });
+                sess.emit_err(LibRequired { crate_name: tcx.crate_name(cnum), kind: kind });
             }
         }
     }
@@ -251,8 +248,7 @@ fn add_library(
             // This error is probably a little obscure, but I imagine that it
             // can be refined over time.
             if link2 != link || link == RequireStatic {
-                tcx.sess
-                    .emit_err(CrateDepMultiple { crate_name: tcx.crate_name(cnum).to_string() });
+                tcx.sess.emit_err(CrateDepMultiple { crate_name: tcx.crate_name(cnum) });
             }
         }
         None => {
@@ -347,8 +343,8 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) {
 
         if tcx.is_panic_runtime(cnum) {
             if let Some((prev, _)) = panic_runtime {
-                let prev_name = tcx.crate_name(prev).to_string();
-                let cur_name = tcx.crate_name(cnum).to_string();
+                let prev_name = tcx.crate_name(prev);
+                let cur_name = tcx.crate_name(cnum);
                 sess.emit_err(TwoPanicRuntimes { prev_name, cur_name });
             }
             panic_runtime = Some((
@@ -370,8 +366,8 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) {
         // our same strategy.
         if found_strategy != desired_strategy {
             sess.emit_err(BadPanicStrategy {
-                runtime: tcx.crate_name(runtime_cnum).to_string(),
-                strategy: desired_strategy.desc().to_string(),
+                runtime: tcx.crate_name(runtime_cnum),
+                strategy: desired_strategy,
             });
         }
 
@@ -390,17 +386,17 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) {
 
             if let Some(found_strategy) = tcx.required_panic_strategy(cnum) && desired_strategy != found_strategy {
                 sess.emit_err(RequiredPanicStrategy {
-                    crate_name: tcx.crate_name(cnum).to_string(),
-                    found_strategy: found_strategy.desc().to_string(),
-                    desired_strategy: desired_strategy.desc().to_string() });
+                    crate_name: tcx.crate_name(cnum),
+                    found_strategy,
+                    desired_strategy});
             }
 
             let found_drop_strategy = tcx.panic_in_drop_strategy(cnum);
             if tcx.sess.opts.unstable_opts.panic_in_drop != found_drop_strategy {
                 sess.emit_err(IncompatiblePanicInDropStrategy {
-                    crate_name: tcx.crate_name(cnum).to_string(),
-                    found_strategy: found_drop_strategy.desc().to_string(),
-                    desired_strategy: tcx.sess.opts.unstable_opts.panic_in_drop.desc().to_string(),
+                    crate_name: tcx.crate_name(cnum),
+                    found_strategy: found_drop_strategy,
+                    desired_strategy: tcx.sess.opts.unstable_opts.panic_in_drop,
                 });
             }
         }
diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs
index d3f35ca8d16..565c96917e2 100644
--- a/compiler/rustc_metadata/src/errors.rs
+++ b/compiler/rustc_metadata/src/errors.rs
@@ -1,59 +1,64 @@
-use std::path::PathBuf;
+use std::{
+    io::Error,
+    path::{Path, PathBuf},
+};
 
-use rustc_errors::{DiagnosticId, ErrorGuaranteed};
+use rustc_errors::{error_code, ErrorGuaranteed};
 use rustc_macros::SessionDiagnostic;
 use rustc_session::{config, SessionDiagnostic};
 use rustc_span::{sym, Span, Symbol};
-use rustc_target::spec::TargetTriple;
+use rustc_target::spec::{PanicStrategy, TargetTriple};
+
+use crate::locator::CrateFlavor;
 
 #[derive(SessionDiagnostic)]
 #[diag(metadata::rlib_required)]
 pub struct RlibRequired {
-    pub crate_name: String,
+    pub crate_name: Symbol,
 }
 
 #[derive(SessionDiagnostic)]
 #[diag(metadata::lib_required)]
-pub struct LibRequired {
-    pub crate_name: String,
-    pub kind: String,
+pub struct LibRequired<'a> {
+    pub crate_name: Symbol,
+    pub kind: &'a str,
 }
 
 #[derive(SessionDiagnostic)]
 #[diag(metadata::crate_dep_multiple)]
 #[help]
 pub struct CrateDepMultiple {
-    pub crate_name: String,
+    pub crate_name: Symbol,
 }
 
 #[derive(SessionDiagnostic)]
 #[diag(metadata::two_panic_runtimes)]
 pub struct TwoPanicRuntimes {
-    pub prev_name: String,
-    pub cur_name: String,
+    pub prev_name: Symbol,
+    pub cur_name: Symbol,
 }
 
 #[derive(SessionDiagnostic)]
 #[diag(metadata::bad_panic_strategy)]
 pub struct BadPanicStrategy {
-    pub runtime: String,
-    pub strategy: String,
+    pub runtime: Symbol,
+    pub strategy: PanicStrategy,
 }
 
 #[derive(SessionDiagnostic)]
 #[diag(metadata::required_panic_strategy)]
 pub struct RequiredPanicStrategy {
-    pub crate_name: String,
-    pub found_strategy: String,
-    pub desired_strategy: String,
+    pub crate_name: Symbol,
+    pub found_strategy: PanicStrategy,
+    pub desired_strategy: PanicStrategy,
 }
 
 #[derive(SessionDiagnostic)]
 #[diag(metadata::incompatible_panic_in_drop_strategy)]
 pub struct IncompatiblePanicInDropStrategy {
-    pub crate_name: String,
-    pub found_strategy: String,
-    pub desired_strategy: String,
+    pub crate_name: Symbol,
+    pub found_strategy: PanicStrategy,
+    pub desired_strategy: PanicStrategy,
 }
 
 #[derive(SessionDiagnostic)]
@@ -129,11 +134,11 @@ pub struct FrameworkOnlyWindows {
 
 #[derive(SessionDiagnostic)]
 #[diag(metadata::unknown_link_kind, code = "E0458")]
-pub struct UnknownLinkKind {
+pub struct UnknownLinkKind<'a> {
     #[primary_span]
     #[label]
     pub span: Span,
-    pub kind: String,
+    pub kind: &'a str,
 }
 
 #[derive(SessionDiagnostic)]
@@ -180,10 +185,10 @@ pub struct InvalidLinkModifier {
 
 #[derive(SessionDiagnostic)]
 #[diag(metadata::multiple_modifiers)]
-pub struct MultipleModifiers {
+pub struct MultipleModifiers<'a> {
     #[primary_span]
     pub span: Span,
-    pub modifier: String,
+    pub modifier: &'a str,
 }
 
 #[derive(SessionDiagnostic)]
@@ -209,10 +214,10 @@ pub struct AsNeededCompatibility {
 
 #[derive(SessionDiagnostic)]
 #[diag(metadata::unknown_link_modifier)]
-pub struct UnknownLinkModifier {
+pub struct UnknownLinkModifier<'a> {
     #[primary_span]
     pub span: Span,
-    pub modifier: String,
+    pub modifier: &'a str,
 }
 
 #[derive(SessionDiagnostic)]
@@ -250,20 +255,20 @@ pub struct LibFrameworkApple;
 
 #[derive(SessionDiagnostic)]
 #[diag(metadata::empty_renaming_target)]
-pub struct EmptyRenamingTarget {
-    pub lib_name: String,
+pub struct EmptyRenamingTarget<'a> {
+    pub lib_name: &'a str,
 }
 
 #[derive(SessionDiagnostic)]
 #[diag(metadata::renaming_no_link)]
-pub struct RenamingNoLink {
-    pub lib_name: String,
+pub struct RenamingNoLink<'a> {
+    pub lib_name: &'a str,
 }
 
 #[derive(SessionDiagnostic)]
 #[diag(metadata::multiple_renamings)]
-pub struct MultipleRenamings {
-    pub lib_name: String,
+pub struct MultipleRenamings<'a> {
+    pub lib_name: &'a str,
 }
 
 #[derive(SessionDiagnostic)]
@@ -290,32 +295,32 @@ pub struct UnsupportedAbi {
 #[derive(SessionDiagnostic)]
 #[diag(metadata::fail_create_file_encoder)]
 pub struct FailCreateFileEncoder {
-    pub err: String,
+    pub err: Error,
 }
 
 #[derive(SessionDiagnostic)]
 #[diag(metadata::fail_seek_file)]
 pub struct FailSeekFile {
-    pub err: String,
+    pub err: Error,
 }
 
 #[derive(SessionDiagnostic)]
 #[diag(metadata::fail_write_file)]
 pub struct FailWriteFile {
-    pub err: String,
+    pub err: Error,
 }
 
 #[derive(SessionDiagnostic)]
 #[diag(metadata::crate_not_panic_runtime)]
 pub struct CrateNotPanicRuntime {
-    pub crate_name: String,
+    pub crate_name: Symbol,
 }
 
 #[derive(SessionDiagnostic)]
 #[diag(metadata::no_panic_strategy)]
 pub struct NoPanicStrategy {
-    pub crate_name: String,
-    pub strategy: String,
+    pub crate_name: Symbol,
+    pub strategy: PanicStrategy,
 }
 
 #[derive(SessionDiagnostic)]
@@ -325,7 +330,7 @@ pub struct ProfilerBuiltinsNeedsCore;
 #[derive(SessionDiagnostic)]
 #[diag(metadata::not_profiler_runtime)]
 pub struct NotProfilerRuntime {
-    pub crate_name: String,
+    pub crate_name: Symbol,
 }
 
 #[derive(SessionDiagnostic)]
@@ -341,8 +346,8 @@ pub struct NoMultipleGlobalAlloc {
 #[derive(SessionDiagnostic)]
 #[diag(metadata::conflicting_global_alloc)]
 pub struct ConflictingGlobalAlloc {
-    pub crate_name: String,
-    pub other_crate_name: String,
+    pub crate_name: Symbol,
+    pub other_crate_name: Symbol,
 }
 
 #[derive(SessionDiagnostic)]
@@ -351,36 +356,36 @@ pub struct GlobalAllocRequired;
 
 #[derive(SessionDiagnostic)]
 #[diag(metadata::no_transitive_needs_dep)]
-pub struct NoTransitiveNeedsDep {
-    pub crate_name: String,
-    pub needs_crate_name: String,
-    pub deps_crate_name: String,
+pub struct NoTransitiveNeedsDep<'a> {
+    pub crate_name: Symbol,
+    pub needs_crate_name: &'a str,
+    pub deps_crate_name: Symbol,
 }
 
 #[derive(SessionDiagnostic)]
 #[diag(metadata::failed_write_error)]
 pub struct FailedWriteError {
-    pub filename: String,
-    pub err: String,
+    pub filename: PathBuf,
+    pub err: Error,
 }
 
 #[derive(SessionDiagnostic)]
 #[diag(metadata::failed_create_tempdir)]
 pub struct FailedCreateTempdir {
-    pub err: String,
+    pub err: Error,
 }
 
 #[derive(SessionDiagnostic)]
 #[diag(metadata::failed_create_file)]
-pub struct FailedCreateFile {
-    pub filename: String,
-    pub err: String,
+pub struct FailedCreateFile<'a> {
+    pub filename: &'a Path,
+    pub err: Error,
 }
 
 #[derive(SessionDiagnostic)]
 #[diag(metadata::failed_create_encoded_metadata)]
 pub struct FailedCreateEncodedMetadata {
-    pub err: String,
+    pub err: Error,
 }
 
 #[derive(SessionDiagnostic)]
@@ -388,31 +393,31 @@ pub struct FailedCreateEncodedMetadata {
 pub struct NonAsciiName {
     #[primary_span]
     pub span: Span,
-    pub crate_name: String,
+    pub crate_name: Symbol,
 }
 
 #[derive(SessionDiagnostic)]
 #[diag(metadata::extern_location_not_exist)]
-pub struct ExternLocationNotExist {
+pub struct ExternLocationNotExist<'a> {
     #[primary_span]
     pub span: Span,
-    pub crate_name: String,
-    pub location: String,
+    pub crate_name: Symbol,
+    pub location: &'a Path,
 }
 
 #[derive(SessionDiagnostic)]
 #[diag(metadata::extern_location_not_file)]
-pub struct ExternLocationNotFile {
+pub struct ExternLocationNotFile<'a> {
     #[primary_span]
     pub span: Span,
-    pub crate_name: String,
-    pub location: String,
+    pub crate_name: Symbol,
+    pub location: &'a Path,
 }
 
-pub struct MultipleCandidates {
+pub(crate) struct MultipleCandidates {
     pub span: Span,
-    pub flavor: String,
-    pub crate_name: String,
+    pub flavor: CrateFlavor,
+    pub crate_name: Symbol,
     pub candidates: Vec<PathBuf>,
 }
 
@@ -424,7 +429,7 @@ impl SessionDiagnostic<'_> for MultipleCandidates {
         let mut diag = sess.struct_err(rustc_errors::fluent::metadata::multiple_candidates);
         diag.set_arg("crate_name", self.crate_name);
         diag.set_arg("flavor", self.flavor);
-        diag.code(DiagnosticId::Error("E0465".into()));
+        diag.code(error_code!(E0465));
         diag.set_span(self.span);
         for (i, candidate) in self.candidates.iter().enumerate() {
             diag.span_note(self.span, &format!("candidate #{}: {}", i + 1, candidate.display()));
@@ -439,7 +444,7 @@ impl SessionDiagnostic<'_> for MultipleCandidates {
 pub struct MultipleMatchingCrates {
     #[primary_span]
     pub span: Span,
-    pub crate_name: String,
+    pub crate_name: Symbol,
     pub candidates: String,
 }
 
@@ -448,7 +453,7 @@ pub struct MultipleMatchingCrates {
 pub struct SymbolConflictsCurrent {
     #[primary_span]
     pub span: Span,
-    pub crate_name: String,
+    pub crate_name: Symbol,
 }
 
 #[derive(SessionDiagnostic)]
@@ -456,7 +461,7 @@ pub struct SymbolConflictsCurrent {
 pub struct SymbolConflictsOthers {
     #[primary_span]
     pub span: Span,
-    pub crate_name: String,
+    pub crate_name: Symbol,
 }
 
 #[derive(SessionDiagnostic)]
@@ -464,8 +469,8 @@ pub struct SymbolConflictsOthers {
 pub struct StableCrateIdCollision {
     #[primary_span]
     pub span: Span,
-    pub crate_name0: String,
-    pub crate_name1: String,
+    pub crate_name0: Symbol,
+    pub crate_name1: Symbol,
 }
 
 #[derive(SessionDiagnostic)]
@@ -483,7 +488,7 @@ pub struct DlError {
 pub struct NewerCrateVersion {
     #[primary_span]
     pub span: Span,
-    pub crate_name: String,
+    pub crate_name: Symbol,
     pub add_info: String,
     pub found_crates: String,
 }
@@ -491,11 +496,11 @@ pub struct NewerCrateVersion {
 #[derive(SessionDiagnostic)]
 #[diag(metadata::no_crate_with_triple, code = "E0461")]
 #[note(metadata::found_crate_versions)]
-pub struct NoCrateWithTriple {
+pub struct NoCrateWithTriple<'a> {
     #[primary_span]
     pub span: Span,
-    pub crate_name: String,
-    pub locator_triple: String,
+    pub crate_name: Symbol,
+    pub locator_triple: &'a str,
     pub add_info: String,
     pub found_crates: String,
 }
@@ -507,7 +512,7 @@ pub struct NoCrateWithTriple {
 pub struct FoundStaticlib {
     #[primary_span]
     pub span: Span,
-    pub crate_name: String,
+    pub crate_name: Symbol,
     pub add_info: String,
     pub found_crates: String,
 }
@@ -519,7 +524,7 @@ pub struct FoundStaticlib {
 pub struct IncompatibleRustc {
     #[primary_span]
     pub span: Span,
-    pub crate_name: String,
+    pub crate_name: Symbol,
     pub add_info: String,
     pub found_crates: String,
     pub rustc_version: String,
@@ -527,7 +532,7 @@ pub struct IncompatibleRustc {
 
 pub struct InvalidMetadataFiles {
     pub span: Span,
-    pub crate_name: String,
+    pub crate_name: Symbol,
     pub add_info: String,
     pub crate_rejections: Vec<String>,
 }
@@ -540,7 +545,7 @@ impl SessionDiagnostic<'_> for InvalidMetadataFiles {
         let mut diag = sess.struct_err(rustc_errors::fluent::metadata::invalid_meta_files);
         diag.set_arg("crate_name", self.crate_name);
         diag.set_arg("add_info", self.add_info);
-        diag.code(DiagnosticId::Error("E0786".into()));
+        diag.code(error_code!(E0786));
         diag.set_span(self.span);
         for crate_rejection in self.crate_rejections {
             diag.note(crate_rejection);
@@ -551,8 +556,7 @@ impl SessionDiagnostic<'_> for InvalidMetadataFiles {
 
 pub struct CannotFindCrate {
     pub span: Span,
-    pub crate_name: String,
-    pub crate_name_symbol: Symbol,
+    pub crate_name: Symbol,
     pub add_info: String,
     pub missing_core: bool,
     pub current_crate: String,
@@ -567,53 +571,41 @@ impl SessionDiagnostic<'_> for CannotFindCrate {
         sess: &'_ rustc_session::parse::ParseSess,
     ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
         let mut diag = sess.struct_err(rustc_errors::fluent::metadata::cannot_find_crate);
-        diag.set_arg("crate_name", self.crate_name.clone());
+        diag.set_arg("crate_name", self.crate_name);
         diag.set_arg("add_info", self.add_info);
-        diag.code(DiagnosticId::Error("E0463".into()));
+        diag.set_arg("locator_triple", self.locator_triple.triple());
+        diag.code(error_code!(E0463));
         diag.set_span(self.span);
-        // FIXME: Find a way to distill this logic down into the derived SessionDiagnostic form
-        if (self.crate_name_symbol == sym::std || self.crate_name_symbol == sym::core)
+        if (self.crate_name == sym::std || self.crate_name == sym::core)
             && self.locator_triple != TargetTriple::from_triple(config::host_triple())
         {
             if self.missing_core {
-                diag.note(&format!("the `{}` target may not be installed", self.locator_triple));
+                diag.note(rustc_errors::fluent::metadata::target_not_installed);
             } else {
-                diag.note(&format!(
-                    "the `{}` target may not support the standard library",
-                    self.locator_triple
-                ));
+                diag.note(rustc_errors::fluent::metadata::target_no_std_support);
             }
             // NOTE: this suggests using rustup, even though the user may not have it installed.
             // That's because they could choose to install it; or this may give them a hint which
             // target they need to install from their distro.
             if self.missing_core {
-                diag.help(&format!(
-                    "consider downloading the target with `rustup target add {}`",
-                    self.locator_triple
-                ));
+                diag.help(rustc_errors::fluent::metadata::consider_downloading_target);
             }
             // Suggest using #![no_std]. #[no_core] is unstable and not really supported anyway.
             // NOTE: this is a dummy span if `extern crate std` was injected by the compiler.
             // If it's not a dummy, that means someone added `extern crate std` explicitly and
             // `#![no_std]` won't help.
             if !self.missing_core && self.span.is_dummy() {
-                diag.note(&format!(
-                    "`std` is required by `{}` because it does not declare `#![no_std]`",
-                    self.current_crate
-                ));
+                diag.note(rustc_errors::fluent::metadata::std_required);
             }
             if self.is_nightly_build {
-                diag.help("consider building the standard library from source with `cargo build -Zbuild-std`");
+                diag.help(rustc_errors::fluent::metadata::consider_building_std);
             }
-        } else if self.crate_name_symbol == self.profiler_runtime {
-            diag.note("the compiler may have been built without the profiler runtime");
-        } else if self.crate_name.starts_with("rustc_") {
-            diag.help(
-                "maybe you need to install the missing components with: \
-                             `rustup component add rust-src rustc-dev llvm-tools-preview`",
-            );
+        } else if self.crate_name == self.profiler_runtime {
+            diag.note(rustc_errors::fluent::metadata::compiler_missing_profiler);
+        } else if self.crate_name.as_str().starts_with("rustc_") {
+            diag.help(rustc_errors::fluent::metadata::install_missing_components);
         }
-        diag.span_label(self.span, "can't find crate");
+        diag.span_label(self.span, rustc_errors::fluent::metadata::cant_find_crate);
         diag
     }
 }
@@ -623,5 +615,22 @@ impl SessionDiagnostic<'_> for CannotFindCrate {
 pub struct NoDylibPlugin {
     #[primary_span]
     pub span: Span,
-    pub crate_name: String,
+    pub crate_name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::crate_location_unknown_type)]
+pub struct CrateLocationUnknownType<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub path: &'a Path,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::lib_filename_form)]
+pub struct LibFilenameForm<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub dll_prefix: &'a str,
+    pub dll_suffix: &'a str,
 }
diff --git a/compiler/rustc_metadata/src/fs.rs b/compiler/rustc_metadata/src/fs.rs
index 67c18766c59..f360a586476 100644
--- a/compiler/rustc_metadata/src/fs.rs
+++ b/compiler/rustc_metadata/src/fs.rs
@@ -26,11 +26,8 @@ pub fn emit_metadata(sess: &Session, metadata: &[u8], tmpdir: &MaybeTempDir) ->
     let out_filename = tmpdir.as_ref().join(METADATA_FILENAME);
     let result = fs::write(&out_filename, metadata);
 
-    if let Err(e) = result {
-        sess.emit_fatal(FailedWriteError {
-            filename: out_filename.display().to_string(),
-            err: e.to_string(),
-        });
+    if let Err(err) = result {
+        sess.emit_fatal(FailedWriteError { filename: out_filename, err });
     }
 
     out_filename
@@ -71,7 +68,7 @@ pub fn encode_and_write_metadata(
     let metadata_tmpdir = TempFileBuilder::new()
         .prefix("rmeta")
         .tempdir_in(out_filename.parent().unwrap_or_else(|| Path::new("")))
-        .unwrap_or_else(|err| tcx.sess.emit_fatal(FailedCreateTempdir { err: err.to_string() }));
+        .unwrap_or_else(|err| tcx.sess.emit_fatal(FailedCreateTempdir { err }));
     let metadata_tmpdir = MaybeTempDir::new(metadata_tmpdir, tcx.sess.opts.cg.save_temps);
     let metadata_filename = metadata_tmpdir.as_ref().join(METADATA_FILENAME);
 
@@ -79,11 +76,8 @@ pub fn encode_and_write_metadata(
     // This simplifies the creation of the output `out_filename` when requested.
     match metadata_kind {
         MetadataKind::None => {
-            std::fs::File::create(&metadata_filename).unwrap_or_else(|e| {
-                tcx.sess.emit_fatal(FailedCreateFile {
-                    filename: metadata_filename.display().to_string(),
-                    err: e.to_string(),
-                });
+            std::fs::File::create(&metadata_filename).unwrap_or_else(|err| {
+                tcx.sess.emit_fatal(FailedCreateFile { filename: &metadata_filename, err });
             });
         }
         MetadataKind::Uncompressed | MetadataKind::Compressed => {
@@ -98,11 +92,8 @@ pub fn encode_and_write_metadata(
     // this file always exists.
     let need_metadata_file = tcx.sess.opts.output_types.contains_key(&OutputType::Metadata);
     let (metadata_filename, metadata_tmpdir) = if need_metadata_file {
-        if let Err(e) = non_durable_rename(&metadata_filename, &out_filename) {
-            tcx.sess.emit_fatal(FailedWriteError {
-                filename: out_filename.display().to_string(),
-                err: e.to_string(),
-            });
+        if let Err(err) = non_durable_rename(&metadata_filename, &out_filename) {
+            tcx.sess.emit_fatal(FailedWriteError { filename: out_filename, err });
         }
         if tcx.sess.opts.json_artifact_notifications {
             tcx.sess
@@ -117,8 +108,8 @@ pub fn encode_and_write_metadata(
 
     // Load metadata back to memory: codegen may need to include it in object files.
     let metadata =
-        EncodedMetadata::from_path(metadata_filename, metadata_tmpdir).unwrap_or_else(|e| {
-            tcx.sess.emit_fatal(FailedCreateEncodedMetadata { err: e.to_string() });
+        EncodedMetadata::from_path(metadata_filename, metadata_tmpdir).unwrap_or_else(|err| {
+            tcx.sess.emit_fatal(FailedCreateEncodedMetadata { err });
         });
 
     let need_metadata_module = metadata_kind == MetadataKind::Compressed;
diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs
index 83c8756078e..5edad819e7e 100644
--- a/compiler/rustc_metadata/src/locator.rs
+++ b/compiler/rustc_metadata/src/locator.rs
@@ -214,10 +214,11 @@
 
 use crate::creader::Library;
 use crate::errors::{
-    CannotFindCrate, DlError, ExternLocationNotExist, ExternLocationNotFile, FoundStaticlib,
-    IncompatibleRustc, InvalidMetadataFiles, MultipleCandidates, MultipleMatchingCrates,
-    NewerCrateVersion, NoCrateWithTriple, NoDylibPlugin, NonAsciiName, StableCrateIdCollision,
-    SymbolConflictsCurrent, SymbolConflictsOthers,
+    CannotFindCrate, CrateLocationUnknownType, DlError, ExternLocationNotExist,
+    ExternLocationNotFile, FoundStaticlib, IncompatibleRustc, InvalidMetadataFiles,
+    LibFilenameForm, MultipleCandidates, MultipleMatchingCrates, NewerCrateVersion,
+    NoCrateWithTriple, NoDylibPlugin, NonAsciiName, StableCrateIdCollision, SymbolConflictsCurrent,
+    SymbolConflictsOthers,
 };
 use crate::rmeta::{rustc_version, MetadataBlob, METADATA_HEADER};
 
@@ -226,7 +227,7 @@ use rustc_data_structures::memmap::Mmap;
 use rustc_data_structures::owning_ref::OwningRef;
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::MetadataRef;
-use rustc_errors::FatalError;
+use rustc_errors::{DiagnosticArgValue, FatalError, IntoDiagnosticArg};
 use rustc_session::config::{self, CrateType};
 use rustc_session::cstore::{CrateSource, MetadataLoader};
 use rustc_session::filesearch::FileSearch;
@@ -238,6 +239,7 @@ use rustc_span::Span;
 use rustc_target::spec::{Target, TargetTriple};
 
 use snap::read::FrameDecoder;
+use std::borrow::Cow;
 use std::fmt::Write as _;
 use std::io::{Read, Result as IoResult, Write};
 use std::path::{Path, PathBuf};
@@ -294,6 +296,16 @@ impl fmt::Display for CrateFlavor {
     }
 }
 
+impl IntoDiagnosticArg for CrateFlavor {
+    fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
+        match self {
+            CrateFlavor::Rlib => DiagnosticArgValue::Str(Cow::Borrowed("rlib")),
+            CrateFlavor::Rmeta => DiagnosticArgValue::Str(Cow::Borrowed("rmeta")),
+            CrateFlavor::Dylib => DiagnosticArgValue::Str(Cow::Borrowed("dylib")),
+        }
+    }
+}
+
 impl<'a> CrateLocator<'a> {
     pub(crate) fn new(
         sess: &'a Session,
@@ -946,29 +958,16 @@ impl CrateError {
     pub(crate) fn report(self, sess: &Session, span: Span, missing_core: bool) {
         match self {
             CrateError::NonAsciiName(crate_name) => {
-                sess.emit_err(NonAsciiName { span, crate_name: crate_name.to_string() });
+                sess.emit_err(NonAsciiName { span, crate_name });
             }
             CrateError::ExternLocationNotExist(crate_name, loc) => {
-                sess.emit_err(ExternLocationNotExist {
-                    span,
-                    crate_name: crate_name.to_string(),
-                    location: loc.display().to_string(),
-                });
+                sess.emit_err(ExternLocationNotExist { span, crate_name, location: &loc });
             }
             CrateError::ExternLocationNotFile(crate_name, loc) => {
-                sess.emit_err(ExternLocationNotFile {
-                    span,
-                    crate_name: crate_name.to_string(),
-                    location: loc.display().to_string(),
-                });
+                sess.emit_err(ExternLocationNotFile { span, crate_name, location: &loc });
             }
             CrateError::MultipleCandidates(crate_name, flavor, candidates) => {
-                sess.emit_err(MultipleCandidates {
-                    span,
-                    flavor: flavor.to_string(),
-                    crate_name: crate_name.to_string(),
-                    candidates,
-                });
+                sess.emit_err(MultipleCandidates { span, flavor: flavor, crate_name, candidates });
             }
             CrateError::MultipleMatchingCrates(crate_name, libraries) => {
                 let mut libraries: Vec<_> = libraries.into_values().collect();
@@ -998,27 +997,23 @@ impl CrateError {
                         s
                     })
                     .collect::<String>();
-                sess.emit_err(MultipleMatchingCrates {
-                    span,
-                    crate_name: crate_name.to_string(),
-                    candidates,
-                });
+                sess.emit_err(MultipleMatchingCrates { span, crate_name, candidates });
             }
             CrateError::SymbolConflictsCurrent(root_name) => {
-                sess.emit_err(SymbolConflictsCurrent { span, crate_name: root_name.to_string() });
+                sess.emit_err(SymbolConflictsCurrent { span, crate_name: root_name });
             }
             CrateError::SymbolConflictsOthers(root_name) => {
-                sess.emit_err(SymbolConflictsOthers { span, crate_name: root_name.to_string() });
+                sess.emit_err(SymbolConflictsOthers { span, crate_name: root_name });
             }
             CrateError::StableCrateIdCollision(crate_name0, crate_name1) => {
                 sess.emit_err(StableCrateIdCollision {
                     span,
-                    crate_name0: crate_name0.to_string(),
-                    crate_name1: crate_name1.to_string(),
+                    crate_name0: crate_name0,
+                    crate_name1: crate_name1,
                 });
             }
             CrateError::DlOpen(s) | CrateError::DlSym(s) => {
-                sess.emit_err(DlError { span, err: s.to_string() });
+                sess.emit_err(DlError { span, err: s });
             }
             CrateError::LocatorCombined(locator) => {
                 let crate_name = locator.crate_name;
@@ -1026,24 +1021,17 @@ impl CrateError {
                     None => String::new(),
                     Some(r) => format!(" which `{}` depends on", r.name),
                 };
-                // FIXME: Is there any way to get these notes and helps onto every diagnostic in this
-                // huge branch arm without changing them all to manual implementations?
-                let mut global_loc_notes = Vec::new();
-                let mut global_loc_helps = Vec::new();
+                // FIXME: There are no tests for CrateLocationUnknownType or LibFilenameForm
                 if !locator.crate_rejections.via_filename.is_empty() {
                     let mismatches = locator.crate_rejections.via_filename.iter();
                     for CrateMismatch { path, .. } in mismatches {
-                        global_loc_notes.push(format!(
-                            "extern location for {} is of an unknown type: {}",
-                            crate_name,
-                            path.display(),
-                        ));
-                        global_loc_helps.push(format!(
-                            "file name should be lib*.rlib or {}*.{}",
-                            locator.dll_prefix, locator.dll_suffix
-                        ));
+                        sess.emit_err(CrateLocationUnknownType { span, path: &path });
+                        sess.emit_err(LibFilenameForm {
+                            span,
+                            dll_prefix: &locator.dll_prefix,
+                            dll_suffix: &locator.dll_suffix,
+                        });
                     }
-                    panic!("!!!!! REVERT THIS COMMIT !!!!!");
                 }
                 let mut found_crates = String::new();
                 if !locator.crate_rejections.via_hash.is_empty() {
@@ -1066,7 +1054,7 @@ impl CrateError {
                     }
                     sess.emit_err(NewerCrateVersion {
                         span,
-                        crate_name: crate_name.to_string(),
+                        crate_name: crate_name,
                         add_info,
                         found_crates,
                     });
@@ -1082,8 +1070,8 @@ impl CrateError {
                     }
                     sess.emit_err(NoCrateWithTriple {
                         span,
-                        crate_name: crate_name.to_string(),
-                        locator_triple: locator.triple.to_string(),
+                        crate_name: crate_name,
+                        locator_triple: locator.triple.triple(),
                         add_info,
                         found_crates,
                     });
@@ -1096,12 +1084,7 @@ impl CrateError {
                             path.display()
                         ));
                     }
-                    sess.emit_err(FoundStaticlib {
-                        span,
-                        crate_name: crate_name.to_string(),
-                        add_info,
-                        found_crates,
-                    });
+                    sess.emit_err(FoundStaticlib { span, crate_name, add_info, found_crates });
                 } else if !locator.crate_rejections.via_version.is_empty() {
                     let mismatches = locator.crate_rejections.via_version.iter();
                     for CrateMismatch { path, got } in mismatches {
@@ -1114,7 +1097,7 @@ impl CrateError {
                     }
                     sess.emit_err(IncompatibleRustc {
                         span,
-                        crate_name: crate_name.to_string(),
+                        crate_name,
                         add_info,
                         found_crates,
                         rustc_version: rustc_version(),
@@ -1126,15 +1109,14 @@ impl CrateError {
                     }
                     sess.emit_err(InvalidMetadataFiles {
                         span,
-                        crate_name: crate_name.to_string(),
+                        crate_name,
                         add_info,
                         crate_rejections,
                     });
                 } else {
                     sess.emit_err(CannotFindCrate {
                         span,
-                        crate_name: crate_name.to_string(),
-                        crate_name_symbol: crate_name,
+                        crate_name,
                         add_info,
                         missing_core,
                         current_crate: sess
@@ -1149,7 +1131,7 @@ impl CrateError {
                 }
             }
             CrateError::NonDylibPlugin(crate_name) => {
-                sess.emit_err(NoDylibPlugin { span, crate_name: crate_name.to_string() });
+                sess.emit_err(NoDylibPlugin { span, crate_name });
             }
         }
     }
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index dbaa2e9defa..19f64ef70c9 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -124,7 +124,7 @@ impl<'tcx> Collector<'tcx> {
                                 NativeLibKind::RawDylib
                             }
                             kind => {
-                                sess.emit_err(UnknownLinkKind { span, kind: kind.to_string() });
+                                sess.emit_err(UnknownLinkKind { span, kind });
                                 continue;
                             }
                         };
@@ -249,10 +249,7 @@ impl<'tcx> Collector<'tcx> {
                     }
                     let assign_modifier = |dst: &mut Option<bool>| {
                         if dst.is_some() {
-                            sess.emit_err(MultipleModifiers {
-                                span,
-                                modifier: modifier.to_string(),
-                            });
+                            sess.emit_err(MultipleModifiers { span, modifier });
                         } else {
                             *dst = Some(value);
                         }
@@ -287,10 +284,7 @@ impl<'tcx> Collector<'tcx> {
                         }
 
                         _ => {
-                            sess.emit_err(UnknownLinkModifier {
-                                span,
-                                modifier: modifier.to_string(),
-                            });
+                            sess.emit_err(UnknownLinkModifier { span, modifier });
                         }
                     }
                 }
@@ -379,11 +373,11 @@ impl<'tcx> Collector<'tcx> {
                     .filter_map(|lib| lib.name.as_ref())
                     .any(|n| n.as_str() == lib.name);
                 if new_name.is_empty() {
-                    self.tcx.sess.emit_err(EmptyRenamingTarget { lib_name: lib.name.clone() });
+                    self.tcx.sess.emit_err(EmptyRenamingTarget { lib_name: &lib.name });
                 } else if !any_duplicate {
-                    self.tcx.sess.emit_err(RenamingNoLink { lib_name: lib.name.clone() });
+                    self.tcx.sess.emit_err(RenamingNoLink { lib_name: &lib.name });
                 } else if !renames.insert(&lib.name) {
-                    self.tcx.sess.emit_err(MultipleRenamings { lib_name: lib.name.clone() });
+                    self.tcx.sess.emit_err(MultipleRenamings { lib_name: &lib.name });
                 }
             }
         }
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 2b1f9f17a3c..8f55fb59f0b 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -2270,7 +2270,7 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
 
 fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) {
     let mut encoder = opaque::FileEncoder::new(path)
-        .unwrap_or_else(|err| tcx.sess.emit_fatal(FailCreateFileEncoder { err: err.to_string() }));
+        .unwrap_or_else(|err| tcx.sess.emit_fatal(FailCreateFileEncoder { err }));
     encoder.emit_raw_bytes(METADATA_HEADER);
 
     // Will be filled with the root position after encoding everything.
@@ -2315,10 +2315,10 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) {
     // Encode the root position.
     let header = METADATA_HEADER.len();
     file.seek(std::io::SeekFrom::Start(header as u64))
-        .unwrap_or_else(|err| tcx.sess.emit_fatal(FailSeekFile { err: err.to_string() }));
+        .unwrap_or_else(|err| tcx.sess.emit_fatal(FailSeekFile { err }));
     let pos = root.position.get();
     file.write_all(&[(pos >> 24) as u8, (pos >> 16) as u8, (pos >> 8) as u8, (pos >> 0) as u8])
-        .unwrap_or_else(|err| tcx.sess.emit_fatal(FailWriteFile { err: err.to_string() }));
+        .unwrap_or_else(|err| tcx.sess.emit_fatal(FailWriteFile { err }));
 
     // Return to the position where we are before writing the root position.
     file.seek(std::io::SeekFrom::Start(pos_before_seek)).unwrap();