- Feature Name:
unsafe_derives_and_attrs
- Start Date: 2024-10-22
- RFC PR: rust-lang/rfcs#3715
- Rust Issue: rust-lang/rust#0000
Allow declaring proc macro attributes and derive macros as unsafe, and
requiring unsafe
to invoke them.
Some traits place requirements on implementations that the Rust compiler cannot
verify. Those traits can mark themselves as unsafe, requiring unsafe impl
syntax to implement. However, trait derive
macros cannot currently require
unsafe
. This RFC defines a syntax for declaring and using unsafe derive
macros.
This RFC also defines a syntax for declaring proc macro attributes as unsafe.
When declaring a proc macro derive
, you can add the unsafe
parameter to the
proc_macro_derive
attribute to indicate that the derive requires unsafe
:
#[proc_macro_derive(DangerousTrait, unsafe)]
pub fn derive_helper_attr(_item: TokenStream) -> TokenStream {
TokenStream::new()
}
Invoking this derive requires writing either
#[unsafe(derive(DangerousTrait))]
or #[derive(unsafe(DangerousTrait))]
.
(The latter syntax allows isolating the unsafe
to a single derive within a
list of derives.) Invoking an unsafe derive without the unsafe derive syntax
will produce a compiler error. Using the unsafe derive syntax without an unsafe
derive will trigger an "unused unsafe" lint.
A proc_macro_derive
attribute can include both attributes
for helper
attributes and unsafe
to declare the derive unsafe, in any order.
When declaring a proc macro attribute, you can add the unsafe
parameter to
the proc_macro_attribute
attribute to indicate that the attribute requires
unsafe
:
#[proc_macro_attribute(unsafe)]
pub fn dangerous(_attr: TokenStream, item: TokenStream) -> TokenStream {
item
}
Invoking an unsafe attribute requires the unsafe attribute syntax:
#[unsafe(dangerous)]
.
Should we support the #[unsafe(derive(DangerousTrait))]
syntax, or only
#[derive(unsafe(DangerousTrait))]
? The former elevates the unsafe
to be
more visible, and allows deriving several traits using one unsafe
. The latter
isolates the unsafe
to a specific trait. This RFC proposes supporting both,
but we could choose to only support the latter instead.
We could use a different syntax for invoking unsafe derives, such as
derive(unsafe Trait)
. However, that would be inconsistent with unsafe
attributes (which use parentheses), and it has the potential to look like a
modifier to Trait
(e.g. an unsafe version of Trait
).
RFC 3325 defined unsafe attributes. This RFC provides a natural extension of that mechanism to derives.
This RFC proposes accepting both #[unsafe(derive(MyTrait))]
and
#[derive(unsafe(MyTrait))]
, among other reasons to make it easy to write
#[derive(SafeTrait, unsafe(MyTrait))]
. Should we allow both, or only allow
the former?
When we add support for macro_rules!
-based attributes and derives, we should
provide a means for such attributes and derives to declare themselves unsafe as
well.
We could provide a syntax to declare specific helper attributes of a derive as unsafe, without declaring the entire derive unsafe.