1
Fork 0

Auto merge of #116199 - Urgau:simplify-invalid_ref_casting, r=cjgillot

Simplify some of the logic in the `invalid_reference_casting` lint

This PR simplifies 2 areas of the logic for the `invalid_reference_casting` lint:
 - The init detection: we now use the newly added `expr_or_init` function instead of a manual detection
 - The ref-to-mut-ptr casting detection logic: I simplified this logic by caring less hardly about the order of the casting operations

Those two simplifications permits us to detect more cases, as can be seen in the test output changes.
This commit is contained in:
bors 2023-09-28 19:44:14 +00:00
commit 1393ef1fa0
6 changed files with 182 additions and 134 deletions

View file

@ -1316,6 +1316,40 @@ impl<'tcx> LateContext<'tcx> {
}) })
} }
/// If the given expression is a local binding, find the initializer expression.
/// If that initializer expression is another local binding, find its initializer again.
///
/// This process repeats as long as possible (but usually no more than once).
/// Type-check adjustments are not taken in account in this function.
///
/// Examples:
/// ```
/// let abc = 1;
/// let def = abc + 2;
/// // ^^^^^^^ output
/// let def = def;
/// dbg!(def);
/// // ^^^ input
/// ```
pub fn expr_or_init<'a>(&self, mut expr: &'a hir::Expr<'tcx>) -> &'a hir::Expr<'tcx> {
expr = expr.peel_blocks();
while let hir::ExprKind::Path(ref qpath) = expr.kind
&& let Some(parent_node) = match self.qpath_res(qpath, expr.hir_id) {
Res::Local(hir_id) => self.tcx.hir().find_parent(hir_id),
_ => None,
}
&& let Some(init) = match parent_node {
hir::Node::Expr(expr) => Some(expr),
hir::Node::Local(hir::Local { init, .. }) => *init,
_ => None
}
{
expr = init.peel_blocks();
}
expr
}
/// If the given expression is a local binding, find the initializer expression. /// If the given expression is a local binding, find the initializer expression.
/// If that initializer expression is another local or **outside** (`const`/`static`) /// If that initializer expression is another local or **outside** (`const`/`static`)
/// binding, find its initializer again. /// binding, find its initializer again.
@ -1338,7 +1372,10 @@ impl<'tcx> LateContext<'tcx> {
/// dbg!(def); /// dbg!(def);
/// // ^^^ input /// // ^^^ input
/// ``` /// ```
pub fn expr_or_init<'a>(&self, mut expr: &'a hir::Expr<'tcx>) -> &'a hir::Expr<'tcx> { pub fn expr_or_init_with_outside_body<'a>(
&self,
mut expr: &'a hir::Expr<'tcx>,
) -> &'a hir::Expr<'tcx> {
expr = expr.peel_blocks(); expr = expr.peel_blocks();
while let hir::ExprKind::Path(ref qpath) = expr.kind while let hir::ExprKind::Path(ref qpath) = expr.kind

View file

@ -84,9 +84,9 @@ impl<'tcx> LateLintPass<'tcx> for InvalidFromUtf8 {
) )
}; };
let mut init = cx.expr_or_init(arg); let mut init = cx.expr_or_init_with_outside_body(arg);
while let ExprKind::AddrOf(.., inner) = init.kind { while let ExprKind::AddrOf(.., inner) = init.kind {
init = cx.expr_or_init(inner); init = cx.expr_or_init_with_outside_body(inner);
} }
match init.kind { match init.kind {
ExprKind::Lit(Spanned { node: lit, .. }) => { ExprKind::Lit(Spanned { node: lit, .. }) => {

View file

@ -196,7 +196,7 @@ late_lint_methods!(
BoxPointers: BoxPointers, BoxPointers: BoxPointers,
PathStatements: PathStatements, PathStatements: PathStatements,
LetUnderscore: LetUnderscore, LetUnderscore: LetUnderscore,
InvalidReferenceCasting: InvalidReferenceCasting::default(), InvalidReferenceCasting: InvalidReferenceCasting,
// Depends on referenced function signatures in expressions // Depends on referenced function signatures in expressions
UnusedResults: UnusedResults, UnusedResults: UnusedResults,
NonUpperCaseGlobals: NonUpperCaseGlobals, NonUpperCaseGlobals: NonUpperCaseGlobals,

View file

@ -1,8 +1,7 @@
use rustc_ast::Mutability; use rustc_ast::Mutability;
use rustc_data_structures::fx::FxHashMap; use rustc_hir::{Expr, ExprKind, UnOp};
use rustc_hir::{def::Res, Expr, ExprKind, HirId, Local, QPath, StmtKind, UnOp};
use rustc_middle::ty::{self, TypeAndMut}; use rustc_middle::ty::{self, TypeAndMut};
use rustc_span::{sym, Span}; use rustc_span::sym;
use crate::{lints::InvalidReferenceCastingDiag, LateContext, LateLintPass, LintContext}; use crate::{lints::InvalidReferenceCastingDiag, LateContext, LateLintPass, LintContext};
@ -34,38 +33,18 @@ declare_lint! {
"casts of `&T` to `&mut T` without interior mutability" "casts of `&T` to `&mut T` without interior mutability"
} }
#[derive(Default)] declare_lint_pass!(InvalidReferenceCasting => [INVALID_REFERENCE_CASTING]);
pub struct InvalidReferenceCasting {
casted: FxHashMap<HirId, Span>,
}
impl_lint_pass!(InvalidReferenceCasting => [INVALID_REFERENCE_CASTING]);
impl<'tcx> LateLintPass<'tcx> for InvalidReferenceCasting { impl<'tcx> LateLintPass<'tcx> for InvalidReferenceCasting {
fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx rustc_hir::Stmt<'tcx>) {
let StmtKind::Local(local) = stmt.kind else {
return;
};
let Local { init: Some(init), els: None, .. } = local else {
return;
};
if is_cast_from_const_to_mut(cx, init) {
self.casted.insert(local.pat.hir_id, init.span);
}
}
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
let Some((is_assignment, e)) = is_operation_we_care_about(cx, expr) else { let Some((is_assignment, e)) = is_operation_we_care_about(cx, expr) else {
return; return;
}; };
let orig_cast = if is_cast_from_const_to_mut(cx, e) { let init = cx.expr_or_init(e);
None
} else if let ExprKind::Path(QPath::Resolved(_, path)) = e.kind let orig_cast = if is_cast_from_const_to_mut(cx, init) {
&& let Res::Local(hir_id) = &path.res if init.span != e.span { Some(init.span) } else { None }
&& let Some(orig_cast) = self.casted.get(hir_id) {
Some(*orig_cast)
} else { } else {
return; return;
}; };
@ -125,99 +104,51 @@ fn is_operation_we_care_about<'tcx>(
deref_assign_or_addr_of(e).or_else(|| ptr_write(cx, e)) deref_assign_or_addr_of(e).or_else(|| ptr_write(cx, e))
} }
fn is_cast_from_const_to_mut<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> bool { fn is_cast_from_const_to_mut<'tcx>(cx: &LateContext<'tcx>, orig_expr: &'tcx Expr<'tcx>) -> bool {
let e = e.peel_blocks(); let mut need_check_freeze = false;
let mut e = orig_expr;
fn from_casts<'tcx>( let end_ty = cx.typeck_results().node_type(orig_expr.hir_id);
cx: &LateContext<'tcx>,
e: &'tcx Expr<'tcx>, // Bail out early if the end type is **not** a mutable pointer.
need_check_freeze: &mut bool, if !matches!(end_ty.kind(), ty::RawPtr(TypeAndMut { ty: _, mutbl: Mutability::Mut })) {
) -> Option<&'tcx Expr<'tcx>> { return false;
// <expr> as *mut ... }
let mut e = if let ExprKind::Cast(e, t) = e.kind
&& let ty::RawPtr(TypeAndMut { mutbl: Mutability::Mut, .. }) = cx.typeck_results().node_type(t.hir_id).kind() { loop {
e e = e.peel_blocks();
// <expr>.cast_mut() // <expr> as ...
e = if let ExprKind::Cast(expr, _) = e.kind {
expr
// <expr>.cast(), <expr>.cast_mut() or <expr>.cast_const()
} else if let ExprKind::MethodCall(_, expr, [], _) = e.kind } else if let ExprKind::MethodCall(_, expr, [], _) = e.kind
&& let Some(def_id) = cx.typeck_results().type_dependent_def_id(e.hir_id) && let Some(def_id) = cx.typeck_results().type_dependent_def_id(e.hir_id)
&& cx.tcx.is_diagnostic_item(sym::ptr_cast_mut, def_id) { && matches!(
cx.tcx.get_diagnostic_name(def_id),
Some(sym::ptr_cast | sym::const_ptr_cast | sym::ptr_cast_mut | sym::ptr_cast_const)
)
{
expr expr
// UnsafeCell::raw_get(<expr>) // ptr::from_ref(<expr>), UnsafeCell::raw_get(<expr>) or mem::transmute<_, _>(<expr>)
} else if let ExprKind::Call(path, [arg]) = e.kind } else if let ExprKind::Call(path, [arg]) = e.kind
&& let ExprKind::Path(ref qpath) = path.kind && let ExprKind::Path(ref qpath) = path.kind
&& let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
&& cx.tcx.is_diagnostic_item(sym::unsafe_cell_raw_get, def_id) && matches!(
cx.tcx.get_diagnostic_name(def_id),
Some(sym::ptr_from_ref | sym::unsafe_cell_raw_get | sym::transmute)
)
{ {
*need_check_freeze = true; if cx.tcx.is_diagnostic_item(sym::unsafe_cell_raw_get, def_id) {
need_check_freeze = true;
}
arg arg
} else { } else {
return None; break;
}; };
let mut had_at_least_one_cast = false;
loop {
e = e.peel_blocks();
// <expr> as *mut/const ... or <expr> as <uint>
e = if let ExprKind::Cast(expr, t) = e.kind
&& matches!(cx.typeck_results().node_type(t.hir_id).kind(), ty::RawPtr(_) | ty::Uint(_)) {
had_at_least_one_cast = true;
expr
// <expr>.cast(), <expr>.cast_mut() or <expr>.cast_const()
} else if let ExprKind::MethodCall(_, expr, [], _) = e.kind
&& let Some(def_id) = cx.typeck_results().type_dependent_def_id(e.hir_id)
&& matches!(
cx.tcx.get_diagnostic_name(def_id),
Some(sym::ptr_cast | sym::const_ptr_cast | sym::ptr_cast_mut | sym::ptr_cast_const)
)
{
had_at_least_one_cast = true;
expr
// ptr::from_ref(<expr>) or UnsafeCell::raw_get(<expr>)
} else if let ExprKind::Call(path, [arg]) = e.kind
&& let ExprKind::Path(ref qpath) = path.kind
&& let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
&& matches!(
cx.tcx.get_diagnostic_name(def_id),
Some(sym::ptr_from_ref | sym::unsafe_cell_raw_get)
)
{
if cx.tcx.is_diagnostic_item(sym::unsafe_cell_raw_get, def_id) {
*need_check_freeze = true;
}
return Some(arg);
} else if had_at_least_one_cast {
return Some(e);
} else {
return None;
};
}
} }
fn from_transmute<'tcx>( let start_ty = cx.typeck_results().node_type(e.hir_id);
cx: &LateContext<'tcx>, if let ty::Ref(_, inner_ty, Mutability::Not) = start_ty.kind() {
e: &'tcx Expr<'tcx>,
) -> Option<&'tcx Expr<'tcx>> {
// mem::transmute::<_, *mut _>(<expr>)
if let ExprKind::Call(path, [arg]) = e.kind
&& let ExprKind::Path(ref qpath) = path.kind
&& let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
&& cx.tcx.is_diagnostic_item(sym::transmute, def_id)
&& let ty::RawPtr(TypeAndMut { mutbl: Mutability::Mut, .. }) = cx.typeck_results().node_type(e.hir_id).kind() {
Some(arg)
} else {
None
}
}
let mut need_check_freeze = false;
let Some(e) = from_casts(cx, e, &mut need_check_freeze).or_else(|| from_transmute(cx, e))
else {
return false;
};
let e = e.peel_blocks();
let node_type = cx.typeck_results().node_type(e.hir_id);
if let ty::Ref(_, inner_ty, Mutability::Not) = node_type.kind() {
// If an UnsafeCell method is involved we need to additionaly check the // If an UnsafeCell method is involved we need to additionaly check the
// inner type for the presence of the Freeze trait (ie does NOT contain // inner type for the presence of the Freeze trait (ie does NOT contain
// an UnsafeCell), since in that case we would incorrectly lint on valid casts. // an UnsafeCell), since in that case we would incorrectly lint on valid casts.

View file

@ -36,6 +36,8 @@ unsafe fn ref_to_mut() {
//~^ ERROR casting `&T` to `&mut T` is undefined behavior //~^ ERROR casting `&T` to `&mut T` is undefined behavior
let _num = &mut *std::mem::transmute::<_, *mut i32>(num); let _num = &mut *std::mem::transmute::<_, *mut i32>(num);
//~^ ERROR casting `&T` to `&mut T` is undefined behavior //~^ ERROR casting `&T` to `&mut T` is undefined behavior
let _num = &mut *(std::mem::transmute::<_, *mut i32>(num) as *mut i32);
//~^ ERROR casting `&T` to `&mut T` is undefined behavior
let _num = &mut *std::cell::UnsafeCell::raw_get( let _num = &mut *std::cell::UnsafeCell::raw_get(
//~^ ERROR casting `&T` to `&mut T` is undefined behavior //~^ ERROR casting `&T` to `&mut T` is undefined behavior
num as *const i32 as *const std::cell::UnsafeCell<i32> num as *const i32 as *const std::cell::UnsafeCell<i32>
@ -47,8 +49,20 @@ unsafe fn ref_to_mut() {
let deferred = (std::ptr::from_ref(num) as *const i32 as *const i32).cast_mut() as *mut i32; let deferred = (std::ptr::from_ref(num) as *const i32 as *const i32).cast_mut() as *mut i32;
let _num = &mut *deferred; let _num = &mut *deferred;
//~^ ERROR casting `&T` to `&mut T` is undefined behavior //~^ ERROR casting `&T` to `&mut T` is undefined behavior
let deferred_rebind = deferred;
let _num = &mut *deferred_rebind;
//~^ ERROR casting `&T` to `&mut T` is undefined behavior
let _num = &mut *(num as *const _ as usize as *mut i32); let _num = &mut *(num as *const _ as usize as *mut i32);
//~^ ERROR casting `&T` to `&mut T` is undefined behavior //~^ ERROR casting `&T` to `&mut T` is undefined behavior
let _num = &mut *(std::mem::transmute::<_, *mut _>(num as *const i32) as *mut i32);
//~^ ERROR casting `&T` to `&mut T` is undefined behavior
static NUM: &'static i32 = &2;
let num = NUM as *const i32 as *mut i32;
let num = num;
let num = num;
let _num = &mut *num;
//~^ ERROR casting `&T` to `&mut T` is undefined behavior
unsafe fn generic_ref_cast_mut<T>(this: &T) -> &mut T { unsafe fn generic_ref_cast_mut<T>(this: &T) -> &mut T {
&mut *((this as *const _) as *mut _) &mut *((this as *const _) as *mut _)
@ -85,6 +99,8 @@ unsafe fn assign_to_ref() {
//~^ ERROR assigning to `&T` is undefined behavior //~^ ERROR assigning to `&T` is undefined behavior
*std::mem::transmute::<_, *mut i32>(num) += 1; *std::mem::transmute::<_, *mut i32>(num) += 1;
//~^ ERROR assigning to `&T` is undefined behavior //~^ ERROR assigning to `&T` is undefined behavior
*(std::mem::transmute::<_, *mut i32>(num) as *mut i32) += 1;
//~^ ERROR assigning to `&T` is undefined behavior
std::ptr::write( std::ptr::write(
//~^ ERROR assigning to `&T` is undefined behavior //~^ ERROR assigning to `&T` is undefined behavior
std::mem::transmute::<*const i32, *mut i32>(num), std::mem::transmute::<*const i32, *mut i32>(num),
@ -94,6 +110,9 @@ unsafe fn assign_to_ref() {
let value = num as *const i32 as *mut i32; let value = num as *const i32 as *mut i32;
*value = 1; *value = 1;
//~^ ERROR assigning to `&T` is undefined behavior //~^ ERROR assigning to `&T` is undefined behavior
let value_rebind = value;
*value_rebind = 1;
//~^ ERROR assigning to `&T` is undefined behavior
*(num as *const i32).cast::<i32>().cast_mut() = 2; *(num as *const i32).cast::<i32>().cast_mut() = 2;
//~^ ERROR assigning to `&T` is undefined behavior //~^ ERROR assigning to `&T` is undefined behavior
*(num as *const _ as usize as *mut i32) = 2; *(num as *const _ as usize as *mut i32) = 2;
@ -111,6 +130,7 @@ unsafe fn assign_to_ref() {
} }
} }
const RAW_PTR: *mut u8 = 1 as *mut u8;
unsafe fn no_warn() { unsafe fn no_warn() {
let num = &3i32; let num = &3i32;
let mut_num = &mut 3i32; let mut_num = &mut 3i32;
@ -125,6 +145,9 @@ unsafe fn no_warn() {
let mut value = 3; let mut value = 3;
let value: *const i32 = &mut value; let value: *const i32 = &mut value;
*(value as *const i16 as *mut i16) = 42; *(value as *const i16 as *mut i16) = 42;
*RAW_PTR = 42; // RAW_PTR is defined outside the function body,
// make sure we don't ICE on it when trying to
// determine if we should lint on it or not.
fn safe_as_mut<T>(x: &std::cell::UnsafeCell<T>) -> &mut T { fn safe_as_mut<T>(x: &std::cell::UnsafeCell<T>) -> &mut T {
unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *const _) } unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *const _) }

View file

@ -82,6 +82,14 @@ LL | let _num = &mut *std::mem::transmute::<_, *mut i32>(num);
error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
--> $DIR/reference_casting.rs:39:16 --> $DIR/reference_casting.rs:39:16
| |
LL | let _num = &mut *(std::mem::transmute::<_, *mut i32>(num) as *mut i32);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
--> $DIR/reference_casting.rs:41:16
|
LL | let _num = &mut *std::cell::UnsafeCell::raw_get( LL | let _num = &mut *std::cell::UnsafeCell::raw_get(
| ________________^ | ________________^
LL | | LL | |
@ -92,7 +100,7 @@ LL | | );
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html> = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
--> $DIR/reference_casting.rs:45:16 --> $DIR/reference_casting.rs:47:16
| |
LL | let deferred = num as *const i32 as *mut i32; LL | let deferred = num as *const i32 as *mut i32;
| ----------------------------- casting happend here | ----------------------------- casting happend here
@ -102,7 +110,7 @@ LL | let _num = &mut *deferred;
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html> = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
--> $DIR/reference_casting.rs:48:16 --> $DIR/reference_casting.rs:50:16
| |
LL | let deferred = (std::ptr::from_ref(num) as *const i32 as *const i32).cast_mut() as *mut i32; LL | let deferred = (std::ptr::from_ref(num) as *const i32 as *const i32).cast_mut() as *mut i32;
| ---------------------------------------------------------------------------- casting happend here | ---------------------------------------------------------------------------- casting happend here
@ -112,7 +120,18 @@ LL | let _num = &mut *deferred;
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html> = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
--> $DIR/reference_casting.rs:50:16 --> $DIR/reference_casting.rs:53:16
|
LL | let deferred = (std::ptr::from_ref(num) as *const i32 as *const i32).cast_mut() as *mut i32;
| ---------------------------------------------------------------------------- casting happend here
...
LL | let _num = &mut *deferred_rebind;
| ^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
--> $DIR/reference_casting.rs:55:16
| |
LL | let _num = &mut *(num as *const _ as usize as *mut i32); LL | let _num = &mut *(num as *const _ as usize as *mut i32);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -120,7 +139,26 @@ LL | let _num = &mut *(num as *const _ as usize as *mut i32);
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html> = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
--> $DIR/reference_casting.rs:54:9 --> $DIR/reference_casting.rs:57:16
|
LL | let _num = &mut *(std::mem::transmute::<_, *mut _>(num as *const i32) as *mut i32);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
--> $DIR/reference_casting.rs:64:16
|
LL | let num = NUM as *const i32 as *mut i32;
| ----------------------------- casting happend here
...
LL | let _num = &mut *num;
| ^^^^^^^^^
|
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
--> $DIR/reference_casting.rs:68:9
| |
LL | &mut *((this as *const _) as *mut _) LL | &mut *((this as *const _) as *mut _)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -128,7 +166,7 @@ LL | &mut *((this as *const _) as *mut _)
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html> = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
--> $DIR/reference_casting.rs:59:18 --> $DIR/reference_casting.rs:73:18
| |
LL | unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *const _) } LL | unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *const _) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -136,7 +174,7 @@ LL | unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *con
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html> = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
--> $DIR/reference_casting.rs:64:18 --> $DIR/reference_casting.rs:78:18
| |
LL | unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *const _) } LL | unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *const _) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -144,7 +182,7 @@ LL | unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *con
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html> = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
--> $DIR/reference_casting.rs:74:5 --> $DIR/reference_casting.rs:88:5
| |
LL | *(a as *const _ as *mut _) = String::from("Replaced"); LL | *(a as *const _ as *mut _) = String::from("Replaced");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -152,7 +190,7 @@ LL | *(a as *const _ as *mut _) = String::from("Replaced");
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html> = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
--> $DIR/reference_casting.rs:76:5 --> $DIR/reference_casting.rs:90:5
| |
LL | *(a as *const _ as *mut String) += " world"; LL | *(a as *const _ as *mut String) += " world";
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -160,7 +198,7 @@ LL | *(a as *const _ as *mut String) += " world";
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html> = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
--> $DIR/reference_casting.rs:78:5 --> $DIR/reference_casting.rs:92:5
| |
LL | *std::ptr::from_ref(num).cast_mut() += 1; LL | *std::ptr::from_ref(num).cast_mut() += 1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -168,7 +206,7 @@ LL | *std::ptr::from_ref(num).cast_mut() += 1;
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html> = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
--> $DIR/reference_casting.rs:80:5 --> $DIR/reference_casting.rs:94:5
| |
LL | *std::ptr::from_ref({ num }).cast_mut() += 1; LL | *std::ptr::from_ref({ num }).cast_mut() += 1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -176,7 +214,7 @@ LL | *std::ptr::from_ref({ num }).cast_mut() += 1;
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html> = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
--> $DIR/reference_casting.rs:82:5 --> $DIR/reference_casting.rs:96:5
| |
LL | *{ std::ptr::from_ref(num) }.cast_mut() += 1; LL | *{ std::ptr::from_ref(num) }.cast_mut() += 1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -184,7 +222,7 @@ LL | *{ std::ptr::from_ref(num) }.cast_mut() += 1;
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html> = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
--> $DIR/reference_casting.rs:84:5 --> $DIR/reference_casting.rs:98:5
| |
LL | *(std::ptr::from_ref({ num }) as *mut i32) += 1; LL | *(std::ptr::from_ref({ num }) as *mut i32) += 1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -192,7 +230,7 @@ LL | *(std::ptr::from_ref({ num }) as *mut i32) += 1;
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html> = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
--> $DIR/reference_casting.rs:86:5 --> $DIR/reference_casting.rs:100:5
| |
LL | *std::mem::transmute::<_, *mut i32>(num) += 1; LL | *std::mem::transmute::<_, *mut i32>(num) += 1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -200,7 +238,15 @@ LL | *std::mem::transmute::<_, *mut i32>(num) += 1;
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html> = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
--> $DIR/reference_casting.rs:88:5 --> $DIR/reference_casting.rs:102:5
|
LL | *(std::mem::transmute::<_, *mut i32>(num) as *mut i32) += 1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
--> $DIR/reference_casting.rs:104:5
| |
LL | / std::ptr::write( LL | / std::ptr::write(
LL | | LL | |
@ -212,7 +258,7 @@ LL | | );
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html> = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
--> $DIR/reference_casting.rs:95:5 --> $DIR/reference_casting.rs:111:5
| |
LL | let value = num as *const i32 as *mut i32; LL | let value = num as *const i32 as *mut i32;
| ----------------------------- casting happend here | ----------------------------- casting happend here
@ -222,7 +268,18 @@ LL | *value = 1;
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html> = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
--> $DIR/reference_casting.rs:97:5 --> $DIR/reference_casting.rs:114:5
|
LL | let value = num as *const i32 as *mut i32;
| ----------------------------- casting happend here
...
LL | *value_rebind = 1;
| ^^^^^^^^^^^^^^^^^
|
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
--> $DIR/reference_casting.rs:116:5
| |
LL | *(num as *const i32).cast::<i32>().cast_mut() = 2; LL | *(num as *const i32).cast::<i32>().cast_mut() = 2;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -230,7 +287,7 @@ LL | *(num as *const i32).cast::<i32>().cast_mut() = 2;
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html> = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
--> $DIR/reference_casting.rs:99:5 --> $DIR/reference_casting.rs:118:5
| |
LL | *(num as *const _ as usize as *mut i32) = 2; LL | *(num as *const _ as usize as *mut i32) = 2;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -238,7 +295,7 @@ LL | *(num as *const _ as usize as *mut i32) = 2;
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html> = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
--> $DIR/reference_casting.rs:101:5 --> $DIR/reference_casting.rs:120:5
| |
LL | let value = num as *const i32 as *mut i32; LL | let value = num as *const i32 as *mut i32;
| ----------------------------- casting happend here | ----------------------------- casting happend here
@ -249,7 +306,7 @@ LL | std::ptr::write(value, 2);
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html> = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
--> $DIR/reference_casting.rs:103:5 --> $DIR/reference_casting.rs:122:5
| |
LL | let value = num as *const i32 as *mut i32; LL | let value = num as *const i32 as *mut i32;
| ----------------------------- casting happend here | ----------------------------- casting happend here
@ -260,7 +317,7 @@ LL | std::ptr::write_unaligned(value, 2);
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html> = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
--> $DIR/reference_casting.rs:105:5 --> $DIR/reference_casting.rs:124:5
| |
LL | let value = num as *const i32 as *mut i32; LL | let value = num as *const i32 as *mut i32;
| ----------------------------- casting happend here | ----------------------------- casting happend here
@ -271,12 +328,12 @@ LL | std::ptr::write_volatile(value, 2);
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html> = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
--> $DIR/reference_casting.rs:109:9 --> $DIR/reference_casting.rs:128:9
| |
LL | *(this as *const _ as *mut _) = a; LL | *(this as *const _ as *mut _) = a;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html> = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
error: aborting due to 32 previous errors error: aborting due to 38 previous errors