Skip to content

Commit 234a1d3

Browse files
committed
recognize metavariables in tail expressions
1 parent 7ac242c commit 234a1d3

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)