diff options
| author | bors <bors@rust-lang.org> | 2023-06-01 01:27:32 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-06-01 01:27:32 +0000 |
| commit | ba1690bedd6ada4e8d91bfecb3d0ccc2b6de85ba (patch) | |
| tree | 6e669dc7e3fd97892062894efef4a9b56e8edad1 /tests | |
| parent | 9af3865deca9c601ef32ef4ed29f7cae5fed50a9 (diff) | |
| parent | 32d4e1c3c71fa30c83405eee7ff8b9bba6a903f0 (diff) | |
| download | rust-ba1690bedd6ada4e8d91bfecb3d0ccc2b6de85ba.tar.gz rust-ba1690bedd6ada4e8d91bfecb3d0ccc2b6de85ba.zip | |
Auto merge of #111567 - Urgau:uplift_cast_ref_to_mut, r=b-naber
Uplift `clippy::cast_ref_to_mut` lint
This PR aims at uplifting the `clippy::cast_ref_to_mut` lint into rustc.
## `cast_ref_to_mut`
(deny-by-default)
The `cast_ref_to_mut` lint checks for casts of `&T` to `&mut T` without using interior mutability.
### Example
```rust,compile_fail
fn x(r: &i32) {
unsafe {
*(r as *const i32 as *mut i32) += 1;
}
}
```
### Explanation
Casting `&T` to `&mut T` without interior mutability is undefined behavior, as it's a violation of Rust reference aliasing requirements.
-----
Mostly followed the instructions for uplifting a clippy lint described here: https://github.com/rust-lang/rust/pull/99696#pullrequestreview-1134072751
`@rustbot` label: +I-lang-nominated
r? compiler
-----
For Clippy:
changelog: Moves: Uplifted `clippy::cast_ref_to_mut` into rustc
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/ui/const-generics/issues/issue-100313.rs | 1 | ||||
| -rw-r--r-- | tests/ui/const-generics/issues/issue-100313.stderr | 12 | ||||
| -rw-r--r-- | tests/ui/lint/cast_ref_to_mut.rs | 50 | ||||
| -rw-r--r-- | tests/ui/lint/cast_ref_to_mut.stderr | 64 |
4 files changed, 125 insertions, 2 deletions
diff --git a/tests/ui/const-generics/issues/issue-100313.rs b/tests/ui/const-generics/issues/issue-100313.rs index 4e9d3626aa8..9a9d4721c84 100644 --- a/tests/ui/const-generics/issues/issue-100313.rs +++ b/tests/ui/const-generics/issues/issue-100313.rs @@ -9,6 +9,7 @@ impl <const B: &'static bool> T<B> { unsafe { *(B as *const bool as *mut bool) = false; //~^ ERROR evaluation of constant value failed [E0080] + //~| ERROR casting `&T` to `&mut T` is undefined behavior } } } diff --git a/tests/ui/const-generics/issues/issue-100313.stderr b/tests/ui/const-generics/issues/issue-100313.stderr index d4b486376ca..ffc34a3a41e 100644 --- a/tests/ui/const-generics/issues/issue-100313.stderr +++ b/tests/ui/const-generics/issues/issue-100313.stderr @@ -1,3 +1,11 @@ +error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` + --> $DIR/issue-100313.rs:10:13 + | +LL | *(B as *const bool as *mut bool) = false; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[deny(cast_ref_to_mut)]` on by default + error[E0080]: evaluation of constant value failed --> $DIR/issue-100313.rs:10:13 | @@ -10,11 +18,11 @@ note: inside `T::<&true>::set_false` LL | *(B as *const bool as *mut bool) = false; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: inside `_` - --> $DIR/issue-100313.rs:18:5 + --> $DIR/issue-100313.rs:19:5 | LL | x.set_false(); | ^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/lint/cast_ref_to_mut.rs b/tests/ui/lint/cast_ref_to_mut.rs new file mode 100644 index 00000000000..745d7070143 --- /dev/null +++ b/tests/ui/lint/cast_ref_to_mut.rs @@ -0,0 +1,50 @@ +// check-fail + +#![feature(ptr_from_ref)] + +extern "C" { + // N.B., mutability can be easily incorrect in FFI calls -- as + // in C, the default is mutable pointers. + fn ffi(c: *mut u8); + fn int_ffi(c: *mut i32); +} + +fn main() { + let s = String::from("Hello"); + let a = &s; + unsafe { + let num = &3i32; + let mut_num = &mut 3i32; + + (*(a as *const _ as *mut String)).push_str(" world"); + //~^ ERROR casting `&T` to `&mut T` is undefined behavior + *(a as *const _ as *mut _) = String::from("Replaced"); + //~^ ERROR casting `&T` to `&mut T` is undefined behavior + *(a as *const _ as *mut String) += " world"; + //~^ ERROR casting `&T` to `&mut T` is undefined behavior + let _num = &mut *(num as *const i32 as *mut i32); + //~^ ERROR casting `&T` to `&mut T` is undefined behavior + let _num = &mut *(num as *const i32).cast_mut(); + //~^ ERROR casting `&T` to `&mut T` is undefined behavior + let _num = *{ num as *const i32 }.cast_mut(); + //~^ ERROR casting `&T` to `&mut T` is undefined behavior + *std::ptr::from_ref(num).cast_mut() += 1; + //~^ ERROR casting `&T` to `&mut T` is undefined behavior + *std::ptr::from_ref({ num }).cast_mut() += 1; + //~^ ERROR casting `&T` to `&mut T` is undefined behavior + *{ std::ptr::from_ref(num) }.cast_mut() += 1; + //~^ ERROR casting `&T` to `&mut T` is undefined behavior + *(std::ptr::from_ref({ num }) as *mut i32) += 1; + //~^ ERROR casting `&T` to `&mut T` is undefined behavior + + // Shouldn't be warned against + println!("{}", *(num as *const _ as *const i16)); + println!("{}", *(mut_num as *mut _ as *mut i16)); + ffi(a.as_ptr() as *mut _); + int_ffi(num as *const _ as *mut _); + int_ffi(&3 as *const _ as *mut _); + let mut value = 3; + let value: *const i32 = &mut value; + *(value as *const i16 as *mut i16) = 42; + } +} diff --git a/tests/ui/lint/cast_ref_to_mut.stderr b/tests/ui/lint/cast_ref_to_mut.stderr new file mode 100644 index 00000000000..baff00d6c04 --- /dev/null +++ b/tests/ui/lint/cast_ref_to_mut.stderr @@ -0,0 +1,64 @@ +error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` + --> $DIR/cast_ref_to_mut.rs:19:9 + | +LL | (*(a as *const _ as *mut String)).push_str(" world"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[deny(cast_ref_to_mut)]` on by default + +error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` + --> $DIR/cast_ref_to_mut.rs:21:9 + | +LL | *(a as *const _ as *mut _) = String::from("Replaced"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` + --> $DIR/cast_ref_to_mut.rs:23:9 + | +LL | *(a as *const _ as *mut String) += " world"; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` + --> $DIR/cast_ref_to_mut.rs:25:25 + | +LL | let _num = &mut *(num as *const i32 as *mut i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` + --> $DIR/cast_ref_to_mut.rs:27:25 + | +LL | let _num = &mut *(num as *const i32).cast_mut(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` + --> $DIR/cast_ref_to_mut.rs:29:20 + | +LL | let _num = *{ num as *const i32 }.cast_mut(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` + --> $DIR/cast_ref_to_mut.rs:31:9 + | +LL | *std::ptr::from_ref(num).cast_mut() += 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` + --> $DIR/cast_ref_to_mut.rs:33:9 + | +LL | *std::ptr::from_ref({ num }).cast_mut() += 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` + --> $DIR/cast_ref_to_mut.rs:35:9 + | +LL | *{ std::ptr::from_ref(num) }.cast_mut() += 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` + --> $DIR/cast_ref_to_mut.rs:37:9 + | +LL | *(std::ptr::from_ref({ num }) as *mut i32) += 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 10 previous errors + |
