Add a pointee_metadata_ty_or_projection
helper
This commit is contained in:
parent
9140c9ad5b
commit
a76e1d9b09
@ -289,19 +289,7 @@ impl<'tcx> UnOp {
|
||||
pub fn ty(&self, tcx: TyCtxt<'tcx>, arg_ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
match self {
|
||||
UnOp::Not | UnOp::Neg => arg_ty,
|
||||
UnOp::PtrMetadata => {
|
||||
let pointee_ty = arg_ty
|
||||
.builtin_deref(true)
|
||||
.unwrap_or_else(|| bug!("PtrMetadata of non-dereferenceable ty {arg_ty:?}"));
|
||||
if pointee_ty.is_trivially_sized(tcx) {
|
||||
tcx.types.unit
|
||||
} else {
|
||||
let Some(metadata_def_id) = tcx.lang_items().metadata_type() else {
|
||||
bug!("No metadata_type lang item while looking at {arg_ty:?}")
|
||||
};
|
||||
Ty::new_projection(tcx, metadata_def_id, [pointee_ty])
|
||||
}
|
||||
}
|
||||
UnOp::PtrMetadata => arg_ty.pointee_metadata_ty_or_projection(tcx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1638,6 +1638,34 @@ impl<'tcx> Ty<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Given a pointer or reference type, returns the type of the *pointee*'s
|
||||
/// metadata. If it can't be determined exactly (perhaps due to still
|
||||
/// being generic) then a projection through `ptr::Pointee` will be returned.
|
||||
///
|
||||
/// This is particularly useful for getting the type of the result of
|
||||
/// [`UnOp::PtrMetadata`](crate::mir::UnOp::PtrMetadata).
|
||||
///
|
||||
/// Panics if `self` is not dereferencable.
|
||||
#[track_caller]
|
||||
pub fn pointee_metadata_ty_or_projection(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
|
||||
let Some(pointee_ty) = self.builtin_deref(true) else {
|
||||
bug!("Type {self:?} is not a pointer or reference type")
|
||||
};
|
||||
if pointee_ty.is_trivially_sized(tcx) {
|
||||
tcx.types.unit
|
||||
} else {
|
||||
match pointee_ty.ptr_metadata_ty_or_tail(tcx, |x| x) {
|
||||
Ok(metadata_ty) => metadata_ty,
|
||||
Err(tail_ty) => {
|
||||
let Some(metadata_def_id) = tcx.lang_items().metadata_type() else {
|
||||
bug!("No metadata_type lang item while looking at {self:?}")
|
||||
};
|
||||
Ty::new_projection(tcx, metadata_def_id, [tail_ty])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// When we create a closure, we record its kind (i.e., what trait
|
||||
/// it implements, constrained by how it uses its borrows) into its
|
||||
/// [`ty::ClosureArgs`] or [`ty::CoroutineClosureArgs`] using a type
|
||||
|
@ -987,23 +987,14 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
||||
// `*const [T]` -> `*const T` which remove metadata.
|
||||
// We run on potentially-generic MIR, though, so unlike codegen
|
||||
// we can't always know exactly what the metadata are.
|
||||
// Thankfully, equality on `ptr_metadata_ty_or_tail` gives us
|
||||
// what we need: `Ok(meta_ty)` if the metadata is known, or
|
||||
// `Err(tail_ty)` if not. Matching metadata is ok, but if
|
||||
// that's not known, then matching tail types is also ok,
|
||||
// allowing things like `*mut (?A, ?T)` <-> `*mut (?B, ?T)`.
|
||||
// To allow things like `*mut (?A, ?T)` <-> `*mut (?B, ?T)`,
|
||||
// it's fine to get a projection as the type.
|
||||
// FIXME: Would it be worth trying to normalize, rather than
|
||||
// passing the identity closure? Or are the types in the
|
||||
// just accepting the projection? Or are the types in the
|
||||
// Cast realistically about as normalized as we can get anyway?
|
||||
Value::Cast { kind: CastKind::PtrToPtr, value: inner, from, to }
|
||||
if from
|
||||
.builtin_deref(true)
|
||||
.unwrap()
|
||||
.ptr_metadata_ty_or_tail(self.tcx, |t| t)
|
||||
== to
|
||||
.builtin_deref(true)
|
||||
.unwrap()
|
||||
.ptr_metadata_ty_or_tail(self.tcx, |t| t) =>
|
||||
if from.pointee_metadata_ty_or_projection(self.tcx)
|
||||
== to.pointee_metadata_ty_or_projection(self.tcx) =>
|
||||
{
|
||||
arg_index = *inner;
|
||||
was_updated = true;
|
||||
|
@ -15,10 +15,12 @@
|
||||
let mut _10: bool;
|
||||
|
||||
bb0: {
|
||||
StorageLive(_3);
|
||||
- StorageLive(_3);
|
||||
+ nop;
|
||||
StorageLive(_4);
|
||||
_4 = _1;
|
||||
StorageLive(_5);
|
||||
- StorageLive(_5);
|
||||
+ nop;
|
||||
StorageLive(_6);
|
||||
StorageLive(_7);
|
||||
_7 = &(*_2);
|
||||
@ -32,12 +34,14 @@
|
||||
bb1: {
|
||||
StorageDead(_6);
|
||||
- _3 = Lt(move _4, move _5);
|
||||
+ _3 = Lt(_1, move _5);
|
||||
switchInt(move _3) -> [0: bb4, otherwise: bb2];
|
||||
- switchInt(move _3) -> [0: bb4, otherwise: bb2];
|
||||
+ _3 = Lt(_1, const N);
|
||||
+ switchInt(_3) -> [0: bb4, otherwise: bb2];
|
||||
}
|
||||
|
||||
bb2: {
|
||||
StorageDead(_5);
|
||||
- StorageDead(_5);
|
||||
+ nop;
|
||||
StorageDead(_4);
|
||||
StorageLive(_8);
|
||||
_8 = _1;
|
||||
@ -45,8 +49,8 @@
|
||||
- _10 = Lt(_8, _9);
|
||||
- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> [success: bb3, unwind unreachable];
|
||||
+ _9 = const N;
|
||||
+ _10 = Lt(_1, const N);
|
||||
+ assert(move _10, "index out of bounds: the length is {} but the index is {}", const N, _1) -> [success: bb3, unwind unreachable];
|
||||
+ _10 = _3;
|
||||
+ assert(_3, "index out of bounds: the length is {} but the index is {}", const N, _1) -> [success: bb3, unwind unreachable];
|
||||
}
|
||||
|
||||
bb3: {
|
||||
@ -57,14 +61,16 @@
|
||||
}
|
||||
|
||||
bb4: {
|
||||
StorageDead(_5);
|
||||
- StorageDead(_5);
|
||||
+ nop;
|
||||
StorageDead(_4);
|
||||
_0 = const 42_u8;
|
||||
goto -> bb5;
|
||||
}
|
||||
|
||||
bb5: {
|
||||
StorageDead(_3);
|
||||
- StorageDead(_3);
|
||||
+ nop;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -15,10 +15,12 @@
|
||||
let mut _10: bool;
|
||||
|
||||
bb0: {
|
||||
StorageLive(_3);
|
||||
- StorageLive(_3);
|
||||
+ nop;
|
||||
StorageLive(_4);
|
||||
_4 = _1;
|
||||
StorageLive(_5);
|
||||
- StorageLive(_5);
|
||||
+ nop;
|
||||
StorageLive(_6);
|
||||
StorageLive(_7);
|
||||
_7 = &(*_2);
|
||||
@ -32,12 +34,14 @@
|
||||
bb1: {
|
||||
StorageDead(_6);
|
||||
- _3 = Lt(move _4, move _5);
|
||||
+ _3 = Lt(_1, move _5);
|
||||
switchInt(move _3) -> [0: bb4, otherwise: bb2];
|
||||
- switchInt(move _3) -> [0: bb4, otherwise: bb2];
|
||||
+ _3 = Lt(_1, const N);
|
||||
+ switchInt(_3) -> [0: bb4, otherwise: bb2];
|
||||
}
|
||||
|
||||
bb2: {
|
||||
StorageDead(_5);
|
||||
- StorageDead(_5);
|
||||
+ nop;
|
||||
StorageDead(_4);
|
||||
StorageLive(_8);
|
||||
_8 = _1;
|
||||
@ -45,8 +49,8 @@
|
||||
- _10 = Lt(_8, _9);
|
||||
- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> [success: bb3, unwind continue];
|
||||
+ _9 = const N;
|
||||
+ _10 = Lt(_1, const N);
|
||||
+ assert(move _10, "index out of bounds: the length is {} but the index is {}", const N, _1) -> [success: bb3, unwind continue];
|
||||
+ _10 = _3;
|
||||
+ assert(_3, "index out of bounds: the length is {} but the index is {}", const N, _1) -> [success: bb3, unwind continue];
|
||||
}
|
||||
|
||||
bb3: {
|
||||
@ -57,14 +61,16 @@
|
||||
}
|
||||
|
||||
bb4: {
|
||||
StorageDead(_5);
|
||||
- StorageDead(_5);
|
||||
+ nop;
|
||||
StorageDead(_4);
|
||||
_0 = const 42_u8;
|
||||
goto -> bb5;
|
||||
}
|
||||
|
||||
bb5: {
|
||||
StorageDead(_3);
|
||||
- StorageDead(_3);
|
||||
+ nop;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -18,10 +18,12 @@
|
||||
let mut _13: bool;
|
||||
|
||||
bb0: {
|
||||
StorageLive(_3);
|
||||
- StorageLive(_3);
|
||||
+ nop;
|
||||
StorageLive(_4);
|
||||
_4 = _1;
|
||||
StorageLive(_5);
|
||||
- StorageLive(_5);
|
||||
+ nop;
|
||||
StorageLive(_6);
|
||||
StorageLive(_7);
|
||||
_7 = &(*_2);
|
||||
@ -35,12 +37,14 @@
|
||||
bb1: {
|
||||
StorageDead(_6);
|
||||
- _3 = Lt(move _4, move _5);
|
||||
+ _3 = Lt(_1, move _5);
|
||||
switchInt(move _3) -> [0: bb4, otherwise: bb2];
|
||||
- switchInt(move _3) -> [0: bb4, otherwise: bb2];
|
||||
+ _3 = Lt(_1, const N);
|
||||
+ switchInt(_3) -> [0: bb4, otherwise: bb2];
|
||||
}
|
||||
|
||||
bb2: {
|
||||
StorageDead(_5);
|
||||
- StorageDead(_5);
|
||||
+ nop;
|
||||
StorageDead(_4);
|
||||
StorageLive(_8);
|
||||
_8 = _1;
|
||||
@ -48,8 +52,8 @@
|
||||
- _10 = Lt(_8, _9);
|
||||
- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> [success: bb3, unwind unreachable];
|
||||
+ _9 = const N;
|
||||
+ _10 = Lt(_1, const N);
|
||||
+ assert(move _10, "index out of bounds: the length is {} but the index is {}", const N, _1) -> [success: bb3, unwind unreachable];
|
||||
+ _10 = _3;
|
||||
+ assert(_3, "index out of bounds: the length is {} but the index is {}", const N, _1) -> [success: bb3, unwind unreachable];
|
||||
}
|
||||
|
||||
bb3: {
|
||||
@ -60,7 +64,8 @@
|
||||
}
|
||||
|
||||
bb4: {
|
||||
StorageDead(_5);
|
||||
- StorageDead(_5);
|
||||
+ nop;
|
||||
StorageDead(_4);
|
||||
StorageLive(_11);
|
||||
_11 = const 0_usize;
|
||||
@ -81,7 +86,8 @@
|
||||
}
|
||||
|
||||
bb6: {
|
||||
StorageDead(_3);
|
||||
- StorageDead(_3);
|
||||
+ nop;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -18,10 +18,12 @@
|
||||
let mut _13: bool;
|
||||
|
||||
bb0: {
|
||||
StorageLive(_3);
|
||||
- StorageLive(_3);
|
||||
+ nop;
|
||||
StorageLive(_4);
|
||||
_4 = _1;
|
||||
StorageLive(_5);
|
||||
- StorageLive(_5);
|
||||
+ nop;
|
||||
StorageLive(_6);
|
||||
StorageLive(_7);
|
||||
_7 = &(*_2);
|
||||
@ -35,12 +37,14 @@
|
||||
bb1: {
|
||||
StorageDead(_6);
|
||||
- _3 = Lt(move _4, move _5);
|
||||
+ _3 = Lt(_1, move _5);
|
||||
switchInt(move _3) -> [0: bb4, otherwise: bb2];
|
||||
- switchInt(move _3) -> [0: bb4, otherwise: bb2];
|
||||
+ _3 = Lt(_1, const N);
|
||||
+ switchInt(_3) -> [0: bb4, otherwise: bb2];
|
||||
}
|
||||
|
||||
bb2: {
|
||||
StorageDead(_5);
|
||||
- StorageDead(_5);
|
||||
+ nop;
|
||||
StorageDead(_4);
|
||||
StorageLive(_8);
|
||||
_8 = _1;
|
||||
@ -48,8 +52,8 @@
|
||||
- _10 = Lt(_8, _9);
|
||||
- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> [success: bb3, unwind continue];
|
||||
+ _9 = const N;
|
||||
+ _10 = Lt(_1, const N);
|
||||
+ assert(move _10, "index out of bounds: the length is {} but the index is {}", const N, _1) -> [success: bb3, unwind continue];
|
||||
+ _10 = _3;
|
||||
+ assert(_3, "index out of bounds: the length is {} but the index is {}", const N, _1) -> [success: bb3, unwind continue];
|
||||
}
|
||||
|
||||
bb3: {
|
||||
@ -60,7 +64,8 @@
|
||||
}
|
||||
|
||||
bb4: {
|
||||
StorageDead(_5);
|
||||
- StorageDead(_5);
|
||||
+ nop;
|
||||
StorageDead(_4);
|
||||
StorageLive(_11);
|
||||
_11 = const 0_usize;
|
||||
@ -81,7 +86,8 @@
|
||||
}
|
||||
|
||||
bb6: {
|
||||
StorageDead(_3);
|
||||
- StorageDead(_3);
|
||||
+ nop;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -5,16 +5,20 @@
|
||||
// EMIT_MIR lower_array_len.array_bound.GVN.diff
|
||||
pub fn array_bound<const N: usize>(index: usize, slice: &[u8; N]) -> u8 {
|
||||
// CHECK-LABEL: fn array_bound(
|
||||
// CHECK: [[len:_.*]] = const N;
|
||||
// CHECK: Lt(_1, move [[len]]);
|
||||
// CHECK-NOT: Lt
|
||||
// CHECK: Lt(_1, const N);
|
||||
// CHECK-NOT: Lt
|
||||
if index < slice.len() { slice[index] } else { 42 }
|
||||
}
|
||||
|
||||
// EMIT_MIR lower_array_len.array_bound_mut.GVN.diff
|
||||
pub fn array_bound_mut<const N: usize>(index: usize, slice: &mut [u8; N]) -> u8 {
|
||||
// CHECK-LABEL: fn array_bound_mut(
|
||||
// CHECK: [[len:_.*]] = const N;
|
||||
// CHECK: Lt(_1, move [[len]]);
|
||||
// CHECK-NOT: Lt
|
||||
// CHECK: Lt(_1, const N);
|
||||
// CHECK-NOT: Lt
|
||||
// CHECK: Lt(const 0_usize, const N)
|
||||
// CHECK-NOT: Lt
|
||||
if index < slice.len() {
|
||||
slice[index]
|
||||
} else {
|
||||
|
Loading…
x
Reference in New Issue
Block a user