small refactor of InterpResult

- don't need type alias to default type argument
- `Residual` impl allows to use more std APIs (like `<[T; N]>::try_map`)
This commit is contained in:
Waffle Lapkin
2025-08-04 09:41:08 +02:00
parent 07b7dc90ee
commit e3ed3e0f1c
2 changed files with 22 additions and 20 deletions

View File

@@ -57,6 +57,7 @@
#![feature(sized_hierarchy)]
#![feature(try_blocks)]
#![feature(try_trait_v2)]
#![feature(try_trait_v2_residual)]
#![feature(try_trait_v2_yeet)]
#![feature(type_alias_impl_trait)]
#![feature(yeet_expr)]

View File

@@ -793,36 +793,37 @@ impl Drop for Guard {
/// We also make things panic if this type is ever implicitly dropped.
#[derive(Debug)]
#[must_use]
pub struct InterpResult_<'tcx, T> {
pub struct InterpResult<'tcx, T = ()> {
res: Result<T, InterpErrorInfo<'tcx>>,
guard: Guard,
}
// Type alias to be able to set a default type argument.
pub type InterpResult<'tcx, T = ()> = InterpResult_<'tcx, T>;
impl<'tcx, T> ops::Try for InterpResult_<'tcx, T> {
impl<'tcx, T> ops::Try for InterpResult<'tcx, T> {
type Output = T;
type Residual = InterpResult_<'tcx, convert::Infallible>;
type Residual = InterpResult<'tcx, convert::Infallible>;
#[inline]
fn from_output(output: Self::Output) -> Self {
InterpResult_::new(Ok(output))
InterpResult::new(Ok(output))
}
#[inline]
fn branch(self) -> ops::ControlFlow<Self::Residual, Self::Output> {
match self.disarm() {
Ok(v) => ops::ControlFlow::Continue(v),
Err(e) => ops::ControlFlow::Break(InterpResult_::new(Err(e))),
Err(e) => ops::ControlFlow::Break(InterpResult::new(Err(e))),
}
}
}
impl<'tcx, T> ops::FromResidual for InterpResult_<'tcx, T> {
impl<'tcx, T> ops::Residual<T> for InterpResult<'tcx, convert::Infallible> {
type TryType = InterpResult<'tcx, T>;
}
impl<'tcx, T> ops::FromResidual for InterpResult<'tcx, T> {
#[inline]
#[track_caller]
fn from_residual(residual: InterpResult_<'tcx, convert::Infallible>) -> Self {
fn from_residual(residual: InterpResult<'tcx, convert::Infallible>) -> Self {
match residual.disarm() {
Err(e) => Self::new(Err(e)),
}
@@ -830,7 +831,7 @@ impl<'tcx, T> ops::FromResidual for InterpResult_<'tcx, T> {
}
// Allow `yeet`ing `InterpError` in functions returning `InterpResult_`.
impl<'tcx, T> ops::FromResidual<ops::Yeet<InterpErrorKind<'tcx>>> for InterpResult_<'tcx, T> {
impl<'tcx, T> ops::FromResidual<ops::Yeet<InterpErrorKind<'tcx>>> for InterpResult<'tcx, T> {
#[inline]
fn from_residual(ops::Yeet(e): ops::Yeet<InterpErrorKind<'tcx>>) -> Self {
Self::new(Err(e.into()))
@@ -840,7 +841,7 @@ impl<'tcx, T> ops::FromResidual<ops::Yeet<InterpErrorKind<'tcx>>> for InterpResu
// Allow `?` on `Result<_, InterpError>` in functions returning `InterpResult_`.
// This is useful e.g. for `option.ok_or_else(|| err_ub!(...))`.
impl<'tcx, T, E: Into<InterpErrorInfo<'tcx>>> ops::FromResidual<Result<convert::Infallible, E>>
for InterpResult_<'tcx, T>
for InterpResult<'tcx, T>
{
#[inline]
fn from_residual(residual: Result<convert::Infallible, E>) -> Self {
@@ -863,7 +864,7 @@ impl<'tcx, T, V: FromIterator<T>> FromIterator<InterpResult<'tcx, T>> for Interp
}
}
impl<'tcx, T> InterpResult_<'tcx, T> {
impl<'tcx, T> InterpResult<'tcx, T> {
#[inline(always)]
fn new(res: Result<T, InterpErrorInfo<'tcx>>) -> Self {
Self { res, guard: Guard }
@@ -890,7 +891,7 @@ impl<'tcx, T> InterpResult_<'tcx, T> {
#[inline]
pub fn map<U>(self, f: impl FnOnce(T) -> U) -> InterpResult<'tcx, U> {
InterpResult_::new(self.disarm().map(f))
InterpResult::new(self.disarm().map(f))
}
#[inline]
@@ -898,7 +899,7 @@ impl<'tcx, T> InterpResult_<'tcx, T> {
self,
f: impl FnOnce(InterpErrorInfo<'tcx>) -> InterpErrorInfo<'tcx>,
) -> InterpResult<'tcx, T> {
InterpResult_::new(self.disarm().map_err(f))
InterpResult::new(self.disarm().map_err(f))
}
#[inline]
@@ -906,7 +907,7 @@ impl<'tcx, T> InterpResult_<'tcx, T> {
self,
f: impl FnOnce(InterpErrorKind<'tcx>) -> InterpErrorKind<'tcx>,
) -> InterpResult<'tcx, T> {
InterpResult_::new(self.disarm().map_err(|mut e| {
InterpResult::new(self.disarm().map_err(|mut e| {
e.0.kind = f(e.0.kind);
e
}))
@@ -914,7 +915,7 @@ impl<'tcx, T> InterpResult_<'tcx, T> {
#[inline]
pub fn inspect_err_kind(self, f: impl FnOnce(&InterpErrorKind<'tcx>)) -> InterpResult<'tcx, T> {
InterpResult_::new(self.disarm().inspect_err(|e| f(&e.0.kind)))
InterpResult::new(self.disarm().inspect_err(|e| f(&e.0.kind)))
}
#[inline]
@@ -937,7 +938,7 @@ impl<'tcx, T> InterpResult_<'tcx, T> {
#[inline]
pub fn and_then<U>(self, f: impl FnOnce(T) -> InterpResult<'tcx, U>) -> InterpResult<'tcx, U> {
InterpResult_::new(self.disarm().and_then(|t| f(t).disarm()))
InterpResult::new(self.disarm().and_then(|t| f(t).disarm()))
}
/// Returns success if both `self` and `other` succeed, while ensuring we don't
@@ -952,7 +953,7 @@ impl<'tcx, T> InterpResult_<'tcx, T> {
// Discard the other error.
drop(other.disarm());
// Return `self`.
InterpResult_::new(Err(e))
InterpResult::new(Err(e))
}
}
}
@@ -960,5 +961,5 @@ impl<'tcx, T> InterpResult_<'tcx, T> {
#[inline(always)]
pub fn interp_ok<'tcx, T>(x: T) -> InterpResult<'tcx, T> {
InterpResult_::new(Ok(x))
InterpResult::new(Ok(x))
}