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

Module iter.
  Module adapters.
    Module map_while.
      (* StructRecord
        {
          name := "MapWhile";
          const_params := [];
          ty_params := [ "I"; "P" ];
          fields := [ ("iter", I); ("predicate", P) ];
        } *)
      
      Module Impl_core_clone_Clone_where_core_clone_Clone_I_where_core_clone_Clone_P_for_core_iter_adapters_map_while_MapWhile_I_P.
        Definition Self (I P : Ty.t) : Ty.t :=
          Ty.apply (Ty.path "core::iter::adapters::map_while::MapWhile") [] [ I; P ].
        
        (* Clone *)
        Definition clone (I P : Ty.t) (ε : list Value.t) (τ : list Ty.t) (α : list Value.t) : M :=
          let Self : Ty.t := Self I P in
          match ε, τ, α with
          | [], [], [ self ] =>
            ltac:(M.monadic
              (let self := M.alloc (| self |) in
              Value.StructRecord
                "core::iter::adapters::map_while::MapWhile"
                [
                  ("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::map_while::MapWhile",
                          "iter"
                        |)
                      ]
                    |));
                  ("predicate",
                    M.call_closure (|
                      M.get_trait_method (| "core::clone::Clone", P, [], "clone", [] |),
                      [
                        M.SubPointer.get_struct_record_field (|
                          M.read (| self |),
                          "core::iter::adapters::map_while::MapWhile",
                          "predicate"
                        |)
                      ]
                    |))
                ]))
          | _, _, _ => M.impossible "wrong number of arguments"
          end.
        
        Axiom Implements :
          forall (I P : Ty.t),
          M.IsTraitInstance
            "core::clone::Clone"
            (Self I P)
            (* Trait polymorphic types *) []
            (* Instance *) [ ("clone", InstanceField.Method (clone I P)) ].
      End Impl_core_clone_Clone_where_core_clone_Clone_I_where_core_clone_Clone_P_for_core_iter_adapters_map_while_MapWhile_I_P.
      
      Module Impl_core_iter_adapters_map_while_MapWhile_I_P.
        Definition Self (I P : Ty.t) : Ty.t :=
          Ty.apply (Ty.path "core::iter::adapters::map_while::MapWhile") [] [ I; P ].
        
        (*
            pub(in crate::iter) fn new(iter: I, predicate: P) -> MapWhile<I, P> {
                MapWhile { iter, predicate }
            }
        *)
        Definition new (I P : Ty.t) (ε : list Value.t) (τ : list Ty.t) (α : list Value.t) : M :=
          let Self : Ty.t := Self I P in
          match ε, τ, α with
          | [], [], [ iter; predicate ] =>
            ltac:(M.monadic
              (let iter := M.alloc (| iter |) in
              let predicate := M.alloc (| predicate |) in
              Value.StructRecord
                "core::iter::adapters::map_while::MapWhile"
                [ ("iter", M.read (| iter |)); ("predicate", M.read (| predicate |)) ]))
          | _, _, _ => M.impossible "wrong number of arguments"
          end.
        
        Axiom AssociatedFunction_new :
          forall (I P : Ty.t),
          M.IsAssociatedFunction (Self I P) "new" (new I P).
      End Impl_core_iter_adapters_map_while_MapWhile_I_P.
      
      Module Impl_core_fmt_Debug_where_core_fmt_Debug_I_for_core_iter_adapters_map_while_MapWhile_I_P.
        Definition Self (I P : Ty.t) : Ty.t :=
          Ty.apply (Ty.path "core::iter::adapters::map_while::MapWhile") [] [ I; P ].
        
        (*
            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                f.debug_struct("MapWhile").field("iter", &self.iter).finish()
            }
        *)
        Definition fmt (I P : Ty.t) (ε : list Value.t) (τ : list Ty.t) (α : list Value.t) : M :=
          let Self : Ty.t := Self I P 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::builders::DebugStruct",
                  "finish",
                  []
                |),
                [
                  M.call_closure (|
                    M.get_associated_function (|
                      Ty.path "core::fmt::builders::DebugStruct",
                      "field",
                      []
                    |),
                    [
                      M.alloc (|
                        M.call_closure (|
                          M.get_associated_function (|
                            Ty.path "core::fmt::Formatter",
                            "debug_struct",
                            []
                          |),
                          [ M.read (| f |); M.read (| Value.String "MapWhile" |) ]
                        |)
                      |);
                      M.read (| Value.String "iter" |);
                      M.SubPointer.get_struct_record_field (|
                        M.read (| self |),
                        "core::iter::adapters::map_while::MapWhile",
                        "iter"
                      |)
                    ]
                  |)
                ]
              |)))
          | _, _, _ => M.impossible "wrong number of arguments"
          end.
        
        Axiom Implements :
          forall (I P : Ty.t),
          M.IsTraitInstance
            "core::fmt::Debug"
            (Self I P)
            (* Trait polymorphic types *) []
            (* Instance *) [ ("fmt", InstanceField.Method (fmt I P)) ].
      End Impl_core_fmt_Debug_where_core_fmt_Debug_I_for_core_iter_adapters_map_while_MapWhile_I_P.
      
      Module Impl_core_iter_traits_iterator_Iterator_where_core_iter_traits_iterator_Iterator_I_where_core_ops_function_FnMut_P_Tuple_associated_type__for_core_iter_adapters_map_while_MapWhile_I_P.
        Definition Self (B I P : Ty.t) : Ty.t :=
          Ty.apply (Ty.path "core::iter::adapters::map_while::MapWhile") [] [ I; P ].
        
        (*     type Item = B; *)
        Definition _Item (B I P : Ty.t) : Ty.t := B.
        
        (*
            fn next(&mut self) -> Option<B> {
                let x = self.iter.next()?;
                (self.predicate)(x)
            }
        *)
        Definition next (B I P : Ty.t) (ε : list Value.t) (τ : list Ty.t) (α : list Value.t) : M :=
          let Self : Ty.t := Self B I P in
          match ε, τ, α with
          | [], [], [ self ] =>
            ltac:(M.monadic
              (let self := M.alloc (| self |) in
              M.catch_return (|
                ltac:(M.monadic
                  (M.read (|
                    let~ x :=
                      M.copy (|
                        M.match_operator (|
                          M.alloc (|
                            M.call_closure (|
                              M.get_trait_method (|
                                "core::ops::try_trait::Try",
                                Ty.apply (Ty.path "core::option::Option") [] [ Ty.associated ],
                                [],
                                "branch",
                                []
                              |),
                              [
                                M.call_closure (|
                                  M.get_trait_method (|
                                    "core::iter::traits::iterator::Iterator",
                                    I,
                                    [],
                                    "next",
                                    []
                                  |),
                                  [
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| self |),
                                      "core::iter::adapters::map_while::MapWhile",
                                      "iter"
                                    |)
                                  ]
                                |)
                              ]
                            |)
                          |),
                          [
                            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",
                                            Ty.apply (Ty.path "core::option::Option") [] [ B ],
                                            [
                                              Ty.apply
                                                (Ty.path "core::option::Option")
                                                []
                                                [ Ty.path "core::convert::Infallible" ]
                                            ],
                                            "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))
                          ]
                        |)
                      |) in
                    M.alloc (|
                      M.call_closure (|
                        M.get_trait_method (|
                          "core::ops::function::FnMut",
                          P,
                          [ Ty.tuple [ Ty.associated ] ],
                          "call_mut",
                          []
                        |),
                        [
                          M.SubPointer.get_struct_record_field (|
                            M.read (| self |),
                            "core::iter::adapters::map_while::MapWhile",
                            "predicate"
                          |);
                          Value.Tuple [ M.read (| x |) ]
                        ]
                      |)
                    |)
                  |)))
              |)))
          | _, _, _ => M.impossible "wrong number of arguments"
          end.
        
        (*
            fn size_hint(&self) -> (usize, Option<usize>) {
                let (_, upper) = self.iter.size_hint();
                (0, upper) // can't know a lower bound, due to the predicate
            }
        *)
        Definition size_hint
            (B I P : Ty.t)
            (ε : list Value.t)
            (τ : list Ty.t)
            (α : list Value.t)
            : M :=
          let Self : Ty.t := Self B I P 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::map_while::MapWhile",
                          "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 upper := M.copy (| γ0_1 |) in
                        M.alloc (|
                          Value.Tuple [ Value.Integer IntegerKind.Usize 0; M.read (| upper |) ]
                        |)))
                  ]
                |)
              |)))
          | _, _, _ => M.impossible "wrong number of arguments"
          end.
        
        (*
            fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R
            where
                Self: Sized,
                Fold: FnMut(Acc, Self::Item) -> R,
                R: Try<Output = Acc>,
            {
                let Self { iter, predicate } = self;
                iter.try_fold(init, |acc, x| match predicate(x) {
                    Some(item) => ControlFlow::from_try(fold(acc, item)),
                    None => ControlFlow::Break(try { acc }),
                })
                .into_try()
            }
        *)
        Definition try_fold
            (B I P : Ty.t)
            (ε : list Value.t)
            (τ : list Ty.t)
            (α : list Value.t)
            : M :=
          let Self : Ty.t := Self B I P in
          match ε, τ, α with
          | [], [ Acc; Fold; R ], [ 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.match_operator (|
                  self,
                  [
                    fun γ =>
                      ltac:(M.monadic
                        (let γ := M.read (| γ |) in
                        let γ1_0 :=
                          M.SubPointer.get_struct_record_field (|
                            γ,
                            "core::iter::adapters::map_while::MapWhile",
                            "iter"
                          |) in
                        let γ1_1 :=
                          M.SubPointer.get_struct_record_field (|
                            γ,
                            "core::iter::adapters::map_while::MapWhile",
                            "predicate"
                          |) in
                        let iter := M.alloc (| γ1_0 |) in
                        let predicate := M.alloc (| γ1_1 |) in
                        M.alloc (|
                          M.call_closure (|
                            M.get_associated_function (|
                              Ty.apply
                                (Ty.path "core::ops::control_flow::ControlFlow")
                                []
                                [ R; Ty.associated ],
                              "into_try",
                              []
                            |),
                            [
                              M.call_closure (|
                                M.get_trait_method (|
                                  "core::iter::traits::iterator::Iterator",
                                  I,
                                  [],
                                  "try_fold",
                                  [
                                    Acc;
                                    Ty.function
                                      [ Ty.tuple [ Acc; Ty.associated ] ]
                                      (Ty.apply
                                        (Ty.path "core::ops::control_flow::ControlFlow")
                                        []
                                        [ R; Acc ]);
                                    Ty.apply
                                      (Ty.path "core::ops::control_flow::ControlFlow")
                                      []
                                      [ R; Acc ]
                                  ]
                                |),
                                [
                                  M.read (| iter |);
                                  M.read (| init |);
                                  M.closure
                                    (fun γ =>
                                      ltac:(M.monadic
                                        match γ with
                                        | [ α0; α1 ] =>
                                          ltac:(M.monadic
                                            (M.match_operator (|
                                              M.alloc (| α0 |),
                                              [
                                                fun γ =>
                                                  ltac:(M.monadic
                                                    (let acc := M.copy (| γ |) in
                                                    M.match_operator (|
                                                      M.alloc (| α1 |),
                                                      [
                                                        fun γ =>
                                                          ltac:(M.monadic
                                                            (let x := M.copy (| γ |) in
                                                            M.read (|
                                                              M.match_operator (|
                                                                M.alloc (|
                                                                  M.call_closure (|
                                                                    M.get_trait_method (|
                                                                      "core::ops::function::FnMut",
                                                                      P,
                                                                      [ Ty.tuple [ Ty.associated ]
                                                                      ],
                                                                      "call_mut",
                                                                      []
                                                                    |),
                                                                    [
                                                                      M.read (| predicate |);
                                                                      Value.Tuple [ M.read (| x |) ]
                                                                    ]
                                                                  |)
                                                                |),
                                                                [
                                                                  fun γ =>
                                                                    ltac:(M.monadic
                                                                      (let γ0_0 :=
                                                                        M.SubPointer.get_struct_tuple_field (|
                                                                          γ,
                                                                          "core::option::Option::Some",
                                                                          0
                                                                        |) in
                                                                      let item :=
                                                                        M.copy (| γ0_0 |) in
                                                                      M.alloc (|
                                                                        M.call_closure (|
                                                                          M.get_associated_function (|
                                                                            Ty.apply
                                                                              (Ty.path
                                                                                "core::ops::control_flow::ControlFlow")
                                                                              []
                                                                              [ R; Ty.associated ],
                                                                            "from_try",
                                                                            []
                                                                          |),
                                                                          [
                                                                            M.call_closure (|
                                                                              M.get_trait_method (|
                                                                                "core::ops::function::FnMut",
                                                                                Fold,
                                                                                [
                                                                                  Ty.tuple
                                                                                    [ Acc; B ]
                                                                                ],
                                                                                "call_mut",
                                                                                []
                                                                              |),
                                                                              [
                                                                                fold;
                                                                                Value.Tuple
                                                                                  [
                                                                                    M.read (|
                                                                                      acc
                                                                                    |);
                                                                                    M.read (|
                                                                                      item
                                                                                    |)
                                                                                  ]
                                                                              ]
                                                                            |)
                                                                          ]
                                                                        |)
                                                                      |)));
                                                                  fun γ =>
                                                                    ltac:(M.monadic
                                                                      (let _ :=
                                                                        M.is_struct_tuple (|
                                                                          γ,
                                                                          "core::option::Option::None"
                                                                        |) in
                                                                      M.alloc (|
                                                                        Value.StructTuple
                                                                          "core::ops::control_flow::ControlFlow::Break"
                                                                          [
                                                                            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))
                                ]
                              |)
                            ]
                          |)
                        |)))
                  ]
                |)
              |)))
          | _, _, _ => 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 fold (B I P : Ty.t) (ε : list Value.t) (τ : list Ty.t) (α : list Value.t) : M :=
          let Self : Ty.t := Self B I P 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::iterator::Iterator",
                        Ty.apply (Ty.path "core::iter::adapters::map_while::MapWhile") [] [ I; P ],
                        [],
                        "try_fold",
                        [
                          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; B; FFF ]
                          |),
                          [ M.read (| fold |) ]
                        |)
                      ]
                    |)
                  |),
                  "core::ops::try_trait::NeverShortCircuit",
                  0
                |)
              |)))
          | _, _, _ => M.impossible "wrong number of arguments"
          end.
        
        Axiom Implements :
          forall (B I P : Ty.t),
          M.IsTraitInstance
            "core::iter::traits::iterator::Iterator"
            (Self B I P)
            (* Trait polymorphic types *) []
            (* Instance *)
            [
              ("Item", InstanceField.Ty (_Item B I P));
              ("next", InstanceField.Method (next B I P));
              ("size_hint", InstanceField.Method (size_hint B I P));
              ("try_fold", InstanceField.Method (try_fold B I P));
              ("fold", InstanceField.Method (fold B I P))
            ].
      End Impl_core_iter_traits_iterator_Iterator_where_core_iter_traits_iterator_Iterator_I_where_core_ops_function_FnMut_P_Tuple_associated_type__for_core_iter_adapters_map_while_MapWhile_I_P.
      
      Module Impl_core_iter_adapters_SourceIter_where_core_iter_adapters_SourceIter_I_for_core_iter_adapters_map_while_MapWhile_I_P.
        Definition Self (I P : Ty.t) : Ty.t :=
          Ty.apply (Ty.path "core::iter::adapters::map_while::MapWhile") [] [ I; P ].
        
        (*     type Source = I::Source; *)
        Definition _Source (I P : 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
            (I P : Ty.t)
            (ε : list Value.t)
            (τ : list Ty.t)
            (α : list Value.t)
            : M :=
          let Self : Ty.t := Self I P 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::map_while::MapWhile",
                    "iter"
                  |)
                ]
              |)))
          | _, _, _ => M.impossible "wrong number of arguments"
          end.
        
        Axiom Implements :
          forall (I P : Ty.t),
          M.IsTraitInstance
            "core::iter::adapters::SourceIter"
            (Self I P)
            (* Trait polymorphic types *) []
            (* Instance *)
            [
              ("Source", InstanceField.Ty (_Source I P));
              ("as_inner", InstanceField.Method (as_inner I P))
            ].
      End Impl_core_iter_adapters_SourceIter_where_core_iter_adapters_SourceIter_I_for_core_iter_adapters_map_while_MapWhile_I_P.
      
      Module Impl_core_iter_traits_marker_InPlaceIterable_where_core_iter_traits_marker_InPlaceIterable_I_for_core_iter_adapters_map_while_MapWhile_I_P.
        Definition Self (I P : Ty.t) : Ty.t :=
          Ty.apply (Ty.path "core::iter::adapters::map_while::MapWhile") [] [ I; P ].
        
        (*     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 (I P : Ty.t) : Value.t :=
          let Self : Ty.t := Self I P in
          M.run
            ltac:(M.monadic
              (M.get_constant (| "core::iter::traits::marker::InPlaceIterable::EXPAND_BY" |))).
        
        (*     const MERGE_BY: Option<NonZero<usize>> = I::MERGE_BY; *)
        (* Ty.apply
          (Ty.path "core::option::Option")
          []
          [ Ty.apply (Ty.path "core::num::nonzero::NonZero") [] [ Ty.path "usize" ] ] *)
        Definition value_MERGE_BY (I P : Ty.t) : Value.t :=
          let Self : Ty.t := Self I P in
          M.run
            ltac:(M.monadic
              (M.get_constant (| "core::iter::traits::marker::InPlaceIterable::MERGE_BY" |))).
        
        Axiom Implements :
          forall (I P : Ty.t),
          M.IsTraitInstance
            "core::iter::traits::marker::InPlaceIterable"
            (Self I P)
            (* Trait polymorphic types *) []
            (* Instance *)
            [
              ("value_EXPAND_BY", InstanceField.Constant (value_EXPAND_BY I P));
              ("value_MERGE_BY", InstanceField.Constant (value_MERGE_BY I P))
            ].
      End Impl_core_iter_traits_marker_InPlaceIterable_where_core_iter_traits_marker_InPlaceIterable_I_for_core_iter_adapters_map_while_MapWhile_I_P.
    End map_while.
  End adapters.
End iter.
