|
| 1 | +- Feature Name: `unsafe_derives_and_attrs` |
| 2 | +- Start Date: 2024-10-22 |
| 3 | +- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000) |
| 4 | +- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000) |
| 5 | + |
| 6 | +# Summary |
| 7 | +[summary]: #summary |
| 8 | + |
| 9 | +Allow declaring proc macro attributes and derive macros as unsafe, and |
| 10 | +requiring `unsafe` to invoke them. |
| 11 | + |
| 12 | +# Motivation |
| 13 | +[motivation]: #motivation |
| 14 | + |
| 15 | +Some traits place requirements on implementations that the Rust compiler cannot |
| 16 | +verify. Those traits can mark themselves as unsafe, requiring `unsafe impl` |
| 17 | +syntax to implement. However, trait `derive` macros cannot currently require |
| 18 | +`unsafe`. This RFC defines a syntax for declaring and using unsafe `derive` |
| 19 | +macros. |
| 20 | + |
| 21 | +This RFC also defines a syntax for declaring proc macro attributes as unsafe. |
| 22 | + |
| 23 | +# Guide-level explanation |
| 24 | +[guide-level-explanation]: #guide-level-explanation |
| 25 | + |
| 26 | +## Derives |
| 27 | + |
| 28 | +When declaring a proc macro `derive`, you can add the `unsafe` parameter to the |
| 29 | +`proc_macro_derive` attribute to indicate that the derive requires `unsafe`: |
| 30 | + |
| 31 | +```rust |
| 32 | +#[proc_macro_derive(DangerousTrait, unsafe)] |
| 33 | +pub fn derive_helper_attr(_item: TokenStream) -> TokenStream { |
| 34 | + TokenStream::new() |
| 35 | +} |
| 36 | +``` |
| 37 | + |
| 38 | +Invoking this derive requires writing either |
| 39 | +`#[unsafe(derive(DangerousTrait))]` or `#[derive(unsafe(DangerousTrait))]`. |
| 40 | +(The latter syntax allows isolating the `unsafe` to a single derive within a |
| 41 | +list of derives.) Invoking an unsafe derive without the unsafe derive syntax |
| 42 | +will produce a compiler error. Using the unsafe derive syntax without an unsafe |
| 43 | +derive will trigger an "unused unsafe" lint. |
| 44 | + |
| 45 | +A `proc_macro_derive` attribute can include both `attributes` for helper |
| 46 | +attributes and `unsafe` to declare the derive unsafe, in any order. |
| 47 | + |
| 48 | +## Attributes |
| 49 | + |
| 50 | +When declaring a proc macro attribute, you can add the `unsafe` parameter to |
| 51 | +the `proc_macro_attribute` attribute to indicate that the attribute requires |
| 52 | +`unsafe`: |
| 53 | + |
| 54 | +```rust |
| 55 | +#[proc_macro_attribute(unsafe)] |
| 56 | +pub fn dangerous(_attr: TokenStream, item: TokenStream) -> TokenStream { |
| 57 | + item |
| 58 | +} |
| 59 | +``` |
| 60 | + |
| 61 | +Invoking an unsafe attribute requires the unsafe attribute syntax: |
| 62 | +`#[unsafe(dangerous)]`. |
| 63 | + |
| 64 | +# Rationale and alternatives |
| 65 | +[rationale-and-alternatives]: #rationale-and-alternatives |
| 66 | + |
| 67 | +Should we support the `#[unsafe(derive(DangerousTrait))]` syntax, or only |
| 68 | +`#[derive(unsafe(DangerousTrait))]`? The former elevates the `unsafe` to be |
| 69 | +more visible, and allows deriving several traits using one `unsafe`. The latter |
| 70 | +isolates the `unsafe` to a specific trait. This RFC proposes supporting both, |
| 71 | +but we could choose to only support the latter instead. |
| 72 | + |
| 73 | +# Prior art |
| 74 | +[prior-art]: #prior-art |
| 75 | + |
| 76 | +RFC 3325 defined unsafe attributes. This RFC provides a natural extension of |
| 77 | +that mechanism to derives. |
| 78 | + |
| 79 | +# Future possibilities |
| 80 | +[future-possibilities]: #future-possibilities |
| 81 | + |
| 82 | +When we add support for `macro_rules!`-based attributes and derives, we should |
| 83 | +provide a means for such attributes and derives to declare themselves unsafe as |
| 84 | +well. |
| 85 | + |
| 86 | +We could provide a syntax to declare specific helper attributes of a derive as |
| 87 | +unsafe, without declaring the entire derive unsafe. |
0 commit comments