Skip to content

Instantly share code, notes, and snippets.

@DutchGhost
Created April 7, 2019 20:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DutchGhost/b8c30364045dbf9e6bde7029bbf6708a to your computer and use it in GitHub Desktop.
Save DutchGhost/b8c30364045dbf9e6bde7029bbf6708a to your computer and use it in GitHub Desktop.
Typed indexing
#![feature(nll)]
use std::marker::PhantomData;
// Can't make it longer or shorter
#[derive(Copy, Clone)]
struct Invariant<'id>(PhantomData<*mut &'id ()>);
impl<'id> Invariant<'id> {
pub const fn new() -> Self {
Self(PhantomData)
}
}
pub trait Relation<'r> {
type Output: for<'x> Relation<'x>;
const THIS: Self;
const ITEM: Self::Output;
}
impl<'id, 'r> Relation<'r> for Invariant<'id> {
type Output = Invariant<'r>;
const THIS: Self = Invariant::new();
const ITEM: Self::Output = Invariant::new();
}
struct Index<V> {
index: usize,
id: PhantomData<V>,
}
impl <V> Copy for Index<V> {
}
impl <V> Clone for Index<V> {
fn clone(&self) -> Self {
*self
}
}
impl<V> Index<V> {
const fn new(index: usize) -> Self {
Self {
index,
id: PhantomData,
}
}
}
struct Container<'a, T, V> {
slice: &'a [T],
v: V,
}
impl<'a, T, V> Container<'a, T, V>
where
for<'r> V: Relation<'r>,
{
fn splice<'s>(
&'s self,
) -> (
Container<'s, T, impl for<'r> Relation<'r>>,
Container<'s, T, impl for<'r> Relation<'r>>,
) {
let len = self.slice.len();
let (lhs, rhs) = self.slice.split_at(len / 2);
(
Container {
slice: lhs,
v: <V as Relation<'_>>::ITEM,
},
Container {
slice: rhs,
v: <V as Relation<'_>>::ITEM,
},
)
}
fn index(&self, index: usize) -> Index<V> {
Index::new(index)
}
fn get(&self, index: Index<V>) -> &'a T {
&self.slice[index.index]
}
}
fn region<'a, T: 'a, F, Out>(slice: &'a [T], f: F) -> Out
where
for<'id> F: FnOnce(Container<'a, T, Invariant<'id>>) -> Out,
{
f(Container {
slice,
v: Invariant::new(),
})
}
fn main() {
let mut v = [1, 2, 3, 4, 5, 6, 7];
let x = region(&v, |slice| {
let idx = slice.index(0);
slice.get(idx)
});
println!("{:?}", x);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment