(* Generated by coq-of-rust *)
Require Import CoqOfRust.CoqOfRust.

(*
fn with_impls<A>(func: impl Default, func2: impl Default, foo: A) {
    let mut x = func;
    x = Default::default();

    let mut y = func2;
    y = Default::default();

    let z = foo;

    let b = Box::new((x, y, z));
}
*)
Definition with_impls (ε : list Value.t) (τ : list Ty.t) (α : list Value.t) : M :=
  match ε, τ, α with
  | [], [ A; impl_Default; impl_Default'1 ], [ func; func2; foo ] =>
    ltac:(M.monadic
      (let func := M.alloc (| func |) in
      let func2 := M.alloc (| func2 |) in
      let foo := M.alloc (| foo |) in
      M.read (|
        let~ x := M.copy (| func |) in
        let~ _ :=
          M.write (|
            x,
            M.call_closure (|
              M.get_trait_method (| "core::default::Default", impl_Default, [], "default", [] |),
              []
            |)
          |) in
        let~ y := M.copy (| func2 |) in
        let~ _ :=
          M.write (|
            y,
            M.call_closure (|
              M.get_trait_method (| "core::default::Default", impl_Default'1, [], "default", [] |),
              []
            |)
          |) in
        let~ z := M.copy (| foo |) in
        let~ b :=
          M.alloc (|
            M.call_closure (|
              M.get_associated_function (|
                Ty.apply
                  (Ty.path "alloc::boxed::Box")
                  []
                  [ Ty.tuple [ impl_Default; impl_Default'1; A ]; Ty.path "alloc::alloc::Global" ],
                "new",
                []
              |),
              [ Value.Tuple [ M.read (| x |); M.read (| y |); M.read (| z |) ] ]
            |)
          |) in
        M.alloc (| Value.Tuple [] |)
      |)))
  | _, _, _ => M.impossible "wrong number of arguments"
  end.

Axiom Function_with_impls : M.IsFunction "impl_param::with_impls" with_impls.
