Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rfc 2070 panic implementation deprecated #467

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -134,17 +134,19 @@ This sets the panic strategy to `abort` for both the `dev` profile (used for `ca

### Panic Implementation

The `panic_impl` language item defines the function that the compiler should invoke when a [panic] occurs. Instead of providing the language item directly, we can use the [`panic_implementation`] attribute to create a `panic` function:
The `panic_impl` language item defines the function that the compiler should invoke when a [panic] occurs. Instead of providing the language item directly, we can use the [`panic_handler`] attribute to create a `panic` function. This used to take the for [`panic_implementation`], which has been deprecated and replaced by [`panic_handler`].

[`panic_implementation`]: https://github.com/rust-lang/rfcs/blob/master/text/2070-panic-implementation.md#panic_implementation

Note: [`panic_implementation`] has been deprecated, and we now use [`panic_handler`] instead

```rust
// in main.rs

use core::panic::PanicInfo;

/// This function is called on panic.
#[panic_implementation]
#[panic_handler]
#[no_mangle]
pub fn panic(_info: &PanicInfo) -> ! {
loop {}
Expand All @@ -157,11 +159,11 @@ The [`PanicInfo` parameter][PanicInfo] contains the file and line where the pani
[diverging function]: https://doc.rust-lang.org/book/first-edition/functions.html#diverging-functions
[“never” type]: https://doc.rust-lang.org/nightly/std/primitive.never.html

When we try `cargo build` now, we get an error that “#[panic_implementation] is an unstable feature”.
When we try `cargo build` now, we get an error that “#[panic_handler] is an unstable feature”.

#### Enabling Unstable Features

The `panic_implementation` attribute was recently added and is thus still unstable and protected by a so-called _feature gate_. A feature gate is a special attribute that you have to specify at the top of your `main.rs` in order to use the corresponding feature. By doing this you basically say: “I know that this feature is unstable and that it might stop working without any warnings. I want to use it anyway.”
The `panic_handler` attribute was recently added and is thus still unstable and protected by a so-called _feature gate_. A feature gate is a special attribute that you have to specify at the top of your `main.rs` in order to use the corresponding feature. By doing this you basically say: “I know that this feature is unstable and that it might stop working without any warnings. I want to use it anyway.”

Feature gates are not available in the stable or beta Rust compilers, only [nightly Rust] makes it possible to opt-in. This means that you have to use a nightly compiler for OS development for the near future (until all unstable features that we need are added are stabilized).

Expand All @@ -171,8 +173,6 @@ To manage Rust installations I highly recommend [rustup]. It allows you to insta

[rustup]: https://www.rustup.rs/

After installing a nightly Rust compiler, you can enable the unstable `panic_implementation` feature by inserting `#![feature(panic_implementation)]` right at the top of `main.rs`.

Now we fixed both language item errors. However, if we try to compile it now, another language item is required:

```
Expand All @@ -196,14 +196,13 @@ Our freestanding executable does not have access to the Rust runtime and `crt0`,
To tell the Rust compiler that we don't want to use the normal entry point chain, we add the `#![no_main]` attribute.

```rust
#![feature(panic_implementation)]
#![no_std]
#![no_main]

use core::panic::PanicInfo;

/// This function is called on panic.
#[panic_implementation]
#[panic_handler]
#[no_mangle]
pub fn panic(_info: &PanicInfo) -> ! {
loop {}
Expand Down Expand Up @@ -311,14 +310,13 @@ A minimal freestanding Rust binary looks like this:
`src/main.rs`:

```rust
#![feature(panic_implementation)] // required for defining the panic handler
#![no_std] // don't link the Rust standard library
#![no_main] // disable all Rust-level entry points

use core::panic::PanicInfo;

/// This function is called on panic.
#[panic_implementation]
#[panic_handler]
#[no_mangle]
pub fn panic(_info: &PanicInfo) -> ! {
loop {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,14 +199,13 @@ Compiling for our new target will use Linux conventions (I'm not quite sure why,
```rust
// src/main.rs

#![feature(panic_implementation)] // required for defining the panic handler
#![no_std] // don't link the Rust standard library
#![no_main] // disable all Rust-level entry points

use core::panic::PanicInfo;

/// This function is called on panic.
#[panic_implementation]
#[panic_handler]
#[no_mangle]
pub fn panic(_info: &PanicInfo) -> ! {
loop {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -627,7 +627,7 @@ Now that we have a `println` macro, we can use it in our panic function to print
// in main.rs

/// This function is called on panic.
#[panic_implementation]
#[panic_handler]
#[no_mangle]
pub fn panic(info: &PanicInfo) -> ! {
println!("{}", info);
Expand Down
4 changes: 2 additions & 2 deletions blog/content/second-edition/posts/04-unit-testing/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ error[E0152]: duplicate lang item found: `panic_impl`.
= note: first defined in crate `std`.
```

The problem is that unit tests are built for the host machine, with the `std` library included. This makes sense because they should be able to run as a normal application on the host operating system. Since the standard library has it's own `panic_implementation` function, we get the above error. To fix it, we use [conditional compilation] to include our implementation of the panic handler only in non-test environments:
The problem is that unit tests are built for the host machine, with the `std` library included. This makes sense because they should be able to run as a normal application on the host operating system. Since the standard library has it's own `panic_handler` function, we get the above error. To fix it, we use [conditional compilation] to include our implementation of the panic handler only in non-test environments:

[conditional compilation]: https://doc.rust-lang.org/reference/attributes.html#conditional-compilation

Expand All @@ -48,7 +48,7 @@ The problem is that unit tests are built for the host machine, with the `std` li
use core::panic::PanicInfo;

#[cfg(not(test))] // only compile when the test flag is not set
#[panic_implementation]
#[panic_handler]
#[no_mangle]
pub fn panic(info: &PanicInfo) -> ! {
println!("{}", info);
Expand Down
12 changes: 4 additions & 8 deletions blog/content/second-edition/posts/05-integration-tests/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,6 @@ Cargo allows to add [additional executables] to a project by putting them inside
```rust
// src/bin/test-something.rs

#![feature(panic_implementation)]
#![no_std]
#![cfg_attr(not(test), no_main)]
#![cfg_attr(test, allow(dead_code, unused_macros, unused_imports))]
Expand All @@ -344,7 +343,7 @@ pub extern "C" fn _start() -> ! {
}

#[cfg(not(test))]
#[panic_implementation]
#[panic_handle]
#[no_mangle]
pub fn panic(_info: &PanicInfo) -> ! {
loop {}
Expand Down Expand Up @@ -402,7 +401,6 @@ pub unsafe fn exit_qemu() {
```rust
// src/main.rs

#![feature(panic_implementation)] // required for defining the panic handler
#![no_std] // don't link the Rust standard library
#![cfg_attr(not(test), no_main)] // disable all Rust-level entry points
#![cfg_attr(test, allow(dead_code, unused_macros, unused_imports))]
Expand All @@ -425,7 +423,7 @@ pub extern "C" fn _start() -> ! {

/// This function is called on panic.
#[cfg(not(test))]
#[panic_implementation]
#[panic_handler]
#[no_mangle]
pub fn panic(info: &PanicInfo) -> ! {
println!("{}", info);
Expand Down Expand Up @@ -464,7 +462,6 @@ We are finally able to create our first integration test executable. We start si
```rust
// in src/bin/test-basic-boot.rs

#![feature(panic_implementation)] // required for defining the panic handler
#![no_std] // don't link the Rust standard library
#![cfg_attr(not(test), no_main)] // disable all Rust-level entry points
#![cfg_attr(test, allow(dead_code, unused_macros, unused_imports))]
Expand All @@ -490,7 +487,7 @@ pub extern "C" fn _start() -> ! {

/// This function is called on panic.
#[cfg(not(test))]
#[panic_implementation]
#[panic_handler]
#[no_mangle]
pub fn panic(info: &PanicInfo) -> ! {
serial_println!("failed");
Expand Down Expand Up @@ -531,7 +528,6 @@ To test that our panic handler is really invoked on a panic, we create a `test-p
```rust
// in src/bin/test-panic.rs

#![feature(panic_implementation)]
#![no_std]
#![cfg_attr(not(test), no_main)]
#![cfg_attr(test, allow(dead_code, unused_macros, unused_imports))]
Expand All @@ -549,7 +545,7 @@ pub extern "C" fn _start() -> ! {
}

#[cfg(not(test))]
#[panic_implementation]
#[panic_handler]
#[no_mangle]
pub fn panic(_info: &PanicInfo) -> ! {
serial_println!("ok");
Expand Down
3 changes: 1 addition & 2 deletions src/bin/test-basic-boot.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#![feature(panic_implementation)] // required for defining the panic handler
#![no_std] // don't link the Rust standard library
#![cfg_attr(not(test), no_main)] // disable all Rust-level entry points
#![cfg_attr(test, allow(dead_code, unused_macros, unused_imports))]
Expand All @@ -25,7 +24,7 @@ pub extern "C" fn _start() -> ! {

/// This function is called on panic.
#[cfg(not(test))]
#[panic_implementation]
#[panic_handler]
#[no_mangle]
pub fn panic(info: &PanicInfo) -> ! {
serial_println!("failed");
Expand Down
3 changes: 1 addition & 2 deletions src/bin/test-exception-breakpoint.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#![feature(panic_implementation)]
#![feature(abi_x86_interrupt)]
#![no_std]
#![cfg_attr(not(test), no_main)]
Expand Down Expand Up @@ -45,7 +44,7 @@ pub extern "C" fn _start() -> ! {

/// This function is called on panic.
#[cfg(not(test))]
#[panic_implementation]
#[panic_handler]
#[no_mangle]
pub fn panic(info: &PanicInfo) -> ! {
serial_println!("failed");
Expand Down
3 changes: 1 addition & 2 deletions src/bin/test-exception-double-fault-stack-overflow.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#![feature(panic_implementation)]
#![feature(abi_x86_interrupt)]
#![no_std]
#![cfg_attr(not(test), no_main)]
Expand Down Expand Up @@ -39,7 +38,7 @@ pub extern "C" fn _start() -> ! {

/// This function is called on panic.
#[cfg(not(test))]
#[panic_implementation]
#[panic_handler]
#[no_mangle]
pub fn panic(info: &PanicInfo) -> ! {
serial_println!("failed");
Expand Down
3 changes: 1 addition & 2 deletions src/bin/test-panic.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#![feature(panic_implementation)]
#![no_std]
#![cfg_attr(not(test), no_main)]
#![cfg_attr(test, allow(dead_code, unused_macros, unused_imports))]
Expand All @@ -16,7 +15,7 @@ pub extern "C" fn _start() -> ! {
}

#[cfg(not(test))]
#[panic_implementation]
#[panic_handler]
#[no_mangle]
pub fn panic(_info: &PanicInfo) -> ! {
serial_println!("ok");
Expand Down
3 changes: 1 addition & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#![feature(panic_implementation)] // required for defining the panic handler
#![feature(abi_x86_interrupt)]
#![no_std] // don't link the Rust standard library
#![cfg_attr(not(test), no_main)] // disable all Rust-level entry points
Expand Down Expand Up @@ -35,7 +34,7 @@ pub extern "C" fn _start() -> ! {

/// This function is called on panic.
#[cfg(not(test))]
#[panic_implementation]
#[panic_handler]
#[no_mangle]
pub fn panic(info: &PanicInfo) -> ! {
println!("{}", info);
Expand Down