Skip to content

Commit

Permalink
Auto merge of #12260 - Jarcho:issue_12255, r=llogiq
Browse files Browse the repository at this point in the history
Take lifetime extension into account in `ref_as_ptr`

fixes #12255

This should be merged upstream as well. Changing `let x = &temp as *const _` into `let x = from_ref(&temp)` is UB.

changelog: `ref_as_ptr`: Take lifetime extension into account
  • Loading branch information
bors committed Feb 24, 2024
2 parents 5a52c8a + 5ab42d8 commit 8542041
Show file tree
Hide file tree
Showing 4 changed files with 226 additions and 206 deletions.
12 changes: 10 additions & 2 deletions clippy_lints/src/casts/ref_as_ptr.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,30 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::is_no_std_crate;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::sugg::Sugg;
use clippy_utils::{expr_use_ctxt, is_no_std_crate, ExprUseNode};
use rustc_errors::Applicability;
use rustc_hir::{Expr, Mutability, Ty, TyKind};
use rustc_lint::LateContext;
use rustc_middle::ty::{self, TypeAndMut};

use super::REF_AS_PTR;

pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_to_hir_ty: &Ty<'_>) {
pub(super) fn check<'tcx>(
cx: &LateContext<'tcx>,
expr: &'tcx Expr<'_>,
cast_expr: &'tcx Expr<'_>,
cast_to_hir_ty: &Ty<'_>,
) {
let (cast_from, cast_to) = (
cx.typeck_results().expr_ty(cast_expr),
cx.typeck_results().expr_ty(expr),
);

if matches!(cast_from.kind(), ty::Ref(..))
&& let ty::RawPtr(TypeAndMut { mutbl: to_mutbl, .. }) = cast_to.kind()
&& let Some(use_cx) = expr_use_ctxt(cx, expr)
// TODO: only block the lint if `cast_expr` is a temporary
&& !matches!(use_cx.node, ExprUseNode::Local(_) | ExprUseNode::ConstStatic(_))
{
let core_or_std = if is_no_std_crate(cx) { "core" } else { "std" };
let fn_name = match to_mutbl {
Expand Down
88 changes: 47 additions & 41 deletions tests/ui/ref_as_ptr.fixed
Original file line number Diff line number Diff line change
@@ -1,55 +1,61 @@
#![warn(clippy::ref_as_ptr)]
#![allow(clippy::unnecessary_mut_passed)]

fn f<T>(_: T) {}

fn main() {
let _ = std::ptr::from_ref(&1u8);
let _ = std::ptr::from_ref::<u32>(&2u32);
let _ = std::ptr::from_ref::<f64>(&3.0f64);
f(std::ptr::from_ref(&1u8));
f(std::ptr::from_ref::<u32>(&2u32));
f(std::ptr::from_ref::<f64>(&3.0f64));

let _ = std::ptr::from_ref(&4) as *const f32;
let _ = std::ptr::from_ref::<f32>(&5.0f32) as *const u32;
f(std::ptr::from_ref(&4) as *const f32);
f(std::ptr::from_ref::<f32>(&5.0f32) as *const u32);

let _ = std::ptr::from_ref(&mut 6u8);
let _ = std::ptr::from_ref::<u32>(&mut 7u32);
let _ = std::ptr::from_ref::<f64>(&mut 8.0f64);
f(std::ptr::from_ref(&mut 6u8));
f(std::ptr::from_ref::<u32>(&mut 7u32));
f(std::ptr::from_ref::<f64>(&mut 8.0f64));

let _ = std::ptr::from_ref(&mut 9) as *const f32;
let _ = std::ptr::from_ref::<f32>(&mut 10.0f32) as *const u32;
f(std::ptr::from_ref(&mut 9) as *const f32);
f(std::ptr::from_ref::<f32>(&mut 10.0f32) as *const u32);

let _ = std::ptr::from_mut(&mut 11u8);
let _ = std::ptr::from_mut::<u32>(&mut 12u32);
let _ = std::ptr::from_mut::<f64>(&mut 13.0f64);
f(std::ptr::from_mut(&mut 11u8));
f(std::ptr::from_mut::<u32>(&mut 12u32));
f(std::ptr::from_mut::<f64>(&mut 13.0f64));

let _ = std::ptr::from_mut(&mut 14) as *const f32;
let _ = std::ptr::from_mut::<f32>(&mut 15.0f32) as *const u32;
f(std::ptr::from_mut(&mut 14) as *const f32);
f(std::ptr::from_mut::<f32>(&mut 15.0f32) as *const u32);

let _ = std::ptr::from_ref(&1u8);
let _ = std::ptr::from_ref::<u32>(&2u32);
let _ = std::ptr::from_ref::<f64>(&3.0f64);
f(std::ptr::from_ref(&1u8));
f(std::ptr::from_ref::<u32>(&2u32));
f(std::ptr::from_ref::<f64>(&3.0f64));

let _ = std::ptr::from_ref(&4) as *const f32;
let _ = std::ptr::from_ref::<f32>(&5.0f32) as *const u32;
f(std::ptr::from_ref(&4) as *const f32);
f(std::ptr::from_ref::<f32>(&5.0f32) as *const u32);

let val = 1;
let _ = std::ptr::from_ref(&val);
let _ = std::ptr::from_ref::<i32>(&val);
f(std::ptr::from_ref(&val));
f(std::ptr::from_ref::<i32>(&val));

let _ = std::ptr::from_ref(&val) as *const f32;
let _ = std::ptr::from_ref::<i32>(&val) as *const f64;
f(std::ptr::from_ref(&val) as *const f32);
f(std::ptr::from_ref::<i32>(&val) as *const f64);

let mut val: u8 = 2;
let _ = std::ptr::from_mut::<u8>(&mut val);
let _ = std::ptr::from_mut(&mut val);
f(std::ptr::from_mut::<u8>(&mut val));
f(std::ptr::from_mut(&mut val));

f(std::ptr::from_ref::<u8>(&mut val));
f(std::ptr::from_ref(&mut val));

let _ = std::ptr::from_ref::<u8>(&mut val);
let _ = std::ptr::from_ref(&mut val);
f(std::ptr::from_ref::<u8>(&mut val) as *const f64);
f::<*const Option<u8>>(std::ptr::from_ref(&mut val) as *const _);

let _ = std::ptr::from_ref::<u8>(&mut val) as *const f64;
let _: *const Option<u8> = std::ptr::from_ref(&mut val) as *const _;
f(std::ptr::from_ref::<[usize; 7]>(&std::array::from_fn(|i| i * i)));
f(std::ptr::from_ref::<[usize; 8]>(&mut std::array::from_fn(|i| i * i)));
f(std::ptr::from_mut::<[usize; 9]>(&mut std::array::from_fn(|i| i * i)));

let _ = std::ptr::from_ref::<[usize; 7]>(&std::array::from_fn(|i| i * i));
let _ = std::ptr::from_ref::<[usize; 8]>(&mut std::array::from_fn(|i| i * i));
let _ = std::ptr::from_mut::<[usize; 9]>(&mut std::array::from_fn(|i| i * i));
let _ = &String::new() as *const _;
let _ = &mut String::new() as *mut _;
const FOO: *const String = &String::new() as *const _;
}

#[clippy::msrv = "1.75"]
Expand All @@ -58,27 +64,27 @@ fn _msrv_1_75() {
let mut_val = &mut 42_i32;

// `std::ptr::from_{ref, mut}` was stabilized in 1.76. Do not lint this
let _ = val as *const i32;
let _ = mut_val as *mut i32;
f(val as *const i32);
f(mut_val as *mut i32);
}

#[clippy::msrv = "1.76"]
fn _msrv_1_76() {
let val = &42_i32;
let mut_val = &mut 42_i32;

let _ = std::ptr::from_ref::<i32>(val);
let _ = std::ptr::from_mut::<i32>(mut_val);
f(std::ptr::from_ref::<i32>(val));
f(std::ptr::from_mut::<i32>(mut_val));
}

fn foo(val: &[u8]) {
let _ = std::ptr::from_ref(val);
let _ = std::ptr::from_ref::<[u8]>(val);
f(std::ptr::from_ref(val));
f(std::ptr::from_ref::<[u8]>(val));
}

fn bar(val: &mut str) {
let _ = std::ptr::from_mut(val);
let _ = std::ptr::from_mut::<str>(val);
f(std::ptr::from_mut(val));
f(std::ptr::from_mut::<str>(val));
}

struct X<'a>(&'a i32);
Expand Down
88 changes: 47 additions & 41 deletions tests/ui/ref_as_ptr.rs
Original file line number Diff line number Diff line change
@@ -1,55 +1,61 @@
#![warn(clippy::ref_as_ptr)]
#![allow(clippy::unnecessary_mut_passed)]

fn f<T>(_: T) {}

fn main() {
let _ = &1u8 as *const _;
let _ = &2u32 as *const u32;
let _ = &3.0f64 as *const f64;
f(&1u8 as *const _);
f(&2u32 as *const u32);
f(&3.0f64 as *const f64);

let _ = &4 as *const _ as *const f32;
let _ = &5.0f32 as *const f32 as *const u32;
f(&4 as *const _ as *const f32);
f(&5.0f32 as *const f32 as *const u32);

let _ = &mut 6u8 as *const _;
let _ = &mut 7u32 as *const u32;
let _ = &mut 8.0f64 as *const f64;
f(&mut 6u8 as *const _);
f(&mut 7u32 as *const u32);
f(&mut 8.0f64 as *const f64);

let _ = &mut 9 as *const _ as *const f32;
let _ = &mut 10.0f32 as *const f32 as *const u32;
f(&mut 9 as *const _ as *const f32);
f(&mut 10.0f32 as *const f32 as *const u32);

let _ = &mut 11u8 as *mut _;
let _ = &mut 12u32 as *mut u32;
let _ = &mut 13.0f64 as *mut f64;
f(&mut 11u8 as *mut _);
f(&mut 12u32 as *mut u32);
f(&mut 13.0f64 as *mut f64);

let _ = &mut 14 as *mut _ as *const f32;
let _ = &mut 15.0f32 as *mut f32 as *const u32;
f(&mut 14 as *mut _ as *const f32);
f(&mut 15.0f32 as *mut f32 as *const u32);

let _ = &1u8 as *const _;
let _ = &2u32 as *const u32;
let _ = &3.0f64 as *const f64;
f(&1u8 as *const _);
f(&2u32 as *const u32);
f(&3.0f64 as *const f64);

let _ = &4 as *const _ as *const f32;
let _ = &5.0f32 as *const f32 as *const u32;
f(&4 as *const _ as *const f32);
f(&5.0f32 as *const f32 as *const u32);

let val = 1;
let _ = &val as *const _;
let _ = &val as *const i32;
f(&val as *const _);
f(&val as *const i32);

let _ = &val as *const _ as *const f32;
let _ = &val as *const i32 as *const f64;
f(&val as *const _ as *const f32);
f(&val as *const i32 as *const f64);

let mut val: u8 = 2;
let _ = &mut val as *mut u8;
let _ = &mut val as *mut _;
f(&mut val as *mut u8);
f(&mut val as *mut _);

f(&mut val as *const u8);
f(&mut val as *const _);

let _ = &mut val as *const u8;
let _ = &mut val as *const _;
f(&mut val as *const u8 as *const f64);
f::<*const Option<u8>>(&mut val as *const _ as *const _);

let _ = &mut val as *const u8 as *const f64;
let _: *const Option<u8> = &mut val as *const _ as *const _;
f(&std::array::from_fn(|i| i * i) as *const [usize; 7]);
f(&mut std::array::from_fn(|i| i * i) as *const [usize; 8]);
f(&mut std::array::from_fn(|i| i * i) as *mut [usize; 9]);

let _ = &std::array::from_fn(|i| i * i) as *const [usize; 7];
let _ = &mut std::array::from_fn(|i| i * i) as *const [usize; 8];
let _ = &mut std::array::from_fn(|i| i * i) as *mut [usize; 9];
let _ = &String::new() as *const _;
let _ = &mut String::new() as *mut _;
const FOO: *const String = &String::new() as *const _;
}

#[clippy::msrv = "1.75"]
Expand All @@ -58,27 +64,27 @@ fn _msrv_1_75() {
let mut_val = &mut 42_i32;

// `std::ptr::from_{ref, mut}` was stabilized in 1.76. Do not lint this
let _ = val as *const i32;
let _ = mut_val as *mut i32;
f(val as *const i32);
f(mut_val as *mut i32);
}

#[clippy::msrv = "1.76"]
fn _msrv_1_76() {
let val = &42_i32;
let mut_val = &mut 42_i32;

let _ = val as *const i32;
let _ = mut_val as *mut i32;
f(val as *const i32);
f(mut_val as *mut i32);
}

fn foo(val: &[u8]) {
let _ = val as *const _;
let _ = val as *const [u8];
f(val as *const _);
f(val as *const [u8]);
}

fn bar(val: &mut str) {
let _ = val as *mut _;
let _ = val as *mut str;
f(val as *mut _);
f(val as *mut str);
}

struct X<'a>(&'a i32);
Expand Down
Loading

0 comments on commit 8542041

Please sign in to comment.