Rfc 2070 panic implementation deprecated (#467)

* Make changes to code examples.

* Explain that panic_implementation has been deprecated

* Update attributes in source code.
This commit is contained in:
Ben
2018-10-01 16:38:48 +08:00
committed by Philipp Oppermann
parent 0bd4fcd99e
commit 2a9075d642
10 changed files with 21 additions and 33 deletions

View File

@@ -134,17 +134,19 @@ This sets the panic strategy to `abort` for both the `dev` profile (used for `ca
### Panic Implementation ### 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 [`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 ```rust
// in main.rs // in main.rs
use core::panic::PanicInfo; use core::panic::PanicInfo;
/// This function is called on panic. /// This function is called on panic.
#[panic_implementation] #[panic_handler]
#[no_mangle] #[no_mangle]
pub fn panic(_info: &PanicInfo) -> ! { pub fn panic(_info: &PanicInfo) -> ! {
loop {} loop {}
@@ -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 [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 [“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 #### 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). 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).
@@ -171,8 +173,6 @@ To manage Rust installations I highly recommend [rustup]. It allows you to insta
[rustup]: https://www.rustup.rs/ [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: Now we fixed both language item errors. However, if we try to compile it now, another language item is required:
``` ```
@@ -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. To tell the Rust compiler that we don't want to use the normal entry point chain, we add the `#![no_main]` attribute.
```rust ```rust
#![feature(panic_implementation)]
#![no_std] #![no_std]
#![no_main] #![no_main]
use core::panic::PanicInfo; use core::panic::PanicInfo;
/// This function is called on panic. /// This function is called on panic.
#[panic_implementation] #[panic_handler]
#[no_mangle] #[no_mangle]
pub fn panic(_info: &PanicInfo) -> ! { pub fn panic(_info: &PanicInfo) -> ! {
loop {} loop {}
@@ -311,14 +310,13 @@ A minimal freestanding Rust binary looks like this:
`src/main.rs`: `src/main.rs`:
```rust ```rust
#![feature(panic_implementation)] // required for defining the panic handler
#![no_std] // don't link the Rust standard library #![no_std] // don't link the Rust standard library
#![no_main] // disable all Rust-level entry points #![no_main] // disable all Rust-level entry points
use core::panic::PanicInfo; use core::panic::PanicInfo;
/// This function is called on panic. /// This function is called on panic.
#[panic_implementation] #[panic_handler]
#[no_mangle] #[no_mangle]
pub fn panic(_info: &PanicInfo) -> ! { pub fn panic(_info: &PanicInfo) -> ! {
loop {} loop {}

View File

@@ -199,14 +199,13 @@ Compiling for our new target will use Linux conventions (I'm not quite sure why,
```rust ```rust
// src/main.rs // src/main.rs
#![feature(panic_implementation)] // required for defining the panic handler
#![no_std] // don't link the Rust standard library #![no_std] // don't link the Rust standard library
#![no_main] // disable all Rust-level entry points #![no_main] // disable all Rust-level entry points
use core::panic::PanicInfo; use core::panic::PanicInfo;
/// This function is called on panic. /// This function is called on panic.
#[panic_implementation] #[panic_handler]
#[no_mangle] #[no_mangle]
pub fn panic(_info: &PanicInfo) -> ! { pub fn panic(_info: &PanicInfo) -> ! {
loop {} loop {}

View File

@@ -627,7 +627,7 @@ Now that we have a `println` macro, we can use it in our panic function to print
// in main.rs // in main.rs
/// This function is called on panic. /// This function is called on panic.
#[panic_implementation] #[panic_handler]
#[no_mangle] #[no_mangle]
pub fn panic(info: &PanicInfo) -> ! { pub fn panic(info: &PanicInfo) -> ! {
println!("{}", info); println!("{}", info);

View File

@@ -37,7 +37,7 @@ error[E0152]: duplicate lang item found: `panic_impl`.
= note: first defined in crate `std`. = 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 [conditional compilation]: https://doc.rust-lang.org/reference/attributes.html#conditional-compilation
@@ -48,7 +48,7 @@ The problem is that unit tests are built for the host machine, with the `std` li
use core::panic::PanicInfo; use core::panic::PanicInfo;
#[cfg(not(test))] // only compile when the test flag is not set #[cfg(not(test))] // only compile when the test flag is not set
#[panic_implementation] #[panic_handler]
#[no_mangle] #[no_mangle]
pub fn panic(info: &PanicInfo) -> ! { pub fn panic(info: &PanicInfo) -> ! {
println!("{}", info); println!("{}", info);

View File

@@ -329,7 +329,6 @@ Cargo allows to add [additional executables] to a project by putting them inside
```rust ```rust
// src/bin/test-something.rs // src/bin/test-something.rs
#![feature(panic_implementation)]
#![no_std] #![no_std]
#![cfg_attr(not(test), no_main)] #![cfg_attr(not(test), no_main)]
#![cfg_attr(test, allow(dead_code, unused_macros, unused_imports))] #![cfg_attr(test, allow(dead_code, unused_macros, unused_imports))]
@@ -344,7 +343,7 @@ pub extern "C" fn _start() -> ! {
} }
#[cfg(not(test))] #[cfg(not(test))]
#[panic_implementation] #[panic_handle]
#[no_mangle] #[no_mangle]
pub fn panic(_info: &PanicInfo) -> ! { pub fn panic(_info: &PanicInfo) -> ! {
loop {} loop {}
@@ -402,7 +401,6 @@ pub unsafe fn exit_qemu() {
```rust ```rust
// src/main.rs // src/main.rs
#![feature(panic_implementation)] // required for defining the panic handler
#![no_std] // don't link the Rust standard library #![no_std] // don't link the Rust standard library
#![cfg_attr(not(test), no_main)] // disable all Rust-level entry points #![cfg_attr(not(test), no_main)] // disable all Rust-level entry points
#![cfg_attr(test, allow(dead_code, unused_macros, unused_imports))] #![cfg_attr(test, allow(dead_code, unused_macros, unused_imports))]
@@ -425,7 +423,7 @@ pub extern "C" fn _start() -> ! {
/// This function is called on panic. /// This function is called on panic.
#[cfg(not(test))] #[cfg(not(test))]
#[panic_implementation] #[panic_handler]
#[no_mangle] #[no_mangle]
pub fn panic(info: &PanicInfo) -> ! { pub fn panic(info: &PanicInfo) -> ! {
println!("{}", info); println!("{}", info);
@@ -464,7 +462,6 @@ We are finally able to create our first integration test executable. We start si
```rust ```rust
// in src/bin/test-basic-boot.rs // 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 #![no_std] // don't link the Rust standard library
#![cfg_attr(not(test), no_main)] // disable all Rust-level entry points #![cfg_attr(not(test), no_main)] // disable all Rust-level entry points
#![cfg_attr(test, allow(dead_code, unused_macros, unused_imports))] #![cfg_attr(test, allow(dead_code, unused_macros, unused_imports))]
@@ -490,7 +487,7 @@ pub extern "C" fn _start() -> ! {
/// This function is called on panic. /// This function is called on panic.
#[cfg(not(test))] #[cfg(not(test))]
#[panic_implementation] #[panic_handler]
#[no_mangle] #[no_mangle]
pub fn panic(info: &PanicInfo) -> ! { pub fn panic(info: &PanicInfo) -> ! {
serial_println!("failed"); serial_println!("failed");
@@ -531,7 +528,6 @@ To test that our panic handler is really invoked on a panic, we create a `test-p
```rust ```rust
// in src/bin/test-panic.rs // in src/bin/test-panic.rs
#![feature(panic_implementation)]
#![no_std] #![no_std]
#![cfg_attr(not(test), no_main)] #![cfg_attr(not(test), no_main)]
#![cfg_attr(test, allow(dead_code, unused_macros, unused_imports))] #![cfg_attr(test, allow(dead_code, unused_macros, unused_imports))]
@@ -549,7 +545,7 @@ pub extern "C" fn _start() -> ! {
} }
#[cfg(not(test))] #[cfg(not(test))]
#[panic_implementation] #[panic_handler]
#[no_mangle] #[no_mangle]
pub fn panic(_info: &PanicInfo) -> ! { pub fn panic(_info: &PanicInfo) -> ! {
serial_println!("ok"); serial_println!("ok");

View File

@@ -1,4 +1,3 @@
#![feature(panic_implementation)] // required for defining the panic handler
#![no_std] // don't link the Rust standard library #![no_std] // don't link the Rust standard library
#![cfg_attr(not(test), no_main)] // disable all Rust-level entry points #![cfg_attr(not(test), no_main)] // disable all Rust-level entry points
#![cfg_attr(test, allow(dead_code, unused_macros, unused_imports))] #![cfg_attr(test, allow(dead_code, unused_macros, unused_imports))]
@@ -25,7 +24,7 @@ pub extern "C" fn _start() -> ! {
/// This function is called on panic. /// This function is called on panic.
#[cfg(not(test))] #[cfg(not(test))]
#[panic_implementation] #[panic_handler]
#[no_mangle] #[no_mangle]
pub fn panic(info: &PanicInfo) -> ! { pub fn panic(info: &PanicInfo) -> ! {
serial_println!("failed"); serial_println!("failed");

View File

@@ -1,4 +1,3 @@
#![feature(panic_implementation)]
#![feature(abi_x86_interrupt)] #![feature(abi_x86_interrupt)]
#![no_std] #![no_std]
#![cfg_attr(not(test), no_main)] #![cfg_attr(not(test), no_main)]
@@ -45,7 +44,7 @@ pub extern "C" fn _start() -> ! {
/// This function is called on panic. /// This function is called on panic.
#[cfg(not(test))] #[cfg(not(test))]
#[panic_implementation] #[panic_handler]
#[no_mangle] #[no_mangle]
pub fn panic(info: &PanicInfo) -> ! { pub fn panic(info: &PanicInfo) -> ! {
serial_println!("failed"); serial_println!("failed");

View File

@@ -1,4 +1,3 @@
#![feature(panic_implementation)]
#![feature(abi_x86_interrupt)] #![feature(abi_x86_interrupt)]
#![no_std] #![no_std]
#![cfg_attr(not(test), no_main)] #![cfg_attr(not(test), no_main)]
@@ -39,7 +38,7 @@ pub extern "C" fn _start() -> ! {
/// This function is called on panic. /// This function is called on panic.
#[cfg(not(test))] #[cfg(not(test))]
#[panic_implementation] #[panic_handler]
#[no_mangle] #[no_mangle]
pub fn panic(info: &PanicInfo) -> ! { pub fn panic(info: &PanicInfo) -> ! {
serial_println!("failed"); serial_println!("failed");

View File

@@ -1,4 +1,3 @@
#![feature(panic_implementation)]
#![no_std] #![no_std]
#![cfg_attr(not(test), no_main)] #![cfg_attr(not(test), no_main)]
#![cfg_attr(test, allow(dead_code, unused_macros, unused_imports))] #![cfg_attr(test, allow(dead_code, unused_macros, unused_imports))]
@@ -16,7 +15,7 @@ pub extern "C" fn _start() -> ! {
} }
#[cfg(not(test))] #[cfg(not(test))]
#[panic_implementation] #[panic_handler]
#[no_mangle] #[no_mangle]
pub fn panic(_info: &PanicInfo) -> ! { pub fn panic(_info: &PanicInfo) -> ! {
serial_println!("ok"); serial_println!("ok");

View File

@@ -1,4 +1,3 @@
#![feature(panic_implementation)] // required for defining the panic handler
#![feature(abi_x86_interrupt)] #![feature(abi_x86_interrupt)]
#![no_std] // don't link the Rust standard library #![no_std] // don't link the Rust standard library
#![cfg_attr(not(test), no_main)] // disable all Rust-level entry points #![cfg_attr(not(test), no_main)] // disable all Rust-level entry points
@@ -35,7 +34,7 @@ pub extern "C" fn _start() -> ! {
/// This function is called on panic. /// This function is called on panic.
#[cfg(not(test))] #[cfg(not(test))]
#[panic_implementation] #[panic_handler]
#[no_mangle] #[no_mangle]
pub fn panic(info: &PanicInfo) -> ! { pub fn panic(info: &PanicInfo) -> ! {
println!("{}", info); println!("{}", info);