No, because the macro never promised that it can be used in this way. Many macros, such as ones using tt
matchers, have literally no way to check or enforce such safety rules. In the IRLO thread I linked, there are examples of actual real-world macros which allow safety laundering, not because of malicious intent or undocumented preconditions, but because they were never intended to be used with unsafe code.
Yes, but we still need to discuss the extended version, to make sure that this RFC really is forward-compatible with arbitrary unsafe attributes, and not just an ad-hoc solution.
Some questions:
-
Is
#[unsafe(foo, bar)]
and#[unsafe(foo)] #[unsafe(bar)]
the same? It would be nice. But an attribute macrofoo
could likely be able to consume#[unsafe(bar)]
, but would not be applicable tobar
in#[unsafe(foo, bar)]
. Unlikederive
macros, which cannot modify the item definition and are (usually) entirely orthogonal, the custom attributes could interact in arbitrary ways, which may become confusing with the#[unsafe(..)]
attribute. -
How can I consume an unsafe attribute via a proc macro? Currently the macros match on the name of the attribute, but with
#[unsafe(..)]
the name will be arbitrarily nested within the inner token tree (there may be nested unsafe blocks, and who knows what else in the future). -
Active attributes remove themselves once they are processed. How would that work if an active attribute is within an (arbitrarily nested)
#[unsafe(..)]
attribute? -
Can I have
cfg_attr(..)
inside of#[unsafe(..)]
? How would it work?
One possible answer to the above questions would be to check unsafe
correctness before macro expansion, and simplify #[unsafe(foo, bar)]
into just #[foo] #[bar]
. But that wouldn't work if the macro attribute or the attributes it uses are themselves unsafe, or if a macro expands to unsafe attributes, or if we want to preserve the unsafety hygiene.
-
Can we have unsafe tool attributes? It's unlikely that Clippy or rustfmt would require that, but we may have other tools in the future, and there is [register_tool].
-
The
#[unsafe(..)]
attribute would cause backwards compatibility issue with any user-defined#[unsafe]
attribute, whether used separately or in derive macros. This may classified as acceptable breakage, and/or be gated over an edition boundary. However, it's hard to detect (the attribute may be emitted by a macro and consumed by another macro), impossible to fix automatically, and with the scope creep [1] [2] [3] [4] of stdlib attributes, this is not an acceptable long-term solution. -
Attributes can exist on statements. What if the statement is inside of an unsafe block? Does it absolve us from using
unsafe
on attributes? I would expect not, but I think it's worth specifying.