extern crate num;
extern crate num_iter;
pub mod arith;
pub mod ix;
use std::borrow::Borrow;
use std::cell::Cell;
use std::marker::PhantomData;
use std::ops::Deref;
use std::{fmt, mem};
pub type PhantomInvariantData<T> = PhantomData<*mut T>;
pub type PhantomInvariantLifetime<'a> = PhantomData<Cell<&'a mut ()>>;
pub trait IntoInner: Deref {
fn into_inner(self) -> Self::Target;
}
pub fn imprint<F, R, T>(value: T, callback: F) -> R
where F: for<'x> FnOnce(Val<'x, T>) -> R {
callback(unsafe { Val::known(value) })
}
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct Val<'x, T> {
tag: PhantomInvariantLifetime<'x>,
inner: T,
}
impl<'x, T> Val<'x, T> {
pub unsafe fn known(value: T) -> Val<'x, T> {
Val { tag: PhantomData, inner: value }
}
}
impl<'x, T: PartialEq> Val<'x, T> {
pub fn eq<'y>(&self, other: &Val<'y, T>)
-> Option<TyEq<Self, Val<'y, T>>> {
arith::partial_equal(self, other).map(|eq| eq.into_ty_eq())
}
}
impl<'x, T: fmt::Debug> fmt::Debug for Val<'x, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("Val(")?;
(*self).fmt(f)?;
f.write_str(")")
}
}
impl<T: Default> Default for Val<'static, T> {
fn default() -> Self {
Val { tag: PhantomData, inner: Default::default() }
}
}
impl<'x, T> AsRef<T> for Val<'x, T> {
fn as_ref(&self) -> &T {
&**self
}
}
impl<'x, T> Borrow<T> for Val<'x, T> {
fn borrow(&self) -> &T {
&**self
}
}
impl<'x, T> Deref for Val<'x, T> {
type Target = T;
fn deref(&self) -> &T {
&self.inner
}
}
impl<'x, T> IntoInner for Val<'x, T> {
fn into_inner(self) -> Self::Target {
self.inner
}
}
pub struct TyEq<T: ?Sized, U: ?Sized>(
PhantomInvariantData<T>,
PhantomInvariantData<U>,
);
impl<T: ?Sized> TyEq<T, T> {
pub fn refl() -> Self {
TyEq(PhantomData, PhantomData)
}
}
impl<T: ?Sized, U: ?Sized> TyEq<T, U> {
pub fn apply<F: ?Sized>(self, value: <F as TyFn<T>>::Output)
-> <F as TyFn<U>>::Output
where F: TyFn<T> + TyFn<U>,
<F as TyFn<T>>::Output: Sized,
<F as TyFn<U>>::Output: Sized {
debug_assert_eq!(mem::size_of::<<F as TyFn<T>>::Output>(),
mem::size_of::<<F as TyFn<U>>::Output>());
let result = unsafe { mem::transmute_copy(&value) };
mem::forget(value);
result
}
pub fn sym(self) -> TyEq<U, T> {
struct F<T: ?Sized>(PhantomInvariantData<T>);
impl<T: ?Sized, U: ?Sized> TyFn<T> for F<U> {
type Output = TyEq<T, U>;
}
self.apply::<F<T>>(TyEq::refl())
}
pub fn trans<R: ?Sized>(self, other: TyEq<U, R>) -> TyEq<T, R> {
struct F<T: ?Sized>(PhantomInvariantData<T>);
impl<T: ?Sized, U: ?Sized> TyFn<T> for F<U> {
type Output = TyEq<U, T>;
}
other.apply::<F<T>>(self)
}
}
impl<T, U> TyEq<T, U> {
pub fn cast(self, value: T) -> U {
self.apply::<IdF>(value)
}
}
#[cfg_attr(feature = "cargo-clippy", allow(expl_impl_clone_on_copy))]
impl<T: ?Sized, U: ?Sized> Clone for TyEq<T, U> {
fn clone(&self) -> Self { *self }
}
impl<T: ?Sized, U: ?Sized> Copy for TyEq<T, U> { }
impl<T: ?Sized, U: ?Sized> fmt::Debug for TyEq<T, U> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("TyEq")
}
}
pub trait TyFn<F: ?Sized> {
type Output: ?Sized;
}
pub struct IdF(());
impl<T: ?Sized> TyFn<T> for IdF {
type Output = T;
}
pub unsafe trait TyFnL<'a> { type Output; }
pub struct ValF<T>(PhantomInvariantData<T>);
unsafe impl<'a, T> TyFnL<'a> for ValF<T> { type Output = Val<'a, T>; }
pub struct Exists<F: for<'a> TyFnL<'a>>(<F as TyFnL<'static>>::Output);
impl<F: for<'a> TyFnL<'a>> Exists<F> {
pub fn new<'a>(value: <F as TyFnL<'a>>::Output) -> Exists<F> {
use std::{mem, ptr};
let result = unsafe {
ptr::read(&value
as *const <F as TyFnL<'a>>::Output
as *const ()
as *const <F as TyFnL<'static>>::Output)
};
mem::forget(value);
Exists(result)
}
pub fn with<U, R>(self, callback: U) -> R
where U: for<'a> FnOnce(<F as TyFnL<'a>>::Output) -> R {
callback(self.0)
}
pub fn with_ref<'b, U, R>(&'b self, callback: U) -> R
where U: for<'a> FnOnce(&'b <F as TyFnL<'a>>::Output) -> R {
callback(&self.0)
}
pub fn with_ref_mut<'b, U, R>(&'b mut self, callback: U) -> R
where U: for<'a> FnOnce(&'b mut <F as TyFnL<'a>>::Output) -> R {
callback(&mut self.0)
}
}
impl<F: for<'a> TyFnL<'a>> Clone for Exists<F>
where for<'a> <F as TyFnL<'a>>::Output: Clone {
fn clone(&self) -> Self {
self.with_ref(|x| Exists::new(x.clone()))
}
}
impl<F: for<'a> TyFnL<'a>> Copy for Exists<F>
where for<'a> <F as TyFnL<'a>>::Output: Copy { }
impl<F: for<'a> TyFnL<'a>> fmt::Debug for Exists<F>
where for<'a> <F as TyFnL<'a>>::Output: fmt::Debug {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("Exists(")?;
self.with_ref(|x| x.fmt(f))?;
f.write_str(")")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
imprint(42, |m| {
assert_eq!(m.into_inner(), 42);
let n = imprint(42, |n| {
assert_eq!(n.into_inner(), 42);
m.eq(&n).unwrap().sym().cast(n)
});
assert_eq!(m, n);
imprint(0, |z| {
assert_eq!(z.into_inner(), 0);
assert!(m.eq(&z).is_none());
})
})
}
#[test]
#[allow(unused)]
fn exists() {
let x = imprint(0, |x| Exists::<ValF<i64>>::new(x));
}
}