diff --git a/clippy_lints/src/pass_by_ref_or_value.rs b/clippy_lints/src/pass_by_ref_or_value.rs index 6edf0e7a7b2..5fa4fd74853 100644 --- a/clippy_lints/src/pass_by_ref_or_value.rs +++ b/clippy_lints/src/pass_by_ref_or_value.rs @@ -14,6 +14,7 @@ use rustc_hir as hir; use rustc_hir::intravisit::FnKind; use rustc_hir::{BindingAnnotation, Body, FnDecl, HirId, Impl, ItemKind, MutTy, Mutability, Node, PatKind}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::adjustment::{Adjust, PointerCast}; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, RegionKind}; use rustc_session::{declare_tool_lint, impl_lint_pass}; @@ -185,6 +186,20 @@ impl<'tcx> PassByRefOrValue { && size <= self.ref_min_size && let hir::TyKind::Rptr(_, MutTy { ty: decl_ty, .. }) = input.kind { + if let Some(typeck) = cx.maybe_typeck_results() { + // Don't lint if an unsafe pointer is created. + // TODO: Limit the check only to unsafe pointers to the argument (or part of the argument) + // which escape the current function. + if typeck.node_types().iter().any(|(_, &ty)| ty.is_unsafe_ptr()) + || typeck + .adjustments() + .iter() + .flat_map(|(_, a)| a) + .any(|a| matches!(a.kind, Adjust::Pointer(PointerCast::UnsafeFnPointer))) + { + continue; + } + } let value_type = if fn_body.and_then(|body| body.params.get(index)).map_or(false, is_self) { "self".into() } else { diff --git a/tests/ui/trivially_copy_pass_by_ref.rs b/tests/ui/trivially_copy_pass_by_ref.rs index 24117e37ed1..8f78f16a0a1 100644 --- a/tests/ui/trivially_copy_pass_by_ref.rs +++ b/tests/ui/trivially_copy_pass_by_ref.rs @@ -139,6 +139,18 @@ fn _unrelated_lifetimes<'a, 'b>(_x: &'a u32, y: &'b u32) -> &'b u32 { y } +fn _return_ptr(x: &u32) -> *const u32 { + x +} + +fn _return_field_ptr(x: &(u32, u32)) -> *const u32 { + &x.0 +} + +fn _return_field_ptr_addr_of(x: &(u32, u32)) -> *const u32 { + core::ptr::addr_of!(x.0) +} + fn main() { let (mut foo, bar) = (Foo(0), Bar([0; 24])); let (mut a, b, c, x, y, z) = (0, 0, Bar([0; 24]), 0, Foo(0), 0);