]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_metadata/src/locator.rs
Rollup merge of #102625 - Rageking8:fix-backtrace-small-typo, r=m-ou-se
[rust.git] / compiler / rustc_metadata / src / locator.rs
index 5b7d0c8581ab214217dc49f520d3044fafbfcbfa..35f9ef92a1c425fb74eb8b4866ee187df9b27957 100644 (file)
 //! metadata::locator or metadata::creader for all the juicy details!
 
 use crate::creader::Library;
+use crate::errors::{
+    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};
 
 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, FatalError};
+use rustc_errors::{DiagnosticArgValue, FatalError, IntoDiagnosticArg};
 use rustc_session::config::{self, CrateType};
 use rustc_session::cstore::{CrateSource, MetadataLoader};
 use rustc_session::filesearch::FileSearch;
 use rustc_session::search_paths::PathKind;
 use rustc_session::utils::CanonicalizedPath;
 use rustc_session::Session;
-use rustc_span::symbol::{sym, Symbol};
+use rustc_span::symbol::Symbol;
 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};
@@ -287,6 +295,16 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
+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,
@@ -937,41 +955,20 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 
 impl CrateError {
     pub(crate) fn report(self, sess: &Session, span: Span, missing_core: bool) {
-        let mut diag = match self {
-            CrateError::NonAsciiName(crate_name) => sess.struct_span_err(
-                span,
-                &format!("cannot load a crate with a non-ascii name `{}`", crate_name),
-            ),
-            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()),
-            ),
+        match self {
+            CrateError::NonAsciiName(crate_name) => {
+                sess.emit_err(NonAsciiName { span, crate_name });
+            }
+            CrateError::ExternLocationNotExist(crate_name, loc) => {
+                sess.emit_err(ExternLocationNotExist { span, crate_name, location: &loc });
+            }
+            CrateError::ExternLocationNotFile(crate_name, loc) => {
+                sess.emit_err(ExternLocationNotFile { span, crate_name, location: &loc });
+            }
             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
+                sess.emit_err(MultipleCandidates { span, flavor: flavor, crate_name, candidates });
             }
             CrateError::MultipleMatchingCrates(crate_name, libraries) => {
-                let mut err = struct_span_err!(
-                    sess,
-                    span,
-                    E0464,
-                    "multiple matching crates for `{}`",
-                    crate_name
-                );
                 let mut libraries: Vec<_> = libraries.into_values().collect();
                 // Make ordering of candidates deterministic.
                 // This has to `clone()` to work around lifetime restrictions with `sort_by_key()`.
@@ -999,223 +996,142 @@ pub(crate) fn report(self, sess: &Session, span: Span, missing_core: bool) {
                         s
                     })
                     .collect::<String>();
-                err.note(&format!("candidates:{}", candidates));
-                err
+                sess.emit_err(MultipleMatchingCrates { span, crate_name, candidates });
+            }
+            CrateError::SymbolConflictsCurrent(root_name) => {
+                sess.emit_err(SymbolConflictsCurrent { span, crate_name: root_name });
+            }
+            CrateError::SymbolConflictsOthers(root_name) => {
+                sess.emit_err(SymbolConflictsOthers { span, crate_name: root_name });
             }
-            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::StableCrateIdCollision(crate_name0, crate_name1) => {
-                let msg = format!(
-                    "found crates (`{}` and `{}`) with colliding StableCrateId values.",
-                    crate_name0, crate_name1
-                );
-                sess.struct_span_err(span, &msg)
+                sess.emit_err(StableCrateIdCollision {
+                    span,
+                    crate_name0: crate_name0,
+                    crate_name1: crate_name1,
+                });
+            }
+            CrateError::DlOpen(s) | CrateError::DlSym(s) => {
+                sess.emit_err(DlError { span, err: s });
             }
-            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 {
+                let add_info = 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.crate_rejections.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?");
+                // 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 {
+                        sess.emit_err(CrateLocationUnknownType { span, path: &path });
+                        sess.emit_err(LibFilenameForm {
+                            span,
+                            dll_prefix: &locator.dll_prefix,
+                            dll_suffix: &locator.dll_suffix,
+                        });
+                    }
+                }
+                let mut found_crates = String::new();
+                if !locator.crate_rejections.via_hash.is_empty() {
                     let mismatches = locator.crate_rejections.via_hash.iter();
                     for CrateMismatch { path, .. } in mismatches {
-                        msg.push_str(&format!("\ncrate `{}`: {}", crate_name, path.display()));
+                        found_crates.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()));
+                            found_crates.push_str(&format!(
+                                "\ncrate `{}`: {}",
+                                r.name,
+                                path.display()
+                            ));
                         }
                     }
-                    err.note(&msg);
-                    err
-                } else if !locator.crate_rejections.via_triple.is_empty() {
-                    let mut err = struct_span_err!(
-                        sess,
+                    sess.emit_err(NewerCrateVersion {
                         span,
-                        E0461,
-                        "couldn't find crate `{}` with expected target triple {}{}",
-                        crate_name,
-                        locator.triple,
-                        add,
-                    );
+                        crate_name: crate_name,
+                        add_info,
+                        found_crates,
+                    });
+                } else if !locator.crate_rejections.via_triple.is_empty() {
                     let mismatches = locator.crate_rejections.via_triple.iter();
                     for CrateMismatch { path, got } in mismatches {
-                        msg.push_str(&format!(
+                        found_crates.push_str(&format!(
                             "\ncrate `{}`, target triple {}: {}",
                             crate_name,
                             got,
                             path.display(),
                         ));
                     }
-                    err.note(&msg);
-                    err
-                } else if !locator.crate_rejections.via_kind.is_empty() {
-                    let mut err = struct_span_err!(
-                        sess,
+                    sess.emit_err(NoCrateWithTriple {
                         span,
-                        E0462,
-                        "found staticlib `{}` instead of rlib or dylib{}",
-                        crate_name,
-                        add,
-                    );
-                    err.help("please recompile that crate using --crate-type lib");
+                        crate_name: crate_name,
+                        locator_triple: locator.triple.triple(),
+                        add_info,
+                        found_crates,
+                    });
+                } else if !locator.crate_rejections.via_kind.is_empty() {
                     let mismatches = locator.crate_rejections.via_kind.iter();
                     for CrateMismatch { path, .. } in mismatches {
-                        msg.push_str(&format!("\ncrate `{}`: {}", crate_name, path.display()));
+                        found_crates.push_str(&format!(
+                            "\ncrate `{}`: {}",
+                            crate_name,
+                            path.display()
+                        ));
                     }
-                    err.note(&msg);
-                    err
+                    sess.emit_err(FoundStaticlib { span, crate_name, add_info, found_crates });
                 } else if !locator.crate_rejections.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 ({}) \
-                         (consider running `cargo clean` first)",
-                        rustc_version(),
-                    ));
                     let mismatches = locator.crate_rejections.via_version.iter();
                     for CrateMismatch { path, got } in mismatches {
-                        msg.push_str(&format!(
+                        found_crates.push_str(&format!(
                             "\ncrate `{}` compiled by {}: {}",
                             crate_name,
                             got,
                             path.display(),
                         ));
                     }
-                    err.note(&msg);
-                    err
-                } else if !locator.crate_rejections.via_invalid.is_empty() {
-                    let mut err = struct_span_err!(
-                        sess,
+                    sess.emit_err(IncompatibleRustc {
                         span,
-                        E0786,
-                        "found invalid metadata files for crate `{}`{}",
                         crate_name,
-                        add,
-                    );
+                        add_info,
+                        found_crates,
+                        rustc_version: rustc_version(),
+                    });
+                } else if !locator.crate_rejections.via_invalid.is_empty() {
+                    let mut crate_rejections = Vec::new();
                     for CrateMismatch { path: _, got } in locator.crate_rejections.via_invalid {
-                        err.note(&got);
+                        crate_rejections.push(got);
                     }
-                    err
+                    sess.emit_err(InvalidMetadataFiles {
+                        span,
+                        crate_name,
+                        add_info,
+                        crate_rejections,
+                    });
                 } else {
-                    let mut err = struct_span_err!(
-                        sess,
+                    sess.emit_err(CannotFindCrate {
                         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())
-                    {
-                        if missing_core {
-                            err.note(&format!(
-                                "the `{}` target may not be installed",
-                                locator.triple
-                            ));
-                        } else {
-                            err.note(&format!(
-                                "the `{}` target may not support the standard library",
-                                locator.triple
-                            ));
-                        }
-                        // 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 missing_core {
-                            err.help(&format!(
-                                "consider downloading the target with `rustup target add {}`",
-                                locator.triple
-                            ));
-                        }
-                        // 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 !missing_core && span.is_dummy() {
-                            let current_crate =
-                                sess.opts.crate_name.as_deref().unwrap_or("<unknown>");
-                            err.note(&format!(
-                                "`std` is required by `{}` because it does not declare `#![no_std]`",
-                                current_crate
-                            ));
-                        }
-                        if sess.is_nightly_build() {
-                            err.help("consider building the standard library from source with `cargo build -Zbuild-std`");
-                        }
-                    } else if crate_name
-                        == Symbol::intern(&sess.opts.unstable_opts.profiler_runtime)
-                    {
-                        err.note("the compiler may have been built without the profiler runtime");
-                    } else if crate_name.as_str().starts_with("rustc_") {
-                        err.help(
-                            "maybe you need to install the missing components with: \
-                             `rustup component add rust-src rustc-dev llvm-tools-preview`",
-                        );
-                    }
-                    err.span_label(span, "can't find crate");
-                    err
-                };
-
-                if !locator.crate_rejections.via_filename.is_empty() {
-                    let mismatches = locator.crate_rejections.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
-                        ));
-                    }
+                        add_info,
+                        missing_core,
+                        current_crate: sess
+                            .opts
+                            .crate_name
+                            .clone()
+                            .unwrap_or("<unknown>".to_string()),
+                        is_nightly_build: sess.is_nightly_build(),
+                        profiler_runtime: Symbol::intern(&sess.opts.unstable_opts.profiler_runtime),
+                        locator_triple: locator.triple,
+                    });
                 }
-                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,
-            ),
-        };
-
-        diag.emit();
+            CrateError::NonDylibPlugin(crate_name) => {
+                sess.emit_err(NoDylibPlugin { span, crate_name });
+            }
+        }
     }
 }