Skip to content

Commit 3d5d7a2

Browse files
committed
Auto merge of #126308 - scottmcm:ban-some-coercions, r=saethlin
Ban `ArrayToPointer` and `MutToConstPointer` from runtime MIR Zulip conversation: <https://rust-lang.zulipchat.com/#narrow/stream/189540-t-compiler.2Fwg-mir-opt/topic/CastKind.3A.3APointerCoercion.20in.20Runtime.20MIR/near/443955195> 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.) r? mir
2 parents d8a38b0 + e04e351 commit 3d5d7a2

24 files changed

+78
-50
lines changed

compiler/rustc_codegen_cranelift/src/base.rs

+11-10
Original file line numberDiff line numberDiff line change
@@ -677,21 +677,22 @@ fn codegen_stmt<'tcx>(
677677
CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer),
678678
ref operand,
679679
to_ty,
680-
)
681-
| Rvalue::Cast(
682-
CastKind::PointerCoercion(PointerCoercion::MutToConstPointer),
683-
ref operand,
684-
to_ty,
685-
)
686-
| Rvalue::Cast(
687-
CastKind::PointerCoercion(PointerCoercion::ArrayToPointer),
688-
ref operand,
689-
to_ty,
690680
) => {
691681
let to_layout = fx.layout_of(fx.monomorphize(to_ty));
692682
let operand = codegen_operand(fx, operand);
693683
lval.write_cvalue(fx, operand.cast_pointer_to(to_layout));
694684
}
685+
Rvalue::Cast(
686+
CastKind::PointerCoercion(
687+
PointerCoercion::MutToConstPointer | PointerCoercion::ArrayToPointer,
688+
),
689+
..,
690+
) => {
691+
bug!(
692+
"{:?} is for borrowck, and should never appear in codegen",
693+
to_place_and_rval.1
694+
);
695+
}
695696
Rvalue::Cast(
696697
CastKind::IntToInt
697698
| CastKind::FloatToFloat

compiler/rustc_codegen_ssa/src/mir/rvalue.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -456,8 +456,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
456456
base::unsize_ptr(bx, lldata, operand.layout.ty, cast.ty, llextra);
457457
OperandValue::Pair(lldata, llextra)
458458
}
459-
mir::CastKind::PointerCoercion(PointerCoercion::MutToConstPointer)
460-
| mir::CastKind::PtrToPtr
459+
mir::CastKind::PointerCoercion(
460+
PointerCoercion::MutToConstPointer | PointerCoercion::ArrayToPointer,
461+
) => {
462+
bug!("{kind:?} is for borrowck, and should never appear in codegen");
463+
}
464+
mir::CastKind::PtrToPtr
461465
if bx.cx().is_backend_scalar_pair(operand.layout) =>
462466
{
463467
if let OperandValue::Pair(data_ptr, meta) = operand.val {
@@ -477,9 +481,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
477481
base::cast_to_dyn_star(bx, lldata, operand.layout, cast.ty, llextra);
478482
OperandValue::Pair(lldata, llextra)
479483
}
480-
mir::CastKind::PointerCoercion(
481-
PointerCoercion::MutToConstPointer | PointerCoercion::ArrayToPointer,
482-
)
483484
| mir::CastKind::IntToInt
484485
| mir::CastKind::FloatToInt
485486
| mir::CastKind::FloatToFloat

compiler/rustc_const_eval/src/interpret/cast.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
7070
CastKind::PointerCoercion(
7171
PointerCoercion::MutToConstPointer | PointerCoercion::ArrayToPointer,
7272
) => {
73-
// These are NOPs, but can be wide pointers.
74-
let v = self.read_immediate(src)?;
75-
self.write_immediate(*v, dest)?;
73+
bug!("{cast_kind:?} casts are for borrowck only, not runtime MIR");
7674
}
7775

7876
CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer) => {

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)