Auto merge of #51363 - japaric:stable-used, r=cramertj
stabilize #[used] closes #40289 RFC for stabilization: rust-lang/rfcs#2386 r? @Centril Where should this be documented? Currently the documentation is in the unstable book
This commit is contained in:
commit
7ee72070bd
11 changed files with 11 additions and 205 deletions
|
@ -1,157 +0,0 @@
|
|||
# `used`
|
||||
|
||||
The tracking issue for this feature
|
||||
is: [40289](https://github.com/rust-lang/rust/issues/40289).
|
||||
|
||||
------------------------
|
||||
|
||||
The `#[used]` attribute can be applied to `static` variables to prevent the Rust
|
||||
compiler from optimizing them away even if they appear to be unused by the crate
|
||||
(appear to be "dead code").
|
||||
|
||||
``` rust
|
||||
#![feature(used)]
|
||||
|
||||
#[used]
|
||||
static FOO: i32 = 1;
|
||||
|
||||
static BAR: i32 = 2;
|
||||
|
||||
fn main() {}
|
||||
```
|
||||
|
||||
If you compile this program into an object file, you'll see that `FOO` makes it
|
||||
to the object file but `BAR` doesn't. Neither static variable is used by the
|
||||
program.
|
||||
|
||||
``` text
|
||||
$ rustc -C opt-level=3 --emit=obj used.rs
|
||||
|
||||
$ nm -C used.o
|
||||
0000000000000000 T main
|
||||
U std::rt::lang_start
|
||||
0000000000000000 r used::FOO
|
||||
0000000000000000 t used::main
|
||||
```
|
||||
|
||||
Note that the *linker* knows nothing about the `#[used]` attribute and will
|
||||
remove `#[used]` symbols if they are not referenced by other parts of the
|
||||
program:
|
||||
|
||||
``` text
|
||||
$ rustc -C opt-level=3 used.rs
|
||||
|
||||
$ nm -C used | grep FOO
|
||||
```
|
||||
|
||||
"This doesn't sound too useful then!" you may think but keep reading.
|
||||
|
||||
To preserve the symbols all the way to the final binary, you'll need the
|
||||
cooperation of the linker. Here's one example:
|
||||
|
||||
The ELF standard defines two special sections, `.init_array` and
|
||||
`.pre_init_array`, that may contain function pointers which will be executed
|
||||
*before* the `main` function is invoked. The linker will preserve symbols placed
|
||||
in these sections (at least when linking programs that target the `*-*-linux-*`
|
||||
targets).
|
||||
|
||||
``` rust,ignore
|
||||
#![feature(used)]
|
||||
|
||||
extern "C" fn before_main() {
|
||||
println!("Hello, world!");
|
||||
}
|
||||
|
||||
#[link_section = ".init_array"]
|
||||
#[used]
|
||||
static INIT_ARRAY: [extern "C" fn(); 1] = [before_main];
|
||||
|
||||
fn main() {}
|
||||
```
|
||||
|
||||
So, `#[used]` and `#[link_section]` can be combined to obtain "life before
|
||||
main".
|
||||
|
||||
``` text
|
||||
$ rustc -C opt-level=3 before-main.rs
|
||||
|
||||
$ ./before-main
|
||||
Hello, world!
|
||||
```
|
||||
|
||||
Another example: ARM Cortex-M microcontrollers need their reset handler, a
|
||||
pointer to the function that will executed right after the microcontroller is
|
||||
turned on, to be placed near the start of their FLASH memory to boot properly.
|
||||
|
||||
This condition can be met using `#[used]` and `#[link_section]` plus a linker
|
||||
script.
|
||||
|
||||
``` rust,ignore
|
||||
#![feature(panic_handler)]
|
||||
#![feature(used)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
extern "C" fn reset_handler() -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[link_section = ".reset_handler"]
|
||||
#[used]
|
||||
static RESET_HANDLER: extern "C" fn() -> ! = reset_handler;
|
||||
|
||||
#[panic_handler]
|
||||
fn panic(info: &PanicInfo) -> ! {
|
||||
loop {}
|
||||
}
|
||||
```
|
||||
|
||||
``` text
|
||||
MEMORY
|
||||
{
|
||||
FLASH : ORIGIN = 0x08000000, LENGTH = 128K
|
||||
RAM : ORIGIN = 0x20000000, LENGTH = 20K
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text ORIGIN(FLASH) :
|
||||
{
|
||||
/* Vector table */
|
||||
LONG(ORIGIN(RAM) + LENGTH(RAM)); /* initial SP value */
|
||||
KEEP(*(.reset_handler));
|
||||
|
||||
/* Omitted: The rest of the vector table */
|
||||
|
||||
*(.text.*);
|
||||
} > FLASH
|
||||
|
||||
/DISCARD/ :
|
||||
{
|
||||
/* Unused unwinding stuff */
|
||||
*(.ARM.exidx.*)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
``` text
|
||||
$ xargo rustc --target thumbv7m-none-eabi --release -- \
|
||||
-C link-arg=-Tlink.x -C link-arg=-nostartfiles
|
||||
|
||||
$ arm-none-eabi-objdump -Cd target/thumbv7m-none-eabi/release/app
|
||||
./target/thumbv7m-none-eabi/release/app: file format elf32-littlearm
|
||||
|
||||
|
||||
Disassembly of section .text:
|
||||
|
||||
08000000 <app::RESET_HANDLER-0x4>:
|
||||
8000000: 20005000 .word 0x20005000
|
||||
|
||||
08000004 <app::RESET_HANDLER>:
|
||||
8000004: 08000009 ....
|
||||
|
||||
08000008 <app::reset_handler>:
|
||||
8000008: e7fe b.n 8000008 <app::reset_handler>
|
||||
```
|
|
@ -307,7 +307,7 @@
|
|||
#![feature(doc_cfg)]
|
||||
#![feature(doc_masked)]
|
||||
#![feature(doc_spotlight)]
|
||||
#![cfg_attr(windows, feature(used))]
|
||||
#![cfg_attr(all(windows, stage0), feature(used))]
|
||||
#![feature(doc_alias)]
|
||||
#![feature(doc_keyword)]
|
||||
#![feature(panic_info_message)]
|
||||
|
|
|
@ -349,9 +349,6 @@ declare_features! (
|
|||
// Allows the `try {...}` expression
|
||||
(active, try_blocks, "1.29.0", Some(31436), None),
|
||||
|
||||
// Used to preserve symbols (see llvm.used)
|
||||
(active, used, "1.18.0", Some(40289), None),
|
||||
|
||||
// Allows module-level inline assembly by way of global_asm!()
|
||||
(active, global_asm, "1.18.0", Some(35119), None),
|
||||
|
||||
|
@ -677,6 +674,9 @@ declare_features! (
|
|||
// Allows all literals in attribute lists and values of key-value pairs.
|
||||
(accepted, attr_literals, "1.30.0", Some(34981), None),
|
||||
(accepted, panic_handler, "1.30.0", Some(44489), None),
|
||||
// Used to preserve symbols (see llvm.used)
|
||||
(accepted, used, "1.30.0", Some(40289), None),
|
||||
|
||||
);
|
||||
|
||||
// If you change this, please modify src/doc/unstable-book as well. You must
|
||||
|
@ -1071,10 +1071,7 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
|
|||
"unwind_attributes",
|
||||
"#[unwind] is experimental",
|
||||
cfg_fn!(unwind_attributes))),
|
||||
("used", Whitelisted, Gated(
|
||||
Stability::Unstable, "used",
|
||||
"the `#[used]` attribute is an experimental feature",
|
||||
cfg_fn!(used))),
|
||||
("used", Whitelisted, Ungated),
|
||||
|
||||
// used in resolve
|
||||
("prelude_import", Whitelisted, Gated(Stability::Unstable,
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
// except according to those terms.
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![feature(used)]
|
||||
|
||||
#[used]
|
||||
static FOO: u32 = 0;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
|
@ -15,6 +15,5 @@
|
|||
|
||||
#[used]
|
||||
fn foo() {}
|
||||
//~^^ ERROR the `#[used]` attribute is an experimental feature
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
error[E0658]: the `#[used]` attribute is an experimental feature (see issue #40289)
|
||||
error: attribute must be applied to a `static` variable
|
||||
--> $DIR/feature-gate-linker-flavor.rs:16:1
|
||||
|
|
||||
LL | #[used]
|
||||
| ^^^^^^^
|
||||
|
|
||||
= help: add #![feature(used)] to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#[used]
|
||||
fn foo() {}
|
||||
//~^^ ERROR the `#[used]` attribute is an experimental feature
|
||||
|
||||
fn main() {}
|
|
@ -1,11 +0,0 @@
|
|||
error[E0658]: the `#[used]` attribute is an experimental feature (see issue #40289)
|
||||
--> $DIR/feature-gate-used.rs:11:1
|
||||
|
|
||||
LL | #[used]
|
||||
| ^^^^^^^
|
||||
|
|
||||
= help: add #![feature(used)] to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
|
@ -10,7 +10,6 @@
|
|||
|
||||
// run-pass
|
||||
#![deny(dead_code)]
|
||||
#![feature(used)]
|
||||
|
||||
#[used]
|
||||
static FOO: u32 = 0;
|
||||
|
|
|
@ -8,8 +8,6 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(used)]
|
||||
|
||||
#[used]
|
||||
static FOO: u32 = 0; // OK
|
||||
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
error: attribute must be applied to a `static` variable
|
||||
--> $DIR/used.rs:16:1
|
||||
--> $DIR/used.rs:14:1
|
||||
|
|
||||
LL | #[used] //~ ERROR attribute must be applied to a `static` variable
|
||||
| ^^^^^^^
|
||||
|
||||
error: attribute must be applied to a `static` variable
|
||||
--> $DIR/used.rs:19:1
|
||||
--> $DIR/used.rs:17:1
|
||||
|
|
||||
LL | #[used] //~ ERROR attribute must be applied to a `static` variable
|
||||
| ^^^^^^^
|
||||
|
||||
error: attribute must be applied to a `static` variable
|
||||
--> $DIR/used.rs:22:1
|
||||
--> $DIR/used.rs:20:1
|
||||
|
|
||||
LL | #[used] //~ ERROR attribute must be applied to a `static` variable
|
||||
| ^^^^^^^
|
||||
|
||||
error: attribute must be applied to a `static` variable
|
||||
--> $DIR/used.rs:25:1
|
||||
--> $DIR/used.rs:23:1
|
||||
|
|
||||
LL | #[used] //~ ERROR attribute must be applied to a `static` variable
|
||||
| ^^^^^^^
|
||||
|
|
Loading…
Reference in a new issue