about summary refs log tree commit diff
diff options
context:
space:
mode:
authorjyn <github@jyn.dev>2025-03-16 22:27:09 -0400
committerjyn <github@jyn.dev>2025-03-17 01:16:47 -0400
commit10bc5acf0d6736bc0a99d55beae739878f94de16 (patch)
tree0f8598178cf2c939351bc8f9938aa27a17e1615c
parent0998d4095b0f11061f78a3f9c77a87838a4c1cb7 (diff)
downloadrust-10bc5acf0d6736bc0a99d55beae739878f94de16.tar.gz
rust-10bc5acf0d6736bc0a99d55beae739878f94de16.zip
Document `#![register_tool]`
-rw-r--r--src/doc/unstable-book/src/language-features/register-tool.md55
-rw-r--r--tests/ui/tool-attributes/crate-attr.rs5
-rw-r--r--tests/ui/tool-attributes/multiple-registered.rs7
-rw-r--r--tests/ui/tool-attributes/nested-disallowed.rs4
-rw-r--r--tests/ui/tool-attributes/nested-disallowed.stderr8
5 files changed, 79 insertions, 0 deletions
diff --git a/src/doc/unstable-book/src/language-features/register-tool.md b/src/doc/unstable-book/src/language-features/register-tool.md
new file mode 100644
index 00000000000..58b923aab57
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/register-tool.md
@@ -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).
+
+------------------------
+
+`#![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)]
+```
diff --git a/tests/ui/tool-attributes/crate-attr.rs b/tests/ui/tool-attributes/crate-attr.rs
new file mode 100644
index 00000000000..c6d7974945f
--- /dev/null
+++ b/tests/ui/tool-attributes/crate-attr.rs
@@ -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() {}
diff --git a/tests/ui/tool-attributes/multiple-registered.rs b/tests/ui/tool-attributes/multiple-registered.rs
new file mode 100644
index 00000000000..4d54c2dcb08
--- /dev/null
+++ b/tests/ui/tool-attributes/multiple-registered.rs
@@ -0,0 +1,7 @@
+//@ check-pass
+
+#![feature(register_tool)]
+#![register_tool(foo, bar, baz)]
+
+#[allow(foo::a, bar::b, baz::c)]
+fn main() {}
diff --git a/tests/ui/tool-attributes/nested-disallowed.rs b/tests/ui/tool-attributes/nested-disallowed.rs
new file mode 100644
index 00000000000..8e780427761
--- /dev/null
+++ b/tests/ui/tool-attributes/nested-disallowed.rs
@@ -0,0 +1,4 @@
+#![feature(register_tool)]
+#![register_tool(foo::bar)] //~ ERROR only accepts identifiers
+
+fn main() {}
diff --git a/tests/ui/tool-attributes/nested-disallowed.stderr b/tests/ui/tool-attributes/nested-disallowed.stderr
new file mode 100644
index 00000000000..1af73fc2f19
--- /dev/null
+++ b/tests/ui/tool-attributes/nested-disallowed.stderr
@@ -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
+