A hammer you can only hold by the handle

A hammer you can only hold by the handle

Presented at RustFest Zürich (http://zurich.rustfest.eu)

Rust’s type system provides tools to ensure safe memory management, and safe concurrent access to data. What if we used those same tools to encode and enforce other API constraints?

We can leverage affine types (non-Clone structs) to enforce that a user performs a series of operations in a certain order; or we can use structs as tokens representing the user’s ability to perform certain actions. And everything’s checked at compile time.

We’ll see how these techniques let us encode complex API constraints, and make them self-documenting by preventing disallowed behaviour at compile time.

98e8177ac82d61a351b3b636e244bbd5?s=128

Andrea Lattuada

September 30, 2017
Tweet

Transcript

  1. A HAMMER YOU CAN ONLY
 HOLD BY THE HANDLE ANDREA

    LATTUADA @UTAAL
 SYSTEMS GROUP, DEPT. OF COMPUTER SCIENCE
 ETH ZÜRICH
  2. API

  3. API

  4. API

  5. API

  6. API

  7. API

  8. API

  9. API

  10. API

  11. API

  12. API

  13. WE ARE MANAGING RESOURCES

  14. OWNERSHIP (LINEAR / AFFINE TYPES)

  15. OWNERSHIP (LINEAR / AFFINE TYPES) fn use_name(name: String) { }

    fn main() { let name = String::from(“Andrea”); use_name(name); println!("{}", name); }
  16. OWNERSHIP (LINEAR / AFFINE TYPES) fn use_name(name: String) { }

    fn main() { let name = String::from(“Andrea”); use_name(name); println!("{}", name); } error[E0382]: use of moved value: `name` ---- value moved here ^^^^ value used here after move
  17. OWNERSHIP (LINEAR / AFFINE TYPES) fn use_name(name: String) { }

    fn main() { let name = String::from(“Andrea”); use_name(name); println!("{}", name); } error[E0382]: use of moved value: `name` ---- value moved here ^^^^ value used here after move
  18. OWNERSHIP (LINEAR / AFFINE TYPES) fn use_name(name: String) { }

    fn main() { let name = String::from(“Andrea”); use_name(name); println!("{}", name); } error[E0382]: use of moved value: `name` ---- value moved here ^^^^ value used here after move
  19. OWNERSHIP (LINEAR / AFFINE TYPES) fn use_name(name: String) { }

    fn main() { let name = String::from(“Andrea”); use_name(name); println!("{}", name); } error[E0382]: use of moved value: `name` ---- value moved here ^^^^ value used here after move
  20. DROP

  21. DROP fn main() { let a = get_number(); if a

    > 3 { let data = vec![3, 4, 8]; } println!("{}", data); }
  22. DROP fn main() { let a = get_number(); if a

    > 3 { let data = vec![3, 4, 8]; } println!("{}", data); } `data` dropped here
  23. WE ARE STILL MANAGING RESOURCES IN HIGHER LEVEL APIS

  24. #[derive(Clone)] pub struct Letter { text: String, } pub struct

    Envelope { letter: Option<Letter>, } pub struct PickupLorryHandle { done: bool, // references to lorry's resources }
  25. #[derive(Clone)] pub struct Letter { text: String, } pub struct

    Envelope { letter: Option<Letter>, } pub struct PickupLorryHandle { done: bool, // references to lorry's resources }
  26. #[derive(Clone)] pub struct Letter { text: String, } pub struct

    Envelope { letter: Option<Letter>, } pub struct PickupLorryHandle { done: bool, // references to lorry's resources }
  27. #[derive(Clone)] pub struct Letter { text: String, } pub struct

    Envelope { letter: Option<Letter>, } pub struct PickupLorryHandle { done: bool, // references to lorry's resources }
  28. #[derive(Clone)] pub struct Letter { text: String, } impl Letter

    { pub fn new(text: String) -> Self { Letter { text: text } } }
  29. pub struct Envelope { letter: Option<Letter>, } impl Envelope {

    pub fn wrap(&mut self, letter: &Letter) { self.letter = Some(letter.clone()); } } pub fn buy_prestamped_envelope() -> Envelope { Envelope { letter: None } }
  30. pub struct Envelope { letter: Option<Letter>, } impl Envelope {

    pub fn wrap(&mut self, letter: &Letter) { self.letter = Some(letter.clone()); } } pub fn buy_prestamped_envelope() -> Envelope { Envelope { letter: None } }
  31. pub struct Envelope { letter: Option<Letter>, } impl Envelope {

    pub fn wrap(&mut self, letter: &Letter) { self.letter = Some(letter.clone()); } } pub fn buy_prestamped_envelope() -> Envelope { Envelope { letter: None } }
  32. pub struct PickupLorryHandle { done: bool, // references to lorry's

    resources } impl PickupLorryHandle { pub fn pickup(&mut self, envelope: &Envelope) { /* give letter */ } pub fn done(&mut self) { self.done = true; println!("sent"); } } pub fn order_pickup() -> PickupLorryHandle { PickupLorryHandle { done: false, /* other handles */ } }
  33. pub struct PickupLorryHandle { done: bool, // references to lorry's

    resources } impl PickupLorryHandle { pub fn pickup(&mut self, envelope: &Envelope) { /* give letter */ } pub fn done(&mut self) { self.done = true; println!("sent"); } } pub fn order_pickup() -> PickupLorryHandle { PickupLorryHandle { done: false, /* other handles */ } }
  34. pub struct PickupLorryHandle { done: bool, // references to lorry's

    resources } impl PickupLorryHandle { pub fn pickup(&mut self, envelope: &Envelope) { /* give letter */ } pub fn done(&mut self) { self.done = true; println!("sent"); } } pub fn order_pickup() -> PickupLorryHandle { PickupLorryHandle { done: false, /* other handles */ } }
  35. pub struct PickupLorryHandle { done: bool, // references to lorry's

    resources } impl PickupLorryHandle { pub fn pickup(&mut self, envelope: &Envelope) { /* give letter */ } pub fn done(&mut self) { self.done = true; println!("sent"); } } pub fn order_pickup() -> PickupLorryHandle { PickupLorryHandle { done: false, /* other handles */ } }
  36. // in a separate module fn main() { let rustfest_letter

    = Letter::new(String::from("Dear RustFest")); let mut rustfest_envelope = buy_prestamped_envelope(); rustfest_envelope.wrap(&rustfest_letter); let mut lorry = order_pickup(); lorry.pickup(&rustfest_envelope); lorry.done(); }
  37. // in a separate module fn main() { let rustfest_letter

    = Letter::new(String::from("Dear RustFest")); let mut rustfest_envelope = buy_prestamped_envelope(); rustfest_envelope.wrap(&rustfest_letter); let mut lorry = order_pickup(); lorry.pickup(&rustfest_envelope); lorry.done(); }
  38. // in a separate module fn main() { let rustfest_letter

    = Letter::new(String::from("Dear RustFest")); let mut rustfest_envelope = buy_prestamped_envelope(); rustfest_envelope.wrap(&rustfest_letter); let mut lorry = order_pickup(); lorry.pickup(&rustfest_envelope); lorry.done(); }
  39. // in a separate module fn main() { let rustfest_letter

    = Letter::new(String::from("Dear RustFest")); let mut rustfest_envelope = buy_prestamped_envelope(); rustfest_envelope.wrap(&rustfest_letter); let mut lorry = order_pickup(); lorry.pickup(&rustfest_envelope); lorry.done(); }
  40. // in a separate module fn main() { let rustfest_letter

    = Letter::new(String::from("Dear RustFest")); let mut rustfest_envelope = buy_prestamped_envelope(); rustfest_envelope.wrap(&rustfest_letter); let mut lorry = order_pickup(); lorry.pickup(&rustfest_envelope); lorry.done(); }
  41. // in a separate module fn main() { let rustfest_letter

    = Letter::new(String::from("Dear RustFest")); let mut rustfest_envelope = buy_prestamped_envelope(); rustfest_envelope.wrap(&rustfest_letter); let mut lorry = order_pickup(); lorry.pickup(&rustfest_envelope); lorry.done(); }
  42. // in a separate module fn main() { let rustfest_letter

    = Letter::new(String::from("Dear RustFest")); let mut rustfest_envelope = buy_prestamped_envelope(); rustfest_envelope.wrap(&rustfest_letter); let mut lorry = order_pickup(); lorry.pickup(&rustfest_envelope); lorry.done(); }
  43. ? 1. 2. 3.

  44. ? 1. 2. 3.

  45. ? 1. 2. 3.

  46. ? 1. 2. 3.

  47. 1.

  48. fn main() { let rustfest_letter = Letter::new(String::from("Dear RustFest")); let mut

    envelopes = vec![ buy_prestamped_envelope(), buy_prestamped_envelope()]; let mut lorry = order_pickup(); for e in envelopes.iter_mut() { e.wrap(&rustfest_letter); lorry.pickup(&e); } lorry.done(); }
  49. fn main() { let rustfest_letter = Letter::new(String::from("Dear RustFest")); let mut

    envelopes = vec![ buy_prestamped_envelope(), buy_prestamped_envelope()]; let mut lorry = order_pickup(); for e in envelopes.iter_mut() { e.wrap(&rustfest_letter); lorry.pickup(&e); } lorry.done(); }
  50. fn main() { let rustfest_letter = Letter::new(String::from("Dear RustFest")); let mut

    envelopes = vec![ buy_prestamped_envelope(), buy_prestamped_envelope()]; let mut lorry = order_pickup(); for e in envelopes.iter_mut() { e.wrap(&rustfest_letter); lorry.pickup(&e); } lorry.done(); }
  51. fn main() { let rustfest_letter = Letter::new(String::from("Dear RustFest")); let mut

    envelopes = vec![ buy_prestamped_envelope(), buy_prestamped_envelope()]; let mut lorry = order_pickup(); for e in envelopes.iter_mut() { e.wrap(&rustfest_letter); lorry.pickup(&e); } lorry.done(); }
  52. fn main() { let rustfest_letter = Letter::new(String::from("Dear RustFest")); let mut

    envelopes = vec![ buy_prestamped_envelope(), buy_prestamped_envelope()]; let mut lorry = order_pickup(); for e in envelopes.iter_mut() { e.wrap(&rustfest_letter); lorry.pickup(&e); } lorry.done(); }
  53. fn main() { let rustfest_letter = Letter::new(String::from("Dear RustFest")); let mut

    envelopes = vec![ buy_prestamped_envelope(), buy_prestamped_envelope()]; let mut lorry = order_pickup(); for e in envelopes.iter_mut() { e.wrap(&rustfest_letter); lorry.pickup(&e); } lorry.done(); } #[derive(Clone)] pub struct Letter { text: String, }
  54. fn main() { let rustfest_letter = Letter::new(String::from("Dear RustFest")); let mut

    envelopes = vec![ buy_prestamped_envelope(), buy_prestamped_envelope()]; let mut lorry = order_pickup(); for e in envelopes.iter_mut() { e.wrap(rustfest_letter); lorry.pickup(&e); #[derive(Clone)] pub struct Letter { text: String, } impl Envelope { pub fn wrap(&mut self, letter: Letter) { self.letter = Some(letter); } }
  55. fn main() { let rustfest_letter = Letter::new(String::from("Dear RustFest")); let mut

    envelopes = vec![ buy_prestamped_envelope(), buy_prestamped_envelope()]; let mut lorry = order_pickup(); for e in envelopes.iter_mut() { e.wrap(rustfest_letter); lorry.pickup(&e); #[derive(Clone)] pub struct Letter { text: String, } impl Envelope { pub fn wrap(&mut self, letter: Letter) { self.letter = Some(letter); } }
  56. fn main() { let rustfest_letter = Letter::new(String::from("Dear RustFest")); let mut

    envelopes = vec![ buy_prestamped_envelope(), buy_prestamped_envelope()]; let mut lorry = order_pickup(); for e in envelopes.iter_mut() { e.wrap(rustfest_letter); lorry.pickup(&e); #[derive(Clone)] pub struct Letter { text: String, } impl Envelope { pub fn wrap(&mut self, letter: Letter) { self.letter = Some(letter); } }
  57. fn main() { let rustfest_letter = Letter::new(String::from("Dear RustFest")); let mut

    envelopes = vec![ buy_prestamped_envelope(), buy_prestamped_envelope()]; let mut lorry = order_pickup(); for e in envelopes.iter_mut() { e.wrap(rustfest_letter); lorry.pickup(&e); #[derive(Clone)] pub struct Letter { text: String, } impl Envelope { pub fn wrap(&mut self, letter: Letter) { self.letter = Some(letter); } }
  58. fn main() { let rustfest_letter = Letter::new(String::from("Dear RustFest")); let mut

    envelopes = vec![ buy_prestamped_envelope(), buy_prestamped_envelope()]; let mut lorry = order_pickup(); for e in envelopes.iter_mut() { e.wrap(rustfest_letter); lorry.pickup(&e); #[derive(Clone)] pub struct Letter { text: String, } impl Envelope { pub fn wrap(&mut self, letter: Letter) { self.letter = Some(letter); } }
  59. fn main() { let rustfest_letter = Letter::new(String::from("Dear RustFest")); let mut

    envelopes = vec![ buy_prestamped_envelope(), buy_prestamped_envelope()]; let mut lorry = order_pickup(); for e in envelopes.iter_mut() { e.wrap(rustfest_letter); lorry.pickup(&e); #[derive(Clone)] pub struct Letter { text: String, } impl Envelope { pub fn wrap(&mut self, letter: Letter) { self.letter = Some(letter); } }
  60. fn main() { let rustfest_letter = Letter::new(String::from("Dear RustFest")); let mut

    envelopes = vec![ buy_prestamped_envelope(), buy_prestamped_envelope()]; let mut lorry = order_pickup(); for e in envelopes.iter_mut() { e.wrap(rustfest_letter); lorry.pickup(&e); } lorry.done(); }
  61. fn main() { let rustfest_letter = Letter::new(String::from("Dear RustFest")); let mut

    envelopes = vec![ buy_prestamped_envelope(), buy_prestamped_envelope()]; let mut lorry = order_pickup(); for e in envelopes.iter_mut() { e.wrap(rustfest_letter); lorry.pickup(&e); } lorry.done(); } error[E0382]: use of moved value: `rustfest_letter` ^^^^^^^^^^^^^^^ value moved here in previous iteration
 of loop
  62. 1.

  63. 2.

  64. // in a separate module fn main() { let rustfest_letter

    = Letter::new(String::from("Dear RustFest")); let mut envelope = buy_prestamped_envelope(); envelope.wrap(rustfest_letter); let eth_letter = Letter::new(String::from("Dear ETH")); envelope.wrap(eth_letter); let mut lorry = order_pickup();
  65. // in a separate module fn main() { let rustfest_letter

    = Letter::new(String::from("Dear RustFest")); let mut envelope = buy_prestamped_envelope(); envelope.wrap(rustfest_letter); let eth_letter = Letter::new(String::from("Dear ETH")); envelope.wrap(eth_letter); let mut lorry = order_pickup();
  66. // in a separate module fn main() { let rustfest_letter

    = Letter::new(String::from("Dear RustFest")); let mut envelope = buy_prestamped_envelope(); envelope.wrap(rustfest_letter); let eth_letter = Letter::new(String::from("Dear ETH")); envelope.wrap(eth_letter); let mut lorry = order_pickup();
  67. // in a separate module fn main() { let rustfest_letter

    = Letter::new(String::from("Dear RustFest")); let mut envelope = buy_prestamped_envelope(); envelope.wrap(rustfest_letter); let eth_letter = Letter::new(String::from("Dear ETH")); envelope.wrap(eth_letter); let mut lorry = order_pickup();
  68. // in a separate module fn main() { let rustfest_letter

    = Letter::new(String::from("Dear RustFest")); let mut envelope = buy_prestamped_envelope(); envelope.wrap(rustfest_letter); let eth_letter = Letter::new(String::from("Dear ETH")); envelope.wrap(eth_letter); let mut lorry = order_pickup(); impl Envelope { pub fn wrap(&mut self, letter: &Letter) { self.letter = Some(letter.clone()); } }
  69. // in a separate module fn main() { let rustfest_letter

    = Letter::new(String::from("Dear RustFest")); let mut envelope = buy_prestamped_envelope(); envelope.wrap(rustfest_letter); let eth_letter = Letter::new(String::from("Dear ETH")); envelope.wrap(eth_letter); let mut lorry = order_pickup(); impl Envelope { pub fn wrap(&mut self, letter: &Letter) { self.letter = Some(letter.clone()); } } assert!(self.letter.is_none());
  70. // in a separate module fn main() { let rustfest_letter

    = Letter::new(String::from("Dear RustFest")); let mut envelope = buy_prestamped_envelope(); envelope.wrap(rustfest_letter); let eth_letter = Letter::new(String::from("Dear ETH")); envelope.wrap(eth_letter); let mut lorry = order_pickup(); impl Envelope { pub fn wrap(&mut self, letter: &Letter) { self.letter = Some(letter.clone()); } } panic assert!(self.letter.is_none());
  71. pub struct EmptyEnvelope { } pub struct ClosedEnvelope { letter:

    Letter, } impl EmptyEnvelope { pub fn wrap(self, letter: Letter) -> ClosedEnvelope { ClosedEnvelope { letter: letter } } } impl PickupLorryHandle { pub fn pickup(&mut self, envelope: ClosedEnvelope) { /* give letter */ } pub fn buy_prestamped_envelope() -> EmptyEnvelope { EmptyEnvelope { } }
  72. pub struct EmptyEnvelope { } pub struct ClosedEnvelope { letter:

    Letter, } impl EmptyEnvelope { pub fn wrap(self, letter: Letter) -> ClosedEnvelope { ClosedEnvelope { letter: letter } } } impl PickupLorryHandle { pub fn pickup(&mut self, envelope: ClosedEnvelope) { /* give letter */ } pub fn buy_prestamped_envelope() -> EmptyEnvelope { EmptyEnvelope { } }
  73. pub struct EmptyEnvelope { } pub struct ClosedEnvelope { letter:

    Letter, } impl EmptyEnvelope { pub fn wrap(self, letter: Letter) -> ClosedEnvelope { ClosedEnvelope { letter: letter } } } impl PickupLorryHandle { pub fn pickup(&mut self, envelope: ClosedEnvelope) { /* give letter */ } pub fn buy_prestamped_envelope() -> EmptyEnvelope { EmptyEnvelope { } }
  74. pub struct EmptyEnvelope { } pub struct ClosedEnvelope { letter:

    Letter, } impl EmptyEnvelope { pub fn wrap(self, letter: Letter) -> ClosedEnvelope { ClosedEnvelope { letter: letter } } } impl PickupLorryHandle { pub fn pickup(&mut self, envelope: ClosedEnvelope) { /* give letter */ } pub fn buy_prestamped_envelope() -> EmptyEnvelope { EmptyEnvelope { } }
  75. pub struct EmptyEnvelope { } pub struct ClosedEnvelope { letter:

    Letter, } impl EmptyEnvelope { pub fn wrap(self, letter: Letter) -> ClosedEnvelope { ClosedEnvelope { letter: letter } } } impl PickupLorryHandle { pub fn pickup(&mut self, envelope: ClosedEnvelope) { /* give letter */ } pub fn buy_prestamped_envelope() -> EmptyEnvelope { EmptyEnvelope { } }
  76. pub struct EmptyEnvelope { } pub struct ClosedEnvelope { letter:

    Letter, } impl EmptyEnvelope { pub fn wrap(self, letter: Letter) -> ClosedEnvelope { ClosedEnvelope { letter: letter } } } impl PickupLorryHandle { pub fn pickup(&mut self, envelope: ClosedEnvelope) { /* give letter */ } pub fn buy_prestamped_envelope() -> EmptyEnvelope { EmptyEnvelope { } }
  77. pub struct EmptyEnvelope { } pub struct ClosedEnvelope { letter:

    Letter, } impl EmptyEnvelope { pub fn wrap(self, letter: Letter) -> ClosedEnvelope { ClosedEnvelope { letter: letter } } } impl PickupLorryHandle { pub fn pickup(&mut self, envelope: ClosedEnvelope) { /* give letter */ } pub fn buy_prestamped_envelope() -> EmptyEnvelope { EmptyEnvelope { } }
  78. None
  79. fn main() { let rustfest_letter = Letter::new(String::from("Dear RustFest")); let envelope

    = buy_prestamped_envelope(); envelope.wrap(rustfest_letter); let eth_letter = Letter::new(String::from("Dear ETH")); envelope.wrap(eth_letter); let mut lorry = order_pickup(); lorry.pickup(envelope); lorry.done(); }
  80. fn main() { let rustfest_letter = Letter::new(String::from("Dear RustFest")); let envelope

    = buy_prestamped_envelope(); envelope.wrap(rustfest_letter); let eth_letter = Letter::new(String::from("Dear ETH")); envelope.wrap(eth_letter); let mut lorry = order_pickup(); lorry.pickup(envelope); lorry.done(); }
  81. fn main() { let rustfest_letter = Letter::new(String::from("Dear RustFest")); let envelope

    = buy_prestamped_envelope(); envelope.wrap(rustfest_letter); let eth_letter = Letter::new(String::from("Dear ETH")); envelope.wrap(eth_letter); let mut lorry = order_pickup(); lorry.pickup(envelope); lorry.done(); }
  82. fn main() { let rustfest_letter = Letter::new(String::from("Dear RustFest")); let envelope

    = buy_prestamped_envelope(); envelope.wrap(rustfest_letter); let eth_letter = Letter::new(String::from("Dear ETH")); envelope.wrap(eth_letter); let mut lorry = order_pickup(); lorry.pickup(envelope); lorry.done(); }
  83. fn main() { let rustfest_letter = Letter::new(String::from("Dear RustFest")); let envelope

    = buy_prestamped_envelope(); envelope.wrap(rustfest_letter); let eth_letter = Letter::new(String::from("Dear ETH")); envelope.wrap(eth_letter); let mut lorry = order_pickup(); lorry.pickup(envelope); lorry.done(); }
  84. fn main() { let rustfest_letter = Letter::new(String::from("Dear RustFest")); let envelope

    = buy_prestamped_envelope(); envelope.wrap(rustfest_letter); let eth_letter = Letter::new(String::from("Dear ETH")); envelope.wrap(eth_letter); let mut lorry = order_pickup(); lorry.pickup(envelope); lorry.done(); } error[E0308]: mismatched types = note: expected type `ClosedEnvelope` found type `EmptyEnvelope` = help: here are some functions which might fulfill your needs: - .wrap(...) ^^^^^^^^ expected struct `ClosedEnvelope`, found struct `EmptyEnvelope`
  85. fn main() { let rustfest_letter = Letter::new(String::from("Dear RustFest")); let envelope

    = buy_prestamped_envelope(); let closed_envelope = envelope.wrap(rustfest_letter); let eth_letter = Letter::new(String::from("Dear ETH")); let closed_envelope = envelope.wrap(eth_letter); let mut lorry = order_pickup(); lorry.pickup(closed_envelope); lorry.done(); }
  86. fn main() { let rustfest_letter = Letter::new(String::from("Dear RustFest")); let envelope

    = buy_prestamped_envelope(); let closed_envelope = envelope.wrap(rustfest_letter); let eth_letter = Letter::new(String::from("Dear ETH")); let closed_envelope = envelope.wrap(eth_letter); let mut lorry = order_pickup(); lorry.pickup(closed_envelope); lorry.done(); }
  87. fn main() { let rustfest_letter = Letter::new(String::from("Dear RustFest")); let envelope

    = buy_prestamped_envelope(); let closed_envelope = envelope.wrap(rustfest_letter); let eth_letter = Letter::new(String::from("Dear ETH")); let closed_envelope = envelope.wrap(eth_letter); let mut lorry = order_pickup(); lorry.pickup(closed_envelope); lorry.done(); }
  88. fn main() { let rustfest_letter = Letter::new(String::from("Dear RustFest")); let envelope

    = buy_prestamped_envelope(); let closed_envelope = envelope.wrap(rustfest_letter); let eth_letter = Letter::new(String::from("Dear ETH")); let closed_envelope = envelope.wrap(eth_letter); let mut lorry = order_pickup(); lorry.pickup(closed_envelope); lorry.done(); }
  89. fn main() { let rustfest_letter = Letter::new(String::from("Dear RustFest")); let envelope

    = buy_prestamped_envelope(); let closed_envelope = envelope.wrap(rustfest_letter); let eth_letter = Letter::new(String::from("Dear ETH")); let closed_envelope = envelope.wrap(eth_letter); let mut lorry = order_pickup(); lorry.pickup(closed_envelope); lorry.done(); } error[E0382]: use of moved value: `envelope` -------- value moved here ^^^^^^^^ value used here after move
  90. 2.

  91. ? 3.

  92. fn main() { let rustfest_letter = Letter::new(String::from("Dear RustFest")); let envelope

    = buy_prestamped_envelope(); let closed_envelope = envelope.wrap(rustfest_letter); let mut lorry = order_pickup(); lorry.pickup(closed_envelope); }
  93. fn main() { let rustfest_letter = Letter::new(String::from("Dear RustFest")); let envelope

    = buy_prestamped_envelope(); let closed_envelope = envelope.wrap(rustfest_letter); let mut lorry = order_pickup(); lorry.pickup(closed_envelope); }
  94. fn main() { let rustfest_letter = Letter::new(String::from("Dear RustFest")); let envelope

    = buy_prestamped_envelope(); let closed_envelope = envelope.wrap(rustfest_letter); let mut lorry = order_pickup(); lorry.pickup(closed_envelope); }
  95. fn main() { let rustfest_letter = Letter::new(String::from("Dear RustFest")); let envelope

    = buy_prestamped_envelope(); let closed_envelope = envelope.wrap(rustfest_letter); let mut lorry = order_pickup(); lorry.pickup(closed_envelope); }
  96. fn main() { let rustfest_letter = Letter::new(String::from("Dear RustFest")); let envelope

    = buy_prestamped_envelope(); let closed_envelope = envelope.wrap(rustfest_letter); let mut lorry = order_pickup(); lorry.pickup(closed_envelope); } impl Drop for PickupLorryHandle { fn drop(&mut self) { println!("sent"); } } impl PickupLorryHandle { pub fn done(self) { } …
  97. fn main() { let rustfest_letter = Letter::new(String::from("Dear RustFest")); let envelope

    = buy_prestamped_envelope(); let closed_envelope = envelope.wrap(rustfest_letter); let mut lorry = order_pickup(); lorry.pickup(closed_envelope); } `lorry` dropped here impl Drop for PickupLorryHandle { fn drop(&mut self) { println!("sent"); } } impl PickupLorryHandle { pub fn done(self) { } …
  98. 3. ✔

  99. 1. 2. 3. ONLY ONCE CORRECT ORDER GUARANTEED “DROP” ✔

  100. 1. 2. 3. ONLY ONCE CORRECT ORDER GUARANTEED “DROP” ✔

  101. 1. 2. 3. ONLY ONCE CORRECT ORDER GUARANTEED “DROP” ✔

  102. 1. 2. 3. ONLY ONCE CORRECT ORDER GUARANTEED “DROP” ✔

  103. CORRECT ORDER LARGE NUMBER OF STATES ⇢MANY STRUCTS

  104. EXAMPLE HTTP RESPONSE

  105. pub struct HttpResponseWritingHeaders { /* connection, … */ } pub

    struct HttpResponseWritingBody { /* ... */ } pub fn start_response() -> HttpResponseWritingHeaders { /* ... */ } impl HttpResponseWritingHeaders { fn header(&mut self, header: Header) { /* ... */ } fn body(self) -> HttpResponseWritingBody { /* ... */ } } impl HttpResponseWritingBody { fn write(&mut self, chunk: Chunk) { /* ... */ } fn cease(self) { } } impl Drop for HttpResponseWritingBody { /* ... */ }
  106. pub struct HttpResponseWritingHeaders { /* connection, … */ } pub

    struct HttpResponseWritingBody { /* ... */ } pub fn start_response() -> HttpResponseWritingHeaders { /* ... */ } impl HttpResponseWritingHeaders { fn header(&mut self, header: Header) { /* ... */ } fn body(self) -> HttpResponseWritingBody { /* ... */ } } impl HttpResponseWritingBody { fn write(&mut self, chunk: Chunk) { /* ... */ } fn cease(self) { } } impl Drop for HttpResponseWritingBody { /* ... */ }
  107. pub struct HttpResponseWritingHeaders { /* connection, … */ } pub

    struct HttpResponseWritingBody { /* ... */ } pub fn start_response() -> HttpResponseWritingHeaders { /* ... */ } impl HttpResponseWritingHeaders { fn header(&mut self, header: Header) { /* ... */ } fn body(self) -> HttpResponseWritingBody { /* ... */ } } impl HttpResponseWritingBody { fn write(&mut self, chunk: Chunk) { /* ... */ } fn cease(self) { } } impl Drop for HttpResponseWritingBody { /* ... */ }
  108. pub struct HttpResponseWritingHeaders { /* connection, … */ } pub

    struct HttpResponseWritingBody { /* ... */ } pub fn start_response() -> HttpResponseWritingHeaders { /* ... */ } impl HttpResponseWritingHeaders { fn header(&mut self, header: Header) { /* ... */ } fn body(self) -> HttpResponseWritingBody { /* ... */ } } impl HttpResponseWritingBody { fn write(&mut self, chunk: Chunk) { /* ... */ } fn cease(self) { } } impl Drop for HttpResponseWritingBody { /* ... */ }
  109. pub struct HttpResponseWritingHeaders { /* connection, … */ } pub

    struct HttpResponseWritingBody { /* ... */ } pub fn start_response() -> HttpResponseWritingHeaders { /* ... */ } impl HttpResponseWritingHeaders { fn header(&mut self, header: Header) { /* ... */ } fn body(self) -> HttpResponseWritingBody { /* ... */ } } impl HttpResponseWritingBody { fn write(&mut self, chunk: Chunk) { /* ... */ } fn cease(self) { } } impl Drop for HttpResponseWritingBody { /* ... */ }
  110. pub struct HttpResponseWritingHeaders { /* connection, … */ } pub

    struct HttpResponseWritingBody { /* ... */ } pub fn start_response() -> HttpResponseWritingHeaders { /* ... */ } impl HttpResponseWritingHeaders { fn header(&mut self, header: Header) { /* ... */ } fn body(self) -> HttpResponseWritingBody { /* ... */ } } impl HttpResponseWritingBody { fn write(&mut self, chunk: Chunk) { /* ... */ } fn cease(self) { } } impl Drop for HttpResponseWritingBody { /* ... */ }
  111. pub struct HttpResponseWritingHeaders { /* connection, … */ } pub

    struct HttpResponseWritingBody { /* ... */ } pub fn start_response() -> HttpResponseWritingHeaders { /* ... */ } impl HttpResponseWritingHeaders { fn header(&mut self, header: Header) { /* ... */ } fn body(self) -> HttpResponseWritingBody { /* ... */ } } impl HttpResponseWritingBody { fn write(&mut self, chunk: Chunk) { /* ... */ } fn cease(self) { } } impl Drop for HttpResponseWritingBody { /* ... */ }
  112. pub struct HttpResponseWritingHeaders { /* connection, … */ } pub

    struct HttpResponseWritingBody { /* ... */ } pub fn start_response() -> HttpResponseWritingHeaders { /* ... */ } impl HttpResponseWritingHeaders { fn header(&mut self, header: Header) { /* ... */ } fn body(self) -> HttpResponseWritingBody { /* ... */ } } impl HttpResponseWritingBody { fn write(&mut self, chunk: Chunk) { /* ... */ } fn cease(self) { } } impl Drop for HttpResponseWritingBody { /* ... */ }
  113. pub struct HttpResponseWritingHeaders { /* connection, … */ } pub

    struct HttpResponseWritingBody { /* ... */ } pub fn start_response() -> HttpResponseWritingHeaders { /* ... */ } impl HttpResponseWritingHeaders { fn header(&mut self, header: Header) { /* ... */ } fn body(self) -> HttpResponseWritingBody { /* ... */ } } impl HttpResponseWritingBody { fn write(&mut self, chunk: Chunk) { /* ... */ } fn cease(self) { } } impl Drop for HttpResponseWritingBody { /* ... */ }
  114. pub struct HttpResponseWritingHeaders { /* connection, … */ } pub

    struct HttpResponseWritingBody { /* ... */ } pub fn start_response() -> HttpResponseWritingHeaders { /* ... */ } impl HttpResponseWritingHeaders { fn header(&mut self, header: Header) { /* ... */ } fn body(self) -> HttpResponseWritingBody { /* ... */ } } impl HttpResponseWritingBody { fn write(&mut self, chunk: Chunk) { /* ... */ } fn cease(self) { } } impl Drop for HttpResponseWritingBody { /* ... */ }
  115. EXAMPLE STREAMING ENGINE

  116. EXAMPLE STREAMING ENGINE time = 3 time = 4 “bolt”

  117. EXAMPLE STREAMING ENGINE time = 3 time = 4 “bolt”

  118. /// The capability to send data with a certain timestamp

    on a dataflow edge. pub struct Capability<T: Timestamp> { time: T, internal: Rc<RefCell<ChangeBatch<T>>>, } impl<T: Timestamp> Clone for Capability<T> { fn clone(&self) -> Capability<T> { // … update self.internal … } } impl<T: Timestamp> Drop for Capability<T> { fn drop(&mut self) { // … update self.internal … } } pub fn session(&mut self, cap: &Capability<T>) -> Handle time
  119. /// The capability to send data with a certain timestamp

    on a dataflow edge. pub struct Capability<T: Timestamp> { time: T, internal: Rc<RefCell<ChangeBatch<T>>>, } impl<T: Timestamp> Clone for Capability<T> { fn clone(&self) -> Capability<T> { // … update self.internal … } } impl<T: Timestamp> Drop for Capability<T> { fn drop(&mut self) { // … update self.internal … } } pub fn session(&mut self, cap: &Capability<T>) -> Handle time
  120. /// The capability to send data with a certain timestamp

    on a dataflow edge. pub struct Capability<T: Timestamp> { time: T, internal: Rc<RefCell<ChangeBatch<T>>>, } impl<T: Timestamp> Clone for Capability<T> { fn clone(&self) -> Capability<T> { // … update self.internal … } } impl<T: Timestamp> Drop for Capability<T> { fn drop(&mut self) { // … update self.internal … } } pub fn session(&mut self, cap: &Capability<T>) -> Handle time
  121. /// The capability to send data with a certain timestamp

    on a dataflow edge. pub struct Capability<T: Timestamp> { time: T, internal: Rc<RefCell<ChangeBatch<T>>>, } impl<T: Timestamp> Clone for Capability<T> { fn clone(&self) -> Capability<T> { // … update self.internal … } } impl<T: Timestamp> Drop for Capability<T> { fn drop(&mut self) { // … update self.internal … } } pub fn session(&mut self, cap: &Capability<T>) -> Handle time
  122. /// The capability to send data with a certain timestamp

    on a dataflow edge. pub struct Capability<T: Timestamp> { time: T, internal: Rc<RefCell<ChangeBatch<T>>>, } impl<T: Timestamp> Clone for Capability<T> { fn clone(&self) -> Capability<T> { // … update self.internal … } } impl<T: Timestamp> Drop for Capability<T> { fn drop(&mut self) { // … update self.internal … } } pub fn session(&mut self, cap: &Capability<T>) -> Handle time
  123. /// The capability to send data with a certain timestamp

    on a dataflow edge. pub struct Capability<T: Timestamp> { time: T, internal: Rc<RefCell<ChangeBatch<T>>>, } impl<T: Timestamp> Clone for Capability<T> { fn clone(&self) -> Capability<T> { // … update self.internal … } } impl<T: Timestamp> Drop for Capability<T> { fn drop(&mut self) { // … update self.internal … } } pub fn session(&mut self, cap: &Capability<T>) -> Handle time
  124. /// The capability to send data with a certain timestamp

    on a dataflow edge. pub struct Capability<T: Timestamp> { time: T, internal: Rc<RefCell<ChangeBatch<T>>>, } impl<T: Timestamp> Clone for Capability<T> { fn clone(&self) -> Capability<T> { // … update self.internal … } } impl<T: Timestamp> Drop for Capability<T> { fn drop(&mut self) { // … update self.internal … } } pub fn session(&mut self, cap: &Capability<T>) -> Handle time
  125. /// The capability to send data with a certain timestamp

    on a dataflow edge. pub struct Capability<T: Timestamp> { time: T, internal: Rc<RefCell<ChangeBatch<T>>>, } impl<T: Timestamp> Clone for Capability<T> { fn clone(&self) -> Capability<T> { // … update self.internal … } } impl<T: Timestamp> Drop for Capability<T> { fn drop(&mut self) { // … update self.internal … } } pub fn session(&mut self, cap: &Capability<T>) -> Handle time
  126. MY GROUP IS LOOKING FOR SOFTWARE ENGINEERS AND PHD STUDENTS

    WE WORK WITH RUST HTTPS://WWW.SYSTEMS.ETHZ.CH ANDREA LATTUADA @UTAAL ON TWITTER, GITHUB ANDREAL@INF.ETHZ.CH FRANK MCSHERRY, TIMELY DATAFLOW HTTPS://GITHUB.COM/FRANKMCSHERRY/TIMELY-DATAFLOW ANDREA LATTUADA, PROGRAMMABLE SCHEDULING IN A STREAM PROCESSING SYSTEM HTTPS://WWW.RESEARCH-COLLECTION.ETHZ.CH/HANDLE/20.500.11850/155664