From d326a4b4c9176193ff0ac445ec14ac50bd081f04 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Thu, 22 Apr 2021 15:23:30 -0400 Subject: [PATCH] Give a better error when std or core are missing - Suggest using `rustup target add` if `RUSTUP_HOME` is set. I don't know if there's any precedent for doing this, but it seems harmless enough and it will be a big help. - Add a note about `#![no_std]` if `std` is missing but not core - On nightly, suggest using `cargo build -Z build-std` if `CARGO` is set - Add a note that std may be unsupported if `std` is missing but not core - Don't suggest `#![no_std]` when the load isn't injected by the compiler --- compiler/rustc_metadata/src/creader.rs | 7 ++-- compiler/rustc_metadata/src/locator.rs | 37 ++++++++++++++++++-- src/test/ui/crate-loading/missing-std.rs | 11 ++++++ src/test/ui/crate-loading/missing-std.stderr | 13 +++++++ 4 files changed, 63 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/crate-loading/missing-std.rs create mode 100644 src/test/ui/crate-loading/missing-std.stderr diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 26db3a5f39d..e9ae22f8ced 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -511,8 +511,11 @@ fn resolve_crate<'b>( if dep.is_none() { self.used_extern_options.insert(name); } - self.maybe_resolve_crate(name, dep_kind, dep) - .unwrap_or_else(|err| err.report(self.sess, span)) + self.maybe_resolve_crate(name, dep_kind, dep).unwrap_or_else(|err| { + let missing_core = + self.maybe_resolve_crate(sym::core, CrateDepKind::Explicit, None).is_err(); + err.report(&self.sess, span, missing_core) + }) } fn maybe_resolve_crate<'b>( diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 7f6311861c1..6e736095090 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -790,7 +790,8 @@ pub fn find_plugin_registrar( ) -> (PathBuf, CrateDisambiguator) { match find_plugin_registrar_impl(sess, metadata_loader, name) { Ok(res) => res, - Err(err) => err.report(sess, span), + // `core` is always available if we got as far as loading plugins. + Err(err) => err.report(sess, span, false), } } @@ -883,7 +884,7 @@ struct CrateMismatch { } impl CrateError { - crate fn report(self, sess: &Session, span: Span) -> ! { + crate fn report(self, sess: &Session, span: Span, missing_core: bool) -> ! { let mut err = match self { CrateError::NonAsciiName(crate_name) => sess.struct_span_err( span, @@ -1068,7 +1069,37 @@ impl CrateError { 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)); + 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 + )); + } + if missing_core && std::env::var("RUSTUP_HOME").is_ok() { + 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(""); + err.note(&format!( + "`std` is required by `{}` because it does not declare `#![no_std]`", + current_crate + )); + } + if sess.is_nightly_build() && std::env::var("CARGO").is_ok() { + err.help("consider building the standard library from source with `cargo build -Zbuild-std`"); + } } else if crate_name == sym::profiler_builtins { err.note(&"the compiler may have been built without the profiler runtime"); } diff --git a/src/test/ui/crate-loading/missing-std.rs b/src/test/ui/crate-loading/missing-std.rs new file mode 100644 index 00000000000..442a7c01e5a --- /dev/null +++ b/src/test/ui/crate-loading/missing-std.rs @@ -0,0 +1,11 @@ +// compile-flags: --target x86_64-unknown-uefi +// rustc-env:CARGO=/usr/bin/cargo +// rustc-env:RUSTUP_HOME=/home/bors/.rustup +#![no_core] +extern crate core; +//~^ ERROR can't find crate for `core` +//~| NOTE can't find crate +//~| NOTE target may not be installed +//~| HELP consider building the standard library from source with `cargo build -Zbuild-std` +//~| HELP consider downloading the target with `rustup target add x86_64-unknown-uefi` +fn main() {} diff --git a/src/test/ui/crate-loading/missing-std.stderr b/src/test/ui/crate-loading/missing-std.stderr new file mode 100644 index 00000000000..25808efdfa6 --- /dev/null +++ b/src/test/ui/crate-loading/missing-std.stderr @@ -0,0 +1,13 @@ +error[E0463]: can't find crate for `core` + --> $DIR/missing-std.rs:5:1 + | +LL | extern crate core; + | ^^^^^^^^^^^^^^^^^^ can't find crate + | + = note: the `x86_64-unknown-uefi` target may not be installed + = help: consider downloading the target with `rustup target add x86_64-unknown-uefi` + = help: consider building the standard library from source with `cargo build -Zbuild-std` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0463`.