Skip to content

Commit 50a4671

Browse files
committed
Avoid linting on expression that are only UB with SB/TB
1 parent f3dafe9 commit 50a4671

File tree

3 files changed

+34
-36
lines changed

3 files changed

+34
-36
lines changed

compiler/rustc_lint/src/reference_casting.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,20 @@ impl<'tcx> LateLintPass<'tcx> for InvalidReferenceCasting {
5656
}
5757

5858
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
59-
let ExprKind::Unary(UnOp::Deref, e) = &expr.kind else {
59+
// &mut <expr>
60+
let inner = if let ExprKind::AddrOf(_, Mutability::Mut, expr) = expr.kind {
61+
expr
62+
// <expr> = ...
63+
} else if let ExprKind::Assign(expr, _, _) = expr.kind {
64+
expr
65+
// <expr> += ...
66+
} else if let ExprKind::AssignOp(_, expr, _) = expr.kind {
67+
expr
68+
} else {
69+
return;
70+
};
71+
72+
let ExprKind::Unary(UnOp::Deref, e) = &inner.kind else {
6073
return;
6174
};
6275

@@ -103,5 +116,5 @@ fn is_cast_from_const_to_mut<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>)
103116
};
104117

105118
let e = e.peel_blocks();
106-
matches!(cx.typeck_results().node_type(e.hir_id).kind(), ty::Ref(..))
119+
matches!(cx.typeck_results().node_type(e.hir_id).kind(), ty::Ref(_, _, Mutability::Not))
107120
}

tests/ui/lint/reference_casting.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ fn main() {
1616
let num = &3i32;
1717
let mut_num = &mut 3i32;
1818

19-
(*(a as *const _ as *mut String)).push_str(" world");
20-
//~^ ERROR casting `&T` to `&mut T` is undefined behavior
2119
*(a as *const _ as *mut _) = String::from("Replaced");
2220
//~^ ERROR casting `&T` to `&mut T` is undefined behavior
2321
*(a as *const _ as *mut String) += " world";
@@ -26,8 +24,6 @@ fn main() {
2624
//~^ ERROR casting `&T` to `&mut T` is undefined behavior
2725
let _num = &mut *(num as *const i32).cast_mut();
2826
//~^ ERROR casting `&T` to `&mut T` is undefined behavior
29-
let _num = *{ num as *const i32 }.cast_mut();
30-
//~^ ERROR casting `&T` to `&mut T` is undefined behavior
3127
*std::ptr::from_ref(num).cast_mut() += 1;
3228
//~^ ERROR casting `&T` to `&mut T` is undefined behavior
3329
*std::ptr::from_ref({ num }).cast_mut() += 1;
@@ -41,6 +37,7 @@ fn main() {
4137
//~^ ERROR casting `&T` to `&mut T` is undefined behavior
4238

4339
// Shouldn't be warned against
40+
*(num as *const i32 as *mut i32);
4441
println!("{}", *(num as *const _ as *const i16));
4542
println!("{}", *(mut_num as *mut _ as *mut i16));
4643
ffi(a.as_ptr() as *mut _);
+18-30
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,60 @@
11
error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
22
--> $DIR/reference_casting.rs:19:9
33
|
4-
LL | (*(a as *const _ as *mut String)).push_str(" world");
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4+
LL | *(a as *const _ as *mut _) = String::from("Replaced");
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
77
= note: `#[deny(invalid_reference_casting)]` on by default
88

99
error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
1010
--> $DIR/reference_casting.rs:21:9
1111
|
12-
LL | *(a as *const _ as *mut _) = String::from("Replaced");
13-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
14-
15-
error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
16-
--> $DIR/reference_casting.rs:23:9
17-
|
1812
LL | *(a as *const _ as *mut String) += " world";
19-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2014

2115
error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
22-
--> $DIR/reference_casting.rs:25:25
16+
--> $DIR/reference_casting.rs:23:20
2317
|
2418
LL | let _num = &mut *(num as *const i32 as *mut i32);
25-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
19+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2620

2721
error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
28-
--> $DIR/reference_casting.rs:27:25
22+
--> $DIR/reference_casting.rs:25:20
2923
|
3024
LL | let _num = &mut *(num as *const i32).cast_mut();
31-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
32-
33-
error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
34-
--> $DIR/reference_casting.rs:29:20
35-
|
36-
LL | let _num = *{ num as *const i32 }.cast_mut();
37-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
25+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3826

3927
error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
40-
--> $DIR/reference_casting.rs:31:9
28+
--> $DIR/reference_casting.rs:27:9
4129
|
4230
LL | *std::ptr::from_ref(num).cast_mut() += 1;
43-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
31+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4432

4533
error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
46-
--> $DIR/reference_casting.rs:33:9
34+
--> $DIR/reference_casting.rs:29:9
4735
|
4836
LL | *std::ptr::from_ref({ num }).cast_mut() += 1;
49-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
37+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5038

5139
error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
52-
--> $DIR/reference_casting.rs:35:9
40+
--> $DIR/reference_casting.rs:31:9
5341
|
5442
LL | *{ std::ptr::from_ref(num) }.cast_mut() += 1;
55-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
43+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5644

5745
error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
58-
--> $DIR/reference_casting.rs:37:9
46+
--> $DIR/reference_casting.rs:33:9
5947
|
6048
LL | *(std::ptr::from_ref({ num }) as *mut i32) += 1;
61-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
49+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6250

6351
error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
64-
--> $DIR/reference_casting.rs:40:9
52+
--> $DIR/reference_casting.rs:36:9
6553
|
6654
LL | let value = num as *const i32 as *mut i32;
6755
| ----------------------------- casting happend here
6856
LL | *value = 1;
69-
| ^^^^^^
57+
| ^^^^^^^^^^
7058

71-
error: aborting due to 11 previous errors
59+
error: aborting due to 9 previous errors
7260

0 commit comments

Comments
 (0)