Skip to content

Commit 4630d1b

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 894f7a4 commit 4630d1b

21 files changed

+60
-32
lines changed

compiler/rustc_middle/src/mir/syntax.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,9 @@ pub enum AnalysisPhase {
127127
/// * [`StatementKind::AscribeUserType`]
128128
/// * [`StatementKind::Coverage`] with [`CoverageKind::BlockMarker`] or [`CoverageKind::SpanMarker`]
129129
/// * [`Rvalue::Ref`] with `BorrowKind::Fake`
130+
/// * [`CastKind::PointerCoercion`] with any of the following:
131+
/// * [`PointerCoercion::ArrayToPointer`]
132+
/// * [`PointerCoercion::MutToConstPointer`]
130133
///
131134
/// Furthermore, `Deref` projections must be the first projection within any place (if they
132135
/// appear at all)
@@ -1284,8 +1287,7 @@ pub enum Rvalue<'tcx> {
12841287
///
12851288
/// This allows for casts from/to a variety of types.
12861289
///
1287-
/// **FIXME**: Document exactly which `CastKind`s allow which types of casts. Figure out why
1288-
/// `ArrayToPointer` and `MutToConstPointer` are special.
1290+
/// **FIXME**: Document exactly which `CastKind`s allow which types of casts.
12891291
Cast(CastKind, Operand<'tcx>, Ty<'tcx>),
12901292

12911293
/// * `Offset` has the same semantics as [`offset`](pointer::offset), except that the second
@@ -1365,6 +1367,13 @@ pub enum CastKind {
13651367
PointerWithExposedProvenance,
13661368
/// Pointer related casts that are done by coercions. Note that reference-to-raw-ptr casts are
13671369
/// translated into `&raw mut/const *r`, i.e., they are not actually casts.
1370+
///
1371+
/// The following are allowed in [`AnalysisPhase::Initial`] as they're needed for borrowck,
1372+
/// but after that are forbidden (including in all phases of runtime MIR):
1373+
/// * [`PointerCoercion::ArrayToPointer`]
1374+
/// * [`PointerCoercion::MutToConstPointer`]
1375+
///
1376+
/// Both are runtime nops, so should be [`CastKind::PtrToPtr`] instead in runtime MIR.
13681377
PointerCoercion(PointerCoercion),
13691378
/// Cast into a dyn* object.
13701379
DynStar,

compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
1919
use crate::MirPass;
2020
use rustc_middle::mir::coverage::CoverageKind;
21-
use rustc_middle::mir::{Body, BorrowKind, Rvalue, StatementKind, TerminatorKind};
21+
use rustc_middle::mir::{Body, BorrowKind, CastKind, Rvalue, StatementKind, TerminatorKind};
22+
use rustc_middle::ty::adjustment::PointerCoercion;
2223
use rustc_middle::ty::TyCtxt;
2324

2425
pub struct CleanupPostBorrowck;
@@ -36,6 +37,22 @@ impl<'tcx> MirPass<'tcx> for CleanupPostBorrowck {
3637
CoverageKind::BlockMarker { .. } | CoverageKind::SpanMarker { .. },
3738
)
3839
| StatementKind::FakeRead(..) => statement.make_nop(),
40+
StatementKind::Assign(box (
41+
_,
42+
Rvalue::Cast(
43+
ref mut cast_kind @ CastKind::PointerCoercion(
44+
PointerCoercion::ArrayToPointer
45+
| PointerCoercion::MutToConstPointer,
46+
),
47+
..,
48+
),
49+
)) => {
50+
// BorrowCk needed to track whether these cases were coercions or casts,
51+
// to know whether to check lifetimes in their pointees,
52+
// but from now on that distinction doesn't matter,
53+
// so just make them ordinary pointer casts instead.
54+
*cast_kind = CastKind::PtrToPtr;
55+
}
3956
_ => (),
4057
}
4158
}

compiler/rustc_mir_transform/src/gvn.rs

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

1167-
if let PtrToPtr | PointerCoercion(MutToConstPointer) = kind
1163+
if let PtrToPtr = kind
11681164
&& let Value::Cast { kind: inner_kind, value: inner_value, from: inner_from, to: _ } =
11691165
*self.get(value)
1170-
&& let PtrToPtr | PointerCoercion(MutToConstPointer) = inner_kind
1166+
&& let PtrToPtr = inner_kind
11711167
{
11721168
from = inner_from;
11731169
value = inner_value;

compiler/rustc_mir_transform/src/lib.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,11 @@ mod abort_unwinding_calls;
5151
mod add_call_guards;
5252
mod add_moves_for_packed_drops;
5353
mod add_retag;
54+
mod add_subtyping_projections;
55+
mod check_alignment;
5456
mod check_const_item_mutation;
5557
mod check_packed_ref;
56-
mod remove_place_mention;
5758
// This pass is public to allow external drivers to perform MIR cleanup
58-
mod add_subtyping_projections;
5959
pub mod cleanup_post_borrowck;
6060
mod copy_prop;
6161
mod coroutine;
@@ -94,6 +94,7 @@ mod prettify;
9494
mod promote_consts;
9595
mod ref_prop;
9696
mod remove_noop_landing_pads;
97+
mod remove_place_mention;
9798
mod remove_storage_markers;
9899
mod remove_uninit_drops;
99100
mod remove_unneeded_drops;
@@ -103,7 +104,6 @@ mod reveal_all;
103104
mod shim;
104105
mod ssa;
105106
// This pass is public to allow external drivers to perform MIR cleanup
106-
mod check_alignment;
107107
pub mod simplify;
108108
mod simplify_branches;
109109
mod simplify_comparison_integral;

compiler/rustc_mir_transform/src/validate.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -1188,6 +1188,9 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
11881188
"CastKind::{kind:?} output must be a raw const pointer, not {:?}",
11891189
ty::RawPtr(_, Mutability::Not)
11901190
);
1191+
if self.mir_phase >= MirPhase::Analysis(AnalysisPhase::PostCleanup) {
1192+
self.fail(location, format!("After borrowck, MIR disallows {kind:?}"));
1193+
}
11911194
}
11921195
CastKind::PointerCoercion(PointerCoercion::ArrayToPointer) => {
11931196
// FIXME: Check pointee types
@@ -1201,6 +1204,9 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
12011204
"CastKind::{kind:?} output must be a raw pointer, not {:?}",
12021205
ty::RawPtr(..)
12031206
);
1207+
if self.mir_phase >= MirPhase::Analysis(AnalysisPhase::PostCleanup) {
1208+
self.fail(location, format!("After borrowck, MIR disallows {kind:?}"));
1209+
}
12041210
}
12051211
CastKind::PointerCoercion(PointerCoercion::Unsize) => {
12061212
// This is used for all `CoerceUnsized` types,
@@ -1212,7 +1218,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
12121218
if !input_valid || !target_valid {
12131219
self.fail(
12141220
location,
1215-
format!("Wrong cast kind {kind:?} for the type {op_ty}",),
1221+
format!("Wrong cast kind {kind:?} for the type {op_ty}"),
12161222
);
12171223
}
12181224
}

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_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range<usize>) ->
4141
StorageLive(_9);
4242
StorageLive(_7);
4343
StorageLive(_6);
44-
_6 = _5 as *const [u32] (PointerCoercion(MutToConstPointer));
44+
_6 = _5 as *const [u32] (PtrToPtr);
4545
_7 = PtrMetadata(_6);
4646
StorageDead(_6);
4747
_8 = <std::ops::Range<usize> as SliceIndex<[T]>>::get_unchecked_mut::precondition_check(_3, _4, move _7) -> [return: bb1, unwind unreachable];

tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range<usize>) ->
4141
StorageLive(_9);
4242
StorageLive(_7);
4343
StorageLive(_6);
44-
_6 = _5 as *const [u32] (PointerCoercion(MutToConstPointer));
44+
_6 = _5 as *const [u32] (PtrToPtr);
4545
_7 = PtrMetadata(_6);
4646
StorageDead(_6);
4747
_8 = <std::ops::Range<usize> as SliceIndex<[T]>>::get_unchecked_mut::precondition_check(_3, _4, move _7) -> [return: bb1, unwind unreachable];

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)