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

Module struct_defs.
  (* StructRecord
    {
      name := "RecursiveStructDefChecker";
      const_params := [];
      ty_params := [];
      fields :=
        [
          ("module",
            Ty.apply (Ty.path "&") [] [ Ty.path "move_binary_format::file_format::CompiledModule" ])
        ];
    } *)
  
  Module Impl_move_bytecode_verifier_struct_defs_RecursiveStructDefChecker.
    Definition Self : Ty.t :=
      Ty.path "move_bytecode_verifier::struct_defs::RecursiveStructDefChecker".
    
    (*
        pub fn verify_module(module: &'a CompiledModule) -> VMResult<()> {
            Self::verify_module_impl(module).map_err(|e| e.finish(Location::Module(module.self_id())))
        }
    *)
    Definition verify_module (ε : list Value.t) (τ : list Ty.t) (α : list Value.t) : M :=
      match ε, τ, α with
      | [], [], [ module ] =>
        ltac:(M.monadic
          (let module := M.alloc (| module |) in
          M.call_closure (|
            M.get_associated_function (|
              Ty.apply
                (Ty.path "core::result::Result")
                []
                [ Ty.tuple []; Ty.path "move_binary_format::errors::PartialVMError" ],
              "map_err",
              [
                Ty.path "move_binary_format::errors::VMError";
                Ty.function
                  [ Ty.tuple [ Ty.path "move_binary_format::errors::PartialVMError" ] ]
                  (Ty.path "move_binary_format::errors::VMError")
              ]
            |),
            [
              M.call_closure (|
                M.get_associated_function (|
                  Ty.path "move_bytecode_verifier::struct_defs::RecursiveStructDefChecker",
                  "verify_module_impl",
                  []
                |),
                [ M.read (| module |) ]
              |);
              M.closure
                (fun γ =>
                  ltac:(M.monadic
                    match γ with
                    | [ α0 ] =>
                      ltac:(M.monadic
                        (M.match_operator (|
                          M.alloc (| α0 |),
                          [
                            fun γ =>
                              ltac:(M.monadic
                                (let e := M.copy (| γ |) in
                                M.call_closure (|
                                  M.get_associated_function (|
                                    Ty.path "move_binary_format::errors::PartialVMError",
                                    "finish",
                                    []
                                  |),
                                  [
                                    M.read (| e |);
                                    Value.StructTuple
                                      "move_binary_format::errors::Location::Module"
                                      [
                                        M.call_closure (|
                                          M.get_associated_function (|
                                            Ty.path
                                              "move_binary_format::file_format::CompiledModule",
                                            "self_id",
                                            []
                                          |),
                                          [ M.read (| module |) ]
                                        |)
                                      ]
                                  ]
                                |)))
                          ]
                        |)))
                    | _ => M.impossible "wrong number of arguments"
                    end))
            ]
          |)))
      | _, _, _ => M.impossible "wrong number of arguments"
      end.
    
    Axiom AssociatedFunction_verify_module :
      M.IsAssociatedFunction Self "verify_module" verify_module.
    
    (*
        fn verify_module_impl(module: &'a CompiledModule) -> PartialVMResult<()> {
            let checker = Self { module };
            let graph = StructDefGraphBuilder::new(checker.module).build()?;
    
            // toposort is iterative while petgraph::algo::is_cyclic_directed is recursive. Prefer
            // the iterative solution here as this code may be dealing with untrusted data.
            match toposort(&graph, None) {
                Ok(_) => Ok(()),
                Err(cycle) => Err(verification_error(
                    StatusCode::RECURSIVE_STRUCT_DEFINITION,
                    IndexKind::StructDefinition,
                    cycle.node_id().into_index() as TableIndex,
                )),
            }
        }
    *)
    Definition verify_module_impl (ε : list Value.t) (τ : list Ty.t) (α : list Value.t) : M :=
      match ε, τ, α with
      | [], [], [ module ] =>
        ltac:(M.monadic
          (let module := M.alloc (| module |) in
          M.catch_return (|
            ltac:(M.monadic
              (M.read (|
                let~ checker :=
                  M.alloc (|
                    Value.StructRecord
                      "move_bytecode_verifier::struct_defs::RecursiveStructDefChecker"
                      [ ("module", M.read (| module |)) ]
                  |) in
                let~ graph :=
                  M.copy (|
                    M.match_operator (|
                      M.alloc (|
                        M.call_closure (|
                          M.get_trait_method (|
                            "core::ops::try_trait::Try",
                            Ty.apply
                              (Ty.path "core::result::Result")
                              []
                              [
                                Ty.apply
                                  (Ty.path "petgraph::graphmap::GraphMap")
                                  []
                                  [
                                    Ty.path
                                      "move_binary_format::file_format::StructDefinitionIndex";
                                    Ty.tuple [];
                                    Ty.path "petgraph::Directed"
                                  ];
                                Ty.path "move_binary_format::errors::PartialVMError"
                              ],
                            [],
                            "branch",
                            []
                          |),
                          [
                            M.call_closure (|
                              M.get_associated_function (|
                                Ty.path
                                  "move_bytecode_verifier::struct_defs::StructDefGraphBuilder",
                                "build",
                                []
                              |),
                              [
                                M.call_closure (|
                                  M.get_associated_function (|
                                    Ty.path
                                      "move_bytecode_verifier::struct_defs::StructDefGraphBuilder",
                                    "new",
                                    []
                                  |),
                                  [
                                    M.read (|
                                      M.SubPointer.get_struct_record_field (|
                                        checker,
                                        "move_bytecode_verifier::struct_defs::RecursiveStructDefChecker",
                                        "module"
                                      |)
                                    |)
                                  ]
                                |)
                              ]
                            |)
                          ]
                        |)
                      |),
                      [
                        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::result::Result")
                                          []
                                          [
                                            Ty.tuple [];
                                            Ty.path "move_binary_format::errors::PartialVMError"
                                          ],
                                        [
                                          Ty.apply
                                            (Ty.path "core::result::Result")
                                            []
                                            [
                                              Ty.path "core::convert::Infallible";
                                              Ty.path "move_binary_format::errors::PartialVMError"
                                            ]
                                        ],
                                        "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.match_operator (|
                  M.alloc (|
                    M.call_closure (|
                      M.get_function (|
                        "petgraph::algo::toposort",
                        [
                          Ty.apply
                            (Ty.path "&")
                            []
                            [
                              Ty.apply
                                (Ty.path "petgraph::graphmap::GraphMap")
                                []
                                [
                                  Ty.path "move_binary_format::file_format::StructDefinitionIndex";
                                  Ty.tuple [];
                                  Ty.path "petgraph::Directed"
                                ]
                            ]
                        ]
                      |),
                      [ graph; Value.StructTuple "core::option::Option::None" [] ]
                    |)
                  |),
                  [
                    fun γ =>
                      ltac:(M.monadic
                        (let γ0_0 :=
                          M.SubPointer.get_struct_tuple_field (|
                            γ,
                            "core::result::Result::Ok",
                            0
                          |) in
                        M.alloc (|
                          Value.StructTuple "core::result::Result::Ok" [ Value.Tuple [] ]
                        |)));
                    fun γ =>
                      ltac:(M.monadic
                        (let γ0_0 :=
                          M.SubPointer.get_struct_tuple_field (|
                            γ,
                            "core::result::Result::Err",
                            0
                          |) in
                        let cycle := M.copy (| γ0_0 |) in
                        M.alloc (|
                          Value.StructTuple
                            "core::result::Result::Err"
                            [
                              M.call_closure (|
                                M.get_function (|
                                  "move_binary_format::errors::verification_error",
                                  []
                                |),
                                [
                                  Value.StructTuple
                                    "move_core_types::vm_status::StatusCode::RECURSIVE_STRUCT_DEFINITION"
                                    [];
                                  Value.StructTuple
                                    "move_binary_format::IndexKind::StructDefinition"
                                    [];
                                  M.rust_cast
                                    (M.call_closure (|
                                      M.get_trait_method (|
                                        "move_binary_format::internals::ModuleIndex",
                                        Ty.path
                                          "move_binary_format::file_format::StructDefinitionIndex",
                                        [],
                                        "into_index",
                                        []
                                      |),
                                      [
                                        M.call_closure (|
                                          M.get_associated_function (|
                                            Ty.apply
                                              (Ty.path "petgraph::algo::Cycle")
                                              []
                                              [
                                                Ty.path
                                                  "move_binary_format::file_format::StructDefinitionIndex"
                                              ],
                                            "node_id",
                                            []
                                          |),
                                          [ cycle ]
                                        |)
                                      ]
                                    |))
                                ]
                              |)
                            ]
                        |)))
                  ]
                |)
              |)))
          |)))
      | _, _, _ => M.impossible "wrong number of arguments"
      end.
    
    Axiom AssociatedFunction_verify_module_impl :
      M.IsAssociatedFunction Self "verify_module_impl" verify_module_impl.
  End Impl_move_bytecode_verifier_struct_defs_RecursiveStructDefChecker.
  
  (* StructRecord
    {
      name := "StructDefGraphBuilder";
      const_params := [];
      ty_params := [];
      fields :=
        [
          ("module",
            Ty.apply
              (Ty.path "&")
              []
              [ Ty.path "move_binary_format::file_format::CompiledModule" ]);
          ("handle_to_def",
            Ty.apply
              (Ty.path "alloc::collections::btree::map::BTreeMap")
              []
              [
                Ty.path "move_binary_format::file_format::StructHandleIndex";
                Ty.path "move_binary_format::file_format::StructDefinitionIndex";
                Ty.path "alloc::alloc::Global"
              ])
        ];
    } *)
  
  Module Impl_move_bytecode_verifier_struct_defs_StructDefGraphBuilder.
    Definition Self : Ty.t := Ty.path "move_bytecode_verifier::struct_defs::StructDefGraphBuilder".
    
    (*
        fn new(module: &'a CompiledModule) -> Self {
            let mut handle_to_def = BTreeMap::new();
            // the mapping from struct definitions to struct handles is already checked to be 1-1 by
            // DuplicationChecker
            for (idx, struct_def) in module.struct_defs().iter().enumerate() {
                let sh_idx = struct_def.struct_handle;
                handle_to_def.insert(sh_idx, StructDefinitionIndex(idx as TableIndex));
            }
    
            Self {
                module,
                handle_to_def,
            }
        }
    *)
    Definition new (ε : list Value.t) (τ : list Ty.t) (α : list Value.t) : M :=
      match ε, τ, α with
      | [], [], [ module ] =>
        ltac:(M.monadic
          (let module := M.alloc (| module |) in
          M.read (|
            let~ handle_to_def :=
              M.alloc (|
                M.call_closure (|
                  M.get_associated_function (|
                    Ty.apply
                      (Ty.path "alloc::collections::btree::map::BTreeMap")
                      []
                      [
                        Ty.path "move_binary_format::file_format::StructHandleIndex";
                        Ty.path "move_binary_format::file_format::StructDefinitionIndex";
                        Ty.path "alloc::alloc::Global"
                      ],
                    "new",
                    []
                  |),
                  []
                |)
              |) in
            let~ _ :=
              M.use
                (M.match_operator (|
                  M.alloc (|
                    M.call_closure (|
                      M.get_trait_method (|
                        "core::iter::traits::collect::IntoIterator",
                        Ty.apply
                          (Ty.path "core::iter::adapters::enumerate::Enumerate")
                          []
                          [
                            Ty.apply
                              (Ty.path "core::slice::iter::Iter")
                              []
                              [ Ty.path "move_binary_format::file_format::StructDefinition" ]
                          ],
                        [],
                        "into_iter",
                        []
                      |),
                      [
                        M.call_closure (|
                          M.get_trait_method (|
                            "core::iter::traits::iterator::Iterator",
                            Ty.apply
                              (Ty.path "core::slice::iter::Iter")
                              []
                              [ Ty.path "move_binary_format::file_format::StructDefinition" ],
                            [],
                            "enumerate",
                            []
                          |),
                          [
                            M.call_closure (|
                              M.get_associated_function (|
                                Ty.apply
                                  (Ty.path "slice")
                                  []
                                  [ Ty.path "move_binary_format::file_format::StructDefinition" ],
                                "iter",
                                []
                              |),
                              [
                                M.call_closure (|
                                  M.get_associated_function (|
                                    Ty.path "move_binary_format::file_format::CompiledModule",
                                    "struct_defs",
                                    []
                                  |),
                                  [ M.read (| module |) ]
                                |)
                              ]
                            |)
                          ]
                        |)
                      ]
                    |)
                  |),
                  [
                    fun γ =>
                      ltac:(M.monadic
                        (let iter := M.copy (| γ |) in
                        M.loop (|
                          ltac:(M.monadic
                            (let~ _ :=
                              M.match_operator (|
                                M.alloc (|
                                  M.call_closure (|
                                    M.get_trait_method (|
                                      "core::iter::traits::iterator::Iterator",
                                      Ty.apply
                                        (Ty.path "core::iter::adapters::enumerate::Enumerate")
                                        []
                                        [
                                          Ty.apply
                                            (Ty.path "core::slice::iter::Iter")
                                            []
                                            [
                                              Ty.path
                                                "move_binary_format::file_format::StructDefinition"
                                            ]
                                        ],
                                      [],
                                      "next",
                                      []
                                    |),
                                    [ iter ]
                                  |)
                                |),
                                [
                                  fun γ =>
                                    ltac:(M.monadic
                                      (let _ :=
                                        M.is_struct_tuple (| γ, "core::option::Option::None" |) in
                                      M.alloc (|
                                        M.never_to_any (| M.read (| M.break (||) |) |)
                                      |)));
                                  fun γ =>
                                    ltac:(M.monadic
                                      (let γ0_0 :=
                                        M.SubPointer.get_struct_tuple_field (|
                                          γ,
                                          "core::option::Option::Some",
                                          0
                                        |) in
                                      let γ1_0 := M.SubPointer.get_tuple_field (| γ0_0, 0 |) in
                                      let γ1_1 := M.SubPointer.get_tuple_field (| γ0_0, 1 |) in
                                      let idx := M.copy (| γ1_0 |) in
                                      let struct_def := M.copy (| γ1_1 |) in
                                      let~ sh_idx :=
                                        M.copy (|
                                          M.SubPointer.get_struct_record_field (|
                                            M.read (| struct_def |),
                                            "move_binary_format::file_format::StructDefinition",
                                            "struct_handle"
                                          |)
                                        |) in
                                      let~ _ :=
                                        M.alloc (|
                                          M.call_closure (|
                                            M.get_associated_function (|
                                              Ty.apply
                                                (Ty.path "alloc::collections::btree::map::BTreeMap")
                                                []
                                                [
                                                  Ty.path
                                                    "move_binary_format::file_format::StructHandleIndex";
                                                  Ty.path
                                                    "move_binary_format::file_format::StructDefinitionIndex";
                                                  Ty.path "alloc::alloc::Global"
                                                ],
                                              "insert",
                                              []
                                            |),
                                            [
                                              handle_to_def;
                                              M.read (| sh_idx |);
                                              Value.StructTuple
                                                "move_binary_format::file_format::StructDefinitionIndex"
                                                [ M.rust_cast (M.read (| idx |)) ]
                                            ]
                                          |)
                                        |) in
                                      M.alloc (| Value.Tuple [] |)))
                                ]
                              |) in
                            M.alloc (| Value.Tuple [] |)))
                        |)))
                  ]
                |)) in
            M.alloc (|
              Value.StructRecord
                "move_bytecode_verifier::struct_defs::StructDefGraphBuilder"
                [ ("module", M.read (| module |)); ("handle_to_def", M.read (| handle_to_def |)) ]
            |)
          |)))
      | _, _, _ => M.impossible "wrong number of arguments"
      end.
    
    Axiom AssociatedFunction_new : M.IsAssociatedFunction Self "new" new.
    
    (*
        fn build(self) -> PartialVMResult<DiGraphMap<StructDefinitionIndex, ()>> {
            let mut neighbors = BTreeMap::new();
            for idx in 0..self.module.struct_defs().len() {
                let sd_idx = StructDefinitionIndex::new(idx as TableIndex);
                self.add_struct_defs(&mut neighbors, sd_idx)?
            }
    
            let edges = neighbors
                .into_iter()
                .flat_map(|(parent, children)| children.into_iter().map(move |child| (parent, child)));
            Ok(DiGraphMap::from_edges(edges))
        }
    *)
    Definition build (ε : list Value.t) (τ : list Ty.t) (α : list Value.t) : M :=
      match ε, τ, α with
      | [], [], [ self ] =>
        ltac:(M.monadic
          (let self := M.alloc (| self |) in
          M.catch_return (|
            ltac:(M.monadic
              (M.read (|
                let~ neighbors :=
                  M.alloc (|
                    M.call_closure (|
                      M.get_associated_function (|
                        Ty.apply
                          (Ty.path "alloc::collections::btree::map::BTreeMap")
                          []
                          [
                            Ty.path "move_binary_format::file_format::StructDefinitionIndex";
                            Ty.apply
                              (Ty.path "alloc::collections::btree::set::BTreeSet")
                              []
                              [
                                Ty.path "move_binary_format::file_format::StructDefinitionIndex";
                                Ty.path "alloc::alloc::Global"
                              ];
                            Ty.path "alloc::alloc::Global"
                          ],
                        "new",
                        []
                      |),
                      []
                    |)
                  |) in
                let~ _ :=
                  M.use
                    (M.match_operator (|
                      M.alloc (|
                        M.call_closure (|
                          M.get_trait_method (|
                            "core::iter::traits::collect::IntoIterator",
                            Ty.apply (Ty.path "core::ops::range::Range") [] [ Ty.path "usize" ],
                            [],
                            "into_iter",
                            []
                          |),
                          [
                            Value.StructRecord
                              "core::ops::range::Range"
                              [
                                ("start", Value.Integer IntegerKind.Usize 0);
                                ("end_",
                                  M.call_closure (|
                                    M.get_associated_function (|
                                      Ty.apply
                                        (Ty.path "slice")
                                        []
                                        [
                                          Ty.path
                                            "move_binary_format::file_format::StructDefinition"
                                        ],
                                      "len",
                                      []
                                    |),
                                    [
                                      M.call_closure (|
                                        M.get_associated_function (|
                                          Ty.path "move_binary_format::file_format::CompiledModule",
                                          "struct_defs",
                                          []
                                        |),
                                        [
                                          M.read (|
                                            M.SubPointer.get_struct_record_field (|
                                              self,
                                              "move_bytecode_verifier::struct_defs::StructDefGraphBuilder",
                                              "module"
                                            |)
                                          |)
                                        ]
                                      |)
                                    ]
                                  |))
                              ]
                          ]
                        |)
                      |),
                      [
                        fun γ =>
                          ltac:(M.monadic
                            (let iter := M.copy (| γ |) in
                            M.loop (|
                              ltac:(M.monadic
                                (let~ _ :=
                                  M.match_operator (|
                                    M.alloc (|
                                      M.call_closure (|
                                        M.get_trait_method (|
                                          "core::iter::traits::iterator::Iterator",
                                          Ty.apply
                                            (Ty.path "core::ops::range::Range")
                                            []
                                            [ Ty.path "usize" ],
                                          [],
                                          "next",
                                          []
                                        |),
                                        [ iter ]
                                      |)
                                    |),
                                    [
                                      fun γ =>
                                        ltac:(M.monadic
                                          (let _ :=
                                            M.is_struct_tuple (|
                                              γ,
                                              "core::option::Option::None"
                                            |) in
                                          M.alloc (|
                                            M.never_to_any (| M.read (| M.break (||) |) |)
                                          |)));
                                      fun γ =>
                                        ltac:(M.monadic
                                          (let γ0_0 :=
                                            M.SubPointer.get_struct_tuple_field (|
                                              γ,
                                              "core::option::Option::Some",
                                              0
                                            |) in
                                          let idx := M.copy (| γ0_0 |) in
                                          let~ sd_idx :=
                                            M.alloc (|
                                              M.call_closure (|
                                                M.get_associated_function (|
                                                  Ty.path
                                                    "move_binary_format::file_format::StructDefinitionIndex",
                                                  "new",
                                                  []
                                                |),
                                                [ M.rust_cast (M.read (| idx |)) ]
                                              |)
                                            |) in
                                          M.match_operator (|
                                            M.alloc (|
                                              M.call_closure (|
                                                M.get_trait_method (|
                                                  "core::ops::try_trait::Try",
                                                  Ty.apply
                                                    (Ty.path "core::result::Result")
                                                    []
                                                    [
                                                      Ty.tuple [];
                                                      Ty.path
                                                        "move_binary_format::errors::PartialVMError"
                                                    ],
                                                  [],
                                                  "branch",
                                                  []
                                                |),
                                                [
                                                  M.call_closure (|
                                                    M.get_associated_function (|
                                                      Ty.path
                                                        "move_bytecode_verifier::struct_defs::StructDefGraphBuilder",
                                                      "add_struct_defs",
                                                      []
                                                    |),
                                                    [ self; neighbors; M.read (| sd_idx |) ]
                                                  |)
                                                ]
                                              |)
                                            |),
                                            [
                                              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::result::Result")
                                                                []
                                                                [
                                                                  Ty.apply
                                                                    (Ty.path
                                                                      "petgraph::graphmap::GraphMap")
                                                                    []
                                                                    [
                                                                      Ty.path
                                                                        "move_binary_format::file_format::StructDefinitionIndex";
                                                                      Ty.tuple [];
                                                                      Ty.path "petgraph::Directed"
                                                                    ];
                                                                  Ty.path
                                                                    "move_binary_format::errors::PartialVMError"
                                                                ],
                                                              [
                                                                Ty.apply
                                                                  (Ty.path "core::result::Result")
                                                                  []
                                                                  [
                                                                    Ty.path
                                                                      "core::convert::Infallible";
                                                                    Ty.path
                                                                      "move_binary_format::errors::PartialVMError"
                                                                  ]
                                                              ],
                                                              "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 (| Value.Tuple [] |)))
                            |)))
                      ]
                    |)) in
                let~ edges :=
                  M.alloc (|
                    M.call_closure (|
                      M.get_trait_method (|
                        "core::iter::traits::iterator::Iterator",
                        Ty.apply
                          (Ty.path "alloc::collections::btree::map::IntoIter")
                          []
                          [
                            Ty.path "move_binary_format::file_format::StructDefinitionIndex";
                            Ty.apply
                              (Ty.path "alloc::collections::btree::set::BTreeSet")
                              []
                              [
                                Ty.path "move_binary_format::file_format::StructDefinitionIndex";
                                Ty.path "alloc::alloc::Global"
                              ];
                            Ty.path "alloc::alloc::Global"
                          ],
                        [],
                        "flat_map",
                        [
                          Ty.apply
                            (Ty.path "core::iter::adapters::map::Map")
                            []
                            [
                              Ty.apply
                                (Ty.path "alloc::collections::btree::set::IntoIter")
                                []
                                [
                                  Ty.path "move_binary_format::file_format::StructDefinitionIndex";
                                  Ty.path "alloc::alloc::Global"
                                ];
                              Ty.function
                                [
                                  Ty.tuple
                                    [
                                      Ty.path
                                        "move_binary_format::file_format::StructDefinitionIndex"
                                    ]
                                ]
                                (Ty.tuple
                                  [
                                    Ty.path
                                      "move_binary_format::file_format::StructDefinitionIndex";
                                    Ty.path "move_binary_format::file_format::StructDefinitionIndex"
                                  ])
                            ];
                          Ty.function
                            [
                              Ty.tuple
                                [
                                  Ty.tuple
                                    [
                                      Ty.path
                                        "move_binary_format::file_format::StructDefinitionIndex";
                                      Ty.apply
                                        (Ty.path "alloc::collections::btree::set::BTreeSet")
                                        []
                                        [
                                          Ty.path
                                            "move_binary_format::file_format::StructDefinitionIndex";
                                          Ty.path "alloc::alloc::Global"
                                        ]
                                    ]
                                ]
                            ]
                            (Ty.apply
                              (Ty.path "core::iter::adapters::map::Map")
                              []
                              [
                                Ty.apply
                                  (Ty.path "alloc::collections::btree::set::IntoIter")
                                  []
                                  [
                                    Ty.path
                                      "move_binary_format::file_format::StructDefinitionIndex";
                                    Ty.path "alloc::alloc::Global"
                                  ];
                                Ty.function
                                  [
                                    Ty.tuple
                                      [
                                        Ty.path
                                          "move_binary_format::file_format::StructDefinitionIndex"
                                      ]
                                  ]
                                  (Ty.tuple
                                    [
                                      Ty.path
                                        "move_binary_format::file_format::StructDefinitionIndex";
                                      Ty.path
                                        "move_binary_format::file_format::StructDefinitionIndex"
                                    ])
                              ])
                        ]
                      |),
                      [
                        M.call_closure (|
                          M.get_trait_method (|
                            "core::iter::traits::collect::IntoIterator",
                            Ty.apply
                              (Ty.path "alloc::collections::btree::map::BTreeMap")
                              []
                              [
                                Ty.path "move_binary_format::file_format::StructDefinitionIndex";
                                Ty.apply
                                  (Ty.path "alloc::collections::btree::set::BTreeSet")
                                  []
                                  [
                                    Ty.path
                                      "move_binary_format::file_format::StructDefinitionIndex";
                                    Ty.path "alloc::alloc::Global"
                                  ];
                                Ty.path "alloc::alloc::Global"
                              ],
                            [],
                            "into_iter",
                            []
                          |),
                          [ M.read (| neighbors |) ]
                        |);
                        M.closure
                          (fun γ =>
                            ltac:(M.monadic
                              match γ with
                              | [ α0 ] =>
                                ltac:(M.monadic
                                  (M.match_operator (|
                                    M.alloc (| α0 |),
                                    [
                                      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 parent := M.copy (| γ0_0 |) in
                                          let children := M.copy (| γ0_1 |) in
                                          M.call_closure (|
                                            M.get_trait_method (|
                                              "core::iter::traits::iterator::Iterator",
                                              Ty.apply
                                                (Ty.path "alloc::collections::btree::set::IntoIter")
                                                []
                                                [
                                                  Ty.path
                                                    "move_binary_format::file_format::StructDefinitionIndex";
                                                  Ty.path "alloc::alloc::Global"
                                                ],
                                              [],
                                              "map",
                                              [
                                                Ty.tuple
                                                  [
                                                    Ty.path
                                                      "move_binary_format::file_format::StructDefinitionIndex";
                                                    Ty.path
                                                      "move_binary_format::file_format::StructDefinitionIndex"
                                                  ];
                                                Ty.function
                                                  [
                                                    Ty.tuple
                                                      [
                                                        Ty.path
                                                          "move_binary_format::file_format::StructDefinitionIndex"
                                                      ]
                                                  ]
                                                  (Ty.tuple
                                                    [
                                                      Ty.path
                                                        "move_binary_format::file_format::StructDefinitionIndex";
                                                      Ty.path
                                                        "move_binary_format::file_format::StructDefinitionIndex"
                                                    ])
                                              ]
                                            |),
                                            [
                                              M.call_closure (|
                                                M.get_trait_method (|
                                                  "core::iter::traits::collect::IntoIterator",
                                                  Ty.apply
                                                    (Ty.path
                                                      "alloc::collections::btree::set::BTreeSet")
                                                    []
                                                    [
                                                      Ty.path
                                                        "move_binary_format::file_format::StructDefinitionIndex";
                                                      Ty.path "alloc::alloc::Global"
                                                    ],
                                                  [],
                                                  "into_iter",
                                                  []
                                                |),
                                                [ M.read (| children |) ]
                                              |);
                                              M.closure
                                                (fun γ =>
                                                  ltac:(M.monadic
                                                    match γ with
                                                    | [ α0 ] =>
                                                      ltac:(M.monadic
                                                        (M.match_operator (|
                                                          M.alloc (| α0 |),
                                                          [
                                                            fun γ =>
                                                              ltac:(M.monadic
                                                                (let child := M.copy (| γ |) in
                                                                Value.Tuple
                                                                  [
                                                                    M.read (| parent |);
                                                                    M.read (| child |)
                                                                  ]))
                                                          ]
                                                        |)))
                                                    | _ => M.impossible "wrong number of arguments"
                                                    end))
                                            ]
                                          |)))
                                    ]
                                  |)))
                              | _ => M.impossible "wrong number of arguments"
                              end))
                      ]
                    |)
                  |) in
                M.alloc (|
                  Value.StructTuple
                    "core::result::Result::Ok"
                    [
                      M.call_closure (|
                        M.get_associated_function (|
                          Ty.apply
                            (Ty.path "petgraph::graphmap::GraphMap")
                            []
                            [
                              Ty.path "move_binary_format::file_format::StructDefinitionIndex";
                              Ty.tuple [];
                              Ty.path "petgraph::Directed"
                            ],
                          "from_edges",
                          [
                            Ty.apply
                              (Ty.path "core::iter::adapters::flatten::FlatMap")
                              []
                              [
                                Ty.apply
                                  (Ty.path "alloc::collections::btree::map::IntoIter")
                                  []
                                  [
                                    Ty.path
                                      "move_binary_format::file_format::StructDefinitionIndex";
                                    Ty.apply
                                      (Ty.path "alloc::collections::btree::set::BTreeSet")
                                      []
                                      [
                                        Ty.path
                                          "move_binary_format::file_format::StructDefinitionIndex";
                                        Ty.path "alloc::alloc::Global"
                                      ];
                                    Ty.path "alloc::alloc::Global"
                                  ];
                                Ty.apply
                                  (Ty.path "core::iter::adapters::map::Map")
                                  []
                                  [
                                    Ty.apply
                                      (Ty.path "alloc::collections::btree::set::IntoIter")
                                      []
                                      [
                                        Ty.path
                                          "move_binary_format::file_format::StructDefinitionIndex";
                                        Ty.path "alloc::alloc::Global"
                                      ];
                                    Ty.function
                                      [
                                        Ty.tuple
                                          [
                                            Ty.path
                                              "move_binary_format::file_format::StructDefinitionIndex"
                                          ]
                                      ]
                                      (Ty.tuple
                                        [
                                          Ty.path
                                            "move_binary_format::file_format::StructDefinitionIndex";
                                          Ty.path
                                            "move_binary_format::file_format::StructDefinitionIndex"
                                        ])
                                  ];
                                Ty.function
                                  [
                                    Ty.tuple
                                      [
                                        Ty.tuple
                                          [
                                            Ty.path
                                              "move_binary_format::file_format::StructDefinitionIndex";
                                            Ty.apply
                                              (Ty.path "alloc::collections::btree::set::BTreeSet")
                                              []
                                              [
                                                Ty.path
                                                  "move_binary_format::file_format::StructDefinitionIndex";
                                                Ty.path "alloc::alloc::Global"
                                              ]
                                          ]
                                      ]
                                  ]
                                  (Ty.apply
                                    (Ty.path "core::iter::adapters::map::Map")
                                    []
                                    [
                                      Ty.apply
                                        (Ty.path "alloc::collections::btree::set::IntoIter")
                                        []
                                        [
                                          Ty.path
                                            "move_binary_format::file_format::StructDefinitionIndex";
                                          Ty.path "alloc::alloc::Global"
                                        ];
                                      Ty.function
                                        [
                                          Ty.tuple
                                            [
                                              Ty.path
                                                "move_binary_format::file_format::StructDefinitionIndex"
                                            ]
                                        ]
                                        (Ty.tuple
                                          [
                                            Ty.path
                                              "move_binary_format::file_format::StructDefinitionIndex";
                                            Ty.path
                                              "move_binary_format::file_format::StructDefinitionIndex"
                                          ])
                                    ])
                              ]
                          ]
                        |),
                        [ M.read (| edges |) ]
                      |)
                    ]
                |)
              |)))
          |)))
      | _, _, _ => M.impossible "wrong number of arguments"
      end.
    
    Axiom AssociatedFunction_build : M.IsAssociatedFunction Self "build" build.
    
    (*
        fn add_struct_defs(
            &self,
            neighbors: &mut BTreeMap<StructDefinitionIndex, BTreeSet<StructDefinitionIndex>>,
            idx: StructDefinitionIndex,
        ) -> PartialVMResult<()> {
            let struct_def = self.module.struct_def_at(idx);
            // The fields iterator is an option in the case of native structs. Flatten makes an empty
            // iterator for that case
            for field in struct_def.fields().into_iter().flatten() {
                self.add_signature_token(neighbors, idx, &field.signature.0)?
            }
            Ok(())
        }
    *)
    Definition add_struct_defs (ε : list Value.t) (τ : list Ty.t) (α : list Value.t) : M :=
      match ε, τ, α with
      | [], [], [ self; neighbors; idx ] =>
        ltac:(M.monadic
          (let self := M.alloc (| self |) in
          let neighbors := M.alloc (| neighbors |) in
          let idx := M.alloc (| idx |) in
          M.catch_return (|
            ltac:(M.monadic
              (M.read (|
                let~ struct_def :=
                  M.alloc (|
                    M.call_closure (|
                      M.get_associated_function (|
                        Ty.path "move_binary_format::file_format::CompiledModule",
                        "struct_def_at",
                        []
                      |),
                      [
                        M.read (|
                          M.SubPointer.get_struct_record_field (|
                            M.read (| self |),
                            "move_bytecode_verifier::struct_defs::StructDefGraphBuilder",
                            "module"
                          |)
                        |);
                        M.read (| idx |)
                      ]
                    |)
                  |) in
                let~ _ :=
                  M.use
                    (M.match_operator (|
                      M.alloc (|
                        M.call_closure (|
                          M.get_trait_method (|
                            "core::iter::traits::collect::IntoIterator",
                            Ty.apply
                              (Ty.path "core::iter::adapters::flatten::Flatten")
                              []
                              [
                                Ty.apply
                                  (Ty.path "core::option::IntoIter")
                                  []
                                  [
                                    Ty.apply
                                      (Ty.path "&")
                                      []
                                      [
                                        Ty.apply
                                          (Ty.path "slice")
                                          []
                                          [
                                            Ty.path
                                              "move_binary_format::file_format::FieldDefinition"
                                          ]
                                      ]
                                  ]
                              ],
                            [],
                            "into_iter",
                            []
                          |),
                          [
                            M.call_closure (|
                              M.get_trait_method (|
                                "core::iter::traits::iterator::Iterator",
                                Ty.apply
                                  (Ty.path "core::option::IntoIter")
                                  []
                                  [
                                    Ty.apply
                                      (Ty.path "&")
                                      []
                                      [
                                        Ty.apply
                                          (Ty.path "slice")
                                          []
                                          [
                                            Ty.path
                                              "move_binary_format::file_format::FieldDefinition"
                                          ]
                                      ]
                                  ],
                                [],
                                "flatten",
                                []
                              |),
                              [
                                M.call_closure (|
                                  M.get_trait_method (|
                                    "core::iter::traits::collect::IntoIterator",
                                    Ty.apply
                                      (Ty.path "core::option::Option")
                                      []
                                      [
                                        Ty.apply
                                          (Ty.path "&")
                                          []
                                          [
                                            Ty.apply
                                              (Ty.path "slice")
                                              []
                                              [
                                                Ty.path
                                                  "move_binary_format::file_format::FieldDefinition"
                                              ]
                                          ]
                                      ],
                                    [],
                                    "into_iter",
                                    []
                                  |),
                                  [
                                    M.call_closure (|
                                      M.get_associated_function (|
                                        Ty.path "move_binary_format::file_format::StructDefinition",
                                        "fields",
                                        []
                                      |),
                                      [ M.read (| struct_def |) ]
                                    |)
                                  ]
                                |)
                              ]
                            |)
                          ]
                        |)
                      |),
                      [
                        fun γ =>
                          ltac:(M.monadic
                            (let iter := M.copy (| γ |) in
                            M.loop (|
                              ltac:(M.monadic
                                (let~ _ :=
                                  M.match_operator (|
                                    M.alloc (|
                                      M.call_closure (|
                                        M.get_trait_method (|
                                          "core::iter::traits::iterator::Iterator",
                                          Ty.apply
                                            (Ty.path "core::iter::adapters::flatten::Flatten")
                                            []
                                            [
                                              Ty.apply
                                                (Ty.path "core::option::IntoIter")
                                                []
                                                [
                                                  Ty.apply
                                                    (Ty.path "&")
                                                    []
                                                    [
                                                      Ty.apply
                                                        (Ty.path "slice")
                                                        []
                                                        [
                                                          Ty.path
                                                            "move_binary_format::file_format::FieldDefinition"
                                                        ]
                                                    ]
                                                ]
                                            ],
                                          [],
                                          "next",
                                          []
                                        |),
                                        [ iter ]
                                      |)
                                    |),
                                    [
                                      fun γ =>
                                        ltac:(M.monadic
                                          (let _ :=
                                            M.is_struct_tuple (|
                                              γ,
                                              "core::option::Option::None"
                                            |) in
                                          M.alloc (|
                                            M.never_to_any (| M.read (| M.break (||) |) |)
                                          |)));
                                      fun γ =>
                                        ltac:(M.monadic
                                          (let γ0_0 :=
                                            M.SubPointer.get_struct_tuple_field (|
                                              γ,
                                              "core::option::Option::Some",
                                              0
                                            |) in
                                          let field := M.copy (| γ0_0 |) in
                                          M.match_operator (|
                                            M.alloc (|
                                              M.call_closure (|
                                                M.get_trait_method (|
                                                  "core::ops::try_trait::Try",
                                                  Ty.apply
                                                    (Ty.path "core::result::Result")
                                                    []
                                                    [
                                                      Ty.tuple [];
                                                      Ty.path
                                                        "move_binary_format::errors::PartialVMError"
                                                    ],
                                                  [],
                                                  "branch",
                                                  []
                                                |),
                                                [
                                                  M.call_closure (|
                                                    M.get_associated_function (|
                                                      Ty.path
                                                        "move_bytecode_verifier::struct_defs::StructDefGraphBuilder",
                                                      "add_signature_token",
                                                      []
                                                    |),
                                                    [
                                                      M.read (| self |);
                                                      M.read (| neighbors |);
                                                      M.read (| idx |);
                                                      M.SubPointer.get_struct_tuple_field (|
                                                        M.SubPointer.get_struct_record_field (|
                                                          M.read (| field |),
                                                          "move_binary_format::file_format::FieldDefinition",
                                                          "signature"
                                                        |),
                                                        "move_binary_format::file_format::TypeSignature",
                                                        0
                                                      |)
                                                    ]
                                                  |)
                                                ]
                                              |)
                                            |),
                                            [
                                              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::result::Result")
                                                                []
                                                                [
                                                                  Ty.tuple [];
                                                                  Ty.path
                                                                    "move_binary_format::errors::PartialVMError"
                                                                ],
                                                              [
                                                                Ty.apply
                                                                  (Ty.path "core::result::Result")
                                                                  []
                                                                  [
                                                                    Ty.path
                                                                      "core::convert::Infallible";
                                                                    Ty.path
                                                                      "move_binary_format::errors::PartialVMError"
                                                                  ]
                                                              ],
                                                              "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 (| Value.Tuple [] |)))
                            |)))
                      ]
                    |)) in
                M.alloc (| Value.StructTuple "core::result::Result::Ok" [ Value.Tuple [] ] |)
              |)))
          |)))
      | _, _, _ => M.impossible "wrong number of arguments"
      end.
    
    Axiom AssociatedFunction_add_struct_defs :
      M.IsAssociatedFunction Self "add_struct_defs" add_struct_defs.
    
    (*
        fn add_signature_token(
            &self,
            neighbors: &mut BTreeMap<StructDefinitionIndex, BTreeSet<StructDefinitionIndex>>,
            cur_idx: StructDefinitionIndex,
            token: &SignatureToken,
        ) -> PartialVMResult<()> {
            use SignatureToken as T;
            match token {
                T::Bool
                | T::U8
                | T::U16
                | T::U32
                | T::U64
                | T::U128
                | T::U256
                | T::Address
                | T::Signer
                | T::TypeParameter(_) => (),
                T::Reference(_) | T::MutableReference(_) => {
                    return Err(
                        PartialVMError::new(StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR)
                            .with_message("Reference field when checking recursive structs".to_owned()),
                    )
                }
                T::Vector(inner) => self.add_signature_token(neighbors, cur_idx, inner)?,
                T::Struct(sh_idx) => {
                    if let Some(struct_def_idx) = self.handle_to_def.get(sh_idx) {
                        neighbors
                            .entry(cur_idx)
                            .or_default()
                            .insert( *struct_def_idx);
                    }
                }
                T::StructInstantiation(struct_inst) => {
                    let (sh_idx, inners) = &**struct_inst;
                    if let Some(struct_def_idx) = self.handle_to_def.get(sh_idx) {
                        neighbors
                            .entry(cur_idx)
                            .or_default()
                            .insert( *struct_def_idx);
                    }
                    for t in inners {
                        self.add_signature_token(neighbors, cur_idx, t)?
                    }
                }
            };
            Ok(())
        }
    *)
    Definition add_signature_token (ε : list Value.t) (τ : list Ty.t) (α : list Value.t) : M :=
      match ε, τ, α with
      | [], [], [ self; neighbors; cur_idx; token ] =>
        ltac:(M.monadic
          (let self := M.alloc (| self |) in
          let neighbors := M.alloc (| neighbors |) in
          let cur_idx := M.alloc (| cur_idx |) in
          let token := M.alloc (| token |) in
          M.catch_return (|
            ltac:(M.monadic
              (M.read (|
                let~ _ :=
                  M.match_operator (|
                    token,
                    [
                      fun γ =>
                        ltac:(M.monadic
                          (M.find_or_pattern (|
                            γ,
                            [
                              fun γ =>
                                ltac:(M.monadic
                                  (let γ := M.read (| γ |) in
                                  let _ :=
                                    M.is_struct_tuple (|
                                      γ,
                                      "move_binary_format::file_format::SignatureToken::Bool"
                                    |) in
                                  Value.Tuple []));
                              fun γ =>
                                ltac:(M.monadic
                                  (let γ := M.read (| γ |) in
                                  let _ :=
                                    M.is_struct_tuple (|
                                      γ,
                                      "move_binary_format::file_format::SignatureToken::U8"
                                    |) in
                                  Value.Tuple []));
                              fun γ =>
                                ltac:(M.monadic
                                  (let γ := M.read (| γ |) in
                                  let _ :=
                                    M.is_struct_tuple (|
                                      γ,
                                      "move_binary_format::file_format::SignatureToken::U16"
                                    |) in
                                  Value.Tuple []));
                              fun γ =>
                                ltac:(M.monadic
                                  (let γ := M.read (| γ |) in
                                  let _ :=
                                    M.is_struct_tuple (|
                                      γ,
                                      "move_binary_format::file_format::SignatureToken::U32"
                                    |) in
                                  Value.Tuple []));
                              fun γ =>
                                ltac:(M.monadic
                                  (let γ := M.read (| γ |) in
                                  let _ :=
                                    M.is_struct_tuple (|
                                      γ,
                                      "move_binary_format::file_format::SignatureToken::U64"
                                    |) in
                                  Value.Tuple []));
                              fun γ =>
                                ltac:(M.monadic
                                  (let γ := M.read (| γ |) in
                                  let _ :=
                                    M.is_struct_tuple (|
                                      γ,
                                      "move_binary_format::file_format::SignatureToken::U128"
                                    |) in
                                  Value.Tuple []));
                              fun γ =>
                                ltac:(M.monadic
                                  (let γ := M.read (| γ |) in
                                  let _ :=
                                    M.is_struct_tuple (|
                                      γ,
                                      "move_binary_format::file_format::SignatureToken::U256"
                                    |) in
                                  Value.Tuple []));
                              fun γ =>
                                ltac:(M.monadic
                                  (let γ := M.read (| γ |) in
                                  let _ :=
                                    M.is_struct_tuple (|
                                      γ,
                                      "move_binary_format::file_format::SignatureToken::Address"
                                    |) in
                                  Value.Tuple []));
                              fun γ =>
                                ltac:(M.monadic
                                  (let γ := M.read (| γ |) in
                                  let _ :=
                                    M.is_struct_tuple (|
                                      γ,
                                      "move_binary_format::file_format::SignatureToken::Signer"
                                    |) in
                                  Value.Tuple []));
                              fun γ =>
                                ltac:(M.monadic
                                  (let γ := M.read (| γ |) in
                                  let γ1_0 :=
                                    M.SubPointer.get_struct_tuple_field (|
                                      γ,
                                      "move_binary_format::file_format::SignatureToken::TypeParameter",
                                      0
                                    |) in
                                  Value.Tuple []))
                            ],
                            M.closure
                              (fun γ =>
                                ltac:(M.monadic
                                  match γ with
                                  | [] => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                                  | _ => M.impossible "wrong number of arguments"
                                  end))
                          |)));
                      fun γ =>
                        ltac:(M.monadic
                          (M.find_or_pattern (|
                            γ,
                            [
                              fun γ =>
                                ltac:(M.monadic
                                  (let γ := M.read (| γ |) in
                                  let γ1_0 :=
                                    M.SubPointer.get_struct_tuple_field (|
                                      γ,
                                      "move_binary_format::file_format::SignatureToken::Reference",
                                      0
                                    |) in
                                  Value.Tuple []));
                              fun γ =>
                                ltac:(M.monadic
                                  (let γ := M.read (| γ |) in
                                  let γ1_0 :=
                                    M.SubPointer.get_struct_tuple_field (|
                                      γ,
                                      "move_binary_format::file_format::SignatureToken::MutableReference",
                                      0
                                    |) in
                                  Value.Tuple []))
                            ],
                            M.closure
                              (fun γ =>
                                ltac:(M.monadic
                                  match γ with
                                  | [] =>
                                    ltac:(M.monadic
                                      (M.alloc (|
                                        M.never_to_any (|
                                          M.read (|
                                            M.return_ (|
                                              Value.StructTuple
                                                "core::result::Result::Err"
                                                [
                                                  M.call_closure (|
                                                    M.get_associated_function (|
                                                      Ty.path
                                                        "move_binary_format::errors::PartialVMError",
                                                      "with_message",
                                                      []
                                                    |),
                                                    [
                                                      M.call_closure (|
                                                        M.get_associated_function (|
                                                          Ty.path
                                                            "move_binary_format::errors::PartialVMError",
                                                          "new",
                                                          []
                                                        |),
                                                        [
                                                          Value.StructTuple
                                                            "move_core_types::vm_status::StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR"
                                                            []
                                                        ]
                                                      |);
                                                      M.call_closure (|
                                                        M.get_trait_method (|
                                                          "alloc::borrow::ToOwned",
                                                          Ty.path "str",
                                                          [],
                                                          "to_owned",
                                                          []
                                                        |),
                                                        [
                                                          M.read (|
                                                            Value.String
                                                              "Reference field when checking recursive structs"
                                                          |)
                                                        ]
                                                      |)
                                                    ]
                                                  |)
                                                ]
                                            |)
                                          |)
                                        |)
                                      |)))
                                  | _ => M.impossible "wrong number of arguments"
                                  end))
                          |)));
                      fun γ =>
                        ltac:(M.monadic
                          (let γ := M.read (| γ |) in
                          let γ1_0 :=
                            M.SubPointer.get_struct_tuple_field (|
                              γ,
                              "move_binary_format::file_format::SignatureToken::Vector",
                              0
                            |) in
                          let inner := M.alloc (| γ1_0 |) in
                          M.match_operator (|
                            M.alloc (|
                              M.call_closure (|
                                M.get_trait_method (|
                                  "core::ops::try_trait::Try",
                                  Ty.apply
                                    (Ty.path "core::result::Result")
                                    []
                                    [
                                      Ty.tuple [];
                                      Ty.path "move_binary_format::errors::PartialVMError"
                                    ],
                                  [],
                                  "branch",
                                  []
                                |),
                                [
                                  M.call_closure (|
                                    M.get_associated_function (|
                                      Ty.path
                                        "move_bytecode_verifier::struct_defs::StructDefGraphBuilder",
                                      "add_signature_token",
                                      []
                                    |),
                                    [
                                      M.read (| self |);
                                      M.read (| neighbors |);
                                      M.read (| cur_idx |);
                                      M.read (| M.read (| inner |) |)
                                    ]
                                  |)
                                ]
                              |)
                            |),
                            [
                              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::result::Result")
                                                []
                                                [
                                                  Ty.tuple [];
                                                  Ty.path
                                                    "move_binary_format::errors::PartialVMError"
                                                ],
                                              [
                                                Ty.apply
                                                  (Ty.path "core::result::Result")
                                                  []
                                                  [
                                                    Ty.path "core::convert::Infallible";
                                                    Ty.path
                                                      "move_binary_format::errors::PartialVMError"
                                                  ]
                                              ],
                                              "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 γ := M.read (| γ |) in
                          let γ1_0 :=
                            M.SubPointer.get_struct_tuple_field (|
                              γ,
                              "move_binary_format::file_format::SignatureToken::Struct",
                              0
                            |) in
                          let sh_idx := M.alloc (| γ1_0 |) in
                          M.match_operator (|
                            M.alloc (| Value.Tuple [] |),
                            [
                              fun γ =>
                                ltac:(M.monadic
                                  (let γ :=
                                    M.alloc (|
                                      M.call_closure (|
                                        M.get_associated_function (|
                                          Ty.apply
                                            (Ty.path "alloc::collections::btree::map::BTreeMap")
                                            []
                                            [
                                              Ty.path
                                                "move_binary_format::file_format::StructHandleIndex";
                                              Ty.path
                                                "move_binary_format::file_format::StructDefinitionIndex";
                                              Ty.path "alloc::alloc::Global"
                                            ],
                                          "get",
                                          [
                                            Ty.path
                                              "move_binary_format::file_format::StructHandleIndex"
                                          ]
                                        |),
                                        [
                                          M.SubPointer.get_struct_record_field (|
                                            M.read (| self |),
                                            "move_bytecode_verifier::struct_defs::StructDefGraphBuilder",
                                            "handle_to_def"
                                          |);
                                          M.read (| sh_idx |)
                                        ]
                                      |)
                                    |) in
                                  let γ0_0 :=
                                    M.SubPointer.get_struct_tuple_field (|
                                      γ,
                                      "core::option::Option::Some",
                                      0
                                    |) in
                                  let struct_def_idx := M.copy (| γ0_0 |) in
                                  let~ _ :=
                                    M.alloc (|
                                      M.call_closure (|
                                        M.get_associated_function (|
                                          Ty.apply
                                            (Ty.path "alloc::collections::btree::set::BTreeSet")
                                            []
                                            [
                                              Ty.path
                                                "move_binary_format::file_format::StructDefinitionIndex";
                                              Ty.path "alloc::alloc::Global"
                                            ],
                                          "insert",
                                          []
                                        |),
                                        [
                                          M.call_closure (|
                                            M.get_associated_function (|
                                              Ty.apply
                                                (Ty.path
                                                  "alloc::collections::btree::map::entry::Entry")
                                                []
                                                [
                                                  Ty.path
                                                    "move_binary_format::file_format::StructDefinitionIndex";
                                                  Ty.apply
                                                    (Ty.path
                                                      "alloc::collections::btree::set::BTreeSet")
                                                    []
                                                    [
                                                      Ty.path
                                                        "move_binary_format::file_format::StructDefinitionIndex";
                                                      Ty.path "alloc::alloc::Global"
                                                    ];
                                                  Ty.path "alloc::alloc::Global"
                                                ],
                                              "or_default",
                                              []
                                            |),
                                            [
                                              M.call_closure (|
                                                M.get_associated_function (|
                                                  Ty.apply
                                                    (Ty.path
                                                      "alloc::collections::btree::map::BTreeMap")
                                                    []
                                                    [
                                                      Ty.path
                                                        "move_binary_format::file_format::StructDefinitionIndex";
                                                      Ty.apply
                                                        (Ty.path
                                                          "alloc::collections::btree::set::BTreeSet")
                                                        []
                                                        [
                                                          Ty.path
                                                            "move_binary_format::file_format::StructDefinitionIndex";
                                                          Ty.path "alloc::alloc::Global"
                                                        ];
                                                      Ty.path "alloc::alloc::Global"
                                                    ],
                                                  "entry",
                                                  []
                                                |),
                                                [ M.read (| neighbors |); M.read (| cur_idx |) ]
                                              |)
                                            ]
                                          |);
                                          M.read (| M.read (| struct_def_idx |) |)
                                        ]
                                      |)
                                    |) in
                                  M.alloc (| Value.Tuple [] |)));
                              fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                            ]
                          |)));
                      fun γ =>
                        ltac:(M.monadic
                          (let γ := M.read (| γ |) in
                          let γ1_0 :=
                            M.SubPointer.get_struct_tuple_field (|
                              γ,
                              "move_binary_format::file_format::SignatureToken::StructInstantiation",
                              0
                            |) in
                          let struct_inst := M.alloc (| γ1_0 |) in
                          M.match_operator (|
                            M.alloc (| M.read (| M.read (| struct_inst |) |) |),
                            [
                              fun γ =>
                                ltac:(M.monadic
                                  (let γ := M.read (| γ |) in
                                  let γ1_0 := M.SubPointer.get_tuple_field (| γ, 0 |) in
                                  let γ1_1 := M.SubPointer.get_tuple_field (| γ, 1 |) in
                                  let sh_idx := M.alloc (| γ1_0 |) in
                                  let inners := M.alloc (| γ1_1 |) in
                                  let~ _ :=
                                    M.match_operator (|
                                      M.alloc (| Value.Tuple [] |),
                                      [
                                        fun γ =>
                                          ltac:(M.monadic
                                            (let γ :=
                                              M.alloc (|
                                                M.call_closure (|
                                                  M.get_associated_function (|
                                                    Ty.apply
                                                      (Ty.path
                                                        "alloc::collections::btree::map::BTreeMap")
                                                      []
                                                      [
                                                        Ty.path
                                                          "move_binary_format::file_format::StructHandleIndex";
                                                        Ty.path
                                                          "move_binary_format::file_format::StructDefinitionIndex";
                                                        Ty.path "alloc::alloc::Global"
                                                      ],
                                                    "get",
                                                    [
                                                      Ty.path
                                                        "move_binary_format::file_format::StructHandleIndex"
                                                    ]
                                                  |),
                                                  [
                                                    M.SubPointer.get_struct_record_field (|
                                                      M.read (| self |),
                                                      "move_bytecode_verifier::struct_defs::StructDefGraphBuilder",
                                                      "handle_to_def"
                                                    |);
                                                    M.read (| sh_idx |)
                                                  ]
                                                |)
                                              |) in
                                            let γ0_0 :=
                                              M.SubPointer.get_struct_tuple_field (|
                                                γ,
                                                "core::option::Option::Some",
                                                0
                                              |) in
                                            let struct_def_idx := M.copy (| γ0_0 |) in
                                            let~ _ :=
                                              M.alloc (|
                                                M.call_closure (|
                                                  M.get_associated_function (|
                                                    Ty.apply
                                                      (Ty.path
                                                        "alloc::collections::btree::set::BTreeSet")
                                                      []
                                                      [
                                                        Ty.path
                                                          "move_binary_format::file_format::StructDefinitionIndex";
                                                        Ty.path "alloc::alloc::Global"
                                                      ],
                                                    "insert",
                                                    []
                                                  |),
                                                  [
                                                    M.call_closure (|
                                                      M.get_associated_function (|
                                                        Ty.apply
                                                          (Ty.path
                                                            "alloc::collections::btree::map::entry::Entry")
                                                          []
                                                          [
                                                            Ty.path
                                                              "move_binary_format::file_format::StructDefinitionIndex";
                                                            Ty.apply
                                                              (Ty.path
                                                                "alloc::collections::btree::set::BTreeSet")
                                                              []
                                                              [
                                                                Ty.path
                                                                  "move_binary_format::file_format::StructDefinitionIndex";
                                                                Ty.path "alloc::alloc::Global"
                                                              ];
                                                            Ty.path "alloc::alloc::Global"
                                                          ],
                                                        "or_default",
                                                        []
                                                      |),
                                                      [
                                                        M.call_closure (|
                                                          M.get_associated_function (|
                                                            Ty.apply
                                                              (Ty.path
                                                                "alloc::collections::btree::map::BTreeMap")
                                                              []
                                                              [
                                                                Ty.path
                                                                  "move_binary_format::file_format::StructDefinitionIndex";
                                                                Ty.apply
                                                                  (Ty.path
                                                                    "alloc::collections::btree::set::BTreeSet")
                                                                  []
                                                                  [
                                                                    Ty.path
                                                                      "move_binary_format::file_format::StructDefinitionIndex";
                                                                    Ty.path "alloc::alloc::Global"
                                                                  ];
                                                                Ty.path "alloc::alloc::Global"
                                                              ],
                                                            "entry",
                                                            []
                                                          |),
                                                          [
                                                            M.read (| neighbors |);
                                                            M.read (| cur_idx |)
                                                          ]
                                                        |)
                                                      ]
                                                    |);
                                                    M.read (| M.read (| struct_def_idx |) |)
                                                  ]
                                                |)
                                              |) in
                                            M.alloc (| Value.Tuple [] |)));
                                        fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                                      ]
                                    |) in
                                  M.use
                                    (M.match_operator (|
                                      M.alloc (|
                                        M.call_closure (|
                                          M.get_trait_method (|
                                            "core::iter::traits::collect::IntoIterator",
                                            Ty.apply
                                              (Ty.path "&")
                                              []
                                              [
                                                Ty.apply
                                                  (Ty.path "alloc::vec::Vec")
                                                  []
                                                  [
                                                    Ty.path
                                                      "move_binary_format::file_format::SignatureToken";
                                                    Ty.path "alloc::alloc::Global"
                                                  ]
                                              ],
                                            [],
                                            "into_iter",
                                            []
                                          |),
                                          [ M.read (| inners |) ]
                                        |)
                                      |),
                                      [
                                        fun γ =>
                                          ltac:(M.monadic
                                            (let iter := M.copy (| γ |) in
                                            M.loop (|
                                              ltac:(M.monadic
                                                (let~ _ :=
                                                  M.match_operator (|
                                                    M.alloc (|
                                                      M.call_closure (|
                                                        M.get_trait_method (|
                                                          "core::iter::traits::iterator::Iterator",
                                                          Ty.apply
                                                            (Ty.path "core::slice::iter::Iter")
                                                            []
                                                            [
                                                              Ty.path
                                                                "move_binary_format::file_format::SignatureToken"
                                                            ],
                                                          [],
                                                          "next",
                                                          []
                                                        |),
                                                        [ iter ]
                                                      |)
                                                    |),
                                                    [
                                                      fun γ =>
                                                        ltac:(M.monadic
                                                          (let _ :=
                                                            M.is_struct_tuple (|
                                                              γ,
                                                              "core::option::Option::None"
                                                            |) in
                                                          M.alloc (|
                                                            M.never_to_any (|
                                                              M.read (| M.break (||) |)
                                                            |)
                                                          |)));
                                                      fun γ =>
                                                        ltac:(M.monadic
                                                          (let γ0_0 :=
                                                            M.SubPointer.get_struct_tuple_field (|
                                                              γ,
                                                              "core::option::Option::Some",
                                                              0
                                                            |) in
                                                          let t := M.copy (| γ0_0 |) in
                                                          M.match_operator (|
                                                            M.alloc (|
                                                              M.call_closure (|
                                                                M.get_trait_method (|
                                                                  "core::ops::try_trait::Try",
                                                                  Ty.apply
                                                                    (Ty.path "core::result::Result")
                                                                    []
                                                                    [
                                                                      Ty.tuple [];
                                                                      Ty.path
                                                                        "move_binary_format::errors::PartialVMError"
                                                                    ],
                                                                  [],
                                                                  "branch",
                                                                  []
                                                                |),
                                                                [
                                                                  M.call_closure (|
                                                                    M.get_associated_function (|
                                                                      Ty.path
                                                                        "move_bytecode_verifier::struct_defs::StructDefGraphBuilder",
                                                                      "add_signature_token",
                                                                      []
                                                                    |),
                                                                    [
                                                                      M.read (| self |);
                                                                      M.read (| neighbors |);
                                                                      M.read (| cur_idx |);
                                                                      M.read (| t |)
                                                                    ]
                                                                  |)
                                                                ]
                                                              |)
                                                            |),
                                                            [
                                                              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::result::Result")
                                                                                []
                                                                                [
                                                                                  Ty.tuple [];
                                                                                  Ty.path
                                                                                    "move_binary_format::errors::PartialVMError"
                                                                                ],
                                                                              [
                                                                                Ty.apply
                                                                                  (Ty.path
                                                                                    "core::result::Result")
                                                                                  []
                                                                                  [
                                                                                    Ty.path
                                                                                      "core::convert::Infallible";
                                                                                    Ty.path
                                                                                      "move_binary_format::errors::PartialVMError"
                                                                                  ]
                                                                              ],
                                                                              "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 (| Value.Tuple [] |)))
                                            |)))
                                      ]
                                    |))))
                            ]
                          |)))
                    ]
                  |) in
                M.alloc (| Value.StructTuple "core::result::Result::Ok" [ Value.Tuple [] ] |)
              |)))
          |)))
      | _, _, _ => M.impossible "wrong number of arguments"
      end.
    
    Axiom AssociatedFunction_add_signature_token :
      M.IsAssociatedFunction Self "add_signature_token" add_signature_token.
  End Impl_move_bytecode_verifier_struct_defs_StructDefGraphBuilder.
End struct_defs.
