Electrolysis Reference

This document shows electrolysis's current coverage of the Rust Reference by testing the translation of code examples (taken from the Reference or made up on the spot). Some sections have been added on top of the Reference to display details and edge cases.

A ✔ means the translated Lean code type checks, whereas a ✗ marks unimplemented language features. A few examples also come with example Lean proofs that are also checked automatically and give greater assurance of semantics preservation.

Notation, Lexical structure, Syntax extensions

Well, that's what MIR is for.

5 Crates and source files [ref]

Skeleton code that surrounds each transpilation, which will be hidden in all further examples. The crate name ('test' in these examples) becomes the root namespace.

Files inside a crate may freely reference items between them. On the other hand, Lean files may only import other files non-recursively and declarations must be strictly sorted in order of usage for termination checking. We therefore translate a crate into a single Lean file and perform a topological sort on its items.

// this file intentionally left blank
import core.generated

noncomputable theory

open bool
open [class] classical
open [notation] function
open [class] int
open [notation] list
open [class] nat
open [notation] prod.ops
open [notation] unit

6 Items And Attributes [ref]

6.1 Items [ref]

6.1.2 Modules [ref]

Modules are translated to namespaces. extern crate and use directives are ignored, instead external theories are imported when some item of them is used.

mod foo {
    use std::cmp::Ordering;

    struct Bar(Ordering);
}
inductive test.foo.Bar :=
mk {} : (core.cmp.Ordering)  test.foo.Bar

6.1.3 Functions [ref]

Rust fns are translated to curried definitions. The return type is wrapped in a semantics monad, which in the simplest case is option for modelling nontermination. The proofs unwrap it using sem.terminates_with h x, which asserts that x terminates and that the predicate h holds on the return value.

fn add(x: i32, y: i32) -> i32 {
    x + y
}

fn first((value, _): (i32, i32)) -> i32 { value }
fn first(_1: (i32, i32)) -> i32 {
    let mut _0: i32;                     // return pointer
    scope 1 {
        let _2: i32;                     // "value" in scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/lib.rs:5:11: 5:16
    }
    let mut _3: i32;

    bb0: {
        StorageLive(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/lib.rs:5:11: 5:16
        _2 = (_1.0: i32);                // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/lib.rs:5:11: 5:16
        StorageLive(_3);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/lib.rs:5:43: 5:48
        _3 = _2;                         // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/lib.rs:5:43: 5:48
        _0 = _3;                         // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/lib.rs:5:43: 5:48
        StorageDead(_3);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/lib.rs:5:50: 5:50
        StorageDead(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/lib.rs:5:50: 5:50
        return;                          // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/lib.rs:5:50: 5:50
    }
}

fn add(_1: i32, _2: i32) -> i32 {
    let mut _0: i32;                     // return pointer
    scope 1 {
        let _3: i32;                     // "x" in scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/lib.rs:1:8: 1:9
        let _4: i32;                     // "y" in scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/lib.rs:1:16: 1:17
    }
    let mut _5: i32;
    let mut _6: i32;
    let mut _7: (i32, bool);

    bb0: {
        StorageLive(_3);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/lib.rs:1:8: 1:9
        _3 = _1;                         // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/lib.rs:1:8: 1:9
        StorageLive(_4);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/lib.rs:1:16: 1:17
        _4 = _2;                         // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/lib.rs:1:16: 1:17
        StorageLive(_5);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/lib.rs:2:5: 2:6
        _5 = _3;                         // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/lib.rs:2:5: 2:6
        StorageLive(_6);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/lib.rs:2:9: 2:10
        _6 = _4;                         // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/lib.rs:2:9: 2:10
        _7 = CheckedAdd(_5, _6);         // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/lib.rs:2:5: 2:10
        assert(!(_7.1: bool), "attempt to add with overflow") -> bb1; // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/lib.rs:2:5: 2:10
    }

    bb1: {
        _0 = (_7.0: i32);                // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/lib.rs:2:5: 2:10
        StorageDead(_6);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/lib.rs:3:2: 3:2
        StorageDead(_5);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/lib.rs:3:2: 3:2
        StorageDead(_4);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/lib.rs:3:2: 3:2
        StorageDead(_3);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/lib.rs:3:2: 3:2
        return;                          // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/lib.rs:3:2: 3:2
    }
}
definition test.add (xₐ : i32) (yₐ : i32) : sem (i32) :=
let' «x$3»  xₐ;
let' «y$4»  yₐ;
let' t5  «x$3»;
let' t6  «y$4»;
do «$tmp0»  sem.map (λx, (x, tt)) (checked.sadd i32.bits t5 t6);
let' t7  «$tmp0»;
let' ret  t7.1;
return (ret)


definition test.first («$a1» : (i32 × i32)) : sem (i32) :=
let' «value$2»  «$a1».1;
let' t3  «value$2»;
let' ret  t3;
return (ret)
example (x y : i32) [is_i32 (x + y)] : sem.terminates_with (λ sum, x + y = sum) (test.add x y) :=
by rewrite [test.add, if_pos `is_i32 (x + y)`, ▸*]

example (x y : i32) : sem.terminates_with (λ z, z = x) (test.first (x, y)) :=
rfl

6.1.3.1 Generic functions [ref]

fn foo<A, B>(x: A, y: B) {}
fn foo(_1: A, _2: B) -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let _3: A;                       // "x" in scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/1/lib.rs:1:14: 1:15
        let _4: B;                       // "y" in scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/1/lib.rs:1:20: 1:21
    }
    let mut _5: ();

    bb0: {
        StorageLive(_3);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/1/lib.rs:1:14: 1:15
        _3 = _1;                         // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/1/lib.rs:1:14: 1:15
        StorageLive(_4);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/1/lib.rs:1:20: 1:21
        _4 = _2;                         // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/1/lib.rs:1:20: 1:21
        _0 = ();                         // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/1/lib.rs:1:26: 1:28
        drop(_2) -> [return: bb5, unwind: bb4]; // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/1/lib.rs:1:28: 1:28
    }

    bb1: {
        resume;                          // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/1/lib.rs:1:1: 1:28
    }

    bb2: {
        drop(_3) -> bb1;                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/1/lib.rs:1:28: 1:28
    }

    bb3: {
        drop(_1) -> bb2;                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/1/lib.rs:1:28: 1:28
    }

    bb4: {
        drop(_4) -> bb3;                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/1/lib.rs:1:28: 1:28
    }

    bb5: {
        drop(_4) -> [return: bb6, unwind: bb3]; // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/1/lib.rs:1:28: 1:28
    }

    bb6: {
        StorageDead(_4);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/1/lib.rs:1:28: 1:28
        drop(_1) -> [return: bb7, unwind: bb2]; // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/1/lib.rs:1:28: 1:28
    }

    bb7: {
        drop(_3) -> bb8;                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/1/lib.rs:1:28: 1:28
    }

    bb8: {
        StorageDead(_3);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/1/lib.rs:1:28: 1:28
        return;                          // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/1/lib.rs:1:28: 1:28
    }
}
definition test.foo {A : Type₁} {B : Type₁} (xₐ : A) (yₐ : B) : sem (unit) :=
let' «x$3»  xₐ;
let' «y$4»  yₐ;
let' ret  ;
return ()
fn foo<T>(x: &[T]) where T: Default {}

fn main() { foo(&[1, 2]); }
fn main() -> () {
    let mut _0: ();                      // return pointer
    let mut _1: ();
    let mut _2: &[i32];
    let mut _3: &[i32; 2];
    let mut _4: &[i32; 2];
    let mut _5: [i32; 2];

    bb0: {
        StorageLive(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/2/lib.rs:3:17: 3:24
        StorageLive(_3);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/2/lib.rs:3:17: 3:24
        StorageLive(_4);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/2/lib.rs:3:17: 3:24
        _4 = promoted0;                  // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/2/lib.rs:3:17: 3:24
        _3 = &(*_4);                     // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/2/lib.rs:3:17: 3:24
        _2 = _3 as &[i32] (Unsize);      // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/2/lib.rs:3:17: 3:24
        _1 = foo::<i32>(_2) -> bb1;      // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/2/lib.rs:3:13: 3:25
    }

    bb1: {
        StorageDead(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/2/lib.rs:3:26: 3:26
        StorageDead(_3);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/2/lib.rs:3:26: 3:26
        StorageDead(_4);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/2/lib.rs:3:26: 3:26
        _0 = ();                         // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/2/lib.rs:3:11: 3:28
        return;                          // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/2/lib.rs:3:28: 3:28
    }
}

promoted0 in main: &[i32; 2] = {
    let mut _0: &[i32; 2];               // return pointer
    let mut _1: [i32; 2];

    bb0: {
        _1 = [const 1i32, const 2i32];   // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/2/lib.rs:3:18: 3:24
        _0 = &_1;                        // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/2/lib.rs:3:17: 3:24
        return;                          // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/2/lib.rs:3:17: 3:24
    }
}

fn foo(_1: &[T]) -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let _2: &[T];                    // "x" in scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/2/lib.rs:1:11: 1:12
    }

    bb0: {
        StorageLive(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/2/lib.rs:1:11: 1:12
        _2 = _1;                         // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/2/lib.rs:1:11: 1:12
        _0 = ();                         // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/2/lib.rs:1:37: 1:39
        StorageDead(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/2/lib.rs:1:39: 1:39
        return;                          // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.1 Generic functions/2/lib.rs:1:39: 1:39
    }
}
definition test.foo {T : Type₁} [«core.default.Default T» : core.default.Default T] (xₐ : (slice T)) : sem (unit) :=
let' «x$2»  xₐ;
let' ret  ;
return ()


definition test.main : sem (unit) :=
do promoted_0 
let' t1  [(1 : int), (2 : int)];
let' ret  t1;
return (ret)
;
let' t4  promoted_0;
let' t3  t4;
let' t2  t3;
dostep «$tmp»  @test.foo i32 (@core.«i32 as core.default.Default») t2;
let' t1  «$tmp»;
let' ret  ;
return ()

6.1.3.2 Diverging functions [ref]

Divergence is represented as MonadZero.mzero (in the simplest case, none). Because MIR distinguishes between normal and divergent control flow, calls to diverging functions are eagerly replaced by mzero (which of course only works because of the absence of side effects).

fn my_err(s: &str) -> ! {
    //println!("{}", s);
    panic!();
}

fn f(i: i32) -> i32 {
    if i == 42 {
        return 42;
    }
    else {
        my_err("Bad number!");
    }
}
static my_err::_FILE_LINE: (&'static str, u32) = {
    let mut _0: (&'static str, u32);     // return pointer

    bb0: {
        _0 = (const "ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.2 Diverging functions/lib.rs", const 3u32); // scope 0 at <panic macros>:5:47: 5:76
        return;                          // scope 0 at <panic macros>:5:1: 5:78
    }
}

fn my_err(_1: &str) -> ! {
    let mut _0: !;                       // return pointer
    scope 1 {
        let _2: &str;                    // "s" in scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.2 Diverging functions/lib.rs:1:11: 1:12
    }
    let mut _3: ();
    let mut _4: !;
    let mut _5: &(&'static str, u32);
    let mut _6: &(&'static str, u32);

    bb0: {
        StorageLive(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.2 Diverging functions/lib.rs:1:11: 1:12
        _2 = _1;                         // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.2 Diverging functions/lib.rs:1:11: 1:12
        StorageLive(_4);                 // scope 1 at <panic macros>:3:1: 6:17
        StorageLive(_5);                 // scope 1 at <panic macros>:4:9: 6:15
        StorageLive(_6);                 // scope 1 at <panic macros>:6:1: 6:13
        _6 = &my_err::_FILE_LINE;        // scope 1 at <panic macros>:6:1: 6:13
        _5 = &(*_6);                     // scope 1 at <panic macros>:6:1: 6:13
        std::rt::begin_panic::<&'static str>(const "explicit panic", _5); // scope 1 at <panic macros>:3:1: 6:17
    }
}

fn f(_1: i32) -> i32 {
    let mut _0: i32;                     // return pointer
    scope 1 {
        let _2: i32;                     // "i" in scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.2 Diverging functions/lib.rs:6:6: 6:7
    }
    let mut _3: bool;
    let mut _4: i32;
    let mut _5: ();
    let mut _6: !;
    let mut _7: ();
    let mut _8: ();
    let mut _9: !;
    let mut _10: &str;
    let mut _11: &'static str;

    bb0: {
        StorageLive(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.2 Diverging functions/lib.rs:6:6: 6:7
        _2 = _1;                         // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.2 Diverging functions/lib.rs:6:6: 6:7
        StorageLive(_3);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.2 Diverging functions/lib.rs:7:8: 7:15
        StorageLive(_4);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.2 Diverging functions/lib.rs:7:8: 7:9
        _4 = _2;                         // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.2 Diverging functions/lib.rs:7:8: 7:9
        _3 = Eq(_4, const 42i32);        // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.2 Diverging functions/lib.rs:7:8: 7:15
        StorageDead(_3);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.2 Diverging functions/lib.rs:7:15: 7:15
        StorageDead(_4);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.2 Diverging functions/lib.rs:7:15: 7:15
        if(_3) -> [true: bb1, false: bb2]; // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.2 Diverging functions/lib.rs:7:5: 12:6
    }

    bb1: {
        StorageLive(_6);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.2 Diverging functions/lib.rs:8:9: 8:18
        _0 = const 42i32;                // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.2 Diverging functions/lib.rs:8:16: 8:18
        StorageDead(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.2 Diverging functions/lib.rs:13:2: 13:2
        return;                          // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.2 Diverging functions/lib.rs:13:2: 13:2
    }

    bb2: {
        StorageLive(_9);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.2 Diverging functions/lib.rs:11:9: 11:30
        StorageLive(_10);                // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.2 Diverging functions/lib.rs:11:16: 11:29
        StorageLive(_11);                // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.2 Diverging functions/lib.rs:11:16: 11:29
        _11 = const "Bad number!";       // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.2 Diverging functions/lib.rs:11:16: 11:29
        _10 = &(*_11);                   // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.2 Diverging functions/lib.rs:11:16: 11:29
        my_err(_10);                     // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.2 Diverging functions/lib.rs:11:9: 11:30
    }
}
definition test.my_err.«$_FILE_LINE» : sem (string × u32) :=
let' ret  ("ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/6.1.3.2 Diverging functions/lib.rs", (3 : nat));
return (ret)


definition test.my_err (sₐ : string) : sem (empty) :=
let' «s$2»  sₐ;
let' t6  test.my_err.«$_FILE_LINE»;
let' t5  t6;
mzero


definition test.f (iₐ : i32) : sem (i32) :=
let' «i$2»  iₐ;
let' t4  «i$2»;
let' t3  t4 = (42 : int);
if t3 = bool.tt then
let' ret  (42 : int);
return (ret)
else
let' t11  "Bad number!";
let' t10  t11;
mzero

Returning mutable reference to first argument

For now, we assume that mutable reference return values will always point into the first argument. Then the return value can be represented as a lens on that argument. We immediately probe the new lens in order to catch out-of-bounds borrows eagerly.

fn foo(xs: &mut [i32]) -> &mut i32 {
    &mut xs[0]
}
fn foo(_1: &mut [i32]) -> &mut i32 {
    let mut _0: &mut i32;                // return pointer
    scope 1 {
        let _2: &mut [i32];              // "xs" in scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/7 Returning mutable reference to first argument./lib.rs:1:8: 1:10
    }
    let mut _3: &mut i32;
    let mut _4: &mut i32;
    let mut _5: usize;
    let mut _6: bool;

    bb0: {
        StorageLive(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/7 Returning mutable reference to first argument./lib.rs:1:8: 1:10
        _2 = _1;                         // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/7 Returning mutable reference to first argument./lib.rs:1:8: 1:10
        StorageLive(_3);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/7 Returning mutable reference to first argument./lib.rs:1:36: 3:2
        StorageLive(_4);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/7 Returning mutable reference to first argument./lib.rs:2:5: 2:15
        _5 = Len((*_2));                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/7 Returning mutable reference to first argument./lib.rs:2:10: 2:15
        _6 = Lt(const 0usize, _5);       // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/7 Returning mutable reference to first argument./lib.rs:2:10: 2:15
        assert(_6, "index out of bounds: the len is {} but the index is {}", _5, const 0usize) -> bb1; // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/7 Returning mutable reference to first argument./lib.rs:2:10: 2:15
    }

    bb1: {
        _4 = &mut (*_2)[const 0usize];   // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/7 Returning mutable reference to first argument./lib.rs:2:5: 2:15
        _3 = &mut (*_4);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/7 Returning mutable reference to first argument./lib.rs:2:5: 2:15
        _0 = &mut (*_3);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/7 Returning mutable reference to first argument./lib.rs:1:36: 3:2
        StorageDead(_3);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/7 Returning mutable reference to first argument./lib.rs:3:2: 3:2
        StorageDead(_4);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/7 Returning mutable reference to first argument./lib.rs:3:2: 3:2
        StorageDead(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/7 Returning mutable reference to first argument./lib.rs:3:2: 3:2
        return;                          // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/7 Returning mutable reference to first argument./lib.rs:3:2: 3:2
    }
}
definition test.foo (xsₐ : (slice i32)) : sem ((lens (slice i32) i32) × (slice i32)) :=
let' «xs$2»  @lens.id (slice i32);
do «$tmp0»  do «$tmp0»  lens.get «xs$2» xsₐ;
return (list.length «$tmp0»);
let' t5  «$tmp0»;
let' t6  (0 : nat) < t5;
let' t4  (lens.index _ (0 : nat)  «xs$2»);
do «$tmp»  lens.get t4 xsₐ;
let' t3  (t4);
do «$tmp»  lens.get t3 xsₐ;
let' ret  (t3);
do «$tmp»  lens.get ret xsₐ;
return (ret, xsₐ)
example (x y : i32) : sem.terminates_with (λ r, lens.get r.1 [x, y] = return x) (test.foo [x, y]) := rfl

Returning arbitrary mutable references

In general, we would have to return a sum type of lenses that represents which argument the return value points into. The callee would then match on the sum and combine the return value with the corresponding argument lens.

fn foo<'a>(x: &'a mut i32, y: &'a mut i32) -> &'a mut i32 {
    if *x > 0 { x } else { y }
}
fn foo(_1: &'a mut i32, _2: &'a mut i32) -> &'a mut i32 {
    let mut _0: &'a mut i32;             // return pointer
    scope 1 {
        let _3: &'a mut i32;             // "x" in scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/8 Returning arbitrary mutable references./lib.rs:1:12: 1:13
        let _4: &'a mut i32;             // "y" in scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/8 Returning arbitrary mutable references./lib.rs:1:28: 1:29
    }
    let mut _5: &'a mut i32;
    let mut _6: &'a mut i32;
    let mut _7: bool;
    let mut _8: i32;
    let mut _9: &'a mut i32;

    bb0: {
        StorageLive(_3);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/8 Returning arbitrary mutable references./lib.rs:1:12: 1:13
        _3 = _1;                         // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/8 Returning arbitrary mutable references./lib.rs:1:12: 1:13
        StorageLive(_4);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/8 Returning arbitrary mutable references./lib.rs:1:28: 1:29
        _4 = _2;                         // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/8 Returning arbitrary mutable references./lib.rs:1:28: 1:29
        StorageLive(_5);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/8 Returning arbitrary mutable references./lib.rs:1:59: 3:2
        StorageLive(_6);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/8 Returning arbitrary mutable references./lib.rs:2:5: 2:31
        StorageLive(_7);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/8 Returning arbitrary mutable references./lib.rs:2:8: 2:14
        StorageLive(_8);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/8 Returning arbitrary mutable references./lib.rs:2:8: 2:10
        _8 = (*_3);                      // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/8 Returning arbitrary mutable references./lib.rs:2:8: 2:10
        _7 = Gt(_8, const 0i32);         // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/8 Returning arbitrary mutable references./lib.rs:2:8: 2:14
        StorageDead(_7);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/8 Returning arbitrary mutable references./lib.rs:2:14: 2:14
        StorageDead(_8);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/8 Returning arbitrary mutable references./lib.rs:2:14: 2:14
        if(_7) -> [true: bb1, false: bb2]; // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/8 Returning arbitrary mutable references./lib.rs:2:5: 2:31
    }

    bb1: {
        _6 = &mut (*_3);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/8 Returning arbitrary mutable references./lib.rs:2:17: 2:18
        goto -> bb3;                     // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/8 Returning arbitrary mutable references./lib.rs:2:5: 2:31
    }

    bb2: {
        StorageLive(_9);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/8 Returning arbitrary mutable references./lib.rs:2:26: 2:31
        _9 = &mut (*_4);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/8 Returning arbitrary mutable references./lib.rs:2:28: 2:29
        _6 = &mut (*_9);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/8 Returning arbitrary mutable references./lib.rs:2:26: 2:31
        StorageDead(_9);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/8 Returning arbitrary mutable references./lib.rs:2:31: 2:31
        goto -> bb3;                     // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/8 Returning arbitrary mutable references./lib.rs:2:5: 2:31
    }

    bb3: {
        _5 = &mut (*_6);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/8 Returning arbitrary mutable references./lib.rs:2:5: 2:31
        _0 = &mut (*_5);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/8 Returning arbitrary mutable references./lib.rs:1:59: 3:2
        StorageDead(_5);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/8 Returning arbitrary mutable references./lib.rs:3:2: 3:2
        StorageDead(_6);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/8 Returning arbitrary mutable references./lib.rs:3:2: 3:2
        StorageDead(_4);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/8 Returning arbitrary mutable references./lib.rs:3:2: 3:2
        StorageDead(_3);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/8 Returning arbitrary mutable references./lib.rs:3:2: 3:2
        return;                          // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.3 Functions/8 Returning arbitrary mutable references./lib.rs:3:2: 3:2
    }
}
/- test.foo: unimplemented: returning mutable reference to argument other than the first -/

6.1.4 Type aliases [ref]

type Point = (u8, u8);
const p: Point = (41, 68);
const p: (u8, u8) = {
    let mut _0: (u8, u8);                // return pointer

    bb0: {
        _0 = (const 41u8, const 68u8);   // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.4 Type aliases/lib.rs:2:18: 2:26
        return;                          // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.4 Type aliases/lib.rs:2:1: 2:27
    }
}
definition test.Point := (u8 × u8)

definition test.p : sem (u8 × u8) :=
let' ret  ((41 : nat), (68 : nat));
return (ret)

6.1.5 Structs [ref]

While MIR prevents us from having to support three different loop constructs, it doesn't help with having to support three different struct constructs.

struct Point {x: i32, y: i32}

fn main() {
    let p = Point {x: 10, y: 11};
    let px: i32 = p.x;
}
fn main() -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let _1: Point;                   // "p" in scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/1/lib.rs:4:9: 4:10
        scope 2 {
            let _2: i32;                 // "px" in scope 2 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/1/lib.rs:5:9: 5:11
        }
    }
    let mut _3: i32;

    bb0: {
        StorageLive(_1);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/1/lib.rs:4:9: 4:10
        _1 = Point { x: const 10i32, y: const 11i32 }; // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/1/lib.rs:4:13: 4:33
        StorageLive(_2);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/1/lib.rs:5:9: 5:11
        StorageLive(_3);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/1/lib.rs:5:19: 5:22
        _3 = (_1.0: i32);                // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/1/lib.rs:5:19: 5:22
        _2 = _3;                         // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/1/lib.rs:5:19: 5:22
        StorageDead(_3);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/1/lib.rs:5:23: 5:23
        _0 = ();                         // scope 2 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/1/lib.rs:3:11: 6:2
        StorageDead(_2);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/1/lib.rs:6:2: 6:2
        StorageDead(_1);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/1/lib.rs:6:2: 6:2
        return;                          // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/1/lib.rs:6:2: 6:2
    }
}
structure test.Point := mk {} ::
(x : i32)
(y : i32)

definition test.main : sem (unit) :=
let' «p$1»  test.Point.mk (10 : int) (11 : int);
let' t3  (test.Point.x «p$1»);
let' «px$2»  t3;
let' ret  ;
return ()
struct Point(i32, i32);

fn main() {
    let p = Point(10, 11);
    let px: i32 = match p { Point(x, _) => x };
}
fn main() -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let _1: Point;                   // "p" in scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/2/lib.rs:4:9: 4:10
        scope 2 {
            let _2: i32;                 // "px" in scope 2 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/2/lib.rs:5:9: 5:11
        }
        scope 3 {
            let _3: i32;                 // "x" in scope 3 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/2/lib.rs:5:35: 5:36
        }
    }
    let mut _4: i32;

    bb0: {
        StorageLive(_1);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/2/lib.rs:4:9: 4:10
        _1 = Point::{{constructor}}(const 10i32, const 11i32); // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/2/lib.rs:4:13: 4:26
        StorageLive(_2);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/2/lib.rs:5:9: 5:11
        StorageLive(_3);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/2/lib.rs:5:35: 5:36
        _3 = (_1.0: i32);                // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/2/lib.rs:5:35: 5:36
        StorageLive(_4);                 // scope 3 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/2/lib.rs:5:44: 5:45
        _4 = _3;                         // scope 3 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/2/lib.rs:5:44: 5:45
        _2 = _4;                         // scope 3 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/2/lib.rs:5:44: 5:45
        StorageDead(_4);                 // scope 3 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/2/lib.rs:5:45: 5:45
        StorageDead(_3);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/2/lib.rs:5:47: 5:47
        _0 = ();                         // scope 2 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/2/lib.rs:3:11: 6:2
        StorageDead(_2);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/2/lib.rs:6:2: 6:2
        StorageDead(_1);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/2/lib.rs:6:2: 6:2
        return;                          // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/2/lib.rs:6:2: 6:2
    }
}
inductive test.Point :=
mk {} : i32  i32  test.Point

definition test.main : sem (unit) :=
let' «p$1»  test.Point.mk (10 : int) (11 : int);
let' «x$3»  match «p$1» with test.Point.mk x0 x1 := x0 end;
let' t4  «x$3»;
let' «px$2»  t4;
let' ret  ;
return ()
struct Cookie;

fn main() {
    let c = [Cookie, Cookie {}, Cookie, Cookie {}];
}
fn main() -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let _1: [Cookie; 4];             // "c" in scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/3/lib.rs:4:9: 4:10
    }
    let mut _2: Cookie;
    let mut _3: Cookie;
    let mut _4: Cookie;
    let mut _5: Cookie;

    bb0: {
        StorageLive(_1);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/3/lib.rs:4:9: 4:10
        StorageLive(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/3/lib.rs:4:14: 4:20
        _2 = Cookie::{{constructor}};    // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/3/lib.rs:4:14: 4:20
        StorageLive(_3);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/3/lib.rs:4:22: 4:31
        _3 = Cookie::{{constructor}};    // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/3/lib.rs:4:22: 4:31
        StorageLive(_4);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/3/lib.rs:4:33: 4:39
        _4 = Cookie::{{constructor}};    // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/3/lib.rs:4:33: 4:39
        StorageLive(_5);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/3/lib.rs:4:41: 4:50
        _5 = Cookie::{{constructor}};    // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/3/lib.rs:4:41: 4:50
        _1 = [_2, _3, _4, _5];           // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/3/lib.rs:4:13: 4:51
        StorageDead(_5);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/3/lib.rs:4:52: 4:52
        StorageDead(_4);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/3/lib.rs:4:52: 4:52
        StorageDead(_3);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/3/lib.rs:4:52: 4:52
        StorageDead(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/3/lib.rs:4:52: 4:52
        _0 = ();                         // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/3/lib.rs:3:11: 5:2
        StorageDead(_1);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/3/lib.rs:5:2: 5:2
        return;                          // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.5 Structs/3/lib.rs:5:2: 5:2
    }
}
structure test.Cookie := mk {} ::

definition test.main : sem (unit) :=
let' t2  test.Cookie.mk;
let' t3  test.Cookie.mk;
let' t4  test.Cookie.mk;
let' t5  test.Cookie.mk;
let' «c$1»  [t2, t3, t4, t5];
let' ret  ;
return ()

6.1.6 Enumerations [ref]

enum Animal {
    Dog,
    Cat,
}

fn main() {
    let mut a: Animal = Animal::Dog;
    a = Animal::Cat;
}
fn main() -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let mut _1: Animal;              // "a" in scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.6 Enumerations/1/lib.rs:7:9: 7:14
    }

    bb0: {
        StorageLive(_1);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.6 Enumerations/1/lib.rs:7:9: 7:14
        _1 = Animal::Dog;                // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.6 Enumerations/1/lib.rs:7:25: 7:36
        _1 = Animal::Cat;                // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.6 Enumerations/1/lib.rs:8:5: 8:20
        _0 = ();                         // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.6 Enumerations/1/lib.rs:6:11: 9:2
        StorageDead(_1);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.6 Enumerations/1/lib.rs:9:2: 9:2
        return;                          // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.6 Enumerations/1/lib.rs:9:2: 9:2
    }
}
inductive test.Animal :=
| Dog {} : test.Animal
| Cat {} : test.Animal

definition test.Animal.discr (self : test.Animal) : isize := match self with
| test.Animal.Dog := 0
| test.Animal.Cat := 1
end

definition test.main : sem (unit) :=
let' «a$1»  test.Animal.Dog;
let' «a$1»  test.Animal.Cat;
let' ret  ;
return ()

Struct-like enum variants

struct Name;

enum Animal {
    Dog (Name, u32),
    Cat { name: Name, weight: u32 },
}

fn main() {
    let mut a: Animal = Animal::Dog(Name, 37);
    a = Animal::Cat { name: Name, weight: 2 };
}
fn main() -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let mut _1: Animal;              // "a" in scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.6 Enumerations/1 Struct-like enum variants./lib.rs:9:9: 9:14
    }
    let mut _2: Name;
    let mut _3: Name;

    bb0: {
        StorageLive(_1);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.6 Enumerations/1 Struct-like enum variants./lib.rs:9:9: 9:14
        StorageLive(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.6 Enumerations/1 Struct-like enum variants./lib.rs:9:37: 9:41
        _2 = Name::{{constructor}};      // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.6 Enumerations/1 Struct-like enum variants./lib.rs:9:37: 9:41
        _1 = Animal::Dog(_2, const 37u32); // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.6 Enumerations/1 Struct-like enum variants./lib.rs:9:25: 9:46
        StorageDead(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.6 Enumerations/1 Struct-like enum variants./lib.rs:9:47: 9:47
        StorageLive(_3);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.6 Enumerations/1 Struct-like enum variants./lib.rs:10:29: 10:33
        _3 = Name::{{constructor}};      // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.6 Enumerations/1 Struct-like enum variants./lib.rs:10:29: 10:33
        _1 = Animal::Cat { name: _3, weight: const 2u32 }; // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.6 Enumerations/1 Struct-like enum variants./lib.rs:10:5: 10:46
        StorageDead(_3);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.6 Enumerations/1 Struct-like enum variants./lib.rs:10:47: 10:47
        _0 = ();                         // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.6 Enumerations/1 Struct-like enum variants./lib.rs:8:11: 11:2
        StorageDead(_1);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.6 Enumerations/1 Struct-like enum variants./lib.rs:11:2: 11:2
        return;                          // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.6 Enumerations/1 Struct-like enum variants./lib.rs:11:2: 11:2
    }
}
structure test.Name := mk {} ::

structure test.Animal.Cat.struct := mk {} ::
(name : (test.Name))
(weight : u32)

inductive test.Animal :=
| Dog {} : (test.Name)  u32  test.Animal
| Cat {} : test.Animal.Cat.struct  test.Animal

definition test.main : sem (unit) :=
let' t2  test.Name.mk;
let' «a$1»  test.Animal.Dog t2 (37 : nat);
let' t3  test.Name.mk;
let' «a$1»  test.Animal.Cat (test.Animal.Cat.struct.mk t3 (2 : nat));
let' ret  ;
return ()

Enum discriminants

enum Foo {
    Bar = 123,
}

fn main() {
    let x = Foo::Bar as u32; // x is now 123u32
}
fn main() -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let _1: u32;                     // "x" in scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.6 Enumerations/2 Enum discriminants./lib.rs:6:9: 6:10
    }
    let mut _2: Foo;

    bb0: {
        StorageLive(_1);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.6 Enumerations/2 Enum discriminants./lib.rs:6:9: 6:10
        StorageLive(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.6 Enumerations/2 Enum discriminants./lib.rs:6:13: 6:21
        _2 = Foo::Bar;                   // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.6 Enumerations/2 Enum discriminants./lib.rs:6:13: 6:21
        _1 = _2 as u32 (Misc);           // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.6 Enumerations/2 Enum discriminants./lib.rs:6:13: 6:28
        StorageDead(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.6 Enumerations/2 Enum discriminants./lib.rs:6:29: 6:29
        _0 = ();                         // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.6 Enumerations/2 Enum discriminants./lib.rs:5:11: 7:2
        StorageDead(_1);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.6 Enumerations/2 Enum discriminants./lib.rs:7:2: 7:2
        return;                          // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.6 Enumerations/2 Enum discriminants./lib.rs:7:2: 7:2
    }
}

const Foo::Bar::{{initializer}}: isize = {
    let mut _0: isize;                   // return pointer

    bb0: {
        _0 = const 123isize;             // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.6 Enumerations/2 Enum discriminants./lib.rs:2:11: 2:14
        return;                          // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.6 Enumerations/2 Enum discriminants./lib.rs:2:11: 2:14
    }
}
inductive test.Foo :=
| Bar {} : test.Foo

definition test.Foo.discr (self : test.Foo) : isize := match self with
| test.Foo.Bar := 123
end

definition test.main : sem (unit) :=
let' t2  test.Foo.Bar;
do «$tmp0»  (signed_to_unsigned u32.bits (test.Foo.discr t2));
let' «x$1»  «$tmp0»;
let' ret  ;
return ()

6.1.7 Constant items [ref]

Constants are fun: If you want to be system-independent, expressions like usize::MAX + 1 or 1usize << 33 suddenly are not so constant any more. Therefore, we wrap them in the semantics burrito monad.

const BIT1: u32 = 1 << 0;
const BIT2: u32 = 1 << 1;

const BITS: [u32; 2] = [BIT1, BIT2];
const STRING: &'static str = "bitstring";

struct BitsNStrings<'a> {
    mybits: [u32; 2],
    mystring: &'a str,
}

const BITS_N_STRINGS: BitsNStrings<'static> = BitsNStrings {
    mybits: BITS,
    mystring: STRING,
};
const BITS_N_STRINGS: BitsNStrings<'static> = {
    let mut _0: BitsNStrings<'static>;   // return pointer
    let mut _1: &'static str;
    let mut _2: &'static str;

    bb0: {
        _2 = STRING;                     // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.7 Constant items/1/lib.rs:14:15: 14:21
        _1 = &(*_2);                     // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.7 Constant items/1/lib.rs:14:15: 14:21
        _0 = BitsNStrings<'static> { mybits: BITS, mystring: _1 }; // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.7 Constant items/1/lib.rs:12:47: 15:2
        return;                          // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.7 Constant items/1/lib.rs:12:1: 15:3
    }
}

const STRING: &'static str = {
    let mut _0: &'static str;            // return pointer

    bb0: {
        _0 = const "bitstring";          // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.7 Constant items/1/lib.rs:5:30: 5:41
        return;                          // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.7 Constant items/1/lib.rs:5:1: 5:42
    }
}

const BIT2: u32 = {
    let mut _0: u32;                     // return pointer
    let mut _1: (u32, bool);

    bb0: {
        _1 = CheckedShl(const 1u32, const 1i32); // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.7 Constant items/1/lib.rs:2:19: 2:25
        assert(!(_1.1: bool), "attempt to shift left with overflow") -> bb1; // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.7 Constant items/1/lib.rs:2:19: 2:25
    }

    bb1: {
        _0 = (_1.0: u32);                // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.7 Constant items/1/lib.rs:2:19: 2:25
        return;                          // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.7 Constant items/1/lib.rs:2:1: 2:26
    }
}

const BitsNStrings::{{initializer}}: usize = {
    let mut _0: usize;                   // return pointer

    bb0: {
        _0 = const 2usize;               // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.7 Constant items/1/lib.rs:8:19: 8:20
        return;                          // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.7 Constant items/1/lib.rs:8:19: 8:20
    }
}

const BITS::{{initializer}}: usize = {
    let mut _0: usize;                   // return pointer

    bb0: {
        _0 = const 2usize;               // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.7 Constant items/1/lib.rs:4:19: 4:20
        return;                          // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.7 Constant items/1/lib.rs:4:19: 4:20
    }
}

const BIT1: u32 = {
    let mut _0: u32;                     // return pointer
    let mut _1: (u32, bool);

    bb0: {
        _1 = CheckedShl(const 1u32, const 0i32); // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.7 Constant items/1/lib.rs:1:19: 1:25
        assert(!(_1.1: bool), "attempt to shift left with overflow") -> bb1; // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.7 Constant items/1/lib.rs:1:19: 1:25
    }

    bb1: {
        _0 = (_1.0: u32);                // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.7 Constant items/1/lib.rs:1:19: 1:25
        return;                          // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.7 Constant items/1/lib.rs:1:1: 1:26
    }
}

const BITS: [u32; 2] = {
    let mut _0: [u32; 2];                // return pointer

    bb0: {
        _0 = [BIT1, BIT2];               // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.7 Constant items/1/lib.rs:4:24: 4:36
        return;                          // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.7 Constant items/1/lib.rs:4:1: 4:37
    }
}
definition test.BIT1 : sem u32 :=
do «$tmp0»  sem.map (λx, (x, tt)) (checked.shls u32.bits (1 : nat) (0 : int));
let' t1  «$tmp0»;
let' ret  t1.1;
return (ret)


definition test.BIT2 : sem u32 :=
do «$tmp0»  sem.map (λx, (x, tt)) (checked.shls u32.bits (1 : nat) (1 : int));
let' t1  «$tmp0»;
let' ret  t1.1;
return (ret)


definition test.BITS : sem (array u32 2) :=
do «$tmp0»  do «$tmp0»  test.BIT1;
do «$tmp1»  test.BIT2;
return ([«$tmp0», «$tmp1»]);
let' ret  «$tmp0»;
return (ret)


definition test.STRING : sem string :=
let' ret  "bitstring";
return (ret)


structure test.BitsNStrings := mk {} ::
(mybits : (array u32 2))
(mystring : string)

definition test.BITS_N_STRINGS : sem (test.BitsNStrings) :=
do «$tmp0»  test.STRING;
let' t2  «$tmp0»;
let' t1  t2;
do «$tmp0»  do «$tmp0»  test.BITS;
return (test.BitsNStrings.mk «$tmp0» t1);
let' ret  «$tmp0»;
return (ret)

6.1.8 Static items [ref]

No semantic difference from constants without unsafe code or *Cells.

static LEVELS: u32 = 0;
static LEVELS: u32 = {
    let mut _0: u32;                     // return pointer

    bb0: {
        _0 = const 0u32;                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.8 Static items/2/lib.rs:1:22: 1:23
        return;                          // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.8 Static items/2/lib.rs:1:1: 1:24
    }
}
definition test.LEVELS : sem u32 :=
let' ret  (0 : nat);
return (ret)

6.1.9 Traits [ref]

Traits, type classes, what's the difference? Well, apart from the implicit Self parameter becoming explicit, we always use explicit calls in the generated code because some Rust types (immutable references, integer types) are translated into the same Lean type, making implicit calls ambiguous. Most proof code should be fine though (see below).

struct Foo;

trait Shape { fn area(&self) -> i64; }
trait Circle : Shape { fn radius(&self) -> i64; }
impl Shape for Foo {
    fn area(&self) -> i64 {
        1
    }
}
impl Circle for Foo {
    fn radius(&self) -> i64 {
        //println!("calling area: {}", self.area());
        -1
    }
}

fn main() {
    let c = Foo;
    c.radius();
}
fn <Foo as Circle>::radius(_1: &Foo) -> i64 {
    let mut _0: i64;                     // return pointer
    scope 1 {
        let _2: &Foo;                    // "self" in scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/1/lib.rs:11:15: 11:20
    }

    bb0: {
        StorageLive(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/1/lib.rs:11:15: 11:20
        _2 = _1;                         // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/1/lib.rs:11:15: 11:20
        _0 = const -1i64;                // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/1/lib.rs:13:9: 13:11
        StorageDead(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/1/lib.rs:14:6: 14:6
        return;                          // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/1/lib.rs:14:6: 14:6
    }
}

fn <Foo as Shape>::area(_1: &Foo) -> i64 {
    let mut _0: i64;                     // return pointer
    scope 1 {
        let _2: &Foo;                    // "self" in scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/1/lib.rs:6:13: 6:18
    }

    bb0: {
        StorageLive(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/1/lib.rs:6:13: 6:18
        _2 = _1;                         // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/1/lib.rs:6:13: 6:18
        _0 = const 1i64;                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/1/lib.rs:7:9: 7:10
        StorageDead(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/1/lib.rs:8:6: 8:6
        return;                          // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/1/lib.rs:8:6: 8:6
    }
}

fn main() -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let _1: Foo;                     // "c" in scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/1/lib.rs:18:9: 18:10
    }
    let mut _2: i64;
    let mut _3: &Foo;

    bb0: {
        StorageLive(_1);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/1/lib.rs:18:9: 18:10
        _1 = Foo::{{constructor}};       // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/1/lib.rs:18:13: 18:16
        StorageLive(_3);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/1/lib.rs:19:5: 19:6
        _3 = &_1;                        // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/1/lib.rs:19:5: 19:6
        _2 = <Foo as Circle>::radius(_3) -> bb1; // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/1/lib.rs:19:5: 19:15
    }

    bb1: {
        StorageDead(_3);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/1/lib.rs:19:16: 19:16
        _0 = ();                         // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/1/lib.rs:17:11: 20:2
        StorageDead(_1);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/1/lib.rs:20:2: 20:2
        return;                          // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/1/lib.rs:20:2: 20:2
    }
}
structure test.Foo := mk {} ::

definition test.«test.Foo as test.Shape».area (selfₐ : (test.Foo)) : sem (i64) :=
let' «self$2»  selfₐ;
let' ret  (1 : int);
return (ret)


definition test.«test.Foo as test.Circle».radius (selfₐ : (test.Foo)) : sem (i64) :=
let' «self$2»  selfₐ;
let' ret  (-1 : int);
return (ret)


structure test.Shape [class] (Self : Type₁) :=
(area : (Self  sem (i64)))

definition test.«test.Foo as test.Shape» [instance] := 
  test.Shape (test.Foo),
  area := @test.«test.Foo as test.Shape».area


structure test.Circle [class] (Self : Type₁) extends test.Shape Self :=
(radius : (Self  sem (i64)))

attribute [coercion] test.Circle.to_Shape

definition test.«test.Foo as test.Circle» [instance] := 
  test.Circle (test.Foo),
  (@test.«test.Foo as test.Shape»),
  radius := @test.«test.Foo as test.Circle».radius


definition test.main : sem (unit) :=
let' «c$1»  test.Foo.mk;
let' t3  «c$1»;
dostep «$tmp»  @test.«test.Foo as test.Circle».radius t3;
let' t2  «$tmp»;
let' ret  ;
return ()
example (foo : Foo) : sem.terminates_with (λ r, r = 1) (Shape.area foo) := rfl
example (foo : Foo) : sem.terminates_with (λ r, r = -1) (Circle.radius foo) := rfl

Generic traits and trait methods

trait Seq<T> {
    fn len(&self) -> u32;
    fn elt_at(&self, n: u32) -> T;
    fn iter<F>(&self, F) where F: Fn(T);
}
structure test.Seq [class] (Self : Type₁) (T : Type₁) :=
(len : (Self  sem (u32)))
(elt_at : (Self  u32  sem (T)))
(iter : Π {F : Type₁} [«core.ops.Fn F T» : core.ops.Fn F T unit], (Self  F  sem (unit)))

Default methods

Default methods are terrible. They should be part of the type class just like standard methods, but they also depend on the type class in order to call other trait methods, creating a cyclic dependency. For now, we just declare them outside of (after) the type class, which works for all current proofs, but can create problems (see below).

trait Foo {
    fn bar(&self);
    fn baz(&self) { self.bar() }
}

struct Bar;

impl Foo for Bar {
    fn bar(&self) {}
}
fn Foo::baz(_1: &Self) -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let _2: &Self;                   // "self" in scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/2 Default methods./lib.rs:3:12: 3:17
    }
    let mut _3: &Self;

    bb0: {
        StorageLive(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/2 Default methods./lib.rs:3:12: 3:17
        _2 = _1;                         // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/2 Default methods./lib.rs:3:12: 3:17
        StorageLive(_3);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/2 Default methods./lib.rs:3:21: 3:25
        _3 = &(*_2);                     // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/2 Default methods./lib.rs:3:21: 3:25
        _0 = <Self as Foo>::bar(_3) -> bb1; // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/2 Default methods./lib.rs:3:21: 3:31
    }

    bb1: {
        StorageDead(_3);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/2 Default methods./lib.rs:3:33: 3:33
        StorageDead(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/2 Default methods./lib.rs:3:33: 3:33
        return;                          // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/2 Default methods./lib.rs:3:33: 3:33
    }
}

fn <Bar as Foo>::bar(_1: &Bar) -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let _2: &Bar;                    // "self" in scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/2 Default methods./lib.rs:9:12: 9:17
    }

    bb0: {
        StorageLive(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/2 Default methods./lib.rs:9:12: 9:17
        _2 = _1;                         // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/2 Default methods./lib.rs:9:12: 9:17
        _0 = ();                         // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/2 Default methods./lib.rs:9:19: 9:21
        StorageDead(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/2 Default methods./lib.rs:9:21: 9:21
        return;                          // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/2 Default methods./lib.rs:9:21: 9:21
    }
}
structure test.Foo [class] (Self : Type₁) :=
(bar : (Self  sem (unit)))

definition test.Foo.baz {Self : Type₁} [«test.Foo Self» : test.Foo Self] (selfₐ : Self) : sem (unit) :=
let' «self$2»  selfₐ;
let' t3  «self$2»;
dostep «$tmp»  @test.Foo.bar Self «test.Foo Self» t3;
let' ret  «$tmp»;
return ()


structure test.Bar := mk {} ::

definition test.«test.Bar as test.Foo».bar (selfₐ : (test.Bar)) : sem (unit) :=
let' «self$2»  selfₐ;
let' ret  ;
return ()


definition test.«test.Bar as test.Foo» [instance] := 
  test.Foo (test.Bar),
  bar := @test.«test.Bar as test.Foo».bar

Calling default methods from inside the trait

trait Foo {
    fn bar(&self);
    fn baz(&self) { self.bar() }
}

struct Bar;

impl Foo for Bar {
    fn bar(&self) { self.baz() }
}
fn Foo::baz(_1: &Self) -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let _2: &Self;                   // "self" in scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/3 Calling default methods from inside the trait./lib.rs:3:12: 3:17
    }
    let mut _3: &Self;

    bb0: {
        StorageLive(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/3 Calling default methods from inside the trait./lib.rs:3:12: 3:17
        _2 = _1;                         // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/3 Calling default methods from inside the trait./lib.rs:3:12: 3:17
        StorageLive(_3);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/3 Calling default methods from inside the trait./lib.rs:3:21: 3:25
        _3 = &(*_2);                     // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/3 Calling default methods from inside the trait./lib.rs:3:21: 3:25
        _0 = <Self as Foo>::bar(_3) -> bb1; // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/3 Calling default methods from inside the trait./lib.rs:3:21: 3:31
    }

    bb1: {
        StorageDead(_3);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/3 Calling default methods from inside the trait./lib.rs:3:33: 3:33
        StorageDead(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/3 Calling default methods from inside the trait./lib.rs:3:33: 3:33
        return;                          // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/3 Calling default methods from inside the trait./lib.rs:3:33: 3:33
    }
}

fn <Bar as Foo>::bar(_1: &Bar) -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let _2: &Bar;                    // "self" in scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/3 Calling default methods from inside the trait./lib.rs:9:12: 9:17
    }
    let mut _3: &Bar;

    bb0: {
        StorageLive(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/3 Calling default methods from inside the trait./lib.rs:9:12: 9:17
        _2 = _1;                         // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/3 Calling default methods from inside the trait./lib.rs:9:12: 9:17
        StorageLive(_3);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/3 Calling default methods from inside the trait./lib.rs:9:21: 9:25
        _3 = &(*_2);                     // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/3 Calling default methods from inside the trait./lib.rs:9:21: 9:25
        _0 = <Bar as Foo>::baz(_3) -> bb1; // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/3 Calling default methods from inside the trait./lib.rs:9:21: 9:31
    }

    bb1: {
        StorageDead(_3);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/3 Calling default methods from inside the trait./lib.rs:9:33: 9:33
        StorageDead(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/3 Calling default methods from inside the trait./lib.rs:9:33: 9:33
        return;                          // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/3 Calling default methods from inside the trait./lib.rs:9:33: 9:33
    }
}
structure test.Foo [class] (Self : Type₁) :=
(bar : (Self  sem (unit)))

definition test.Foo.baz {Self : Type₁} [«test.Foo Self» : test.Foo Self] (selfₐ : Self) : sem (unit) :=
let' «self$2»  selfₐ;
let' t3  «self$2»;
dostep «$tmp»  @test.Foo.bar Self «test.Foo Self» t3;
let' ret  «$tmp»;
return ()


structure test.Bar := mk {} ::

/- unimplemented: circular dependencies: test.«test.Bar as test.Foo», test.«test.Bar as test.Foo».bar

definition test.«test.Bar as test.Foo» [instance] := ⦃
  test.Foo (test.Bar),
  bar := @test.«test.Bar as test.Foo».bar


definition test.«test.Bar as test.Foo».bar (selfₐ : (test.Bar)) : sem (unit) :=
let' «self$2» ← selfₐ;
let' t3 ← «self$2»;
dostep «$tmp» ← @test.Foo.baz (test.Bar) (@test.«test.Bar as test.Foo») t3;
let' ret ← «$tmp»;
return (⋆)


-/

Overriding default methods

trait Foo {
    fn bar(&self);
    fn baz(&self) { self.bar() }
}

struct Bar;

impl Foo for Bar {
    fn bar(&self) {}
    fn baz(&self) {}
}
fn <Bar as Foo>::baz(_1: &Bar) -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let _2: &Bar;                    // "self" in scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/4 Overriding default methods./lib.rs:10:12: 10:17
    }

    bb0: {
        StorageLive(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/4 Overriding default methods./lib.rs:10:12: 10:17
        _2 = _1;                         // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/4 Overriding default methods./lib.rs:10:12: 10:17
        _0 = ();                         // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/4 Overriding default methods./lib.rs:10:19: 10:21
        StorageDead(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/4 Overriding default methods./lib.rs:10:21: 10:21
        return;                          // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/4 Overriding default methods./lib.rs:10:21: 10:21
    }
}

fn Foo::baz(_1: &Self) -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let _2: &Self;                   // "self" in scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/4 Overriding default methods./lib.rs:3:12: 3:17
    }
    let mut _3: &Self;

    bb0: {
        StorageLive(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/4 Overriding default methods./lib.rs:3:12: 3:17
        _2 = _1;                         // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/4 Overriding default methods./lib.rs:3:12: 3:17
        StorageLive(_3);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/4 Overriding default methods./lib.rs:3:21: 3:25
        _3 = &(*_2);                     // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/4 Overriding default methods./lib.rs:3:21: 3:25
        _0 = <Self as Foo>::bar(_3) -> bb1; // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/4 Overriding default methods./lib.rs:3:21: 3:31
    }

    bb1: {
        StorageDead(_3);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/4 Overriding default methods./lib.rs:3:33: 3:33
        StorageDead(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/4 Overriding default methods./lib.rs:3:33: 3:33
        return;                          // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/4 Overriding default methods./lib.rs:3:33: 3:33
    }
}

fn <Bar as Foo>::bar(_1: &Bar) -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let _2: &Bar;                    // "self" in scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/4 Overriding default methods./lib.rs:9:12: 9:17
    }

    bb0: {
        StorageLive(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/4 Overriding default methods./lib.rs:9:12: 9:17
        _2 = _1;                         // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/4 Overriding default methods./lib.rs:9:12: 9:17
        _0 = ();                         // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/4 Overriding default methods./lib.rs:9:19: 9:21
        StorageDead(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/4 Overriding default methods./lib.rs:9:21: 9:21
        return;                          // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/4 Overriding default methods./lib.rs:9:21: 9:21
    }
}
structure test.Foo [class] (Self : Type₁) :=
(bar : (Self  sem (unit)))

definition test.Foo.baz {Self : Type₁} [«test.Foo Self» : test.Foo Self] (selfₐ : Self) : sem (unit) :=
let' «self$2»  selfₐ;
let' t3  «self$2»;
dostep «$tmp»  @test.Foo.bar Self «test.Foo Self» t3;
let' ret  «$tmp»;
return ()


structure test.Bar := mk {} ::

definition test.«test.Bar as test.Foo».bar (selfₐ : (test.Bar)) : sem (unit) :=
let' «self$2»  selfₐ;
let' ret  ;
return ()


/- test.«test.Bar as test.Foo».baz: unimplemented: overriding default method |test.«test.Bar as test.Foo».baz -/

/- test.«test.Bar as test.Foo»: failed dependencies |test.«test.Bar as test.Foo».baz -/

Trait bounds

struct Surface {}
trait Shape {
    fn draw(&self, &Surface);
}

fn draw_twice<T: Shape>(surface: Surface, sh: T) {
    sh.draw(&surface);
    sh.draw(&surface);
}
fn draw_twice(_1: Surface, _2: T) -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let _3: Surface;                 // "surface" in scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/5 Trait bounds./lib.rs:6:25: 6:32
        let _4: T;                       // "sh" in scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/5 Trait bounds./lib.rs:6:43: 6:45
    }
    let mut _5: ();
    let mut _6: &T;
    let mut _7: ();
    let mut _8: &Surface;
    let mut _9: &Surface;
    let mut _10: ();
    let mut _11: &T;
    let mut _12: &Surface;
    let mut _13: &Surface;

    bb0: {
        StorageLive(_3);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/5 Trait bounds./lib.rs:6:25: 6:32
        _3 = _1;                         // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/5 Trait bounds./lib.rs:6:25: 6:32
        StorageLive(_4);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/5 Trait bounds./lib.rs:6:43: 6:45
        _4 = _2;                         // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/5 Trait bounds./lib.rs:6:43: 6:45
        StorageLive(_6);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/5 Trait bounds./lib.rs:7:5: 7:7
        _6 = &_4;                        // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/5 Trait bounds./lib.rs:7:5: 7:7
        StorageLive(_8);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/5 Trait bounds./lib.rs:7:13: 7:21
        StorageLive(_9);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/5 Trait bounds./lib.rs:7:13: 7:21
        _9 = &_3;                        // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/5 Trait bounds./lib.rs:7:13: 7:21
        _8 = &(*_9);                     // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/5 Trait bounds./lib.rs:7:13: 7:21
        _5 = <T as Shape>::draw(_6, _8) -> [return: bb4, unwind: bb3]; // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/5 Trait bounds./lib.rs:7:5: 7:22
    }

    bb1: {
        resume;                          // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/5 Trait bounds./lib.rs:6:1: 9:2
    }

    bb2: {
        drop(_4) -> bb1;                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/5 Trait bounds./lib.rs:9:2: 9:2
    }

    bb3: {
        drop(_2) -> bb2;                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/5 Trait bounds./lib.rs:9:2: 9:2
    }

    bb4: {
        StorageDead(_8);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/5 Trait bounds./lib.rs:7:23: 7:23
        StorageDead(_9);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/5 Trait bounds./lib.rs:7:23: 7:23
        StorageDead(_6);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/5 Trait bounds./lib.rs:7:23: 7:23
        StorageLive(_11);                // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/5 Trait bounds./lib.rs:8:5: 8:7
        _11 = &_4;                       // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/5 Trait bounds./lib.rs:8:5: 8:7
        StorageLive(_12);                // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/5 Trait bounds./lib.rs:8:13: 8:21
        StorageLive(_13);                // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/5 Trait bounds./lib.rs:8:13: 8:21
        _13 = &_3;                       // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/5 Trait bounds./lib.rs:8:13: 8:21
        _12 = &(*_13);                   // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/5 Trait bounds./lib.rs:8:13: 8:21
        _10 = <T as Shape>::draw(_11, _12) -> [return: bb5, unwind: bb3]; // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/5 Trait bounds./lib.rs:8:5: 8:22
    }

    bb5: {
        StorageDead(_12);                // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/5 Trait bounds./lib.rs:8:23: 8:23
        StorageDead(_13);                // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/5 Trait bounds./lib.rs:8:23: 8:23
        StorageDead(_11);                // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/5 Trait bounds./lib.rs:8:23: 8:23
        _0 = ();                         // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/5 Trait bounds./lib.rs:6:50: 9:2
        drop(_2) -> [return: bb6, unwind: bb2]; // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/5 Trait bounds./lib.rs:9:2: 9:2
    }

    bb6: {
        drop(_4) -> bb7;                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/5 Trait bounds./lib.rs:9:2: 9:2
    }

    bb7: {
        StorageDead(_4);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/5 Trait bounds./lib.rs:9:2: 9:2
        StorageDead(_3);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/5 Trait bounds./lib.rs:9:2: 9:2
        return;                          // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/5 Trait bounds./lib.rs:9:2: 9:2
    }
}
structure test.Surface := mk {} ::


structure test.Shape [class] (Self : Type₁) :=
(draw : (Self  (test.Surface)  sem (unit)))

definition test.draw_twice {T : Type₁} [«test.Shape T» : test.Shape T] (surfaceₐ : (test.Surface)) (shₐ : T) : sem (unit) :=
let' «surface$3»  surfaceₐ;
let' «sh$4»  shₐ;
let' t6  «sh$4»;
let' t9  «surface$3»;
let' t8  t9;
dostep «$tmp»  @test.Shape.draw T «test.Shape T» t6 t8;
let' t5  «$tmp»;
let' t11  «sh$4»;
let' t13  «surface$3»;
let' t12  t13;
dostep «$tmp»  @test.Shape.draw T «test.Shape T» t11 t12;
let' t10  «$tmp»;
let' ret  ;
return ()

Associated types

You would think that a language with awesome dependent types like Lean would not have any problem declaring a type as a type class member, and you would be right. What it cannot express, however, are definitional type equalities like in Iterator<Item=T>, which could be written as Iterator::Item ~ T in a more Haskell-y syntax. Therefore, we follow the original paper [1] on associated types in Haskell and desugar them into type parameters. This does weaken type class inference, which is another reason why we don't do that inference in generated code. We might be able to regain inference in a potential future version of Lean that supports functional dependencies.

[1] System F with Type Equality Coercions
Martin Sulzmann, Manuel M. T. Chakravarty, Simon Peyton Jones, and Kevin Donnelly.
In G. Necula, editor, Proceedings of The Third ACM SIGPLAN Workshop on Types in Language Design and Implementation, ACM Press, 2007.

trait Container {
    type E;
    fn empty() -> Self;
    fn insert(&mut self, Self::E);
}

impl<T> Container for Vec<T> {
    type E = T;
    fn empty() -> Vec<T> { Vec::new() }
    fn insert(&mut self, x: T) { self.push(x); }
}
fn <std::vec::Vec<T> as Container>::insert(_1: &mut std::vec::Vec<T>, _2: T) -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let _3: &mut std::vec::Vec<T>;   // "self" in scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/6 Associated types./lib.rs:10:15: 10:24
        let _4: T;                       // "x" in scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/6 Associated types./lib.rs:10:26: 10:27
    }
    let mut _5: ();
    let mut _6: &mut std::vec::Vec<T>;
    let mut _7: ();
    let mut _8: T;

    bb0: {
        StorageLive(_3);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/6 Associated types./lib.rs:10:15: 10:24
        _3 = _1;                         // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/6 Associated types./lib.rs:10:15: 10:24
        StorageLive(_4);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/6 Associated types./lib.rs:10:26: 10:27
        _4 = _2;                         // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/6 Associated types./lib.rs:10:26: 10:27
        StorageLive(_6);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/6 Associated types./lib.rs:10:34: 10:38
        _6 = &mut (*_3);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/6 Associated types./lib.rs:10:34: 10:38
        StorageLive(_8);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/6 Associated types./lib.rs:10:44: 10:45
        _8 = _4;                         // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/6 Associated types./lib.rs:10:44: 10:45
        _5 = <std::vec::Vec<T>><T>::push(_6, _8) -> [return: bb5, unwind: bb4]; // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/6 Associated types./lib.rs:10:34: 10:46
    }

    bb1: {
        resume;                          // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/6 Associated types./lib.rs:10:5: 10:49
    }

    bb2: {
        drop(_4) -> bb1;                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/6 Associated types./lib.rs:10:49: 10:49
    }

    bb3: {
        drop(_2) -> bb2;                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/6 Associated types./lib.rs:10:49: 10:49
    }

    bb4: {
        drop(_8) -> bb3;                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/6 Associated types./lib.rs:10:47: 10:47
    }

    bb5: {
        drop(_8) -> [return: bb6, unwind: bb3]; // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/6 Associated types./lib.rs:10:47: 10:47
    }

    bb6: {
        StorageDead(_8);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/6 Associated types./lib.rs:10:47: 10:47
        StorageDead(_6);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/6 Associated types./lib.rs:10:47: 10:47
        _0 = ();                         // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/6 Associated types./lib.rs:10:32: 10:49
        drop(_2) -> [return: bb7, unwind: bb2]; // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/6 Associated types./lib.rs:10:49: 10:49
    }

    bb7: {
        drop(_4) -> bb8;                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/6 Associated types./lib.rs:10:49: 10:49
    }

    bb8: {
        StorageDead(_4);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/6 Associated types./lib.rs:10:49: 10:49
        StorageDead(_3);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/6 Associated types./lib.rs:10:49: 10:49
        return;                          // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/6 Associated types./lib.rs:10:49: 10:49
    }
}

fn <std::vec::Vec<T> as Container>::empty() -> std::vec::Vec<T> {
    let mut _0: std::vec::Vec<T>;        // return pointer

    bb0: {
        _0 = <std::vec::Vec<T>><T>::new() -> bb1; // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/6 Associated types./lib.rs:9:28: 9:38
    }

    bb1: {
        return;                          // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/6 Associated types./lib.rs:9:40: 9:40
    }
}
structure test.Container [class] (Self : Type₁) («<Self as Container>.E» : Type₁) :=
(empty : (sem (Self)))
(insert : (Self  «<Self as Container>.E»  sem (unit × Self)))

definition test.«collections.vec.Vec<T> as test.Container».empty {T : Type₁} : sem ((collections.vec.Vec T)) :=
dostep «$tmp»  @collections.vec.«Vec<T>».new T;
let' ret  «$tmp»;
return (ret)


definition test.«collections.vec.Vec<T> as test.Container».insert {T : Type₁} (selfₐ : (collections.vec.Vec T)) (xₐ : T) : sem (unit × (collections.vec.Vec T)) :=
let' «self$3»  @lens.id (collections.vec.Vec T);
let' «x$4»  xₐ;
let' t6  («self$3»);
do «$tmp»  lens.get t6 selfₐ;
let' t8  «x$4»;
do «$tmp0»  lens.get t6 selfₐ;
dostep «$tmp»  @collections.vec.«Vec<T>».push T «$tmp0» t8;
match «$tmp» with (t5, «t6) :=
do selfₐ  lens.set t6 selfₐ «t6;
let' ret  ;
return (, selfₐ)
end


definition test.«collections.vec.Vec<T> as test.Container» [instance] {T : Type₁} := 
  test.Container (collections.vec.Vec T) T,
  empty := @test.«collections.vec.Vec<T> as test.Container».empty T,
  insert := @test.«collections.vec.Vec<T> as test.Container».insert T

Trait objects

A trait object type &Trait can be interpreted as an existential type ∃ (T : Trait), T or, generically for all traits in Lean, as a dependent record

structure trait_obj (Trait : Type  Type) := -- `Trait` explicitly takes `Self` in Lean
(ActualType : Type)
(impl : Trait ActualType)
(self : ActualType)

We could then specify that a trait object indeed implements its trait by generating an instance of type Trait (trait_obj Trait). The instance would call the respective function on impl with self, and, in the case of &mut self methods, place the new value of self back into the trait object.

However, this wouldn't integrate well (or at all) currently because of technical reasons (trait_obj Trait living in Type₂ and Lean's universe hierarchy being noncumulative, if you really want to know), so we simply don't touch that yet.

trait Shape {
    fn draw(&self) {}
}
impl Shape for i32 { }

fn main() {
    let mycircle = 0i32;
    let myshape: &Shape = &mycircle;
    myshape.draw();
}
fn main() -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let _1: i32;                     // "mycircle" in scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/7 Trait objects./lib.rs:7:9: 7:17
        scope 2 {
            let _2: &Shape;              // "myshape" in scope 2 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/7 Trait objects./lib.rs:8:9: 8:16
        }
    }
    let mut _3: &i32;
    let mut _4: &i32;
    let mut _5: ();
    let mut _6: &Shape;

    bb0: {
        StorageLive(_1);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/7 Trait objects./lib.rs:7:9: 7:17
        _1 = const 0i32;                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/7 Trait objects./lib.rs:7:20: 7:24
        StorageLive(_2);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/7 Trait objects./lib.rs:8:9: 8:16
        StorageLive(_3);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/7 Trait objects./lib.rs:8:27: 8:36
        StorageLive(_4);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/7 Trait objects./lib.rs:8:27: 8:36
        _4 = &_1;                        // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/7 Trait objects./lib.rs:8:27: 8:36
        _3 = &(*_4);                     // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/7 Trait objects./lib.rs:8:27: 8:36
        _2 = _3 as &Shape (Unsize);      // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/7 Trait objects./lib.rs:8:27: 8:36
        StorageLive(_6);                 // scope 2 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/7 Trait objects./lib.rs:9:5: 9:12
        _6 = &(*_2);                     // scope 2 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/7 Trait objects./lib.rs:9:5: 9:12
        _5 = <Shape as Shape>::draw(_6) -> bb1; // scope 2 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/7 Trait objects./lib.rs:9:5: 9:19
    }

    bb1: {
        StorageDead(_6);                 // scope 2 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/7 Trait objects./lib.rs:9:20: 9:20
        _0 = ();                         // scope 2 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/7 Trait objects./lib.rs:6:11: 10:2
        StorageDead(_3);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/7 Trait objects./lib.rs:10:2: 10:2
        StorageDead(_4);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/7 Trait objects./lib.rs:10:2: 10:2
        StorageDead(_2);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/7 Trait objects./lib.rs:10:2: 10:2
        StorageDead(_1);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/7 Trait objects./lib.rs:10:2: 10:2
        return;                          // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/7 Trait objects./lib.rs:10:2: 10:2
    }
}

fn Shape::draw(_1: &Self) -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let _2: &Self;                   // "self" in scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/7 Trait objects./lib.rs:2:13: 2:18
    }

    bb0: {
        StorageLive(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/7 Trait objects./lib.rs:2:13: 2:18
        _2 = _1;                         // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/7 Trait objects./lib.rs:2:13: 2:18
        _0 = ();                         // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/7 Trait objects./lib.rs:2:20: 2:22
        StorageDead(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/7 Trait objects./lib.rs:2:22: 2:22
        return;                          // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/7 Trait objects./lib.rs:2:22: 2:22
    }
}
structure test.Shape [class] (Self : Type₁) := mk

definition test.Shape.draw {Self : Type₁} [«test.Shape Self» : test.Shape Self] (selfₐ : Self) : sem (unit) :=
let' «self$2»  selfₐ;
let' ret  ;
return ()


/- test.main: unimplemented: trait object -/

definition test.«i32 as test.Shape» [instance] := 
  test.Shape i32

Static trait methods

trait Num {
    fn from_i32(n: i32) -> Self;
}
impl Num for i64 {
    fn from_i32(n: i32) -> i64 { n as i64 }
}
fn main() {
    let x: i64 = Num::from_i32(42);
}
fn <i64 as Num>::from_i32(_1: i32) -> i64 {
    let mut _0: i64;                     // return pointer
    scope 1 {
        let _2: i32;                     // "n" in scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/8 Static trait methods./lib.rs:5:17: 5:18
    }
    let mut _3: i32;

    bb0: {
        StorageLive(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/8 Static trait methods./lib.rs:5:17: 5:18
        _2 = _1;                         // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/8 Static trait methods./lib.rs:5:17: 5:18
        StorageLive(_3);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/8 Static trait methods./lib.rs:5:34: 5:35
        _3 = _2;                         // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/8 Static trait methods./lib.rs:5:34: 5:35
        _0 = _3 as i64 (Misc);           // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/8 Static trait methods./lib.rs:5:34: 5:42
        StorageDead(_3);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/8 Static trait methods./lib.rs:5:44: 5:44
        StorageDead(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/8 Static trait methods./lib.rs:5:44: 5:44
        return;                          // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/8 Static trait methods./lib.rs:5:44: 5:44
    }
}

fn main() -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let _1: i64;                     // "x" in scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/8 Static trait methods./lib.rs:8:9: 8:10
    }

    bb0: {
        StorageLive(_1);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/8 Static trait methods./lib.rs:8:9: 8:10
        _1 = <i64 as Num>::from_i32(const 42i32) -> bb1; // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/8 Static trait methods./lib.rs:8:18: 8:35
    }

    bb1: {
        _0 = ();                         // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/8 Static trait methods./lib.rs:7:11: 9:2
        StorageDead(_1);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/8 Static trait methods./lib.rs:9:2: 9:2
        return;                          // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.9 Traits/8 Static trait methods./lib.rs:9:2: 9:2
    }
}
structure test.Num [class] (Self : Type₁) :=
(from_i32 : (i32  sem (Self)))

definition test.«i64 as test.Num».from_i32 (nₐ : i32) : sem (i64) :=
let' «n$2»  nₐ;
let' t3  «n$2»;
do «$tmp0»  (signed_to_signed i64.bits t3);
let' ret  «$tmp0»;
return (ret)


definition test.«i64 as test.Num» [instance] := 
  test.Num i64,
  from_i32 := @test.«i64 as test.Num».from_i32


definition test.main : sem (unit) :=
dostep «$tmp»  @test.«i64 as test.Num».from_i32 (42 : int);
let' «x$1»  «$tmp»;
let' ret  ;
return ()

6.1.10 Implementations [ref]

Trait implementations

See 6.1.9 Traits.

That other type of implementations

struct Point {x: i32, y: i32}

impl Point {
    fn log(&self) {
        //println!("Point is at ({}, {})", self.x, self.y);
    }
}

fn main() {
    let my_point = Point {x: 10, y:11};
    my_point.log();
}
fn Point::log(_1: &Point) -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let _2: &Point;                  // "self" in scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.10 Implementations/2 That other type of implementations./lib.rs:4:12: 4:17
    }

    bb0: {
        StorageLive(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.10 Implementations/2 That other type of implementations./lib.rs:4:12: 4:17
        _2 = _1;                         // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.10 Implementations/2 That other type of implementations./lib.rs:4:12: 4:17
        _0 = ();                         // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.10 Implementations/2 That other type of implementations./lib.rs:4:19: 6:6
        StorageDead(_2);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.10 Implementations/2 That other type of implementations./lib.rs:6:6: 6:6
        return;                          // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.10 Implementations/2 That other type of implementations./lib.rs:6:6: 6:6
    }
}

fn main() -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let _1: Point;                   // "my_point" in scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.10 Implementations/2 That other type of implementations./lib.rs:10:9: 10:17
    }
    let mut _2: ();
    let mut _3: &Point;

    bb0: {
        StorageLive(_1);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.10 Implementations/2 That other type of implementations./lib.rs:10:9: 10:17
        _1 = Point { x: const 10i32, y: const 11i32 }; // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.10 Implementations/2 That other type of implementations./lib.rs:10:20: 10:39
        StorageLive(_3);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.10 Implementations/2 That other type of implementations./lib.rs:11:5: 11:13
        _3 = &_1;                        // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.10 Implementations/2 That other type of implementations./lib.rs:11:5: 11:13
        _2 = Point::log(_3) -> bb1;      // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.10 Implementations/2 That other type of implementations./lib.rs:11:5: 11:19
    }

    bb1: {
        StorageDead(_3);                 // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.10 Implementations/2 That other type of implementations./lib.rs:11:20: 11:20
        _0 = ();                         // scope 1 at ref/6 Items And Attributes/6.1 Items/6.1.10 Implementations/2 That other type of implementations./lib.rs:9:11: 12:2
        StorageDead(_1);                 // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.10 Implementations/2 That other type of implementations./lib.rs:12:2: 12:2
        return;                          // scope 0 at ref/6 Items And Attributes/6.1 Items/6.1.10 Implementations/2 That other type of implementations./lib.rs:12:2: 12:2
    }
}
structure test.Point := mk {} ::
(x : i32)
(y : i32)

definition test.Point.log (selfₐ : (test.Point)) : sem (unit) :=
let' «self$2»  selfₐ;
let' ret  ;
return ()


definition test.main : sem (unit) :=
let' «my_point$1»  test.Point.mk (10 : int) (11 : int);
let' t3  «my_point$1»;
dostep «$tmp»  @test.Point.log t3;
let' t2  «$tmp»;
let' ret  ;
return ()

6.3 Attributes [ref]

Most attributes do not influence the language semantics, so we can ignore them. Except for...

6.3.8 Conditional compilation [ref]

Since the verification should not depend on the host system, we skip all items marked with #[cfg(..)] except for the harmless #[cfg(not(test))]. These items instead have to be axiomatized in a sensible way by the user.

#[cfg(any(unix, windows))]
fn foo() {}

#[cfg(all(unix, target_pointer_width = "32"))]
fn bar() {}

#[cfg(not(foo))]
fn not_foo() {}

#[cfg(not(test))]
fn not_test() {}
fn not_foo() -> () {
    let mut _0: ();                      // return pointer

    bb0: {
        _0 = ();                         // scope 0 at ref/6 Items And Attributes/6.3 Attributes/6.3.8 Conditional compilation/lib.rs:8:14: 8:16
        return;                          // scope 0 at ref/6 Items And Attributes/6.3 Attributes/6.3.8 Conditional compilation/lib.rs:8:16: 8:16
    }
}

fn foo() -> () {
    let mut _0: ();                      // return pointer

    bb0: {
        _0 = ();                         // scope 0 at ref/6 Items And Attributes/6.3 Attributes/6.3.8 Conditional compilation/lib.rs:2:10: 2:12
        return;                          // scope 0 at ref/6 Items And Attributes/6.3 Attributes/6.3.8 Conditional compilation/lib.rs:2:12: 2:12
    }
}

fn not_test() -> () {
    let mut _0: ();                      // return pointer

    bb0: {
        _0 = ();                         // scope 0 at ref/6 Items And Attributes/6.3 Attributes/6.3.8 Conditional compilation/lib.rs:11:15: 11:17
        return;                          // scope 0 at ref/6 Items And Attributes/6.3 Attributes/6.3.8 Conditional compilation/lib.rs:11:17: 11:17
    }
}
definition test.foo : sem (unit) :=
let' ret  ;
return ()


definition test.not_foo : sem (unit) :=
let' ret  ;
return ()


definition test.not_test : sem (unit) :=
let' ret  ;
return ()

7 Statements and expressions [ref]

7.1 Statements [ref]

7.1.1 Declaration Statements [ref]

7.1.1.1 Item declarations [ref]

fn foo() {
    fn bar() {}
    bar()
}
fn foo::bar() -> () {
    let mut _0: ();                      // return pointer

    bb0: {
        _0 = ();                         // scope 0 at ref/7 Statements and expressions/7.1 Statements/7.1.1 Declaration Statements/7.1.1.1 Item declarations/lib.rs:2:14: 2:16
        return;                          // scope 0 at ref/7 Statements and expressions/7.1 Statements/7.1.1 Declaration Statements/7.1.1.1 Item declarations/lib.rs:2:16: 2:16
    }
}

fn foo() -> () {
    let mut _0: ();                      // return pointer

    bb0: {
        _0 = foo::bar() -> bb1;          // scope 0 at ref/7 Statements and expressions/7.1 Statements/7.1.1 Declaration Statements/7.1.1.1 Item declarations/lib.rs:3:5: 3:10
    }

    bb1: {
        return;                          // scope 0 at ref/7 Statements and expressions/7.1 Statements/7.1.1 Declaration Statements/7.1.1.1 Item declarations/lib.rs:4:2: 4:2
    }
}
definition test.foo.bar : sem (unit) :=
let' ret  ;
return ()


definition test.foo : sem (unit) :=
dostep «$tmp»  @test.foo.bar;
let' ret  «$tmp»;
return ()

7.1.1.2 let statements [ref]

fn foo() -> i32 {
    let a = 1;
    a
}
fn foo() -> i32 {
    let mut _0: i32;                     // return pointer
    scope 1 {
        let _1: i32;                     // "a" in scope 1 at ref/7 Statements and expressions/7.1 Statements/7.1.1 Declaration Statements/7.1.1.2 let statements/lib.rs:2:9: 2:10
    }
    let mut _2: i32;

    bb0: {
        StorageLive(_1);                 // scope 0 at ref/7 Statements and expressions/7.1 Statements/7.1.1 Declaration Statements/7.1.1.2 let statements/lib.rs:2:9: 2:10
        _1 = const 1i32;                 // scope 0 at ref/7 Statements and expressions/7.1 Statements/7.1.1 Declaration Statements/7.1.1.2 let statements/lib.rs:2:13: 2:14
        StorageLive(_2);                 // scope 1 at ref/7 Statements and expressions/7.1 Statements/7.1.1 Declaration Statements/7.1.1.2 let statements/lib.rs:3:5: 3:6
        _2 = _1;                         // scope 1 at ref/7 Statements and expressions/7.1 Statements/7.1.1 Declaration Statements/7.1.1.2 let statements/lib.rs:3:5: 3:6
        _0 = _2;                         // scope 1 at ref/7 Statements and expressions/7.1 Statements/7.1.1 Declaration Statements/7.1.1.2 let statements/lib.rs:3:5: 3:6
        StorageDead(_1);                 // scope 0 at ref/7 Statements and expressions/7.1 Statements/7.1.1 Declaration Statements/7.1.1.2 let statements/lib.rs:4:2: 4:2
        StorageDead(_2);                 // scope 0 at ref/7 Statements and expressions/7.1 Statements/7.1.1 Declaration Statements/7.1.1.2 let statements/lib.rs:4:2: 4:2
        return;                          // scope 0 at ref/7 Statements and expressions/7.1 Statements/7.1.1 Declaration Statements/7.1.1.2 let statements/lib.rs:4:2: 4:2
    }
}
definition test.foo : sem (i32) :=
let' «a$1»  (1 : int);
let' t2  «a$1»;
let' ret  t2;
return (ret)

7.1.2 Expression statements [ref]

fn foo() {
    1;
}
fn foo() -> () {
    let mut _0: ();                      // return pointer
    let mut _1: i32;

    bb0: {
        _1 = const 1i32;                 // scope 0 at ref/7 Statements and expressions/7.1 Statements/7.1.2 Expression statements/lib.rs:2:5: 2:6
        _0 = ();                         // scope 0 at ref/7 Statements and expressions/7.1 Statements/7.1.2 Expression statements/lib.rs:1:10: 3:2
        return;                          // scope 0 at ref/7 Statements and expressions/7.1 Statements/7.1.2 Expression statements/lib.rs:3:2: 3:2
    }
}
definition test.foo : sem (unit) :=
let' t1  (1 : int);
let' ret  ;
return ()

7.2 Expressions [ref]

7.2.1 Literal expressions [ref]

Lean3 will have support for char literals! Exciting!

fn main() {
    ();        // unit type
    "hello";   // string type
    //'5';       // character type
    5;         // integer type
}
fn main() -> () {
    let mut _0: ();                      // return pointer
    let mut _1: ();
    let mut _2: &'static str;
    let mut _3: i32;

    bb0: {
        _1 = ();                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.1 Literal expressions/lib.rs:2:5: 2:7
        _2 = const "hello";              // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.1 Literal expressions/lib.rs:3:5: 3:12
        _3 = const 5i32;                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.1 Literal expressions/lib.rs:5:5: 5:6
        _0 = ();                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.1 Literal expressions/lib.rs:1:11: 6:2
        return;                          // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.1 Literal expressions/lib.rs:6:2: 6:2
    }
}
definition test.main : sem (unit) :=
let' t1  ;
let' t2  "hello";
let' t3  (5 : int);
let' ret  ;
return ()

7.2.3 Tuple expressions [ref]

fn main() {
    (0, 4);
    ("a", 4usize, true);
}
fn main() -> () {
    let mut _0: ();                      // return pointer
    let mut _1: (i32, i32);
    let mut _2: (&'static str, usize, bool);

    bb0: {
        _1 = (const 0i32, const 4i32);   // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.3 Tuple expressions/1/lib.rs:2:5: 2:11
        _2 = (const "a", const 4usize, const true); // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.3 Tuple expressions/1/lib.rs:3:5: 3:24
        _0 = ();                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.3 Tuple expressions/1/lib.rs:1:11: 4:2
        return;                          // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.3 Tuple expressions/1/lib.rs:4:2: 4:2
    }
}
definition test.main : sem (unit) :=
let' t1  ((0 : int), (4 : int));
let' t2  ("a", (4 : nat), tt);
let' ret  ;
return ()

Lean uses the much more satisfying definition of tuples as nested pairs, which has the interesting side-effect of unary tuples not being a thing.

fn main() {
    (0,); // single-element tuple
    (0); // zero in parentheses
}
fn main() -> () {
    let mut _0: ();                      // return pointer
    let mut _1: (i32,);
    let mut _2: i32;

    bb0: {
        _1 = (const 0i32,);              // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.3 Tuple expressions/2/lib.rs:2:5: 2:9
        _2 = const 0i32;                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.3 Tuple expressions/2/lib.rs:3:5: 3:8
        _0 = ();                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.3 Tuple expressions/2/lib.rs:1:11: 4:2
        return;                          // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.3 Tuple expressions/2/lib.rs:4:2: 4:2
    }
}
definition test.main : sem (unit) :=
let' t1  (0 : int);
let' t2  (0 : int);
let' ret  ;
return ()

7.2.4 Struct expressions [ref]

fn main() {
    struct Point { x: i64, y: i64 }
    struct NothingInMe { }
    struct TuplePoint(i64, i64);
    mod game { pub struct User<'a> { pub name: &'a str, pub age: u32, pub score: usize } }
    struct Cookie; fn some_fn<T>(t: T) {}

    Point {x: 10, y: 20};
    NothingInMe {};
    TuplePoint(10, 20);
    let u = game::User {name: "Joe", age: 35, score: 100_000};
    some_fn::<Cookie>(Cookie);
}
fn main() -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let _4: main::game::User<'_>;    // "u" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.4 Struct expressions/lib.rs:11:9: 11:10
    }
    let mut _1: main::Point;
    let mut _2: main::NothingInMe;
    let mut _3: main::TuplePoint;
    let mut _5: &str;
    let mut _6: &'static str;
    let mut _7: ();
    let mut _8: main::Cookie;

    bb0: {
        _1 = main::Point { x: const 10i64, y: const 20i64 }; // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.4 Struct expressions/lib.rs:8:5: 8:25
        _2 = main::NothingInMe;          // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.4 Struct expressions/lib.rs:9:5: 9:19
        _3 = main::TuplePoint::{{constructor}}(const 10i64, const 20i64); // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.4 Struct expressions/lib.rs:10:5: 10:23
        StorageLive(_4);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.4 Struct expressions/lib.rs:11:9: 11:10
        StorageLive(_5);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.4 Struct expressions/lib.rs:11:31: 11:36
        StorageLive(_6);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.4 Struct expressions/lib.rs:11:31: 11:36
        _6 = const "Joe";                // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.4 Struct expressions/lib.rs:11:31: 11:36
        _5 = &(*_6);                     // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.4 Struct expressions/lib.rs:11:31: 11:36
        _4 = main::game::User<'_> { name: _5, age: const 35u32, score: const 100000usize }; // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.4 Struct expressions/lib.rs:11:13: 11:62
        StorageDead(_5);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.4 Struct expressions/lib.rs:11:63: 11:63
        StorageDead(_6);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.4 Struct expressions/lib.rs:11:63: 11:63
        StorageLive(_8);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.4 Struct expressions/lib.rs:12:23: 12:29
        _8 = main::Cookie::{{constructor}}; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.4 Struct expressions/lib.rs:12:23: 12:29
        _7 = main::some_fn::<main::Cookie>(_8) -> bb1; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.4 Struct expressions/lib.rs:12:5: 12:30
    }

    bb1: {
        StorageDead(_8);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.4 Struct expressions/lib.rs:12:31: 12:31
        _0 = ();                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.4 Struct expressions/lib.rs:1:11: 13:2
        StorageDead(_4);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.4 Struct expressions/lib.rs:13:2: 13:2
        return;                          // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.4 Struct expressions/lib.rs:13:2: 13:2
    }
}

fn main::some_fn(_1: T) -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let _2: T;                       // "t" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.4 Struct expressions/lib.rs:6:34: 6:35
    }
    let mut _3: ();

    bb0: {
        StorageLive(_2);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.4 Struct expressions/lib.rs:6:34: 6:35
        _2 = _1;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.4 Struct expressions/lib.rs:6:34: 6:35
        _0 = ();                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.4 Struct expressions/lib.rs:6:40: 6:42
        drop(_1) -> [return: bb3, unwind: bb2]; // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.4 Struct expressions/lib.rs:6:42: 6:42
    }

    bb1: {
        resume;                          // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.4 Struct expressions/lib.rs:6:20: 6:42
    }

    bb2: {
        drop(_2) -> bb1;                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.4 Struct expressions/lib.rs:6:42: 6:42
    }

    bb3: {
        drop(_2) -> bb4;                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.4 Struct expressions/lib.rs:6:42: 6:42
    }

    bb4: {
        StorageDead(_2);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.4 Struct expressions/lib.rs:6:42: 6:42
        return;                          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.4 Struct expressions/lib.rs:6:42: 6:42
    }
}
structure test.main.Point := mk {} ::
(x : i64)
(y : i64)

structure test.main.NothingInMe := mk {} ::


inductive test.main.TuplePoint :=
mk {} : i64  i64  test.main.TuplePoint

structure test.main.game.User := mk {} ::
(name : string)
(age : u32)
(score : usize)

structure test.main.Cookie := mk {} ::

definition test.main.some_fn {T : Type₁} (tₐ : T) : sem (unit) :=
let' «t$2»  tₐ;
let' ret  ;
return ()


definition test.main : sem (unit) :=
let' t1  test.main.Point.mk (10 : int) (20 : int);
let' t2  test.main.NothingInMe.mk;
let' t3  test.main.TuplePoint.mk (10 : int) (20 : int);
let' t6  "Joe";
let' t5  t6;
let' «u$4»  test.main.game.User.mk t5 (35 : nat) (100000 : nat);
let' t8  test.main.Cookie.mk;
dostep «$tmp»  @test.main.some_fn (test.main.Cookie) t8;
let' t7  «$tmp»;
let' ret  ;
return ()
fn main() {
    struct Point3d { x: i32, y: i32, z: i32 }

    let base = Point3d {x: 1, y: 2, z: 3};
    Point3d {y: 0, z: 10, .. base};
}
fn main() -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let _1: main::Point3d;           // "base" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.4 Struct expressions/2/lib.rs:4:9: 4:13
    }
    let mut _2: main::Point3d;

    bb0: {
        StorageLive(_1);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.4 Struct expressions/2/lib.rs:4:9: 4:13
        _1 = main::Point3d { x: const 1i32, y: const 2i32, z: const 3i32 }; // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.4 Struct expressions/2/lib.rs:4:16: 4:42
        _2 = main::Point3d { x: (_1.0: i32), y: const 0i32, z: const 10i32 }; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.4 Struct expressions/2/lib.rs:5:5: 5:35
        _0 = ();                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.4 Struct expressions/2/lib.rs:1:11: 6:2
        StorageDead(_1);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.4 Struct expressions/2/lib.rs:6:2: 6:2
        return;                          // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.4 Struct expressions/2/lib.rs:6:2: 6:2
    }
}
structure test.main.Point3d := mk {} ::
(x : i32)
(y : i32)
(z : i32)

definition test.main : sem (unit) :=
let' «base$1»  test.main.Point3d.mk (1 : int) (2 : int) (3 : int);
let' t2  test.main.Point3d.mk (test.main.Point3d.x «base$1») (0 : int) (10 : int);
let' ret  ;
return ()

7.2.5 Block expressions [ref]

Well, that's what we have MIR for.

fn foo() -> i32 {
    let x: i32 = { ; 5 };
    x
}
fn foo() -> i32 {
    let mut _0: i32;                     // return pointer
    scope 1 {
        let _1: i32;                     // "x" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.5 Block expressions/lib.rs:2:9: 2:10
    }
    let mut _2: i32;

    bb0: {
        StorageLive(_1);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.5 Block expressions/lib.rs:2:9: 2:10
        _1 = const 5i32;                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.5 Block expressions/lib.rs:2:22: 2:23
        StorageLive(_2);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.5 Block expressions/lib.rs:3:5: 3:6
        _2 = _1;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.5 Block expressions/lib.rs:3:5: 3:6
        _0 = _2;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.5 Block expressions/lib.rs:3:5: 3:6
        StorageDead(_1);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.5 Block expressions/lib.rs:4:2: 4:2
        StorageDead(_2);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.5 Block expressions/lib.rs:4:2: 4:2
        return;                          // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.5 Block expressions/lib.rs:4:2: 4:2
    }
}
definition test.foo : sem (i32) :=
let' «x$1»  (5 : int);
let' t2  «x$1»;
let' ret  t2;
return (ret)

7.2.6 Method-call expressions [ref]

See 6.1.9 Traits and 6.1.10 Implementations.

7.2.7 Field expressions [ref]

Yes, that's some beautiful tuple struct extraction code.

fn main() {
    struct Point { x: i64, y: i64 }
    struct TuplePoint(i64, i64);

    Point {x: 10, y: 20}.x;
    TuplePoint(10, 20).0;
}
fn main() -> () {
    let mut _0: ();                      // return pointer
    let mut _1: i64;
    let mut _2: i64;
    let mut _3: main::Point;
    let mut _4: i64;
    let mut _5: i64;
    let mut _6: main::TuplePoint;

    bb0: {
        StorageLive(_2);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.7 Field expressions/lib.rs:5:5: 5:27
        StorageLive(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.7 Field expressions/lib.rs:5:5: 5:25
        _3 = main::Point { x: const 10i64, y: const 20i64 }; // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.7 Field expressions/lib.rs:5:5: 5:25
        _2 = (_3.0: i64);                // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.7 Field expressions/lib.rs:5:5: 5:27
        _1 = _2;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.7 Field expressions/lib.rs:5:5: 5:27
        StorageDead(_2);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.7 Field expressions/lib.rs:5:28: 5:28
        StorageDead(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.7 Field expressions/lib.rs:5:28: 5:28
        StorageLive(_5);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.7 Field expressions/lib.rs:6:5: 6:25
        StorageLive(_6);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.7 Field expressions/lib.rs:6:5: 6:23
        _6 = main::TuplePoint::{{constructor}}(const 10i64, const 20i64); // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.7 Field expressions/lib.rs:6:5: 6:23
        _5 = (_6.0: i64);                // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.7 Field expressions/lib.rs:6:5: 6:25
        _4 = _5;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.7 Field expressions/lib.rs:6:5: 6:25
        StorageDead(_5);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.7 Field expressions/lib.rs:6:26: 6:26
        StorageDead(_6);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.7 Field expressions/lib.rs:6:26: 6:26
        _0 = ();                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.7 Field expressions/lib.rs:1:11: 7:2
        return;                          // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.7 Field expressions/lib.rs:7:2: 7:2
    }
}
structure test.main.Point := mk {} ::
(x : i64)
(y : i64)

inductive test.main.TuplePoint :=
mk {} : i64  i64  test.main.TuplePoint

definition test.main : sem (unit) :=
let' t3  test.main.Point.mk (10 : int) (20 : int);
let' t2  (test.main.Point.x t3);
let' t1  t2;
let' t6  test.main.TuplePoint.mk (10 : int) (20 : int);
let' t5  match t6 with test.main.TuplePoint.mk x0 x1 := x0 end;
let' t4  t5;
let' ret  ;
return ()

7.2.8 Array expressions [ref]

fn main() {
    [1, 2, 3, 4];
    ["a", "b", "c", "d"];
    [0; 128];              // array with 128 zeros
    [0u8, 0u8, 0u8, 0u8];
}
const main::{{initializer}}: usize = {
    let mut _0: usize;                   // return pointer

    bb0: {
        _0 = const 128usize;             // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.8 Array expressions/lib.rs:4:9: 4:12
        return;                          // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.8 Array expressions/lib.rs:4:9: 4:12
    }
}

fn main() -> () {
    let mut _0: ();                      // return pointer
    let mut _1: [i32; 4];
    let mut _2: [&'static str; 4];
    let mut _3: [i32; 128];
    let mut _4: [u8; 4];

    bb0: {
        _1 = [const 1i32, const 2i32, const 3i32, const 4i32]; // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.8 Array expressions/lib.rs:2:5: 2:17
        _2 = [const "a", const "b", const "c", const "d"]; // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.8 Array expressions/lib.rs:3:5: 3:25
        _3 = [const 0i32; const 128usize]; // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.8 Array expressions/lib.rs:4:5: 4:13
        _4 = [const 0u8, const 0u8, const 0u8, const 0u8]; // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.8 Array expressions/lib.rs:5:5: 5:25
        _0 = ();                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.8 Array expressions/lib.rs:1:11: 6:2
        return;                          // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.8 Array expressions/lib.rs:6:2: 6:2
    }
}
definition test.main : sem (unit) :=
let' t1  [(1 : int), (2 : int), (3 : int), (4 : int)];
let' t2  ["a", "b", "c", "d"];
let' t3  list.replicate 128 (0 : int);
let' t4  [(0 : nat), (0 : nat), (0 : nat), (0 : nat)];
let' ret  ;
return ()

7.2.9 Index expressions [ref]

fn foo() -> i32 {
    ([1, 2, 3, 4])[0]
}

fn bar() -> &'static str {
    let n = 10;
    let y = (["a", "b"])[n]; // panics
    y
}
fn bar() -> &'static str {
    let mut _0: &'static str;            // return pointer
    scope 1 {
        let _1: usize;                   // "n" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.9 Index expressions/lib.rs:6:9: 6:10
        scope 2 {
            let _2: &'static str;        // "y" in scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.9 Index expressions/lib.rs:7:9: 7:10
        }
    }
    let mut _3: &'static str;
    let mut _4: [&'static str; 2];
    let mut _5: usize;
    let mut _6: usize;
    let mut _7: bool;

    bb0: {
        StorageLive(_1);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.9 Index expressions/lib.rs:6:9: 6:10
        _1 = const 10usize;              // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.9 Index expressions/lib.rs:6:13: 6:15
        StorageLive(_2);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.9 Index expressions/lib.rs:7:9: 7:10
        StorageLive(_3);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.9 Index expressions/lib.rs:7:13: 7:28
        StorageLive(_4);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.9 Index expressions/lib.rs:7:13: 7:25
        _4 = [const "a", const "b"];     // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.9 Index expressions/lib.rs:7:13: 7:25
        StorageLive(_5);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.9 Index expressions/lib.rs:7:26: 7:27
        _5 = _1;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.9 Index expressions/lib.rs:7:26: 7:27
        _6 = Len(_4);                    // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.9 Index expressions/lib.rs:7:13: 7:28
        _7 = Lt(_5, _6);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.9 Index expressions/lib.rs:7:13: 7:28
        assert(_7, "index out of bounds: the len is {} but the index is {}", _6, _5) -> bb1; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.9 Index expressions/lib.rs:7:13: 7:28
    }

    bb1: {
        _3 = _4[_5];                     // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.9 Index expressions/lib.rs:7:13: 7:28
        _2 = _3;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.9 Index expressions/lib.rs:7:13: 7:28
        StorageDead(_3);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.9 Index expressions/lib.rs:7:29: 7:29
        StorageDead(_5);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.9 Index expressions/lib.rs:7:29: 7:29
        StorageDead(_4);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.9 Index expressions/lib.rs:7:29: 7:29
        _0 = &(*_2);                     // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.9 Index expressions/lib.rs:8:5: 8:6
        StorageDead(_2);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.9 Index expressions/lib.rs:9:2: 9:2
        StorageDead(_1);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.9 Index expressions/lib.rs:9:2: 9:2
        return;                          // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.9 Index expressions/lib.rs:9:2: 9:2
    }
}

fn foo() -> i32 {
    let mut _0: i32;                     // return pointer
    let mut _1: i32;
    let mut _2: [i32; 4];
    let mut _3: usize;
    let mut _4: bool;

    bb0: {
        StorageLive(_1);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.9 Index expressions/lib.rs:2:5: 2:22
        StorageLive(_2);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.9 Index expressions/lib.rs:2:5: 2:19
        _2 = [const 1i32, const 2i32, const 3i32, const 4i32]; // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.9 Index expressions/lib.rs:2:5: 2:19
        _3 = Len(_2);                    // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.9 Index expressions/lib.rs:2:5: 2:22
        _4 = Lt(const 0usize, _3);       // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.9 Index expressions/lib.rs:2:5: 2:22
        assert(_4, "index out of bounds: the len is {} but the index is {}", _3, const 0usize) -> bb1; // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.9 Index expressions/lib.rs:2:5: 2:22
    }

    bb1: {
        _1 = _2[const 0usize];           // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.9 Index expressions/lib.rs:2:5: 2:22
        _0 = _1;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.9 Index expressions/lib.rs:2:5: 2:22
        StorageDead(_1);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.9 Index expressions/lib.rs:3:2: 3:2
        StorageDead(_2);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.9 Index expressions/lib.rs:3:2: 3:2
        return;                          // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.9 Index expressions/lib.rs:3:2: 3:2
    }
}
definition test.foo : sem (i32) :=
let' t2  [(1 : int), (2 : int), (3 : int), (4 : int)];
let' t3  list.length t2;
let' t4  (0 : nat) < t3;
do «$tmp0»  core.«[T] as core.slice.SliceExt».get_unchecked t2 (0 : nat);
let' t1  «$tmp0»;
let' ret  t1;
return (ret)


definition test.bar : sem (string) :=
let' «n$1»  (10 : nat);
let' t4  ["a", "b"];
let' t5  «n$1»;
let' t6  list.length t4;
let' t7  t5 < t6;
do «$tmp0»  core.«[T] as core.slice.SliceExt».get_unchecked t4 t5;
let' t3  «$tmp0»;
let' «y$2»  t3;
let' ret  «y$2»;
return (ret)
example : sem.terminates_with (λ r, r = 1) test.foo := rfl
example : ¬sem.terminates test.bar := id

7.2.10 Range expressions [ref]

fn main() {
    1..2;   // std::ops::Range
    3..;    // std::ops::RangeFrom
    ..4;    // std::ops::RangeTo
    ..;     // std::ops::RangeFull

    // still feature gated
    // 1...2;   // std::ops::RangeInclusive
    // ...4;    // std::ops::RangeToInclusive
}
fn main() -> () {
    let mut _0: ();                      // return pointer
    let mut _1: std::ops::Range<i32>;
    let mut _2: i32;
    let mut _3: i32;
    let mut _4: std::ops::RangeFrom<i32>;
    let mut _5: i32;
    let mut _6: std::ops::RangeTo<i32>;
    let mut _7: i32;
    let mut _8: std::ops::RangeFull;

    bb0: {
        StorageLive(_2);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.10 Range expressions/lib.rs:2:5: 2:6
        _2 = const 1i32;                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.10 Range expressions/lib.rs:2:5: 2:6
        StorageLive(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.10 Range expressions/lib.rs:2:8: 2:9
        _3 = const 2i32;                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.10 Range expressions/lib.rs:2:8: 2:9
        _1 = std::ops::Range<i32> { start: _2, end: _3 }; // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.10 Range expressions/lib.rs:2:5: 2:9
        StorageDead(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.10 Range expressions/lib.rs:2:10: 2:10
        StorageDead(_2);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.10 Range expressions/lib.rs:2:10: 2:10
        StorageLive(_5);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.10 Range expressions/lib.rs:3:5: 3:6
        _5 = const 3i32;                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.10 Range expressions/lib.rs:3:5: 3:6
        _4 = std::ops::RangeFrom<i32> { start: _5 }; // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.10 Range expressions/lib.rs:3:5: 3:8
        StorageDead(_5);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.10 Range expressions/lib.rs:3:9: 3:9
        StorageLive(_7);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.10 Range expressions/lib.rs:4:7: 4:8
        _7 = const 4i32;                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.10 Range expressions/lib.rs:4:7: 4:8
        _6 = std::ops::RangeTo<i32> { end: _7 }; // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.10 Range expressions/lib.rs:4:5: 4:8
        StorageDead(_7);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.10 Range expressions/lib.rs:4:9: 4:9
        _8 = std::ops::RangeFull::{{constructor}}; // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.10 Range expressions/lib.rs:5:5: 5:7
        _0 = ();                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.10 Range expressions/lib.rs:1:11: 10:2
        return;                          // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.10 Range expressions/lib.rs:10:2: 10:2
    }
}
definition test.main : sem (unit) :=
let' t2  (1 : int);
let' t3  (2 : int);
let' t1  core.ops.Range.mk t2 t3;
let' t5  (3 : int);
let' t4  core.ops.RangeFrom.mk t5;
let' t7  (4 : int);
let' t6  core.ops.RangeTo.mk t7;
let' t8  core.ops.RangeFull.mk;
let' ret  ;
return ()

7.2.11 Unary operator expressions [ref]

fn foo(mut x: i32, y: &i32, b: bool) {
    -x;
    !x;
    *y;
    !b;
    &x;
    &mut x;
}
fn foo(_1: i32, _2: &i32, _3: bool) -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let mut _4: i32;                 // "x" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/lib.rs:1:8: 1:13
        let _5: &i32;                    // "y" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/lib.rs:1:20: 1:21
        let _6: bool;                    // "b" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/lib.rs:1:29: 1:30
    }
    let mut _7: i32;
    let mut _8: i32;
    let mut _9: bool;
    let mut _10: i32;
    let mut _11: i32;
    let mut _12: i32;
    let mut _13: i32;
    let mut _14: bool;
    let mut _15: bool;
    let mut _16: &i32;
    let mut _17: &mut i32;

    bb0: {
        StorageLive(_4);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/lib.rs:1:8: 1:13
        _4 = _1;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/lib.rs:1:8: 1:13
        StorageLive(_5);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/lib.rs:1:20: 1:21
        _5 = _2;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/lib.rs:1:20: 1:21
        StorageLive(_6);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/lib.rs:1:29: 1:30
        _6 = _3;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/lib.rs:1:29: 1:30
        StorageLive(_8);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/lib.rs:2:6: 2:7
        _8 = _4;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/lib.rs:2:6: 2:7
        _9 = Eq(_8, const -2147483648i32); // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/lib.rs:2:5: 2:7
        assert(!_9, "attempt to negate with overflow") -> bb1; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/lib.rs:2:5: 2:7
    }

    bb1: {
        _7 = Neg(_8);                    // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/lib.rs:2:5: 2:7
        StorageDead(_8);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/lib.rs:2:8: 2:8
        StorageLive(_11);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/lib.rs:3:6: 3:7
        _11 = _4;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/lib.rs:3:6: 3:7
        _10 = Not(_11);                  // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/lib.rs:3:5: 3:7
        StorageDead(_11);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/lib.rs:3:8: 3:8
        StorageLive(_13);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/lib.rs:4:5: 4:7
        _13 = (*_5);                     // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/lib.rs:4:5: 4:7
        _12 = _13;                       // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/lib.rs:4:5: 4:7
        StorageDead(_13);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/lib.rs:4:8: 4:8
        StorageLive(_15);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/lib.rs:5:6: 5:7
        _15 = _6;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/lib.rs:5:6: 5:7
        _14 = Not(_15);                  // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/lib.rs:5:5: 5:7
        StorageDead(_15);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/lib.rs:5:8: 5:8
        _16 = &_4;                       // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/lib.rs:6:5: 6:7
        _17 = &mut _4;                   // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/lib.rs:7:5: 7:11
        _0 = ();                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/lib.rs:1:38: 8:2
        StorageDead(_6);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/lib.rs:8:2: 8:2
        StorageDead(_5);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/lib.rs:8:2: 8:2
        StorageDead(_4);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/lib.rs:8:2: 8:2
        return;                          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/lib.rs:8:2: 8:2
    }
}
definition test.foo (xₐ : i32) (yₐ : i32) (bₐ : bool) : sem (unit) :=
let' «x$4»  xₐ;
let' «y$5»  yₐ;
let' «b$6»  bₐ;
let' t8  «x$4»;
let' t9  t8 = (-2147483648 : int);
do «$tmp0»  checked.neg i32.bits t8;
let' t7  «$tmp0»;
let' t11  «x$4»;
let' t10  sbitnot i32.bits t11;
let' t13  «y$5»;
let' t12  t13;
let' t15  «b$6»;
let' t14  bool.bnot t15;
let' t16  «x$4»;
let' t17  @lens.id i32;
do «$tmp»  lens.get t17 «x$4»;
let' ret  ;
return ()

Mutable borrowing

A mutable reference points somewhere into a local of type T and can read from and write into that values of type S. We represent this as a lens T S and statically keep track of which local the lens focuses on. The act of mutable borrowing translates to creating a new lens.

Basic borrowing of local paths
struct S { x: [i32; 2] }

fn foo(mut s: S) -> i32 {
    let p = &mut s.x[0];
    *p
}
fn foo(_1: S) -> i32 {
    let mut _0: i32;                     // return pointer
    scope 1 {
        let mut _2: S;                   // "s" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./0 Basic borrowing of local paths./lib.rs:3:8: 3:13
        scope 2 {
            let _3: &mut i32;            // "p" in scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./0 Basic borrowing of local paths./lib.rs:4:9: 4:10
        }
    }
    let mut _4: usize;
    let mut _5: bool;
    let mut _6: i32;

    bb0: {
        StorageLive(_2);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./0 Basic borrowing of local paths./lib.rs:3:8: 3:13
        _2 = _1;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./0 Basic borrowing of local paths./lib.rs:3:8: 3:13
        StorageLive(_3);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./0 Basic borrowing of local paths./lib.rs:4:9: 4:10
        _4 = Len((_2.0: [i32; 2]));      // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./0 Basic borrowing of local paths./lib.rs:4:18: 4:24
        _5 = Lt(const 0usize, _4);       // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./0 Basic borrowing of local paths./lib.rs:4:18: 4:24
        assert(_5, "index out of bounds: the len is {} but the index is {}", _4, const 0usize) -> bb1; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./0 Basic borrowing of local paths./lib.rs:4:18: 4:24
    }

    bb1: {
        _3 = &mut (_2.0: [i32; 2])[const 0usize]; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./0 Basic borrowing of local paths./lib.rs:4:13: 4:24
        StorageLive(_6);                 // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./0 Basic borrowing of local paths./lib.rs:5:5: 5:7
        _6 = (*_3);                      // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./0 Basic borrowing of local paths./lib.rs:5:5: 5:7
        _0 = _6;                         // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./0 Basic borrowing of local paths./lib.rs:5:5: 5:7
        StorageDead(_3);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./0 Basic borrowing of local paths./lib.rs:6:2: 6:2
        StorageDead(_6);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./0 Basic borrowing of local paths./lib.rs:6:2: 6:2
        StorageDead(_2);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./0 Basic borrowing of local paths./lib.rs:6:2: 6:2
        return;                          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./0 Basic borrowing of local paths./lib.rs:6:2: 6:2
    }
}

const S::{{initializer}}: usize = {
    let mut _0: usize;                   // return pointer

    bb0: {
        _0 = const 2usize;               // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./0 Basic borrowing of local paths./lib.rs:1:21: 1:22
        return;                          // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./0 Basic borrowing of local paths./lib.rs:1:21: 1:22
    }
}
structure test.S := mk {} ::
(x : (array i32 2))

definition test.foo (sₐ : (test.S)) : sem (i32) :=
let' «s$2»  sₐ;
let' t4  list.length (test.S.x «s$2»);
let' t5  (0 : nat) < t4;
let' «p$3»  (lens.index _ (0 : nat)  lens.mk (return  test.S.x) (λ (o : (test.S)) i, return  (test.S), x := i ⦄));
do «$tmp»  lens.get «p$3» «s$2»;
do «$tmp0»  lens.get «p$3» «s$2»;
let' t6  «$tmp0»;
let' ret  t6;
return (ret)
example : sem.terminates_with (λ i, i = 41) (test.foo test.S, x := [41, 42]⦄) := rfl
Reborrowing

Reborrowing means composing a new lens onto the existing one.

struct S { x: [i32; 2] }

fn foo(s: &mut S) -> i32 {
    let p = &mut s.x[0];
    *p
}
fn foo(_1: &mut S) -> i32 {
    let mut _0: i32;                     // return pointer
    scope 1 {
        let _2: &mut S;                  // "s" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./0 Reborrowing./lib.rs:3:8: 3:9
        scope 2 {
            let _3: &mut i32;            // "p" in scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./0 Reborrowing./lib.rs:4:9: 4:10
        }
    }
    let mut _4: usize;
    let mut _5: bool;
    let mut _6: i32;

    bb0: {
        StorageLive(_2);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./0 Reborrowing./lib.rs:3:8: 3:9
        _2 = _1;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./0 Reborrowing./lib.rs:3:8: 3:9
        StorageLive(_3);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./0 Reborrowing./lib.rs:4:9: 4:10
        _4 = Len(((*_2).0: [i32; 2]));   // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./0 Reborrowing./lib.rs:4:18: 4:24
        _5 = Lt(const 0usize, _4);       // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./0 Reborrowing./lib.rs:4:18: 4:24
        assert(_5, "index out of bounds: the len is {} but the index is {}", _4, const 0usize) -> bb1; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./0 Reborrowing./lib.rs:4:18: 4:24
    }

    bb1: {
        _3 = &mut ((*_2).0: [i32; 2])[const 0usize]; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./0 Reborrowing./lib.rs:4:13: 4:24
        StorageLive(_6);                 // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./0 Reborrowing./lib.rs:5:5: 5:7
        _6 = (*_3);                      // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./0 Reborrowing./lib.rs:5:5: 5:7
        _0 = _6;                         // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./0 Reborrowing./lib.rs:5:5: 5:7
        StorageDead(_3);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./0 Reborrowing./lib.rs:6:2: 6:2
        StorageDead(_6);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./0 Reborrowing./lib.rs:6:2: 6:2
        StorageDead(_2);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./0 Reborrowing./lib.rs:6:2: 6:2
        return;                          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./0 Reborrowing./lib.rs:6:2: 6:2
    }
}

const S::{{initializer}}: usize = {
    let mut _0: usize;                   // return pointer

    bb0: {
        _0 = const 2usize;               // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./0 Reborrowing./lib.rs:1:21: 1:22
        return;                          // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./0 Reborrowing./lib.rs:1:21: 1:22
    }
}
structure test.S := mk {} ::
(x : (array i32 2))

definition test.foo (sₐ : (test.S)) : sem (i32 × (test.S)) :=
let' «s$2»  @lens.id (test.S);
do «$tmp0»  do «$tmp0»  do «$tmp0»  lens.get «s$2» sₐ;
return ((test.S.x «$tmp0»));
return (list.length «$tmp0»);
let' t4  «$tmp0»;
let' t5  (0 : nat) < t4;
let' «p$3»  (lens.index _ (0 : nat)  lens.mk (return  test.S.x) (λ (o : (test.S)) i, return  (test.S), x := i ⦄)  «s$2»);
do «$tmp»  lens.get «p$3» sₐ;
do «$tmp0»  lens.get «p$3» sₐ;
let' t6  «$tmp0»;
let' ret  t6;
return (ret, sₐ)
Nested storing of mut refs

Nested storing of &mut makes the static tracking harder.

fn foo(mut x: i32, mut y: i32) -> i32 {
    {
        let rs = [&mut x, &mut y];
        *rs[0] += 1;
    }
    x
}
fn foo(_1: i32, _2: i32) -> i32 {
    let mut _0: i32;                     // return pointer
    scope 1 {
        let mut _3: i32;                 // "x" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./2 Nested storing of mut refs./lib.rs:1:8: 1:13
        let mut _4: i32;                 // "y" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./2 Nested storing of mut refs./lib.rs:1:20: 1:25
        scope 2 {
            let _6: [&mut i32; 2];       // "rs" in scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./2 Nested storing of mut refs./lib.rs:3:13: 3:15
        }
    }
    let mut _5: ();
    let mut _7: &mut i32;
    let mut _8: &mut i32;
    let mut _9: &mut i32;
    let mut _10: usize;
    let mut _11: bool;
    let mut _12: (i32, bool);
    let mut _13: i32;

    bb0: {
        StorageLive(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./2 Nested storing of mut refs./lib.rs:1:8: 1:13
        _3 = _1;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./2 Nested storing of mut refs./lib.rs:1:8: 1:13
        StorageLive(_4);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./2 Nested storing of mut refs./lib.rs:1:20: 1:25
        _4 = _2;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./2 Nested storing of mut refs./lib.rs:1:20: 1:25
        StorageLive(_6);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./2 Nested storing of mut refs./lib.rs:3:13: 3:15
        StorageLive(_7);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./2 Nested storing of mut refs./lib.rs:3:19: 3:25
        _7 = &mut _3;                    // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./2 Nested storing of mut refs./lib.rs:3:19: 3:25
        StorageLive(_8);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./2 Nested storing of mut refs./lib.rs:3:27: 3:33
        StorageLive(_9);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./2 Nested storing of mut refs./lib.rs:3:27: 3:33
        _9 = &mut _4;                    // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./2 Nested storing of mut refs./lib.rs:3:27: 3:33
        _8 = &mut (*_9);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./2 Nested storing of mut refs./lib.rs:3:27: 3:33
        _6 = [_7, _8];                   // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./2 Nested storing of mut refs./lib.rs:3:18: 3:34
        StorageDead(_8);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./2 Nested storing of mut refs./lib.rs:3:35: 3:35
        StorageDead(_9);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./2 Nested storing of mut refs./lib.rs:3:35: 3:35
        StorageDead(_7);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./2 Nested storing of mut refs./lib.rs:3:35: 3:35
        _10 = Len(_6);                   // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./2 Nested storing of mut refs./lib.rs:4:10: 4:15
        _11 = Lt(const 0usize, _10);     // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./2 Nested storing of mut refs./lib.rs:4:10: 4:15
        assert(_11, "index out of bounds: the len is {} but the index is {}", _10, const 0usize) -> bb1; // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./2 Nested storing of mut refs./lib.rs:4:10: 4:15
    }

    bb1: {
        _12 = CheckedAdd((*_6[const 0usize]), const 1i32); // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./2 Nested storing of mut refs./lib.rs:4:9: 4:20
        assert(!(_12.1: bool), "attempt to add with overflow") -> bb2; // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./2 Nested storing of mut refs./lib.rs:4:9: 4:20
    }

    bb2: {
        (*_6[const 0usize]) = (_12.0: i32); // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./2 Nested storing of mut refs./lib.rs:4:9: 4:20
        _5 = ();                         // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./2 Nested storing of mut refs./lib.rs:2:5: 5:6
        StorageDead(_6);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./2 Nested storing of mut refs./lib.rs:5:6: 5:6
        StorageLive(_13);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./2 Nested storing of mut refs./lib.rs:6:5: 6:6
        _13 = _3;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./2 Nested storing of mut refs./lib.rs:6:5: 6:6
        _0 = _13;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./2 Nested storing of mut refs./lib.rs:6:5: 6:6
        StorageDead(_13);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./2 Nested storing of mut refs./lib.rs:7:2: 7:2
        StorageDead(_4);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./2 Nested storing of mut refs./lib.rs:7:2: 7:2
        StorageDead(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./2 Nested storing of mut refs./lib.rs:7:2: 7:2
        return;                          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.11 Unary operator expressions/2 Mutable borrowing./2 Nested storing of mut refs./lib.rs:7:2: 7:2
    }
}
/- test.foo: unimplemented: arbitrary move of &mut | _7 -/

7.2.12 Binary operator expressions [ref]

7.2.12.1 Arithmetic operators [ref]

fn unsigned(x: u32, y: u32) {
    x + y;
    x - y;
    x * y;
    x / y;
    x % y;
}

fn signed(x: i32, y: i32) {
    x + y;
    x - y;
    x * y;
    x / y;
    x % y;
}
fn signed(_1: i32, _2: i32) -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let _3: i32;                     // "x" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:9:11: 9:12
        let _4: i32;                     // "y" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:9:19: 9:20
    }
    let mut _5: i32;
    let mut _6: i32;
    let mut _7: i32;
    let mut _8: (i32, bool);
    let mut _9: i32;
    let mut _10: i32;
    let mut _11: i32;
    let mut _12: (i32, bool);
    let mut _13: i32;
    let mut _14: i32;
    let mut _15: i32;
    let mut _16: (i32, bool);
    let mut _17: i32;
    let mut _18: i32;
    let mut _19: i32;
    let mut _20: bool;
    let mut _21: bool;
    let mut _22: bool;
    let mut _23: bool;
    let mut _24: i32;
    let mut _25: i32;
    let mut _26: i32;
    let mut _27: bool;
    let mut _28: bool;
    let mut _29: bool;
    let mut _30: bool;

    bb0: {
        StorageLive(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:9:11: 9:12
        _3 = _1;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:9:11: 9:12
        StorageLive(_4);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:9:19: 9:20
        _4 = _2;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:9:19: 9:20
        StorageLive(_6);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:10:5: 10:6
        _6 = _3;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:10:5: 10:6
        StorageLive(_7);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:10:9: 10:10
        _7 = _4;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:10:9: 10:10
        _8 = CheckedAdd(_6, _7);         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:10:5: 10:10
        assert(!(_8.1: bool), "attempt to add with overflow") -> bb1; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:10:5: 10:10
    }

    bb1: {
        _5 = (_8.0: i32);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:10:5: 10:10
        StorageDead(_7);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:10:11: 10:11
        StorageDead(_6);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:10:11: 10:11
        StorageLive(_10);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:11:5: 11:6
        _10 = _3;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:11:5: 11:6
        StorageLive(_11);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:11:9: 11:10
        _11 = _4;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:11:9: 11:10
        _12 = CheckedSub(_10, _11);      // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:11:5: 11:10
        assert(!(_12.1: bool), "attempt to subtract with overflow") -> bb2; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:11:5: 11:10
    }

    bb2: {
        _9 = (_12.0: i32);               // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:11:5: 11:10
        StorageDead(_11);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:11:11: 11:11
        StorageDead(_10);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:11:11: 11:11
        StorageLive(_14);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:12:5: 12:6
        _14 = _3;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:12:5: 12:6
        StorageLive(_15);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:12:9: 12:10
        _15 = _4;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:12:9: 12:10
        _16 = CheckedMul(_14, _15);      // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:12:5: 12:10
        assert(!(_16.1: bool), "attempt to multiply with overflow") -> bb3; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:12:5: 12:10
    }

    bb3: {
        _13 = (_16.0: i32);              // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:12:5: 12:10
        StorageDead(_15);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:12:11: 12:11
        StorageDead(_14);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:12:11: 12:11
        StorageLive(_18);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:13:5: 13:6
        _18 = _3;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:13:5: 13:6
        StorageLive(_19);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:13:9: 13:10
        _19 = _4;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:13:9: 13:10
        _20 = Eq(_19, const 0i32);       // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:13:5: 13:10
        assert(!_20, "attempt to divide by zero") -> bb4; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:13:5: 13:10
    }

    bb4: {
        _21 = Eq(_19, const -1i32);      // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:13:5: 13:10
        _22 = Eq(_18, const -2147483648i32); // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:13:5: 13:10
        _23 = BitAnd(_21, _22);          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:13:5: 13:10
        assert(!_23, "attempt to divide with overflow") -> bb5; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:13:5: 13:10
    }

    bb5: {
        _17 = Div(_18, _19);             // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:13:5: 13:10
        StorageDead(_19);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:13:11: 13:11
        StorageDead(_18);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:13:11: 13:11
        StorageLive(_25);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:14:5: 14:6
        _25 = _3;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:14:5: 14:6
        StorageLive(_26);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:14:9: 14:10
        _26 = _4;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:14:9: 14:10
        _27 = Eq(_26, const 0i32);       // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:14:5: 14:10
        assert(!_27, "attempt to calculate the remainder with a divisor of zero") -> bb6; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:14:5: 14:10
    }

    bb6: {
        _28 = Eq(_26, const -1i32);      // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:14:5: 14:10
        _29 = Eq(_25, const -2147483648i32); // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:14:5: 14:10
        _30 = BitAnd(_28, _29);          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:14:5: 14:10
        assert(!_30, "attempt to calculate the remainder with overflow") -> bb7; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:14:5: 14:10
    }

    bb7: {
        _24 = Rem(_25, _26);             // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:14:5: 14:10
        StorageDead(_26);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:14:11: 14:11
        StorageDead(_25);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:14:11: 14:11
        _0 = ();                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:9:27: 15:2
        StorageDead(_4);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:15:2: 15:2
        StorageDead(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:15:2: 15:2
        return;                          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:15:2: 15:2
    }
}

fn unsigned(_1: u32, _2: u32) -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let _3: u32;                     // "x" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:1:13: 1:14
        let _4: u32;                     // "y" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:1:21: 1:22
    }
    let mut _5: u32;
    let mut _6: u32;
    let mut _7: u32;
    let mut _8: (u32, bool);
    let mut _9: u32;
    let mut _10: u32;
    let mut _11: u32;
    let mut _12: (u32, bool);
    let mut _13: u32;
    let mut _14: u32;
    let mut _15: u32;
    let mut _16: (u32, bool);
    let mut _17: u32;
    let mut _18: u32;
    let mut _19: u32;
    let mut _20: bool;
    let mut _21: u32;
    let mut _22: u32;
    let mut _23: u32;
    let mut _24: bool;

    bb0: {
        StorageLive(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:1:13: 1:14
        _3 = _1;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:1:13: 1:14
        StorageLive(_4);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:1:21: 1:22
        _4 = _2;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:1:21: 1:22
        StorageLive(_6);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:2:5: 2:6
        _6 = _3;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:2:5: 2:6
        StorageLive(_7);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:2:9: 2:10
        _7 = _4;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:2:9: 2:10
        _8 = CheckedAdd(_6, _7);         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:2:5: 2:10
        assert(!(_8.1: bool), "attempt to add with overflow") -> bb1; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:2:5: 2:10
    }

    bb1: {
        _5 = (_8.0: u32);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:2:5: 2:10
        StorageDead(_7);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:2:11: 2:11
        StorageDead(_6);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:2:11: 2:11
        StorageLive(_10);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:3:5: 3:6
        _10 = _3;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:3:5: 3:6
        StorageLive(_11);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:3:9: 3:10
        _11 = _4;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:3:9: 3:10
        _12 = CheckedSub(_10, _11);      // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:3:5: 3:10
        assert(!(_12.1: bool), "attempt to subtract with overflow") -> bb2; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:3:5: 3:10
    }

    bb2: {
        _9 = (_12.0: u32);               // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:3:5: 3:10
        StorageDead(_11);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:3:11: 3:11
        StorageDead(_10);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:3:11: 3:11
        StorageLive(_14);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:4:5: 4:6
        _14 = _3;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:4:5: 4:6
        StorageLive(_15);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:4:9: 4:10
        _15 = _4;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:4:9: 4:10
        _16 = CheckedMul(_14, _15);      // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:4:5: 4:10
        assert(!(_16.1: bool), "attempt to multiply with overflow") -> bb3; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:4:5: 4:10
    }

    bb3: {
        _13 = (_16.0: u32);              // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:4:5: 4:10
        StorageDead(_15);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:4:11: 4:11
        StorageDead(_14);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:4:11: 4:11
        StorageLive(_18);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:5:5: 5:6
        _18 = _3;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:5:5: 5:6
        StorageLive(_19);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:5:9: 5:10
        _19 = _4;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:5:9: 5:10
        _20 = Eq(_19, const 0u32);       // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:5:5: 5:10
        assert(!_20, "attempt to divide by zero") -> bb4; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:5:5: 5:10
    }

    bb4: {
        _17 = Div(_18, _19);             // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:5:5: 5:10
        StorageDead(_19);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:5:11: 5:11
        StorageDead(_18);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:5:11: 5:11
        StorageLive(_22);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:6:5: 6:6
        _22 = _3;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:6:5: 6:6
        StorageLive(_23);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:6:9: 6:10
        _23 = _4;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:6:9: 6:10
        _24 = Eq(_23, const 0u32);       // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:6:5: 6:10
        assert(!_24, "attempt to calculate the remainder with a divisor of zero") -> bb5; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:6:5: 6:10
    }

    bb5: {
        _21 = Rem(_22, _23);             // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:6:5: 6:10
        StorageDead(_23);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:6:11: 6:11
        StorageDead(_22);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:6:11: 6:11
        _0 = ();                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:1:29: 7:2
        StorageDead(_4);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:7:2: 7:2
        StorageDead(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:7:2: 7:2
        return;                          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.1 Arithmetic operators/lib.rs:7:2: 7:2
    }
}
definition test.unsigned (xₐ : u32) (yₐ : u32) : sem (unit) :=
let' «x$3»  xₐ;
let' «y$4»  yₐ;
let' t6  «x$3»;
let' t7  «y$4»;
do «$tmp0»  sem.map (λx, (x, tt)) (checked.add u32.bits t6 t7);
let' t8  «$tmp0»;
let' t5  t8.1;
let' t10  «x$3»;
let' t11  «y$4»;
do «$tmp0»  sem.map (λx, (x, tt)) (checked.sub u32.bits t10 t11);
let' t12  «$tmp0»;
let' t9  t12.1;
let' t14  «x$3»;
let' t15  «y$4»;
do «$tmp0»  sem.map (λx, (x, tt)) (checked.mul u32.bits t14 t15);
let' t16  «$tmp0»;
let' t13  t16.1;
let' t18  «x$3»;
let' t19  «y$4»;
let' t20  t19 = (0 : nat);
do «$tmp0»  checked.div u32.bits t18 t19;
let' t17  «$tmp0»;
let' t22  «x$3»;
let' t23  «y$4»;
let' t24  t23 = (0 : nat);
do «$tmp0»  checked.rem u32.bits t22 t23;
let' t21  «$tmp0»;
let' ret  ;
return ()


definition test.signed (xₐ : i32) (yₐ : i32) : sem (unit) :=
let' «x$3»  xₐ;
let' «y$4»  yₐ;
let' t6  «x$3»;
let' t7  «y$4»;
do «$tmp0»  sem.map (λx, (x, tt)) (checked.sadd i32.bits t6 t7);
let' t8  «$tmp0»;
let' t5  t8.1;
let' t10  «x$3»;
let' t11  «y$4»;
do «$tmp0»  sem.map (λx, (x, tt)) (checked.ssub i32.bits t10 t11);
let' t12  «$tmp0»;
let' t9  t12.1;
let' t14  «x$3»;
let' t15  «y$4»;
do «$tmp0»  sem.map (λx, (x, tt)) (checked.smul i32.bits t14 t15);
let' t16  «$tmp0»;
let' t13  t16.1;
let' t18  «x$3»;
let' t19  «y$4»;
let' t20  t19 = (0 : int);
let' t21  t19 = (-1 : int);
let' t22  t18 = (-2147483648 : int);
let' t23  band t21 t22;
do «$tmp0»  checked.sdiv i32.bits t18 t19;
let' t17  «$tmp0»;
let' t25  «x$3»;
let' t26  «y$4»;
let' t27  t26 = (0 : int);
let' t28  t26 = (-1 : int);
let' t29  t25 = (-2147483648 : int);
let' t30  band t28 t29;
do «$tmp0»  checked.srem i32.bits t25 t26;
let' t24  «$tmp0»;
let' ret  ;
return ()

7.2.12.2 Bitwise operators [ref]

fn unsigned(x: u32, y: u32) {
    x & y;
    x | y;
    x ^ y;
    x << y;
    x >> y;
}

fn signed(x: i32, y: i32) {
    x & y;
    x | y;
    x ^ y;
    x << y;
    x >> y;
}

fn bool(x: bool, y: bool) {
    x & y;
    x | y;
    x ^ y;
}
fn bool(_1: bool, _2: bool) -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let _3: bool;                    // "x" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:17:9: 17:10
        let _4: bool;                    // "y" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:17:18: 17:19
    }
    let mut _5: bool;
    let mut _6: bool;
    let mut _7: bool;
    let mut _8: bool;
    let mut _9: bool;
    let mut _10: bool;
    let mut _11: bool;
    let mut _12: bool;
    let mut _13: bool;

    bb0: {
        StorageLive(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:17:9: 17:10
        _3 = _1;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:17:9: 17:10
        StorageLive(_4);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:17:18: 17:19
        _4 = _2;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:17:18: 17:19
        StorageLive(_6);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:18:5: 18:6
        _6 = _3;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:18:5: 18:6
        StorageLive(_7);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:18:9: 18:10
        _7 = _4;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:18:9: 18:10
        _5 = BitAnd(_6, _7);             // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:18:5: 18:10
        StorageDead(_7);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:18:11: 18:11
        StorageDead(_6);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:18:11: 18:11
        StorageLive(_9);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:19:5: 19:6
        _9 = _3;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:19:5: 19:6
        StorageLive(_10);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:19:9: 19:10
        _10 = _4;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:19:9: 19:10
        _8 = BitOr(_9, _10);             // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:19:5: 19:10
        StorageDead(_10);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:19:11: 19:11
        StorageDead(_9);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:19:11: 19:11
        StorageLive(_12);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:20:5: 20:6
        _12 = _3;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:20:5: 20:6
        StorageLive(_13);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:20:9: 20:10
        _13 = _4;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:20:9: 20:10
        _11 = BitXor(_12, _13);          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:20:5: 20:10
        StorageDead(_13);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:20:11: 20:11
        StorageDead(_12);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:20:11: 20:11
        _0 = ();                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:17:27: 21:2
        StorageDead(_4);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:21:2: 21:2
        StorageDead(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:21:2: 21:2
        return;                          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:21:2: 21:2
    }
}

fn signed(_1: i32, _2: i32) -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let _3: i32;                     // "x" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:9:11: 9:12
        let _4: i32;                     // "y" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:9:19: 9:20
    }
    let mut _5: i32;
    let mut _6: i32;
    let mut _7: i32;
    let mut _8: i32;
    let mut _9: i32;
    let mut _10: i32;
    let mut _11: i32;
    let mut _12: i32;
    let mut _13: i32;
    let mut _14: i32;
    let mut _15: i32;
    let mut _16: i32;
    let mut _17: (i32, bool);
    let mut _18: i32;
    let mut _19: i32;
    let mut _20: i32;
    let mut _21: (i32, bool);

    bb0: {
        StorageLive(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:9:11: 9:12
        _3 = _1;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:9:11: 9:12
        StorageLive(_4);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:9:19: 9:20
        _4 = _2;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:9:19: 9:20
        StorageLive(_6);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:10:5: 10:6
        _6 = _3;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:10:5: 10:6
        StorageLive(_7);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:10:9: 10:10
        _7 = _4;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:10:9: 10:10
        _5 = BitAnd(_6, _7);             // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:10:5: 10:10
        StorageDead(_7);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:10:11: 10:11
        StorageDead(_6);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:10:11: 10:11
        StorageLive(_9);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:11:5: 11:6
        _9 = _3;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:11:5: 11:6
        StorageLive(_10);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:11:9: 11:10
        _10 = _4;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:11:9: 11:10
        _8 = BitOr(_9, _10);             // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:11:5: 11:10
        StorageDead(_10);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:11:11: 11:11
        StorageDead(_9);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:11:11: 11:11
        StorageLive(_12);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:12:5: 12:6
        _12 = _3;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:12:5: 12:6
        StorageLive(_13);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:12:9: 12:10
        _13 = _4;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:12:9: 12:10
        _11 = BitXor(_12, _13);          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:12:5: 12:10
        StorageDead(_13);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:12:11: 12:11
        StorageDead(_12);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:12:11: 12:11
        StorageLive(_15);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:13:5: 13:6
        _15 = _3;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:13:5: 13:6
        StorageLive(_16);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:13:10: 13:11
        _16 = _4;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:13:10: 13:11
        _17 = CheckedShl(_15, _16);      // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:13:5: 13:11
        assert(!(_17.1: bool), "attempt to shift left with overflow") -> bb1; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:13:5: 13:11
    }

    bb1: {
        _14 = (_17.0: i32);              // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:13:5: 13:11
        StorageDead(_16);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:13:12: 13:12
        StorageDead(_15);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:13:12: 13:12
        StorageLive(_19);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:14:5: 14:6
        _19 = _3;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:14:5: 14:6
        StorageLive(_20);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:14:10: 14:11
        _20 = _4;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:14:10: 14:11
        _21 = CheckedShr(_19, _20);      // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:14:5: 14:11
        assert(!(_21.1: bool), "attempt to shift right with overflow") -> bb2; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:14:5: 14:11
    }

    bb2: {
        _18 = (_21.0: i32);              // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:14:5: 14:11
        StorageDead(_20);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:14:12: 14:12
        StorageDead(_19);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:14:12: 14:12
        _0 = ();                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:9:27: 15:2
        StorageDead(_4);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:15:2: 15:2
        StorageDead(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:15:2: 15:2
        return;                          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:15:2: 15:2
    }
}

fn unsigned(_1: u32, _2: u32) -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let _3: u32;                     // "x" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:1:13: 1:14
        let _4: u32;                     // "y" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:1:21: 1:22
    }
    let mut _5: u32;
    let mut _6: u32;
    let mut _7: u32;
    let mut _8: u32;
    let mut _9: u32;
    let mut _10: u32;
    let mut _11: u32;
    let mut _12: u32;
    let mut _13: u32;
    let mut _14: u32;
    let mut _15: u32;
    let mut _16: u32;
    let mut _17: (u32, bool);
    let mut _18: u32;
    let mut _19: u32;
    let mut _20: u32;
    let mut _21: (u32, bool);

    bb0: {
        StorageLive(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:1:13: 1:14
        _3 = _1;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:1:13: 1:14
        StorageLive(_4);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:1:21: 1:22
        _4 = _2;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:1:21: 1:22
        StorageLive(_6);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:2:5: 2:6
        _6 = _3;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:2:5: 2:6
        StorageLive(_7);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:2:9: 2:10
        _7 = _4;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:2:9: 2:10
        _5 = BitAnd(_6, _7);             // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:2:5: 2:10
        StorageDead(_7);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:2:11: 2:11
        StorageDead(_6);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:2:11: 2:11
        StorageLive(_9);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:3:5: 3:6
        _9 = _3;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:3:5: 3:6
        StorageLive(_10);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:3:9: 3:10
        _10 = _4;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:3:9: 3:10
        _8 = BitOr(_9, _10);             // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:3:5: 3:10
        StorageDead(_10);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:3:11: 3:11
        StorageDead(_9);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:3:11: 3:11
        StorageLive(_12);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:4:5: 4:6
        _12 = _3;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:4:5: 4:6
        StorageLive(_13);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:4:9: 4:10
        _13 = _4;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:4:9: 4:10
        _11 = BitXor(_12, _13);          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:4:5: 4:10
        StorageDead(_13);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:4:11: 4:11
        StorageDead(_12);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:4:11: 4:11
        StorageLive(_15);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:5:5: 5:6
        _15 = _3;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:5:5: 5:6
        StorageLive(_16);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:5:10: 5:11
        _16 = _4;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:5:10: 5:11
        _17 = CheckedShl(_15, _16);      // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:5:5: 5:11
        assert(!(_17.1: bool), "attempt to shift left with overflow") -> bb1; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:5:5: 5:11
    }

    bb1: {
        _14 = (_17.0: u32);              // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:5:5: 5:11
        StorageDead(_16);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:5:12: 5:12
        StorageDead(_15);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:5:12: 5:12
        StorageLive(_19);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:6:5: 6:6
        _19 = _3;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:6:5: 6:6
        StorageLive(_20);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:6:10: 6:11
        _20 = _4;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:6:10: 6:11
        _21 = CheckedShr(_19, _20);      // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:6:5: 6:11
        assert(!(_21.1: bool), "attempt to shift right with overflow") -> bb2; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:6:5: 6:11
    }

    bb2: {
        _18 = (_21.0: u32);              // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:6:5: 6:11
        StorageDead(_20);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:6:12: 6:12
        StorageDead(_19);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:6:12: 6:12
        _0 = ();                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:1:29: 7:2
        StorageDead(_4);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:7:2: 7:2
        StorageDead(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:7:2: 7:2
        return;                          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.2 Bitwise operators/lib.rs:7:2: 7:2
    }
}
definition test.unsigned (xₐ : u32) (yₐ : u32) : sem (unit) :=
let' «x$3»  xₐ;
let' «y$4»  yₐ;
let' t6  «x$3»;
let' t7  «y$4»;
let' t5  bitand u32.bits t6 t7;
let' t9  «x$3»;
let' t10  «y$4»;
let' t8  bitor u32.bits t9 t10;
let' t12  «x$3»;
let' t13  «y$4»;
let' t11  bitxor u32.bits t12 t13;
let' t15  «x$3»;
let' t16  «y$4»;
do «$tmp0»  sem.map (λx, (x, tt)) (checked.shl u32.bits t15 t16);
let' t17  «$tmp0»;
let' t14  t17.1;
let' t19  «x$3»;
let' t20  «y$4»;
do «$tmp0»  sem.map (λx, (x, tt)) (checked.shr u32.bits t19 t20);
let' t21  «$tmp0»;
let' t18  t21.1;
let' ret  ;
return ()


definition test.signed (xₐ : i32) (yₐ : i32) : sem (unit) :=
let' «x$3»  xₐ;
let' «y$4»  yₐ;
let' t6  «x$3»;
let' t7  «y$4»;
let' t5  sbitand i32.bits t6 t7;
let' t9  «x$3»;
let' t10  «y$4»;
let' t8  sbitor i32.bits t9 t10;
let' t12  «x$3»;
let' t13  «y$4»;
let' t11  sbitxor i32.bits t12 t13;
let' t15  «x$3»;
let' t16  «y$4»;
do «$tmp0»  sem.map (λx, (x, tt)) (checked.sshls i32.bits t15 t16);
let' t17  «$tmp0»;
let' t14  t17.1;
let' t19  «x$3»;
let' t20  «y$4»;
do «$tmp0»  sem.map (λx, (x, tt)) (checked.sshrs i32.bits t19 t20);
let' t21  «$tmp0»;
let' t18  t21.1;
let' ret  ;
return ()


definition test.bool (xₐ : bool) (yₐ : bool) : sem (unit) :=
let' «x$3»  xₐ;
let' «y$4»  yₐ;
let' t6  «x$3»;
let' t7  «y$4»;
let' t5  band t6 t7;
let' t9  «x$3»;
let' t10  «y$4»;
let' t8  bor t9 t10;
let' t12  «x$3»;
let' t13  «y$4»;
let' t11  bxor t12 t13;
let' ret  ;
return ()

7.2.12.3 Lazy boolean operators [ref]

fn main(x: bool, y: bool) {
    x && y;
    x || y;
}
fn main(_1: bool, _2: bool) -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let _3: bool;                    // "x" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.3 Lazy boolean operators/lib.rs:1:9: 1:10
        let _4: bool;                    // "y" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.3 Lazy boolean operators/lib.rs:1:18: 1:19
    }
    let mut _5: bool;
    let mut _6: bool;
    let mut _7: bool;
    let mut _8: bool;
    let mut _9: bool;
    let mut _10: bool;

    bb0: {
        StorageLive(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.3 Lazy boolean operators/lib.rs:1:9: 1:10
        _3 = _1;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.3 Lazy boolean operators/lib.rs:1:9: 1:10
        StorageLive(_4);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.3 Lazy boolean operators/lib.rs:1:18: 1:19
        _4 = _2;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.3 Lazy boolean operators/lib.rs:1:18: 1:19
        StorageLive(_6);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.3 Lazy boolean operators/lib.rs:2:5: 2:6
        _6 = _3;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.3 Lazy boolean operators/lib.rs:2:5: 2:6
        if(_6) -> [true: bb3, false: bb2]; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.3 Lazy boolean operators/lib.rs:2:5: 2:11
    }

    bb1: {
        _5 = const true;                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.3 Lazy boolean operators/lib.rs:2:5: 2:11
        goto -> bb4;                     // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.3 Lazy boolean operators/lib.rs:2:5: 2:11
    }

    bb2: {
        _5 = const false;                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.3 Lazy boolean operators/lib.rs:2:5: 2:11
        goto -> bb4;                     // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.3 Lazy boolean operators/lib.rs:2:5: 2:11
    }

    bb3: {
        StorageLive(_7);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.3 Lazy boolean operators/lib.rs:2:10: 2:11
        _7 = _4;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.3 Lazy boolean operators/lib.rs:2:10: 2:11
        StorageDead(_7);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.3 Lazy boolean operators/lib.rs:2:11: 2:11
        if(_7) -> [true: bb1, false: bb2]; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.3 Lazy boolean operators/lib.rs:2:5: 2:11
    }

    bb4: {
        StorageDead(_6);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.3 Lazy boolean operators/lib.rs:2:12: 2:12
        StorageLive(_9);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.3 Lazy boolean operators/lib.rs:3:5: 3:6
        _9 = _3;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.3 Lazy boolean operators/lib.rs:3:5: 3:6
        if(_9) -> [true: bb5, false: bb7]; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.3 Lazy boolean operators/lib.rs:3:5: 3:11
    }

    bb5: {
        _8 = const true;                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.3 Lazy boolean operators/lib.rs:3:5: 3:11
        goto -> bb8;                     // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.3 Lazy boolean operators/lib.rs:3:5: 3:11
    }

    bb6: {
        _8 = const false;                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.3 Lazy boolean operators/lib.rs:3:5: 3:11
        goto -> bb8;                     // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.3 Lazy boolean operators/lib.rs:3:5: 3:11
    }

    bb7: {
        StorageLive(_10);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.3 Lazy boolean operators/lib.rs:3:10: 3:11
        _10 = _4;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.3 Lazy boolean operators/lib.rs:3:10: 3:11
        StorageDead(_10);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.3 Lazy boolean operators/lib.rs:3:11: 3:11
        if(_10) -> [true: bb5, false: bb6]; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.3 Lazy boolean operators/lib.rs:3:5: 3:11
    }

    bb8: {
        StorageDead(_9);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.3 Lazy boolean operators/lib.rs:3:12: 3:12
        _0 = ();                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.3 Lazy boolean operators/lib.rs:1:27: 4:2
        StorageDead(_4);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.3 Lazy boolean operators/lib.rs:4:2: 4:2
        StorageDead(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.3 Lazy boolean operators/lib.rs:4:2: 4:2
        return;                          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.3 Lazy boolean operators/lib.rs:4:2: 4:2
    }
}
definition test.main (xₐ : bool) (yₐ : bool) : sem (unit) :=
let' «x$3»  xₐ;
let' «y$4»  yₐ;
let' t6  «x$3»;
if t6 = bool.tt then
let' t7  «y$4»;
if t7 = bool.tt then
let' t5  tt;
let' t9  «x$3»;
if t9 = bool.tt then
let' t8  tt;
let' ret  ;
return ()
else
let' t10  «y$4»;
if t10 = bool.tt then
let' t8  tt;
let' ret  ;
return ()
else
let' t8  ff;
let' ret  ;
return ()
else
let' t5  ff;
let' t9  «x$3»;
if t9 = bool.tt then
let' t8  tt;
let' ret  ;
return ()
else
let' t10  «y$4»;
if t10 = bool.tt then
let' t8  tt;
let' ret  ;
return ()
else
let' t8  ff;
let' ret  ;
return ()
else
let' t5  ff;
let' t9  «x$3»;
if t9 = bool.tt then
let' t8  tt;
let' ret  ;
return ()
else
let' t10  «y$4»;
if t10 = bool.tt then
let' t8  tt;
let' ret  ;
return ()
else
let' t8  ff;
let' ret  ;
return ()

7.2.12.4 Comparison operators [ref]

fn foo(x: i32, y: i32) -> bool { x < y }
// etc...
fn foo(_1: i32, _2: i32) -> bool {
    let mut _0: bool;                    // return pointer
    scope 1 {
        let _3: i32;                     // "x" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.4 Comparison operators/lib.rs:1:8: 1:9
        let _4: i32;                     // "y" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.4 Comparison operators/lib.rs:1:16: 1:17
    }
    let mut _5: i32;
    let mut _6: i32;

    bb0: {
        StorageLive(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.4 Comparison operators/lib.rs:1:8: 1:9
        _3 = _1;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.4 Comparison operators/lib.rs:1:8: 1:9
        StorageLive(_4);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.4 Comparison operators/lib.rs:1:16: 1:17
        _4 = _2;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.4 Comparison operators/lib.rs:1:16: 1:17
        StorageLive(_5);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.4 Comparison operators/lib.rs:1:34: 1:35
        _5 = _3;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.4 Comparison operators/lib.rs:1:34: 1:35
        StorageLive(_6);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.4 Comparison operators/lib.rs:1:38: 1:39
        _6 = _4;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.4 Comparison operators/lib.rs:1:38: 1:39
        _0 = Lt(_5, _6);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.4 Comparison operators/lib.rs:1:34: 1:39
        StorageDead(_6);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.4 Comparison operators/lib.rs:1:41: 1:41
        StorageDead(_5);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.4 Comparison operators/lib.rs:1:41: 1:41
        StorageDead(_4);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.4 Comparison operators/lib.rs:1:41: 1:41
        StorageDead(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.4 Comparison operators/lib.rs:1:41: 1:41
        return;                          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.4 Comparison operators/lib.rs:1:41: 1:41
    }
}
definition test.foo (xₐ : i32) (yₐ : i32) : sem (bool) :=
let' «x$3»  xₐ;
let' «y$4»  yₐ;
let' t5  «x$3»;
let' t6  «y$4»;
let' ret  t5 < t6;
return (ret)

7.2.12.5 Type cast expressions [ref]

Integral casts
fn foo(x: isize) -> u32 { x as u32 }
// etc...
fn foo(_1: isize) -> u32 {
    let mut _0: u32;                     // return pointer
    scope 1 {
        let _2: isize;                   // "x" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.5 Type cast expressions/1 Integral casts./lib.rs:1:8: 1:9
    }
    let mut _3: isize;

    bb0: {
        StorageLive(_2);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.5 Type cast expressions/1 Integral casts./lib.rs:1:8: 1:9
        _2 = _1;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.5 Type cast expressions/1 Integral casts./lib.rs:1:8: 1:9
        StorageLive(_3);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.5 Type cast expressions/1 Integral casts./lib.rs:1:27: 1:28
        _3 = _2;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.5 Type cast expressions/1 Integral casts./lib.rs:1:27: 1:28
        _0 = _3 as u32 (Misc);           // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.5 Type cast expressions/1 Integral casts./lib.rs:1:27: 1:35
        StorageDead(_3);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.5 Type cast expressions/1 Integral casts./lib.rs:1:37: 1:37
        StorageDead(_2);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.5 Type cast expressions/1 Integral casts./lib.rs:1:37: 1:37
        return;                          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.5 Type cast expressions/1 Integral casts./lib.rs:1:37: 1:37
    }
}
definition test.foo (xₐ : isize) : sem (u32) :=
let' «x$2»  xₐ;
let' t3  «x$2»;
do «$tmp0»  (signed_to_unsigned u32.bits t3);
let' ret  «$tmp0»;
return (ret)
Unsize casts

A no-op without trait objects and with identifying [T;N] and [T].

fn foo(x: &[u32; 2]) -> &[u32] { x }
fn foo(_1: &[u32; 2]) -> &[u32] {
    let mut _0: &[u32];                  // return pointer
    scope 1 {
        let _2: &[u32; 2];               // "x" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.5 Type cast expressions/2 Unsize casts./lib.rs:1:8: 1:9
    }
    let mut _3: &[u32; 2];

    bb0: {
        StorageLive(_2);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.5 Type cast expressions/2 Unsize casts./lib.rs:1:8: 1:9
        _2 = _1;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.5 Type cast expressions/2 Unsize casts./lib.rs:1:8: 1:9
        StorageLive(_3);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.5 Type cast expressions/2 Unsize casts./lib.rs:1:34: 1:35
        _3 = &(*_2);                     // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.5 Type cast expressions/2 Unsize casts./lib.rs:1:34: 1:35
        _0 = _3 as &[u32] (Unsize);      // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.5 Type cast expressions/2 Unsize casts./lib.rs:1:34: 1:35
        StorageDead(_3);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.5 Type cast expressions/2 Unsize casts./lib.rs:1:37: 1:37
        StorageDead(_2);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.5 Type cast expressions/2 Unsize casts./lib.rs:1:37: 1:37
        return;                          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.5 Type cast expressions/2 Unsize casts./lib.rs:1:37: 1:37
    }
}

const foo::{{initializer}}: usize = {
    let mut _0: usize;                   // return pointer

    bb0: {
        _0 = const 2usize;               // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.5 Type cast expressions/2 Unsize casts./lib.rs:1:18: 1:19
        return;                          // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.5 Type cast expressions/2 Unsize casts./lib.rs:1:18: 1:19
    }
}
definition test.foo (xₐ : (array u32 2)) : sem ((slice u32)) :=
let' «x$2»  xₐ;
let' t3  «x$2»;
let' ret  t3;
return (ret)

7.2.12.6 Assignment expressions [ref]

fn main() {
    let mut x = 1;
    x = 2;
}
fn main() -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let mut _1: i32;                 // "x" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/lib.rs:2:9: 2:14
    }

    bb0: {
        StorageLive(_1);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/lib.rs:2:9: 2:14
        _1 = const 1i32;                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/lib.rs:2:17: 2:18
        _1 = const 2i32;                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/lib.rs:3:5: 3:10
        _0 = ();                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/lib.rs:1:11: 4:2
        StorageDead(_1);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/lib.rs:4:2: 4:2
        return;                          // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/lib.rs:4:2: 4:2
    }
}
definition test.main : sem (unit) :=
let' «x$1»  (1 : int);
let' «x$1»  (2 : int);
let' ret  ;
return ()
Assignment through lvalue paths
struct S { x: [i32; 2] }

fn foo(mut s: S, i: usize) -> S {
    s.x[i] = 2;
    s
}
fn foo(_1: S, _2: usize) -> S {
    let mut _0: S;                       // return pointer
    scope 1 {
        let mut _3: S;                   // "s" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/1 Assignment through lvalue paths./lib.rs:3:8: 3:13
        let _4: usize;                   // "i" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/1 Assignment through lvalue paths./lib.rs:3:18: 3:19
    }
    let mut _5: usize;
    let mut _6: usize;
    let mut _7: bool;
    let mut _8: S;

    bb0: {
        StorageLive(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/1 Assignment through lvalue paths./lib.rs:3:8: 3:13
        _3 = _1;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/1 Assignment through lvalue paths./lib.rs:3:8: 3:13
        StorageLive(_4);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/1 Assignment through lvalue paths./lib.rs:3:18: 3:19
        _4 = _2;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/1 Assignment through lvalue paths./lib.rs:3:18: 3:19
        StorageLive(_5);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/1 Assignment through lvalue paths./lib.rs:4:9: 4:10
        _5 = _4;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/1 Assignment through lvalue paths./lib.rs:4:9: 4:10
        _6 = Len((_3.0: [i32; 2]));      // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/1 Assignment through lvalue paths./lib.rs:4:5: 4:11
        _7 = Lt(_5, _6);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/1 Assignment through lvalue paths./lib.rs:4:5: 4:11
        assert(_7, "index out of bounds: the len is {} but the index is {}", _6, _5) -> bb1; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/1 Assignment through lvalue paths./lib.rs:4:5: 4:11
    }

    bb1: {
        (_3.0: [i32; 2])[_5] = const 2i32; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/1 Assignment through lvalue paths./lib.rs:4:5: 4:15
        StorageDead(_5);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/1 Assignment through lvalue paths./lib.rs:4:16: 4:16
        StorageLive(_8);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/1 Assignment through lvalue paths./lib.rs:5:5: 5:6
        _8 = _3;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/1 Assignment through lvalue paths./lib.rs:5:5: 5:6
        _0 = _8;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/1 Assignment through lvalue paths./lib.rs:5:5: 5:6
        StorageDead(_8);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/1 Assignment through lvalue paths./lib.rs:6:2: 6:2
        StorageDead(_4);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/1 Assignment through lvalue paths./lib.rs:6:2: 6:2
        StorageDead(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/1 Assignment through lvalue paths./lib.rs:6:2: 6:2
        return;                          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/1 Assignment through lvalue paths./lib.rs:6:2: 6:2
    }
}

const S::{{initializer}}: usize = {
    let mut _0: usize;                   // return pointer

    bb0: {
        _0 = const 2usize;               // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/1 Assignment through lvalue paths./lib.rs:1:21: 1:22
        return;                          // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/1 Assignment through lvalue paths./lib.rs:1:21: 1:22
    }
}
structure test.S := mk {} ::
(x : (array i32 2))

definition test.foo (sₐ : (test.S)) (iₐ : usize) : sem ((test.S)) :=
let' «s$3»  sₐ;
let' «i$4»  iₐ;
let' t5  «i$4»;
let' t6  list.length (test.S.x «s$3»);
let' t7  t5 < t6;
do «$tmp2»  sem.lift_opt (list.update (test.S.x «s$3») t5 (2 : int));
let' «s$3»   (test.S), x := «$tmp2» ;
let' t8  «s$3»;
let' ret  t8;
return (ret)
example : sem.terminates_with (λ s', s' = test.S, x := [2, 42]⦄) (test.foo test.S, x := [41, 42]⦄ 0) := rfl

example : ¬sem.terminates (test.foo test.S, x := [41, 42]⦄ 2) := id
Assignment through mut refs
struct S { x: [i32; 2] }

fn foo(mut s: S) {
    let p = &mut s.x[0];
    *p = 2;
}
fn foo(_1: S) -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let mut _2: S;                   // "s" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/3 Assignment through mut refs./lib.rs:3:8: 3:13
        scope 2 {
            let _3: &mut i32;            // "p" in scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/3 Assignment through mut refs./lib.rs:4:9: 4:10
        }
    }
    let mut _4: usize;
    let mut _5: bool;

    bb0: {
        StorageLive(_2);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/3 Assignment through mut refs./lib.rs:3:8: 3:13
        _2 = _1;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/3 Assignment through mut refs./lib.rs:3:8: 3:13
        StorageLive(_3);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/3 Assignment through mut refs./lib.rs:4:9: 4:10
        _4 = Len((_2.0: [i32; 2]));      // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/3 Assignment through mut refs./lib.rs:4:18: 4:24
        _5 = Lt(const 0usize, _4);       // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/3 Assignment through mut refs./lib.rs:4:18: 4:24
        assert(_5, "index out of bounds: the len is {} but the index is {}", _4, const 0usize) -> bb1; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/3 Assignment through mut refs./lib.rs:4:18: 4:24
    }

    bb1: {
        _3 = &mut (_2.0: [i32; 2])[const 0usize]; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/3 Assignment through mut refs./lib.rs:4:13: 4:24
        (*_3) = const 2i32;              // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/3 Assignment through mut refs./lib.rs:5:5: 5:11
        _0 = ();                         // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/3 Assignment through mut refs./lib.rs:3:18: 6:2
        StorageDead(_3);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/3 Assignment through mut refs./lib.rs:6:2: 6:2
        StorageDead(_2);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/3 Assignment through mut refs./lib.rs:6:2: 6:2
        return;                          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/3 Assignment through mut refs./lib.rs:6:2: 6:2
    }
}

const S::{{initializer}}: usize = {
    let mut _0: usize;                   // return pointer

    bb0: {
        _0 = const 2usize;               // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/3 Assignment through mut refs./lib.rs:1:21: 1:22
        return;                          // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.12 Binary operator expressions/7.2.12.6 Assignment expressions/3 Assignment through mut refs./lib.rs:1:21: 1:22
    }
}
structure test.S := mk {} ::
(x : (array i32 2))

definition test.foo (sₐ : (test.S)) : sem (unit) :=
let' «s$2»  sₐ;
let' t4  list.length (test.S.x «s$2»);
let' t5  (0 : nat) < t4;
let' «p$3»  (lens.index _ (0 : nat)  lens.mk (return  test.S.x) (λ (o : (test.S)) i, return  (test.S), x := i ⦄));
do «$tmp»  lens.get «p$3» «s$2»;
do «s$2»  lens.set «p$3» «s$2» (2 : int);
let' ret  ;
return ()

7.2.12.7 Compound assignment expressions [ref]

Desugared in MIR

7.2.14 Call expressions [ref]

Calling a function increments the step counter via the dostep notation.

(Yes, that's the actual example from the reference. Though the implementation of add is hidden by default.)

fn add(x: i32, y: i32) -> i32 { 0 }

fn main() {
    let x: i32 = add(1i32, 2i32);
}
fn main() -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let _1: i32;                     // "x" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/lib.rs:4:9: 4:10
    }

    bb0: {
        StorageLive(_1);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/lib.rs:4:9: 4:10
        _1 = add(const 1i32, const 2i32) -> bb1; // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/lib.rs:4:18: 4:33
    }

    bb1: {
        _0 = ();                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/lib.rs:3:11: 5:2
        StorageDead(_1);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/lib.rs:5:2: 5:2
        return;                          // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/lib.rs:5:2: 5:2
    }
}

fn add(_1: i32, _2: i32) -> i32 {
    let mut _0: i32;                     // return pointer
    scope 1 {
        let _3: i32;                     // "x" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/lib.rs:1:8: 1:9
        let _4: i32;                     // "y" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/lib.rs:1:16: 1:17
    }

    bb0: {
        StorageLive(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/lib.rs:1:8: 1:9
        _3 = _1;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/lib.rs:1:8: 1:9
        StorageLive(_4);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/lib.rs:1:16: 1:17
        _4 = _2;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/lib.rs:1:16: 1:17
        _0 = const 0i32;                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/lib.rs:1:33: 1:34
        StorageDead(_4);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/lib.rs:1:36: 1:36
        StorageDead(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/lib.rs:1:36: 1:36
        return;                          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/lib.rs:1:36: 1:36
    }
}
definition test.add (xₐ : i32) (yₐ : i32) : sem (i32) :=
let' «x$3»  xₐ;
let' «y$4»  yₐ;
let' ret  (0 : int);
return (ret)


definition test.main : sem (unit) :=
dostep «$tmp»  @test.add (1 : int) (2 : int);
let' «x$1»  «$tmp»;
let' ret  ;
return ()

Mutable reference parameters

Passing a mutable reference means reading the current value from the lens, then writing back the new value through the lens.

fn set(x: &mut i32, y: i32) {
    *x = y
        ; () // FIXME: removing this line leaves `ret` uninitialized, which sounds at least like 'undesired behavior' from MIR
}

fn foo() -> i32 {
    let mut x = 1;
    set(&mut x, 2);
    x
}
fn foo() -> i32 {
    let mut _0: i32;                     // return pointer
    scope 1 {
        let mut _1: i32;                 // "x" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/1 Mutable reference parameters./lib.rs:7:9: 7:14
    }
    let mut _2: ();
    let mut _3: &mut i32;
    let mut _4: &mut i32;
    let mut _5: i32;

    bb0: {
        StorageLive(_1);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/1 Mutable reference parameters./lib.rs:7:9: 7:14
        _1 = const 1i32;                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/1 Mutable reference parameters./lib.rs:7:17: 7:18
        StorageLive(_3);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/1 Mutable reference parameters./lib.rs:8:9: 8:15
        StorageLive(_4);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/1 Mutable reference parameters./lib.rs:8:9: 8:15
        _4 = &mut _1;                    // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/1 Mutable reference parameters./lib.rs:8:9: 8:15
        _3 = &mut (*_4);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/1 Mutable reference parameters./lib.rs:8:9: 8:15
        _2 = set(_3, const 2i32) -> bb1; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/1 Mutable reference parameters./lib.rs:8:5: 8:19
    }

    bb1: {
        StorageDead(_3);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/1 Mutable reference parameters./lib.rs:8:20: 8:20
        StorageDead(_4);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/1 Mutable reference parameters./lib.rs:8:20: 8:20
        StorageLive(_5);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/1 Mutable reference parameters./lib.rs:9:5: 9:6
        _5 = _1;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/1 Mutable reference parameters./lib.rs:9:5: 9:6
        _0 = _5;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/1 Mutable reference parameters./lib.rs:9:5: 9:6
        StorageDead(_1);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/1 Mutable reference parameters./lib.rs:10:2: 10:2
        StorageDead(_5);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/1 Mutable reference parameters./lib.rs:10:2: 10:2
        return;                          // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/1 Mutable reference parameters./lib.rs:10:2: 10:2
    }
}

fn set(_1: &mut i32, _2: i32) -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let _3: &mut i32;                // "x" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/1 Mutable reference parameters./lib.rs:1:8: 1:9
        let _4: i32;                     // "y" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/1 Mutable reference parameters./lib.rs:1:21: 1:22
    }
    let mut _5: i32;

    bb0: {
        StorageLive(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/1 Mutable reference parameters./lib.rs:1:8: 1:9
        _3 = _1;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/1 Mutable reference parameters./lib.rs:1:8: 1:9
        StorageLive(_4);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/1 Mutable reference parameters./lib.rs:1:21: 1:22
        _4 = _2;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/1 Mutable reference parameters./lib.rs:1:21: 1:22
        StorageLive(_5);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/1 Mutable reference parameters./lib.rs:2:10: 2:11
        _5 = _4;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/1 Mutable reference parameters./lib.rs:2:10: 2:11
        (*_3) = _5;                      // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/1 Mutable reference parameters./lib.rs:2:5: 2:11
        StorageDead(_5);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/1 Mutable reference parameters./lib.rs:3:10: 3:10
        _0 = ();                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/1 Mutable reference parameters./lib.rs:3:11: 3:13
        StorageDead(_4);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/1 Mutable reference parameters./lib.rs:4:2: 4:2
        StorageDead(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/1 Mutable reference parameters./lib.rs:4:2: 4:2
        return;                          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/1 Mutable reference parameters./lib.rs:4:2: 4:2
    }
}
definition test.set (xₐ : i32) (yₐ : i32) : sem (unit × i32) :=
let' «x$3»  @lens.id i32;
let' «y$4»  yₐ;
let' t5  «y$4»;
do xₐ  lens.set «x$3» xₐ t5;
let' ret  ;
return (, xₐ)


definition test.foo : sem (i32) :=
let' «x$1»  (1 : int);
let' t4  @lens.id i32;
do «$tmp»  lens.get t4 «x$1»;
let' t3  (t4);
do «$tmp»  lens.get t3 «x$1»;
do «$tmp0»  lens.get t3 «x$1»;
dostep «$tmp»  @test.set «$tmp0» (2 : int);
match «$tmp» with (t2, «t3) :=
do «x$1»  lens.set t3 «x$1» «t3;
let' t5  «x$1»;
let' ret  t5;
return (ret)
end
example : sem.terminates_with (λ r, r = 2) test.foo := rfl

Mutable references as return values

We know that the return value will be a lens into the first argument, so we compose it with that one's lens. Note that we also get back the new value of the first argument.

fn foo(xs: &mut [i32]) -> &mut i32 {
    &mut xs[0]
}

fn bar(xs: &mut [i32]) {
    *foo(xs) = 2;
}
fn foo(_1: &mut [i32]) -> &mut i32 {
    let mut _0: &mut i32;                // return pointer
    scope 1 {
        let _2: &mut [i32];              // "xs" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/2 Mutable references as return values./lib.rs:1:8: 1:10
    }
    let mut _3: &mut i32;
    let mut _4: &mut i32;
    let mut _5: usize;
    let mut _6: bool;

    bb0: {
        StorageLive(_2);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/2 Mutable references as return values./lib.rs:1:8: 1:10
        _2 = _1;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/2 Mutable references as return values./lib.rs:1:8: 1:10
        StorageLive(_3);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/2 Mutable references as return values./lib.rs:1:36: 3:2
        StorageLive(_4);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/2 Mutable references as return values./lib.rs:2:5: 2:15
        _5 = Len((*_2));                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/2 Mutable references as return values./lib.rs:2:10: 2:15
        _6 = Lt(const 0usize, _5);       // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/2 Mutable references as return values./lib.rs:2:10: 2:15
        assert(_6, "index out of bounds: the len is {} but the index is {}", _5, const 0usize) -> bb1; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/2 Mutable references as return values./lib.rs:2:10: 2:15
    }

    bb1: {
        _4 = &mut (*_2)[const 0usize];   // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/2 Mutable references as return values./lib.rs:2:5: 2:15
        _3 = &mut (*_4);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/2 Mutable references as return values./lib.rs:2:5: 2:15
        _0 = &mut (*_3);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/2 Mutable references as return values./lib.rs:1:36: 3:2
        StorageDead(_3);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/2 Mutable references as return values./lib.rs:3:2: 3:2
        StorageDead(_4);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/2 Mutable references as return values./lib.rs:3:2: 3:2
        StorageDead(_2);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/2 Mutable references as return values./lib.rs:3:2: 3:2
        return;                          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/2 Mutable references as return values./lib.rs:3:2: 3:2
    }
}

fn bar(_1: &mut [i32]) -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let _2: &mut [i32];              // "xs" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/2 Mutable references as return values./lib.rs:5:8: 5:10
    }
    let mut _3: &mut i32;
    let mut _4: &mut [i32];

    bb0: {
        StorageLive(_2);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/2 Mutable references as return values./lib.rs:5:8: 5:10
        _2 = _1;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/2 Mutable references as return values./lib.rs:5:8: 5:10
        StorageLive(_3);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/2 Mutable references as return values./lib.rs:6:6: 6:13
        StorageLive(_4);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/2 Mutable references as return values./lib.rs:6:10: 6:12
        _4 = &mut (*_2);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/2 Mutable references as return values./lib.rs:6:10: 6:12
        _3 = foo(_4) -> bb1;             // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/2 Mutable references as return values./lib.rs:6:6: 6:13
    }

    bb1: {
        (*_3) = const 2i32;              // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/2 Mutable references as return values./lib.rs:6:5: 6:17
        StorageDead(_3);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/2 Mutable references as return values./lib.rs:6:18: 6:18
        StorageDead(_4);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/2 Mutable references as return values./lib.rs:6:18: 6:18
        _0 = ();                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/2 Mutable references as return values./lib.rs:5:24: 7:2
        StorageDead(_2);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/2 Mutable references as return values./lib.rs:7:2: 7:2
        return;                          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.14 Call expressions/2 Mutable references as return values./lib.rs:7:2: 7:2
    }
}
definition test.foo (xsₐ : (slice i32)) : sem ((lens (slice i32) i32) × (slice i32)) :=
let' «xs$2»  @lens.id (slice i32);
do «$tmp0»  do «$tmp0»  lens.get «xs$2» xsₐ;
return (list.length «$tmp0»);
let' t5  «$tmp0»;
let' t6  (0 : nat) < t5;
let' t4  (lens.index _ (0 : nat)  «xs$2»);
do «$tmp»  lens.get t4 xsₐ;
let' t3  (t4);
do «$tmp»  lens.get t3 xsₐ;
let' ret  (t3);
do «$tmp»  lens.get ret xsₐ;
return (ret, xsₐ)


definition test.bar (xsₐ : (slice i32)) : sem (unit × (slice i32)) :=
let' «xs$2»  @lens.id (slice i32);
let' t4  («xs$2»);
do «$tmp»  lens.get t4 xsₐ;
do «$tmp0»  lens.get t4 xsₐ;
dostep «$tmp»  @test.foo «$tmp0»;
match «$tmp» with («t3, «t4) :=
do xsₐ  lens.set t4 xsₐ «t4;
let' t3  («t3  t4);
do xsₐ  lens.set t3 xsₐ (2 : int);
let' ret  ;
return (, xsₐ)
end
example (x y : i32) : sem.terminates_with (λ r, r.2 = [2, y]) (test.bar [x, y]) := rfl

7.2.15 Lambda expressions [ref]

Compiling lambda expressions means creating a closure structure, a function for the lambda body taking that structure (and returning it for FnMut), and implementing the respective Fn trait.

fn apply<T, R, F: FnOnce(T) -> R>(f: F, x: T) -> R {
    f(x)
}

fn foo(x: i32, y: i32) -> i32 {
    apply(|x| x + y, x)
}
fn foo::{{closure}}(_1: [closure@ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:6:11: 6:20 y:&i32], _2: i32) -> i32 {
    let mut _0: i32;                     // return pointer
    scope 1 {
        let _3: i32;                     // "x" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:6:12: 6:13
    }
    let mut _4: i32;
    let mut _5: i32;
    let mut _6: (i32, bool);

    bb0: {
        StorageLive(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:6:12: 6:13
        _3 = _2;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:6:12: 6:13
        StorageLive(_4);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:6:15: 6:16
        _4 = _3;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:6:15: 6:16
        StorageLive(_5);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:6:19: 6:20
        _5 = (*(_1.0: &i32));            // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:6:19: 6:20
        _6 = CheckedAdd(_4, _5);         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:6:15: 6:20
        assert(!(_6.1: bool), "attempt to add with overflow") -> bb1; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:6:15: 6:20
    }

    bb1: {
        _0 = (_6.0: i32);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:6:15: 6:20
        StorageDead(_5);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:6:20: 6:20
        StorageDead(_4);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:6:20: 6:20
        StorageDead(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:6:20: 6:20
        return;                          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:6:20: 6:20
    }
}

fn foo(_1: i32, _2: i32) -> i32 {
    let mut _0: i32;                     // return pointer
    scope 1 {
        let _3: i32;                     // "x" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:5:8: 5:9
        let _4: i32;                     // "y" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:5:16: 5:17
    }
    let mut _5: [closure@ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:6:11: 6:20 y:&i32];
    let mut _6: &i32;
    let mut _7: i32;

    bb0: {
        StorageLive(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:5:8: 5:9
        _3 = _1;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:5:8: 5:9
        StorageLive(_4);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:5:16: 5:17
        _4 = _2;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:5:16: 5:17
        StorageLive(_5);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:6:11: 6:20
        StorageLive(_6);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:6:11: 6:20
        _6 = &_4;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:6:11: 6:20
        _5 = [closure@ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:6:11: 6:20] { y: _6 }; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:6:11: 6:20
        StorageLive(_7);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:6:22: 6:23
        _7 = _3;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:6:22: 6:23
        _0 = apply::<i32, i32, [closure@ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:6:11: 6:20 y:&i32]>(_5, _7) -> bb1; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:6:5: 6:24
    }

    bb1: {
        StorageDead(_7);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:7:2: 7:2
        StorageDead(_5);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:7:2: 7:2
        StorageDead(_6);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:7:2: 7:2
        StorageDead(_4);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:7:2: 7:2
        StorageDead(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:7:2: 7:2
        return;                          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:7:2: 7:2
    }
}

fn apply(_1: F, _2: T) -> R {
    let mut _0: R;                       // return pointer
    scope 1 {
        let _3: F;                       // "f" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:1:35: 1:36
        let _4: T;                       // "x" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:1:41: 1:42
    }
    let mut _5: F;
    let mut _6: ();
    let mut _7: (T,);
    let mut _8: T;

    bb0: {
        StorageLive(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:1:35: 1:36
        _3 = _1;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:1:35: 1:36
        StorageLive(_4);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:1:41: 1:42
        _4 = _2;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:1:41: 1:42
        StorageLive(_5);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:2:5: 2:6
        _5 = _3;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:2:5: 2:6
        StorageLive(_7);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:2:5: 2:9
        StorageLive(_8);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:2:7: 2:8
        _8 = _4;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:2:7: 2:8
        _7 = (_8,);                      // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:2:5: 2:9
        _0 = <F as std::ops::FnOnce<(T,)>>::call_once(_5, _7) -> [return: bb8, unwind: bb9]; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:2:5: 2:9
    }

    bb1: {
        resume;                          // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:1:1: 3:2
    }

    bb2: {
        drop(_3) -> bb1;                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:3:2: 3:2
    }

    bb3: {
        drop(_1) -> bb2;                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:3:2: 3:2
    }

    bb4: {
        drop(_4) -> bb3;                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:3:2: 3:2
    }

    bb5: {
        drop(_2) -> bb4;                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:3:2: 3:2
    }

    bb6: {
        drop(_5) -> bb5;                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:3:2: 3:2
    }

    bb7: {
        drop(_8) -> bb6;                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:3:2: 3:2
    }

    bb8: {
        drop(_7) -> [return: bb10, unwind: bb7]; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:3:2: 3:2
    }

    bb9: {
        drop(_7) -> bb7;                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:3:2: 3:2
    }

    bb10: {
        StorageDead(_7);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:3:2: 3:2
        drop(_8) -> [return: bb11, unwind: bb6]; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:3:2: 3:2
    }

    bb11: {
        StorageDead(_8);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:3:2: 3:2
        drop(_5) -> [return: bb12, unwind: bb5]; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:3:2: 3:2
    }

    bb12: {
        StorageDead(_5);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:3:2: 3:2
        drop(_2) -> [return: bb13, unwind: bb4]; // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:3:2: 3:2
    }

    bb13: {
        drop(_4) -> [return: bb14, unwind: bb3]; // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:3:2: 3:2
    }

    bb14: {
        StorageDead(_4);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:3:2: 3:2
        drop(_1) -> [return: bb15, unwind: bb2]; // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:3:2: 3:2
    }

    bb15: {
        drop(_3) -> bb16;                // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:3:2: 3:2
    }

    bb16: {
        StorageDead(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:3:2: 3:2
        return;                          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/lib.rs:3:2: 3:2
    }
}
definition test.apply {T : Type₁} {R : Type₁} {F : Type₁} [«core.ops.FnOnce F T» : core.ops.FnOnce F T R] (fₐ : F) (xₐ : T) : sem (R) :=
let' «f$3»  fₐ;
let' «x$4»  xₐ;
let' t5  «f$3»;
let' t8  «x$4»;
let' t7  t8;
dostep «$tmp»  @core.ops.FnOnce.call_once F T R «core.ops.FnOnce F T» t5 t7;
let' ret  «$tmp»;
return (ret)


section

structure test.foo.closure_13 (U0 : Type₁) := (val : U0)



definition test.foo.closure_13.fn («$a1» : (test.foo.closure_13 i32)) (xₐ : i32) : sem (i32) :=
let' «x$3»  xₐ;
let' t4  «x$3»;
let' t5  (test.foo.closure_13.val «$a1»);
do «$tmp0»  sem.map (λx, (x, tt)) (checked.sadd i32.bits t4 t5);
let' t6  «$tmp0»;
let' ret  t6.1;
return (ret)



definition test.foo.closure_13.inst [instance] : core.ops.FnOnce (test.foo.closure_13 i32) i32 i32 :=
core.ops.FnOnce.mk_simple (λ self args, let' xₐ  args;
  test.foo.closure_13.fn self xₐ
)

end

definition test.foo (xₐ : i32) (yₐ : i32) : sem (i32) :=
let' «x$3»  xₐ;
let' «y$4»  yₐ;
let' t6  «y$4»;
let' t5  test.foo.closure_13.mk t6;
let' t7  «x$3»;
dostep «$tmp»  @test.apply i32 i32 (test.foo.closure_13 i32) (@test.foo.closure_13.inst ) t5 t7;
let' ret  «$tmp»;
return (ret)

Mutable closures

Mutable closures work out of the box as long as they don't close over mutable references - that would require nested storing of &mut.

fn apply<T, F: FnMut(T) -> T>(mut f: F, x: T) -> T {
    let y = f(x);
    f(y)
}

fn foo(x: i32, mut y: i32) -> i32 {
    apply(move |x| {
        y += 1;
        x + y
    }, x)
}
fn foo::{{closure}}(_1: &mut [closure@ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:7:11: 10:6 y:i32], _2: i32) -> i32 {
    let mut _0: i32;                     // return pointer
    scope 1 {
        let _3: i32;                     // "x" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:7:17: 7:18
    }
    let mut _4: (i32, bool);
    let mut _5: i32;
    let mut _6: i32;
    let mut _7: (i32, bool);

    bb0: {
        StorageLive(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:7:17: 7:18
        _3 = _2;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:7:17: 7:18
        _4 = CheckedAdd(((*_1).0: i32), const 1i32); // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:8:9: 8:15
        assert(!(_4.1: bool), "attempt to add with overflow") -> bb1; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:8:9: 8:15
    }

    bb1: {
        ((*_1).0: i32) = (_4.0: i32);    // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:8:9: 8:15
        StorageLive(_5);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:9:9: 9:10
        _5 = _3;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:9:9: 9:10
        StorageLive(_6);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:9:13: 9:14
        _6 = ((*_1).0: i32);             // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:9:13: 9:14
        _7 = CheckedAdd(_5, _6);         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:9:9: 9:14
        assert(!(_7.1: bool), "attempt to add with overflow") -> bb2; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:9:9: 9:14
    }

    bb2: {
        _0 = (_7.0: i32);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:9:9: 9:14
        StorageDead(_6);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:10:6: 10:6
        StorageDead(_5);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:10:6: 10:6
        StorageDead(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:10:6: 10:6
        return;                          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:10:6: 10:6
    }
}

fn foo(_1: i32, _2: i32) -> i32 {
    let mut _0: i32;                     // return pointer
    scope 1 {
        let _3: i32;                     // "x" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:6:8: 6:9
        let mut _4: i32;                 // "y" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:6:16: 6:21
    }
    let mut _5: [closure@ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:7:11: 10:6 y:i32];
    let mut _6: i32;
    let mut _7: i32;

    bb0: {
        StorageLive(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:6:8: 6:9
        _3 = _1;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:6:8: 6:9
        StorageLive(_4);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:6:16: 6:21
        _4 = _2;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:6:16: 6:21
        StorageLive(_5);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:7:11: 10:6
        StorageLive(_6);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:7:11: 10:6
        _6 = _4;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:7:11: 10:6
        _5 = [closure@ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:7:11: 10:6] { y: _6 }; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:7:11: 10:6
        StorageLive(_7);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:10:8: 10:9
        _7 = _3;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:10:8: 10:9
        _0 = apply::<i32, [closure@ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:7:11: 10:6 y:i32]>(_5, _7) -> bb1; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:7:5: 10:10
    }

    bb1: {
        StorageDead(_7);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:11:2: 11:2
        StorageDead(_5);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:11:2: 11:2
        StorageDead(_6);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:11:2: 11:2
        StorageDead(_4);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:11:2: 11:2
        StorageDead(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:11:2: 11:2
        return;                          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:11:2: 11:2
    }
}

fn apply(_1: F, _2: T) -> T {
    let mut _0: T;                       // return pointer
    scope 1 {
        let mut _3: F;                   // "f" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:1:31: 1:36
        let _4: T;                       // "x" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:1:41: 1:42
        scope 2 {
            let _5: T;                   // "y" in scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:2:9: 2:10
        }
    }
    let mut _6: &mut F;
    let mut _7: ();
    let mut _8: (T,);
    let mut _9: T;
    let mut _10: &mut F;
    let mut _11: (T,);
    let mut _12: T;

    bb0: {
        StorageLive(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:1:31: 1:36
        _3 = _1;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:1:31: 1:36
        StorageLive(_4);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:1:41: 1:42
        _4 = _2;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:1:41: 1:42
        StorageLive(_5);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:2:9: 2:10
        StorageLive(_6);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:2:13: 2:14
        _6 = &mut _3;                    // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:2:13: 2:14
        StorageLive(_8);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:2:13: 2:17
        StorageLive(_9);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:2:15: 2:16
        _9 = _4;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:2:15: 2:16
        _8 = (_9,);                      // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:2:13: 2:17
        _5 = <F as std::ops::FnMut<(T,)>>::call_mut(_6, _8) -> [return: bb8, unwind: bb9]; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:2:13: 2:17
    }

    bb1: {
        resume;                          // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:1:1: 4:2
    }

    bb2: {
        drop(_3) -> bb1;                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:4:2: 4:2
    }

    bb3: {
        drop(_1) -> bb2;                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:4:2: 4:2
    }

    bb4: {
        drop(_4) -> bb3;                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:4:2: 4:2
    }

    bb5: {
        drop(_2) -> bb4;                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:4:2: 4:2
    }

    bb6: {
        drop(_5) -> bb5;                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:4:2: 4:2
    }

    bb7: {
        drop(_9) -> bb6;                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:2:18: 2:18
    }

    bb8: {
        drop(_8) -> [return: bb10, unwind: bb7]; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:2:18: 2:18
    }

    bb9: {
        drop(_8) -> bb7;                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:2:18: 2:18
    }

    bb10: {
        StorageDead(_8);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:2:18: 2:18
        drop(_9) -> [return: bb11, unwind: bb6]; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:2:18: 2:18
    }

    bb11: {
        StorageDead(_9);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:2:18: 2:18
        StorageDead(_6);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:2:18: 2:18
        StorageLive(_10);                // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:3:5: 3:6
        _10 = &mut _3;                   // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:3:5: 3:6
        StorageLive(_11);                // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:3:5: 3:9
        StorageLive(_12);                // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:3:7: 3:8
        _12 = _5;                        // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:3:7: 3:8
        _11 = (_12,);                    // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:3:5: 3:9
        _0 = <F as std::ops::FnMut<(T,)>>::call_mut(_10, _11) -> [return: bb13, unwind: bb15]; // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:3:5: 3:9
    }

    bb12: {
        drop(_12) -> bb5;                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:4:2: 4:2
    }

    bb13: {
        drop(_5) -> [return: bb16, unwind: bb14]; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:4:2: 4:2
    }

    bb14: {
        drop(_11) -> bb12;               // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:4:2: 4:2
    }

    bb15: {
        drop(_5) -> bb14;                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:4:2: 4:2
    }

    bb16: {
        StorageDead(_5);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:4:2: 4:2
        drop(_11) -> [return: bb17, unwind: bb12]; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:4:2: 4:2
    }

    bb17: {
        StorageDead(_11);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:4:2: 4:2
        drop(_12) -> [return: bb18, unwind: bb5]; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:4:2: 4:2
    }

    bb18: {
        StorageDead(_12);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:4:2: 4:2
        StorageDead(_10);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:4:2: 4:2
        drop(_2) -> [return: bb19, unwind: bb4]; // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:4:2: 4:2
    }

    bb19: {
        drop(_4) -> [return: bb20, unwind: bb3]; // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:4:2: 4:2
    }

    bb20: {
        StorageDead(_4);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:4:2: 4:2
        drop(_1) -> [return: bb21, unwind: bb2]; // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:4:2: 4:2
    }

    bb21: {
        drop(_3) -> bb22;                // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:4:2: 4:2
    }

    bb22: {
        StorageDead(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:4:2: 4:2
        return;                          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.15 Lambda expressions/1 Mutable closures./lib.rs:4:2: 4:2
    }
}
definition test.apply {T : Type₁} {F : Type₁} [«core.ops.FnMut F T» : core.ops.FnMut F T T] (fₐ : F) (xₐ : T) : sem (T) :=
let' «f$3»  fₐ;
let' «x$4»  xₐ;
let' t6  @lens.id F;
do «$tmp»  lens.get t6 «f$3»;
let' t9  «x$4»;
let' t8  t9;
do «$tmp0»  lens.get t6 «f$3»;
dostep «$tmp»  @core.ops.FnMut.call_mut F T T «core.ops.FnMut F T» «$tmp0» t8;
match «$tmp» with («y$5», «t6) :=
do «f$3»  lens.set t6 «f$3» «t6;
let' t10  @lens.id F;
do «$tmp»  lens.get t10 «f$3»;
let' t12  «y$5»;
let' t11  t12;
do «$tmp0»  lens.get t10 «f$3»;
dostep «$tmp»  @core.ops.FnMut.call_mut F T T «core.ops.FnMut F T» «$tmp0» t11;
match «$tmp» with (ret, «t10) :=
do «f$3»  lens.set t10 «f$3» «t10;
return (ret)
end
end


section

structure test.foo.closure_13 (U0 : Type₁) := (val : U0)



definition test.foo.closure_13.fn («$a1» : (test.foo.closure_13 i32)) (xₐ : i32) : sem (i32 × (test.foo.closure_13 i32)) :=
let' «x$3»  xₐ;
do «$tmp0»  sem.map (λx, (x, tt)) (checked.sadd i32.bits (test.foo.closure_13.val «$a1») (1 : int));
let' t4  «$tmp0»;
let' «$a1»  test.foo.closure_13.mk t4.1;
let' t5  «x$3»;
let' t6  (test.foo.closure_13.val «$a1»);
do «$tmp0»  sem.map (λx, (x, tt)) (checked.sadd i32.bits t5 t6);
let' t7  «$tmp0»;
let' ret  t7.1;
return (ret, «$a1»)



definition test.foo.closure_13.inst [instance] : core.ops.FnMut (test.foo.closure_13 i32) i32 i32 :=
core.ops.FnMut.mk_simple (λ self args, let' xₐ  args;
  test.foo.closure_13.fn self xₐ
)

end

definition test.foo (xₐ : i32) (yₐ : i32) : sem (i32) :=
let' «x$3»  xₐ;
let' «y$4»  yₐ;
let' t6  «y$4»;
let' t5  test.foo.closure_13.mk t6;
let' t7  «x$3»;
dostep «$tmp»  @test.apply i32 (test.foo.closure_13 i32) (@test.foo.closure_13.inst ) t5 t7;
let' ret  «$tmp»;
return (ret)

Loops

There is no for, while, loop, continue, or break in MIR, just control flow edges. So we search for strongly connected components in the MIR graph (via petgraph), translate them into separate helper definitions, and compute a fixed point (if any) via a generic loop combinator.

fn foo(mut x: i32) {
    while x != 0 {
        if x == 1 { continue };
        if x == 2 { break; };
        if x == 3 { return; }
        x -= 1;
    }
}
fn foo(_1: i32) -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let mut _2: i32;                 // "x" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:1:8: 1:13
    }
    let mut _3: bool;
    let mut _4: i32;
    let mut _5: ();
    let mut _6: ();
    let mut _7: bool;
    let mut _8: i32;
    let mut _9: !;
    let mut _10: ();
    let mut _11: bool;
    let mut _12: i32;
    let mut _13: ();
    let mut _14: !;
    let mut _15: ();
    let mut _16: bool;
    let mut _17: i32;
    let mut _18: ();
    let mut _19: !;
    let mut _20: (i32, bool);

    bb0: {
        StorageLive(_2);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:1:8: 1:13
        _2 = _1;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:1:8: 1:13
        goto -> bb1;                     // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:2:5: 7:6
    }

    bb1: {
        StorageLive(_3);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:2:11: 2:17
        StorageLive(_4);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:2:11: 2:12
        _4 = _2;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:2:11: 2:12
        _3 = Ne(_4, const 0i32);         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:2:11: 2:17
        StorageDead(_3);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:2:17: 2:17
        StorageDead(_4);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:2:17: 2:17
        if(_3) -> [true: bb3, false: bb2]; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:2:5: 7:6
    }

    bb2: {
        _0 = ();                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:2:5: 7:6
        StorageDead(_2);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:8:2: 8:2
        goto -> bb10;                    // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:8:2: 8:2
    }

    bb3: {
        StorageLive(_7);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:3:12: 3:18
        StorageLive(_8);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:3:12: 3:13
        _8 = _2;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:3:12: 3:13
        _7 = Eq(_8, const 1i32);         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:3:12: 3:18
        StorageDead(_7);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:3:18: 3:18
        StorageDead(_8);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:3:18: 3:18
        if(_7) -> [true: bb4, false: bb5]; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:3:9: 3:31
    }

    bb4: {
        StorageLive(_9);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:3:21: 3:29
        goto -> bb1;                     // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:3:21: 3:29
    }

    bb5: {
        _6 = ();                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:3:9: 3:31
        StorageLive(_11);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:4:12: 4:18
        StorageLive(_12);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:4:12: 4:13
        _12 = _2;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:4:12: 4:13
        _11 = Eq(_12, const 2i32);       // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:4:12: 4:18
        StorageDead(_11);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:4:18: 4:18
        StorageDead(_12);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:4:18: 4:18
        if(_11) -> [true: bb6, false: bb7]; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:4:9: 4:29
    }

    bb6: {
        StorageLive(_14);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:4:21: 4:26
        goto -> bb2;                     // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:4:21: 4:26
    }

    bb7: {
        _10 = ();                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:4:9: 4:29
        StorageLive(_16);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:5:12: 5:18
        StorageLive(_17);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:5:12: 5:13
        _17 = _2;                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:5:12: 5:13
        _16 = Eq(_17, const 3i32);       // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:5:12: 5:18
        StorageDead(_16);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:5:18: 5:18
        StorageDead(_17);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:5:18: 5:18
        if(_16) -> [true: bb8, false: bb9]; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:5:9: 5:30
    }

    bb8: {
        StorageLive(_19);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:5:21: 5:27
        _0 = ();                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:5:21: 5:27
        StorageDead(_2);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:8:2: 8:2
        goto -> bb10;                    // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:5:21: 5:27
    }

    bb9: {
        _15 = ();                        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:5:9: 5:30
        _20 = CheckedSub(_2, const 1i32); // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:6:9: 6:15
        assert(!(_20.1: bool), "attempt to subtract with overflow") -> bb11; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:6:9: 6:15
    }

    bb10: {
        return;                          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:8:2: 8:2
    }

    bb11: {
        _2 = (_20.0: i32);               // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:6:9: 6:15
        _5 = ();                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:2:18: 7:6
        goto -> bb1;                     // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./lib.rs:2:5: 7:6
    }
}
section
definition test.foo.loop_1 (state__ : i32) : sem (sum (i32) (unit)) :=
let' «x$2»  state__;
let' t4  «x$2»;
let' t3  t4  (0 : int);
if t3 = bool.tt then
let' t8  «x$2»;
let' t7  t8 = (1 : int);
if t7 = bool.tt then
return (sum.inl «x$2»)
else
let' t6  ;
let' t12  «x$2»;
let' t11  t12 = (2 : int);
if t11 = bool.tt then
do tmp__  let' ret  ;
return ()
;
return (sum.inr tmp__)else
let' t10  ;
let' t17  «x$2»;
let' t16  t17 = (3 : int);
if t16 = bool.tt then
do tmp__  let' ret  ;
return ()
;
return (sum.inr tmp__)else
let' t15  ;
do «$tmp0»  sem.map (λx, (x, tt)) (checked.ssub i32.bits «x$2» (1 : int));
let' t20  «$tmp0»;
let' «x$2»  t20.1;
let' t5  ;
return (sum.inl «x$2»)
else
do tmp__  let' ret  ;
return ()
;
return (sum.inr tmp__)

definition test.foo (xₐ : i32) : sem (unit) :=
let' «x$2»  xₐ;
loop (test.foo.loop_1) «x$2»

end

Mutable borrowing in loops

Basically an instance of Returning arbitrary mutable references.

/*
// would require generalized mutually inductive types
enum List<T> {
    Single(T),
    Cons(T, Box<List<T>>),
}

impl<T> List<T> {
    fn last_mut(&mut self) -> &mut T {
        let mut xs = self;
        loop {
            let tmp = xs;
            xs = match tmp {
                &mut List::Single(ref mut x) => return x,
                &mut List::Cons(_, ref mut b) => &mut *b,
            };
        }
    }
}*/

fn foo(mut xs: &mut [i32]) {
    loop {
        let tmp = xs;
        xs = &mut tmp[2..];
    }
}
fn foo(_1: &mut [i32]) -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let mut _2: &mut [i32];          // "xs" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./1 Mutable borrowing in loops./lib.rs:21:8: 21:14
        scope 2 {
            let _5: &mut [i32];          // "tmp" in scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./1 Mutable borrowing in loops./lib.rs:23:13: 23:16
        }
    }
    let mut _3: !;
    let mut _4: ();
    let mut _6: &mut [i32];
    let mut _7: &mut [i32];
    let mut _8: &mut [i32];
    let mut _9: &mut [i32];
    let mut _10: std::ops::RangeFrom<usize>;
    let mut _11: usize;

    bb0: {
        StorageLive(_2);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./1 Mutable borrowing in loops./lib.rs:21:8: 21:14
        _2 = _1;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./1 Mutable borrowing in loops./lib.rs:21:8: 21:14
        StorageLive(_3);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./1 Mutable borrowing in loops./lib.rs:22:5: 25:6
        goto -> bb1;                     // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./1 Mutable borrowing in loops./lib.rs:22:5: 25:6
    }

    bb1: {
        StorageLive(_5);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./1 Mutable borrowing in loops./lib.rs:23:13: 23:16
        StorageLive(_6);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./1 Mutable borrowing in loops./lib.rs:23:19: 23:21
        _6 = _2;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./1 Mutable borrowing in loops./lib.rs:23:19: 23:21
        _5 = _6;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./1 Mutable borrowing in loops./lib.rs:23:19: 23:21
        StorageDead(_6);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./1 Mutable borrowing in loops./lib.rs:23:22: 23:22
        StorageLive(_7);                 // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./1 Mutable borrowing in loops./lib.rs:24:14: 24:27
        StorageLive(_8);                 // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./1 Mutable borrowing in loops./lib.rs:24:19: 24:27
        StorageLive(_9);                 // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./1 Mutable borrowing in loops./lib.rs:24:19: 24:22
        _9 = &mut (*_5);                 // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./1 Mutable borrowing in loops./lib.rs:24:19: 24:22
        StorageLive(_10);                // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./1 Mutable borrowing in loops./lib.rs:24:23: 24:26
        StorageLive(_11);                // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./1 Mutable borrowing in loops./lib.rs:24:23: 24:24
        _11 = const 2usize;              // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./1 Mutable borrowing in loops./lib.rs:24:23: 24:24
        _10 = std::ops::RangeFrom<usize> { start: _11 }; // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./1 Mutable borrowing in loops./lib.rs:24:23: 24:26
        _8 = <[i32] as std::ops::IndexMut<std::ops::RangeFrom<usize>>>::index_mut(_9, _10) -> bb2; // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./1 Mutable borrowing in loops./lib.rs:24:19: 24:27
    }

    bb2: {
        _7 = &mut (*_8);                 // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./1 Mutable borrowing in loops./lib.rs:24:14: 24:27
        _2 = &mut (*_7);                 // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./1 Mutable borrowing in loops./lib.rs:24:9: 24:27
        StorageDead(_7);                 // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./1 Mutable borrowing in loops./lib.rs:24:28: 24:28
        StorageDead(_8);                 // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./1 Mutable borrowing in loops./lib.rs:24:28: 24:28
        StorageDead(_10);                // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./1 Mutable borrowing in loops./lib.rs:24:28: 24:28
        StorageDead(_11);                // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./1 Mutable borrowing in loops./lib.rs:24:28: 24:28
        StorageDead(_9);                 // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./1 Mutable borrowing in loops./lib.rs:24:28: 24:28
        _4 = ();                         // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./1 Mutable borrowing in loops./lib.rs:22:10: 25:6
        StorageDead(_5);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./1 Mutable borrowing in loops./lib.rs:25:6: 25:6
        goto -> bb1;                     // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.16-20 Loops./1 Mutable borrowing in loops./lib.rs:22:5: 25:6
    }
}
/- test.foo: unimplemented: &mut nested in type -/

7.2.21 if expressions [ref]

We currently translate all arms of an if or match separately, which is easy but not ideal if the control flow converges again at a later point (where 'not ideal' is a nice way of saying 'overhead exponential in the number of sequential ifs'). It works fine for now, but we should factor out convergence points into separate helper definitions at some point (just as we're already doing for loops).

fn foo(b: bool, c: bool) -> i32 {
    let mut x = 0;
    if b { x += 1 }
    if c { x += 1 }
    x
}
fn foo(_1: bool, _2: bool) -> i32 {
    let mut _0: i32;                     // return pointer
    scope 1 {
        let _3: bool;                    // "b" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.21 if expressions/lib.rs:1:8: 1:9
        let _4: bool;                    // "c" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.21 if expressions/lib.rs:1:17: 1:18
        scope 2 {
            let mut _5: i32;             // "x" in scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.21 if expressions/lib.rs:2:9: 2:14
        }
    }
    let mut _6: ();
    let mut _7: bool;
    let mut _8: (i32, bool);
    let mut _9: ();
    let mut _10: bool;
    let mut _11: (i32, bool);
    let mut _12: i32;

    bb0: {
        StorageLive(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.21 if expressions/lib.rs:1:8: 1:9
        _3 = _1;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.21 if expressions/lib.rs:1:8: 1:9
        StorageLive(_4);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.21 if expressions/lib.rs:1:17: 1:18
        _4 = _2;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.21 if expressions/lib.rs:1:17: 1:18
        StorageLive(_5);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.21 if expressions/lib.rs:2:9: 2:14
        _5 = const 0i32;                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.21 if expressions/lib.rs:2:17: 2:18
        StorageLive(_7);                 // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.21 if expressions/lib.rs:3:8: 3:9
        _7 = _3;                         // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.21 if expressions/lib.rs:3:8: 3:9
        StorageDead(_7);                 // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.21 if expressions/lib.rs:3:9: 3:9
        if(_7) -> [true: bb1, false: bb2]; // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.21 if expressions/lib.rs:3:5: 3:20
    }

    bb1: {
        _8 = CheckedAdd(_5, const 1i32); // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.21 if expressions/lib.rs:3:12: 3:18
        assert(!(_8.1: bool), "attempt to add with overflow") -> bb3; // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.21 if expressions/lib.rs:3:12: 3:18
    }

    bb2: {
        _6 = ();                         // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.21 if expressions/lib.rs:3:5: 3:20
        goto -> bb4;                     // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.21 if expressions/lib.rs:3:5: 3:20
    }

    bb3: {
        _5 = (_8.0: i32);                // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.21 if expressions/lib.rs:3:12: 3:18
        goto -> bb4;                     // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.21 if expressions/lib.rs:3:5: 3:20
    }

    bb4: {
        StorageLive(_10);                // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.21 if expressions/lib.rs:4:8: 4:9
        _10 = _4;                        // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.21 if expressions/lib.rs:4:8: 4:9
        StorageDead(_10);                // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.21 if expressions/lib.rs:4:9: 4:9
        if(_10) -> [true: bb5, false: bb6]; // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.21 if expressions/lib.rs:4:5: 4:20
    }

    bb5: {
        _11 = CheckedAdd(_5, const 1i32); // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.21 if expressions/lib.rs:4:12: 4:18
        assert(!(_11.1: bool), "attempt to add with overflow") -> bb7; // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.21 if expressions/lib.rs:4:12: 4:18
    }

    bb6: {
        _9 = ();                         // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.21 if expressions/lib.rs:4:5: 4:20
        goto -> bb8;                     // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.21 if expressions/lib.rs:4:5: 4:20
    }

    bb7: {
        _5 = (_11.0: i32);               // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.21 if expressions/lib.rs:4:12: 4:18
        goto -> bb8;                     // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.21 if expressions/lib.rs:4:5: 4:20
    }

    bb8: {
        StorageLive(_12);                // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.21 if expressions/lib.rs:5:5: 5:6
        _12 = _5;                        // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.21 if expressions/lib.rs:5:5: 5:6
        _0 = _12;                        // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.21 if expressions/lib.rs:5:5: 5:6
        StorageDead(_5);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.21 if expressions/lib.rs:6:2: 6:2
        StorageDead(_12);                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.21 if expressions/lib.rs:6:2: 6:2
        StorageDead(_4);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.21 if expressions/lib.rs:6:2: 6:2
        StorageDead(_3);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.21 if expressions/lib.rs:6:2: 6:2
        return;                          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.21 if expressions/lib.rs:6:2: 6:2
    }
}
definition test.foo (bₐ : bool) (cₐ : bool) : sem (i32) :=
let' «b$3»  bₐ;
let' «c$4»  cₐ;
let' «x$5»  (0 : int);
let' t7  «b$3»;
if t7 = bool.tt then
do «$tmp0»  sem.map (λx, (x, tt)) (checked.sadd i32.bits «x$5» (1 : int));
let' t8  «$tmp0»;
let' «x$5»  t8.1;
let' t10  «c$4»;
if t10 = bool.tt then
do «$tmp0»  sem.map (λx, (x, tt)) (checked.sadd i32.bits «x$5» (1 : int));
let' t11  «$tmp0»;
let' «x$5»  t11.1;
let' t12  «x$5»;
let' ret  t12;
return (ret)
else
let' t9  ;
let' t12  «x$5»;
let' ret  t12;
return (ret)
else
let' t6  ;
let' t10  «c$4»;
if t10 = bool.tt then
do «$tmp0»  sem.map (λx, (x, tt)) (checked.sadd i32.bits «x$5» (1 : int));
let' t11  «$tmp0»;
let' «x$5»  t11.1;
let' t12  «x$5»;
let' ret  t12;
return (ret)
else
let' t9  ;
let' t12  «x$5»;
let' ret  t12;
return (ret)

7.2.22 Match expressions [ref]

fn f1(x: i32) -> &'static str {
    match x {
        1 => "one",
        2 => "two",
        3 => "three",
        4 => "four",
        5 => "five",
        _ => "something else",
    }
}

fn f2(x: i32) -> &'static str {
    match x {
        e @ 1 ... 5 => "got a range element",
        _ => "anything",
    }
}

fn f3(x: &i32) {
    let y = match *x { 0 => "zero", _ => "some" };
    let z = match x { &0 => "zero", _ => "some" };
}

fn f4(x: i32) {
    let message = match x {
        0 | 1  => "not many",
        2 ... 9 => "a few",
        _      => "lots"
    };
}

fn f5(x: Option<i32>) -> Option<i32> {
    match x {
        Some(x) if x < 10 => Some(x),
        Some(x) => None,
        None => panic!(),
    }
}
fn f5(_1: std::option::Option<i32>) -> std::option::Option<i32> {
    let mut _0: std::option::Option<i32>; // return pointer
    scope 1 {
        let _2: std::option::Option<i32>; // "x" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:32:7: 32:8
        scope 2 {
            let _3: i32;                 // "x" in scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:34:14: 34:15
        }
        scope 3 {
            let _4: i32;                 // "x" in scope 3 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:35:14: 35:15
        }
    }
    let mut _5: bool;
    let mut _6: i32;
    let mut _7: i32;
    let mut _8: !;
    let mut _9: &(&'static str, u32);
    let mut _10: &(&'static str, u32);

    bb0: {
        StorageLive(_2);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:32:7: 32:8
        _2 = _1;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:32:7: 32:8
        switch(_2) -> [None: bb2, Some: bb3]; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:34:9: 34:16
    }

    bb1: {
        StorageLive(_7);                 // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:34:35: 34:36
        _7 = _3;                         // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:34:35: 34:36
        _0 = std::option::Option<i32>::Some(_7,); // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:34:30: 34:37
        StorageDead(_7);                 // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:34:37: 34:37
        goto -> bb5;                     // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:33:5: 37:6
    }

    bb2: {
        StorageLive(_8);                 // scope 1 at <panic macros>:3:1: 6:17
        StorageLive(_9);                 // scope 1 at <panic macros>:4:9: 6:15
        StorageLive(_10);                // scope 1 at <panic macros>:6:1: 6:13
        _10 = &f5::_FILE_LINE;           // scope 1 at <panic macros>:6:1: 6:13
        _9 = &(*_10);                    // scope 1 at <panic macros>:6:1: 6:13
        std::rt::begin_panic::<&'static str>(const "explicit panic", _9); // scope 1 at <panic macros>:3:1: 6:17
    }

    bb3: {
        StorageLive(_3);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:34:14: 34:15
        _3 = ((_2 as Some).0: i32);      // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:34:14: 34:15
        StorageLive(_5);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:34:20: 34:26
        StorageLive(_6);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:34:20: 34:21
        _6 = _3;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:34:20: 34:21
        _5 = Lt(_6, const 10i32);        // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:34:20: 34:26
        StorageDead(_5);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:34:26: 34:26
        StorageDead(_6);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:34:26: 34:26
        if(_5) -> [true: bb1, false: bb4]; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:34:20: 34:26
    }

    bb4: {
        StorageLive(_4);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:35:14: 35:15
        _4 = ((_2 as Some).0: i32);      // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:35:14: 35:15
        _0 = std::option::Option<i32>::None; // scope 3 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:35:20: 35:24
        goto -> bb5;                     // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:33:5: 37:6
    }

    bb5: {
        StorageDead(_4);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:37:6: 37:6
        StorageDead(_3);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:37:6: 37:6
        StorageDead(_2);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:38:2: 38:2
        return;                          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:38:2: 38:2
    }
}

fn f4(_1: i32) -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let _2: i32;                     // "x" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:24:7: 24:8
        scope 2 {
            let _3: &str;                // "message" in scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:25:9: 25:16
        }
    }
    let mut _4: bool;
    let mut _5: bool;

    bb0: {
        StorageLive(_2);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:24:7: 24:8
        _2 = _1;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:24:7: 24:8
        StorageLive(_3);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:25:9: 25:16
        switchInt(_2) -> [0i32: bb1, 1i32: bb1, otherwise: bb4]; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:26:9: 26:10
    }

    bb1: {
        _3 = const "not many";           // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:26:19: 26:29
        goto -> bb6;                     // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:25:19: 29:6
    }

    bb2: {
        _3 = const "a few";              // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:27:20: 27:27
        goto -> bb6;                     // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:25:19: 29:6
    }

    bb3: {
        _3 = const "lots";               // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:28:19: 28:25
        goto -> bb6;                     // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:25:19: 29:6
    }

    bb4: {
        _4 = Le(const 2i32, _2);         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:27:9: 27:16
        if(_4) -> [true: bb5, false: bb3]; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:27:9: 27:16
    }

    bb5: {
        _5 = Le(_2, const 9i32);         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:27:9: 27:16
        if(_5) -> [true: bb2, false: bb3]; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:27:9: 27:16
    }

    bb6: {
        _0 = ();                         // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:24:15: 30:2
        StorageDead(_3);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:30:2: 30:2
        StorageDead(_2);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:30:2: 30:2
        return;                          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:30:2: 30:2
    }
}

fn f1(_1: i32) -> &'static str {
    let mut _0: &'static str;            // return pointer
    scope 1 {
        let _2: i32;                     // "x" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:1:7: 1:8
    }

    bb0: {
        StorageLive(_2);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:1:7: 1:8
        _2 = _1;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:1:7: 1:8
        switchInt(_2) -> [1i32: bb1, 2i32: bb2, 3i32: bb3, 4i32: bb4, 5i32: bb5, otherwise: bb6]; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:3:9: 3:10
    }

    bb1: {
        _0 = const "one";                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:3:14: 3:19
        goto -> bb7;                     // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:2:5: 9:6
    }

    bb2: {
        _0 = const "two";                // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:4:14: 4:19
        goto -> bb7;                     // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:2:5: 9:6
    }

    bb3: {
        _0 = const "three";              // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:5:14: 5:21
        goto -> bb7;                     // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:2:5: 9:6
    }

    bb4: {
        _0 = const "four";               // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:6:14: 6:20
        goto -> bb7;                     // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:2:5: 9:6
    }

    bb5: {
        _0 = const "five";               // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:7:14: 7:20
        goto -> bb7;                     // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:2:5: 9:6
    }

    bb6: {
        _0 = const "something else";     // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:8:14: 8:30
        goto -> bb7;                     // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:2:5: 9:6
    }

    bb7: {
        StorageDead(_2);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:10:2: 10:2
        return;                          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:10:2: 10:2
    }
}

static f5::_FILE_LINE: (&'static str, u32) = {
    let mut _0: (&'static str, u32);     // return pointer

    bb0: {
        _0 = (const "ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs", const 36u32); // scope 0 at <panic macros>:5:47: 5:76
        return;                          // scope 0 at <panic macros>:5:1: 5:78
    }
}

fn f3(_1: &i32) -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let _2: &i32;                    // "x" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:19:7: 19:8
        scope 2 {
            let _3: &str;                // "y" in scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:20:9: 20:10
            scope 3 {
                let _4: &str;            // "z" in scope 3 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:21:9: 21:10
            }
        }
    }

    bb0: {
        StorageLive(_2);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:19:7: 19:8
        _2 = _1;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:19:7: 19:8
        StorageLive(_3);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:20:9: 20:10
        switchInt((*_2)) -> [0i32: bb1, otherwise: bb2]; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:20:24: 20:25
    }

    bb1: {
        _3 = const "zero";               // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:20:29: 20:35
        goto -> bb3;                     // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:20:13: 20:50
    }

    bb2: {
        _3 = const "some";               // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:20:42: 20:48
        goto -> bb3;                     // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:20:13: 20:50
    }

    bb3: {
        StorageLive(_4);                 // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:21:9: 21:10
        switchInt((*_2)) -> [0i32: bb4, otherwise: bb5]; // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:21:24: 21:25
    }

    bb4: {
        _4 = const "zero";               // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:21:29: 21:35
        goto -> bb6;                     // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:21:13: 21:50
    }

    bb5: {
        _4 = const "some";               // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:21:42: 21:48
        goto -> bb6;                     // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:21:13: 21:50
    }

    bb6: {
        _0 = ();                         // scope 3 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:19:16: 22:2
        StorageDead(_4);                 // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:22:2: 22:2
        StorageDead(_3);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:22:2: 22:2
        StorageDead(_2);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:22:2: 22:2
        return;                          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:22:2: 22:2
    }
}

fn f2(_1: i32) -> &'static str {
    let mut _0: &'static str;            // return pointer
    scope 1 {
        let _2: i32;                     // "x" in scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:12:7: 12:8
        scope 2 {
            let _3: i32;                 // "e" in scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:14:9: 14:20
        }
    }
    let mut _4: bool;
    let mut _5: bool;

    bb0: {
        StorageLive(_2);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:12:7: 12:8
        _2 = _1;                         // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:12:7: 12:8
        _4 = Le(const 1i32, _2);         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:14:13: 14:20
        if(_4) -> [true: bb2, false: bb1]; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:14:13: 14:20
    }

    bb1: {
        _0 = const "anything";           // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:15:14: 15:24
        goto -> bb4;                     // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:13:5: 16:6
    }

    bb2: {
        _5 = Le(_2, const 5i32);         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:14:13: 14:20
        if(_5) -> [true: bb3, false: bb1]; // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:14:13: 14:20
    }

    bb3: {
        StorageLive(_3);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:14:9: 14:20
        _3 = _2;                         // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:14:9: 14:20
        _0 = const "got a range element"; // scope 2 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:14:24: 14:45
        goto -> bb4;                     // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:13:5: 16:6
    }

    bb4: {
        StorageDead(_3);                 // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:16:6: 16:6
        StorageDead(_2);                 // scope 0 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:17:2: 17:2
        return;                          // scope 1 at ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs:17:2: 17:2
    }
}
definition test.f1 (xₐ : i32) : sem (string) :=
let' «x$2»  xₐ;
match «x$2» with
| 1 :=
let' ret  "one";
return (ret)
| 2 :=
let' ret  "two";
return (ret)
| 3 :=
let' ret  "three";
return (ret)
| 4 :=
let' ret  "four";
return (ret)
| 5 :=
let' ret  "five";
return (ret)
| _ :=
let' ret  "something else";
return (ret)

end


definition test.f2 (xₐ : i32) : sem (string) :=
let' «x$2»  xₐ;
let' t4  (1 : int)  «x$2»;
if t4 = bool.tt then
let' t5  «x$2»  (5 : int);
if t5 = bool.tt then
let' «e$3»  «x$2»;
let' ret  "got a range element";
return (ret)
else
let' ret  "anything";
return (ret)
else
let' ret  "anything";
return (ret)


definition test.f3 (xₐ : i32) : sem (unit) :=
let' «x$2»  xₐ;
match «x$2» with
| 0 :=
let' «y$3»  "zero";
match «x$2» with
| 0 :=
let' «z$4»  "zero";
let' ret  ;
return ()
| _ :=
let' «z$4»  "some";
let' ret  ;
return ()

end
| _ :=
let' «y$3»  "some";
match «x$2» with
| 0 :=
let' «z$4»  "zero";
let' ret  ;
return ()
| _ :=
let' «z$4»  "some";
let' ret  ;
return ()

end

end


definition test.f4 (xₐ : i32) : sem (unit) :=
let' «x$2»  xₐ;
match «x$2» with
| 0 :=
let' «message$3»  "not many";
let' ret  ;
return ()
| 1 :=
let' «message$3»  "not many";
let' ret  ;
return ()
| _ :=
let' t4  (2 : int)  «x$2»;
if t4 = bool.tt then
let' t5  «x$2»  (9 : int);
if t5 = bool.tt then
let' «message$3»  "a few";
let' ret  ;
return ()
else
let' «message$3»  "lots";
let' ret  ;
return ()
else
let' «message$3»  "lots";
let' ret  ;
return ()

end


definition test.f5.«$_FILE_LINE» : sem (string × u32) :=
let' ret  ("ref/7 Statements and expressions/7.2 Expressions/7.2.22 Match expressions/lib.rs", (36 : nat));
return (ret)


definition test.f5 (xₐ : (core.option.Option i32)) : sem ((core.option.Option i32)) :=
let' «x$2»  xₐ;
match «x$2» with
| core.option.Option.None :=
let' t10  test.f5.«$_FILE_LINE»;
let' t9  t10;
mzero
 | core.option.Option.Some «» :=
do «$tmp0»  match «x$2» with
| core.option.Option.None := mzero
 | core.option.Option.Some «$0» := return «$0»
end
;
let' «x$3»  «$tmp0»;
let' t6  «x$3»;
let' t5  t6 < (10 : int);
if t5 = bool.tt then
let' t7  «x$3»;
let' ret  core.option.Option.Some t7;
return (ret)
else
do «$tmp0»  match «x$2» with
| core.option.Option.None := mzero
 | core.option.Option.Some «$0» := return «$0»
end
;
let' «x$4»  «$tmp0»;
let' ret  core.option.Option.None;
return (ret)
end

8 Type system [ref]

TODO: Should probably discuss the axiomatized primitives and argue for their correctness via example proofs.