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

Module iter.
  Module adapters.
    Module array_chunks.
      (* StructRecord
        {
          name := "ArrayChunks";
          const_params := [ "N" ];
          ty_params := [ "I" ];
          fields :=
            [
              ("iter", I);
              ("remainder",
                Ty.apply
                  (Ty.path "core::option::Option")
                  []
                  [ Ty.apply (Ty.path "core::array::iter::IntoIter") [ N ] [ Ty.associated ] ])
            ];
        } *)
      
      Module Impl_core_fmt_Debug_where_core_fmt_Debug_I_where_core_iter_traits_iterator_Iterator_I_where_core_fmt_Debug_associated_type_for_core_iter_adapters_array_chunks_ArrayChunks_N_I.
        Definition Self (N : Value.t) (I : Ty.t) : Ty.t :=
          Ty.apply (Ty.path "core::iter::adapters::array_chunks::ArrayChunks") [ N ] [ I ].
        
        (* Debug *)
        Definition fmt
            (N : Value.t)
            (I : Ty.t)
            (ε : list Value.t)
            (τ : list Ty.t)
            (α : list Value.t)
            : M :=
          let Self : Ty.t := Self N I in
          match ε, τ, α with
          | [], [], [ self; f ] =>
            ltac:(M.monadic
              (let self := M.alloc (| self |) in
              let f := M.alloc (| f |) in
              M.call_closure (|
                M.get_associated_function (|
                  Ty.path "core::fmt::Formatter",
                  "debug_struct_field2_finish",
                  []
                |),
                [
                  M.read (| f |);
                  M.read (| Value.String "ArrayChunks" |);
                  M.read (| Value.String "iter" |);
                  M.SubPointer.get_struct_record_field (|
                    M.read (| self |),
                    "core::iter::adapters::array_chunks::ArrayChunks",
                    "iter"
                  |);
                  M.read (| Value.String "remainder" |);
                  M.alloc (|
                    M.SubPointer.get_struct_record_field (|
                      M.read (| self |),
                      "core::iter::adapters::array_chunks::ArrayChunks",
                      "remainder"
                    |)
                  |)
                ]
              |)))
          | _, _, _ => M.impossible "wrong number of arguments"
          end.
        
        Axiom Implements :
          forall (N : Value.t) (I : Ty.t),
          M.IsTraitInstance
            "core::fmt::Debug"
            (Self N I)
            (* Trait polymorphic types *) []
            (* Instance *) [ ("fmt", InstanceField.Method (fmt N I)) ].
      End Impl_core_fmt_Debug_where_core_fmt_Debug_I_where_core_iter_traits_iterator_Iterator_I_where_core_fmt_Debug_associated_type_for_core_iter_adapters_array_chunks_ArrayChunks_N_I.
      
      Module Impl_core_clone_Clone_where_core_clone_Clone_I_where_core_iter_traits_iterator_Iterator_I_where_core_clone_Clone_associated_type_for_core_iter_adapters_array_chunks_ArrayChunks_N_I.
        Definition Self (N : Value.t) (I : Ty.t) : Ty.t :=
          Ty.apply (Ty.path "core::iter::adapters::array_chunks::ArrayChunks") [ N ] [ I ].
        
        (* Clone *)
        Definition clone
            (N : Value.t)
            (I : Ty.t)
            (ε : list Value.t)
            (τ : list Ty.t)
            (α : list Value.t)
            : M :=
          let Self : Ty.t := Self N I in
          match ε, τ, α with
          | [], [], [ self ] =>
            ltac:(M.monadic
              (let self := M.alloc (| self |) in
              Value.StructRecord
                "core::iter::adapters::array_chunks::ArrayChunks"
                [
                  ("iter",
                    M.call_closure (|
                      M.get_trait_method (| "core::clone::Clone", I, [], "clone", [] |),
                      [
                        M.SubPointer.get_struct_record_field (|
                          M.read (| self |),
                          "core::iter::adapters::array_chunks::ArrayChunks",
                          "iter"
                        |)
                      ]
                    |));
                  ("remainder",
                    M.call_closure (|
                      M.get_trait_method (|
                        "core::clone::Clone",
                        Ty.apply
                          (Ty.path "core::option::Option")
                          []
                          [ Ty.apply (Ty.path "core::array::iter::IntoIter") [ N ] [ Ty.associated ]
                          ],
                        [],
                        "clone",
                        []
                      |),
                      [
                        M.SubPointer.get_struct_record_field (|
                          M.read (| self |),
                          "core::iter::adapters::array_chunks::ArrayChunks",
                          "remainder"
                        |)
                      ]
                    |))
                ]))
          | _, _, _ => M.impossible "wrong number of arguments"
          end.
        
        Axiom Implements :
          forall (N : Value.t) (I : Ty.t),
          M.IsTraitInstance
            "core::clone::Clone"
            (Self N I)
            (* Trait polymorphic types *) []
            (* Instance *) [ ("clone", InstanceField.Method (clone N I)) ].
      End Impl_core_clone_Clone_where_core_clone_Clone_I_where_core_iter_traits_iterator_Iterator_I_where_core_clone_Clone_associated_type_for_core_iter_adapters_array_chunks_ArrayChunks_N_I.
      
      Module Impl_core_iter_adapters_array_chunks_ArrayChunks_N_I.
        Definition Self (N : Value.t) (I : Ty.t) : Ty.t :=
          Ty.apply (Ty.path "core::iter::adapters::array_chunks::ArrayChunks") [ N ] [ I ].
        
        (*
            pub(in crate::iter) fn new(iter: I) -> Self {
                assert!(N != 0, "chunk size must be non-zero");
                Self { iter, remainder: None }
            }
        *)
        Definition new
            (N : Value.t)
            (I : Ty.t)
            (ε : list Value.t)
            (τ : list Ty.t)
            (α : list Value.t)
            : M :=
          let Self : Ty.t := Self N I in
          match ε, τ, α with
          | [], [], [ iter ] =>
            ltac:(M.monadic
              (let iter := M.alloc (| iter |) in
              M.read (|
                let~ _ :=
                  M.match_operator (|
                    M.alloc (| Value.Tuple [] |),
                    [
                      fun γ =>
                        ltac:(M.monadic
                          (let γ :=
                            M.use
                              (M.alloc (|
                                UnOp.not (|
                                  BinOp.ne (|
                                    M.read (|
                                      M.get_constant (| "core::iter::adapters::array_chunks::N" |)
                                    |),
                                    Value.Integer IntegerKind.Usize 0
                                  |)
                                |)
                              |)) in
                          let _ :=
                            M.is_constant_or_break_match (| M.read (| γ |), Value.Bool true |) in
                          M.alloc (|
                            M.never_to_any (|
                              M.call_closure (|
                                M.get_function (| "core::panicking::panic_fmt", [] |),
                                [
                                  M.call_closure (|
                                    M.get_associated_function (|
                                      Ty.path "core::fmt::Arguments",
                                      "new_const",
                                      []
                                    |),
                                    [
                                      M.alloc (|
                                        Value.Array
                                          [ M.read (| Value.String "chunk size must be non-zero" |)
                                          ]
                                      |)
                                    ]
                                  |)
                                ]
                              |)
                            |)
                          |)));
                      fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                    ]
                  |) in
                M.alloc (|
                  Value.StructRecord
                    "core::iter::adapters::array_chunks::ArrayChunks"
                    [
                      ("iter", M.read (| iter |));
                      ("remainder", Value.StructTuple "core::option::Option::None" [])
                    ]
                |)
              |)))
          | _, _, _ => M.impossible "wrong number of arguments"
          end.
        
        Axiom AssociatedFunction_new :
          forall (N : Value.t) (I : Ty.t),
          M.IsAssociatedFunction (Self N I) "new" (new N I).
        
        (*
            pub fn into_remainder(mut self) -> Option<array::IntoIter<I::Item, N>> {
                if self.remainder.is_none() {
                    while let Some(_) = self.next() {}
                }
                self.remainder
            }
        *)
        Definition into_remainder
            (N : Value.t)
            (I : Ty.t)
            (ε : list Value.t)
            (τ : list Ty.t)
            (α : list Value.t)
            : M :=
          let Self : Ty.t := Self N I in
          match ε, τ, α with
          | [], [], [ self ] =>
            ltac:(M.monadic
              (let self := M.alloc (| self |) in
              M.read (|
                let~ _ :=
                  M.match_operator (|
                    M.alloc (| Value.Tuple [] |),
                    [
                      fun γ =>
                        ltac:(M.monadic
                          (let γ :=
                            M.use
                              (M.alloc (|
                                M.call_closure (|
                                  M.get_associated_function (|
                                    Ty.apply
                                      (Ty.path "core::option::Option")
                                      []
                                      [
                                        Ty.apply
                                          (Ty.path "core::array::iter::IntoIter")
                                          [ N ]
                                          [ Ty.associated ]
                                      ],
                                    "is_none",
                                    []
                                  |),
                                  [
                                    M.SubPointer.get_struct_record_field (|
                                      self,
                                      "core::iter::adapters::array_chunks::ArrayChunks",
                                      "remainder"
                                    |)
                                  ]
                                |)
                              |)) in
                          let _ :=
                            M.is_constant_or_break_match (| M.read (| γ |), Value.Bool true |) in
                          M.loop (|
                            ltac:(M.monadic
                              (M.match_operator (|
                                M.alloc (| Value.Tuple [] |),
                                [
                                  fun γ =>
                                    ltac:(M.monadic
                                      (let γ :=
                                        M.alloc (|
                                          M.call_closure (|
                                            M.get_trait_method (|
                                              "core::iter::traits::iterator::Iterator",
                                              Ty.apply
                                                (Ty.path
                                                  "core::iter::adapters::array_chunks::ArrayChunks")
                                                [ N ]
                                                [ I ],
                                              [],
                                              "next",
                                              []
                                            |),
                                            [ self ]
                                          |)
                                        |) in
                                      let γ0_0 :=
                                        M.SubPointer.get_struct_tuple_field (|
                                          γ,
                                          "core::option::Option::Some",
                                          0
                                        |) in
                                      M.alloc (| Value.Tuple [] |)));
                                  fun γ =>
                                    ltac:(M.monadic
                                      (M.alloc (|
                                        M.never_to_any (|
                                          M.read (|
                                            let~ _ :=
                                              M.alloc (|
                                                M.never_to_any (| M.read (| M.break (||) |) |)
                                              |) in
                                            M.alloc (| Value.Tuple [] |)
                                          |)
                                        |)
                                      |)))
                                ]
                              |)))
                          |)));
                      fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                    ]
                  |) in
                M.SubPointer.get_struct_record_field (|
                  self,
                  "core::iter::adapters::array_chunks::ArrayChunks",
                  "remainder"
                |)
              |)))
          | _, _, _ => M.impossible "wrong number of arguments"
          end.
        
        Axiom AssociatedFunction_into_remainder :
          forall (N : Value.t) (I : Ty.t),
          M.IsAssociatedFunction (Self N I) "into_remainder" (into_remainder N I).
        (*
            fn next_back_remainder(&mut self) {
                // Make sure to not override `self.remainder` with an empty array
                // when `next_back` is called after `ArrayChunks` exhaustion.
                if self.remainder.is_some() {
                    return;
                }
        
                // We use the `ExactSizeIterator` implementation of the underlying
                // iterator to know how many remaining elements there are.
                let rem = self.iter.len() % N;
        
                // Take the last `rem` elements out of `self.iter`.
                let mut remainder =
                    // SAFETY: `unwrap_err` always succeeds because x % N < N for all x.
                    unsafe { self.iter.by_ref().rev().take(rem).next_chunk().unwrap_err_unchecked() };
        
                // We used `.rev()` above, so we need to re-reverse the reminder
                remainder.as_mut_slice().reverse();
                self.remainder = Some(remainder);
            }
        *)
        Definition next_back_remainder
            (N : Value.t)
            (I : Ty.t)
            (ε : list Value.t)
            (τ : list Ty.t)
            (α : list Value.t)
            : M :=
          let Self : Ty.t := Self N I in
          match ε, τ, α with
          | [], [], [ self ] =>
            ltac:(M.monadic
              (let self := M.alloc (| self |) in
              M.catch_return (|
                ltac:(M.monadic
                  (M.read (|
                    let~ _ :=
                      M.match_operator (|
                        M.alloc (| Value.Tuple [] |),
                        [
                          fun γ =>
                            ltac:(M.monadic
                              (let γ :=
                                M.use
                                  (M.alloc (|
                                    M.call_closure (|
                                      M.get_associated_function (|
                                        Ty.apply
                                          (Ty.path "core::option::Option")
                                          []
                                          [
                                            Ty.apply
                                              (Ty.path "core::array::iter::IntoIter")
                                              [ N ]
                                              [ Ty.associated ]
                                          ],
                                        "is_some",
                                        []
                                      |),
                                      [
                                        M.SubPointer.get_struct_record_field (|
                                          M.read (| self |),
                                          "core::iter::adapters::array_chunks::ArrayChunks",
                                          "remainder"
                                        |)
                                      ]
                                    |)
                                  |)) in
                              let _ :=
                                M.is_constant_or_break_match (|
                                  M.read (| γ |),
                                  Value.Bool true
                                |) in
                              M.alloc (|
                                M.never_to_any (| M.read (| M.return_ (| Value.Tuple [] |) |) |)
                              |)));
                          fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                        ]
                      |) in
                    let~ rem :=
                      M.alloc (|
                        BinOp.Wrap.rem (|
                          M.call_closure (|
                            M.get_trait_method (|
                              "core::iter::traits::exact_size::ExactSizeIterator",
                              I,
                              [],
                              "len",
                              []
                            |),
                            [
                              M.SubPointer.get_struct_record_field (|
                                M.read (| self |),
                                "core::iter::adapters::array_chunks::ArrayChunks",
                                "iter"
                              |)
                            ]
                          |),
                          M.read (| M.get_constant (| "core::iter::adapters::array_chunks::N" |) |)
                        |)
                      |) in
                    let~ remainder :=
                      M.alloc (|
                        M.call_closure (|
                          M.get_associated_function (|
                            Ty.apply
                              (Ty.path "core::result::Result")
                              []
                              [
                                Ty.apply (Ty.path "array") [ N ] [ Ty.associated ];
                                Ty.apply
                                  (Ty.path "core::array::iter::IntoIter")
                                  [ N ]
                                  [ Ty.associated ]
                              ],
                            "unwrap_err_unchecked",
                            []
                          |),
                          [
                            M.call_closure (|
                              M.get_trait_method (|
                                "core::iter::traits::iterator::Iterator",
                                Ty.apply
                                  (Ty.path "core::iter::adapters::take::Take")
                                  []
                                  [
                                    Ty.apply
                                      (Ty.path "core::iter::adapters::rev::Rev")
                                      []
                                      [ Ty.apply (Ty.path "&mut") [] [ I ] ]
                                  ],
                                [],
                                "next_chunk",
                                []
                              |),
                              [
                                M.alloc (|
                                  M.call_closure (|
                                    M.get_trait_method (|
                                      "core::iter::traits::iterator::Iterator",
                                      Ty.apply
                                        (Ty.path "core::iter::adapters::rev::Rev")
                                        []
                                        [ Ty.apply (Ty.path "&mut") [] [ I ] ],
                                      [],
                                      "take",
                                      []
                                    |),
                                    [
                                      M.call_closure (|
                                        M.get_trait_method (|
                                          "core::iter::traits::iterator::Iterator",
                                          Ty.apply (Ty.path "&mut") [] [ I ],
                                          [],
                                          "rev",
                                          []
                                        |),
                                        [
                                          M.call_closure (|
                                            M.get_trait_method (|
                                              "core::iter::traits::iterator::Iterator",
                                              I,
                                              [],
                                              "by_ref",
                                              []
                                            |),
                                            [
                                              M.SubPointer.get_struct_record_field (|
                                                M.read (| self |),
                                                "core::iter::adapters::array_chunks::ArrayChunks",
                                                "iter"
                                              |)
                                            ]
                                          |)
                                        ]
                                      |);
                                      M.read (| rem |)
                                    ]
                                  |)
                                |)
                              ]
                            |)
                          ]
                        |)
                      |) in
                    let~ _ :=
                      M.alloc (|
                        M.call_closure (|
                          M.get_associated_function (|
                            Ty.apply (Ty.path "slice") [] [ Ty.associated ],
                            "reverse",
                            []
                          |),
                          [
                            M.call_closure (|
                              M.get_associated_function (|
                                Ty.apply
                                  (Ty.path "core::array::iter::IntoIter")
                                  [ N ]
                                  [ Ty.associated ],
                                "as_mut_slice",
                                []
                              |),
                              [ remainder ]
                            |)
                          ]
                        |)
                      |) in
                    let~ _ :=
                      M.write (|
                        M.SubPointer.get_struct_record_field (|
                          M.read (| self |),
                          "core::iter::adapters::array_chunks::ArrayChunks",
                          "remainder"
                        |),
                        Value.StructTuple "core::option::Option::Some" [ M.read (| remainder |) ]
                      |) in
                    M.alloc (| Value.Tuple [] |)
                  |)))
              |)))
          | _, _, _ => M.impossible "wrong number of arguments"
          end.
        
        Axiom AssociatedFunction_next_back_remainder :
          forall (N : Value.t) (I : Ty.t),
          M.IsAssociatedFunction (Self N I) "next_back_remainder" (next_back_remainder N I).
      End Impl_core_iter_adapters_array_chunks_ArrayChunks_N_I.
      
      Module Impl_core_iter_traits_iterator_Iterator_where_core_iter_traits_iterator_Iterator_I_for_core_iter_adapters_array_chunks_ArrayChunks_N_I.
        Definition Self (N : Value.t) (I : Ty.t) : Ty.t :=
          Ty.apply (Ty.path "core::iter::adapters::array_chunks::ArrayChunks") [ N ] [ I ].
        
        (*     type Item = [I::Item; N]; *)
        Definition _Item (N : Value.t) (I : Ty.t) : Ty.t :=
          Ty.apply (Ty.path "array") [ N ] [ Ty.associated ].
        
        (*
            fn next(&mut self) -> Option<Self::Item> {
                self.try_for_each(ControlFlow::Break).break_value()
            }
        *)
        Definition next
            (N : Value.t)
            (I : Ty.t)
            (ε : list Value.t)
            (τ : list Ty.t)
            (α : list Value.t)
            : M :=
          let Self : Ty.t := Self N I in
          match ε, τ, α with
          | [], [], [ self ] =>
            ltac:(M.monadic
              (let self := M.alloc (| self |) in
              M.call_closure (|
                M.get_associated_function (|
                  Ty.apply
                    (Ty.path "core::ops::control_flow::ControlFlow")
                    []
                    [ Ty.apply (Ty.path "array") [ N ] [ Ty.associated ]; Ty.tuple [] ],
                  "break_value",
                  []
                |),
                [
                  M.call_closure (|
                    M.get_trait_method (|
                      "core::iter::traits::iterator::Iterator",
                      Ty.apply
                        (Ty.path "core::iter::adapters::array_chunks::ArrayChunks")
                        [ N ]
                        [ I ],
                      [],
                      "try_for_each",
                      [
                        Ty.function
                          [ Ty.apply (Ty.path "array") [ N ] [ Ty.associated ] ]
                          (Ty.apply
                            (Ty.path "core::ops::control_flow::ControlFlow")
                            []
                            [ Ty.apply (Ty.path "array") [ N ] [ Ty.associated ]; Ty.tuple [] ]);
                        Ty.apply
                          (Ty.path "core::ops::control_flow::ControlFlow")
                          []
                          [ Ty.apply (Ty.path "array") [ N ] [ Ty.associated ]; Ty.tuple [] ]
                      ]
                    |),
                    [
                      M.read (| self |);
                      M.constructor_as_closure "core::ops::control_flow::ControlFlow::Break"
                    ]
                  |)
                ]
              |)))
          | _, _, _ => M.impossible "wrong number of arguments"
          end.
        
        (*
            fn size_hint(&self) -> (usize, Option<usize>) {
                let (lower, upper) = self.iter.size_hint();
        
                (lower / N, upper.map(|n| n / N))
            }
        *)
        Definition size_hint
            (N : Value.t)
            (I : Ty.t)
            (ε : list Value.t)
            (τ : list Ty.t)
            (α : list Value.t)
            : M :=
          let Self : Ty.t := Self N I in
          match ε, τ, α with
          | [], [], [ self ] =>
            ltac:(M.monadic
              (let self := M.alloc (| self |) in
              M.read (|
                M.match_operator (|
                  M.alloc (|
                    M.call_closure (|
                      M.get_trait_method (|
                        "core::iter::traits::iterator::Iterator",
                        I,
                        [],
                        "size_hint",
                        []
                      |),
                      [
                        M.SubPointer.get_struct_record_field (|
                          M.read (| self |),
                          "core::iter::adapters::array_chunks::ArrayChunks",
                          "iter"
                        |)
                      ]
                    |)
                  |),
                  [
                    fun γ =>
                      ltac:(M.monadic
                        (let γ0_0 := M.SubPointer.get_tuple_field (| γ, 0 |) in
                        let γ0_1 := M.SubPointer.get_tuple_field (| γ, 1 |) in
                        let lower := M.copy (| γ0_0 |) in
                        let upper := M.copy (| γ0_1 |) in
                        M.alloc (|
                          Value.Tuple
                            [
                              BinOp.Wrap.div (|
                                M.read (| lower |),
                                M.read (|
                                  M.get_constant (| "core::iter::adapters::array_chunks::N" |)
                                |)
                              |);
                              M.call_closure (|
                                M.get_associated_function (|
                                  Ty.apply (Ty.path "core::option::Option") [] [ Ty.path "usize" ],
                                  "map",
                                  [
                                    Ty.path "usize";
                                    Ty.function [ Ty.tuple [ Ty.path "usize" ] ] (Ty.path "usize")
                                  ]
                                |),
                                [
                                  M.read (| upper |);
                                  M.closure
                                    (fun γ =>
                                      ltac:(M.monadic
                                        match γ with
                                        | [ α0 ] =>
                                          ltac:(M.monadic
                                            (M.match_operator (|
                                              M.alloc (| α0 |),
                                              [
                                                fun γ =>
                                                  ltac:(M.monadic
                                                    (let n := M.copy (| γ |) in
                                                    BinOp.Wrap.div (|
                                                      M.read (| n |),
                                                      M.read (|
                                                        M.get_constant (|
                                                          "core::iter::adapters::array_chunks::N"
                                                        |)
                                                      |)
                                                    |)))
                                              ]
                                            |)))
                                        | _ => M.impossible "wrong number of arguments"
                                        end))
                                ]
                              |)
                            ]
                        |)))
                  ]
                |)
              |)))
          | _, _, _ => M.impossible "wrong number of arguments"
          end.
        
        (*
            fn count(self) -> usize {
                self.iter.count() / N
            }
        *)
        Definition count
            (N : Value.t)
            (I : Ty.t)
            (ε : list Value.t)
            (τ : list Ty.t)
            (α : list Value.t)
            : M :=
          let Self : Ty.t := Self N I in
          match ε, τ, α with
          | [], [], [ self ] =>
            ltac:(M.monadic
              (let self := M.alloc (| self |) in
              BinOp.Wrap.div (|
                M.call_closure (|
                  M.get_trait_method (|
                    "core::iter::traits::iterator::Iterator",
                    I,
                    [],
                    "count",
                    []
                  |),
                  [
                    M.read (|
                      M.SubPointer.get_struct_record_field (|
                        self,
                        "core::iter::adapters::array_chunks::ArrayChunks",
                        "iter"
                      |)
                    |)
                  ]
                |),
                M.read (| M.get_constant (| "core::iter::adapters::array_chunks::N" |) |)
              |)))
          | _, _, _ => M.impossible "wrong number of arguments"
          end.
        
        (*
            fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
            where
                Self: Sized,
                F: FnMut(B, Self::Item) -> R,
                R: Try<Output = B>,
            {
                let mut acc = init;
                loop {
                    match self.iter.next_chunk() {
                        Ok(chunk) => acc = f(acc, chunk)?,
                        Err(remainder) => {
                            // Make sure to not override `self.remainder` with an empty array
                            // when `next` is called after `ArrayChunks` exhaustion.
                            self.remainder.get_or_insert(remainder);
        
                            break try { acc };
                        }
                    }
                }
            }
        *)
        Definition try_fold
            (N : Value.t)
            (I : Ty.t)
            (ε : list Value.t)
            (τ : list Ty.t)
            (α : list Value.t)
            : M :=
          let Self : Ty.t := Self N I in
          match ε, τ, α with
          | [], [ B; F; R ], [ self; init; f ] =>
            ltac:(M.monadic
              (let self := M.alloc (| self |) in
              let init := M.alloc (| init |) in
              let f := M.alloc (| f |) in
              M.catch_return (|
                ltac:(M.monadic
                  (M.read (|
                    let~ acc := M.copy (| init |) in
                    M.loop (|
                      ltac:(M.monadic
                        (M.match_operator (|
                          M.alloc (|
                            M.call_closure (|
                              M.get_trait_method (|
                                "core::iter::traits::iterator::Iterator",
                                I,
                                [],
                                "next_chunk",
                                []
                              |),
                              [
                                M.SubPointer.get_struct_record_field (|
                                  M.read (| self |),
                                  "core::iter::adapters::array_chunks::ArrayChunks",
                                  "iter"
                                |)
                              ]
                            |)
                          |),
                          [
                            fun γ =>
                              ltac:(M.monadic
                                (let γ0_0 :=
                                  M.SubPointer.get_struct_tuple_field (|
                                    γ,
                                    "core::result::Result::Ok",
                                    0
                                  |) in
                                let chunk := M.copy (| γ0_0 |) in
                                M.write (|
                                  acc,
                                  M.read (|
                                    M.match_operator (|
                                      M.alloc (|
                                        M.call_closure (|
                                          M.get_trait_method (|
                                            "core::ops::try_trait::Try",
                                            R,
                                            [],
                                            "branch",
                                            []
                                          |),
                                          [
                                            M.call_closure (|
                                              M.get_trait_method (|
                                                "core::ops::function::FnMut",
                                                F,
                                                [
                                                  Ty.tuple
                                                    [
                                                      B;
                                                      Ty.apply
                                                        (Ty.path "array")
                                                        [ N ]
                                                        [ Ty.associated ]
                                                    ]
                                                ],
                                                "call_mut",
                                                []
                                              |),
                                              [
                                                f;
                                                Value.Tuple [ M.read (| acc |); M.read (| chunk |) ]
                                              ]
                                            |)
                                          ]
                                        |)
                                      |),
                                      [
                                        fun γ =>
                                          ltac:(M.monadic
                                            (let γ0_0 :=
                                              M.SubPointer.get_struct_tuple_field (|
                                                γ,
                                                "core::ops::control_flow::ControlFlow::Break",
                                                0
                                              |) in
                                            let residual := M.copy (| γ0_0 |) in
                                            M.alloc (|
                                              M.never_to_any (|
                                                M.read (|
                                                  M.return_ (|
                                                    M.call_closure (|
                                                      M.get_trait_method (|
                                                        "core::ops::try_trait::FromResidual",
                                                        R,
                                                        [ Ty.associated ],
                                                        "from_residual",
                                                        []
                                                      |),
                                                      [ M.read (| residual |) ]
                                                    |)
                                                  |)
                                                |)
                                              |)
                                            |)));
                                        fun γ =>
                                          ltac:(M.monadic
                                            (let γ0_0 :=
                                              M.SubPointer.get_struct_tuple_field (|
                                                γ,
                                                "core::ops::control_flow::ControlFlow::Continue",
                                                0
                                              |) in
                                            let val := M.copy (| γ0_0 |) in
                                            val))
                                      ]
                                    |)
                                  |)
                                |)));
                            fun γ =>
                              ltac:(M.monadic
                                (let γ0_0 :=
                                  M.SubPointer.get_struct_tuple_field (|
                                    γ,
                                    "core::result::Result::Err",
                                    0
                                  |) in
                                let remainder := M.copy (| γ0_0 |) in
                                M.alloc (|
                                  M.never_to_any (|
                                    M.read (|
                                      let~ _ :=
                                        M.alloc (|
                                          M.call_closure (|
                                            M.get_associated_function (|
                                              Ty.apply
                                                (Ty.path "core::option::Option")
                                                []
                                                [
                                                  Ty.apply
                                                    (Ty.path "core::array::iter::IntoIter")
                                                    [ N ]
                                                    [ Ty.associated ]
                                                ],
                                              "get_or_insert",
                                              []
                                            |),
                                            [
                                              M.SubPointer.get_struct_record_field (|
                                                M.read (| self |),
                                                "core::iter::adapters::array_chunks::ArrayChunks",
                                                "remainder"
                                              |);
                                              M.read (| remainder |)
                                            ]
                                          |)
                                        |) in
                                      M.break (||)
                                    |)
                                  |)
                                |)))
                          ]
                        |)))
                    |)
                  |)))
              |)))
          | _, _, _ => M.impossible "wrong number of arguments"
          end.
        
        (*
            fn fold<B, F>(self, init: B, f: F) -> B
            where
                Self: Sized,
                F: FnMut(B, Self::Item) -> B,
            {
                <Self as SpecFold>::fold(self, init, f)
            }
        *)
        Definition fold
            (N : Value.t)
            (I : Ty.t)
            (ε : list Value.t)
            (τ : list Ty.t)
            (α : list Value.t)
            : M :=
          let Self : Ty.t := Self N I in
          match ε, τ, α with
          | [], [ B; F ], [ self; init; f ] =>
            ltac:(M.monadic
              (let self := M.alloc (| self |) in
              let init := M.alloc (| init |) in
              let f := M.alloc (| f |) in
              M.call_closure (|
                M.get_trait_method (|
                  "core::iter::adapters::array_chunks::SpecFold",
                  Ty.apply (Ty.path "core::iter::adapters::array_chunks::ArrayChunks") [ N ] [ I ],
                  [],
                  "fold",
                  [ B; F ]
                |),
                [ M.read (| self |); M.read (| init |); M.read (| f |) ]
              |)))
          | _, _, _ => M.impossible "wrong number of arguments"
          end.
        
        Axiom Implements :
          forall (N : Value.t) (I : Ty.t),
          M.IsTraitInstance
            "core::iter::traits::iterator::Iterator"
            (Self N I)
            (* Trait polymorphic types *) []
            (* Instance *)
            [
              ("Item", InstanceField.Ty (_Item N I));
              ("next", InstanceField.Method (next N I));
              ("size_hint", InstanceField.Method (size_hint N I));
              ("count", InstanceField.Method (count N I));
              ("try_fold", InstanceField.Method (try_fold N I));
              ("fold", InstanceField.Method (fold N I))
            ].
      End Impl_core_iter_traits_iterator_Iterator_where_core_iter_traits_iterator_Iterator_I_for_core_iter_adapters_array_chunks_ArrayChunks_N_I.
      
      Module Impl_core_iter_traits_double_ended_DoubleEndedIterator_where_core_iter_traits_double_ended_DoubleEndedIterator_I_where_core_iter_traits_exact_size_ExactSizeIterator_I_for_core_iter_adapters_array_chunks_ArrayChunks_N_I.
        Definition Self (N : Value.t) (I : Ty.t) : Ty.t :=
          Ty.apply (Ty.path "core::iter::adapters::array_chunks::ArrayChunks") [ N ] [ I ].
        
        (*
            fn next_back(&mut self) -> Option<Self::Item> {
                self.try_rfold((), |(), x| ControlFlow::Break(x)).break_value()
            }
        *)
        Definition next_back
            (N : Value.t)
            (I : Ty.t)
            (ε : list Value.t)
            (τ : list Ty.t)
            (α : list Value.t)
            : M :=
          let Self : Ty.t := Self N I in
          match ε, τ, α with
          | [], [], [ self ] =>
            ltac:(M.monadic
              (let self := M.alloc (| self |) in
              M.call_closure (|
                M.get_associated_function (|
                  Ty.apply
                    (Ty.path "core::ops::control_flow::ControlFlow")
                    []
                    [ Ty.apply (Ty.path "array") [ N ] [ Ty.associated ]; Ty.tuple [] ],
                  "break_value",
                  []
                |),
                [
                  M.call_closure (|
                    M.get_trait_method (|
                      "core::iter::traits::double_ended::DoubleEndedIterator",
                      Ty.apply
                        (Ty.path "core::iter::adapters::array_chunks::ArrayChunks")
                        [ N ]
                        [ I ],
                      [],
                      "try_rfold",
                      [
                        Ty.tuple [];
                        Ty.function
                          [
                            Ty.tuple
                              [ Ty.tuple []; Ty.apply (Ty.path "array") [ N ] [ Ty.associated ] ]
                          ]
                          (Ty.apply
                            (Ty.path "core::ops::control_flow::ControlFlow")
                            []
                            [ Ty.apply (Ty.path "array") [ N ] [ Ty.associated ]; Ty.tuple [] ]);
                        Ty.apply
                          (Ty.path "core::ops::control_flow::ControlFlow")
                          []
                          [ Ty.apply (Ty.path "array") [ N ] [ Ty.associated ]; Ty.tuple [] ]
                      ]
                    |),
                    [
                      M.read (| self |);
                      Value.Tuple [];
                      M.closure
                        (fun γ =>
                          ltac:(M.monadic
                            match γ with
                            | [ α0; α1 ] =>
                              ltac:(M.monadic
                                (M.match_operator (|
                                  M.alloc (| α0 |),
                                  [
                                    fun γ =>
                                      ltac:(M.monadic
                                        (M.match_operator (|
                                          M.alloc (| α1 |),
                                          [
                                            fun γ =>
                                              ltac:(M.monadic
                                                (let x := M.copy (| γ |) in
                                                Value.StructTuple
                                                  "core::ops::control_flow::ControlFlow::Break"
                                                  [ M.read (| x |) ]))
                                          ]
                                        |)))
                                  ]
                                |)))
                            | _ => M.impossible "wrong number of arguments"
                            end))
                    ]
                  |)
                ]
              |)))
          | _, _, _ => M.impossible "wrong number of arguments"
          end.
        
        (*
            fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
            where
                Self: Sized,
                F: FnMut(B, Self::Item) -> R,
                R: Try<Output = B>,
            {
                // We are iterating from the back we need to first handle the remainder.
                self.next_back_remainder();
        
                let mut acc = init;
                let mut iter = ByRefSized(&mut self.iter).rev();
        
                // NB remainder is handled by `next_back_remainder`, so
                // `next_chunk` can't return `Err` with non-empty remainder
                // (assuming correct `I as ExactSizeIterator` impl).
                while let Ok(mut chunk) = iter.next_chunk() {
                    // FIXME: do not do double reverse
                    //        (we could instead add `next_chunk_back` for example)
                    chunk.reverse();
                    acc = f(acc, chunk)?
                }
        
                try { acc }
            }
        *)
        Definition try_rfold
            (N : Value.t)
            (I : Ty.t)
            (ε : list Value.t)
            (τ : list Ty.t)
            (α : list Value.t)
            : M :=
          let Self : Ty.t := Self N I in
          match ε, τ, α with
          | [], [ B; F; R ], [ self; init; f ] =>
            ltac:(M.monadic
              (let self := M.alloc (| self |) in
              let init := M.alloc (| init |) in
              let f := M.alloc (| f |) in
              M.catch_return (|
                ltac:(M.monadic
                  (M.read (|
                    let~ _ :=
                      M.alloc (|
                        M.call_closure (|
                          M.get_associated_function (|
                            Ty.apply
                              (Ty.path "core::iter::adapters::array_chunks::ArrayChunks")
                              [ N ]
                              [ I ],
                            "next_back_remainder",
                            []
                          |),
                          [ M.read (| self |) ]
                        |)
                      |) in
                    let~ acc := M.copy (| init |) in
                    let~ iter :=
                      M.alloc (|
                        M.call_closure (|
                          M.get_trait_method (|
                            "core::iter::traits::iterator::Iterator",
                            Ty.apply
                              (Ty.path "core::iter::adapters::by_ref_sized::ByRefSized")
                              []
                              [ I ],
                            [],
                            "rev",
                            []
                          |),
                          [
                            Value.StructTuple
                              "core::iter::adapters::by_ref_sized::ByRefSized"
                              [
                                M.SubPointer.get_struct_record_field (|
                                  M.read (| self |),
                                  "core::iter::adapters::array_chunks::ArrayChunks",
                                  "iter"
                                |)
                              ]
                          ]
                        |)
                      |) in
                    let~ _ :=
                      M.loop (|
                        ltac:(M.monadic
                          (M.match_operator (|
                            M.alloc (| Value.Tuple [] |),
                            [
                              fun γ =>
                                ltac:(M.monadic
                                  (let γ :=
                                    M.alloc (|
                                      M.call_closure (|
                                        M.get_trait_method (|
                                          "core::iter::traits::iterator::Iterator",
                                          Ty.apply
                                            (Ty.path "core::iter::adapters::rev::Rev")
                                            []
                                            [
                                              Ty.apply
                                                (Ty.path
                                                  "core::iter::adapters::by_ref_sized::ByRefSized")
                                                []
                                                [ I ]
                                            ],
                                          [],
                                          "next_chunk",
                                          []
                                        |),
                                        [ iter ]
                                      |)
                                    |) in
                                  let γ0_0 :=
                                    M.SubPointer.get_struct_tuple_field (|
                                      γ,
                                      "core::result::Result::Ok",
                                      0
                                    |) in
                                  let chunk := M.copy (| γ0_0 |) in
                                  let~ _ :=
                                    M.alloc (|
                                      M.call_closure (|
                                        M.get_associated_function (|
                                          Ty.apply (Ty.path "slice") [] [ Ty.associated ],
                                          "reverse",
                                          []
                                        |),
                                        [ chunk ]
                                      |)
                                    |) in
                                  M.write (|
                                    acc,
                                    M.read (|
                                      M.match_operator (|
                                        M.alloc (|
                                          M.call_closure (|
                                            M.get_trait_method (|
                                              "core::ops::try_trait::Try",
                                              R,
                                              [],
                                              "branch",
                                              []
                                            |),
                                            [
                                              M.call_closure (|
                                                M.get_trait_method (|
                                                  "core::ops::function::FnMut",
                                                  F,
                                                  [
                                                    Ty.tuple
                                                      [
                                                        B;
                                                        Ty.apply
                                                          (Ty.path "array")
                                                          [ N ]
                                                          [ Ty.associated ]
                                                      ]
                                                  ],
                                                  "call_mut",
                                                  []
                                                |),
                                                [
                                                  f;
                                                  Value.Tuple
                                                    [ M.read (| acc |); M.read (| chunk |) ]
                                                ]
                                              |)
                                            ]
                                          |)
                                        |),
                                        [
                                          fun γ =>
                                            ltac:(M.monadic
                                              (let γ0_0 :=
                                                M.SubPointer.get_struct_tuple_field (|
                                                  γ,
                                                  "core::ops::control_flow::ControlFlow::Break",
                                                  0
                                                |) in
                                              let residual := M.copy (| γ0_0 |) in
                                              M.alloc (|
                                                M.never_to_any (|
                                                  M.read (|
                                                    M.return_ (|
                                                      M.call_closure (|
                                                        M.get_trait_method (|
                                                          "core::ops::try_trait::FromResidual",
                                                          R,
                                                          [ Ty.associated ],
                                                          "from_residual",
                                                          []
                                                        |),
                                                        [ M.read (| residual |) ]
                                                      |)
                                                    |)
                                                  |)
                                                |)
                                              |)));
                                          fun γ =>
                                            ltac:(M.monadic
                                              (let γ0_0 :=
                                                M.SubPointer.get_struct_tuple_field (|
                                                  γ,
                                                  "core::ops::control_flow::ControlFlow::Continue",
                                                  0
                                                |) in
                                              let val := M.copy (| γ0_0 |) in
                                              val))
                                        ]
                                      |)
                                    |)
                                  |)));
                              fun γ =>
                                ltac:(M.monadic
                                  (M.alloc (|
                                    M.never_to_any (|
                                      M.read (|
                                        let~ _ :=
                                          M.alloc (|
                                            M.never_to_any (| M.read (| M.break (||) |) |)
                                          |) in
                                        M.alloc (| Value.Tuple [] |)
                                      |)
                                    |)
                                  |)))
                            ]
                          |)))
                      |) in
                    M.alloc (|
                      M.call_closure (|
                        M.get_trait_method (|
                          "core::ops::try_trait::Try",
                          R,
                          [],
                          "from_output",
                          []
                        |),
                        [ M.read (| acc |) ]
                      |)
                    |)
                  |)))
              |)))
          | _, _, _ => M.impossible "wrong number of arguments"
          end.
        
        (*
                fn $fold<AAA, FFF>(mut self, init: AAA, fold: FFF) -> AAA
                where
                    FFF: FnMut(AAA, Self::Item) -> AAA,
                {
                    use crate::ops::NeverShortCircuit;
        
                    self.$try_fold(init, NeverShortCircuit::wrap_mut_2(fold)).0
                }
        *)
        Definition rfold
            (N : Value.t)
            (I : Ty.t)
            (ε : list Value.t)
            (τ : list Ty.t)
            (α : list Value.t)
            : M :=
          let Self : Ty.t := Self N I in
          match ε, τ, α with
          | [], [ AAA; FFF ], [ self; init; fold ] =>
            ltac:(M.monadic
              (let self := M.alloc (| self |) in
              let init := M.alloc (| init |) in
              let fold := M.alloc (| fold |) in
              M.read (|
                M.SubPointer.get_struct_tuple_field (|
                  M.alloc (|
                    M.call_closure (|
                      M.get_trait_method (|
                        "core::iter::traits::double_ended::DoubleEndedIterator",
                        Ty.apply
                          (Ty.path "core::iter::adapters::array_chunks::ArrayChunks")
                          [ N ]
                          [ I ],
                        [],
                        "try_rfold",
                        [
                          AAA;
                          Ty.associated;
                          Ty.apply (Ty.path "core::ops::try_trait::NeverShortCircuit") [] [ AAA ]
                        ]
                      |),
                      [
                        self;
                        M.read (| init |);
                        M.call_closure (|
                          M.get_associated_function (|
                            Ty.apply (Ty.path "core::ops::try_trait::NeverShortCircuit") [] [ AAA ],
                            "wrap_mut_2",
                            [ AAA; Ty.apply (Ty.path "array") [ N ] [ Ty.associated ]; FFF ]
                          |),
                          [ M.read (| fold |) ]
                        |)
                      ]
                    |)
                  |),
                  "core::ops::try_trait::NeverShortCircuit",
                  0
                |)
              |)))
          | _, _, _ => M.impossible "wrong number of arguments"
          end.
        
        Axiom Implements :
          forall (N : Value.t) (I : Ty.t),
          M.IsTraitInstance
            "core::iter::traits::double_ended::DoubleEndedIterator"
            (Self N I)
            (* Trait polymorphic types *) []
            (* Instance *)
            [
              ("next_back", InstanceField.Method (next_back N I));
              ("try_rfold", InstanceField.Method (try_rfold N I));
              ("rfold", InstanceField.Method (rfold N I))
            ].
      End Impl_core_iter_traits_double_ended_DoubleEndedIterator_where_core_iter_traits_double_ended_DoubleEndedIterator_I_where_core_iter_traits_exact_size_ExactSizeIterator_I_for_core_iter_adapters_array_chunks_ArrayChunks_N_I.
      
      
      Module Impl_core_iter_traits_marker_FusedIterator_where_core_iter_traits_marker_FusedIterator_I_for_core_iter_adapters_array_chunks_ArrayChunks_N_I.
        Definition Self (N : Value.t) (I : Ty.t) : Ty.t :=
          Ty.apply (Ty.path "core::iter::adapters::array_chunks::ArrayChunks") [ N ] [ I ].
        
        Axiom Implements :
          forall (N : Value.t) (I : Ty.t),
          M.IsTraitInstance
            "core::iter::traits::marker::FusedIterator"
            (Self N I)
            (* Trait polymorphic types *) []
            (* Instance *) [].
      End Impl_core_iter_traits_marker_FusedIterator_where_core_iter_traits_marker_FusedIterator_I_for_core_iter_adapters_array_chunks_ArrayChunks_N_I.
      
      Module Impl_core_iter_traits_marker_TrustedFused_where_core_iter_traits_marker_TrustedFused_I_where_core_iter_traits_iterator_Iterator_I_for_core_iter_adapters_array_chunks_ArrayChunks_N_I.
        Definition Self (N : Value.t) (I : Ty.t) : Ty.t :=
          Ty.apply (Ty.path "core::iter::adapters::array_chunks::ArrayChunks") [ N ] [ I ].
        
        Axiom Implements :
          forall (N : Value.t) (I : Ty.t),
          M.IsTraitInstance
            "core::iter::traits::marker::TrustedFused"
            (Self N I)
            (* Trait polymorphic types *) []
            (* Instance *) [].
      End Impl_core_iter_traits_marker_TrustedFused_where_core_iter_traits_marker_TrustedFused_I_where_core_iter_traits_iterator_Iterator_I_for_core_iter_adapters_array_chunks_ArrayChunks_N_I.
      
      Module Impl_core_iter_traits_exact_size_ExactSizeIterator_where_core_iter_traits_exact_size_ExactSizeIterator_I_for_core_iter_adapters_array_chunks_ArrayChunks_N_I.
        Definition Self (N : Value.t) (I : Ty.t) : Ty.t :=
          Ty.apply (Ty.path "core::iter::adapters::array_chunks::ArrayChunks") [ N ] [ I ].
        
        (*
            fn len(&self) -> usize {
                self.iter.len() / N
            }
        *)
        Definition len
            (N : Value.t)
            (I : Ty.t)
            (ε : list Value.t)
            (τ : list Ty.t)
            (α : list Value.t)
            : M :=
          let Self : Ty.t := Self N I in
          match ε, τ, α with
          | [], [], [ self ] =>
            ltac:(M.monadic
              (let self := M.alloc (| self |) in
              BinOp.Wrap.div (|
                M.call_closure (|
                  M.get_trait_method (|
                    "core::iter::traits::exact_size::ExactSizeIterator",
                    I,
                    [],
                    "len",
                    []
                  |),
                  [
                    M.SubPointer.get_struct_record_field (|
                      M.read (| self |),
                      "core::iter::adapters::array_chunks::ArrayChunks",
                      "iter"
                    |)
                  ]
                |),
                M.read (| M.get_constant (| "core::iter::adapters::array_chunks::N" |) |)
              |)))
          | _, _, _ => M.impossible "wrong number of arguments"
          end.
        
        (*
            fn is_empty(&self) -> bool {
                self.iter.len() < N
            }
        *)
        Definition is_empty
            (N : Value.t)
            (I : Ty.t)
            (ε : list Value.t)
            (τ : list Ty.t)
            (α : list Value.t)
            : M :=
          let Self : Ty.t := Self N I in
          match ε, τ, α with
          | [], [], [ self ] =>
            ltac:(M.monadic
              (let self := M.alloc (| self |) in
              BinOp.lt (|
                M.call_closure (|
                  M.get_trait_method (|
                    "core::iter::traits::exact_size::ExactSizeIterator",
                    I,
                    [],
                    "len",
                    []
                  |),
                  [
                    M.SubPointer.get_struct_record_field (|
                      M.read (| self |),
                      "core::iter::adapters::array_chunks::ArrayChunks",
                      "iter"
                    |)
                  ]
                |),
                M.read (| M.get_constant (| "core::iter::adapters::array_chunks::N" |) |)
              |)))
          | _, _, _ => M.impossible "wrong number of arguments"
          end.
        
        Axiom Implements :
          forall (N : Value.t) (I : Ty.t),
          M.IsTraitInstance
            "core::iter::traits::exact_size::ExactSizeIterator"
            (Self N I)
            (* Trait polymorphic types *) []
            (* Instance *)
            [
              ("len", InstanceField.Method (len N I));
              ("is_empty", InstanceField.Method (is_empty N I))
            ].
      End Impl_core_iter_traits_exact_size_ExactSizeIterator_where_core_iter_traits_exact_size_ExactSizeIterator_I_for_core_iter_adapters_array_chunks_ArrayChunks_N_I.
      
      (* Trait *)
      (* Empty module 'SpecFold' *)
      
      Module Impl_core_iter_adapters_array_chunks_SpecFold_where_core_iter_traits_iterator_Iterator_I_for_core_iter_adapters_array_chunks_ArrayChunks_N_I.
        Definition Self (N : Value.t) (I : Ty.t) : Ty.t :=
          Ty.apply (Ty.path "core::iter::adapters::array_chunks::ArrayChunks") [ N ] [ I ].
        
        (*
            default fn fold<B, F>(mut self, init: B, f: F) -> B
            where
                Self: Sized,
                F: FnMut(B, Self::Item) -> B,
            {
                self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).0
            }
        *)
        Definition fold
            (N : Value.t)
            (I : Ty.t)
            (ε : list Value.t)
            (τ : list Ty.t)
            (α : list Value.t)
            : M :=
          let Self : Ty.t := Self N I in
          match ε, τ, α with
          | [], [ B; F ], [ self; init; f ] =>
            ltac:(M.monadic
              (let self := M.alloc (| self |) in
              let init := M.alloc (| init |) in
              let f := M.alloc (| f |) in
              M.read (|
                M.SubPointer.get_struct_tuple_field (|
                  M.alloc (|
                    M.call_closure (|
                      M.get_trait_method (|
                        "core::iter::traits::iterator::Iterator",
                        Ty.apply
                          (Ty.path "core::iter::adapters::array_chunks::ArrayChunks")
                          [ N ]
                          [ I ],
                        [],
                        "try_fold",
                        [
                          B;
                          Ty.associated;
                          Ty.apply (Ty.path "core::ops::try_trait::NeverShortCircuit") [] [ B ]
                        ]
                      |),
                      [
                        self;
                        M.read (| init |);
                        M.call_closure (|
                          M.get_associated_function (|
                            Ty.apply (Ty.path "core::ops::try_trait::NeverShortCircuit") [] [ B ],
                            "wrap_mut_2",
                            [ B; Ty.apply (Ty.path "array") [ N ] [ Ty.associated ]; F ]
                          |),
                          [ M.read (| f |) ]
                        |)
                      ]
                    |)
                  |),
                  "core::ops::try_trait::NeverShortCircuit",
                  0
                |)
              |)))
          | _, _, _ => M.impossible "wrong number of arguments"
          end.
        
        Axiom Implements :
          forall (N : Value.t) (I : Ty.t),
          M.IsTraitInstance
            "core::iter::adapters::array_chunks::SpecFold"
            (Self N I)
            (* Trait polymorphic types *) []
            (* Instance *) [ ("fold", InstanceField.Method (fold N I)) ].
      End Impl_core_iter_adapters_array_chunks_SpecFold_where_core_iter_traits_iterator_Iterator_I_for_core_iter_adapters_array_chunks_ArrayChunks_N_I.
      
      Module Impl_core_iter_adapters_array_chunks_SpecFold_where_core_iter_traits_iterator_Iterator_I_where_core_iter_adapters_zip_TrustedRandomAccessNoCoerce_I_for_core_iter_adapters_array_chunks_ArrayChunks_N_I.
        Definition Self (N : Value.t) (I : Ty.t) : Ty.t :=
          Ty.apply (Ty.path "core::iter::adapters::array_chunks::ArrayChunks") [ N ] [ I ].
        
        (*
            fn fold<B, F>(mut self, init: B, mut f: F) -> B
            where
                Self: Sized,
                F: FnMut(B, Self::Item) -> B,
            {
                let mut accum = init;
                let inner_len = self.iter.size();
                let mut i = 0;
                // Use a while loop because (0..len).step_by(N) doesn't optimize well.
                while inner_len - i >= N {
                    let chunk = crate::array::from_fn(|local| {
                        // SAFETY: The method consumes the iterator and the loop condition ensures that
                        // all accesses are in bounds and only happen once.
                        unsafe {
                            let idx = i + local;
                            self.iter.__iterator_get_unchecked(idx)
                        }
                    });
                    accum = f(accum, chunk);
                    i += N;
                }
        
                // unlike try_fold this method does not need to take care of the remainder
                // since `self` will be dropped
        
                accum
            }
        *)
        Definition fold
            (N : Value.t)
            (I : Ty.t)
            (ε : list Value.t)
            (τ : list Ty.t)
            (α : list Value.t)
            : M :=
          let Self : Ty.t := Self N I in
          match ε, τ, α with
          | [], [ B; F ], [ self; init; f ] =>
            ltac:(M.monadic
              (let self := M.alloc (| self |) in
              let init := M.alloc (| init |) in
              let f := M.alloc (| f |) in
              M.read (|
                let~ accum := M.copy (| init |) in
                let~ inner_len :=
                  M.alloc (|
                    M.call_closure (|
                      M.get_trait_method (|
                        "core::iter::adapters::zip::TrustedRandomAccessNoCoerce",
                        I,
                        [],
                        "size",
                        []
                      |),
                      [
                        M.SubPointer.get_struct_record_field (|
                          self,
                          "core::iter::adapters::array_chunks::ArrayChunks",
                          "iter"
                        |)
                      ]
                    |)
                  |) in
                let~ i := M.alloc (| Value.Integer IntegerKind.Usize 0 |) in
                let~ _ :=
                  M.loop (|
                    ltac:(M.monadic
                      (M.match_operator (|
                        M.alloc (| Value.Tuple [] |),
                        [
                          fun γ =>
                            ltac:(M.monadic
                              (let γ :=
                                M.use
                                  (M.alloc (|
                                    BinOp.ge (|
                                      BinOp.Wrap.sub (| M.read (| inner_len |), M.read (| i |) |),
                                      M.read (|
                                        M.get_constant (| "core::iter::adapters::array_chunks::N" |)
                                      |)
                                    |)
                                  |)) in
                              let _ :=
                                M.is_constant_or_break_match (|
                                  M.read (| γ |),
                                  Value.Bool true
                                |) in
                              let~ chunk :=
                                M.alloc (|
                                  M.call_closure (|
                                    M.get_function (|
                                      "core::array::from_fn",
                                      [
                                        Ty.associated;
                                        Ty.function [ Ty.tuple [ Ty.path "usize" ] ] Ty.associated
                                      ]
                                    |),
                                    [
                                      M.closure
                                        (fun γ =>
                                          ltac:(M.monadic
                                            match γ with
                                            | [ α0 ] =>
                                              ltac:(M.monadic
                                                (M.match_operator (|
                                                  M.alloc (| α0 |),
                                                  [
                                                    fun γ =>
                                                      ltac:(M.monadic
                                                        (let local := M.copy (| γ |) in
                                                        M.read (|
                                                          let~ idx :=
                                                            M.alloc (|
                                                              BinOp.Wrap.add (|
                                                                M.read (| i |),
                                                                M.read (| local |)
                                                              |)
                                                            |) in
                                                          M.alloc (|
                                                            M.call_closure (|
                                                              M.get_trait_method (|
                                                                "core::iter::traits::iterator::Iterator",
                                                                I,
                                                                [],
                                                                "__iterator_get_unchecked",
                                                                []
                                                              |),
                                                              [
                                                                M.SubPointer.get_struct_record_field (|
                                                                  self,
                                                                  "core::iter::adapters::array_chunks::ArrayChunks",
                                                                  "iter"
                                                                |);
                                                                M.read (| idx |)
                                                              ]
                                                            |)
                                                          |)
                                                        |)))
                                                  ]
                                                |)))
                                            | _ => M.impossible "wrong number of arguments"
                                            end))
                                    ]
                                  |)
                                |) in
                              let~ _ :=
                                M.write (|
                                  accum,
                                  M.call_closure (|
                                    M.get_trait_method (|
                                      "core::ops::function::FnMut",
                                      F,
                                      [
                                        Ty.tuple
                                          [ B; Ty.apply (Ty.path "array") [ N ] [ Ty.associated ] ]
                                      ],
                                      "call_mut",
                                      []
                                    |),
                                    [ f; Value.Tuple [ M.read (| accum |); M.read (| chunk |) ] ]
                                  |)
                                |) in
                              let~ _ :=
                                let β := i in
                                M.write (|
                                  β,
                                  BinOp.Wrap.add (|
                                    M.read (| β |),
                                    M.read (|
                                      M.get_constant (| "core::iter::adapters::array_chunks::N" |)
                                    |)
                                  |)
                                |) in
                              M.alloc (| Value.Tuple [] |)));
                          fun γ =>
                            ltac:(M.monadic
                              (M.alloc (|
                                M.never_to_any (|
                                  M.read (|
                                    let~ _ :=
                                      M.alloc (|
                                        M.never_to_any (| M.read (| M.break (||) |) |)
                                      |) in
                                    M.alloc (| Value.Tuple [] |)
                                  |)
                                |)
                              |)))
                        ]
                      |)))
                  |) in
                accum
              |)))
          | _, _, _ => M.impossible "wrong number of arguments"
          end.
        
        Axiom Implements :
          forall (N : Value.t) (I : Ty.t),
          M.IsTraitInstance
            "core::iter::adapters::array_chunks::SpecFold"
            (Self N I)
            (* Trait polymorphic types *) []
            (* Instance *) [ ("fold", InstanceField.Method (fold N I)) ].
      End Impl_core_iter_adapters_array_chunks_SpecFold_where_core_iter_traits_iterator_Iterator_I_where_core_iter_adapters_zip_TrustedRandomAccessNoCoerce_I_for_core_iter_adapters_array_chunks_ArrayChunks_N_I.
      
      Module Impl_core_iter_adapters_SourceIter_where_core_iter_adapters_SourceIter_I_where_core_iter_traits_iterator_Iterator_I_for_core_iter_adapters_array_chunks_ArrayChunks_N_I.
        Definition Self (N : Value.t) (I : Ty.t) : Ty.t :=
          Ty.apply (Ty.path "core::iter::adapters::array_chunks::ArrayChunks") [ N ] [ I ].
        
        (*     type Source = I::Source; *)
        Definition _Source (N : Value.t) (I : Ty.t) : Ty.t := Ty.associated.
        
        (*
            unsafe fn as_inner(&mut self) -> &mut I::Source {
                // SAFETY: unsafe function forwarding to unsafe function with the same requirements
                unsafe { SourceIter::as_inner(&mut self.iter) }
            }
        *)
        Definition as_inner
            (N : Value.t)
            (I : Ty.t)
            (ε : list Value.t)
            (τ : list Ty.t)
            (α : list Value.t)
            : M :=
          let Self : Ty.t := Self N I in
          match ε, τ, α with
          | [], [], [ self ] =>
            ltac:(M.monadic
              (let self := M.alloc (| self |) in
              M.call_closure (|
                M.get_trait_method (| "core::iter::adapters::SourceIter", I, [], "as_inner", [] |),
                [
                  M.SubPointer.get_struct_record_field (|
                    M.read (| self |),
                    "core::iter::adapters::array_chunks::ArrayChunks",
                    "iter"
                  |)
                ]
              |)))
          | _, _, _ => M.impossible "wrong number of arguments"
          end.
        
        Axiom Implements :
          forall (N : Value.t) (I : Ty.t),
          M.IsTraitInstance
            "core::iter::adapters::SourceIter"
            (Self N I)
            (* Trait polymorphic types *) []
            (* Instance *)
            [
              ("Source", InstanceField.Ty (_Source N I));
              ("as_inner", InstanceField.Method (as_inner N I))
            ].
      End Impl_core_iter_adapters_SourceIter_where_core_iter_adapters_SourceIter_I_where_core_iter_traits_iterator_Iterator_I_for_core_iter_adapters_array_chunks_ArrayChunks_N_I.
      
      Module Impl_core_iter_traits_marker_InPlaceIterable_where_core_iter_traits_marker_InPlaceIterable_I_where_core_iter_traits_iterator_Iterator_I_for_core_iter_adapters_array_chunks_ArrayChunks_N_I.
        Definition Self (N : Value.t) (I : Ty.t) : Ty.t :=
          Ty.apply (Ty.path "core::iter::adapters::array_chunks::ArrayChunks") [ N ] [ I ].
        
        (*     const EXPAND_BY: Option<NonZero<usize>> = I::EXPAND_BY; *)
        (* Ty.apply
          (Ty.path "core::option::Option")
          []
          [ Ty.apply (Ty.path "core::num::nonzero::NonZero") [] [ Ty.path "usize" ] ] *)
        Definition value_EXPAND_BY (N : Value.t) (I : Ty.t) : Value.t :=
          let Self : Ty.t := Self N I in
          M.run
            ltac:(M.monadic
              (M.get_constant (| "core::iter::traits::marker::InPlaceIterable::EXPAND_BY" |))).
        
        (*
            const MERGE_BY: Option<NonZero<usize>> = const {
                match (I::MERGE_BY, NonZero::new(N)) {
                    (Some(m), Some(n)) => m.checked_mul(n),
                    _ => None,
                }
            };
        *)
        (* Ty.apply
          (Ty.path "core::option::Option")
          []
          [ Ty.apply (Ty.path "core::num::nonzero::NonZero") [] [ Ty.path "usize" ] ] *)
        Definition value_MERGE_BY (N : Value.t) (I : Ty.t) : Value.t :=
          let Self : Ty.t := Self N I in
          M.run
            ltac:(M.monadic
              (M.get_constant (| "core::iter::adapters::array_chunks::MERGE_BY_discriminant" |))).
        
        Axiom Implements :
          forall (N : Value.t) (I : Ty.t),
          M.IsTraitInstance
            "core::iter::traits::marker::InPlaceIterable"
            (Self N I)
            (* Trait polymorphic types *) []
            (* Instance *)
            [
              ("value_EXPAND_BY", InstanceField.Constant (value_EXPAND_BY N I));
              ("value_MERGE_BY", InstanceField.Constant (value_MERGE_BY N I))
            ].
      End Impl_core_iter_traits_marker_InPlaceIterable_where_core_iter_traits_marker_InPlaceIterable_I_where_core_iter_traits_iterator_Iterator_I_for_core_iter_adapters_array_chunks_ArrayChunks_N_I.
    End array_chunks.
  End adapters.
End iter.
