Skip to content

Commit afc8a38

Browse files
Check for ptr-to-int casts in const functions in THIR unsafeck
1 parent f1977c9 commit afc8a38

6 files changed

+107
-16
lines changed

compiler/rustc_mir_build/src/check_unsafety.rs

+19-3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ struct UnsafetyVisitor<'a, 'tcx> {
2121
/// `unsafe` block, and whether it has been used.
2222
safety_context: SafetyContext,
2323
body_unsafety: BodyUnsafety,
24+
is_const: bool,
2425
}
2526

2627
impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
@@ -166,6 +167,16 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
166167
(Bound::Unbounded, Bound::Unbounded) => {}
167168
_ => self.requires_unsafe(expr.span, InitializingTypeWith),
168169
},
170+
ExprKind::Cast { source } => {
171+
let source = &self.thir[source];
172+
if self.tcx.features().const_raw_ptr_to_usize_cast
173+
&& self.is_const
174+
&& (source.ty.is_unsafe_ptr() || source.ty.is_fn_ptr())
175+
&& expr.ty.is_integral()
176+
{
177+
self.requires_unsafe(expr.span, CastOfPointerToInt);
178+
}
179+
}
169180
_ => {}
170181
}
171182

@@ -209,7 +220,6 @@ enum UnsafeOpKind {
209220
CallToUnsafeFunction,
210221
UseOfInlineAssembly,
211222
InitializingTypeWith,
212-
#[allow(dead_code)] // FIXME
213223
CastOfPointerToInt,
214224
#[allow(dead_code)] // FIXME
215225
UseOfMutableStatic,
@@ -299,6 +309,7 @@ pub fn check_unsafety<'tcx>(
299309
tcx: TyCtxt<'tcx>,
300310
thir: &Thir<'tcx>,
301311
expr: ExprId,
312+
def_id: LocalDefId,
302313
hir_id: hir::HirId,
303314
) {
304315
let body_unsafety = tcx.hir().fn_sig_by_hir_id(hir_id).map_or(BodyUnsafety::Safe, |fn_sig| {
@@ -310,8 +321,13 @@ pub fn check_unsafety<'tcx>(
310321
});
311322
let safety_context =
312323
if body_unsafety.is_unsafe() { SafetyContext::UnsafeFn } else { SafetyContext::Safe };
324+
let is_const = match tcx.hir().body_owner_kind(hir_id) {
325+
hir::BodyOwnerKind::Closure => false,
326+
hir::BodyOwnerKind::Fn => tcx.is_const_fn_raw(def_id.to_def_id()),
327+
hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => true,
328+
};
313329
let mut visitor =
314-
UnsafetyVisitor { tcx, thir, safety_context, hir_context: hir_id, body_unsafety };
330+
UnsafetyVisitor { tcx, thir, safety_context, hir_context: hir_id, body_unsafety, is_const };
315331
visitor.visit_expr(&thir[expr]);
316332
}
317333

@@ -323,7 +339,7 @@ crate fn thir_check_unsafety_inner<'tcx>(
323339
let body_id = tcx.hir().body_owned_by(hir_id);
324340
let body = tcx.hir().body(body_id);
325341
let (thir, expr) = cx::build_thir(tcx, def, &body.value);
326-
check_unsafety(tcx, &thir, expr, hir_id);
342+
check_unsafety(tcx, &thir, expr, def.did, hir_id);
327343
}
328344

329345
crate fn thir_check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error[E0133]: cast of pointer to int is unsafe and requires unsafe function or block
2+
--> $DIR/cast-ptr-to-int-const.rs:10:9
3+
|
4+
LL | &Y as *const u32 as usize
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ cast of pointer to int
6+
|
7+
= note: casting pointers to integers in constants
8+
9+
error[E0133]: cast of pointer to int is unsafe and requires unsafe function or block
10+
--> $DIR/cast-ptr-to-int-const.rs:17:5
11+
|
12+
LL | &0 as *const i32 as usize
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ cast of pointer to int
14+
|
15+
= note: casting pointers to integers in constants
16+
17+
error: aborting due to 2 previous errors
18+
19+
For more information about this error, try `rustc --explain E0133`.
+7-13
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,19 @@
1-
// gate-test-const_raw_ptr_to_usize_cast
2-
// revisions: with_feature without_feature
1+
// revisions: mir thir
2+
// [thir]compile-flags: -Z thir-unsafeck
33

4-
#![cfg_attr(with_feature, feature(const_raw_ptr_to_usize_cast))]
4+
#![feature(const_raw_ptr_to_usize_cast)]
55

66
fn main() {
7-
const X: usize = unsafe {
8-
main as usize //[without_feature]~ ERROR casting pointers to integers in constants is unstable
9-
};
107
const Y: u32 = 0;
11-
const Z: usize = unsafe {
12-
&Y as *const u32 as usize //[without_feature]~ ERROR is unstable
13-
};
148
// Cast in `const` without `unsafe` block
159
const SAFE: usize = {
16-
&Y as *const u32 as usize //[without_feature]~ ERROR is unstable
17-
//[with_feature]~^ ERROR cast of pointer to int is unsafe and requires unsafe
10+
&Y as *const u32 as usize
11+
//~^ ERROR cast of pointer to int is unsafe and requires unsafe
1812
};
1913
}
2014

2115
// Cast in `const fn` without `unsafe` block
2216
const fn test() -> usize {
23-
&0 as *const i32 as usize //[without_feature]~ ERROR is unstable
24-
//[with_feature]~^ ERROR cast of pointer to int is unsafe and requires unsafe
17+
&0 as *const i32 as usize
18+
//~^ ERROR cast of pointer to int is unsafe and requires unsafe
2519
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error[E0133]: cast of pointer to int is unsafe and requires unsafe function or block
2+
--> $DIR/cast-ptr-to-int-const.rs:10:9
3+
|
4+
LL | &Y as *const u32 as usize
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ cast of pointer to int
6+
|
7+
= note: casting pointers to integers in constants
8+
9+
error[E0133]: cast of pointer to int is unsafe and requires unsafe function or block
10+
--> $DIR/cast-ptr-to-int-const.rs:17:5
11+
|
12+
LL | &0 as *const i32 as usize
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ cast of pointer to int
14+
|
15+
= note: casting pointers to integers in constants
16+
17+
error: aborting due to 2 previous errors
18+
19+
For more information about this error, try `rustc --explain E0133`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
fn main() {
2+
const X: usize = unsafe {
3+
main as usize //~ ERROR casting pointers to integers in constants is unstable
4+
};
5+
const Y: u32 = 0;
6+
const Z: usize = unsafe {
7+
&Y as *const u32 as usize //~ ERROR is unstable
8+
};
9+
}
10+
11+
const fn test() -> usize {
12+
&0 as *const i32 as usize //~ ERROR is unstable
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
error[E0658]: casting pointers to integers in constants is unstable
2+
--> $DIR/feature-gate-const_raw_ptr_to_usize_cast.rs:3:9
3+
|
4+
LL | main as usize
5+
| ^^^^^^^^^^^^^
6+
|
7+
= note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
8+
= help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
9+
10+
error[E0658]: casting pointers to integers in constants is unstable
11+
--> $DIR/feature-gate-const_raw_ptr_to_usize_cast.rs:7:9
12+
|
13+
LL | &Y as *const u32 as usize
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
15+
|
16+
= note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
17+
= help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
18+
19+
error[E0658]: casting pointers to integers in constant functions is unstable
20+
--> $DIR/feature-gate-const_raw_ptr_to_usize_cast.rs:12:5
21+
|
22+
LL | &0 as *const i32 as usize
23+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
24+
|
25+
= note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
26+
= help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
27+
28+
error: aborting due to 3 previous errors
29+
30+
For more information about this error, try `rustc --explain E0658`.

0 commit comments

Comments
 (0)