Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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.

Andrea Lattuada

September 30, 2017
Tweet

More Decks by Andrea Lattuada

Other Decks in Programming

Transcript

  1. A HAMMER YOU CAN ONLY

    HOLD BY THE HANDLE
    ANDREA LATTUADA @UTAAL

    SYSTEMS GROUP, DEPT. OF COMPUTER SCIENCE

    ETH ZÜRICH

    View Slide

  2. API

    View Slide

  3. API

    View Slide

  4. API

    View Slide

  5. API

    View Slide

  6. API

    View Slide

  7. API

    View Slide

  8. API

    View Slide

  9. API

    View Slide

  10. API

    View Slide

  11. API

    View Slide

  12. API

    View Slide

  13. WE ARE MANAGING RESOURCES

    View Slide

  14. OWNERSHIP (LINEAR / AFFINE TYPES)

    View Slide

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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  20. DROP

    View Slide

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

    View Slide

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

    View Slide

  23. WE ARE STILL MANAGING RESOURCES
    IN HIGHER LEVEL APIS

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  28. #[derive(Clone)]
    pub struct Letter {
    text: String,
    }
    impl Letter {
    pub fn new(text: String) -> Self { Letter { text: text } }
    }

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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 */ }
    }

    View Slide

  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 */ }
    }

    View Slide

  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 */ }
    }

    View Slide

  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 */ }
    }

    View Slide

  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();
    }

    View Slide

  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();
    }

    View Slide

  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();
    }

    View Slide

  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();
    }

    View Slide

  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();
    }

    View Slide

  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();
    }

    View Slide

  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();
    }

    View Slide

  43. ?
    1.
    2.
    3.

    View Slide

  44. ?
    1.
    2.
    3.

    View Slide

  45. ?
    1.
    2.
    3.

    View Slide

  46. ?
    1.
    2.
    3.

    View Slide

  47. 1.

    View Slide

  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();
    }

    View Slide

  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();
    }

    View Slide

  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();
    }

    View Slide

  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();
    }

    View Slide

  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();
    }

    View Slide

  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,
    }

    View Slide

  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);
    }
    }

    View Slide

  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);
    }
    }

    View Slide

  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);
    }
    }

    View Slide

  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);
    }
    }

    View Slide

  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);
    }
    }

    View Slide

  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);
    }
    }

    View Slide

  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();
    }

    View Slide

  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

    View Slide

  62. 1.

    View Slide

  63. 2.

    View Slide

  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();

    View Slide

  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();

    View Slide

  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();

    View Slide

  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();

    View Slide

  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());
    }
    }

    View Slide

  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());

    View Slide

  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());

    View Slide

  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 { } }

    View Slide

  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 { } }

    View Slide

  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 { } }

    View Slide

  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 { } }

    View Slide

  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 { } }

    View Slide

  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 { } }

    View Slide

  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 { } }

    View Slide

  78. View Slide

  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();
    }

    View Slide

  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();
    }

    View Slide

  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();
    }

    View Slide

  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();
    }

    View Slide

  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();
    }

    View Slide

  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`

    View Slide

  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();
    }

    View Slide

  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();
    }

    View Slide

  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();
    }

    View Slide

  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();
    }

    View Slide

  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

    View Slide

  90. 2.

    View Slide

  91. ?
    3.

    View Slide

  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);
    }

    View Slide

  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);
    }

    View Slide

  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);
    }

    View Slide

  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);
    }

    View Slide

  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) { }

    View Slide

  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) { }

    View Slide

  98. 3. ✔

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  103. CORRECT ORDER
    LARGE NUMBER OF STATES ⇢MANY STRUCTS

    View Slide

  104. EXAMPLE HTTP RESPONSE

    View Slide

  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 { /* ... */ }

    View Slide

  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 { /* ... */ }

    View Slide

  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 { /* ... */ }

    View Slide

  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 { /* ... */ }

    View Slide

  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 { /* ... */ }

    View Slide

  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 { /* ... */ }

    View Slide

  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 { /* ... */ }

    View Slide

  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 { /* ... */ }

    View Slide

  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 { /* ... */ }

    View Slide

  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 { /* ... */ }

    View Slide

  115. EXAMPLE STREAMING ENGINE

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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
    [email protected]
    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

    View Slide