Skip to content

Commit f1eb2c4

Browse files
committed
Recommend with_exposed_provenance instead of as casts in non-const
1 parent 28bcb16 commit f1eb2c4

File tree

5 files changed

+194
-67
lines changed

5 files changed

+194
-67
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: 50 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -90,13 +90,15 @@ declare_lint! {
9090
/// Any attempt to use the resulting pointers are undefined behavior as the resulting
9191
/// pointers won't have any provenance.
9292
///
93-
/// Alternatively, `as` casts should be used, as they do not carry the provenance
94-
/// requirement or if the wanting to create pointers without provenance
95-
/// `ptr::without_provenance_mut` should be used.
93+
/// Alternatively, [`std::ptr::with_exposed_provenance`] or `as` casts should be used,
94+
/// as they do not carry the provenance requirement. If the wanting to create pointers
95+
/// without provenance [`std::ptr::without_provenance`] should be used instead.
9696
///
97-
/// See [std::mem::transmute] in the reference for more details.
97+
/// See [`std::mem::transmute`] in the reference for more details.
9898
///
99-
/// [std::mem::transmute]: https://doc.rust-lang.org/std/mem/fn.transmute.html
99+
/// [`std::mem::transmute`]: https://doc.rust-lang.org/std/mem/fn.transmute.html
100+
/// [`std::ptr::with_exposed_provenance`]: https://doc.rust-lang.org/std/ptr/fn.with_exposed_provenance.html
101+
/// [`std::ptr::without_provenance`]: https://doc.rust-lang.org/std/ptr/fn.without_provenance.html
100102
pub INTEGER_TO_PTR_TRANSMUTES,
101103
Warn,
102104
"detects integer to pointer transmutes",
@@ -152,36 +154,56 @@ fn check_int_to_ptr_transmute<'tcx>(
152154
.layout_of(cx.typing_env().as_query_input(*inner_ty))
153155
.is_ok_and(|layout| !layout.is_1zst())
154156
{
155-
// does the argument needs parenthesis
156-
let mut paren_left = "";
157-
let mut paren_right = "";
158-
if matches!(arg.kind, hir::ExprKind::Binary(..)) {
159-
paren_left = "(";
160-
paren_right = ")";
161-
}
162-
163157
cx.tcx.emit_node_span_lint(
164158
INTEGER_TO_PTR_TRANSMUTES,
165159
expr.hir_id,
166160
expr.span,
167161
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()),
162+
// FIXME: once https://github.com/rust-lang/rust/issues/144538 finishes,
163+
// we can recommend the method in const context too.
164+
suggestion: if !cx.tcx.hir_is_inside_const_context(expr.hir_id) {
165+
let suffix = if mutbl.is_mut() { "_mut" } else { "" };
166+
if dst.is_ref() {
167+
IntegerToPtrTransmutesSuggestion::ToRef {
168+
dst: *inner_ty,
169+
suffix,
170+
ref_mutbl: mutbl.prefix_str(),
171+
start_call: expr.span.shrink_to_lo().until(arg.span),
172+
}
173+
} else {
174+
IntegerToPtrTransmutesSuggestion::ToPtr {
175+
dst: *inner_ty,
176+
suffix,
177+
start_call: expr.span.shrink_to_lo().until(arg.span),
178+
}
177179
}
178180
} 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()),
181+
// does the argument needs parenthesis
182+
let mut paren_left = "";
183+
let mut paren_right = "";
184+
if matches!(arg.kind, hir::ExprKind::Binary(..)) {
185+
paren_left = "(";
186+
paren_right = ")";
187+
}
188+
189+
if dst.is_ref() {
190+
IntegerToPtrTransmutesSuggestion::ToRefInConst {
191+
dst: *inner_ty,
192+
ref_mutbl: mutbl.prefix_str(),
193+
ptr_mutbl: mutbl.ptr_str(),
194+
paren_left,
195+
paren_right,
196+
start_call: expr.span.shrink_to_lo().until(arg.span),
197+
end_call: arg.span.shrink_to_hi().until(expr.span.shrink_to_hi()),
198+
}
199+
} else {
200+
IntegerToPtrTransmutesSuggestion::ToPtrInConst {
201+
dst,
202+
paren_left,
203+
paren_right,
204+
start_call: expr.span.shrink_to_lo().until(arg.span),
205+
end_call: arg.span.shrink_to_hi().until(expr.span.shrink_to_hi()),
206+
}
185207
}
186208
},
187209
},

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) };

0 commit comments

Comments
 (0)