diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 062f7cef3a72..49dd1bb09c61 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -432,6 +432,11 @@ impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> { fn visit_expr(&mut self, expr: &'tcx Expr<'_>) -> Self::Result { if let ExprKind::Block(block, _) = expr.kind && block.rules == BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) + && block + .span + .source_callee() + .and_then(|expr| expr.macro_def_id) + .is_none_or(|did| !self.cx.tcx.is_diagnostic_item(sym::pin_macro, did)) { return ControlFlow::Break(()); } diff --git a/tests/ui/unsafe_derive_deserialize.rs b/tests/ui/unsafe_derive_deserialize.rs index 14371bc203b3..d0022f3b6d93 100644 --- a/tests/ui/unsafe_derive_deserialize.rs +++ b/tests/ui/unsafe_derive_deserialize.rs @@ -82,3 +82,32 @@ impl H { } fn main() {} + +mod issue15120 { + macro_rules! uns { + ($e:expr) => { + unsafe { $e } + }; + } + + #[derive(serde::Deserialize)] + struct Foo; + + impl Foo { + fn foo(&self) { + // Do not lint if `unsafe` comes from the `core::pin::pin!()` macro + std::pin::pin!(()); + } + } + + //~v unsafe_derive_deserialize + #[derive(serde::Deserialize)] + struct Bar; + + impl Bar { + fn bar(&self) { + // Lint if `unsafe` comes from the another macro + _ = uns!(42); + } + } +} diff --git a/tests/ui/unsafe_derive_deserialize.stderr b/tests/ui/unsafe_derive_deserialize.stderr index f2d4429f707a..4b5dd6e61fcc 100644 --- a/tests/ui/unsafe_derive_deserialize.stderr +++ b/tests/ui/unsafe_derive_deserialize.stderr @@ -36,5 +36,14 @@ LL | #[derive(Deserialize)] = help: consider implementing `serde::Deserialize` manually. See https://serde.rs/impl-deserialize.html = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 4 previous errors +error: you are deriving `serde::Deserialize` on a type that has methods using `unsafe` + --> tests/ui/unsafe_derive_deserialize.rs:104:14 + | +LL | #[derive(serde::Deserialize)] + | ^^^^^^^^^^^^^^^^^^ + | + = help: consider implementing `serde::Deserialize` manually. See https://serde.rs/impl-deserialize.html + = note: this error originates in the derive macro `serde::Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 5 previous errors