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

Document #![register_tool] #138586

Merged
merged 1 commit into from
Mar 17, 2025
Merged
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
55 changes: 55 additions & 0 deletions src/doc/unstable-book/src/language-features/register-tool.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# `register_tool`

The tracking issue for this feature is: [#66079]

[#66079]: https://github.com/rust-lang/rust/issues/66079

------------------------

The `register_tool` language feature informs the compiler that attributes in your code are meant to be used with tools other than the compiler itself. This can be useful if your code has semantic meaning without the external tool, but enables additional features when the tool is present.

`register_tool` also allows configuring lint levels for external tools.

Tool attributes are only meant for ignorable attributes. If your code *changes* meaning when the attribute is present, it should not use a tool attribute (because it cannot be compiled with anything other than the external tool, and in a sense is a fork of the language).
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this bit really belongs in an RFC, not here. i will try to make an RFC in the new few months.


------------------------

`#![register_tool(tool)]` is an attribute, and is only valid at the crate root.
Attributes using the registered tool are checked for valid syntax, and lint attributes are checked to be in a valid format. However, the compiler cannot validate the semantics of the attribute, nor can it tell whether the configured lint is present in the external tool.

Semantically, `clippy::*`, `rustdoc::*`, and `rustfmt::*` lints and attributes all behave as if `#![register_tool(clippy, rustdoc, rustfmt)]` were injected into the crate root, except that the `rustdoc` namespace can only be used for lints, not for attributes.
When compiling with `-Z unstable-features`, `rustc::*` lints can also be used. Like `rustdoc`, the `rustc` namespace can only be used with lints, not attributes.

The compiler will emit an error if it encounters a lint/attribute whose namespace isn't a registered tool.

Tool namespaces cannot be nested; `register_tool(main_tool::subtool)` is an error.

## Examples

Tool attributes:

```rust
#![feature(register_tool)]
#![register_tool(c2rust)]

// Mark which C header file this module was generated from.
#[c2rust::header_src = "operations.h"]
pub mod operations_h {
use std::ffi::c_int;

// Mark which source line this struct was generated from.
#[c2rust::src_loc = "11:0"]
pub struct Point {
pub x: c_int,
pub y: c_int,
}
}
```

Tool lints:

```
#![feature(register_tool)]
#![register_tool(bevy)]
#![deny(bevy::duplicate_bevy_dependencies)]
Comment on lines +52 to +54
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i've already asked @alice-i-cecile about this example, she said mentioning bevy is fine.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this lint / tool doesn't exist yet, but I think it's a very clear example of where this might be useful.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this lint / tool doesn't exist yet, but I think it's a very clear example of where this might be useful.

This specific lint comes in the 0.2.0 release, but yea it's not an official bevy tool yet.

```
5 changes: 5 additions & 0 deletions tests/ui/tool-attributes/crate-attr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
//@ check-pass
//@ compile-flags: -Z crate-attr=feature(register_tool) -Z crate-attr=register_tool(foo)

#[allow(foo::bar)]
fn main() {}
7 changes: 7 additions & 0 deletions tests/ui/tool-attributes/multiple-registered.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//@ check-pass

#![feature(register_tool)]
#![register_tool(foo, bar, baz)]

#[allow(foo::a, bar::b, baz::c)]
fn main() {}
4 changes: 4 additions & 0 deletions tests/ui/tool-attributes/nested-disallowed.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#![feature(register_tool)]
#![register_tool(foo::bar)] //~ ERROR only accepts identifiers

fn main() {}
8 changes: 8 additions & 0 deletions tests/ui/tool-attributes/nested-disallowed.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
error: `register_tool` only accepts identifiers
--> $DIR/nested-disallowed.rs:2:18
|
LL | #![register_tool(foo::bar)]
| ^^^^^^^^ not an identifier

error: aborting due to 1 previous error

Loading