/// example: prevent "wrong interner" bugs at compile time use typetoken::{token, Token}; use std::marker::PhantomData; //#[derive(PartialEq)] struct Interner { // actual interning implementation doesn't matter v: Vec, _token: PhantomData, } struct InternedString { index: usize, _token: PhantomData, } impl Interner { fn new(_token: T) -> Self { Self{ v: vec![], _token: PhantomData::default() } } fn intern(&mut self, s: &str) -> InternedString { let index; if let Some(idx) = self.v.iter().position(|x| x == s) { index = idx; } else { index = self.v.len(); self.v.push(s.to_string()); } InternedString{ index, _token: PhantomData::default(), } } fn resolve(&self, s: InternedString) -> &str { &self.v[s.index] } } fn main() { token!(token1); let mut pool1 = Interner::new(token1); token!(token2); let mut pool2 = Interner::new(token2); let str1 = pool1.intern("abcd"); let str2 = pool2.intern("1234"); println!("{}", pool1.resolve(str1)); println!("{}", pool2.resolve(str2)); // wrong interner, compile error //println!("{}", pool2.resolve(str1)); } // TODO: test that a recursive function cant construct the same token twice (invariant lifetimes should make this impossible) //fn recursive(args: Option<(