From 4533a77118114d0e1553518357ad850dce0e2d75 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Mon, 2 Oct 2023 12:32:31 +0000 Subject: [PATCH] Stop mentioning internal lang items in no_std binary errors When writing a no_std binary, you'll be greeted with nonsensical errors mentioning lang items like eh_personality and start. That's pretty bad because it makes you think that you need to define them somewhere! But oh no, now you're getting the `internal_features` lint telling you that you shouldn't use them! But you need a no_std binary! What now? No problem! Writing a no_std binary is super easy. Just use panic=abort and supply your own platform specific entrypoint symbol (like `main`) and you're good to go. Would be nice if the compiler told you that, right? This makes it so that it does do that. --- compiler/rustc_monomorphize/messages.ftl | 3 +++ compiler/rustc_monomorphize/src/collector.rs | 6 ++++-- compiler/rustc_monomorphize/src/errors.rs | 5 +++++ compiler/rustc_passes/messages.ftl | 5 +++++ compiler/rustc_passes/src/errors.rs | 6 ++++++ compiler/rustc_passes/src/weak_lang_items.rs | 6 +++++- src/tools/tidy/src/ui_tests.rs | 2 +- tests/ui/extern-flag/empty-extern-arg.stderr | 6 +++--- tests/ui/lang-items/required-lang-item.rs | 7 +++---- tests/ui/lang-items/required-lang-item.stderr | 6 +++++- tests/ui/no_std/no-std-no-start-binary.rs | 13 +++++++++++++ tests/ui/no_std/no-std-no-start-binary.stderr | 6 ++++++ tests/ui/no_std/no-std-unwind-binary.rs | 13 +++++++++++++ tests/ui/no_std/no-std-unwind-binary.stderr | 7 +++++++ tests/ui/panic-handler/weak-lang-item.rs | 2 +- tests/ui/panic-handler/weak-lang-item.stderr | 6 +++--- 16 files changed, 83 insertions(+), 16 deletions(-) create mode 100644 tests/ui/no_std/no-std-no-start-binary.rs create mode 100644 tests/ui/no_std/no-std-no-start-binary.stderr create mode 100644 tests/ui/no_std/no-std-unwind-binary.rs create mode 100644 tests/ui/no_std/no-std-unwind-binary.stderr diff --git a/compiler/rustc_monomorphize/messages.ftl b/compiler/rustc_monomorphize/messages.ftl index e27875853df08..94b553a07a755 100644 --- a/compiler/rustc_monomorphize/messages.ftl +++ b/compiler/rustc_monomorphize/messages.ftl @@ -20,6 +20,9 @@ monomorphize_recursion_limit = reached the recursion limit while instantiating `{$shrunk}` .note = `{$def_path_str}` defined here +monomorphize_start_not_found = using `fn main` requires the standard library + .help = use `#![no_main]` to bypass the Rust generated entrypoint and declare a platform specific entrypoint yourself, usually with `#[no_mangle]` + monomorphize_symbol_already_defined = symbol `{$symbol}` is already defined monomorphize_type_length_limit = reached the type-length limit while instantiating `{$shrunk}` diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 44beafa08736e..92f001cc3212e 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -194,7 +194,7 @@ use rustc_target::abi::Size; use std::path::PathBuf; use crate::errors::{ - EncounteredErrorWhileInstantiating, LargeAssignmentsLint, NoOptimizedMir, RecursionLimit, + self, EncounteredErrorWhileInstantiating, LargeAssignmentsLint, NoOptimizedMir, RecursionLimit, TypeLengthLimit, }; @@ -1272,7 +1272,9 @@ impl<'v> RootCollector<'_, 'v> { return; }; - let start_def_id = self.tcx.require_lang_item(LangItem::Start, None); + let Some(start_def_id) = self.tcx.lang_items().start_fn() else { + self.tcx.dcx().emit_fatal(errors::StartNotFound); + }; let main_ret_ty = self.tcx.fn_sig(main_def_id).no_bound_vars().unwrap().output(); // Given that `main()` has no arguments, diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs index 2ca14673a58a3..bd89874b5cc48 100644 --- a/compiler/rustc_monomorphize/src/errors.rs +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -94,6 +94,11 @@ pub struct EncounteredErrorWhileInstantiating { pub formatted_item: String, } +#[derive(Diagnostic)] +#[diag(monomorphize_start_not_found)] +#[help] +pub struct StartNotFound; + #[derive(Diagnostic)] #[diag(monomorphize_unknown_cgu_collection_mode)] pub struct UnknownCguCollectionMode<'a> { diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index be50aad13032f..d41cc724408a4 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -575,6 +575,11 @@ passes_outside_loop = passes_outside_loop_suggestion = consider labeling this block to be able to break within it +passes_panic_unwind_without_std = + unwinding panics are not supported without std + .note = since the core library is usually precompiled with panic="unwind", rebuilding your crate with panic="abort" may not be enough to fix the problem + .help = using nightly cargo, use -Zbuild-std with panic="abort" to avoid unwinding + passes_params_not_allowed = referencing function parameters is not allowed in naked functions .help = follow the calling convention in asm block to use parameters diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 9bd9dd41cf691..c099bb1dfe241 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -812,6 +812,12 @@ pub struct UnknownExternLangItem { #[diag(passes_missing_panic_handler)] pub struct MissingPanicHandler; +#[derive(Diagnostic)] +#[diag(passes_panic_unwind_without_std)] +#[help] +#[note] +pub struct PanicUnwindWithoutStd; + #[derive(Diagnostic)] #[diag(passes_missing_lang_item)] #[note] diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs index db3d442676eb1..4eb0c6c275e61 100644 --- a/compiler/rustc_passes/src/weak_lang_items.rs +++ b/compiler/rustc_passes/src/weak_lang_items.rs @@ -9,7 +9,9 @@ use rustc_middle::middle::lang_items::required; use rustc_middle::ty::TyCtxt; use rustc_session::config::CrateType; -use crate::errors::{MissingLangItem, MissingPanicHandler, UnknownExternLangItem}; +use crate::errors::{ + MissingLangItem, MissingPanicHandler, PanicUnwindWithoutStd, UnknownExternLangItem, +}; /// Checks the crate for usage of weak lang items, returning a vector of all the /// language items required by this crate, but not defined yet. @@ -76,6 +78,8 @@ fn verify(tcx: TyCtxt<'_>, items: &lang_items::LanguageItems) { if missing.contains(&item) && required(tcx, item) && items.get(item).is_none() { if item == LangItem::PanicImpl { tcx.dcx().emit_err(MissingPanicHandler); + } else if item == LangItem::EhPersonality { + tcx.dcx().emit_err(PanicUnwindWithoutStd); } else { tcx.dcx().emit_err(MissingLangItem { name: item.name() }); } diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index b4745d4883c55..a8857878de362 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -11,7 +11,7 @@ use std::path::{Path, PathBuf}; const ENTRY_LIMIT: usize = 900; // FIXME: The following limits should be reduced eventually. const ISSUES_ENTRY_LIMIT: usize = 1849; -const ROOT_ENTRY_LIMIT: usize = 867; +const ROOT_ENTRY_LIMIT: usize = 868; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ "rs", // test source files diff --git a/tests/ui/extern-flag/empty-extern-arg.stderr b/tests/ui/extern-flag/empty-extern-arg.stderr index 54b5e66fc2100..79efcc5d8b041 100644 --- a/tests/ui/extern-flag/empty-extern-arg.stderr +++ b/tests/ui/extern-flag/empty-extern-arg.stderr @@ -2,10 +2,10 @@ error: extern location for std does not exist: error: `#[panic_handler]` function required, but not found -error: language item required, but not found: `eh_personality` +error: unwinding panics are not supported without std | - = note: this can occur when a binary crate with `#![no_std]` is compiled for a target where `eh_personality` is defined in the standard library - = help: you may be able to compile for a target that doesn't need `eh_personality`, specify a target with `--target` or in `.cargo/config` + = help: using nightly cargo, use -Zbuild-std with panic="abort" to avoid unwinding + = note: since the core library is usually precompiled with panic="unwind", rebuilding your crate with panic="abort" may not be enough to fix the problem error: aborting due to 3 previous errors diff --git a/tests/ui/lang-items/required-lang-item.rs b/tests/ui/lang-items/required-lang-item.rs index 3b17c5b72551d..7f8933ac2ad65 100644 --- a/tests/ui/lang-items/required-lang-item.rs +++ b/tests/ui/lang-items/required-lang-item.rs @@ -1,11 +1,10 @@ -// build-fail +// edition: 2018 #![feature(lang_items, no_core)] #![no_core] +#![no_main] #[lang="copy"] pub trait Copy { } #[lang="sized"] pub trait Sized { } -// error-pattern:requires `start` lang_item - -fn main() {} +async fn x() {} //~ ERROR requires `ResumeTy` lang_item diff --git a/tests/ui/lang-items/required-lang-item.stderr b/tests/ui/lang-items/required-lang-item.stderr index bb53d336bb29d..13c07ee652933 100644 --- a/tests/ui/lang-items/required-lang-item.stderr +++ b/tests/ui/lang-items/required-lang-item.stderr @@ -1,4 +1,8 @@ -error: requires `start` lang_item +error: requires `ResumeTy` lang_item + --> $DIR/required-lang-item.rs:10:14 + | +LL | async fn x() {} + | ^^ error: aborting due to 1 previous error diff --git a/tests/ui/no_std/no-std-no-start-binary.rs b/tests/ui/no_std/no-std-no-start-binary.rs new file mode 100644 index 0000000000000..ce1c871f6a691 --- /dev/null +++ b/tests/ui/no_std/no-std-no-start-binary.rs @@ -0,0 +1,13 @@ +// compile-flags: -Cpanic=abort --emit link +// error-pattern:using `fn main` requires the standard library + +// Make sure that we don't emit an error message mentioning internal lang items. + +#![no_std] + +#[panic_handler] +fn handler(_info: &core::panic::PanicInfo<'_>) -> ! { + loop {} +} + +fn main() {} diff --git a/tests/ui/no_std/no-std-no-start-binary.stderr b/tests/ui/no_std/no-std-no-start-binary.stderr new file mode 100644 index 0000000000000..dd06c234da294 --- /dev/null +++ b/tests/ui/no_std/no-std-no-start-binary.stderr @@ -0,0 +1,6 @@ +error: using `fn main` requires the standard library + | + = help: use `#![no_main]` to bypass the Rust generated entrypoint and declare a platform specific entrypoint yourself, usually with `#[no_mangle]` + +error: aborting due to 1 previous error + diff --git a/tests/ui/no_std/no-std-unwind-binary.rs b/tests/ui/no_std/no-std-unwind-binary.rs new file mode 100644 index 0000000000000..7e8f4445d6b0a --- /dev/null +++ b/tests/ui/no_std/no-std-unwind-binary.rs @@ -0,0 +1,13 @@ +// error-pattern:unwinding panics are not supported without std + +// Make sure that we don't emit an error message mentioning internal lang items. + +#![no_std] +#![no_main] + +#[panic_handler] +fn handler(_info: &core::panic::PanicInfo<'_>) -> ! { + loop {} +} + +fn main() {} diff --git a/tests/ui/no_std/no-std-unwind-binary.stderr b/tests/ui/no_std/no-std-unwind-binary.stderr new file mode 100644 index 0000000000000..a3b54fe33ab4b --- /dev/null +++ b/tests/ui/no_std/no-std-unwind-binary.stderr @@ -0,0 +1,7 @@ +error: unwinding panics are not supported without std + | + = help: using nightly cargo, use -Zbuild-std with panic="abort" to avoid unwinding + = note: since the core library is usually precompiled with panic="unwind", rebuilding your crate with panic="abort" may not be enough to fix the problem + +error: aborting due to 1 previous error + diff --git a/tests/ui/panic-handler/weak-lang-item.rs b/tests/ui/panic-handler/weak-lang-item.rs index 14a07a9ef1b55..296a2c1514f13 100644 --- a/tests/ui/panic-handler/weak-lang-item.rs +++ b/tests/ui/panic-handler/weak-lang-item.rs @@ -1,6 +1,6 @@ // aux-build:weak-lang-items.rs // error-pattern: `#[panic_handler]` function required, but not found -// error-pattern: language item required, but not found: `eh_personality` +// error-pattern: unwinding panics are not supported without std // needs-unwind since it affects the error output // ignore-emscripten missing eh_catch_typeinfo lang item diff --git a/tests/ui/panic-handler/weak-lang-item.stderr b/tests/ui/panic-handler/weak-lang-item.stderr index 202f3309d035e..de351d2c3e4aa 100644 --- a/tests/ui/panic-handler/weak-lang-item.stderr +++ b/tests/ui/panic-handler/weak-lang-item.stderr @@ -12,10 +12,10 @@ LL | extern crate core as other_core; error: `#[panic_handler]` function required, but not found -error: language item required, but not found: `eh_personality` +error: unwinding panics are not supported without std | - = note: this can occur when a binary crate with `#![no_std]` is compiled for a target where `eh_personality` is defined in the standard library - = help: you may be able to compile for a target that doesn't need `eh_personality`, specify a target with `--target` or in `.cargo/config` + = help: using nightly cargo, use -Zbuild-std with panic="abort" to avoid unwinding + = note: since the core library is usually precompiled with panic="unwind", rebuilding your crate with panic="abort" may not be enough to fix the problem error: aborting due to 3 previous errors