//! > unused captures

//! > test_runner_name
test_borrow_check

//! > function
fn foo(a: u32, mut b: Array<u32>, mut c: Felt252Dict<felt252>,) {
    |d: u32| {
        let _ = a + d;
    };
    |d: u32| {
        let _ = b.append(d);
    };
    |d: felt252| {
        let _ = c.insert(d, d);
    };
}

//! > function_name
foo

//! > module_code

//! > semantic_diagnostics
error: Capture of mutable variables in a closure is not supported
 --> lib.cairo:6:17
        let _ = b.append(d);
                ^

error: Capture of mutable variables in a closure is not supported
 --> lib.cairo:9:17
        let _ = c.insert(d, d);
                ^

//! > lowering_diagnostics

//! > lowering

//! > ==========================================================================

//! > Panic destructable capture

//! > test_runner_name
test_borrow_check

//! > function
fn foo(a: PanicDestructable) {
    || {
        let PanicDestructable { } = a;
    };
    panic_with_felt252('Panic');
}

//! > function_name
foo

//! > module_code
struct PanicDestructable {}

impl MyPanicDesruct of PanicDestruct<PanicDestructable> {
    fn panic_destruct(self: PanicDestructable, ref panic: Panic) nopanic {
        let PanicDestructable { } = self;
    }
}

//! > semantic_diagnostics

//! > lowering_diagnostics

//! > lowering
Parameters: v0: test::PanicDestructable
blk0 (root):
Statements:
  (v1: {closure@lib.cairo:9:5: 9:7}) <- struct_construct(v0{`a`})
  (v2: core::felt252) <- 345232009571
  (v3: core::never) <- core::panic_with_felt252(v2{`'Panic'`})
End:
  Match(match_enum(v3{`panic_with_felt252('Panic')`}) {
  })

//! > ==========================================================================

//! > invalidated capture mutable variable

//! > test_runner_name
test_borrow_check

//! > function
fn foo(mut a: Array<u32>) {
    |b: u32| {
        let _ = a.append(b);
    };
    a.append(0);
}

//! > function_name
foo

//! > module_code

//! > semantic_diagnostics
error: Capture of mutable variables in a closure is not supported
 --> lib.cairo:3:17
        let _ = a.append(b);
                ^

//! > lowering_diagnostics

//! > lowering

//! > ==========================================================================

//! > invalidated capture immutable variable

//! > test_runner_name
test_borrow_check

//! > function
fn foo(a: S) {
    |b: u32| {
        let _ = a.a + b;
    };
    let _ = a.a;
}

//! > function_name
foo

//! > module_code
struct S {
    a: u32,
}

//! > semantic_diagnostics

//! > lowering_diagnostics

//! > lowering
Parameters: v0: test::S
blk0 (root):
Statements:
  (v1: core::integer::u32) <- struct_destructure(v0{`a.a`})
  (v2: {closure@lib.cairo:5:5: 5:13}) <- struct_construct(v1{`a.a`})
  (v3: ()) <- struct_construct()
End:
  Return(v3)

//! > ==========================================================================

//! > capture use after invalidatian.

//! > test_runner_name
test_borrow_check

//! > function
fn foo(mut a: Array<u32>) {
    let f = |b: u32| {
        let _ = a.append(b);
    };
    a.append(0);
    use_f(f)
}

//! > function_name
foo

//! > module_code
extern fn use_f<T>(f: T) nopanic;

//! > semantic_diagnostics
error: Capture of mutable variables in a closure is not supported
 --> lib.cairo:4:17
        let _ = a.append(b);
                ^

//! > lowering_diagnostics

//! > lowering

//! > ==========================================================================

//! > Snapshot capture

//! > test_runner_name
test_borrow_check

//! > function
fn foo(mut a: Array<u32>) {
    let f = |_b: u32| {
        let _ = a.len();
    };
    a.append(0);
    use_f(f)
}

//! > function_name
foo

//! > module_code
extern fn use_f<T>(f: T) nopanic;

//! > semantic_diagnostics
error: Capture of mutable variables in a closure is not supported
 --> lib.cairo:4:17
        let _ = a.len();
                ^

//! > lowering_diagnostics

//! > lowering

//! > ==========================================================================

//! > Capture changed but unused variable.

//! > test_runner_name
test_borrow_check

//! > function
fn foo(mut a: Array<u32>) {
    |_b: u32| {
        a = array![];
    };
    a.append(0);
}

//! > function_name
foo

//! > module_code
extern fn use_f<T>(f: T) nopanic;

//! > semantic_diagnostics
error: Capture of mutable variables in a closure is not supported
 --> lib.cairo:4:9
        a = array![];
        ^

//! > lowering_diagnostics

//! > lowering

//! > ==========================================================================

//! > Test using captured copiable variable after closure.

//! > test_runner_name
test_borrow_check

//! > function
fn foo() -> felt252 {
    let x = 8;
    let c = |a| {
        x * (a + 3)
    };
    let y = c(2);
    y + x
}

//! > function_name
foo

//! > module_code

//! > semantic_diagnostics

//! > lowering_diagnostics

//! > lowering
Parameters:
blk0 (root):
Statements:
  (v0: core::felt252) <- 8
  (v1: {closure@lib.cairo:3:13: 3:16}) <- struct_construct(v0{`x`})
  (v2: core::felt252) <- 2
  (v3: (core::felt252,)) <- struct_construct(v2{`2`})
  (v4: core::felt252) <- Generated core::ops::function::FnOnce::<{closure@lib.cairo:3:13: 3:16}, (core::felt252,)>::call(v1{`c`}, v3{`c(2)`})
  (v5: core::felt252) <- core::Felt252Add::add(v4{`y`}, v0{`x`})
End:
  Return(v5)

//! > ==========================================================================

//! > Test using captured snapshoted variable after closure.

//! > test_runner_name
test_borrow_check

//! > function
fn foo() -> felt252 {
    let x = array![99_felt252];
    let c = |a| {
        (@x).len() * (a + 3)
    };
    let _ = c(2);
    *x[0]
}

//! > function_name
foo

//! > module_code

//! > semantic_diagnostics

//! > lowering_diagnostics

//! > lowering
Parameters:
blk0 (root):
Statements:
  (v0: core::array::Array::<core::felt252>) <- core::array::ArrayImpl::<core::felt252>::new()
  (v1: core::felt252) <- 99
  (v3: core::array::Array::<core::felt252>, v2: ()) <- core::array::ArrayImpl::<core::felt252>::append(v0{`__array_builder_macro_result__`}, v1{`99_felt252`})
  (v4: core::array::Array::<core::felt252>, v5: @core::array::Array::<core::felt252>) <- snapshot(v3{`x`})
  (v6: {closure@lib.cairo:3:13: 3:16}) <- struct_construct(v5{`|a| { (@x).len() * (a + 3) }`})
  (v7: core::integer::u32) <- 2
  (v8: (core::integer::u32,)) <- struct_construct(v7{`2`})
  (v9: core::integer::u32) <- Generated core::ops::function::FnOnce::<{closure@lib.cairo:3:13: 3:16}, (core::integer::u32,)>::call(v6{`c`}, v8{`c(2)`})
  (v10: core::array::Array::<core::felt252>, v11: @core::array::Array::<core::felt252>) <- snapshot(v4{`x`})
  (v12: core::integer::u32) <- 0
  (v13: @core::felt252) <- core::ops::index::DeprecatedIndexViewImpl::<core::array::Array::<core::felt252>, core::integer::u32, @core::felt252, core::array::ArrayIndex::<core::felt252>>::index(v11{`x`}, v12{`0`})
  (v14: core::felt252) <- desnap(v13{`0`})
End:
  Return(v14)

//! > ==========================================================================

//! > Test mutating captured copiable variable before closure.

//! > test_runner_name
test_borrow_check

//! > function
fn foo() -> felt252 {
    let mut x = 8;
    let c = |a| {
        x * (a + 3)
    };
    x = 9;
    let y = c(2);
    y + x
}

//! > function_name
foo

//! > module_code

//! > semantic_diagnostics
error: Capture of mutable variables in a closure is not supported
 --> lib.cairo:4:9
        x * (a + 3)
        ^

//! > lowering_diagnostics

//! > lowering

//! > ==========================================================================

//! > Test mutating captured copiable variable before closure with indirection.

//! > test_runner_name
test_borrow_check

//! > function
fn identity<T>(x: T) -> T {
    x
}
fn foo() {
    let mut x = 8;
    let c = |a| {
        x * (a + 3)
    };
    let c2 = identity(c);
    x = 9;
    let y = c2(2);
}

//! > function_name
foo

//! > module_code

//! > semantic_diagnostics
error: Capture of mutable variables in a closure is not supported
 --> lib.cairo:7:9
        x * (a + 3)
        ^

warning[E0001]: Unused variable. Consider ignoring by prefixing with `_`.
 --> lib.cairo:11:9
    let y = c2(2);
        ^

//! > lowering_diagnostics

//! > lowering
