Skip to content

Commit

Permalink
Stop mentioning internal lang items in no_std binary errors
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Nilstrieb committed Oct 2, 2023
1 parent b0889cb commit a5a795a
Show file tree
Hide file tree
Showing 16 changed files with 79 additions and 15 deletions.
3 changes: 3 additions & 0 deletions compiler/rustc_monomorphize/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ monomorphize_recursion_limit =
reached the recursion limit while instantiating `{$shrunk}`
.note = `{$def_path_str}` defined here
monomorphize_start_not_found = no Rust entrypoint found
.help = use `#![no_main]` to bypass the Rust generated entrypoint and declare a platform specific entrypoint yourself
monomorphize_symbol_already_defined = symbol `{$symbol}` is already defined
monomorphize_type_length_limit = reached the type-length limit while instantiating `{$shrunk}`
Expand Down
6 changes: 4 additions & 2 deletions compiler/rustc_monomorphize/src/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ use rustc_target::abi::Size;
use std::path::PathBuf;

use crate::errors::{
EncounteredErrorWhileInstantiating, LargeAssignmentsLint, NoOptimizedMir, RecursionLimit,
self, EncounteredErrorWhileInstantiating, LargeAssignmentsLint, NoOptimizedMir, RecursionLimit,
TypeLengthLimit,
};

Expand Down Expand Up @@ -1233,7 +1233,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.sess.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,
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_monomorphize/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,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> {
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_passes/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,10 @@ passes_outside_loop =
*[false] {""}
}
passes_panic_unwind_without_std =
panic unwind is not supported without std
.help = specify panic="abort" instead
passes_params_not_allowed =
referencing function parameters is not allowed in naked functions
.help = follow the calling convention in asm block to use parameters
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_passes/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -809,6 +809,11 @@ pub struct UnknownExternLangItem {
#[diag(passes_missing_panic_handler)]
pub struct MissingPanicHandler;

#[derive(Diagnostic)]
#[diag(passes_panic_unwind_without_std)]
#[help]
pub struct PanicUnwindWithoutStd;

#[derive(Diagnostic)]
#[diag(passes_missing_lang_item)]
#[note]
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_passes/src/weak_lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,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.
Expand Down Expand Up @@ -66,6 +68,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.sess.emit_err(MissingPanicHandler);
} else if item == LangItem::EhPersonality {
tcx.sess.emit_err(PanicUnwindWithoutStd);
} else {
tcx.sess.emit_err(MissingLangItem { name: item.name() });
}
Expand Down
2 changes: 1 addition & 1 deletion src/tools/tidy/src/ui_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 = 1854;
const ROOT_ENTRY_LIMIT: usize = 865;
const ROOT_ENTRY_LIMIT: usize = 866;

const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
"rs", // test source files
Expand Down
5 changes: 2 additions & 3 deletions tests/ui/extern-flag/empty-extern-arg.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ 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: `panic unwind is 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: specify panic="abort" instead

error: aborting due to 3 previous errors

7 changes: 4 additions & 3 deletions tests/ui/lang-items/required-lang-item.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
// 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 `future_trait` lang_item
6 changes: 5 additions & 1 deletion tests/ui/lang-items/required-lang-item.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
error: requires `start` lang_item
error: requires `future_trait` lang_item
--> $DIR/required-lang-item.rs:12:14
|
LL | async fn x() {}
| ^

error: aborting due to previous error

13 changes: 13 additions & 0 deletions tests/ui/no_std/no-std-no-start-binary.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// compile-flags: -Cpanic=abort --emit link
// error-pattern:no Rust entrypoint found

// 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() {}
6 changes: 6 additions & 0 deletions tests/ui/no_std/no-std-no-start-binary.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
error: no Rust entrypoint found
|
= help: use `#![no_main]` to bypass the Rust generated entrypoint and declare a platform specific entrypoint yourself

error: aborting due to previous error

13 changes: 13 additions & 0 deletions tests/ui/no_std/no-std-unwind-binary.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// error-pattern:panic unwind is 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() {}
6 changes: 6 additions & 0 deletions tests/ui/no_std/no-std-unwind-binary.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
error: panic unwind is not supported without std
|
= help: specify panic="abort" instead

error: aborting due to previous error

2 changes: 1 addition & 1 deletion tests/ui/panic-handler/weak-lang-item.rs
Original file line number Diff line number Diff line change
@@ -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: panic unwind is not supported without std
// needs-unwind since it affects the error output
// ignore-emscripten missing eh_catch_typeinfo lang item

Expand Down
5 changes: 2 additions & 3 deletions tests/ui/panic-handler/weak-lang-item.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,9 @@ 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: `panic unwind is 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: specify panic="abort" instead

error: aborting due to 3 previous errors

Expand Down

0 comments on commit a5a795a

Please sign in to comment.