Skip to content

Commit 05f597c

Browse files
committed
Ban ArrayToPointer and MutToConstPointer from runtime MIR
Apparently MIR borrowck cares about at least one of these for checking variance. In runtime MIR, though, there's no need for them as `PtrToPtr` does the same thing. (Banning them simplifies passes like GVN that no longer need to handle multiple cast possibilities.)
1 parent 9a7bf4a commit 05f597c

19 files changed

+65
-29
lines changed

compiler/rustc_middle/src/mir/syntax.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,9 @@ pub enum RuntimePhase {
143143
/// * [`TerminatorKind::CoroutineDrop`]
144144
/// * [`Rvalue::Aggregate`] for any `AggregateKind` except `Array`
145145
/// * [`PlaceElem::OpaqueCast`]
146+
/// * [`CastKind::PointerCoercion`] with any of the following:
147+
/// * [`PointerCoercion::ArrayToPointer`]
148+
/// * [`PointerCoercion::MutToConstPointer`]
146149
///
147150
/// And the following variants are allowed:
148151
/// * [`StatementKind::Retag`]
@@ -1281,8 +1284,7 @@ pub enum Rvalue<'tcx> {
12811284
///
12821285
/// This allows for casts from/to a variety of types.
12831286
///
1284-
/// **FIXME**: Document exactly which `CastKind`s allow which types of casts. Figure out why
1285-
/// `ArrayToPointer` and `MutToConstPointer` are special.
1287+
/// **FIXME**: Document exactly which `CastKind`s allow which types of casts.
12861288
Cast(CastKind, Operand<'tcx>, Ty<'tcx>),
12871289

12881290
/// * `Offset` has the same semantics as [`offset`](pointer::offset), except that the second
@@ -1362,6 +1364,12 @@ pub enum CastKind {
13621364
PointerWithExposedProvenance,
13631365
/// Pointer related casts that are done by coercions. Note that reference-to-raw-ptr casts are
13641366
/// translated into `&raw mut/const *r`, i.e., they are not actually casts.
1367+
///
1368+
/// The following are allowed in analysis MIR (for borrowck), but are forbidden in runtime MIR:
1369+
/// * [`PointerCoercion::ArrayToPointer`]
1370+
/// * [`PointerCoercion::MutToConstPointer`]
1371+
///
1372+
/// Both are runtime nops, so should be [`CastKind::PtrToPtr`] instead in runtime MIR.
13651373
PointerCoercion(PointerCoercion),
13661374
/// Cast into a dyn* object.
13671375
DynStar,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
use rustc_middle::mir::*;
2+
use rustc_middle::ty::adjustment::PointerCoercion;
3+
use rustc_middle::ty::TyCtxt;
4+
5+
/// This pass turns the `PointerCoercion` variants which are disallowed in runtime MIR
6+
/// into ordinary `PtrToPtr` casts instead.
7+
pub struct CoercionsToCasts;
8+
9+
impl<'tcx> MirPass<'tcx> for CoercionsToCasts {
10+
fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
11+
for block in body.basic_blocks.as_mut_preserves_cfg() {
12+
for statement in block.statements.iter_mut() {
13+
if let StatementKind::Assign(box (_place, rvalue)) = &mut statement.kind
14+
&& let Rvalue::Cast(cast_kind, ..) = rvalue
15+
&& let CastKind::PointerCoercion(
16+
PointerCoercion::ArrayToPointer | PointerCoercion::MutToConstPointer,
17+
) = cast_kind
18+
{
19+
*cast_kind = CastKind::PtrToPtr;
20+
}
21+
}
22+
}
23+
}
24+
}

compiler/rustc_mir_transform/src/gvn.rs

+3-7
Original file line numberDiff line numberDiff line change
@@ -572,11 +572,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
572572
let ret = self.ecx.ptr_to_ptr(&src, to).ok()?;
573573
ret.into()
574574
}
575-
CastKind::PointerCoercion(
576-
ty::adjustment::PointerCoercion::MutToConstPointer
577-
| ty::adjustment::PointerCoercion::ArrayToPointer
578-
| ty::adjustment::PointerCoercion::UnsafeFnPointer,
579-
) => {
575+
CastKind::PointerCoercion(ty::adjustment::PointerCoercion::UnsafeFnPointer) => {
580576
let src = self.evaluated[value].as_ref()?;
581577
let src = self.ecx.read_immediate(src).ok()?;
582578
let to = self.ecx.layout_of(to).ok()?;
@@ -1165,10 +1161,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
11651161
}
11661162
}
11671163

1168-
if let PtrToPtr | PointerCoercion(MutToConstPointer) = kind
1164+
if let PtrToPtr = kind
11691165
&& let Value::Cast { kind: inner_kind, value: inner_value, from: inner_from, to: _ } =
11701166
*self.get(value)
1171-
&& let PtrToPtr | PointerCoercion(MutToConstPointer) = inner_kind
1167+
&& let PtrToPtr = inner_kind
11721168
{
11731169
from = inner_from;
11741170
value = inner_value;

compiler/rustc_mir_transform/src/lib.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,13 @@ mod abort_unwinding_calls;
4949
mod add_call_guards;
5050
mod add_moves_for_packed_drops;
5151
mod add_retag;
52+
mod add_subtyping_projections;
53+
mod check_alignment;
5254
mod check_const_item_mutation;
5355
mod check_packed_ref;
54-
mod remove_place_mention;
5556
// This pass is public to allow external drivers to perform MIR cleanup
56-
mod add_subtyping_projections;
5757
pub mod cleanup_post_borrowck;
58+
mod coercions_to_casts;
5859
mod copy_prop;
5960
mod coroutine;
6061
mod cost_checker;
@@ -92,6 +93,7 @@ mod prettify;
9293
mod promote_consts;
9394
mod ref_prop;
9495
mod remove_noop_landing_pads;
96+
mod remove_place_mention;
9597
mod remove_storage_markers;
9698
mod remove_uninit_drops;
9799
mod remove_unneeded_drops;
@@ -101,7 +103,6 @@ mod reveal_all;
101103
mod shim;
102104
mod ssa;
103105
// This pass is public to allow external drivers to perform MIR cleanup
104-
mod check_alignment;
105106
pub mod simplify;
106107
mod simplify_branches;
107108
mod simplify_comparison_integral;
@@ -506,6 +507,7 @@ fn run_analysis_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
506507
/// Returns the sequence of passes that lowers analysis to runtime MIR.
507508
fn run_runtime_lowering_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
508509
let passes: &[&dyn MirPass<'tcx>] = &[
510+
&coercions_to_casts::CoercionsToCasts,
509511
// These next passes must be executed together
510512
&add_call_guards::CriticalCallEdges,
511513
&reveal_all::RevealAll, // has to be done before drop elaboration, since we need to drop opaque types, too.

compiler/rustc_mir_transform/src/validate.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -1187,6 +1187,9 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
11871187
"CastKind::{kind:?} output must be a raw const pointer, not {:?}",
11881188
ty::RawPtr(_, Mutability::Not)
11891189
);
1190+
if let MirPhase::Runtime(..) = self.mir_phase {
1191+
self.fail(location, format!("Runtime MIR disallows {kind:?}"));
1192+
}
11901193
}
11911194
CastKind::PointerCoercion(PointerCoercion::ArrayToPointer) => {
11921195
// FIXME: Check pointee types
@@ -1200,6 +1203,9 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
12001203
"CastKind::{kind:?} output must be a raw pointer, not {:?}",
12011204
ty::RawPtr(..)
12021205
);
1206+
if let MirPhase::Runtime(..) = self.mir_phase {
1207+
self.fail(location, format!("Runtime MIR disallows {kind:?}"));
1208+
}
12031209
}
12041210
CastKind::PointerCoercion(PointerCoercion::Unsize) => {
12051211
// This is used for all `CoerceUnsized` types,
@@ -1211,7 +1217,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
12111217
if !input_valid || !target_valid {
12121218
self.fail(
12131219
location,
1214-
format!("Wrong cast kind {kind:?} for the type {op_ty}",),
1220+
format!("Wrong cast kind {kind:?} for the type {op_ty}"),
12151221
);
12161222
}
12171223
}

tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff

+1-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@
8080

8181
bb4: {
8282
StorageDead(_8);
83-
- _11 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer));
83+
- _11 = _6 as *const [bool; 0] (PtrToPtr);
8484
- _5 = NonNull::<[bool; 0]> { pointer: _11 };
8585
+ _11 = const {0x1 as *const [bool; 0]};
8686
+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};

tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@
8484

8585
bb5: {
8686
StorageDead(_8);
87-
- _11 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer));
87+
- _11 = _6 as *const [bool; 0] (PtrToPtr);
8888
- _5 = NonNull::<[bool; 0]> { pointer: _11 };
8989
+ _11 = const {0x1 as *const [bool; 0]};
9090
+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};

tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff

+1-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@
8080

8181
bb4: {
8282
StorageDead(_8);
83-
- _11 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer));
83+
- _11 = _6 as *const [bool; 0] (PtrToPtr);
8484
- _5 = NonNull::<[bool; 0]> { pointer: _11 };
8585
+ _11 = const {0x1 as *const [bool; 0]};
8686
+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};

tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@
8484

8585
bb5: {
8686
StorageDead(_8);
87-
- _11 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer));
87+
- _11 = _6 as *const [bool; 0] (PtrToPtr);
8888
- _5 = NonNull::<[bool; 0]> { pointer: _11 };
8989
+ _11 = const {0x1 as *const [bool; 0]};
9090
+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};

tests/mir-opt/instsimplify/casts.roundtrip.InstSimplify.diff

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
StorageLive(_4);
1515
_4 = _1;
1616
_3 = move _4 as *mut u8 (PtrToPtr);
17-
_2 = move _3 as *const u8 (PointerCoercion(MutToConstPointer));
17+
_2 = move _3 as *const u8 (PtrToPtr);
1818
StorageDead(_4);
1919
StorageDead(_3);
2020
- _0 = move _2 as *const u8 (PtrToPtr);

tests/mir-opt/instsimplify/casts.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ pub fn roundtrip(x: *const u8) -> *const u8 {
2121
// CHECK-LABEL: fn roundtrip(
2222
// CHECK: _4 = _1;
2323
// CHECK: _3 = move _4 as *mut u8 (PtrToPtr);
24-
// CHECK: _2 = move _3 as *const u8 (PointerCoercion(MutToConstPointer));
24+
// CHECK: _2 = move _3 as *const u8 (PtrToPtr);
2525
x as *mut u8 as *const u8
2626
}
2727

tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir

+1-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
7979
_7 = _4 as *mut T (PtrToPtr);
8080
_8 = Offset(_7, _3);
8181
StorageDead(_7);
82-
_9 = move _8 as *const T (PointerCoercion(MutToConstPointer));
82+
_9 = move _8 as *const T (PtrToPtr);
8383
StorageDead(_8);
8484
goto -> bb3;
8585
}

tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir

+1-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
7979
_7 = _4 as *mut T (PtrToPtr);
8080
_8 = Offset(_7, _3);
8181
StorageDead(_7);
82-
_9 = move _8 as *const T (PointerCoercion(MutToConstPointer));
82+
_9 = move _8 as *const T (PtrToPtr);
8383
StorageDead(_8);
8484
goto -> bb3;
8585
}

tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
7171
_7 = _4 as *mut T (PtrToPtr);
7272
_8 = Offset(_7, _3);
7373
StorageDead(_7);
74-
_9 = move _8 as *const T (PointerCoercion(MutToConstPointer));
74+
_9 = move _8 as *const T (PtrToPtr);
7575
StorageDead(_8);
7676
goto -> bb3;
7777
}

tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
7171
_7 = _4 as *mut T (PtrToPtr);
7272
_8 = Offset(_7, _3);
7373
StorageDead(_7);
74-
_9 = move _8 as *const T (PointerCoercion(MutToConstPointer));
74+
_9 = move _8 as *const T (PtrToPtr);
7575
StorageDead(_8);
7676
goto -> bb3;
7777
}

tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir

+1-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
7979
_7 = _4 as *mut T (PtrToPtr);
8080
_8 = Offset(_7, _3);
8181
StorageDead(_7);
82-
_9 = move _8 as *const T (PointerCoercion(MutToConstPointer));
82+
_9 = move _8 as *const T (PtrToPtr);
8383
StorageDead(_8);
8484
goto -> bb3;
8585
}

tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir

+1-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
7979
_7 = _4 as *mut T (PtrToPtr);
8080
_8 = Offset(_7, _3);
8181
StorageDead(_7);
82-
_9 = move _8 as *const T (PointerCoercion(MutToConstPointer));
82+
_9 = move _8 as *const T (PtrToPtr);
8383
StorageDead(_8);
8484
goto -> bb3;
8585
}

tests/mir-opt/retag.array_casts.SimplifyCfg-pre-optimizations.after.panic-abort.mir

+2-2
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ fn array_casts() -> () {
6464
StorageLive(_4);
6565
_4 = &mut _1;
6666
_3 = &raw mut (*_4);
67-
_2 = move _3 as *mut usize (PointerCoercion(ArrayToPointer));
67+
_2 = move _3 as *mut usize (PtrToPtr);
6868
StorageDead(_3);
6969
StorageDead(_4);
7070
StorageLive(_5);
@@ -87,7 +87,7 @@ fn array_casts() -> () {
8787
StorageLive(_11);
8888
_11 = &_8;
8989
_10 = &raw const (*_11);
90-
_9 = move _10 as *const usize (PointerCoercion(ArrayToPointer));
90+
_9 = move _10 as *const usize (PtrToPtr);
9191
StorageDead(_10);
9292
StorageDead(_11);
9393
StorageLive(_12);

tests/mir-opt/retag.array_casts.SimplifyCfg-pre-optimizations.after.panic-unwind.mir

+2-2
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ fn array_casts() -> () {
6464
StorageLive(_4);
6565
_4 = &mut _1;
6666
_3 = &raw mut (*_4);
67-
_2 = move _3 as *mut usize (PointerCoercion(ArrayToPointer));
67+
_2 = move _3 as *mut usize (PtrToPtr);
6868
StorageDead(_3);
6969
StorageDead(_4);
7070
StorageLive(_5);
@@ -87,7 +87,7 @@ fn array_casts() -> () {
8787
StorageLive(_11);
8888
_11 = &_8;
8989
_10 = &raw const (*_11);
90-
_9 = move _10 as *const usize (PointerCoercion(ArrayToPointer));
90+
_9 = move _10 as *const usize (PtrToPtr);
9191
StorageDead(_10);
9292
StorageDead(_11);
9393
StorageLive(_12);

0 commit comments

Comments
 (0)