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
- //!
- //! Cargo feature gates:
- //! - docs: Manually implement Since<L> for each R
- //! - no_backwards: Don't support deprecated functions
- //! - debug_tests: Cause a panic to show which functions were called
- /// Marker trait: 'Self' fits within the range requirement of `L..` (inclusive)
- pub trait Since<L> {}
- /// Marker trait: 'Self' fits within the range requirement of `..R` (exclusive)
- pub trait Until<R> {}
- /// Inclusive left, exclusive right range sugar
- pub trait Range<L, R>: Since<L> + Until<R> {}
- #[cfg(not(feature = "docs"))]
- impl<L, R> Since<L> for R where L: Until<R> {}
- impl<L, R, T> Range<L, R> for T where T: Since<L> + Until<R> {}
- macro_rules! ordered {
- () => {};
- ($head:ident $($tail:ident)*) => {
- #[allow(non_camel_case_types)]
- pub enum $head {}
- impl Since<$head> for $head {}
- $(
- #[cfg(feature = "docs")]
- impl Since<$head> for $tail {}
- )*
- $(impl Until<$tail> for $head {})*
- ordered!{ $($tail)* }
- }
- }
- #[cfg(any(test, feature = "docs"))]
- pub mod test {
- use {Since, Until, Range};
- 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;
- pub trait FooTypes {
- type A;
- type B;
- }
- #[cfg(not(feature = "no_backwards"))]
- impl FooTypes for Alice {
- // impl<R: Range<Alice, Bob>> FooTypes for R {
- type A = u8; // A was too small
- type B = (); // B did not exist
- }
- impl<R: Since<Bob>> FooTypes for R {
- type A = u16;
- type B = u64;
- }
- #[allow(dead_code)]
- pub struct Foo<R> where R: FooTypes {
- a: <R as FooTypes>::A,
- b: <R as FooTypes>::B,
- marker: ::std::marker::PhantomData<R>
- }
- #[cfg(not(feature = "no_backwards"))]
- impl<R: Range<Alice, Bob>> Foo<R> where R: FooTypes {
- // Deprecated since Bob
- fn alice() {
- println!("Deprecated function: fn alice. Alice <= Version < Bob")
- }
- }
- impl<R: Since<Bob>> Foo<R> where R: FooTypes {
- // Updated implementation of Alice.
- fn alice() {
- println!("Alice: Version = Bob+")
- }
- // Added in Beta
- fn bob() {}
- // Added in Beta RC 1
- fn carol() where R: Since<Carol> {}
- // Bob..Dave
- fn until_dave() where R: Until<Dave> {}
- // Unofficially deprecated since 2.0
- fn beta_nightly() where R: Range<Beta, 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::<Carol>::until_dave(); // Carol < Dave
- Foo::<Stable>::beta_nightly();
- if cfg!(feature = "debug_tests") {
- panic!("Debug")
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement