Auto merge of #117525 - GKFX:remove_option_payload_ptr, r=petrochenkov
Remove option_payload_ptr; redundant to offset_of The `option_payload_ptr` intrinsic is no longer required as `offset_of` supports traversing enums (#114208). This PR removes it in order to dogfood offset_of (as suggested at https://github.com/rust-lang/rust/issues/106655#issuecomment-1790907626). However, it will not build until those changes reach beta (which I think is within the next 8 days?) so I've opened it as a draft.
This commit is contained in:
commit
33688d2467
11 changed files with 16 additions and 171 deletions
|
@ -225,25 +225,6 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
|
||||||
],
|
],
|
||||||
Ty::new_ptr(tcx, ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
|
Ty::new_ptr(tcx, ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
|
||||||
),
|
),
|
||||||
sym::option_payload_ptr => {
|
|
||||||
let option_def_id = tcx.require_lang_item(hir::LangItem::Option, None);
|
|
||||||
let p0 = param(0);
|
|
||||||
(
|
|
||||||
1,
|
|
||||||
vec![Ty::new_ptr(
|
|
||||||
tcx,
|
|
||||||
ty::TypeAndMut {
|
|
||||||
ty: Ty::new_adt(
|
|
||||||
tcx,
|
|
||||||
tcx.adt_def(option_def_id),
|
|
||||||
tcx.mk_args_from_iter([ty::GenericArg::from(p0)].into_iter()),
|
|
||||||
),
|
|
||||||
mutbl: hir::Mutability::Not,
|
|
||||||
},
|
|
||||||
)],
|
|
||||||
Ty::new_ptr(tcx, ty::TypeAndMut { ty: p0, mutbl: hir::Mutability::Not }),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
sym::ptr_mask => (
|
sym::ptr_mask => (
|
||||||
1,
|
1,
|
||||||
vec![
|
vec![
|
||||||
|
|
|
@ -4,7 +4,6 @@ use crate::MirPass;
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::ty::{self, TyCtxt};
|
use rustc_middle::ty::{self, TyCtxt};
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use rustc_target::abi::{FieldIdx, VariantIdx};
|
|
||||||
|
|
||||||
pub struct LowerIntrinsics;
|
pub struct LowerIntrinsics;
|
||||||
|
|
||||||
|
@ -251,37 +250,6 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
|
||||||
});
|
});
|
||||||
terminator.kind = TerminatorKind::Goto { target };
|
terminator.kind = TerminatorKind::Goto { target };
|
||||||
}
|
}
|
||||||
sym::option_payload_ptr => {
|
|
||||||
if let (Some(target), Some(arg)) = (*target, args[0].place()) {
|
|
||||||
let ty::RawPtr(ty::TypeAndMut { ty: dest_ty, .. }) =
|
|
||||||
destination.ty(local_decls, tcx).ty.kind()
|
|
||||||
else {
|
|
||||||
bug!();
|
|
||||||
};
|
|
||||||
|
|
||||||
block.statements.push(Statement {
|
|
||||||
source_info: terminator.source_info,
|
|
||||||
kind: StatementKind::Assign(Box::new((
|
|
||||||
*destination,
|
|
||||||
Rvalue::AddressOf(
|
|
||||||
Mutability::Not,
|
|
||||||
arg.project_deeper(
|
|
||||||
&[
|
|
||||||
PlaceElem::Deref,
|
|
||||||
PlaceElem::Downcast(
|
|
||||||
Some(sym::Some),
|
|
||||||
VariantIdx::from_u32(1),
|
|
||||||
),
|
|
||||||
PlaceElem::Field(FieldIdx::from_u32(0), *dest_ty),
|
|
||||||
],
|
|
||||||
tcx,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
))),
|
|
||||||
});
|
|
||||||
terminator.kind = TerminatorKind::Goto { target };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sym::transmute | sym::transmute_unchecked => {
|
sym::transmute | sym::transmute_unchecked => {
|
||||||
let dst_ty = destination.ty(local_decls, tcx).ty;
|
let dst_ty = destination.ty(local_decls, tcx).ty;
|
||||||
let Ok([arg]) = <[_; 1]>::try_from(std::mem::take(args)) else {
|
let Ok([arg]) = <[_; 1]>::try_from(std::mem::take(args)) else {
|
||||||
|
|
|
@ -1164,7 +1164,6 @@ symbols! {
|
||||||
optin_builtin_traits,
|
optin_builtin_traits,
|
||||||
option,
|
option,
|
||||||
option_env,
|
option_env,
|
||||||
option_payload_ptr,
|
|
||||||
options,
|
options,
|
||||||
or,
|
or,
|
||||||
or_patterns,
|
or_patterns,
|
||||||
|
|
|
@ -2487,12 +2487,6 @@ extern "rust-intrinsic" {
|
||||||
where
|
where
|
||||||
G: FnOnce<ARG, Output = RET>,
|
G: FnOnce<ARG, Output = RET>,
|
||||||
F: FnOnce<ARG, Output = RET>;
|
F: FnOnce<ARG, Output = RET>;
|
||||||
|
|
||||||
/// This method creates a pointer to any `Some` value. If the argument is
|
|
||||||
/// `None`, an invalid within-bounds pointer (that is still acceptable for
|
|
||||||
/// constructing an empty slice) is returned.
|
|
||||||
#[rustc_nounwind]
|
|
||||||
pub fn option_payload_ptr<T>(arg: *const Option<T>) -> *const T;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some functions are defined here because they accidentally got made
|
// Some functions are defined here because they accidentally got made
|
||||||
|
|
|
@ -97,9 +97,11 @@ where
|
||||||
// SAFETY: Loop conditions ensure the index is in bounds.
|
// SAFETY: Loop conditions ensure the index is in bounds.
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let opt_payload_at = core::intrinsics::option_payload_ptr(&val);
|
let opt_payload_at: *const MaybeUninit<B> = (&val as *const Option<B>)
|
||||||
|
.byte_add(core::mem::offset_of!(Option<B>, Some.0))
|
||||||
|
.cast();
|
||||||
let dst = guard.array.as_mut_ptr().add(idx);
|
let dst = guard.array.as_mut_ptr().add(idx);
|
||||||
crate::ptr::copy_nonoverlapping(opt_payload_at.cast(), dst, 1);
|
crate::ptr::copy_nonoverlapping(opt_payload_at, dst, 1);
|
||||||
crate::mem::forget(val);
|
crate::mem::forget(val);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -178,6 +178,8 @@
|
||||||
#![feature(is_ascii_octdigit)]
|
#![feature(is_ascii_octdigit)]
|
||||||
#![feature(isqrt)]
|
#![feature(isqrt)]
|
||||||
#![feature(maybe_uninit_uninit_array)]
|
#![feature(maybe_uninit_uninit_array)]
|
||||||
|
#![feature(offset_of)]
|
||||||
|
#![feature(offset_of_enum)]
|
||||||
#![feature(ptr_alignment_type)]
|
#![feature(ptr_alignment_type)]
|
||||||
#![feature(ptr_metadata)]
|
#![feature(ptr_metadata)]
|
||||||
#![feature(set_ptr_value)]
|
#![feature(set_ptr_value)]
|
||||||
|
|
|
@ -780,7 +780,7 @@ impl<T> Option<T> {
|
||||||
// `None` case it's just padding).
|
// `None` case it's just padding).
|
||||||
unsafe {
|
unsafe {
|
||||||
slice::from_raw_parts(
|
slice::from_raw_parts(
|
||||||
crate::intrinsics::option_payload_ptr(crate::ptr::from_ref(self)),
|
(self as *const Self).byte_add(core::mem::offset_of!(Self, Some.0)).cast(),
|
||||||
usize::from(self.is_some()),
|
usize::from(self.is_some()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -836,8 +836,7 @@ impl<T> Option<T> {
|
||||||
// the `None` case it's just padding).
|
// the `None` case it's just padding).
|
||||||
unsafe {
|
unsafe {
|
||||||
slice::from_raw_parts_mut(
|
slice::from_raw_parts_mut(
|
||||||
crate::intrinsics::option_payload_ptr(crate::ptr::from_mut(self).cast_const())
|
(self as *mut Self).byte_add(core::mem::offset_of!(Self, Some.0)).cast(),
|
||||||
.cast_mut(),
|
|
||||||
usize::from(self.is_some()),
|
usize::from(self.is_some()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -568,3 +568,11 @@ fn zip_unzip_roundtrip() {
|
||||||
let a = z.unzip();
|
let a = z.unzip();
|
||||||
assert_eq!(a, (x, y));
|
assert_eq!(a, (x, y));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn as_slice() {
|
||||||
|
assert_eq!(Some(42).as_slice(), &[42]);
|
||||||
|
assert_eq!(Some(43).as_mut_slice(), &[43]);
|
||||||
|
assert_eq!(None::<i32>.as_slice(), &[]);
|
||||||
|
assert_eq!(None::<i32>.as_mut_slice(), &[]);
|
||||||
|
}
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
- // MIR for `option_payload` before LowerIntrinsics
|
|
||||||
+ // MIR for `option_payload` after LowerIntrinsics
|
|
||||||
|
|
||||||
fn option_payload(_1: &Option<usize>, _2: &Option<String>) -> () {
|
|
||||||
debug o => _1;
|
|
||||||
debug p => _2;
|
|
||||||
let mut _0: ();
|
|
||||||
let mut _4: *const std::option::Option<usize>;
|
|
||||||
let mut _6: *const std::option::Option<std::string::String>;
|
|
||||||
scope 1 {
|
|
||||||
let _3: *const usize;
|
|
||||||
scope 2 {
|
|
||||||
debug _x => _3;
|
|
||||||
let _5: *const std::string::String;
|
|
||||||
scope 3 {
|
|
||||||
debug _y => _5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bb0: {
|
|
||||||
StorageLive(_3);
|
|
||||||
StorageLive(_4);
|
|
||||||
_4 = &raw const (*_1);
|
|
||||||
- _3 = option_payload_ptr::<usize>(move _4) -> [return: bb1, unwind unreachable];
|
|
||||||
+ _3 = &raw const (((*_4) as Some).0: usize);
|
|
||||||
+ goto -> bb1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bb1: {
|
|
||||||
StorageDead(_4);
|
|
||||||
StorageLive(_5);
|
|
||||||
StorageLive(_6);
|
|
||||||
_6 = &raw const (*_2);
|
|
||||||
- _5 = option_payload_ptr::<String>(move _6) -> [return: bb2, unwind unreachable];
|
|
||||||
+ _5 = &raw const (((*_6) as Some).0: std::string::String);
|
|
||||||
+ goto -> bb2;
|
|
||||||
}
|
|
||||||
|
|
||||||
bb2: {
|
|
||||||
StorageDead(_6);
|
|
||||||
_0 = const ();
|
|
||||||
StorageDead(_5);
|
|
||||||
StorageDead(_3);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
- // MIR for `option_payload` before LowerIntrinsics
|
|
||||||
+ // MIR for `option_payload` after LowerIntrinsics
|
|
||||||
|
|
||||||
fn option_payload(_1: &Option<usize>, _2: &Option<String>) -> () {
|
|
||||||
debug o => _1;
|
|
||||||
debug p => _2;
|
|
||||||
let mut _0: ();
|
|
||||||
let mut _4: *const std::option::Option<usize>;
|
|
||||||
let mut _6: *const std::option::Option<std::string::String>;
|
|
||||||
scope 1 {
|
|
||||||
let _3: *const usize;
|
|
||||||
scope 2 {
|
|
||||||
debug _x => _3;
|
|
||||||
let _5: *const std::string::String;
|
|
||||||
scope 3 {
|
|
||||||
debug _y => _5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bb0: {
|
|
||||||
StorageLive(_3);
|
|
||||||
StorageLive(_4);
|
|
||||||
_4 = &raw const (*_1);
|
|
||||||
- _3 = option_payload_ptr::<usize>(move _4) -> [return: bb1, unwind unreachable];
|
|
||||||
+ _3 = &raw const (((*_4) as Some).0: usize);
|
|
||||||
+ goto -> bb1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bb1: {
|
|
||||||
StorageDead(_4);
|
|
||||||
StorageLive(_5);
|
|
||||||
StorageLive(_6);
|
|
||||||
_6 = &raw const (*_2);
|
|
||||||
- _5 = option_payload_ptr::<String>(move _6) -> [return: bb2, unwind unreachable];
|
|
||||||
+ _5 = &raw const (((*_6) as Some).0: std::string::String);
|
|
||||||
+ goto -> bb2;
|
|
||||||
}
|
|
||||||
|
|
||||||
bb2: {
|
|
||||||
StorageDead(_6);
|
|
||||||
_0 = const ();
|
|
||||||
StorageDead(_5);
|
|
||||||
StorageDead(_3);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -222,18 +222,6 @@ pub fn write_via_move_string(r: &mut String, v: String) {
|
||||||
|
|
||||||
pub enum Never {}
|
pub enum Never {}
|
||||||
|
|
||||||
// EMIT_MIR lower_intrinsics.option_payload.LowerIntrinsics.diff
|
|
||||||
pub fn option_payload(o: &Option<usize>, p: &Option<String>) {
|
|
||||||
// CHECK-LABEL: fn option_payload(
|
|
||||||
// CHECK: {{_.*}} = &raw const (((*{{_.*}}) as Some).0: usize);
|
|
||||||
// CHECK: {{_.*}} = &raw const (((*{{_.*}}) as Some).0: std::string::String);
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
let _x = core::intrinsics::option_payload_ptr(o);
|
|
||||||
let _y = core::intrinsics::option_payload_ptr(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// EMIT_MIR lower_intrinsics.ptr_offset.LowerIntrinsics.diff
|
// EMIT_MIR lower_intrinsics.ptr_offset.LowerIntrinsics.diff
|
||||||
pub unsafe fn ptr_offset(p: *const i32, d: isize) -> *const i32 {
|
pub unsafe fn ptr_offset(p: *const i32, d: isize) -> *const i32 {
|
||||||
// CHECK-LABEL: fn ptr_offset(
|
// CHECK-LABEL: fn ptr_offset(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue