Skip to content

Commit a76e1d9

Browse files
committed
Add a pointee_metadata_ty_or_projection helper
1 parent 9140c9a commit a76e1d9

8 files changed

+102
-67
lines changed

compiler/rustc_middle/src/mir/tcx.rs

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -289,19 +289,7 @@ impl<'tcx> UnOp {
289289
pub fn ty(&self, tcx: TyCtxt<'tcx>, arg_ty: Ty<'tcx>) -> Ty<'tcx> {
290290
match self {
291291
UnOp::Not | UnOp::Neg => arg_ty,
292-
UnOp::PtrMetadata => {
293-
let pointee_ty = arg_ty
294-
.builtin_deref(true)
295-
.unwrap_or_else(|| bug!("PtrMetadata of non-dereferenceable ty {arg_ty:?}"));
296-
if pointee_ty.is_trivially_sized(tcx) {
297-
tcx.types.unit
298-
} else {
299-
let Some(metadata_def_id) = tcx.lang_items().metadata_type() else {
300-
bug!("No metadata_type lang item while looking at {arg_ty:?}")
301-
};
302-
Ty::new_projection(tcx, metadata_def_id, [pointee_ty])
303-
}
304-
}
292+
UnOp::PtrMetadata => arg_ty.pointee_metadata_ty_or_projection(tcx),
305293
}
306294
}
307295
}

compiler/rustc_middle/src/ty/sty.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1638,6 +1638,34 @@ impl<'tcx> Ty<'tcx> {
16381638
}
16391639
}
16401640

1641+
/// Given a pointer or reference type, returns the type of the *pointee*'s
1642+
/// metadata. If it can't be determined exactly (perhaps due to still
1643+
/// being generic) then a projection through `ptr::Pointee` will be returned.
1644+
///
1645+
/// This is particularly useful for getting the type of the result of
1646+
/// [`UnOp::PtrMetadata`](crate::mir::UnOp::PtrMetadata).
1647+
///
1648+
/// Panics if `self` is not dereferencable.
1649+
#[track_caller]
1650+
pub fn pointee_metadata_ty_or_projection(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
1651+
let Some(pointee_ty) = self.builtin_deref(true) else {
1652+
bug!("Type {self:?} is not a pointer or reference type")
1653+
};
1654+
if pointee_ty.is_trivially_sized(tcx) {
1655+
tcx.types.unit
1656+
} else {
1657+
match pointee_ty.ptr_metadata_ty_or_tail(tcx, |x| x) {
1658+
Ok(metadata_ty) => metadata_ty,
1659+
Err(tail_ty) => {
1660+
let Some(metadata_def_id) = tcx.lang_items().metadata_type() else {
1661+
bug!("No metadata_type lang item while looking at {self:?}")
1662+
};
1663+
Ty::new_projection(tcx, metadata_def_id, [tail_ty])
1664+
}
1665+
}
1666+
}
1667+
}
1668+
16411669
/// When we create a closure, we record its kind (i.e., what trait
16421670
/// it implements, constrained by how it uses its borrows) into its
16431671
/// [`ty::ClosureArgs`] or [`ty::CoroutineClosureArgs`] using a type

compiler/rustc_mir_transform/src/gvn.rs

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -987,23 +987,14 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
987987
// `*const [T]` -> `*const T` which remove metadata.
988988
// We run on potentially-generic MIR, though, so unlike codegen
989989
// we can't always know exactly what the metadata are.
990-
// Thankfully, equality on `ptr_metadata_ty_or_tail` gives us
991-
// what we need: `Ok(meta_ty)` if the metadata is known, or
992-
// `Err(tail_ty)` if not. Matching metadata is ok, but if
993-
// that's not known, then matching tail types is also ok,
994-
// allowing things like `*mut (?A, ?T)` <-> `*mut (?B, ?T)`.
990+
// To allow things like `*mut (?A, ?T)` <-> `*mut (?B, ?T)`,
991+
// it's fine to get a projection as the type.
995992
// FIXME: Would it be worth trying to normalize, rather than
996-
// passing the identity closure? Or are the types in the
993+
// just accepting the projection? Or are the types in the
997994
// Cast realistically about as normalized as we can get anyway?
998995
Value::Cast { kind: CastKind::PtrToPtr, value: inner, from, to }
999-
if from
1000-
.builtin_deref(true)
1001-
.unwrap()
1002-
.ptr_metadata_ty_or_tail(self.tcx, |t| t)
1003-
== to
1004-
.builtin_deref(true)
1005-
.unwrap()
1006-
.ptr_metadata_ty_or_tail(self.tcx, |t| t) =>
996+
if from.pointee_metadata_ty_or_projection(self.tcx)
997+
== to.pointee_metadata_ty_or_projection(self.tcx) =>
1007998
{
1008999
arg_index = *inner;
10091000
was_updated = true;

tests/mir-opt/lower_array_len.array_bound.GVN.panic-abort.diff

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@
1515
let mut _10: bool;
1616

1717
bb0: {
18-
StorageLive(_3);
18+
- StorageLive(_3);
19+
+ nop;
1920
StorageLive(_4);
2021
_4 = _1;
21-
StorageLive(_5);
22+
- StorageLive(_5);
23+
+ nop;
2224
StorageLive(_6);
2325
StorageLive(_7);
2426
_7 = &(*_2);
@@ -32,21 +34,23 @@
3234
bb1: {
3335
StorageDead(_6);
3436
- _3 = Lt(move _4, move _5);
35-
+ _3 = Lt(_1, move _5);
36-
switchInt(move _3) -> [0: bb4, otherwise: bb2];
37+
- switchInt(move _3) -> [0: bb4, otherwise: bb2];
38+
+ _3 = Lt(_1, const N);
39+
+ switchInt(_3) -> [0: bb4, otherwise: bb2];
3740
}
3841

3942
bb2: {
40-
StorageDead(_5);
43+
- StorageDead(_5);
44+
+ nop;
4145
StorageDead(_4);
4246
StorageLive(_8);
4347
_8 = _1;
4448
- _9 = Len((*_2));
4549
- _10 = Lt(_8, _9);
4650
- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> [success: bb3, unwind unreachable];
4751
+ _9 = const N;
48-
+ _10 = Lt(_1, const N);
49-
+ assert(move _10, "index out of bounds: the length is {} but the index is {}", const N, _1) -> [success: bb3, unwind unreachable];
52+
+ _10 = _3;
53+
+ assert(_3, "index out of bounds: the length is {} but the index is {}", const N, _1) -> [success: bb3, unwind unreachable];
5054
}
5155

5256
bb3: {
@@ -57,14 +61,16 @@
5761
}
5862

5963
bb4: {
60-
StorageDead(_5);
64+
- StorageDead(_5);
65+
+ nop;
6166
StorageDead(_4);
6267
_0 = const 42_u8;
6368
goto -> bb5;
6469
}
6570

6671
bb5: {
67-
StorageDead(_3);
72+
- StorageDead(_3);
73+
+ nop;
6874
return;
6975
}
7076
}

tests/mir-opt/lower_array_len.array_bound.GVN.panic-unwind.diff

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@
1515
let mut _10: bool;
1616

1717
bb0: {
18-
StorageLive(_3);
18+
- StorageLive(_3);
19+
+ nop;
1920
StorageLive(_4);
2021
_4 = _1;
21-
StorageLive(_5);
22+
- StorageLive(_5);
23+
+ nop;
2224
StorageLive(_6);
2325
StorageLive(_7);
2426
_7 = &(*_2);
@@ -32,21 +34,23 @@
3234
bb1: {
3335
StorageDead(_6);
3436
- _3 = Lt(move _4, move _5);
35-
+ _3 = Lt(_1, move _5);
36-
switchInt(move _3) -> [0: bb4, otherwise: bb2];
37+
- switchInt(move _3) -> [0: bb4, otherwise: bb2];
38+
+ _3 = Lt(_1, const N);
39+
+ switchInt(_3) -> [0: bb4, otherwise: bb2];
3740
}
3841

3942
bb2: {
40-
StorageDead(_5);
43+
- StorageDead(_5);
44+
+ nop;
4145
StorageDead(_4);
4246
StorageLive(_8);
4347
_8 = _1;
4448
- _9 = Len((*_2));
4549
- _10 = Lt(_8, _9);
4650
- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> [success: bb3, unwind continue];
4751
+ _9 = const N;
48-
+ _10 = Lt(_1, const N);
49-
+ assert(move _10, "index out of bounds: the length is {} but the index is {}", const N, _1) -> [success: bb3, unwind continue];
52+
+ _10 = _3;
53+
+ assert(_3, "index out of bounds: the length is {} but the index is {}", const N, _1) -> [success: bb3, unwind continue];
5054
}
5155

5256
bb3: {
@@ -57,14 +61,16 @@
5761
}
5862

5963
bb4: {
60-
StorageDead(_5);
64+
- StorageDead(_5);
65+
+ nop;
6166
StorageDead(_4);
6267
_0 = const 42_u8;
6368
goto -> bb5;
6469
}
6570

6671
bb5: {
67-
StorageDead(_3);
72+
- StorageDead(_3);
73+
+ nop;
6874
return;
6975
}
7076
}

tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-abort.diff

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@
1818
let mut _13: bool;
1919

2020
bb0: {
21-
StorageLive(_3);
21+
- StorageLive(_3);
22+
+ nop;
2223
StorageLive(_4);
2324
_4 = _1;
24-
StorageLive(_5);
25+
- StorageLive(_5);
26+
+ nop;
2527
StorageLive(_6);
2628
StorageLive(_7);
2729
_7 = &(*_2);
@@ -35,21 +37,23 @@
3537
bb1: {
3638
StorageDead(_6);
3739
- _3 = Lt(move _4, move _5);
38-
+ _3 = Lt(_1, move _5);
39-
switchInt(move _3) -> [0: bb4, otherwise: bb2];
40+
- switchInt(move _3) -> [0: bb4, otherwise: bb2];
41+
+ _3 = Lt(_1, const N);
42+
+ switchInt(_3) -> [0: bb4, otherwise: bb2];
4043
}
4144

4245
bb2: {
43-
StorageDead(_5);
46+
- StorageDead(_5);
47+
+ nop;
4448
StorageDead(_4);
4549
StorageLive(_8);
4650
_8 = _1;
4751
- _9 = Len((*_2));
4852
- _10 = Lt(_8, _9);
4953
- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> [success: bb3, unwind unreachable];
5054
+ _9 = const N;
51-
+ _10 = Lt(_1, const N);
52-
+ assert(move _10, "index out of bounds: the length is {} but the index is {}", const N, _1) -> [success: bb3, unwind unreachable];
55+
+ _10 = _3;
56+
+ assert(_3, "index out of bounds: the length is {} but the index is {}", const N, _1) -> [success: bb3, unwind unreachable];
5357
}
5458

5559
bb3: {
@@ -60,7 +64,8 @@
6064
}
6165

6266
bb4: {
63-
StorageDead(_5);
67+
- StorageDead(_5);
68+
+ nop;
6469
StorageDead(_4);
6570
StorageLive(_11);
6671
_11 = const 0_usize;
@@ -81,7 +86,8 @@
8186
}
8287

8388
bb6: {
84-
StorageDead(_3);
89+
- StorageDead(_3);
90+
+ nop;
8591
return;
8692
}
8793
}

tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-unwind.diff

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@
1818
let mut _13: bool;
1919

2020
bb0: {
21-
StorageLive(_3);
21+
- StorageLive(_3);
22+
+ nop;
2223
StorageLive(_4);
2324
_4 = _1;
24-
StorageLive(_5);
25+
- StorageLive(_5);
26+
+ nop;
2527
StorageLive(_6);
2628
StorageLive(_7);
2729
_7 = &(*_2);
@@ -35,21 +37,23 @@
3537
bb1: {
3638
StorageDead(_6);
3739
- _3 = Lt(move _4, move _5);
38-
+ _3 = Lt(_1, move _5);
39-
switchInt(move _3) -> [0: bb4, otherwise: bb2];
40+
- switchInt(move _3) -> [0: bb4, otherwise: bb2];
41+
+ _3 = Lt(_1, const N);
42+
+ switchInt(_3) -> [0: bb4, otherwise: bb2];
4043
}
4144

4245
bb2: {
43-
StorageDead(_5);
46+
- StorageDead(_5);
47+
+ nop;
4448
StorageDead(_4);
4549
StorageLive(_8);
4650
_8 = _1;
4751
- _9 = Len((*_2));
4852
- _10 = Lt(_8, _9);
4953
- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> [success: bb3, unwind continue];
5054
+ _9 = const N;
51-
+ _10 = Lt(_1, const N);
52-
+ assert(move _10, "index out of bounds: the length is {} but the index is {}", const N, _1) -> [success: bb3, unwind continue];
55+
+ _10 = _3;
56+
+ assert(_3, "index out of bounds: the length is {} but the index is {}", const N, _1) -> [success: bb3, unwind continue];
5357
}
5458

5559
bb3: {
@@ -60,7 +64,8 @@
6064
}
6165

6266
bb4: {
63-
StorageDead(_5);
67+
- StorageDead(_5);
68+
+ nop;
6469
StorageDead(_4);
6570
StorageLive(_11);
6671
_11 = const 0_usize;
@@ -81,7 +86,8 @@
8186
}
8287

8388
bb6: {
84-
StorageDead(_3);
89+
- StorageDead(_3);
90+
+ nop;
8591
return;
8692
}
8793
}

tests/mir-opt/lower_array_len.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,20 @@
55
// EMIT_MIR lower_array_len.array_bound.GVN.diff
66
pub fn array_bound<const N: usize>(index: usize, slice: &[u8; N]) -> u8 {
77
// CHECK-LABEL: fn array_bound(
8-
// CHECK: [[len:_.*]] = const N;
9-
// CHECK: Lt(_1, move [[len]]);
8+
// CHECK-NOT: Lt
9+
// CHECK: Lt(_1, const N);
10+
// CHECK-NOT: Lt
1011
if index < slice.len() { slice[index] } else { 42 }
1112
}
1213

1314
// EMIT_MIR lower_array_len.array_bound_mut.GVN.diff
1415
pub fn array_bound_mut<const N: usize>(index: usize, slice: &mut [u8; N]) -> u8 {
1516
// CHECK-LABEL: fn array_bound_mut(
16-
// CHECK: [[len:_.*]] = const N;
17-
// CHECK: Lt(_1, move [[len]]);
17+
// CHECK-NOT: Lt
18+
// CHECK: Lt(_1, const N);
19+
// CHECK-NOT: Lt
20+
// CHECK: Lt(const 0_usize, const N)
21+
// CHECK-NOT: Lt
1822
if index < slice.len() {
1923
slice[index]
2024
} else {

0 commit comments

Comments
 (0)