Skip to main content

type_eq

Function type_eq 

Source
pub const fn type_eq<Lhs, Rhs>(_: Lhs, _: Rhs) -> TypeCmp<Lhs, Rhs>
where Lhs: IsTStr, Rhs: IsTStr,
Expand description

Compares two IsTStrs for equality, returning a proof of the (in)equality of the arguments.

This is a non-associated function for const compatibility, the (non-const) trait method equivalent of this is IsTStr::type_eq

ยงExample

use tstr::{IsTStr, TStr, TS, ts};
use tstr::typewit::TypeCmp;


assert_eq!(is_right_guess(Guess(ts!(foo))), None);
assert_eq!(is_right_guess(Guess(ts!(bar))), None);
assert_eq!(is_right_guess(Guess(ts!(world))), None);

assert!(is_right_guess(Guess(ts!(hello))).is_some_and(|x| x.0 == "hello"));

#[derive(Debug, PartialEq, Eq)]
struct Guess<S: IsTStr>(S);

const fn is_right_guess<S: IsTStr>(guess: Guess<S>) -> Option<Guess<impl IsTStr>> {
    match typecast_guess(guess) {
        Ok(ret @ Guess::<TS!(hello)>{..}) => Some(ret),
        Err(_) => None,
    }
}

/// Coerces `Guess<A>` to `Guess<B>` if `A == B`, returns `Err(guess)` if `A != B`.
const fn typecast_guess<A, B>(guess: Guess<A>) -> Result<Guess<B>, Guess<A>>
where
    A: IsTStr,
    B: IsTStr,
{
    tstr::typewit::type_fn!{
        // type-level function from `S` to `Guess<S>`
        struct GuessFn;
        impl<S: IsTStr> S => Guess<S>
    }
     
    match tstr::type_eq(A::VAL, B::VAL) {
        TypeCmp::Eq(te) => Ok(
            // te is a `TypeEq<A, B>`, a value-level proof that both args are the same type.
            te               
            .map(GuessFn)    // : TypeEq<Guess<A>, Guess<B>>
            .to_right(guess) // : Guess<B>
        ),
        TypeCmp::Ne(_) => Err(guess),
    }
}