Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //! Evolv-ty: Enforcing evolving protocols with Rust's type system.
- //!
- //! Pros:
- //! - Avoid regressions in the protocol
- //! - Tiny and simple implementation
- //! - Deprecated functions can be trivially no-op
- //! - Types may be changed trivially
- //!
- //! Cons:
- //! - Tracking versions can get verbose and messy
- /// Marker trait: 'Self' fits within the range requirement of `L..` (inclusive)
- pub trait Start<L> {}
- /// Marker trait: 'Self' fits within the range requirement of `..R` (exclusive)
- pub trait End<R> {}
- /// Allow structs to use the evolving properties
- trait Pick<V> { type Ty; }
- impl<L, R> Start<L> for R where L: End<R> {}
- macro_rules! ordered {
- () => {};
- ($head:ident $($tail:ident)*) => {
- #[allow(non_camel_case_types)]
- pub enum $head {}
- impl Start<$head> for $head {}
- $(impl End<$tail> for $head {})*
- ordered!{ $($tail)* }
- }
- }
- #[cfg(test)]
- mod test {
- use {Start, End, Pick};
- ordered!{
- Alice // Alpha
- Bob // Beta
- Carol // Beta RC1
- Dave // Beta RC2
- Stable_1_0_0 // Cannonical version numbers
- Nightly_2_0_0 // Not yet officially in the protocol
- }
- // Version tagging may be relative to assist with stability tests
- type Alpha = Alice;
- type Beta = Dave;
- type Stable = Stable_1_0_0;
- type Nightly = Nightly_2_0_0;
- enum FooAB {}
- // impl<R: Start<Alpha> + End<Beta>> Pick<R> for FooAB {
- impl Pick<Alpha> for FooAB {
- type Ty = u8;
- }
- impl<R: Start<Beta>> Pick<R> for FooAB {
- type Ty = u16;
- }
- pub struct Foo<V> where FooAB: Pick<V> {
- a: <FooAB as Pick<V>>::Ty,
- marker: ::std::marker::PhantomData<V>
- }
- #[cfg(not(feature = "no_backwards"))]
- impl<V: Start<Alice> + End<Bob>> Foo<V> {
- // Deprecated since Bob
- fn alice() {
- println!("Deprecated function: fn alice. Alice <= Version < Bob")
- }
- }
- impl<V: Start<Bob>> Foo<V> {
- // Updated implementation of alice.
- fn alice() {
- println!("Alice: Version = Bob+")
- }
- // Added in Beta
- fn bob() where V: Start<Bob> {}
- // Added in Beta RC 1
- fn carol() where V: Start<Carol> {}
- // Unofficially deprecated since 2.0
- fn beta_nightly() where V: Start<Beta> + End<Nightly> {}
- }
- #[test]
- fn typecheck() {
- // Fails to typecheck when --features no_backwards
- Foo::<Alice>::alice(); // Alice == Alice < Bob
- Foo::<Bob>::alice(); // Bob > Alice
- Foo::<Carol>::bob(); // Carol > Bob
- Foo::<Carol>::carol(); // Carol == Carol
- Foo::<Stable>::beta_nightly();
- if cfg!(feature = "debug_tests") {
- panic!("Debug")
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement