Created
April 7, 2019 20:13
-
-
Save DutchGhost/b8c30364045dbf9e6bde7029bbf6708a to your computer and use it in GitHub Desktop.
Typed indexing
This file contains 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(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