Created
July 27, 2024 10:11
-
-
Save ClarkeRemy/b2eb208726c25eedb9a566f090ead28b to your computer and use it in GitHub Desktop.
Rust with Holes
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
use std::marker::PhantomData; | |
pub fn main() { | |
let mut s = Splitter::new(); | |
s.list[0] = 1; | |
s.id = 5; | |
println!("Splitter {{list : [{},{}], id : {} }}", s.list[0], s.list[1], s.id); | |
let (s, mut list) = s.mut_list(); | |
let (s, mut id) = s.mut_id(); | |
*id += 13; | |
list[1] = 25; | |
let s = s.unborrow_id(id); | |
let s = s.unborrow_list(list); | |
println!("Splitter {{list : [{},{}], id : {} }}", s.list[0], s.list[1], s.id); | |
} | |
type ID = usize; | |
type LIST = [u8;2]; | |
struct Splitter<List = LIST, Id = ID> {list : List, id : Id} | |
impl Splitter{ | |
fn new() -> Self { | |
Self { list: Default::default(), id: 0 } | |
} | |
} | |
impl<List,Id> Splitter<List,Id> { | |
fn mut_list(self)->(Splitter<(), Id>, Mutator<List, Splitter<(), Id>>) { | |
(Splitter {list : (), id : self.id}, Mutator{ mutable: self.list, src: PhantomData }) | |
} | |
fn mut_id(self)->(Splitter<List, ()>, Mutator<Id, Splitter<List, ()>>) { | |
(Splitter {list : self.list, id : ()}, Mutator{ mutable: self.id, src: PhantomData }) | |
} | |
} | |
impl<List> Splitter<List, ()> { | |
fn unborrow_id(self, id_mut : Mutator<ID, Self>) -> Splitter<List, ID> { | |
let id = unsafe{ id_mut.consume() }; | |
Splitter { list: self.list, id } | |
} | |
} | |
impl<Id> Splitter<(), Id> { | |
fn unborrow_list(self, id_mut : Mutator<LIST, Self>) -> Splitter<LIST, Id> { | |
let list = unsafe{ id_mut.consume() }; | |
Splitter { list, id: self.id } | |
} | |
} | |
#[must_use] | |
struct Mutator<M,Src> { | |
mutable : M, | |
src : PhantomData<Src> | |
} | |
impl<M,Src> Mutator<M,Src> { | |
unsafe fn consume(self) -> M { | |
let m = core::ptr::read(&self.mutable); | |
let _ = core::mem::ManuallyDrop::new(self); | |
m | |
} | |
} | |
impl<M,Src> Drop for Mutator<M,Src> { | |
fn drop(&mut self) { | |
core::panic!() | |
} | |
} | |
impl<M,Src> core::ops::Deref for Mutator<M,Src> { | |
type Target = M; | |
fn deref(&self) -> &Self::Target { | |
&self.mutable | |
} | |
} | |
impl<M,Src> core::ops::DerefMut for Mutator<M,Src> { | |
fn deref_mut(&mut self) -> &mut Self::Target { | |
&mut self.mutable | |
} | |
} |
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
use std::marker::PhantomData; | |
pub fn main() { | |
let mut s = Splitter::new(); | |
s.list[0]=1; | |
s.id = 5; | |
println!("Splitter {{list : [{},{}], id : {} }}", s.list[0], s.list[1], s.id); | |
let (s, mut list) = s.mut_list(); | |
let (s, mut id) = s.mut_id(); | |
*id += 13; | |
list[1]=25; | |
let s = s.unborrow_id(id); | |
let s = s.unborrow_list(list); | |
println!("Splitter {{list : [{},{}], id : {} }}", s.list[0], s.list[1], s.id); | |
} | |
type ID = usize; | |
type LIST = [u8;2]; | |
#[derive(Debug)] | |
struct Z; | |
#[derive(Debug)] | |
struct S<T : Nat>(T); | |
mod sealed { | |
pub trait Nat { const VAL : Self; } | |
pub trait Succ : Nat { type S : Nat; } | |
pub trait Pred : Nat{ type P : Nat;} | |
} | |
use sealed::*; | |
impl Nat for Z { const VAL : Self = Z;} | |
impl<T : Nat> Nat for S<T>{ const VAL : Self = S(T::VAL); } | |
impl Succ for Z { type S = S<Z>; } | |
impl<T : Nat> Succ for S<T> { type S = S<Self>; } | |
impl<T : Nat> Pred for S<T> { type P = T; } | |
#[derive(Clone, Debug)] | |
struct Splitter<List = LIST, Id = ID, Scope : Nat = Z> {list : List, id : Id, _scope : Scope} | |
impl Splitter{ | |
fn new() -> Self { | |
Self { list: [0;2], id: 0 , _scope : Z} | |
} | |
} | |
impl<List,Id,Scope : Succ> Splitter<List,Id, Scope> { | |
fn mut_list(self)->(Splitter<Scope::S, Id, Scope::S>, Mutator<List, Splitter<Scope::S, Id, Scope::S>>) { | |
( Splitter {list : Scope::S::VAL, id : self.id , _scope : Scope::S::VAL}, | |
Mutator { mutable: self.list, src: PhantomData } | |
) | |
} | |
fn mut_id(self)->(Splitter<List, Scope::S, Scope::S>, Mutator<Id, Splitter<List, Scope::S, Scope::S>>) { | |
( Splitter {list : self.list, id : Scope::S::VAL, _scope : Scope::S::VAL}, | |
Mutator{ mutable: self.id, src: PhantomData } | |
) | |
} | |
} | |
impl<List, Scope : Pred> Splitter<List, Scope, Scope> { | |
fn unborrow_id(self, id_mut : Mutator<ID, Self>) -> Splitter<List, ID, Scope::P> { | |
let id = unsafe{ id_mut.consume() }; | |
Splitter { list: self.list, id , _scope: Scope::P::VAL} | |
} | |
} | |
impl<Id, Scope : Pred> Splitter<Scope, Id, Scope> { | |
fn unborrow_list(self, id_mut : Mutator<LIST, Self>) -> Splitter<LIST, Id, Scope::P> { | |
let list = unsafe{ id_mut.consume() }; | |
Splitter { list, id: self.id, _scope : Scope::P::VAL } | |
} | |
} | |
#[must_use] | |
struct Mutator<M,Src> { | |
mutable : M, | |
src : PhantomData<Src> | |
} | |
impl<M,Src> Mutator<M,Src> { | |
unsafe fn consume(self) -> M { | |
let m = core::ptr::read(&self.mutable); | |
let _ = core::mem::ManuallyDrop::new(self); | |
m | |
} | |
} | |
impl<M,Src> Drop for Mutator<M,Src> { | |
fn drop(&mut self) { | |
core::panic!() | |
} | |
} | |
impl<M,Src> core::ops::Deref for Mutator<M,Src> { | |
type Target = M; | |
fn deref(&self) -> &Self::Target { | |
&self.mutable | |
} | |
} | |
impl<M,Src> core::ops::DerefMut for Mutator<M,Src> { | |
fn deref_mut(&mut self) -> &mut Self::Target { | |
&mut self.mutable | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment