Skip to content

Commit 2011707

Browse files
committed
Recommend with_exposed_provenance instead of as casts in non-const
1 parent 996a9ab commit 2011707

File tree

5 files changed

+177
-54
lines changed

5 files changed

+177
-54
lines changed

compiler/rustc_lint/src/lints.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1617,10 +1617,27 @@ pub(crate) struct IntegerToPtrTransmutes<'tcx> {
16171617
}
16181618

16191619
#[derive(Subdiagnostic)]
1620-
// FIXME: recommend `with_exposed_provenance` when it's const-stable
1620+
// FIXME: always recommend `with_exposed_provenance` when it's const-stable
16211621
pub(crate) enum IntegerToPtrTransmutesSuggestion<'tcx> {
16221622
#[multipart_suggestion(lint_suggestion_as, applicability = "machine-applicable")]
16231623
ToPtr {
1624+
dst: Ty<'tcx>,
1625+
suffix: &'static str,
1626+
#[suggestion_part(code = "std::ptr::with_exposed_provenance{suffix}::<{dst}>(")]
1627+
start_call: Span,
1628+
},
1629+
#[multipart_suggestion(lint_suggestion_as, applicability = "machine-applicable")]
1630+
ToRef {
1631+
dst: Ty<'tcx>,
1632+
suffix: &'static str,
1633+
ref_mutbl: &'static str,
1634+
#[suggestion_part(
1635+
code = "&{ref_mutbl}*std::ptr::with_exposed_provenance{suffix}::<{dst}>("
1636+
)]
1637+
start_call: Span,
1638+
},
1639+
#[multipart_suggestion(lint_suggestion_as, applicability = "machine-applicable")]
1640+
ToPtrInConst {
16241641
dst: Ty<'tcx>,
16251642
paren_left: &'static str,
16261643
paren_right: &'static str,
@@ -1630,7 +1647,7 @@ pub(crate) enum IntegerToPtrTransmutesSuggestion<'tcx> {
16301647
end_call: Span,
16311648
},
16321649
#[multipart_suggestion(lint_suggestion_as, applicability = "machine-applicable")]
1633-
ToRef {
1650+
ToRefInConst {
16341651
dst: Ty<'tcx>,
16351652
ptr_mutbl: &'static str,
16361653
ref_mutbl: &'static str,

compiler/rustc_lint/src/transmute.rs

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -165,23 +165,41 @@ fn check_int_to_ptr_transmute<'tcx>(
165165
expr.hir_id,
166166
expr.span,
167167
IntegerToPtrTransmutes {
168-
suggestion: if dst.is_ref() {
169-
IntegerToPtrTransmutesSuggestion::ToRef {
170-
dst: *inner_ty,
171-
ref_mutbl: mutbl.prefix_str(),
172-
ptr_mutbl: mutbl.ptr_str(),
173-
paren_left,
174-
paren_right,
175-
start_call: expr.span.shrink_to_lo().until(arg.span),
176-
end_call: arg.span.shrink_to_hi().until(expr.span.shrink_to_hi()),
168+
suggestion: if !cx.tcx.hir_is_inside_const_context(expr.hir_id) {
169+
let suffix = if mutbl.is_mut() { "_mut" } else { "" };
170+
if dst.is_ref() {
171+
IntegerToPtrTransmutesSuggestion::ToRef {
172+
dst: *inner_ty,
173+
suffix,
174+
ref_mutbl: mutbl.prefix_str(),
175+
start_call: expr.span.shrink_to_lo().until(arg.span),
176+
}
177+
} else {
178+
IntegerToPtrTransmutesSuggestion::ToPtr {
179+
dst: *inner_ty,
180+
suffix,
181+
start_call: expr.span.shrink_to_lo().until(arg.span),
182+
}
177183
}
178184
} else {
179-
IntegerToPtrTransmutesSuggestion::ToPtr {
180-
dst,
181-
paren_left,
182-
paren_right,
183-
start_call: expr.span.shrink_to_lo().until(arg.span),
184-
end_call: arg.span.shrink_to_hi().until(expr.span.shrink_to_hi()),
185+
if dst.is_ref() {
186+
IntegerToPtrTransmutesSuggestion::ToRefInConst {
187+
dst: *inner_ty,
188+
ref_mutbl: mutbl.prefix_str(),
189+
ptr_mutbl: mutbl.ptr_str(),
190+
paren_left,
191+
paren_right,
192+
start_call: expr.span.shrink_to_lo().until(arg.span),
193+
end_call: arg.span.shrink_to_hi().until(expr.span.shrink_to_hi()),
194+
}
195+
} else {
196+
IntegerToPtrTransmutesSuggestion::ToPtrInConst {
197+
dst,
198+
paren_left,
199+
paren_right,
200+
start_call: expr.span.shrink_to_lo().until(arg.span),
201+
end_call: arg.span.shrink_to_hi().until(expr.span.shrink_to_hi()),
202+
}
185203
}
186204
},
187205
},

tests/ui/lint/int_to_ptr.fixed

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,31 @@
77
#![allow(dead_code)]
88

99
unsafe fn should_lint(a: usize) {
10-
let _ptr = unsafe { a as *const u8 };
10+
let _ptr: *const u8 = unsafe { std::ptr::with_exposed_provenance::<u8>(a) };
1111
//~^ WARN transmuting an integer to a pointer
12-
let _ptr = unsafe { &*(a as *const u8) };
12+
let _ptr: *mut u8 = unsafe { std::ptr::with_exposed_provenance_mut::<u8>(a) };
1313
//~^ WARN transmuting an integer to a pointer
14-
let _ptr = unsafe { 42usize as *const u8 };
14+
let _ref: &'static u8 = unsafe { &*std::ptr::with_exposed_provenance::<u8>(a) };
1515
//~^ WARN transmuting an integer to a pointer
16-
let _ptr = unsafe { (a + a) as *const u8 };
16+
let _ref: &'static mut u8 = unsafe { &mut *std::ptr::with_exposed_provenance_mut::<u8>(a) };
17+
//~^ WARN transmuting an integer to a pointer
18+
19+
let _ptr = unsafe { std::ptr::with_exposed_provenance::<u8>(42usize) };
20+
//~^ WARN transmuting an integer to a pointer
21+
let _ptr = unsafe { std::ptr::with_exposed_provenance::<u8>(a + a) };
1722
//~^ WARN transmuting an integer to a pointer
1823
}
1924

2025
const unsafe fn should_lintin_const(a: usize) {
21-
let _ptr = unsafe { a as *const u8 };
26+
let _ptr: *const u8 = unsafe { a as *const u8 };
27+
//~^ WARN transmuting an integer to a pointer
28+
let _ptr: *mut u8 = unsafe { a as *mut u8 };
2229
//~^ WARN transmuting an integer to a pointer
23-
let _ptr = unsafe { &*(a as *const u8) };
30+
let _ref: &'static u8 = unsafe { &*(a as *const u8) };
2431
//~^ WARN transmuting an integer to a pointer
32+
let _ref: &'static mut u8 = unsafe { &mut *(a as *mut u8) };
33+
//~^ WARN transmuting an integer to a pointer
34+
2535
let _ptr = unsafe { 42usize as *const u8 };
2636
//~^ WARN transmuting an integer to a pointer
2737
let _ptr = unsafe { (a + a) as *const u8 };

tests/ui/lint/int_to_ptr.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,31 @@
77
#![allow(dead_code)]
88

99
unsafe fn should_lint(a: usize) {
10-
let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(a) };
10+
let _ptr: *const u8 = unsafe { std::mem::transmute::<usize, *const u8>(a) };
1111
//~^ WARN transmuting an integer to a pointer
12-
let _ptr = unsafe { std::mem::transmute::<usize, &'static u8>(a) };
12+
let _ptr: *mut u8 = unsafe { std::mem::transmute::<usize, *mut u8>(a) };
1313
//~^ WARN transmuting an integer to a pointer
14+
let _ref: &'static u8 = unsafe { std::mem::transmute::<usize, &'static u8>(a) };
15+
//~^ WARN transmuting an integer to a pointer
16+
let _ref: &'static mut u8 = unsafe { std::mem::transmute::<usize, &'static mut u8>(a) };
17+
//~^ WARN transmuting an integer to a pointer
18+
1419
let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(42usize) };
1520
//~^ WARN transmuting an integer to a pointer
1621
let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(a + a) };
1722
//~^ WARN transmuting an integer to a pointer
1823
}
1924

2025
const unsafe fn should_lintin_const(a: usize) {
21-
let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(a) };
26+
let _ptr: *const u8 = unsafe { std::mem::transmute::<usize, *const u8>(a) };
2227
//~^ WARN transmuting an integer to a pointer
23-
let _ptr = unsafe { std::mem::transmute::<usize, &'static u8>(a) };
28+
let _ptr: *mut u8 = unsafe { std::mem::transmute::<usize, *mut u8>(a) };
2429
//~^ WARN transmuting an integer to a pointer
30+
let _ref: &'static u8 = unsafe { std::mem::transmute::<usize, &'static u8>(a) };
31+
//~^ WARN transmuting an integer to a pointer
32+
let _ref: &'static mut u8 = unsafe { std::mem::transmute::<usize, &'static mut u8>(a) };
33+
//~^ WARN transmuting an integer to a pointer
34+
2535
let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(42usize) };
2636
//~^ WARN transmuting an integer to a pointer
2737
let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(a + a) };

tests/ui/lint/int_to_ptr.stderr

Lines changed: 95 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
warning: transmuting an integer to a pointer creates a pointer without provenance
2-
--> $DIR/int_to_ptr.rs:10:25
2+
--> $DIR/int_to_ptr.rs:10:36
33
|
4-
LL | let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(a) };
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4+
LL | let _ptr: *const u8 = unsafe { std::mem::transmute::<usize, *const u8>(a) };
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
77
= note: this is dangerous because dereferencing the resulting pointer is undefined behavior
88
= note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
@@ -12,15 +12,15 @@ LL | let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(a) };
1212
= note: `#[warn(integer_to_ptr_transmutes)]` on by default
1313
help: use `as` cast instead to use a previously exposed provenance
1414
|
15-
LL - let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(a) };
16-
LL + let _ptr = unsafe { a as *const u8 };
15+
LL - let _ptr: *const u8 = unsafe { std::mem::transmute::<usize, *const u8>(a) };
16+
LL + let _ptr: *const u8 = unsafe { std::ptr::with_exposed_provenance::<u8>(a) };
1717
|
1818

1919
warning: transmuting an integer to a pointer creates a pointer without provenance
20-
--> $DIR/int_to_ptr.rs:12:25
20+
--> $DIR/int_to_ptr.rs:12:34
2121
|
22-
LL | let _ptr = unsafe { std::mem::transmute::<usize, &'static u8>(a) };
23-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
22+
LL | let _ptr: *mut u8 = unsafe { std::mem::transmute::<usize, *mut u8>(a) };
23+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2424
|
2525
= note: this is dangerous because dereferencing the resulting pointer is undefined behavior
2626
= note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
@@ -29,12 +29,46 @@ LL | let _ptr = unsafe { std::mem::transmute::<usize, &'static u8>(a) };
2929
= help: for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance>
3030
help: use `as` cast instead to use a previously exposed provenance
3131
|
32-
LL - let _ptr = unsafe { std::mem::transmute::<usize, &'static u8>(a) };
33-
LL + let _ptr = unsafe { &*(a as *const u8) };
32+
LL - let _ptr: *mut u8 = unsafe { std::mem::transmute::<usize, *mut u8>(a) };
33+
LL + let _ptr: *mut u8 = unsafe { std::ptr::with_exposed_provenance_mut::<u8>(a) };
3434
|
3535

3636
warning: transmuting an integer to a pointer creates a pointer without provenance
37-
--> $DIR/int_to_ptr.rs:14:25
37+
--> $DIR/int_to_ptr.rs:14:38
38+
|
39+
LL | let _ref: &'static u8 = unsafe { std::mem::transmute::<usize, &'static u8>(a) };
40+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
41+
|
42+
= note: this is dangerous because dereferencing the resulting pointer is undefined behavior
43+
= note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
44+
= help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`
45+
= help: for more information about transmute, see <https://doc.rust-lang.org/std/mem/fn.transmute.html#transmutation-between-pointers-and-integers>
46+
= help: for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance>
47+
help: use `as` cast instead to use a previously exposed provenance
48+
|
49+
LL - let _ref: &'static u8 = unsafe { std::mem::transmute::<usize, &'static u8>(a) };
50+
LL + let _ref: &'static u8 = unsafe { &*std::ptr::with_exposed_provenance::<u8>(a) };
51+
|
52+
53+
warning: transmuting an integer to a pointer creates a pointer without provenance
54+
--> $DIR/int_to_ptr.rs:16:42
55+
|
56+
LL | let _ref: &'static mut u8 = unsafe { std::mem::transmute::<usize, &'static mut u8>(a) };
57+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
58+
|
59+
= note: this is dangerous because dereferencing the resulting pointer is undefined behavior
60+
= note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
61+
= help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`
62+
= help: for more information about transmute, see <https://doc.rust-lang.org/std/mem/fn.transmute.html#transmutation-between-pointers-and-integers>
63+
= help: for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance>
64+
help: use `as` cast instead to use a previously exposed provenance
65+
|
66+
LL - let _ref: &'static mut u8 = unsafe { std::mem::transmute::<usize, &'static mut u8>(a) };
67+
LL + let _ref: &'static mut u8 = unsafe { &mut *std::ptr::with_exposed_provenance_mut::<u8>(a) };
68+
|
69+
70+
warning: transmuting an integer to a pointer creates a pointer without provenance
71+
--> $DIR/int_to_ptr.rs:19:25
3872
|
3973
LL | let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(42usize) };
4074
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -47,11 +81,11 @@ LL | let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(42usize) };
4781
help: use `as` cast instead to use a previously exposed provenance
4882
|
4983
LL - let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(42usize) };
50-
LL + let _ptr = unsafe { 42usize as *const u8 };
84+
LL + let _ptr = unsafe { std::ptr::with_exposed_provenance::<u8>(42usize) };
5185
|
5286

5387
warning: transmuting an integer to a pointer creates a pointer without provenance
54-
--> $DIR/int_to_ptr.rs:16:25
88+
--> $DIR/int_to_ptr.rs:21:25
5589
|
5690
LL | let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(a + a) };
5791
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -64,14 +98,48 @@ LL | let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(a + a) };
6498
help: use `as` cast instead to use a previously exposed provenance
6599
|
66100
LL - let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(a + a) };
67-
LL + let _ptr = unsafe { (a + a) as *const u8 };
101+
LL + let _ptr = unsafe { std::ptr::with_exposed_provenance::<u8>(a + a) };
68102
|
69103

70104
warning: transmuting an integer to a pointer creates a pointer without provenance
71-
--> $DIR/int_to_ptr.rs:21:25
105+
--> $DIR/int_to_ptr.rs:26:36
106+
|
107+
LL | let _ptr: *const u8 = unsafe { std::mem::transmute::<usize, *const u8>(a) };
108+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
109+
|
110+
= note: this is dangerous because dereferencing the resulting pointer is undefined behavior
111+
= note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
112+
= help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`
113+
= help: for more information about transmute, see <https://doc.rust-lang.org/std/mem/fn.transmute.html#transmutation-between-pointers-and-integers>
114+
= help: for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance>
115+
help: use `as` cast instead to use a previously exposed provenance
116+
|
117+
LL - let _ptr: *const u8 = unsafe { std::mem::transmute::<usize, *const u8>(a) };
118+
LL + let _ptr: *const u8 = unsafe { a as *const u8 };
119+
|
120+
121+
warning: transmuting an integer to a pointer creates a pointer without provenance
122+
--> $DIR/int_to_ptr.rs:28:34
123+
|
124+
LL | let _ptr: *mut u8 = unsafe { std::mem::transmute::<usize, *mut u8>(a) };
125+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
126+
|
127+
= note: this is dangerous because dereferencing the resulting pointer is undefined behavior
128+
= note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
129+
= help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`
130+
= help: for more information about transmute, see <https://doc.rust-lang.org/std/mem/fn.transmute.html#transmutation-between-pointers-and-integers>
131+
= help: for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance>
132+
help: use `as` cast instead to use a previously exposed provenance
133+
|
134+
LL - let _ptr: *mut u8 = unsafe { std::mem::transmute::<usize, *mut u8>(a) };
135+
LL + let _ptr: *mut u8 = unsafe { a as *mut u8 };
136+
|
137+
138+
warning: transmuting an integer to a pointer creates a pointer without provenance
139+
--> $DIR/int_to_ptr.rs:30:38
72140
|
73-
LL | let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(a) };
74-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
141+
LL | let _ref: &'static u8 = unsafe { std::mem::transmute::<usize, &'static u8>(a) };
142+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
75143
|
76144
= note: this is dangerous because dereferencing the resulting pointer is undefined behavior
77145
= note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
@@ -80,15 +148,15 @@ LL | let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(a) };
80148
= help: for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance>
81149
help: use `as` cast instead to use a previously exposed provenance
82150
|
83-
LL - let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(a) };
84-
LL + let _ptr = unsafe { a as *const u8 };
151+
LL - let _ref: &'static u8 = unsafe { std::mem::transmute::<usize, &'static u8>(a) };
152+
LL + let _ref: &'static u8 = unsafe { &*(a as *const u8) };
85153
|
86154

87155
warning: transmuting an integer to a pointer creates a pointer without provenance
88-
--> $DIR/int_to_ptr.rs:23:25
156+
--> $DIR/int_to_ptr.rs:32:42
89157
|
90-
LL | let _ptr = unsafe { std::mem::transmute::<usize, &'static u8>(a) };
91-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
158+
LL | let _ref: &'static mut u8 = unsafe { std::mem::transmute::<usize, &'static mut u8>(a) };
159+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
92160
|
93161
= note: this is dangerous because dereferencing the resulting pointer is undefined behavior
94162
= note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
@@ -97,12 +165,12 @@ LL | let _ptr = unsafe { std::mem::transmute::<usize, &'static u8>(a) };
97165
= help: for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance>
98166
help: use `as` cast instead to use a previously exposed provenance
99167
|
100-
LL - let _ptr = unsafe { std::mem::transmute::<usize, &'static u8>(a) };
101-
LL + let _ptr = unsafe { &*(a as *const u8) };
168+
LL - let _ref: &'static mut u8 = unsafe { std::mem::transmute::<usize, &'static mut u8>(a) };
169+
LL + let _ref: &'static mut u8 = unsafe { &mut *(a as *mut u8) };
102170
|
103171

104172
warning: transmuting an integer to a pointer creates a pointer without provenance
105-
--> $DIR/int_to_ptr.rs:25:25
173+
--> $DIR/int_to_ptr.rs:35:25
106174
|
107175
LL | let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(42usize) };
108176
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -119,7 +187,7 @@ LL + let _ptr = unsafe { 42usize as *const u8 };
119187
|
120188

121189
warning: transmuting an integer to a pointer creates a pointer without provenance
122-
--> $DIR/int_to_ptr.rs:27:25
190+
--> $DIR/int_to_ptr.rs:37:25
123191
|
124192
LL | let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(a + a) };
125193
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -135,5 +203,5 @@ LL - let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(a + a) };
135203
LL + let _ptr = unsafe { (a + a) as *const u8 };
136204
|
137205

138-
warning: 8 warnings emitted
206+
warning: 12 warnings emitted
139207

0 commit comments

Comments
 (0)