Description
Given the following code: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=4fc81da81334f7865f292f98a62735a3
unsafe fn unsafe_code() { }
macro_rules! macro_inner
{
() => { unsafe { unsafe_code(); } };
}
macro_rules! macro_outer
{
() => { unsafe { macro_inner!(); unsafe_code(); } };
}
fn main()
{
macro_inner!();
macro_outer!();
}
The current output is:
warning: unnecessary `unsafe` block
--> src\poc.rs:5:13
|
5 | () => { unsafe { unsafe_code(); } };
| ^^^^^^ unnecessary `unsafe` block
...
9 | () => { unsafe { macro_inner!(); unsafe_code(); } };
| ------ because it's nested under this `unsafe` block
...
16 | macro_outer!();
| -------------- in this macro invocation
|
= note: this warning originates in the macro `macro_inner` (in Nightly builds, run with -Z macro-backtrace for more info)
This is obviously wrong, because macro_inner!
is also invoked at line 14, in the main
function, outside an unsafe
block. The analyzer seems to only take in account the invocation occurring inside the macro_outer!
expansion during the unused_unsafe
check.
Although it makes technical sense to perform the analysis that way, the result is that an incorrect piece of advice is given to the user ("This unsafe
specifier is unnecessary, remove it"). Here, removing the unsafe
block breaks the code, for the first invocation.
Tested on stable 1.58.1 and nightly 1.61.0 (2022-02-23).
EDIT: still present on 1.67.0 (2022-11-02).
PS: Sorry if this is not in the right triage category, I wasn't sure whether it would better fit the "Diagnostics" or the "Bug" label.