Skip to content

#[used] attribute on static items in extern block has suboptimal error message #126789

Closed
@aleksanderkrauze

Description

@aleksanderkrauze

Code

extern "C" {
    #[used]
    static FOO: i32;
}

Current output

error: attribute must be applied to a `static` variable
 --> src/lib.rs:2:5
  |
2 |     #[used]
  |     ^^^^^^^

Desired output

There should be at least a hint, or other kind of diagnostic message, explaining why #[used] attribute is invalid in this context.

Rationale and extra context

#[used] attribute cannot be applied to static items defined inside extern blocks. However current compiler error, contrary to great Rust standards, does not explain why it is forbidden, or how to fix it. Moreover it can be confusing to newbie users. To the information "attribute must be applied to a static variable", one could say "But it is static. Look, it says it right there".

I would expect a hint, or another diagnostic that would explain that the #[used] attribute is used on static items that are defined inside crate, and extern blocks are used to declare an item, that exists elsewhere. Using this attribute inside extern block means that user either does not understand how #[used] attribute works, or how extern blocks work and a hint pointing it out to them could be helpful.

This would also be more inline with other errors related to incorrectly using static items inside extern blocks. For example assigning value to such static will result in following error message:

extern "C" {
    static FOO: i32 = 42;
}
error: incorrect `static` inside `extern` block
 --> src/lib.rs:2:12
  |
1 | extern "C" {
  | ---------- `extern` blocks define existing foreign statics and statics inside of them cannot have a body
2 |     static FOO: i32 = 42;
  |            ^^^        -- the invalid body
  |            |
  |            cannot have a body
  |
  = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html

Here compiler provides also notes, explaining why this code does not work and directs user to documentation that could be useful in this context.

Other cases

A similar case could be made for the #[no_mangle] attribute. Using it on static item in extern block produces following warning (which will become error in the future):

extern "C" {
    #[no_mangle]
    static FOO: i32;
}
warning: `#[no_mangle]` has no effect on a foreign static
 --> src/lib.rs:2:5
  |
2 |     #[no_mangle]
  |     ^^^^^^^^^^^^ help: remove this attribute
3 |     static FOO: i32;
  |     ---------------- foreign static
  |
  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
  = note: symbol names in extern blocks are not mangled
  = note: `#[warn(unused_attributes)]` on by default

The Rust Reference says that #[no_mangle] implies #[used]:

Additionally, the item will be publicly exported from the produced library or object file, similar to the used attribute.

Therefore using this attribute can be caused by the same fallacy - user not understanding that extern blocks refer to, well, external items, and not to those that are exported from their crate. Adding similar hint to this warning (and future error) could also help users making this error.

PS. Actually the same argument could be made for other ABI attributes, like #[link_section] and #[export_name].

Rust Version

rustc 1.79.0 (129f3b996 2024-06-10)
binary: rustc
commit-hash: 129f3b9964af4d4a709d1383930ade12dfe7c081
commit-date: 2024-06-10
host: x86_64-unknown-linux-gnu
release: 1.79.0
LLVM version: 18.1.7

Anything else?

No response

Metadata

Metadata

Assignees

Labels

A-diagnosticsArea: Messages for errors, warnings, and lintsT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions