Skip to content

Commit bbbe28d

Browse files
committed
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.
1 parent b0889cb commit bbbe28d

16 files changed

+79
-15
lines changed

compiler/rustc_monomorphize/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ monomorphize_recursion_limit =
2222
reached the recursion limit while instantiating `{$shrunk}`
2323
.note = `{$def_path_str}` defined here
2424
25+
monomorphize_start_not_found = no Rust entrypoint found
26+
.help = use `#![no_main]` to bypass the Rust generated entrypoint and declare a platform specific entrypoint yourself
27+
2528
monomorphize_symbol_already_defined = symbol `{$symbol}` is already defined
2629
2730
monomorphize_type_length_limit = reached the type-length limit while instantiating `{$shrunk}`

compiler/rustc_monomorphize/src/collector.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ use rustc_target::abi::Size;
192192
use std::path::PathBuf;
193193

194194
use crate::errors::{
195-
EncounteredErrorWhileInstantiating, LargeAssignmentsLint, NoOptimizedMir, RecursionLimit,
195+
self, EncounteredErrorWhileInstantiating, LargeAssignmentsLint, NoOptimizedMir, RecursionLimit,
196196
TypeLengthLimit,
197197
};
198198

@@ -1233,7 +1233,9 @@ impl<'v> RootCollector<'_, 'v> {
12331233
return;
12341234
};
12351235

1236-
let start_def_id = self.tcx.require_lang_item(LangItem::Start, None);
1236+
let Some(start_def_id) = self.tcx.lang_items().start_fn() else {
1237+
self.tcx.sess.emit_fatal(errors::StartNotFound);
1238+
};
12371239
let main_ret_ty = self.tcx.fn_sig(main_def_id).no_bound_vars().unwrap().output();
12381240

12391241
// Given that `main()` has no arguments,

compiler/rustc_monomorphize/src/errors.rs

+5
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,11 @@ pub struct EncounteredErrorWhileInstantiating {
101101
pub formatted_item: String,
102102
}
103103

104+
#[derive(Diagnostic)]
105+
#[diag(monomorphize_start_not_found)]
106+
#[help]
107+
pub struct StartNotFound;
108+
104109
#[derive(Diagnostic)]
105110
#[diag(monomorphize_unknown_cgu_collection_mode)]
106111
pub struct UnknownCguCollectionMode<'a> {

compiler/rustc_passes/messages.ftl

+4
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,10 @@ passes_outside_loop =
580580
*[false] {""}
581581
}
582582
583+
passes_panic_unwind_without_std =
584+
panic unwind is not supported without std
585+
.help = specify panic="abort" instead
586+
583587
passes_params_not_allowed =
584588
referencing function parameters is not allowed in naked functions
585589
.help = follow the calling convention in asm block to use parameters

compiler/rustc_passes/src/errors.rs

+5
Original file line numberDiff line numberDiff line change
@@ -809,6 +809,11 @@ pub struct UnknownExternLangItem {
809809
#[diag(passes_missing_panic_handler)]
810810
pub struct MissingPanicHandler;
811811

812+
#[derive(Diagnostic)]
813+
#[diag(passes_panic_unwind_without_std)]
814+
#[help]
815+
pub struct PanicUnwindWithoutStd;
816+
812817
#[derive(Diagnostic)]
813818
#[diag(passes_missing_lang_item)]
814819
#[note]

compiler/rustc_passes/src/weak_lang_items.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ use rustc_middle::middle::lang_items::required;
77
use rustc_middle::ty::TyCtxt;
88
use rustc_session::config::CrateType;
99

10-
use crate::errors::{MissingLangItem, MissingPanicHandler, UnknownExternLangItem};
10+
use crate::errors::{
11+
MissingLangItem, MissingPanicHandler, PanicUnwindWithoutStd, UnknownExternLangItem,
12+
};
1113

1214
/// Checks the crate for usage of weak lang items, returning a vector of all the
1315
/// language items required by this crate, but not defined yet.
@@ -66,6 +68,8 @@ fn verify(tcx: TyCtxt<'_>, items: &lang_items::LanguageItems) {
6668
if missing.contains(&item) && required(tcx, item) && items.get(item).is_none() {
6769
if item == LangItem::PanicImpl {
6870
tcx.sess.emit_err(MissingPanicHandler);
71+
} else if item == LangItem::EhPersonality {
72+
tcx.sess.emit_err(PanicUnwindWithoutStd);
6973
} else {
7074
tcx.sess.emit_err(MissingLangItem { name: item.name() });
7175
}

src/tools/tidy/src/ui_tests.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use std::path::{Path, PathBuf};
1111
const ENTRY_LIMIT: usize = 900;
1212
// FIXME: The following limits should be reduced eventually.
1313
const ISSUES_ENTRY_LIMIT: usize = 1854;
14-
const ROOT_ENTRY_LIMIT: usize = 865;
14+
const ROOT_ENTRY_LIMIT: usize = 866;
1515

1616
const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
1717
"rs", // test source files

tests/ui/extern-flag/empty-extern-arg.stderr

+2-3
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@ error: extern location for std does not exist:
22

33
error: `#[panic_handler]` function required, but not found
44

5-
error: language item required, but not found: `eh_personality`
5+
error: panic unwind is not supported without std
66
|
7-
= 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
8-
= 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`
7+
= help: specify panic="abort" instead
98

109
error: aborting due to 3 previous errors
1110

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
// build-fail
1+
// edition: 2018
22

33
#![feature(lang_items, no_core)]
44
#![no_core]
5+
#![no_main]
56

67
#[lang="copy"] pub trait Copy { }
78
#[lang="sized"] pub trait Sized { }
89

9-
// error-pattern:requires `start` lang_item
10-
1110
fn main() {}
11+
12+
async fn x() {} //~ ERROR requires `future_trait` lang_item
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
error: requires `start` lang_item
1+
error: requires `future_trait` lang_item
2+
--> $DIR/required-lang-item.rs:12:14
3+
|
4+
LL | async fn x() {}
5+
| ^
26

37
error: aborting due to previous error
48

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// compile-flags: -Cpanic=abort --emit link
2+
// error-pattern:no Rust entrypoint found
3+
4+
// Make sure that we don't emit an error message mentioning internal lang items.
5+
6+
#![no_std]
7+
8+
#[panic_handler]
9+
fn handler(_info: &core::panic::PanicInfo<'_>) -> ! {
10+
loop {}
11+
}
12+
13+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
error: no Rust entrypoint found
2+
|
3+
= help: use `#![no_main]` to bypass the Rust generated entrypoint and declare a platform specific entrypoint yourself
4+
5+
error: aborting due to previous error
6+
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// error-pattern:panic unwind is not supported without std
2+
3+
// Make sure that we don't emit an error message mentioning internal lang items.
4+
5+
#![no_std]
6+
#![no_main]
7+
8+
#[panic_handler]
9+
fn handler(_info: &core::panic::PanicInfo<'_>) -> ! {
10+
loop {}
11+
}
12+
13+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
error: panic unwind is not supported without std
2+
|
3+
= help: specify panic="abort" instead
4+
5+
error: aborting due to previous error
6+

tests/ui/panic-handler/weak-lang-item.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// aux-build:weak-lang-items.rs
22
// error-pattern: `#[panic_handler]` function required, but not found
3-
// error-pattern: language item required, but not found: `eh_personality`
3+
// error-pattern: panic unwind is not supported without std
44
// needs-unwind since it affects the error output
55
// ignore-emscripten missing eh_catch_typeinfo lang item
66

tests/ui/panic-handler/weak-lang-item.stderr

+2-3
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,9 @@ LL | extern crate core as other_core;
1212

1313
error: `#[panic_handler]` function required, but not found
1414

15-
error: language item required, but not found: `eh_personality`
15+
error: panic unwind is not supported without std
1616
|
17-
= 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
18-
= 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`
17+
= help: specify panic="abort" instead
1918

2019
error: aborting due to 3 previous errors
2120

0 commit comments

Comments
 (0)