//! > Basic borrow checking valid.

//! > test_runner_name
test_function_lowering

//! > function
fn foo(x: ACopy, y: ADrop) {
  if true {
    use_a_copy(x);
    use_a_drop(y);
  } else {
    use_a_drop(y);
  }
  use_a_copy(x);
}

//! > function_name
foo

//! > module_code
extern type ACopy;
impl ACopyCopy of Copy::<ACopy>;
extern type ADrop;
impl ADropDrop of Drop::<ADrop>;

extern fn use_a_copy(x: ACopy) nopanic;
extern fn use_a_drop(x: ADrop) nopanic;

//! > semantic_diagnostics

//! > lowering_diagnostics

//! > lowering_flat
Parameters: v0: test::ACopy, v1: test::ADrop
blk0 (root):
Statements:
  () <- test::use_a_copy(v0)
  () <- test::use_a_drop(v1)
  () <- test::use_a_copy(v0)
  (v6: ()) <- struct_construct()
End:
  Return(v6)

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

//! > Basic borrow checking failures.

//! > test_runner_name
test_function_lowering

//! > function
fn foo(x: ACopy, y: ADrop) {
  if true {
    use_a_copy(x);
    use_a_drop(y);
  } else {
  }
  use_a_drop(y);
}

//! > function_name
foo

//! > module_code
extern type ACopy;
impl ACopyCopy of Copy::<ACopy>;
extern type ADrop;
impl ADropDrop of Drop::<ADrop>;

extern fn use_a_copy(x: ACopy) nopanic;
extern fn use_a_drop(x: ADrop) nopanic;

//! > semantic_diagnostics

//! > lowering_diagnostics
error: Variable was previously moved. Trait has no implementation in context: core::traits::Copy::<test::ADrop>
 --> lib.cairo:8:18
fn foo(x: ACopy, y: ADrop) {
                 ^

error: Variable not dropped. Trait has no implementation in context: core::traits::Drop::<test::ACopy>. Trait has no implementation in context: core::traits::Destruct::<test::ACopy>.
 --> lib.cairo:8:8
fn foo(x: ACopy, y: ADrop) {
       ^

//! > lowering_flat
Parameters: v0: test::ACopy, v1: test::ADrop

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

//! > Borrow checking with panic

//! > test_runner_name
test_function_lowering

//! > function
fn foo(ref x: ADrop, y: ADrop) {
  use_a_drop(x);
  bar();
  x = y;
}

fn bar(){
  let mut data = Default::default();
  data.append(1);
  panic(data);
}

//! > function_name
foo

//! > module_code
extern type ACopy;
impl ACopyCopy of Copy::<ACopy>;
extern type ADrop;
impl ADropDrop of Drop::<ADrop>;

extern fn use_a_copy(x: ACopy) nopanic;
extern fn use_a_drop(x: ADrop) nopanic;

use array::ArrayTrait;

//! > semantic_diagnostics

//! > lowering_diagnostics

//! > lowering_flat
Parameters: v0: test::ADrop, v1: test::ADrop
blk0 (root):
Statements:
  () <- test::use_a_drop(v0)
  (v4: core::PanicResult::<((),)>) <- test::bar()
End:
  Match(match_enum(v4) {
    PanicResult::Ok(v5) => blk1,
    PanicResult::Err(v7) => blk2,
  })

blk1:
Statements:
  (v3: ()) <- struct_construct()
  (v8: (test::ADrop, ())) <- struct_construct(v1, v3)
  (v9: core::PanicResult::<(test::ADrop, ())>) <- PanicResult::Ok(v8)
End:
  Return(v9)

blk2:
Statements:
  (v10: core::PanicResult::<(test::ADrop, ())>) <- PanicResult::Err(v7)
End:
  Return(v10)

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

//! > Borrow checking array

//! > test_runner_name
test_function_lowering

//! > function
fn foo(ref self: Query::<felt252>, value: felt252) {
  self.data.append(value)
}

//! > function_name
foo

//! > module_code
use array::ArrayTrait;

struct Query<T> {
  data: Array::<T>,
}

//! > semantic_diagnostics

//! > lowering_diagnostics

//! > lowering_flat
Parameters: v0: test::Query::<core::felt252>, v1: core::felt252
blk0 (root):
Statements:
  (v2: core::array::Array::<core::felt252>) <- struct_destructure(v0)
  (v6: core::array::Array::<core::felt252>) <- core::array::array_append::<core::felt252>(v2, v1)
  (v5: test::Query::<core::felt252>) <- struct_construct(v6)
  (v7: ()) <- struct_construct()
End:
  Return(v5, v7)

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

//! > Find drops.

//! > test_runner_name
test_function_lowering

//! > function
fn foo() {
   let mut arr: Array<u256> = Default::default();
   arr.append(1.into());
}

//! > function_name
foo

//! > module_code
// Core library imports.
use array::ArrayTrait;
use traits::Into;

//! > semantic_diagnostics

//! > lowering_diagnostics

//! > lowering_flat
Parameters: v11: core::RangeCheck
blk0 (root):
Statements:
  (v8: core::array::Array::<core::integer::u256>) <- core::array::array_new::<core::integer::u256>()
  (v1: core::felt252) <- 1u
  (v17: core::RangeCheck, v7: core::integer::u256) <- core::integer::u256_from_felt252(v11, v1)
  (v9: core::array::Array::<core::integer::u256>) <- core::array::array_append::<core::integer::u256>(v8, v7)
  (v5: ()) <- struct_construct()
End:
  Return(v17, v5)

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

//! > Non destructible with panicable call.

//! > test_runner_name
test_function_lowering

//! > function
fn foo(ref a: A) {
   1 + 1;
}

//! > function_name
foo

//! > module_code
struct A {}

//! > semantic_diagnostics

//! > lowering_diagnostics
error: Variable not dropped. Trait has no implementation in context: core::traits::Drop::<test::A>. Trait has no implementation in context: core::traits::Destruct::<test::A>.
 --> lib.cairo:2:12
fn foo(ref a: A) {
           ^

//! > lowering_flat
Parameters: v0: test::A
