-
-
Save rust-play/37b15966e1c1359cff23ba28af2424dd to your computer and use it in GitHub Desktop.
Code shared from the Rust Playground
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #![feature(fn_traits)] | |
| #![feature(min_specialization)] | |
| #![feature(unboxed_closures)] | |
| #![feature(rustc_attrs)] | |
| #![feature(associated_type_defaults)] | |
| #![feature(never_type)] | |
| #![feature(exhaustive_patterns)] | |
| use std::marker::PhantomData as Ph; | |
| pub use promise_same::{promise_cast, Trait as PromiseSame}; | |
| pub mod promise_same { | |
| use std::mem::ManuallyDrop as Md; | |
| #[rustc_unsafe_specialization_marker] | |
| pub trait Same<A> {} | |
| impl<A> Same<A> for A {} | |
| pub trait Trait<A>: Sized { | |
| fn promise_cast(self) -> A; | |
| } | |
| impl<A, B> Trait<A> for B { | |
| default fn promise_cast(self) -> A { | |
| unreachable!("promise_cast default unreachable: This should only be called if A and B are the same type via specialization.") | |
| } | |
| } | |
| pub union Tool<A, B> { | |
| a: Md<A>, | |
| b: Md<B>, | |
| } | |
| impl<A: Same<B>, B> Trait<A> for B { | |
| #[inline(always)] | |
| fn promise_cast(self) -> A { | |
| let tool = Tool::<A, Self> { b: Md::new(self) }; | |
| Md::into_inner(unsafe { tool.a }) | |
| } | |
| } | |
| #[inline(always)] | |
| pub fn promise_cast<Source, Target>(b: Source) -> Target | |
| where | |
| Source: Trait<Target>, | |
| { | |
| b.promise_cast() | |
| } | |
| } | |
| pub struct UnreachableFn<A, B, C, D, Imp>(Imp, Ph<(A, B, C, D)>); | |
| impl<A, B, C, D, Imp> FnOnce<(A,)> for UnreachableFn<A, B, C, D, Imp> | |
| where | |
| Imp: FnOnce(C) -> D, | |
| { | |
| type Output = B; | |
| extern "rust-call" fn call_once(self, args: (A,)) -> Self::Output { | |
| let arg_a = args.0; | |
| let arg_c = promise_cast::<A, C>(arg_a); | |
| let out_d = (self.0)(arg_c); | |
| promise_cast::<D, B>(out_d) | |
| } | |
| } | |
| impl<A, B, C, D, Imp: Clone> Clone for UnreachableFn<A, B, C, D, Imp> { | |
| fn clone(&self) -> Self { | |
| UnreachableFn(self.0.clone(), Ph) | |
| } | |
| } | |
| impl<A, B, C, D, Imp: Copy> Copy for UnreachableFn<A, B, C, D, Imp> {} | |
| use NGuard as Ng; | |
| pub trait NGuard: Sized + Copy { | |
| const DEFAULT: Self; | |
| type NGuard<A, U: Cursor, V: Cursor, W: Attic> = Ph<A>; | |
| type CGuard<A: Cursor>: Cursor = (); | |
| fn get<A, U: Cursor, V: Cursor, W: Attic>(self, _ng_val: Self::NGuard<A, U, V, W>) -> A { | |
| unreachable!("NGuard::get default unreachable!") | |
| } | |
| // Default impl returns promise_cast, which doesn't actually use _ng_ref. | |
| // The _ng_ref is for type system / specialization. | |
| fn _vu_cast<A, TargetAtt: Attic, U: Cursor, V: Cursor, WSourceAtt: Attic>( | |
| self, | |
| _ng_ref: &Self::NGuard<A, U, V, WSourceAtt>, | |
| ) -> impl FnOnce(SolOf<V, WSourceAtt>) -> SolOf<U, TargetAtt> { | |
| promise_cast::<_, _> | |
| } | |
| fn vu_cast<A, CurrentAtt: Attic, U: Cursor, V: Cursor>( | |
| self, | |
| _ng_ref: &Self::NGuard<A, U, V, CurrentAtt>, | |
| ) -> impl FnOnce(SolOf<V, CurrentAtt>) -> SolOf<U, CurrentAtt> { | |
| promise_cast::<_, _> | |
| } | |
| } | |
| impl NGuard for ! { | |
| const DEFAULT: Self = panic!("Attempted to get DEFAULT for '!' type NGuard"); | |
| } | |
| impl NGuard for () { | |
| const DEFAULT: Self = (); | |
| type NGuard<A, U: Cursor, V: Cursor, W: Attic> = A; | |
| type CGuard<A: Cursor> = A; | |
| fn get<A, U: Cursor, V: Cursor, W: Attic>(self, ng_val: Self::NGuard<A, U, V, W>) -> A { | |
| ng_val | |
| } | |
| // For `()` guard, _vu_cast and vu_cast will use the default `promise_cast` from the trait. | |
| } | |
| pub trait Clause { | |
| type Repr<Cur: Cursor, Att: Attic>: Eval<Cur, Att> = Gadt<Cur, Att>; | |
| } | |
| impl Clause for () {} | |
| pub type SolOf<A, B> = <A as Cursor>::Sol<B>; | |
| pub trait Cursor { | |
| type Sol<Att: Attic> = (); | |
| type _1: Cursor = (); | |
| type _2: Cursor = (); | |
| type _3: Cursor = (); | |
| type _V01<Att: Attic>: NGuard = Att::_V01; | |
| type _V02<Att: Attic>: NGuard = Att::_V02; | |
| type _V03<Att: Attic>: NGuard = Att::_V03; | |
| type _V04<Att: Attic>: NGuard = Att::_V04; | |
| } | |
| impl Cursor for () {} | |
| pub type ReprOf<A, B, C> = <<A as Attic>::Clause as Clause>::Repr<B, C>; | |
| pub trait Attic { | |
| type Clause: Clause = (); | |
| type Fun<Dom, Cod>: FnOnce(Dom) -> Cod = fn(Dom) -> Cod; | |
| type DomCur: Cursor = (); | |
| type FunAtt: Attic<Clause = Self::Clause> = (Self::Clause,); | |
| type _1: Attic = (); | |
| type _2: Attic = (); | |
| type _3: Attic = (); | |
| type _V01: NGuard = !; | |
| type _V02: NGuard = !; | |
| type _V03: NGuard = !; | |
| type _V04: NGuard = !; | |
| } | |
| impl Attic for () {} | |
| impl<Cls: Clause> Attic for (Cls,) { | |
| type Clause = Cls; | |
| } | |
| pub type _1Of<A> = <A as Attic>::_1; | |
| pub type _2Of<A> = <A as Attic>::_2; | |
| pub mod cursors { | |
| use super::*; | |
| pub struct Int; | |
| impl Cursor for Int { | |
| type Sol<Att: Attic> = isize; | |
| type _V02<Att: Attic> = !; | |
| } | |
| pub struct ReprFun<A, B>(Ph<(A, B)>); | |
| impl<A: Cursor, B: Cursor> Cursor for ReprFun<A, B> { | |
| type Sol<Att: Attic> = Att::Fun<ReprOf<Att, A, Att::_1>, ReprOf<Att, B, Att::_2>>; | |
| type _1 = A; | |
| type _2 = B; | |
| type _V01<Att: Attic> = !; | |
| type _V03<Att: Attic> = !; | |
| type _V04<Att: Attic> = !; | |
| } | |
| } | |
| pub mod attics { | |
| use super::*; | |
| pub struct Int; | |
| impl Attic for Int { | |
| type _V01 = (); | |
| } | |
| pub struct ReprFun<Cls, A, B, C, D, Imp>(Ph<(Cls, A, B, C, D, Imp)>); | |
| impl<Cls: Clause, A: Cursor, B: Cursor, C: Attic, D: Attic, Imp> Attic | |
| for ReprFun<Cls, A, B, C, D, Imp> | |
| where | |
| Imp: FnOnce(Cls::Repr<A, C>) -> Cls::Repr<B, D> + Clone + Copy, | |
| { | |
| type Clause = Cls; | |
| type Fun<Dom, Cod> = UnreachableFn<Dom, Cod, Cls::Repr<A, C>, Cls::Repr<B, D>, Imp>; | |
| type _1 = C; | |
| type _2 = D; | |
| type _V02 = (); | |
| } | |
| pub struct Apply<Cls, DomCur, Cur, FunAtt>(Ph<(Cls, DomCur, Cur, FunAtt)>); | |
| impl<Cls, DomCur, Cur, FunAtt> Attic for Apply<Cls, DomCur, Cur, FunAtt> | |
| where | |
| Cls: Clause, | |
| DomCur: Cursor, | |
| Cur: Cursor, | |
| FunAtt: Attic<Clause = Cls>, | |
| { | |
| type Clause = Cls; | |
| type DomCur = DomCur; | |
| type FunAtt = FunAtt; | |
| type _V03 = (); | |
| } | |
| pub struct Add<Cls, _1, _2>(Ph<(Cls, _1, _2)>); | |
| impl<Cls: Clause, _1: Attic, _2: Attic> Attic for Add<Cls, _1, _2> { | |
| type Clause = Cls; | |
| type _1 = _1; | |
| type _2 = _2; | |
| type _V04 = (); | |
| } | |
| } | |
| pub struct Gadt<Cur: Cursor, Att: Attic>( | |
| Enum<Cur::_V01<Att>, Cur::_V02<Att>, Cur::_V03<Att>, Cur::_V04<Att>, Cur, Att>, | |
| ); | |
| impl<Cur: Cursor, Att: Attic> Clone for Gadt<Cur, Att> | |
| where | |
| Enum<Cur::_V01<Att>, Cur::_V02<Att>, Cur::_V03<Att>, Cur::_V04<Att>, Cur, Att>: Clone, | |
| { | |
| fn clone(&self) -> Self { | |
| Gadt(self.0.clone()) | |
| } | |
| } | |
| impl<Cur: Cursor, Att: Attic> Copy for Gadt<Cur, Att> where | |
| Enum<Cur::_V01<Att>, Cur::_V02<Att>, Cur::_V03<Att>, Cur::_V04<Att>, Cur, Att>: Copy | |
| { | |
| } | |
| #[allow(clippy::type_complexity)] | |
| pub enum Enum<V01: Ng, V02: Ng, V03: Ng, V04: Ng, Cur: Cursor, Att: Attic> { | |
| __Ph__(std::convert::Infallible, Ph<(V01, V02, V03, V04, Cur, Att)>), | |
| IntConst(V01, V01::NGuard<isize, Cur, cursors::Int, Att>), | |
| Lambda( | |
| V02, | |
| V02::NGuard< | |
| Att::Fun<ReprOf<Att, Cur::_1, Att::_1>, ReprOf<Att, Cur::_2, Att::_2>>, | |
| Cur, | |
| cursors::ReprFun<Cur::_1, Cur::_2>, | |
| Att, | |
| >, | |
| ), | |
| Apply( | |
| V03, | |
| V03::NGuard< | |
| ( | |
| ReprOf<Att, cursors::ReprFun<Att::DomCur, <V03 as NGuard>::CGuard<Cur>>, Att::FunAtt>, | |
| ReprOf<Att, Att::DomCur, _1Of<Att::FunAtt>>, | |
| ), | |
| Cur, | |
| <V03 as NGuard>::CGuard<Cur>, | |
| _2Of<Att::FunAtt>, | |
| >, | |
| ), | |
| Add( | |
| V04, | |
| V04::NGuard< | |
| (ReprOf<Att, cursors::Int, Att::_1>, ReprOf<Att, cursors::Int, Att::_2>), | |
| Cur, | |
| cursors::Int, | |
| Att, | |
| >, | |
| ), | |
| } | |
| impl<V01: Ng, V02: Ng, V03: Ng, V04: Ng, Cur: Cursor, Att: Attic> Clone | |
| for Enum<V01, V02, V03, V04, Cur, Att> | |
| where | |
| V01::NGuard<isize, Cur, cursors::Int, Att>: Clone, | |
| V02::NGuard< | |
| Att::Fun<ReprOf<Att, Cur::_1, Att::_1>, ReprOf<Att, Cur::_2, Att::_2>>, | |
| Cur, | |
| cursors::ReprFun<Cur::_1, Cur::_2>, | |
| Att, | |
| >: Clone, | |
| V03::NGuard< | |
| ( | |
| ReprOf<Att, cursors::ReprFun<Att::DomCur, <V03 as NGuard>::CGuard<Cur>>, Att::FunAtt>, | |
| ReprOf<Att, Att::DomCur, _1Of<Att::FunAtt>>, | |
| ), | |
| Cur, | |
| <V03 as NGuard>::CGuard<Cur>, | |
| _2Of<Att::FunAtt>, | |
| >: Clone, | |
| V04::NGuard<(ReprOf<Att, cursors::Int, Att::_1>, ReprOf<Att, cursors::Int, Att::_2>), Cur, cursors::Int, Att>: | |
| Clone, | |
| { | |
| fn clone(&self) -> Self { | |
| match self { | |
| Enum::__Ph__(val, ph) => Enum::__Ph__(*val, *ph), | |
| Enum::IntConst(guard, val) => Enum::IntConst(*guard, val.clone()), | |
| Enum::Lambda(guard, val) => Enum::Lambda(*guard, val.clone()), | |
| Enum::Apply(guard, val) => Enum::Apply(*guard, val.clone()), | |
| Enum::Add(guard, val) => Enum::Add(*guard, val.clone()), | |
| } | |
| } | |
| } | |
| impl<V01: Ng, V02: Ng, V03: Ng, V04: Ng, Cur: Cursor, Att: Attic> Copy | |
| for Enum<V01, V02, V03, V04, Cur, Att> | |
| where | |
| V01::NGuard<isize, Cur, cursors::Int, Att>: Copy, | |
| V02::NGuard< | |
| Att::Fun<ReprOf<Att, Cur::_1, Att::_1>, ReprOf<Att, Cur::_2, Att::_2>>, | |
| Cur, | |
| cursors::ReprFun<Cur::_1, Cur::_2>, | |
| Att, | |
| >: Copy, | |
| V03::NGuard< | |
| ( | |
| ReprOf<Att, cursors::ReprFun<Att::DomCur, <V03 as NGuard>::CGuard<Cur>>, Att::FunAtt>, | |
| ReprOf<Att, Att::DomCur, _1Of<Att::FunAtt>>, | |
| ), | |
| Cur, | |
| <V03 as NGuard>::CGuard<Cur>, | |
| _2Of<Att::FunAtt>, | |
| >: Copy, | |
| V04::NGuard<(ReprOf<Att, cursors::Int, Att::_1>, ReprOf<Att, cursors::Int, Att::_2>), Cur, cursors::Int, Att>: | |
| Copy, | |
| { | |
| } | |
| fn int_const(a: isize) -> Gadt<cursors::Int, attics::Int> { | |
| Gadt(Enum::IntConst((), a)) | |
| } | |
| fn lambda<Cls, A, B, C, D, Imp>( | |
| imp: Imp, | |
| ) -> Gadt<cursors::ReprFun<A, B>, attics::ReprFun<Cls, A, B, C, D, Imp>> | |
| where | |
| Cls: Clause, | |
| A: Cursor, | |
| B: Cursor, | |
| C: Attic, | |
| D: Attic, | |
| Imp: FnOnce(Cls::Repr<A, C>) -> Cls::Repr<B, D> + Copy + Clone, | |
| { | |
| Gadt(Enum::Lambda((), UnreachableFn(imp, Ph))) | |
| } | |
| fn apply<Cls, DomCur, Cur, FunAtt>( | |
| func_repr: Cls::Repr<cursors::ReprFun<DomCur, Cur>, FunAtt>, | |
| arg_repr: Cls::Repr<DomCur, _1Of<FunAtt>>, | |
| ) -> Gadt<Cur, attics::Apply<Cls, DomCur, Cur, FunAtt>> | |
| where | |
| Cls: Clause, | |
| DomCur: Cursor, | |
| Cur: Cursor<_V03<attics::Apply<Cls, DomCur, Cur, FunAtt>> = ()>, | |
| FunAtt: Attic<Clause = Cls>, | |
| { | |
| Gadt(Enum::Apply((), (func_repr, arg_repr))) | |
| } | |
| fn add<Cls: Clause, Att1: Attic, Att2: Attic>( | |
| lhs: Cls::Repr<cursors::Int, Att1>, | |
| rhs: Cls::Repr<cursors::Int, Att2>, | |
| ) -> Gadt<cursors::Int, attics::Add<Cls, Att1, Att2>> { | |
| Gadt(Enum::Add((), (lhs, rhs))) | |
| } | |
| pub trait Eval<Cur: Cursor, Att: Attic> { | |
| fn eval(self) -> SolOf<Cur, Att>; | |
| } | |
| impl<Cur: Cursor, Att: Attic> Eval<Cur, Att> for Gadt<Cur, Att> { | |
| #[inline(always)] | |
| fn eval(self) -> SolOf<Cur, Att> { | |
| match self.0 { | |
| Enum::IntConst(guard_v01, guarded_val) => { | |
| let val_after_get = guard_v01.get(guarded_val); | |
| promise_cast::<isize, SolOf<Cur, Att>>(val_after_get) | |
| } | |
| Enum::Lambda(guard_v02, guarded_fn_wrapper) => { | |
| let val_after_get = guard_v02.get(guarded_fn_wrapper); | |
| promise_cast::<Att::Fun<ReprOf<Att, Cur::_1, Att::_1>, ReprOf<Att, Cur::_2, Att::_2>>, SolOf<Cur, Att>>(val_after_get) | |
| } | |
| Enum::Apply(guard_v03, guarded_apply_args) => { | |
| let (func_gadt, arg_gadt) = guard_v03.get(guarded_apply_args); | |
| let evaluated_func = func_gadt.eval(); | |
| let intermediate_result_gadt = evaluated_func(arg_gadt); | |
| let final_val_to_cast = intermediate_result_gadt.eval(); | |
| promise_cast::< | |
| <<<Cur as Cursor>::_V03<Att> as NGuard>::CGuard<Cur> as Cursor>::Sol<<<Att as Attic>::FunAtt as Attic>::_2>, // Corrected: Added 'as Attic' | |
| SolOf<Cur, Att> | |
| >(final_val_to_cast) | |
| } | |
| Enum::Add(guard_v04, guarded_add_args) => { | |
| let (lhs_gadt, rhs_gadt) = guard_v04.get(guarded_add_args); | |
| let lhs_val = lhs_gadt.eval(); | |
| let rhs_val = rhs_gadt.eval(); | |
| let result_val = lhs_val + rhs_val; | |
| promise_cast::<isize, SolOf<Cur, Att>>(result_val) | |
| } | |
| } | |
| } | |
| } | |
| type BasicClause = (); | |
| type IntAtt = attics::Int; | |
| type CAttic = attics::Add<BasicClause, IntAtt, IntAtt>; | |
| #[derive(Clone, Copy)] | |
| struct MyClosure1 { u: isize, v: isize, w: isize } | |
| impl FnOnce<(Gadt<cursors::Int, CAttic>,)> for MyClosure1 { | |
| type Output = Gadt<cursors::Int, attics::Add<BasicClause, IntAtt, CAttic>>; | |
| extern "rust-call" fn call_once(self, args: (Gadt<cursors::Int, CAttic>,)) -> Self::Output { | |
| let x = args.0; | |
| let a = int_const(self.u * 2 + self.v * 3 + self.w * 5); | |
| add::<BasicClause, _, _>(a, x) | |
| } | |
| } | |
| type DOutputAttic = attics::Add<BasicClause, IntAtt, CAttic>; | |
| type Lambda1Att = attics::ReprFun<BasicClause, cursors::Int, cursors::Int, CAttic, DOutputAttic, MyClosure1>; | |
| type EAttic = attics::Apply<BasicClause, cursors::Int, cursors::Int, Lambda1Att>; | |
| #[derive(Clone, Copy)] | |
| struct MyClosure2 { u: isize, v: isize, w: isize, c: Gadt<cursors::Int, CAttic> } | |
| impl FnOnce<(Gadt<cursors::Int, EAttic>,)> for MyClosure2 { | |
| type Output = Gadt<cursors::Int, attics::Add<BasicClause, attics::Add<BasicClause, IntAtt, EAttic>, CAttic>>; | |
| extern "rust-call" fn call_once(self, args: (Gadt<cursors::Int, EAttic>,)) -> Self::Output { | |
| let x = args.0; | |
| let a = int_const(self.u * 3 + self.v * 5 + self.w * 13); | |
| add::<BasicClause, _, _>(add::<BasicClause, _, _>(a, x), self.c) | |
| } | |
| } | |
| type FOutputAttic = attics::Add<BasicClause, attics::Add<BasicClause, IntAtt, EAttic>, CAttic>; | |
| type Lambda2Att = attics::ReprFun<BasicClause, cursors::Int, cursors::Int, EAttic, FOutputAttic, MyClosure2>; | |
| type InterFunCur = cursors::ReprFun<cursors::Int, cursors::Int>; | |
| type InterFunAtt = Lambda2Att; | |
| #[derive(Clone, Copy)] | |
| struct MyClosureJ { e: Gadt<cursors::Int, EAttic> } | |
| impl FnOnce<(Gadt<InterFunCur, InterFunAtt>,)> for MyClosureJ { | |
| type Output = Gadt<cursors::Int, attics::Apply<BasicClause, cursors::Int, cursors::Int, InterFunAtt>>; | |
| extern "rust-call" fn call_once(self, args: (Gadt<InterFunCur, InterFunAtt>,)) -> Self::Output { | |
| let x_fn_gadt = args.0; | |
| apply::<BasicClause, cursors::Int, cursors::Int, InterFunAtt>(x_fn_gadt, self.e) | |
| } | |
| } | |
| fn expr(u: isize, v: isize, w: isize) -> Gadt<cursors::Int, impl Attic> { | |
| let a = int_const(u); | |
| let b = int_const(v); | |
| let c = add::<(), _, _>(a, b); | |
| let closure_d = MyClosure1 { u, v, w }; | |
| let d = lambda::<(), _, _, _, _, _>(closure_d); | |
| let e = apply::<(), _, _, _>(d, c); | |
| let closure_f = MyClosure2 { u, v, w, c }; | |
| let f = lambda::<(), _, _, _, _, _>(closure_f); | |
| let closure_j = MyClosureJ { e }; | |
| let j = lambda::<(), _, _, _, _, _>(closure_j); | |
| apply::<(), _, _, _>(j, f) | |
| } | |
| #[inline(never)] | |
| pub extern "C" fn eval_expr(u: isize, v: isize, w: isize) -> isize { | |
| expr(u, v, w).eval() | |
| } | |
| fn main() { | |
| use rand::Rng; | |
| let mut rng = rand::rng(); | |
| let u: isize = rng.random::<i64>() as isize; | |
| let v: isize = rng.random::<i64>() as isize; | |
| let w: isize = rng.random::<i64>() as isize; | |
| let r = eval_expr(u, v, w); | |
| let expected_r = u * 7 + v * 10 + w * 18; | |
| assert_eq!(expected_r, r, "Calculation mismatch: u={}, v={}, w={}", u, v, w); | |
| println!("LAMBDA EXPR EVAL (u={}, v={}, w={}) = {} (expected {})", u, v, w, r, expected_r); | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment