Advertisement
Guest User

Untitled

a guest
Nov 26th, 2015
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.48 KB | None | 0 0
  1. //! Evolv-ty: Enforcing evolving protocols with Rust's type system.
  2. //!
  3. //! Pros:
  4. //! - Avoid regressions in the protocol
  5. //! - Tiny and simple implementation
  6. //! - Deprecated functions can be trivially no-op
  7. //! - Types may be changed trivially
  8. //!
  9. //! Cons:
  10. //! - Tracking versions can get verbose and messy
  11. //!
  12. //! Cargo feature gates:
  13. //! - docs: Manually implement Since<L> for each R
  14. //! - no_backwards: Don't support deprecated functions
  15. //! - debug_tests: Cause a panic to show which functions were called
  16.  
  17. /// Marker trait: 'Self' fits within the range requirement of `L..` (inclusive)
  18. pub trait Since<L> {}
  19. /// Marker trait: 'Self' fits within the range requirement of `..R` (exclusive)
  20. pub trait Until<R> {}
  21. /// Inclusive left, exclusive right range sugar
  22. pub trait Range<L, R>: Since<L> + Until<R> {}
  23.  
  24. #[cfg(not(feature = "docs"))]
  25. impl<L, R> Since<L> for R where L: Until<R> {}
  26. impl<L, R, T> Range<L, R> for T where T: Since<L> + Until<R> {}
  27.  
  28. macro_rules! ordered {
  29. () => {};
  30. ($head:ident $($tail:ident)*) => {
  31. #[allow(non_camel_case_types)]
  32. pub enum $head {}
  33. impl Since<$head> for $head {}
  34. $(
  35. #[cfg(feature = "docs")]
  36. impl Since<$head> for $tail {}
  37. )*
  38. $(impl Until<$tail> for $head {})*
  39. ordered!{ $($tail)* }
  40. }
  41. }
  42.  
  43. #[cfg(any(test, feature = "docs"))]
  44. pub mod test {
  45. use {Since, Until, Range};
  46.  
  47. ordered!{
  48. Alice // Alpha
  49. Bob // Beta
  50. Carol // Beta RC1
  51. Dave // Beta RC2
  52. Stable_1_0_0 // Cannonical version numbers
  53. Nightly_2_0_0 // Not yet officially in the protocol
  54. }
  55.  
  56. // Version tagging may be relative to assist with stability tests
  57. type Alpha = Alice;
  58. type Beta = Dave;
  59. type Stable = Stable_1_0_0;
  60. type Nightly = Nightly_2_0_0;
  61.  
  62. pub trait FooTypes {
  63. type A;
  64. type B;
  65. }
  66.  
  67. #[cfg(not(feature = "no_backwards"))]
  68. impl FooTypes for Alice {
  69. // impl<R: Range<Alice, Bob>> FooTypes for R {
  70. type A = u8; // A was too small
  71. type B = (); // B did not exist
  72. }
  73.  
  74. impl<R: Since<Bob>> FooTypes for R {
  75. type A = u16;
  76. type B = u64;
  77. }
  78.  
  79. #[allow(dead_code)]
  80. pub struct Foo<R> where R: FooTypes {
  81. a: <R as FooTypes>::A,
  82. b: <R as FooTypes>::B,
  83. marker: ::std::marker::PhantomData<R>
  84. }
  85.  
  86. #[cfg(not(feature = "no_backwards"))]
  87. impl<R: Range<Alice, Bob>> Foo<R> where R: FooTypes {
  88. // Deprecated since Bob
  89. fn alice() {
  90. println!("Deprecated function: fn alice. Alice <= Version < Bob")
  91. }
  92. }
  93.  
  94. impl<R: Since<Bob>> Foo<R> where R: FooTypes {
  95. // Updated implementation of Alice.
  96. fn alice() {
  97. println!("Alice: Version = Bob+")
  98. }
  99.  
  100. // Added in Beta
  101. fn bob() {}
  102. // Added in Beta RC 1
  103. fn carol() where R: Since<Carol> {}
  104.  
  105. // Bob..Dave
  106. fn until_dave() where R: Until<Dave> {}
  107.  
  108. // Unofficially deprecated since 2.0
  109. fn beta_nightly() where R: Range<Beta, Nightly> {}
  110. }
  111.  
  112. #[test]
  113. fn typecheck() {
  114. // Fails to typecheck when --features no_backwards
  115. Foo::<Alice>::alice(); // Alice == Alice < Bob
  116.  
  117. Foo::<Bob>::alice(); // Bob > Alice
  118. Foo::<Carol>::bob(); // Carol > Bob
  119. Foo::<Carol>::carol(); // Carol == Carol
  120. Foo::<Carol>::until_dave(); // Carol < Dave
  121.  
  122. Foo::<Stable>::beta_nightly();
  123. if cfg!(feature = "debug_tests") {
  124. panic!("Debug")
  125. }
  126. }
  127. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement