Skip to content

Commit 37f98ff

Browse files
committed
Auto merge of #13220 - y21:issue13219, r=dswij
[`macro_metavars_in_unsafe`]: recognize metavariables in tail expressions Fixes #13219 `macro_metavars_in_unsafe` keeps track of the current "expansion depth" (incremented/decremented when entering/leaving a macro span) to tell if an expression from the root context is contained within a macro (see the doc comment I added for a hopefully better explanation) Before this PR, we didn't increment said `expn_depth` for `unsafe` blocks within macros, because we already do that in `visit_stmt` anyway, so it would work fine for statements, but that's not enough for tail expressions of an unsafe block. So we now also increment it for macro unsafe blocks. Also updated the comment for `expn_depth` while I'm at it because "This is not necessary for correctness" isn't correct now that I think about it ------ changelog: none
2 parents 780c61f + 234a1d3 commit 37f98ff

File tree

3 files changed

+46
-6
lines changed

3 files changed

+46
-6
lines changed

clippy_lints/src/macro_metavars_in_unsafe.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,23 @@ struct BodyVisitor<'a, 'tcx> {
122122
/// within a relevant macro.
123123
macro_unsafe_blocks: Vec<HirId>,
124124
/// When this is >0, it means that the node currently being visited is "within" a
125-
/// macro definition. This is not necessary for correctness, it merely helps reduce the number
126-
/// of spans we need to insert into the map, since only spans from macros are relevant.
125+
/// macro definition.
126+
/// This is used to detect if an expression represents a metavariable.
127+
///
128+
/// For example, the following pre-expansion code that we want to lint
129+
/// ```ignore
130+
/// macro_rules! m { ($e:expr) => { unsafe { $e; } } }
131+
/// m!(1);
132+
/// ```
133+
/// would look like this post-expansion code:
134+
/// ```ignore
135+
/// unsafe { /* macro */
136+
/// 1 /* root */; /* macro */
137+
/// }
138+
/// ```
139+
/// Visiting the block and the statement will increment the `expn_depth` so that it is >0,
140+
/// and visiting the expression with a root context while `expn_depth > 0` tells us
141+
/// that it must be a metavariable.
127142
expn_depth: u32,
128143
cx: &'a LateContext<'tcx>,
129144
lint: &'a mut ExprMetavarsInUnsafe,
@@ -157,7 +172,9 @@ impl<'a, 'tcx> Visitor<'tcx> for BodyVisitor<'a, 'tcx> {
157172
&& (self.lint.warn_unsafe_macro_metavars_in_private_macros || is_public_macro(self.cx, macro_def_id))
158173
{
159174
self.macro_unsafe_blocks.push(block.hir_id);
175+
self.expn_depth += 1;
160176
walk_block(self, block);
177+
self.expn_depth -= 1;
161178
self.macro_unsafe_blocks.pop();
162179
} else if ctxt.is_root() && self.expn_depth > 0 {
163180
let unsafe_block = self.macro_unsafe_blocks.last().copied();

tests/ui-toml/macro_metavars_in_unsafe/default/test.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Tests macro_metavars_in_unsafe with default configuration
22
#![feature(decl_macro)]
33
#![warn(clippy::macro_metavars_in_unsafe)]
4-
#![allow(clippy::no_effect)]
4+
#![allow(clippy::no_effect, clippy::not_unsafe_ptr_arg_deref)]
55

66
#[macro_export]
77
macro_rules! allow_works {
@@ -237,6 +237,19 @@ macro_rules! nested_macros {
237237
}};
238238
}
239239

240+
pub mod issue13219 {
241+
#[macro_export]
242+
macro_rules! m {
243+
($e:expr) => {
244+
// Metavariable in a block tail expression
245+
unsafe { $e }
246+
};
247+
}
248+
pub fn f(p: *const i32) -> i32 {
249+
m!(*p)
250+
}
251+
}
252+
240253
fn main() {
241254
allow_works!(1);
242255
simple!(1);

tests/ui-toml/macro_metavars_in_unsafe/default/test.stderr

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
error: this macro expands metavariables in an unsafe block
2+
--> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:245:13
3+
|
4+
LL | unsafe { $e }
5+
| ^^^^^^^^^^^^^
6+
|
7+
= note: this allows the user of the macro to write unsafe code outside of an unsafe block
8+
= help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable
9+
= help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite
10+
= note: `-D clippy::macro-metavars-in-unsafe` implied by `-D warnings`
11+
= help: to override `-D warnings` add `#[allow(clippy::macro_metavars_in_unsafe)]`
12+
113
error: this macro expands metavariables in an unsafe block
214
--> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:19:9
315
|
@@ -10,8 +22,6 @@ LL | | }
1022
= note: this allows the user of the macro to write unsafe code outside of an unsafe block
1123
= help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable
1224
= help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite
13-
= note: `-D clippy::macro-metavars-in-unsafe` implied by `-D warnings`
14-
= help: to override `-D warnings` add `#[allow(clippy::macro_metavars_in_unsafe)]`
1525

1626
error: this macro expands metavariables in an unsafe block
1727
--> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:30:9
@@ -183,5 +193,5 @@ LL | | }
183193
= help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable
184194
= help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite
185195

186-
error: aborting due to 14 previous errors
196+
error: aborting due to 15 previous errors
187197

0 commit comments

Comments
 (0)