(** WARNING: this file is partially auto-generated. Do not edit `OfJson.ml` by
    hand. Edit `templates/OfJson.ml` instead, or improve the code generation
    tool so avoid the need for hand-writing things.

    `templates/OfJson.ml` contains the manual definitions and some `(*
    __REPLACEn__ *)` comments. These comments are replaced by auto-generated
    definitions by running `make generate-ml` in the crate root. The
    code-generation code is in `charon/src/bin/generate-ml`. *)

open Yojson.Basic
open OfJsonBasic
open Identifiers
open Generated_Meta
open Generated_Values
open Generated_Types
open Generated_Expressions
open Generated_GAst
open Generated_FullAst
open Scalars
module FileId = IdGen ()
module HashConsId = IdGen ()

(** The default logger *)
let log = Logging.llbc_of_json_logger

module FileTbl = Hashtbl.Make (struct
  type t = FileId.id

  let equal = FileId.equal_id
  let hash = Hashtbl.hash
end)

type of_json_ctx = {
  id_to_file_map : file FileTbl.t;
  ty_hashcons_map : ty HashConsId.Map.t ref;
  tref_hashcons_map : trait_ref HashConsId.Map.t ref;
}

let empty_of_json_ctx : of_json_ctx =
  {
    id_to_file_map = FileTbl.create 8;
    ty_hashcons_map = ref HashConsId.Map.empty;
    tref_hashcons_map = ref HashConsId.Map.empty;
  }

let hash_consed_val_of_json (map : 'a HashConsId.Map.t ref)
    (of_json : of_json_ctx -> json -> ('a, string) result) (ctx : of_json_ctx)
    (js : json) : ('a, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("Untagged", json) ] -> of_json ctx json
    | `Assoc [ ("HashConsedValue", `List [ `Int id; json ]) ] ->
        let* v = of_json ctx json in
        let id = HashConsId.of_int id in
        map := HashConsId.Map.add id v !map;
        Ok v
    | `Assoc [ ("Deduplicated", `Int id) ] -> begin
        let id = HashConsId.of_int id in
        match HashConsId.Map.find_opt id !map with
        | Some v -> Ok v
        | None ->
            Error
              "Hash-consing key not found; there is a serialization mismatch \
               between Rust and OCaml"
      end
    | _ -> Error "")

let path_buf_of_json = string_of_json

let big_int_of_json _ (js : json) : (big_int, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Int i -> Ok (Z.of_int i)
    | `String is -> Ok (Z.of_string is)
    | _ -> Error "")

let opt_indexed_map_of_json :
    'a0 'a1.
    (of_json_ctx -> json -> ('a0, string) result) ->
    (of_json_ctx -> json -> ('a1, string) result) ->
    of_json_ctx ->
    json ->
    ('a1 option list, string) result =
 fun arg0_of_json arg1_of_json ctx js ->
  list_of_json (option_of_json arg1_of_json) ctx js

let rec ___ = ()

and abi_of_json (ctx : of_json_ctx) (js : json) : (abi, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `String "Rust" -> Ok AbiRust
    | `String "C" -> Ok AbiC
    | `Assoc [ ("Other", other) ] ->
        let* other = string_of_json ctx other in
        Ok (AbiOther other)
    | _ -> Error "")

and abort_kind_of_json (ctx : of_json_ctx) (js : json) :
    (abort_kind, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("Panic", panic) ] ->
        let* panic = option_of_json name_of_json ctx panic in
        Ok (Panic panic)
    | `String "UndefinedBehavior" -> Ok UndefinedBehavior
    | `String "UnwindTerminate" -> Ok UnwindTerminate
    | _ -> Error "")

and aggregate_kind_of_json (ctx : of_json_ctx) (js : json) :
    (aggregate_kind, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("Adt", `List [ x_0; x_1; x_2 ]) ] ->
        let* x_0 = type_decl_ref_of_json ctx x_0 in
        let* x_1 = option_of_json variant_id_of_json ctx x_1 in
        let* x_2 = option_of_json field_id_of_json ctx x_2 in
        Ok (AggregatedAdt (x_0, x_1, x_2))
    | `Assoc [ ("Array", `List [ x_0; x_1 ]) ] ->
        let* x_0 = ty_of_json ctx x_0 in
        let* x_1 = box_of_json constant_expr_of_json ctx x_1 in
        Ok (AggregatedArray (x_0, x_1))
    | `Assoc [ ("RawPtr", `List [ x_0; x_1 ]) ] ->
        let* x_0 = ty_of_json ctx x_0 in
        let* x_1 = ref_kind_of_json ctx x_1 in
        Ok (AggregatedRawPtr (x_0, x_1))
    | _ -> Error "")

and assertion_of_json (ctx : of_json_ctx) (js : json) :
    (assertion, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc
        [ ("cond", cond); ("expected", expected); ("check_kind", check_kind) ]
      ->
        let* cond = operand_of_json ctx cond in
        let* expected = bool_of_json ctx expected in
        let* check_kind =
          option_of_json builtin_assert_kind_of_json ctx check_kind
        in
        Ok ({ cond; expected; check_kind } : assertion)
    | _ -> Error "")

and assoc_const_id_of_json (ctx : of_json_ctx) (js : json) :
    (assoc_const_id, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | x -> AssocConstId.id_of_json ctx x
    | _ -> Error "")

and assoc_type_id_of_json (ctx : of_json_ctx) (js : json) :
    (assoc_type_id, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | x -> AssocTypeId.id_of_json ctx x
    | _ -> Error "")

and binop_of_json (ctx : of_json_ctx) (js : json) : (binop, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `String "BitXor" -> Ok BitXor
    | `String "BitAnd" -> Ok BitAnd
    | `String "BitOr" -> Ok BitOr
    | `String "Eq" -> Ok Eq
    | `String "Lt" -> Ok Lt
    | `String "Le" -> Ok Le
    | `String "Ne" -> Ok Ne
    | `String "Ge" -> Ok Ge
    | `String "Gt" -> Ok Gt
    | `Assoc [ ("Add", add) ] ->
        let* add = overflow_mode_of_json ctx add in
        Ok (Add add)
    | `Assoc [ ("Sub", sub) ] ->
        let* sub = overflow_mode_of_json ctx sub in
        Ok (Sub sub)
    | `Assoc [ ("Mul", mul) ] ->
        let* mul = overflow_mode_of_json ctx mul in
        Ok (Mul mul)
    | `Assoc [ ("Div", div) ] ->
        let* div = overflow_mode_of_json ctx div in
        Ok (Div div)
    | `Assoc [ ("Rem", rem) ] ->
        let* rem = overflow_mode_of_json ctx rem in
        Ok (Rem rem)
    | `String "AddChecked" -> Ok AddChecked
    | `String "SubChecked" -> Ok SubChecked
    | `String "MulChecked" -> Ok MulChecked
    | `Assoc [ ("Shl", shl) ] ->
        let* shl = overflow_mode_of_json ctx shl in
        Ok (Shl shl)
    | `Assoc [ ("Shr", shr) ] ->
        let* shr = overflow_mode_of_json ctx shr in
        Ok (Shr shr)
    | `String "Offset" -> Ok Offset
    | `String "Cmp" -> Ok Cmp
    | _ -> Error "")

and binder_of_json :
    'a0.
    (of_json_ctx -> json -> ('a0, string) result) ->
    of_json_ctx ->
    json ->
    ('a0 binder, string) result =
 fun arg0_of_json ctx js ->
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("params", params); ("skip_binder", skip_binder); ("kind", _) ]
      ->
        let* binder_params = generic_params_of_json ctx params in
        let* binder_value = arg0_of_json ctx skip_binder in
        Ok ({ binder_params; binder_value } : _ binder)
    | _ -> Error "")

and binder_kind_of_json (ctx : of_json_ctx) (js : json) :
    (binder_kind, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("TraitType", `List [ x_0; x_1 ]) ] ->
        let* x_0 = trait_decl_id_of_json ctx x_0 in
        let* x_1 = assoc_type_id_of_json ctx x_1 in
        Ok (BKTraitType (x_0, x_1))
    | `Assoc [ ("TraitMethod", `List [ x_0; x_1 ]) ] ->
        let* x_0 = trait_decl_id_of_json ctx x_0 in
        let* x_1 = trait_method_id_of_json ctx x_1 in
        Ok (BKTraitMethod (x_0, x_1))
    | `String "InherentImplBlock" -> Ok BKInherentImplBlock
    | `String "Dyn" -> Ok BKDyn
    | `String "Other" -> Ok BKOther
    | _ -> Error "")

and borrow_kind_of_json (ctx : of_json_ctx) (js : json) :
    (borrow_kind, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `String "Shared" -> Ok BShared
    | `String "Mut" -> Ok BMut
    | `String "TwoPhaseMut" -> Ok BTwoPhaseMut
    | `String "Shallow" -> Ok BShallow
    | `String "UniqueImmutable" -> Ok BUniqueImmutable
    | _ -> Error "")

and builtin_assert_kind_of_json (ctx : of_json_ctx) (js : json) :
    (builtin_assert_kind, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("BoundsCheck", `Assoc [ ("len", len); ("index", index) ]) ] ->
        let* len = operand_of_json ctx len in
        let* index = operand_of_json ctx index in
        Ok (BoundsCheck (len, index))
    | `Assoc [ ("Overflow", `List [ x_0; x_1; x_2 ]) ] ->
        let* x_0 = binop_of_json ctx x_0 in
        let* x_1 = operand_of_json ctx x_1 in
        let* x_2 = operand_of_json ctx x_2 in
        Ok (Overflow (x_0, x_1, x_2))
    | `Assoc [ ("OverflowNeg", overflow_neg) ] ->
        let* overflow_neg = operand_of_json ctx overflow_neg in
        Ok (OverflowNeg overflow_neg)
    | `Assoc [ ("DivisionByZero", division_by_zero) ] ->
        let* division_by_zero = operand_of_json ctx division_by_zero in
        Ok (DivisionByZero division_by_zero)
    | `Assoc [ ("RemainderByZero", remainder_by_zero) ] ->
        let* remainder_by_zero = operand_of_json ctx remainder_by_zero in
        Ok (RemainderByZero remainder_by_zero)
    | `Assoc
        [
          ( "MisalignedPointerDereference",
            `Assoc [ ("required", required); ("found", found) ] );
        ] ->
        let* required = operand_of_json ctx required in
        let* found = operand_of_json ctx found in
        Ok (MisalignedPointerDereference (required, found))
    | `String "NullPointerDereference" -> Ok NullPointerDereference
    | `Assoc [ ("InvalidEnumConstruction", invalid_enum_construction) ] ->
        let* invalid_enum_construction =
          operand_of_json ctx invalid_enum_construction
        in
        Ok (InvalidEnumConstruction invalid_enum_construction)
    | `String "ResumedAfterReturn" -> Ok ResumedAfterReturn
    | `String "ResumedAfterPanic" -> Ok ResumedAfterPanic
    | `String "ResumedAfterDrop" -> Ok ResumedAfterDrop
    | _ -> Error "")

and builtin_fun_id_of_json (ctx : of_json_ctx) (js : json) :
    (builtin_fun_id, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `String "BoxNew" -> Ok BoxNew
    | `String "ArrayToSliceShared" -> Ok ArrayToSliceShared
    | `String "ArrayToSliceMut" -> Ok ArrayToSliceMut
    | `String "ArrayRepeat" -> Ok ArrayRepeat
    | `Assoc [ ("Index", index) ] ->
        let* index = builtin_index_op_of_json ctx index in
        Ok (Index index)
    | `Assoc [ ("PtrFromParts", ptr_from_parts) ] ->
        let* ptr_from_parts = ref_kind_of_json ctx ptr_from_parts in
        Ok (PtrFromParts ptr_from_parts)
    | _ -> Error "")

and builtin_impl_data_of_json (ctx : of_json_ctx) (js : json) :
    (builtin_impl_data, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `String "Auto" -> Ok BuiltinAuto
    | `String "Sized" -> Ok BuiltinSized
    | `String "MetaSized" -> Ok BuiltinMetaSized
    | `String "PointeeSized" -> Ok BuiltinPointeeSized
    | `String "Copy" -> Ok BuiltinCopy
    | `String "Clone" -> Ok BuiltinClone
    | `String "Tuple" -> Ok BuiltinTuple
    | `String "Transmute" -> Ok BuiltinTransmute
    | `String "Unsize" -> Ok BuiltinUnsize
    | `String "Pointee" -> Ok BuiltinPointee
    | `String "DiscriminantKind" -> Ok BuiltinDiscriminantKind
    | `String "Fn" -> Ok BuiltinFn
    | `String "FnMut" -> Ok BuiltinFnMut
    | `String "FnOnce" -> Ok BuiltinFnOnce
    | `String "FnPtr" -> Ok BuiltinFnPtr
    | `String "AsyncFn" -> Ok BuiltinAsyncFn
    | `String "AsyncFnMut" -> Ok BuiltinAsyncFnMut
    | `String "AsyncFnOnce" -> Ok BuiltinAsyncFnOnce
    | `String "Coroutine" -> Ok BuiltinCoroutine
    | `String "Future" -> Ok BuiltinFuture
    | `String "NoopDestruct" -> Ok BuiltinNoopDestruct
    | `String "UntrackedDestruct" -> Ok BuiltinUntrackedDestruct
    | `String "RemovedAdtClause" -> Ok BuiltinRemovedAdtClause
    | _ -> Error "")

and builtin_index_op_of_json (ctx : of_json_ctx) (js : json) :
    (builtin_index_op, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc
        [
          ("is_array", is_array);
          ("mutability", mutability);
          ("is_range", is_range);
        ] ->
        let* is_array = bool_of_json ctx is_array in
        let* mutability = ref_kind_of_json ctx mutability in
        let* is_range = bool_of_json ctx is_range in
        Ok ({ is_array; mutability; is_range } : builtin_index_op)
    | _ -> Error "")

and builtin_ty_of_json (ctx : of_json_ctx) (js : json) :
    (builtin_ty, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `String "Box" -> Ok TBox
    | `String "Str" -> Ok TStr
    | _ -> Error "")

and byte_of_json (ctx : of_json_ctx) (js : json) : (byte, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `String "Uninit" -> Ok Uninit
    | `Assoc [ ("Value", value) ] ->
        let* value = int_of_json ctx value in
        Ok (Value value)
    | `Assoc [ ("Provenance", `List [ x_0; x_1 ]) ] ->
        let* x_0 = provenance_of_json ctx x_0 in
        let* x_1 = int_of_json ctx x_1 in
        Ok (Provenance (x_0, x_1))
    | _ -> Error "")

and call_of_json (ctx : of_json_ctx) (js : json) : (call, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("func", func); ("args", args); ("dest", dest) ] ->
        let* func = fn_operand_of_json ctx func in
        let* args = list_of_json operand_of_json ctx args in
        let* dest = place_of_json ctx dest in
        Ok ({ func; args; dest } : call)
    | _ -> Error "")

and cast_kind_of_json (ctx : of_json_ctx) (js : json) :
    (cast_kind, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("Scalar", `List [ x_0; x_1 ]) ] ->
        let* x_0 = literal_type_of_json ctx x_0 in
        let* x_1 = literal_type_of_json ctx x_1 in
        Ok (CastScalar (x_0, x_1))
    | `Assoc [ ("RawPtr", `List [ x_0; x_1 ]) ] ->
        let* x_0 = ty_of_json ctx x_0 in
        let* x_1 = ty_of_json ctx x_1 in
        Ok (CastRawPtr (x_0, x_1))
    | `Assoc [ ("FnPtr", `List [ x_0; x_1 ]) ] ->
        let* x_0 = ty_of_json ctx x_0 in
        let* x_1 = ty_of_json ctx x_1 in
        Ok (CastFnPtr (x_0, x_1))
    | `Assoc [ ("Unsize", `List [ x_0; x_1; x_2 ]) ] ->
        let* x_0 = ty_of_json ctx x_0 in
        let* x_1 = ty_of_json ctx x_1 in
        let* x_2 = unsizing_metadata_of_json ctx x_2 in
        Ok (CastUnsize (x_0, x_1, x_2))
    | `Assoc [ ("Transmute", `List [ x_0; x_1 ]) ] ->
        let* x_0 = ty_of_json ctx x_0 in
        let* x_1 = ty_of_json ctx x_1 in
        Ok (CastTransmute (x_0, x_1))
    | `Assoc [ ("Concretize", `List [ x_0; x_1 ]) ] ->
        let* x_0 = ty_of_json ctx x_0 in
        let* x_1 = ty_of_json ctx x_1 in
        Ok (CastConcretize (x_0, x_1))
    | _ -> Error "")

and const_generic_param_of_json (ctx : of_json_ctx) (js : json) :
    (const_generic_param, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("index", index); ("name", name); ("ty", ty) ] ->
        let* index = const_generic_var_id_of_json ctx index in
        let* name = string_of_json ctx name in
        let* ty = ty_of_json ctx ty in
        Ok ({ index; name; ty } : const_generic_param)
    | _ -> Error "")

and const_generic_var_id_of_json (ctx : of_json_ctx) (js : json) :
    (const_generic_var_id, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | x -> ConstGenericVarId.id_of_json ctx x
    | _ -> Error "")

and constant_expr_of_json (ctx : of_json_ctx) (js : json) :
    (constant_expr, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("kind", kind); ("ty", ty) ] ->
        let* kind = constant_expr_kind_of_json ctx kind in
        let* ty = ty_of_json ctx ty in
        Ok ({ kind; ty } : constant_expr)
    | _ -> Error "")

and constant_expr_kind_of_json (ctx : of_json_ctx) (js : json) :
    (constant_expr_kind, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("Literal", literal) ] ->
        let* literal = literal_of_json ctx literal in
        Ok (CLiteral literal)
    | `Assoc [ ("Adt", `List [ x_0; x_1 ]) ] ->
        let* x_0 = option_of_json variant_id_of_json ctx x_0 in
        let* x_1 = list_of_json constant_expr_of_json ctx x_1 in
        Ok (CAdt (x_0, x_1))
    | `Assoc [ ("Array", array) ] ->
        let* array = list_of_json constant_expr_of_json ctx array in
        Ok (CArray array)
    | `Assoc [ ("Global", global) ] ->
        let* global = global_decl_ref_of_json ctx global in
        Ok (CGlobal global)
    | `Assoc [ ("TraitConst", `List [ x_0; x_1 ]) ] ->
        let* x_0 = trait_ref_of_json ctx x_0 in
        let* x_1 = assoc_const_id_of_json ctx x_1 in
        Ok (CTraitConst (x_0, x_1))
    | `Assoc [ ("VTableRef", v_table_ref) ] ->
        let* v_table_ref = trait_ref_of_json ctx v_table_ref in
        Ok (CVTableRef v_table_ref)
    | `Assoc [ ("Ref", `List [ x_0; x_1 ]) ] ->
        let* x_0 = box_of_json constant_expr_of_json ctx x_0 in
        let* x_1 = option_of_json unsizing_metadata_of_json ctx x_1 in
        Ok (CRef (x_0, x_1))
    | `Assoc [ ("Ptr", `List [ x_0; x_1; x_2 ]) ] ->
        let* x_0 = ref_kind_of_json ctx x_0 in
        let* x_1 = box_of_json constant_expr_of_json ctx x_1 in
        let* x_2 = option_of_json unsizing_metadata_of_json ctx x_2 in
        Ok (CPtr (x_0, x_1, x_2))
    | `Assoc [ ("Var", var) ] ->
        let* var = de_bruijn_var_of_json const_generic_var_id_of_json ctx var in
        Ok (CVar var)
    | `Assoc [ ("Call", `List [ x_0; x_1 ]) ] ->
        let* x_0 = fn_ptr_of_json ctx x_0 in
        let* x_1 = list_of_json constant_expr_of_json ctx x_1 in
        Ok (CCall (x_0, x_1))
    | `Assoc [ ("FnDef", fn_def) ] ->
        let* fn_def = fn_ptr_of_json ctx fn_def in
        Ok (CFnDef fn_def)
    | `Assoc [ ("FnPtr", fn_ptr) ] ->
        let* fn_ptr = fn_ptr_of_json ctx fn_ptr in
        Ok (CFnPtr fn_ptr)
    | `Assoc [ ("TypeId", type_id) ] ->
        let* type_id = ty_of_json ctx type_id in
        Ok (CTypeId type_id)
    | `Assoc [ ("PtrNoProvenance", ptr_no_provenance) ] ->
        let* ptr_no_provenance = big_int_of_json ctx ptr_no_provenance in
        Ok (CPtrNoProvenance ptr_no_provenance)
    | `Assoc [ ("RawMemory", raw_memory) ] ->
        let* raw_memory = list_of_json byte_of_json ctx raw_memory in
        Ok (CRawMemory raw_memory)
    | `Assoc [ ("Opaque", opaque) ] ->
        let* opaque = string_of_json ctx opaque in
        Ok (COpaque opaque)
    | _ -> Error "")

and copy_non_overlapping_of_json (ctx : of_json_ctx) (js : json) :
    (copy_non_overlapping, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("src", src); ("dst", dst); ("count", count) ] ->
        let* src = operand_of_json ctx src in
        let* dst = operand_of_json ctx dst in
        let* count = operand_of_json ctx count in
        Ok ({ src; dst; count } : copy_non_overlapping)
    | _ -> Error "")

and de_bruijn_id_of_json (ctx : of_json_ctx) (js : json) :
    (de_bruijn_id, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | x -> int_of_json ctx x
    | _ -> Error "")

and de_bruijn_var_of_json :
    'a0.
    (of_json_ctx -> json -> ('a0, string) result) ->
    of_json_ctx ->
    json ->
    ('a0 de_bruijn_var, string) result =
 fun arg0_of_json ctx js ->
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("Bound", `List [ x_0; x_1 ]) ] ->
        let* x_0 = de_bruijn_id_of_json ctx x_0 in
        let* x_1 = arg0_of_json ctx x_1 in
        Ok (Bound (x_0, x_1))
    | `Assoc [ ("Free", free) ] ->
        let* free = arg0_of_json ctx free in
        Ok (Free free)
    | _ -> Error "")

and disambiguator_of_json (ctx : of_json_ctx) (js : json) :
    (disambiguator, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | x -> Disambiguator.id_of_json ctx x
    | _ -> Error "")

and drop_kind_of_json (ctx : of_json_ctx) (js : json) :
    (drop_kind, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `String "Precise" -> Ok Precise
    | `String "Conditional" -> Ok Conditional
    | _ -> Error "")

and dyn_predicate_of_json (ctx : of_json_ctx) (js : json) :
    (dyn_predicate, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("binder", binder) ] ->
        let* binder = binder_of_json ty_of_json ctx binder in
        Ok ({ binder } : dyn_predicate)
    | _ -> Error "")

and field_id_of_json (ctx : of_json_ctx) (js : json) : (field_id, string) result
    =
  combine_error_msgs js __FUNCTION__
    (match js with
    | x -> FieldId.id_of_json ctx x
    | _ -> Error "")

and field_proj_kind_of_json (ctx : of_json_ctx) (js : json) :
    (field_proj_kind, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("Adt", `List [ x_0; x_1 ]) ] ->
        let* x_0 = type_decl_id_of_json ctx x_0 in
        let* x_1 = option_of_json variant_id_of_json ctx x_1 in
        Ok (ProjAdt (x_0, x_1))
    | `Assoc [ ("Tuple", tuple) ] ->
        let* tuple = int_of_json ctx tuple in
        Ok (ProjTuple tuple)
    | _ -> Error "")

and file_id_of_json (ctx : of_json_ctx) (js : json) : (file_id, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | json ->
        let* file_id = FileId.id_of_json ctx json in
        let file = FileTbl.find ctx.id_to_file_map file_id in
        Ok file
    | _ -> Error "")

and float_type_of_json (ctx : of_json_ctx) (js : json) :
    (float_type, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `String "F16" -> Ok F16
    | `String "F32" -> Ok F32
    | `String "F64" -> Ok F64
    | `String "F128" -> Ok F128
    | _ -> Error "")

and float_value_of_json (ctx : of_json_ctx) (js : json) :
    (float_value, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("value", value); ("ty", ty) ] ->
        let* float_value = string_of_json ctx value in
        let* float_ty = float_type_of_json ctx ty in
        Ok ({ float_value; float_ty } : float_value)
    | _ -> Error "")

and fn_operand_of_json (ctx : of_json_ctx) (js : json) :
    (fn_operand, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("Regular", regular) ] ->
        let* regular = fn_ptr_of_json ctx regular in
        Ok (FnOpRegular regular)
    | `Assoc [ ("Dynamic", dynamic) ] ->
        let* dynamic = operand_of_json ctx dynamic in
        Ok (FnOpDynamic dynamic)
    | _ -> Error "")

and fn_ptr_of_json (ctx : of_json_ctx) (js : json) : (fn_ptr, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("kind", kind); ("generics", generics) ] ->
        let* kind = box_of_json fn_ptr_kind_of_json ctx kind in
        let* generics = box_of_json generic_args_of_json ctx generics in
        Ok ({ kind; generics } : fn_ptr)
    | _ -> Error "")

and fn_ptr_kind_of_json (ctx : of_json_ctx) (js : json) :
    (fn_ptr_kind, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("Fun", fun_) ] ->
        let* fun_ = fun_id_of_json ctx fun_ in
        Ok (FunId fun_)
    | `Assoc [ ("Trait", `List [ x_0; x_1 ]) ] ->
        let* x_0 = trait_ref_of_json ctx x_0 in
        let* x_1 = trait_method_id_of_json ctx x_1 in
        Ok (TraitMethod (x_0, x_1))
    | _ -> Error "")

and fun_decl_id_of_json (ctx : of_json_ctx) (js : json) :
    (fun_decl_id, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | x -> FunDeclId.id_of_json ctx x
    | _ -> Error "")

and fun_decl_ref_of_json (ctx : of_json_ctx) (js : json) :
    (fun_decl_ref, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("id", id); ("generics", generics) ] ->
        let* id = fun_decl_id_of_json ctx id in
        let* generics = box_of_json generic_args_of_json ctx generics in
        Ok ({ id; generics } : fun_decl_ref)
    | _ -> Error "")

and fun_id_of_json (ctx : of_json_ctx) (js : json) : (fun_id, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("Regular", regular) ] ->
        let* regular = fun_decl_id_of_json ctx regular in
        Ok (FRegular regular)
    | `Assoc [ ("Builtin", builtin) ] ->
        let* builtin = builtin_fun_id_of_json ctx builtin in
        Ok (FBuiltin builtin)
    | _ -> Error "")

and fun_sig_of_json (ctx : of_json_ctx) (js : json) : (fun_sig, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc
        [
          ("is_unsafe", is_unsafe);
          ("abi", abi);
          ("is_variadic", is_variadic);
          ("inputs", inputs);
          ("output", output);
        ] ->
        let* is_unsafe = bool_of_json ctx is_unsafe in
        let* abi = abi_of_json ctx abi in
        let* is_variadic = bool_of_json ctx is_variadic in
        let* inputs = list_of_json ty_of_json ctx inputs in
        let* output = ty_of_json ctx output in
        Ok ({ is_unsafe; abi; is_variadic; inputs; output } : fun_sig)
    | _ -> Error "")

and generic_args_of_json (ctx : of_json_ctx) (js : json) :
    (generic_args, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc
        [
          ("regions", regions);
          ("types", types);
          ("const_generics", const_generics);
          ("trait_refs", trait_refs);
        ] ->
        let* regions =
          index_vec_of_json region_id_of_json region_of_json ctx regions
        in
        let* types =
          index_vec_of_json type_var_id_of_json ty_of_json ctx types
        in
        let* const_generics =
          index_vec_of_json const_generic_var_id_of_json constant_expr_of_json
            ctx const_generics
        in
        let* trait_refs =
          index_vec_of_json trait_clause_id_of_json trait_ref_of_json ctx
            trait_refs
        in
        Ok ({ regions; types; const_generics; trait_refs } : generic_args)
    | _ -> Error "")

and generic_params_of_json (ctx : of_json_ctx) (js : json) :
    (generic_params, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc
        [
          ("regions", regions);
          ("types", types);
          ("const_generics", const_generics);
          ("trait_clauses", trait_clauses);
          ("regions_outlive", regions_outlive);
          ("types_outlive", types_outlive);
          ("trait_type_constraints", trait_type_constraints);
        ] ->
        let* regions =
          index_vec_of_json region_id_of_json region_param_of_json ctx regions
        in
        let* types =
          index_vec_of_json type_var_id_of_json type_param_of_json ctx types
        in
        let* const_generics =
          index_vec_of_json const_generic_var_id_of_json
            const_generic_param_of_json ctx const_generics
        in
        let* trait_clauses =
          index_vec_of_json trait_clause_id_of_json trait_param_of_json ctx
            trait_clauses
        in
        let* regions_outlive =
          list_of_json
            (region_binder_of_json
               (outlives_pred_of_json region_of_json region_of_json))
            ctx regions_outlive
        in
        let* types_outlive =
          list_of_json
            (region_binder_of_json
               (outlives_pred_of_json ty_of_json region_of_json))
            ctx types_outlive
        in
        let* trait_type_constraints =
          index_vec_of_json trait_type_constraint_id_of_json
            (region_binder_of_json trait_type_constraint_of_json)
            ctx trait_type_constraints
        in
        Ok
          ({
             regions;
             types;
             const_generics;
             trait_clauses;
             regions_outlive;
             types_outlive;
             trait_type_constraints;
           }
            : generic_params)
    | _ -> Error "")

and global_decl_id_of_json (ctx : of_json_ctx) (js : json) :
    (global_decl_id, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | x -> GlobalDeclId.id_of_json ctx x
    | _ -> Error "")

and global_decl_ref_of_json (ctx : of_json_ctx) (js : json) :
    (global_decl_ref, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("id", id); ("generics", generics) ] ->
        let* id = global_decl_id_of_json ctx id in
        let* generics = box_of_json generic_args_of_json ctx generics in
        Ok ({ id; generics } : global_decl_ref)
    | _ -> Error "")

and hash_consed_of_json :
    'a0.
    (of_json_ctx -> json -> ('a0, string) result) ->
    of_json_ctx ->
    json ->
    ('a0 hash_consed, string) result =
 fun arg0_of_json ctx js ->
  combine_error_msgs js __FUNCTION__
    (match js with
    | json -> Error "use `hash_consed_val_of_json` instead"
    | _ -> Error "")

and impl_elem_of_json (ctx : of_json_ctx) (js : json) :
    (impl_elem, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("Ty", ty) ] ->
        let* ty = box_of_json (binder_of_json ty_of_json) ctx ty in
        Ok (ImplElemTy ty)
    | `Assoc [ ("Trait", trait) ] ->
        let* trait = trait_impl_id_of_json ctx trait in
        Ok (ImplElemTrait trait)
    | _ -> Error "")

and index_vec_of_json :
    'a0 'a1.
    (of_json_ctx -> json -> ('a0, string) result) ->
    (of_json_ctx -> json -> ('a1, string) result) ->
    of_json_ctx ->
    json ->
    ('a1 list, string) result =
 fun arg0_of_json arg1_of_json ctx js ->
  combine_error_msgs js __FUNCTION__
    (match js with
    | json -> list_of_json arg1_of_json ctx json
    | _ -> Error "")

and int_ty_of_json (ctx : of_json_ctx) (js : json) : (int_ty, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `String "Isize" -> Ok Isize
    | `String "I8" -> Ok I8
    | `String "I16" -> Ok I16
    | `String "I32" -> Ok I32
    | `String "I64" -> Ok I64
    | `String "I128" -> Ok I128
    | _ -> Error "")

and lifetime_mutability_of_json (ctx : of_json_ctx) (js : json) :
    (lifetime_mutability, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `String "Mutable" -> Ok LtMutable
    | `String "Shared" -> Ok LtShared
    | `String "Unknown" -> Ok LtUnknown
    | _ -> Error "")

and literal_of_json (ctx : of_json_ctx) (js : json) : (literal, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("Scalar", scalar) ] ->
        let* scalar = scalar_value_of_json ctx scalar in
        Ok (VScalar scalar)
    | `Assoc [ ("Float", float_) ] ->
        let* float_ = float_value_of_json ctx float_ in
        Ok (VFloat float_)
    | `Assoc [ ("Bool", bool_) ] ->
        let* bool_ = bool_of_json ctx bool_ in
        Ok (VBool bool_)
    | `Assoc [ ("Char", char_) ] ->
        let* char_ = char_of_json ctx char_ in
        Ok (VChar char_)
    | `Assoc [ ("ByteStr", byte_str) ] ->
        let* byte_str = list_of_json int_of_json ctx byte_str in
        Ok (VByteStr byte_str)
    | `Assoc [ ("Str", str) ] ->
        let* str = string_of_json ctx str in
        Ok (VStr str)
    | _ -> Error "")

and literal_type_of_json (ctx : of_json_ctx) (js : json) :
    (literal_type, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("Int", int) ] ->
        let* int = int_ty_of_json ctx int in
        Ok (TInt int)
    | `Assoc [ ("UInt", u_int) ] ->
        let* u_int = u_int_ty_of_json ctx u_int in
        Ok (TUInt u_int)
    | `Assoc [ ("Float", float_) ] ->
        let* float_ = float_type_of_json ctx float_ in
        Ok (TFloat float_)
    | `String "Bool" -> Ok TBool
    | `String "Char" -> Ok TChar
    | _ -> Error "")

and loc_of_json (ctx : of_json_ctx) (js : json) : (loc, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("line", line); ("col", col) ] ->
        let* line = int_of_json ctx line in
        let* col = int_of_json ctx col in
        Ok ({ line; col } : loc)
    | _ -> Error "")

and local_id_of_json (ctx : of_json_ctx) (js : json) : (local_id, string) result
    =
  combine_error_msgs js __FUNCTION__
    (match js with
    | x -> LocalId.id_of_json ctx x
    | _ -> Error "")

and name_of_json (ctx : of_json_ctx) (js : json) : (name, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | x -> list_of_json path_elem_of_json ctx x
    | _ -> Error "")

and nullop_of_json (ctx : of_json_ctx) (js : json) : (nullop, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `String "SizeOf" -> Ok SizeOf
    | `String "AlignOf" -> Ok AlignOf
    | `Assoc [ ("OffsetOf", `List [ x_0; x_1; x_2 ]) ] ->
        let* x_0 = type_decl_ref_of_json ctx x_0 in
        let* x_1 = option_of_json variant_id_of_json ctx x_1 in
        let* x_2 = field_id_of_json ctx x_2 in
        Ok (OffsetOf (x_0, x_1, x_2))
    | `String "UbChecks" -> Ok UbChecks
    | `String "OverflowChecks" -> Ok OverflowChecks
    | `String "ContractChecks" -> Ok ContractChecks
    | _ -> Error "")

and operand_of_json (ctx : of_json_ctx) (js : json) : (operand, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("Copy", copy) ] ->
        let* copy = place_of_json ctx copy in
        Ok (Copy copy)
    | `Assoc [ ("Move", move) ] ->
        let* move = place_of_json ctx move in
        Ok (Move move)
    | `Assoc [ ("Const", const) ] ->
        let* const = box_of_json constant_expr_of_json ctx const in
        Ok (Constant const)
    | _ -> Error "")

and outlives_pred_of_json :
    'a0 'a1.
    (of_json_ctx -> json -> ('a0, string) result) ->
    (of_json_ctx -> json -> ('a1, string) result) ->
    of_json_ctx ->
    json ->
    (('a0, 'a1) outlives_pred, string) result =
 fun arg0_of_json arg1_of_json ctx js ->
  combine_error_msgs js __FUNCTION__
    (match js with
    | `List [ x_0; x_1 ] ->
        let* x_0 = arg0_of_json ctx x_0 in
        let* x_1 = arg1_of_json ctx x_1 in
        Ok (x_0, x_1)
    | _ -> Error "")

and overflow_mode_of_json (ctx : of_json_ctx) (js : json) :
    (overflow_mode, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `String "Panic" -> Ok OPanic
    | `String "UB" -> Ok OUB
    | `String "Wrap" -> Ok OWrap
    | _ -> Error "")

and path_elem_of_json (ctx : of_json_ctx) (js : json) :
    (path_elem, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("Ident", `List [ x_0; x_1 ]) ] ->
        let* x_0 = string_of_json ctx x_0 in
        let* x_1 = disambiguator_of_json ctx x_1 in
        Ok (PeIdent (x_0, x_1))
    | `Assoc [ ("Impl", impl) ] ->
        let* impl = impl_elem_of_json ctx impl in
        Ok (PeImpl impl)
    | `Assoc [ ("Instantiated", instantiated) ] ->
        let* instantiated =
          box_of_json (binder_of_json generic_args_of_json) ctx instantiated
        in
        Ok (PeInstantiated instantiated)
    | `Assoc [ ("Target", target) ] ->
        let* target = string_of_json ctx target in
        Ok (PeTarget target)
    | _ -> Error "")

and place_of_json (ctx : of_json_ctx) (js : json) : (place, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("kind", kind); ("ty", ty) ] ->
        let* kind = place_kind_of_json ctx kind in
        let* ty = ty_of_json ctx ty in
        Ok ({ kind; ty } : place)
    | _ -> Error "")

and place_kind_of_json (ctx : of_json_ctx) (js : json) :
    (place_kind, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("Local", local) ] ->
        let* local = local_id_of_json ctx local in
        Ok (PlaceLocal local)
    | `Assoc [ ("Projection", `List [ x_0; x_1 ]) ] ->
        let* x_0 = box_of_json place_of_json ctx x_0 in
        let* x_1 = projection_elem_of_json ctx x_1 in
        Ok (PlaceProjection (x_0, x_1))
    | `Assoc [ ("Global", global) ] ->
        let* global = global_decl_ref_of_json ctx global in
        Ok (PlaceGlobal global)
    | _ -> Error "")

and predicate_origin_of_json (ctx : of_json_ctx) (js : json) :
    (predicate_origin, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `String "WhereClauseOnFn" -> Ok WhereClauseOnFn
    | `String "WhereClauseOnType" -> Ok WhereClauseOnType
    | `String "WhereClauseOnImpl" -> Ok WhereClauseOnImpl
    | `String "TraitSelf" -> Ok TraitSelf
    | `String "WhereClauseOnTrait" -> Ok WhereClauseOnTrait
    | `Assoc [ ("TraitItem", trait_item) ] ->
        let* trait_item = assoc_type_id_of_json ctx trait_item in
        Ok (TraitItem trait_item)
    | `String "Dyn" -> Ok OriginDyn
    | _ -> Error "")

and projection_elem_of_json (ctx : of_json_ctx) (js : json) :
    (projection_elem, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `String "Deref" -> Ok Deref
    | `Assoc [ ("Field", `List [ x_0; x_1 ]) ] ->
        let* x_0 = field_proj_kind_of_json ctx x_0 in
        let* x_1 = field_id_of_json ctx x_1 in
        Ok (Field (x_0, x_1))
    | `String "PtrMetadata" -> Ok PtrMetadata
    | `Assoc
        [ ("Index", `Assoc [ ("offset", offset); ("from_end", from_end) ]) ] ->
        let* offset = box_of_json operand_of_json ctx offset in
        let* from_end = bool_of_json ctx from_end in
        Ok (ProjIndex (offset, from_end))
    | `Assoc
        [
          ( "Subslice",
            `Assoc [ ("from", from); ("to", to_); ("from_end", from_end) ] );
        ] ->
        let* from = box_of_json operand_of_json ctx from in
        let* to_ = box_of_json operand_of_json ctx to_ in
        let* from_end = bool_of_json ctx from_end in
        Ok (Subslice (from, to_, from_end))
    | _ -> Error "")

and provenance_of_json (ctx : of_json_ctx) (js : json) :
    (provenance, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("Global", global) ] ->
        let* global = global_decl_ref_of_json ctx global in
        Ok (ProvGlobal global)
    | `Assoc [ ("Function", function_) ] ->
        let* function_ = fun_decl_ref_of_json ctx function_ in
        Ok (ProvFunction function_)
    | `String "Unknown" -> Ok ProvUnknown
    | _ -> Error "")

and ref_kind_of_json (ctx : of_json_ctx) (js : json) : (ref_kind, string) result
    =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `String "Mut" -> Ok RMut
    | `String "Shared" -> Ok RShared
    | _ -> Error "")

and region_of_json (ctx : of_json_ctx) (js : json) : (region, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("Var", var) ] ->
        let* var = de_bruijn_var_of_json region_id_of_json ctx var in
        Ok (RVar var)
    | `String "Static" -> Ok RStatic
    | `Assoc [ ("Body", body) ] ->
        let* body = region_id_of_json ctx body in
        Ok (RBody body)
    | `String "Erased" -> Ok RErased
    | _ -> Error "")

and region_binder_of_json :
    'a0.
    (of_json_ctx -> json -> ('a0, string) result) ->
    of_json_ctx ->
    json ->
    ('a0 region_binder, string) result =
 fun arg0_of_json ctx js ->
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("regions", regions); ("skip_binder", skip_binder) ] ->
        let* binder_regions =
          index_vec_of_json region_id_of_json region_param_of_json ctx regions
        in
        let* binder_value = arg0_of_json ctx skip_binder in
        Ok ({ binder_regions; binder_value } : _ region_binder)
    | _ -> Error "")

and region_id_of_json (ctx : of_json_ctx) (js : json) :
    (region_id, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | x -> RegionId.id_of_json ctx x
    | _ -> Error "")

and region_param_of_json (ctx : of_json_ctx) (js : json) :
    (region_param, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("index", index); ("name", name); ("mutability", mutability) ] ->
        let* index = region_id_of_json ctx index in
        let* name = option_of_json string_of_json ctx name in
        let* mutability = lifetime_mutability_of_json ctx mutability in
        Ok ({ index; name; mutability } : region_param)
    | _ -> Error "")

and rvalue_of_json (ctx : of_json_ctx) (js : json) : (rvalue, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("Use", `List [ x_0; x_1 ]) ] ->
        let* x_0 = operand_of_json ctx x_0 in
        let* x_1 = with_retag_of_json ctx x_1 in
        Ok (Use (x_0, x_1))
    | `Assoc
        [
          ( "Ref",
            `Assoc
              [
                ("place", place); ("kind", kind); ("ptr_metadata", ptr_metadata);
              ] );
        ] ->
        let* place = place_of_json ctx place in
        let* kind = borrow_kind_of_json ctx kind in
        let* ptr_metadata = operand_of_json ctx ptr_metadata in
        Ok (RvRef (place, kind, ptr_metadata))
    | `Assoc
        [
          ( "RawPtr",
            `Assoc
              [
                ("place", place); ("kind", kind); ("ptr_metadata", ptr_metadata);
              ] );
        ] ->
        let* place = place_of_json ctx place in
        let* kind = ref_kind_of_json ctx kind in
        let* ptr_metadata = operand_of_json ctx ptr_metadata in
        Ok (RawPtr (place, kind, ptr_metadata))
    | `Assoc [ ("BinaryOp", `List [ x_0; x_1; x_2 ]) ] ->
        let* x_0 = binop_of_json ctx x_0 in
        let* x_1 = operand_of_json ctx x_1 in
        let* x_2 = operand_of_json ctx x_2 in
        Ok (BinaryOp (x_0, x_1, x_2))
    | `Assoc [ ("UnaryOp", `List [ x_0; x_1 ]) ] ->
        let* x_0 = unop_of_json ctx x_0 in
        let* x_1 = operand_of_json ctx x_1 in
        Ok (UnaryOp (x_0, x_1))
    | `Assoc [ ("NullaryOp", `List [ x_0; x_1 ]) ] ->
        let* x_0 = nullop_of_json ctx x_0 in
        let* x_1 = ty_of_json ctx x_1 in
        Ok (NullaryOp (x_0, x_1))
    | `Assoc [ ("Discriminant", discriminant) ] ->
        let* discriminant = place_of_json ctx discriminant in
        Ok (Discriminant discriminant)
    | `Assoc [ ("Aggregate", `List [ x_0; x_1 ]) ] ->
        let* x_0 = aggregate_kind_of_json ctx x_0 in
        let* x_1 = list_of_json operand_of_json ctx x_1 in
        Ok (Aggregate (x_0, x_1))
    | `Assoc [ ("Len", `List [ x_0; x_1; x_2 ]) ] ->
        let* x_0 = place_of_json ctx x_0 in
        let* x_1 = ty_of_json ctx x_1 in
        let* x_2 = option_of_json (box_of_json constant_expr_of_json) ctx x_2 in
        Ok (Len (x_0, x_1, x_2))
    | `Assoc [ ("Repeat", `List [ x_0; x_1; x_2 ]) ] ->
        let* x_0 = operand_of_json ctx x_0 in
        let* x_1 = ty_of_json ctx x_1 in
        let* x_2 = box_of_json constant_expr_of_json ctx x_2 in
        Ok (Repeat (x_0, x_1, x_2))
    | _ -> Error "")

and scalar_value_of_json (ctx : of_json_ctx) (js : json) :
    (scalar_value, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("Unsigned", `List [ x_0; x_1 ]) ] ->
        let* x_0 = u_int_ty_of_json ctx x_0 in
        let* x_1 = big_int_of_json ctx x_1 in
        Ok (UnsignedScalar (x_0, x_1))
    | `Assoc [ ("Signed", `List [ x_0; x_1 ]) ] ->
        let* x_0 = int_ty_of_json ctx x_0 in
        let* x_1 = big_int_of_json ctx x_1 in
        Ok (SignedScalar (x_0, x_1))
    | _ -> Error "")

and span_of_json (ctx : of_json_ctx) (js : json) : (span, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("data", data); ("generated_from_span", generated_from_span) ] ->
        let* data = span_data_of_json ctx data in
        let* generated_from_span =
          option_of_json span_data_of_json ctx generated_from_span
        in
        Ok ({ data; generated_from_span } : span)
    | _ -> Error "")

and span_data_of_json (ctx : of_json_ctx) (js : json) :
    (span_data, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("file_id", file_id); ("beg", beg); ("end", end_) ] ->
        let* file = file_id_of_json ctx file_id in
        let* beg_loc = loc_of_json ctx beg in
        let* end_loc = loc_of_json ctx end_ in
        Ok ({ file; beg_loc; end_loc } : span_data)
    | _ -> Error "")

and trait_assoc_ty_impl_of_json (ctx : of_json_ctx) (js : json) :
    (trait_assoc_ty_impl, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("value", value); ("implied_trait_refs", implied_trait_refs) ] ->
        let* value = ty_of_json ctx value in
        let* implied_trait_refs =
          index_vec_of_json trait_clause_id_of_json trait_ref_of_json ctx
            implied_trait_refs
        in
        Ok ({ value; implied_trait_refs } : trait_assoc_ty_impl)
    | _ -> Error "")

and trait_clause_id_of_json (ctx : of_json_ctx) (js : json) :
    (trait_clause_id, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | x -> TraitClauseId.id_of_json ctx x
    | _ -> Error "")

and trait_decl_id_of_json (ctx : of_json_ctx) (js : json) :
    (trait_decl_id, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | x -> TraitDeclId.id_of_json ctx x
    | _ -> Error "")

and trait_decl_ref_of_json (ctx : of_json_ctx) (js : json) :
    (trait_decl_ref, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("id", id); ("generics", generics) ] ->
        let* id = trait_decl_id_of_json ctx id in
        let* generics = box_of_json generic_args_of_json ctx generics in
        Ok ({ id; generics } : trait_decl_ref)
    | _ -> Error "")

and trait_impl_id_of_json (ctx : of_json_ctx) (js : json) :
    (trait_impl_id, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | x -> TraitImplId.id_of_json ctx x
    | _ -> Error "")

and trait_impl_ref_of_json (ctx : of_json_ctx) (js : json) :
    (trait_impl_ref, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("id", id); ("generics", generics) ] ->
        let* id = trait_impl_id_of_json ctx id in
        let* generics = box_of_json generic_args_of_json ctx generics in
        Ok ({ id; generics } : trait_impl_ref)
    | _ -> Error "")

and trait_method_id_of_json (ctx : of_json_ctx) (js : json) :
    (trait_method_id, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | x -> TraitMethodId.id_of_json ctx x
    | _ -> Error "")

and trait_param_of_json (ctx : of_json_ctx) (js : json) :
    (trait_param, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc
        [
          ("clause_id", clause_id);
          ("span", span);
          ("origin", origin);
          ("trait_", trait);
        ] ->
        let* clause_id = trait_clause_id_of_json ctx clause_id in
        let* span = option_of_json span_of_json ctx span in
        let* origin = predicate_origin_of_json ctx origin in
        let* trait = region_binder_of_json trait_decl_ref_of_json ctx trait in
        Ok ({ clause_id; span; origin; trait } : trait_param)
    | _ -> Error "")

and trait_ref_of_json (ctx : of_json_ctx) (js : json) :
    (trait_ref, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | json ->
        hash_consed_val_of_json ctx.tref_hashcons_map trait_ref_contents_of_json
          ctx json
    | _ -> Error "")

and trait_ref_contents_of_json (ctx : of_json_ctx) (js : json) :
    (trait_ref_contents, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("kind", kind); ("trait_decl_ref", trait_decl_ref) ] ->
        let* kind = trait_ref_kind_of_json ctx kind in
        let* trait_decl_ref =
          region_binder_of_json trait_decl_ref_of_json ctx trait_decl_ref
        in
        Ok ({ kind; trait_decl_ref } : trait_ref_contents)
    | _ -> Error "")

and trait_ref_kind_of_json (ctx : of_json_ctx) (js : json) :
    (trait_ref_kind, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("TraitImpl", trait_impl) ] ->
        let* trait_impl = trait_impl_ref_of_json ctx trait_impl in
        Ok (TraitImpl trait_impl)
    | `Assoc [ ("Clause", clause) ] ->
        let* clause =
          de_bruijn_var_of_json trait_clause_id_of_json ctx clause
        in
        Ok (Clause clause)
    | `Assoc [ ("ParentClause", `List [ x_0; x_1 ]) ] ->
        let* x_0 = box_of_json trait_ref_of_json ctx x_0 in
        let* x_1 = trait_clause_id_of_json ctx x_1 in
        Ok (ParentClause (x_0, x_1))
    | `Assoc [ ("ItemClause", `List [ x_0; x_1; x_2 ]) ] ->
        let* x_0 = box_of_json trait_ref_of_json ctx x_0 in
        let* x_1 = assoc_type_id_of_json ctx x_1 in
        let* x_2 = trait_clause_id_of_json ctx x_2 in
        Ok (ItemClause (x_0, x_1, x_2))
    | `String "SelfId" -> Ok Self
    | `Assoc
        [
          ( "BuiltinOrAuto",
            `Assoc
              [
                ("builtin_data", builtin_data);
                ("parent_trait_refs", parent_trait_refs);
                ("types", types);
              ] );
        ] ->
        let* builtin_data = builtin_impl_data_of_json ctx builtin_data in
        let* parent_trait_refs =
          index_vec_of_json trait_clause_id_of_json trait_ref_of_json ctx
            parent_trait_refs
        in
        let* types =
          (fun ctx json ->
            Result.map AssocTypeId.map_of_indexed_list
              (opt_indexed_map_of_json assoc_type_id_of_json
                 trait_assoc_ty_impl_of_json ctx json))
            ctx types
        in
        Ok (BuiltinOrAuto (builtin_data, parent_trait_refs, types))
    | `String "Dyn" -> Ok Dyn
    | `Assoc [ ("Unknown", unknown) ] ->
        let* unknown = string_of_json ctx unknown in
        Ok (UnknownTrait unknown)
    | _ -> Error "")

and trait_type_constraint_of_json (ctx : of_json_ctx) (js : json) :
    (trait_type_constraint, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("trait_ref", trait_ref); ("type_id", type_id); ("ty", ty) ] ->
        let* trait_ref = trait_ref_of_json ctx trait_ref in
        let* type_id = assoc_type_id_of_json ctx type_id in
        let* ty = ty_of_json ctx ty in
        Ok ({ trait_ref; type_id; ty } : trait_type_constraint)
    | _ -> Error "")

and trait_type_constraint_id_of_json (ctx : of_json_ctx) (js : json) :
    (trait_type_constraint_id, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | x -> TraitTypeConstraintId.id_of_json ctx x
    | _ -> Error "")

and ty_of_json (ctx : of_json_ctx) (js : json) : (ty, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | json ->
        hash_consed_val_of_json ctx.ty_hashcons_map ty_kind_of_json ctx json
    | _ -> Error "")

and ty_kind_of_json (ctx : of_json_ctx) (js : json) : (ty_kind, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("Adt", adt) ] ->
        let* adt = type_decl_ref_of_json ctx adt in
        Ok (TAdt adt)
    | `Assoc [ ("TypeVar", type_var) ] ->
        let* type_var =
          de_bruijn_var_of_json type_var_id_of_json ctx type_var
        in
        Ok (TVar type_var)
    | `Assoc [ ("Literal", literal) ] ->
        let* literal = literal_type_of_json ctx literal in
        Ok (TLiteral literal)
    | `String "Never" -> Ok TNever
    | `Assoc [ ("Ref", `List [ x_0; x_1; x_2 ]) ] ->
        let* x_0 = region_of_json ctx x_0 in
        let* x_1 = ty_of_json ctx x_1 in
        let* x_2 = ref_kind_of_json ctx x_2 in
        Ok (TRef (x_0, x_1, x_2))
    | `Assoc [ ("RawPtr", `List [ x_0; x_1 ]) ] ->
        let* x_0 = ty_of_json ctx x_0 in
        let* x_1 = ref_kind_of_json ctx x_1 in
        Ok (TRawPtr (x_0, x_1))
    | `Assoc [ ("TraitType", `List [ x_0; x_1; x_2 ]) ] ->
        let* x_0 = trait_ref_of_json ctx x_0 in
        let* x_1 = assoc_type_id_of_json ctx x_1 in
        let* x_2 = generic_args_of_json ctx x_2 in
        Ok (TTraitType (x_0, x_1, x_2))
    | `Assoc [ ("DynTrait", dyn_trait) ] ->
        let* dyn_trait = dyn_predicate_of_json ctx dyn_trait in
        Ok (TDynTrait dyn_trait)
    | `Assoc [ ("FnPtr", fn_ptr) ] ->
        let* fn_ptr = region_binder_of_json fun_sig_of_json ctx fn_ptr in
        Ok (TFnPtr fn_ptr)
    | `Assoc [ ("FnDef", fn_def) ] ->
        let* fn_def = region_binder_of_json fn_ptr_of_json ctx fn_def in
        Ok (TFnDef fn_def)
    | `Assoc [ ("PtrMetadata", ptr_metadata) ] ->
        let* ptr_metadata = ty_of_json ctx ptr_metadata in
        Ok (TPtrMetadata ptr_metadata)
    | `Assoc [ ("Array", `List [ x_0; x_1 ]) ] ->
        let* x_0 = ty_of_json ctx x_0 in
        let* x_1 = box_of_json constant_expr_of_json ctx x_1 in
        Ok (TArray (x_0, x_1))
    | `Assoc [ ("Slice", slice) ] ->
        let* slice = ty_of_json ctx slice in
        Ok (TSlice slice)
    | `Assoc [ ("Pattern", `List [ x_0; x_1 ]) ] ->
        let* x_0 = ty_of_json ctx x_0 in
        let* x_1 = type_pattern_of_json ctx x_1 in
        Ok (TPattern (x_0, x_1))
    | `Assoc [ ("Error", error) ] ->
        let* error = string_of_json ctx error in
        Ok (TError error)
    | _ -> Error "")

and type_decl_id_of_json (ctx : of_json_ctx) (js : json) :
    (type_decl_id, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | x -> TypeDeclId.id_of_json ctx x
    | _ -> Error "")

and type_decl_ref_of_json (ctx : of_json_ctx) (js : json) :
    (type_decl_ref, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("id", id); ("generics", generics) ] ->
        let* id = type_id_of_json ctx id in
        let* generics = box_of_json generic_args_of_json ctx generics in
        Ok ({ id; generics } : type_decl_ref)
    | _ -> Error "")

and type_id_of_json (ctx : of_json_ctx) (js : json) : (type_id, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("Adt", adt) ] ->
        let* adt = type_decl_id_of_json ctx adt in
        Ok (TAdtId adt)
    | `String "Tuple" -> Ok TTuple
    | `Assoc [ ("Builtin", builtin) ] ->
        let* builtin = builtin_ty_of_json ctx builtin in
        Ok (TBuiltin builtin)
    | _ -> Error "")

and type_param_of_json (ctx : of_json_ctx) (js : json) :
    (type_param, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("index", index); ("name", name) ] ->
        let* index = type_var_id_of_json ctx index in
        let* name = string_of_json ctx name in
        Ok ({ index; name } : type_param)
    | _ -> Error "")

and type_pattern_of_json (ctx : of_json_ctx) (js : json) :
    (type_pattern, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("Range", `List [ x_0; x_1 ]) ] ->
        let* x_0 = box_of_json constant_expr_of_json ctx x_0 in
        let* x_1 = box_of_json constant_expr_of_json ctx x_1 in
        Ok (Range (x_0, x_1))
    | `Assoc [ ("OrPattern", or_pattern) ] ->
        let* or_pattern = list_of_json type_pattern_of_json ctx or_pattern in
        Ok (OrPattern or_pattern)
    | `String "NotNull" -> Ok NotNull
    | _ -> Error "")

and type_var_id_of_json (ctx : of_json_ctx) (js : json) :
    (type_var_id, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | x -> TypeVarId.id_of_json ctx x
    | _ -> Error "")

and u_int_ty_of_json (ctx : of_json_ctx) (js : json) : (u_int_ty, string) result
    =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `String "Usize" -> Ok Usize
    | `String "U8" -> Ok U8
    | `String "U16" -> Ok U16
    | `String "U32" -> Ok U32
    | `String "U64" -> Ok U64
    | `String "U128" -> Ok U128
    | _ -> Error "")

and unop_of_json (ctx : of_json_ctx) (js : json) : (unop, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `String "Not" -> Ok Not
    | `Assoc [ ("Neg", neg) ] ->
        let* neg = overflow_mode_of_json ctx neg in
        Ok (Neg neg)
    | `Assoc [ ("Cast", cast) ] ->
        let* cast = cast_kind_of_json ctx cast in
        Ok (Cast cast)
    | _ -> Error "")

and unsizing_metadata_of_json (ctx : of_json_ctx) (js : json) :
    (unsizing_metadata, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("Length", length) ] ->
        let* length = box_of_json constant_expr_of_json ctx length in
        Ok (MetaLength length)
    | `Assoc [ ("VTable", `List [ x_0; x_1 ]) ] ->
        let* x_0 = trait_ref_of_json ctx x_0 in
        let* x_1 = box_of_json constant_expr_of_json ctx x_1 in
        Ok (MetaVTable (x_0, x_1))
    | `Assoc [ ("VTableUpcast", v_table_upcast) ] ->
        let* v_table_upcast =
          list_of_json field_id_of_json ctx v_table_upcast
        in
        Ok (MetaVTableUpcast v_table_upcast)
    | `String "Unknown" -> Ok MetaUnknown
    | _ -> Error "")

and variant_id_of_json (ctx : of_json_ctx) (js : json) :
    (variant_id, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | x -> VariantId.id_of_json ctx x
    | _ -> Error "")

and with_retag_of_json (ctx : of_json_ctx) (js : json) :
    (with_retag, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `String "No" -> Ok NoRetag
    | `String "Yes" -> Ok YesRetag
    | _ -> Error "")

module Ullbc = struct
  open UllbcAst

  let rec ___ = ()

  and block_of_json (ctx : of_json_ctx) (js : json) :
      (Generated_UllbcAst.block, string) result =
    combine_error_msgs js __FUNCTION__
      (match js with
      | `Assoc [ ("statements", statements); ("terminator", terminator) ] ->
          let* statements = list_of_json statement_of_json ctx statements in
          let* terminator = terminator_of_json ctx terminator in
          Ok ({ statements; terminator } : Generated_UllbcAst.block)
      | _ -> Error "")

  and block_id_of_json (ctx : of_json_ctx) (js : json) :
      (Generated_UllbcAst.block_id, string) result =
    combine_error_msgs js __FUNCTION__
      (match js with
      | x -> BlockId.id_of_json ctx x
      | _ -> Error "")

  and statement_of_json (ctx : of_json_ctx) (js : json) :
      (Generated_UllbcAst.statement, string) result =
    combine_error_msgs js __FUNCTION__
      (match js with
      | `Assoc
          [
            ("span", span); ("kind", kind); ("comments_before", comments_before);
          ] ->
          let* span = span_of_json ctx span in
          let* kind = statement_kind_of_json ctx kind in
          let* comments_before =
            list_of_json string_of_json ctx comments_before
          in
          Ok ({ span; kind; comments_before } : Generated_UllbcAst.statement)
      | _ -> Error "")

  and statement_kind_of_json (ctx : of_json_ctx) (js : json) :
      (Generated_UllbcAst.statement_kind, string) result =
    combine_error_msgs js __FUNCTION__
      (match js with
      | `Assoc [ ("Assign", `List [ x_0; x_1 ]) ] ->
          let* x_0 = place_of_json ctx x_0 in
          let* x_1 = rvalue_of_json ctx x_1 in
          Ok (Assign (x_0, x_1))
      | `Assoc [ ("SetDiscriminant", `List [ x_0; x_1 ]) ] ->
          let* x_0 = place_of_json ctx x_0 in
          let* x_1 = variant_id_of_json ctx x_1 in
          Ok (SetDiscriminant (x_0, x_1))
      | `Assoc [ ("CopyNonOverlapping", copy_non_overlapping) ] ->
          let* copy_non_overlapping =
            box_of_json copy_non_overlapping_of_json ctx copy_non_overlapping
          in
          Ok (CopyNonOverlapping copy_non_overlapping)
      | `Assoc [ ("StorageLive", storage_live) ] ->
          let* storage_live = local_id_of_json ctx storage_live in
          Ok (StorageLive storage_live)
      | `Assoc [ ("StorageDead", storage_dead) ] ->
          let* storage_dead = local_id_of_json ctx storage_dead in
          Ok (StorageDead storage_dead)
      | `Assoc [ ("PlaceMention", place_mention) ] ->
          let* place_mention = place_of_json ctx place_mention in
          Ok (PlaceMention place_mention)
      | `Assoc
          [
            ( "Assert",
              `Assoc [ ("assert", assert_); ("on_failure", on_failure) ] );
          ] ->
          let* assert_ = assertion_of_json ctx assert_ in
          let* on_failure = abort_kind_of_json ctx on_failure in
          Ok (Assert (assert_, on_failure))
      | `String "Nop" -> Ok Nop
      | _ -> Error "")

  and switch_of_json (ctx : of_json_ctx) (js : json) :
      (Generated_UllbcAst.switch, string) result =
    combine_error_msgs js __FUNCTION__
      (match js with
      | `Assoc [ ("If", `List [ x_0; x_1 ]) ] ->
          let* x_0 = block_id_of_json ctx x_0 in
          let* x_1 = block_id_of_json ctx x_1 in
          Ok (If (x_0, x_1))
      | `Assoc [ ("SwitchInt", `List [ x_0; x_1; x_2 ]) ] ->
          let* x_0 = literal_type_of_json ctx x_0 in
          let* x_1 =
            list_of_json (pair_of_json literal_of_json block_id_of_json) ctx x_1
          in
          let* x_2 = block_id_of_json ctx x_2 in
          Ok (SwitchInt (x_0, x_1, x_2))
      | _ -> Error "")

  and terminator_of_json (ctx : of_json_ctx) (js : json) :
      (terminator, string) result =
    combine_error_msgs js __FUNCTION__
      (match js with
      | `Assoc
          [
            ("span", span); ("kind", kind); ("comments_before", comments_before);
          ] ->
          let* span = span_of_json ctx span in
          let* kind = terminator_kind_of_json ctx kind in
          let* comments_before =
            list_of_json string_of_json ctx comments_before
          in
          Ok ({ span; kind; comments_before } : terminator)
      | _ -> Error "")

  and terminator_kind_of_json (ctx : of_json_ctx) (js : json) :
      (terminator_kind, string) result =
    combine_error_msgs js __FUNCTION__
      (match js with
      | `Assoc [ ("Goto", `Assoc [ ("target", target) ]) ] ->
          let* target = block_id_of_json ctx target in
          Ok (Goto target)
      | `Assoc [ ("Switch", `Assoc [ ("discr", discr); ("targets", targets) ]) ]
        ->
          let* discr = operand_of_json ctx discr in
          let* targets = switch_of_json ctx targets in
          Ok (Switch (discr, targets))
      | `Assoc
          [
            ( "Call",
              `Assoc
                [ ("call", call); ("target", target); ("on_unwind", on_unwind) ]
            );
          ] ->
          let* call = call_of_json ctx call in
          let* target = block_id_of_json ctx target in
          let* on_unwind = block_id_of_json ctx on_unwind in
          Ok (Call (call, target, on_unwind))
      | `Assoc
          [
            ( "Drop",
              `Assoc
                [
                  ("kind", kind);
                  ("place", place);
                  ("fn_ptr", fn_ptr);
                  ("target", target);
                  ("on_unwind", on_unwind);
                ] );
          ] ->
          let* kind = drop_kind_of_json ctx kind in
          let* place = place_of_json ctx place in
          let* fn_ptr = fn_ptr_of_json ctx fn_ptr in
          let* target = block_id_of_json ctx target in
          let* on_unwind = block_id_of_json ctx on_unwind in
          Ok (Drop (kind, place, fn_ptr, target, on_unwind))
      | `Assoc
          [
            ( "Assert",
              `Assoc
                [
                  ("assert", assert_);
                  ("target", target);
                  ("on_unwind", on_unwind);
                ] );
          ] ->
          let* assert_ = assertion_of_json ctx assert_ in
          let* target = block_id_of_json ctx target in
          let* on_unwind = block_id_of_json ctx on_unwind in
          Ok (TAssert (assert_, target, on_unwind))
      | `Assoc
          [
            ( "InlineAsm",
              `Assoc
                [ ("asm", asm); ("targets", targets); ("on_unwind", on_unwind) ]
            );
          ] ->
          let* asm = string_of_json ctx asm in
          let* targets = list_of_json block_id_of_json ctx targets in
          let* on_unwind = block_id_of_json ctx on_unwind in
          Ok (InlineAsm (asm, targets, on_unwind))
      | `Assoc [ ("Abort", abort) ] ->
          let* abort = abort_kind_of_json ctx abort in
          Ok (Abort abort)
      | `String "Return" -> Ok Return
      | `String "UnwindResume" -> Ok UnwindResume
      | _ -> Error "")
end

module Llbc = struct
  open LlbcAst

  let rec ___ = ()

  and block_of_json (ctx : of_json_ctx) (js : json) :
      (Generated_LlbcAst.block, string) result =
    combine_error_msgs js __FUNCTION__
      (match js with
      | `Assoc [ ("span", span); ("statements", statements) ] ->
          let* span = span_of_json ctx span in
          let* statements = list_of_json statement_of_json ctx statements in
          Ok ({ span; statements } : Generated_LlbcAst.block)
      | _ -> Error "")

  and statement_of_json (ctx : of_json_ctx) (js : json) :
      (Generated_LlbcAst.statement, string) result =
    combine_error_msgs js __FUNCTION__
      (match js with
      | `Assoc
          [
            ("span", span);
            ("id", id);
            ("kind", kind);
            ("comments_before", comments_before);
          ] ->
          let* span = span_of_json ctx span in
          let* statement_id = statement_id_of_json ctx id in
          let* kind = statement_kind_of_json ctx kind in
          let* comments_before =
            list_of_json string_of_json ctx comments_before
          in
          Ok
            ({ span; statement_id; kind; comments_before }
              : Generated_LlbcAst.statement)
      | _ -> Error "")

  and statement_id_of_json (ctx : of_json_ctx) (js : json) :
      (statement_id, string) result =
    combine_error_msgs js __FUNCTION__
      (match js with
      | x -> StatementId.id_of_json ctx x
      | _ -> Error "")

  and statement_kind_of_json (ctx : of_json_ctx) (js : json) :
      (Generated_LlbcAst.statement_kind, string) result =
    combine_error_msgs js __FUNCTION__
      (match js with
      | `Assoc [ ("Assign", `List [ x_0; x_1 ]) ] ->
          let* x_0 = place_of_json ctx x_0 in
          let* x_1 = rvalue_of_json ctx x_1 in
          Ok (Assign (x_0, x_1))
      | `Assoc [ ("SetDiscriminant", `List [ x_0; x_1 ]) ] ->
          let* x_0 = place_of_json ctx x_0 in
          let* x_1 = variant_id_of_json ctx x_1 in
          Ok (SetDiscriminant (x_0, x_1))
      | `Assoc [ ("CopyNonOverlapping", copy_non_overlapping) ] ->
          let* copy_non_overlapping =
            box_of_json copy_non_overlapping_of_json ctx copy_non_overlapping
          in
          Ok (CopyNonOverlapping copy_non_overlapping)
      | `Assoc [ ("StorageLive", storage_live) ] ->
          let* storage_live = local_id_of_json ctx storage_live in
          Ok (StorageLive storage_live)
      | `Assoc [ ("StorageDead", storage_dead) ] ->
          let* storage_dead = local_id_of_json ctx storage_dead in
          Ok (StorageDead storage_dead)
      | `Assoc [ ("PlaceMention", place_mention) ] ->
          let* place_mention = place_of_json ctx place_mention in
          Ok (PlaceMention place_mention)
      | `Assoc
          [
            ( "Drop",
              `Assoc
                [
                  ("place", place);
                  ("fn_ptr", fn_ptr);
                  ("kind", kind);
                  ("on_unwind", on_unwind);
                ] );
          ] ->
          let* place = place_of_json ctx place in
          let* fn_ptr = fn_ptr_of_json ctx fn_ptr in
          let* kind = drop_kind_of_json ctx kind in
          let* on_unwind = block_of_json ctx on_unwind in
          Ok (Drop (place, fn_ptr, kind, on_unwind))
      | `Assoc
          [
            ( "Assert",
              `Assoc
                [
                  ("assert", assert_);
                  ("on_failure", on_failure);
                  ("on_unwind", on_unwind);
                ] );
          ] ->
          let* assert_ = assertion_of_json ctx assert_ in
          let* on_failure = abort_kind_of_json ctx on_failure in
          let* on_unwind = block_of_json ctx on_unwind in
          Ok (Assert (assert_, on_failure, on_unwind))
      | `Assoc
          [
            ( "InlineAsm",
              `Assoc
                [ ("asm", asm); ("targets", targets); ("on_unwind", on_unwind) ]
            );
          ] ->
          let* asm = string_of_json ctx asm in
          let* targets = list_of_json block_of_json ctx targets in
          let* on_unwind = block_of_json ctx on_unwind in
          Ok (InlineAsm (asm, targets, on_unwind))
      | `Assoc [ ("Call", `Assoc [ ("call", call); ("on_unwind", on_unwind) ]) ]
        ->
          let* call = call_of_json ctx call in
          let* on_unwind = block_of_json ctx on_unwind in
          Ok (Call (call, on_unwind))
      | `Assoc [ ("Abort", abort) ] ->
          let* abort = abort_kind_of_json ctx abort in
          Ok (Abort abort)
      | `String "Return" -> Ok Return
      | `String "UnwindResume" -> Ok UnwindResume
      | `Assoc [ ("Break", break) ] ->
          let* break = int_of_json ctx break in
          Ok (Break break)
      | `Assoc [ ("Continue", continue) ] ->
          let* continue = int_of_json ctx continue in
          Ok (Continue continue)
      | `String "Nop" -> Ok Nop
      | `Assoc [ ("Switch", switch) ] ->
          let* switch = switch_of_json ctx switch in
          Ok (Switch switch)
      | `Assoc [ ("Loop", loop) ] ->
          let* loop = block_of_json ctx loop in
          Ok (Loop loop)
      | `Assoc [ ("Error", error) ] ->
          let* error = string_of_json ctx error in
          Ok (Error error)
      | _ -> Error "")

  and switch_of_json (ctx : of_json_ctx) (js : json) :
      (Generated_LlbcAst.switch, string) result =
    combine_error_msgs js __FUNCTION__
      (match js with
      | `Assoc [ ("If", `List [ x_0; x_1; x_2 ]) ] ->
          let* x_0 = operand_of_json ctx x_0 in
          let* x_1 = block_of_json ctx x_1 in
          let* x_2 = block_of_json ctx x_2 in
          Ok (If (x_0, x_1, x_2))
      | `Assoc [ ("SwitchInt", `List [ x_0; x_1; x_2; x_3 ]) ] ->
          let* x_0 = operand_of_json ctx x_0 in
          let* x_1 = literal_type_of_json ctx x_1 in
          let* x_2 =
            list_of_json
              (pair_of_json (list_of_json literal_of_json) block_of_json)
              ctx x_2
          in
          let* x_3 = block_of_json ctx x_3 in
          Ok (SwitchInt (x_0, x_1, x_2, x_3))
      | `Assoc [ ("Match", `List [ x_0; x_1; x_2 ]) ] ->
          let* x_0 = place_of_json ctx x_0 in
          let* x_1 =
            list_of_json
              (pair_of_json (list_of_json variant_id_of_json) block_of_json)
              ctx x_1
          in
          let* x_2 = option_of_json block_of_json ctx x_2 in
          Ok (Match (x_0, x_1, x_2))
      | _ -> Error "")
end

let rec ___ = ()

and alignment_modifier_of_json (ctx : of_json_ctx) (js : json) :
    (alignment_modifier, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("Align", align) ] ->
        let* align = int_of_json ctx align in
        Ok (Align align)
    | `Assoc [ ("Pack", pack) ] ->
        let* pack = int_of_json ctx pack in
        Ok (Pack pack)
    | _ -> Error "")

and assoc_item_id_of_json (ctx : of_json_ctx) (js : json) :
    (assoc_item_id, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("Type", type_) ] ->
        let* type_ = assoc_type_id_of_json ctx type_ in
        Ok (AssocIdType type_)
    | `Assoc [ ("Method", method_) ] ->
        let* method_ = trait_method_id_of_json ctx method_ in
        Ok (AssocIdMethod method_)
    | `Assoc [ ("Const", const) ] ->
        let* const = assoc_const_id_of_json ctx const in
        Ok (AssocIdConst const)
    | _ -> Error "")

and assoc_item_names_of_json (ctx : of_json_ctx) (js : json) :
    (assoc_item_names, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("types", types); ("methods", methods); ("consts", consts) ] ->
        let* types =
          index_vec_of_json assoc_type_id_of_json trait_item_name_of_json ctx
            types
        in
        let* methods =
          index_vec_of_json trait_method_id_of_json trait_item_name_of_json ctx
            methods
        in
        let* consts =
          index_vec_of_json assoc_const_id_of_json trait_item_name_of_json ctx
            consts
        in
        Ok ({ types; methods; consts } : assoc_item_names)
    | _ -> Error "")

and attr_info_of_json (ctx : of_json_ctx) (js : json) :
    (attr_info, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc
        [
          ("attributes", attributes);
          ("inline", inline);
          ("rename", rename);
          ("public", public);
        ] ->
        let* attributes = list_of_json attribute_of_json ctx attributes in
        let* inline = option_of_json inline_attr_of_json ctx inline in
        let* rename = option_of_json string_of_json ctx rename in
        let* public = bool_of_json ctx public in
        Ok ({ attributes; inline; rename; public } : attr_info)
    | _ -> Error "")

and attribute_of_json (ctx : of_json_ctx) (js : json) :
    (attribute, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `String "Opaque" -> Ok AttrOpaque
    | `String "Exclude" -> Ok AttrExclude
    | `Assoc [ ("Rename", rename) ] ->
        let* rename = string_of_json ctx rename in
        Ok (AttrRename rename)
    | `Assoc [ ("VariantsPrefix", variants_prefix) ] ->
        let* variants_prefix = string_of_json ctx variants_prefix in
        Ok (AttrVariantsPrefix variants_prefix)
    | `Assoc [ ("VariantsSuffix", variants_suffix) ] ->
        let* variants_suffix = string_of_json ctx variants_suffix in
        Ok (AttrVariantsSuffix variants_suffix)
    | `String "Transparent" -> Ok AttrTransparent
    | `Assoc [ ("DocComment", doc_comment) ] ->
        let* doc_comment = string_of_json ctx doc_comment in
        Ok (AttrDocComment doc_comment)
    | `Assoc [ ("Unknown", unknown) ] ->
        let* unknown = raw_attribute_of_json ctx unknown in
        Ok (AttrUnknown unknown)
    | _ -> Error "")

and body_of_json (ctx : of_json_ctx) (js : json) : (body, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("Unstructured", unstructured) ] ->
        let* unstructured =
          gexpr_body_of_json
            (index_vec_of_json Ullbc.block_id_of_json Ullbc.block_of_json)
            ctx unstructured
        in
        Ok (UnstructuredBody unstructured)
    | `Assoc [ ("Structured", structured) ] ->
        let* structured =
          gexpr_body_of_json Llbc.block_of_json ctx structured
        in
        Ok (StructuredBody structured)
    | `Assoc [ ("TargetDispatch", target_dispatch) ] ->
        let* target_dispatch =
          index_map_of_json string_of_json fun_decl_ref_of_json int_of_json ctx
            target_dispatch
        in
        Ok (TargetDispatchBody target_dispatch)
    | `Assoc [ ("Extern", extern) ] ->
        let* extern = string_of_json ctx extern in
        Ok (ExternBody extern)
    | `Assoc
        [ ("Intrinsic", `Assoc [ ("name", name); ("arg_names", arg_names) ]) ]
      ->
        let* name = string_of_json ctx name in
        let* arg_names =
          list_of_json (option_of_json string_of_json) ctx arg_names
        in
        Ok (IntrinsicBody (name, arg_names))
    | `String "Opaque" -> Ok OpaqueBody
    | `String "Missing" -> Ok MissingBody
    | `Assoc [ ("Error", error) ] ->
        let* error = error_of_json ctx error in
        Ok (ErrorBody error)
    | _ -> Error "")

and cli_options_of_json (ctx : of_json_ctx) (js : json) :
    (cli_options, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc
        [
          ("ullbc", ullbc);
          ("precise_drops", precise_drops);
          ("skip_borrowck", skip_borrowck);
          ("mir", mir);
          ("rustc_args", rustc_args);
          ("targets", targets);
          ("sysroot", sysroot);
          ("monomorphize", monomorphize);
          ("monomorphize_mut", monomorphize_mut);
          ("start_from", start_from);
          ("start_from_if_exists", start_from_if_exists);
          ("start_from_attribute", start_from_attribute);
          ("start_from_pub", start_from_pub);
          ("include", include_);
          ("opaque", opaque);
          ("exclude", exclude);
          ("extract_opaque_bodies", extract_opaque_bodies);
          ("translate_all_methods", translate_all_methods);
          ("duplicate_defaulted_methods", duplicate_defaulted_methods);
          ("lift_associated_types", lift_associated_types);
          ("hide_marker_traits", hide_marker_traits);
          ("hide_allocator", hide_allocator);
          ("remove_unused_clauses", remove_unused_clauses);
          ("remove_unused_self_clauses", remove_unused_self_clauses);
          ("remove_adt_clauses", remove_adt_clauses);
          ("desugar_drops", desugar_drops);
          ("ops_to_function_calls", ops_to_function_calls);
          ("index_to_function_calls", index_to_function_calls);
          ("treat_box_as_builtin", treat_box_as_builtin);
          ("raw_consts", raw_consts);
          ("consts", consts);
          ("unsized_strings", unsized_strings);
          ("reconstruct_fallible_operations", reconstruct_fallible_operations);
          ("reconstruct_asserts", reconstruct_asserts);
          ("unbind_item_vars", unbind_item_vars);
          ("print_original_ullbc", print_original_ullbc);
          ("print_ullbc", print_ullbc);
          ("print_built_llbc", print_built_llbc);
          ("print_llbc", print_llbc);
          ("dest_dir", dest_dir);
          ("dest_file", dest_file);
          ("no_dedup_serialized_ast", no_dedup_serialized_ast);
          ("format", format);
          ("no_serialize", no_serialize);
          ("no_typecheck", no_typecheck);
          ("no_normalize", no_normalize);
          ("no_reorder_decls", no_reorder_decls);
          ("abort_on_error", abort_on_error);
          ("error_on_warnings", error_on_warnings);
          ("preset", preset);
        ] ->
        let* ullbc = bool_of_json ctx ullbc in
        let* precise_drops = bool_of_json ctx precise_drops in
        let* skip_borrowck = bool_of_json ctx skip_borrowck in
        let* mir = option_of_json mir_level_of_json ctx mir in
        let* rustc_args = list_of_json string_of_json ctx rustc_args in
        let* targets = list_of_json string_of_json ctx targets in
        let* sysroot = option_of_json string_of_json ctx sysroot in
        let* monomorphize = bool_of_json ctx monomorphize in
        let* monomorphize_mut =
          option_of_json monomorphize_mut_of_json ctx monomorphize_mut
        in
        let* start_from = list_of_json string_of_json ctx start_from in
        let* start_from_if_exists =
          list_of_json string_of_json ctx start_from_if_exists
        in
        let* start_from_attribute =
          list_of_json string_of_json ctx start_from_attribute
        in
        let* start_from_pub = bool_of_json ctx start_from_pub in
        let* included = list_of_json string_of_json ctx include_ in
        let* opaque = list_of_json string_of_json ctx opaque in
        let* exclude = list_of_json string_of_json ctx exclude in
        let* extract_opaque_bodies = bool_of_json ctx extract_opaque_bodies in
        let* translate_all_methods = bool_of_json ctx translate_all_methods in
        let* duplicate_defaulted_methods =
          bool_of_json ctx duplicate_defaulted_methods
        in
        let* lift_associated_types =
          list_of_json string_of_json ctx lift_associated_types
        in
        let* hide_marker_traits = bool_of_json ctx hide_marker_traits in
        let* hide_allocator = bool_of_json ctx hide_allocator in
        let* remove_unused_clauses = bool_of_json ctx remove_unused_clauses in
        let* remove_unused_self_clauses =
          bool_of_json ctx remove_unused_self_clauses
        in
        let* remove_adt_clauses = bool_of_json ctx remove_adt_clauses in
        let* desugar_drops = bool_of_json ctx desugar_drops in
        let* ops_to_function_calls = bool_of_json ctx ops_to_function_calls in
        let* index_to_function_calls =
          bool_of_json ctx index_to_function_calls
        in
        let* treat_box_as_builtin = bool_of_json ctx treat_box_as_builtin in
        let* raw_consts = bool_of_json ctx raw_consts in
        let* consts = option_of_json const_handling_of_json ctx consts in
        let* unsized_strings = bool_of_json ctx unsized_strings in
        let* reconstruct_fallible_operations =
          bool_of_json ctx reconstruct_fallible_operations
        in
        let* reconstruct_asserts = bool_of_json ctx reconstruct_asserts in
        let* unbind_item_vars = bool_of_json ctx unbind_item_vars in
        let* print_original_ullbc = bool_of_json ctx print_original_ullbc in
        let* print_ullbc = bool_of_json ctx print_ullbc in
        let* print_built_llbc = bool_of_json ctx print_built_llbc in
        let* print_llbc = bool_of_json ctx print_llbc in
        let* dest_dir = option_of_json path_buf_of_json ctx dest_dir in
        let* dest_file = option_of_json path_buf_of_json ctx dest_file in
        let* no_dedup_serialized_ast =
          bool_of_json ctx no_dedup_serialized_ast
        in
        let* format =
          option_of_json serialization_format_arg_of_json ctx format
        in
        let* no_serialize = bool_of_json ctx no_serialize in
        let* no_typecheck = bool_of_json ctx no_typecheck in
        let* no_normalize = bool_of_json ctx no_normalize in
        let* no_reorder_decls = bool_of_json ctx no_reorder_decls in
        let* abort_on_error = bool_of_json ctx abort_on_error in
        let* error_on_warnings = bool_of_json ctx error_on_warnings in
        let* preset = option_of_json preset_of_json ctx preset in
        Ok
          ({
             ullbc;
             precise_drops;
             skip_borrowck;
             mir;
             rustc_args;
             targets;
             sysroot;
             monomorphize;
             monomorphize_mut;
             start_from;
             start_from_if_exists;
             start_from_attribute;
             start_from_pub;
             included;
             opaque;
             exclude;
             extract_opaque_bodies;
             translate_all_methods;
             duplicate_defaulted_methods;
             lift_associated_types;
             hide_marker_traits;
             hide_allocator;
             remove_unused_clauses;
             remove_unused_self_clauses;
             remove_adt_clauses;
             desugar_drops;
             ops_to_function_calls;
             index_to_function_calls;
             treat_box_as_builtin;
             raw_consts;
             consts;
             unsized_strings;
             reconstruct_fallible_operations;
             reconstruct_asserts;
             unbind_item_vars;
             print_original_ullbc;
             print_ullbc;
             print_built_llbc;
             print_llbc;
             dest_dir;
             dest_file;
             no_dedup_serialized_ast;
             format;
             no_serialize;
             no_typecheck;
             no_normalize;
             no_reorder_decls;
             abort_on_error;
             error_on_warnings;
             preset;
           }
            : cli_options)
    | _ -> Error "")

and closure_info_of_json (ctx : of_json_ctx) (js : json) :
    (closure_info, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc
        [
          ("kind", kind);
          ("fn_once_impl", fn_once_impl);
          ("fn_mut_impl", fn_mut_impl);
          ("fn_impl", fn_impl);
          ("signature", signature);
        ] ->
        let* kind = closure_kind_of_json ctx kind in
        let* fn_once_impl =
          region_binder_of_json trait_impl_ref_of_json ctx fn_once_impl
        in
        let* fn_mut_impl =
          option_of_json
            (region_binder_of_json trait_impl_ref_of_json)
            ctx fn_mut_impl
        in
        let* fn_impl =
          option_of_json
            (region_binder_of_json trait_impl_ref_of_json)
            ctx fn_impl
        in
        let* signature = region_binder_of_json fun_sig_of_json ctx signature in
        Ok
          ({ kind; fn_once_impl; fn_mut_impl; fn_impl; signature }
            : closure_info)
    | _ -> Error "")

and closure_kind_of_json (ctx : of_json_ctx) (js : json) :
    (closure_kind, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `String "Fn" -> Ok Fn
    | `String "FnMut" -> Ok FnMut
    | `String "FnOnce" -> Ok FnOnce
    | _ -> Error "")

and const_handling_of_json (ctx : of_json_ctx) (js : json) :
    (const_handling, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `String "Initializers" -> Ok Initializers
    | `String "Values" -> Ok Values
    | _ -> Error "")

and declaration_group_of_json (ctx : of_json_ctx) (js : json) :
    (declaration_group, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("Type", type_) ] ->
        let* type_ =
          g_declaration_group_of_json type_decl_id_of_json ctx type_
        in
        Ok (TypeGroup type_)
    | `Assoc [ ("Fun", fun_) ] ->
        let* fun_ = g_declaration_group_of_json fun_decl_id_of_json ctx fun_ in
        Ok (FunGroup fun_)
    | `Assoc [ ("Global", global) ] ->
        let* global =
          g_declaration_group_of_json global_decl_id_of_json ctx global
        in
        Ok (GlobalGroup global)
    | `Assoc [ ("TraitDecl", trait_decl) ] ->
        let* trait_decl =
          g_declaration_group_of_json trait_decl_id_of_json ctx trait_decl
        in
        Ok (TraitDeclGroup trait_decl)
    | `Assoc [ ("TraitImpl", trait_impl) ] ->
        let* trait_impl =
          g_declaration_group_of_json trait_impl_id_of_json ctx trait_impl
        in
        Ok (TraitImplGroup trait_impl)
    | `Assoc [ ("Mixed", mixed) ] ->
        let* mixed = g_declaration_group_of_json item_id_of_json ctx mixed in
        Ok (MixedGroup mixed)
    | _ -> Error "")

and discriminator_of_json (ctx : of_json_ctx) (js : json) :
    (discriminator, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("Known", known) ] ->
        let* known = variant_id_of_json ctx known in
        Ok (Known known)
    | `String "Invalid" -> Ok Invalid
    | `Assoc
        [
          ( "Branch",
            `Assoc
              [
                ("offset", offset);
                ("int_ty", int_ty);
                ("children", children);
                ("fallback", fallback);
              ] );
        ] ->
        let* offset = int_of_json ctx offset in
        let* int_ty = integer_type_of_json ctx int_ty in
        let* children =
          list_of_json
            (pair_of_json
               (range_inclusive_of_json scalar_value_of_json)
               discriminator_of_json)
            ctx children
        in
        let* fallback = box_of_json discriminator_of_json ctx fallback in
        Ok (Branch (offset, int_ty, children, fallback))
    | _ -> Error "")

and error_of_json (ctx : of_json_ctx) (js : json) : (error, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("span", span); ("msg", msg) ] ->
        let* span = span_of_json ctx span in
        let* msg = string_of_json ctx msg in
        Ok ({ span; msg } : error)
    | _ -> Error "")

and field_of_json (ctx : of_json_ctx) (js : json) : (field, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc
        [ ("span", span); ("attr_info", attr_info); ("name", name); ("ty", ty) ]
      ->
        let* span = span_of_json ctx span in
        let* attr_info = attr_info_of_json ctx attr_info in
        let* field_name = option_of_json string_of_json ctx name in
        let* field_ty = ty_of_json ctx ty in
        Ok ({ span; attr_info; field_name; field_ty } : field)
    | _ -> Error "")

and file_of_json (ctx : of_json_ctx) (js : json) : (file, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | json -> (
        match json with
        | `Assoc
            [
              ("id", id);
              ("name", name);
              ("crate_name", crate_name);
              ("contents", contents);
            ] ->
            let* id = FileId.id_of_json ctx id in
            let* name = file_name_of_json ctx name in
            let* crate_name = string_of_json ctx crate_name in
            let* contents = option_of_json string_of_json ctx contents in
            let file : file = { name; crate_name; contents } in
            FileTbl.add ctx.id_to_file_map id file;
            Ok file
        | _ -> Error "")
    | _ -> Error "")

and file_name_of_json (ctx : of_json_ctx) (js : json) :
    (file_name, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("Virtual", virtual_) ] ->
        let* virtual_ = path_buf_of_json ctx virtual_ in
        Ok (Virtual virtual_)
    | `Assoc [ ("Local", local) ] ->
        let* local = path_buf_of_json ctx local in
        Ok (Local local)
    | `Assoc [ ("NotReal", not_real) ] ->
        let* not_real = string_of_json ctx not_real in
        Ok (NotReal not_real)
    | _ -> Error "")

and fun_decl_of_json (ctx : of_json_ctx) (js : json) : (fun_decl, string) result
    =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc
        [
          ("def_id", def_id);
          ("item_meta", item_meta);
          ("generics", generics);
          ("signature", signature);
          ("src", src);
          ("is_global_initializer", is_global_initializer);
          ("body", body);
        ] ->
        let* def_id = fun_decl_id_of_json ctx def_id in
        let* item_meta = item_meta_of_json ctx item_meta in
        let* generics = generic_params_of_json ctx generics in
        let* signature = box_of_json fun_sig_of_json ctx signature in
        let* src = item_source_of_json ctx src in
        let* is_global_initializer =
          option_of_json global_decl_id_of_json ctx is_global_initializer
        in
        let* body = body_of_json ctx body in
        Ok
          ({
             def_id;
             item_meta;
             generics;
             signature;
             src;
             is_global_initializer;
             body;
           }
            : fun_decl)
    | _ -> Error "")

and g_declaration_group_of_json :
    'a0.
    (of_json_ctx -> json -> ('a0, string) result) ->
    of_json_ctx ->
    json ->
    ('a0 g_declaration_group, string) result =
 fun arg0_of_json ctx js ->
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("NonRec", non_rec) ] ->
        let* non_rec = arg0_of_json ctx non_rec in
        Ok (NonRecGroup non_rec)
    | `Assoc [ ("Rec", rec_) ] ->
        let* rec_ = list_of_json arg0_of_json ctx rec_ in
        Ok (RecGroup rec_)
    | _ -> Error "")

and gexpr_body_of_json :
    'a0.
    (of_json_ctx -> json -> ('a0, string) result) ->
    of_json_ctx ->
    json ->
    ('a0 gexpr_body, string) result =
 fun arg0_of_json ctx js ->
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc
        [
          ("span", span);
          ("bound_body_regions", bound_body_regions);
          ("locals", locals);
          ("body", body);
          ("comments", _);
        ] ->
        let* span = span_of_json ctx span in
        let* bound_body_regions = int_of_json ctx bound_body_regions in
        let* locals = locals_of_json ctx locals in
        let* body = arg0_of_json ctx body in
        Ok ({ span; bound_body_regions; locals; body } : _ gexpr_body)
    | _ -> Error "")

and global_decl_of_json (ctx : of_json_ctx) (js : json) :
    (global_decl, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc
        [
          ("def_id", def_id);
          ("item_meta", item_meta);
          ("generics", generics);
          ("ty", ty);
          ("src", src);
          ("global_kind", global_kind);
          ("value", value);
        ] ->
        let* def_id = global_decl_id_of_json ctx def_id in
        let* item_meta = item_meta_of_json ctx item_meta in
        let* generics = generic_params_of_json ctx generics in
        let* ty = ty_of_json ctx ty in
        let* src = item_source_of_json ctx src in
        let* global_kind = global_kind_of_json ctx global_kind in
        let* value = constant_expr_of_json ctx value in
        Ok
          ({ def_id; item_meta; generics; ty; src; global_kind; value }
            : global_decl)
    | _ -> Error "")

and global_kind_of_json (ctx : of_json_ctx) (js : json) :
    (global_kind, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `String "Static" -> Ok Static
    | `String "ThreadLocal" -> Ok ThreadLocal
    | `String "NamedConst" -> Ok NamedConst
    | `String "AnonConst" -> Ok AnonConst
    | _ -> Error "")

and index_map_of_json :
    'a0 'a1 'a2.
    (of_json_ctx -> json -> ('a0, string) result) ->
    (of_json_ctx -> json -> ('a1, string) result) ->
    (of_json_ctx -> json -> ('a2, string) result) ->
    of_json_ctx ->
    json ->
    (('a0 * 'a1) list, string) result =
 fun arg0_of_json arg1_of_json arg2_of_json ctx js ->
  combine_error_msgs js __FUNCTION__
    (match js with
    | json ->
        list_of_json (key_value_pair_of_json arg0_of_json arg1_of_json) ctx json
    | _ -> Error "")

and inline_attr_of_json (ctx : of_json_ctx) (js : json) :
    (inline_attr, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `String "Hint" -> Ok Hint
    | `String "Never" -> Ok Never
    | `String "Always" -> Ok Always
    | _ -> Error "")

and integer_type_of_json (ctx : of_json_ctx) (js : json) :
    (integer_type, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("Signed", signed) ] ->
        let* signed = int_ty_of_json ctx signed in
        Ok (Signed signed)
    | `Assoc [ ("Unsigned", unsigned) ] ->
        let* unsigned = u_int_ty_of_json ctx unsigned in
        Ok (Unsigned unsigned)
    | _ -> Error "")

and item_id_of_json (ctx : of_json_ctx) (js : json) : (item_id, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("Type", type_) ] ->
        let* type_ = type_decl_id_of_json ctx type_ in
        Ok (IdType type_)
    | `Assoc [ ("TraitDecl", trait_decl) ] ->
        let* trait_decl = trait_decl_id_of_json ctx trait_decl in
        Ok (IdTraitDecl trait_decl)
    | `Assoc [ ("TraitImpl", trait_impl) ] ->
        let* trait_impl = trait_impl_id_of_json ctx trait_impl in
        Ok (IdTraitImpl trait_impl)
    | `Assoc [ ("Fun", fun_) ] ->
        let* fun_ = fun_decl_id_of_json ctx fun_ in
        Ok (IdFun fun_)
    | `Assoc [ ("Global", global) ] ->
        let* global = global_decl_id_of_json ctx global in
        Ok (IdGlobal global)
    | _ -> Error "")

and item_meta_of_json (ctx : of_json_ctx) (js : json) :
    (item_meta, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc
        [
          ("name", name);
          ("span", span);
          ("source_text", source_text);
          ("attr_info", attr_info);
          ("is_local", is_local);
          ("opacity", opacity);
          ("lang_item", lang_item);
        ] ->
        let* name = name_of_json ctx name in
        let* span = span_of_json ctx span in
        let* source_text = option_of_json string_of_json ctx source_text in
        let* attr_info = attr_info_of_json ctx attr_info in
        let* is_local = bool_of_json ctx is_local in
        let* opacity = item_opacity_of_json ctx opacity in
        let* lang_item = option_of_json string_of_json ctx lang_item in
        Ok
          ({ name; span; source_text; attr_info; is_local; opacity; lang_item }
            : item_meta)
    | _ -> Error "")

and item_opacity_of_json (ctx : of_json_ctx) (js : json) :
    (item_opacity, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `String "Transparent" -> Ok Transparent
    | `String "Foreign" -> Ok Foreign
    | `String "Opaque" -> Ok ItemOpaque
    | `String "Invisible" -> Ok Invisible
    | _ -> Error "")

and item_source_of_json (ctx : of_json_ctx) (js : json) :
    (item_source, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `String "TopLevel" -> Ok TopLevelItem
    | `Assoc [ ("Closure", `Assoc [ ("info", info) ]) ] ->
        let* info = closure_info_of_json ctx info in
        Ok (ClosureItem info)
    | `Assoc
        [
          ( "TraitDecl",
            `Assoc [ ("trait_ref", trait_ref); ("item_id", item_id) ] );
        ] ->
        let* trait_ref = trait_decl_ref_of_json ctx trait_ref in
        let* item_id = assoc_item_id_of_json ctx item_id in
        Ok (TraitDeclItem (trait_ref, item_id))
    | `Assoc
        [
          ( "TraitImpl",
            `Assoc
              [
                ("impl_ref", impl_ref);
                ("trait_ref", trait_ref);
                ("item_id", item_id);
                ("reuses_default", reuses_default);
              ] );
        ] ->
        let* impl_ref = trait_impl_ref_of_json ctx impl_ref in
        let* trait_ref = trait_decl_ref_of_json ctx trait_ref in
        let* item_id = assoc_item_id_of_json ctx item_id in
        let* reuses_default = bool_of_json ctx reuses_default in
        Ok (TraitImplItem (impl_ref, trait_ref, item_id, reuses_default))
    | `Assoc [ ("TargetDependent", `Assoc [ ("dispatcher", dispatcher) ]) ] ->
        let* dispatcher = fun_decl_ref_of_json ctx dispatcher in
        Ok (TargetDependentItem dispatcher)
    | `Assoc
        [
          ( "VTableTy",
            `Assoc
              [
                ("dyn_predicate", dyn_predicate);
                ("field_map", field_map);
                ("supertrait_map", supertrait_map);
              ] );
        ] ->
        let* dyn_predicate = dyn_predicate_of_json ctx dyn_predicate in
        let* field_map =
          index_vec_of_json field_id_of_json v_table_field_of_json ctx field_map
        in
        let* supertrait_map =
          index_vec_of_json trait_clause_id_of_json
            (option_of_json field_id_of_json)
            ctx supertrait_map
        in
        Ok (VTableTyItem (dyn_predicate, field_map, supertrait_map))
    | `Assoc [ ("VTableInstance", `Assoc [ ("impl_ref", impl_ref) ]) ] ->
        let* impl_ref = trait_impl_ref_of_json ctx impl_ref in
        Ok (VTableInstanceItem impl_ref)
    | `String "VTableMethodShim" -> Ok VTableMethodShimItem
    | `String "VTableInstanceMono" -> Ok VTableInstanceMonoItem
    | _ -> Error "")

and layout_of_json (ctx : of_json_ctx) (js : json) : (layout, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc
        [
          ("size", size);
          ("align", align);
          ("discriminator", discriminator);
          ("uninhabited", uninhabited);
          ("variant_layouts", variant_layouts);
          ("repr", repr);
        ] ->
        let* size = option_of_json int_of_json ctx size in
        let* align = option_of_json int_of_json ctx align in
        let* discriminator =
          option_of_json discriminator_of_json ctx discriminator
        in
        let* uninhabited = bool_of_json ctx uninhabited in
        let* variant_layouts =
          index_vec_of_json variant_id_of_json
            (option_of_json variant_layout_of_json)
            ctx variant_layouts
        in
        let* repr = repr_options_of_json ctx repr in
        Ok
          ({ size; align; discriminator; uninhabited; variant_layouts; repr }
            : layout)
    | _ -> Error "")

and local_of_json (ctx : of_json_ctx) (js : json) : (local, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("index", index); ("name", name); ("span", span); ("ty", ty) ] ->
        let* index = local_id_of_json ctx index in
        let* name = option_of_json string_of_json ctx name in
        let* span = span_of_json ctx span in
        let* local_ty = ty_of_json ctx ty in
        Ok ({ index; name; span; local_ty } : local)
    | _ -> Error "")

and locals_of_json (ctx : of_json_ctx) (js : json) : (locals, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("arg_count", arg_count); ("locals", locals) ] ->
        let* arg_count = int_of_json ctx arg_count in
        let* locals =
          index_vec_of_json local_id_of_json local_of_json ctx locals
        in
        Ok ({ arg_count; locals } : locals)
    | _ -> Error "")

and mir_level_of_json (ctx : of_json_ctx) (js : json) :
    (mir_level, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `String "Built" -> Ok Built
    | `String "Promoted" -> Ok Promoted
    | `String "Elaborated" -> Ok Elaborated
    | `String "Optimized" -> Ok Optimized
    | _ -> Error "")

and monomorphize_mut_of_json (ctx : of_json_ctx) (js : json) :
    (monomorphize_mut, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `String "All" -> Ok All
    | `String "ExceptTypes" -> Ok ExceptTypes
    | _ -> Error "")

and preset_of_json (ctx : of_json_ctx) (js : json) : (preset, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `String "OldDefaults" -> Ok OldDefaults
    | `String "RawMir" -> Ok RawMir
    | `String "Fast" -> Ok Fast
    | `String "Aeneas" -> Ok Aeneas
    | `String "Eurydice" -> Ok Eurydice
    | `String "Soteria" -> Ok Soteria
    | `String "Tests" -> Ok Tests
    | _ -> Error "")

and ptr_metadata_of_json (ctx : of_json_ctx) (js : json) :
    (ptr_metadata, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `String "None" -> Ok NoMetadata
    | `String "Length" -> Ok Length
    | `Assoc [ ("VTable", v_table) ] ->
        let* v_table = type_decl_ref_of_json ctx v_table in
        Ok (VTable v_table)
    | `Assoc [ ("InheritFrom", inherit_from) ] ->
        let* inherit_from = ty_of_json ctx inherit_from in
        Ok (InheritFrom inherit_from)
    | _ -> Error "")

and raw_attribute_of_json (ctx : of_json_ctx) (js : json) :
    (raw_attribute, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("path", path); ("args", args) ] ->
        let* path = string_of_json ctx path in
        let* args = option_of_json string_of_json ctx args in
        Ok ({ path; args } : raw_attribute)
    | _ -> Error "")

and repr_algorithm_of_json (ctx : of_json_ctx) (js : json) :
    (repr_algorithm, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `String "Rust" -> Ok Rust
    | `String "C" -> Ok C
    | _ -> Error "")

and repr_options_of_json (ctx : of_json_ctx) (js : json) :
    (repr_options, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc
        [
          ("repr_algo", repr_algo);
          ("align_modif", align_modif);
          ("transparent", transparent);
          ("explicit_discr_type", explicit_discr_type);
        ] ->
        let* repr_algo = repr_algorithm_of_json ctx repr_algo in
        let* align_modif =
          option_of_json alignment_modifier_of_json ctx align_modif
        in
        let* transparent = bool_of_json ctx transparent in
        let* explicit_discr_type = bool_of_json ctx explicit_discr_type in
        Ok
          ({ repr_algo; align_modif; transparent; explicit_discr_type }
            : repr_options)
    | _ -> Error "")

and serialization_format_arg_of_json (ctx : of_json_ctx) (js : json) :
    (serialization_format_arg, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `String "Json" -> Ok Json
    | `String "Postcard" -> Ok Postcard
    | `String "All" -> Ok AllFormats
    | _ -> Error "")

and target_info_of_json (ctx : of_json_ctx) (js : json) :
    (target_info, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc
        [
          ("target_pointer_size", target_pointer_size);
          ("is_little_endian", is_little_endian);
        ] ->
        let* target_pointer_size = int_of_json ctx target_pointer_size in
        let* is_little_endian = bool_of_json ctx is_little_endian in
        Ok ({ target_pointer_size; is_little_endian } : target_info)
    | _ -> Error "")

and trait_assoc_const_of_json (ctx : of_json_ctx) (js : json) :
    (trait_assoc_const, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc
        [
          ("name", name);
          ("attr_info", attr_info);
          ("ty", ty);
          ("default", default);
        ] ->
        let* name = trait_item_name_of_json ctx name in
        let* attr_info = attr_info_of_json ctx attr_info in
        let* ty = ty_of_json ctx ty in
        let* default = option_of_json global_decl_ref_of_json ctx default in
        Ok ({ name; attr_info; ty; default } : trait_assoc_const)
    | _ -> Error "")

and trait_assoc_ty_of_json (ctx : of_json_ctx) (js : json) :
    (trait_assoc_ty, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc
        [
          ("name", name);
          ("attr_info", attr_info);
          ("default", default);
          ("implied_clauses", implied_clauses);
        ] ->
        let* name = trait_item_name_of_json ctx name in
        let* attr_info = attr_info_of_json ctx attr_info in
        let* default = option_of_json trait_assoc_ty_impl_of_json ctx default in
        let* implied_clauses =
          index_vec_of_json trait_clause_id_of_json trait_param_of_json ctx
            implied_clauses
        in
        Ok ({ name; attr_info; default; implied_clauses } : trait_assoc_ty)
    | _ -> Error "")

and trait_decl_of_json (ctx : of_json_ctx) (js : json) :
    (trait_decl, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc
        [
          ("def_id", def_id);
          ("item_meta", item_meta);
          ("generics", generics);
          ("implied_clauses", implied_clauses);
          ("consts", consts);
          ("types", types);
          ("methods", methods);
          ("vtable", vtable);
        ] ->
        let* def_id = trait_decl_id_of_json ctx def_id in
        let* item_meta = item_meta_of_json ctx item_meta in
        let* generics = generic_params_of_json ctx generics in
        let* implied_clauses =
          index_vec_of_json trait_clause_id_of_json trait_param_of_json ctx
            implied_clauses
        in
        let* consts =
          (fun ctx json ->
            Result.map AssocConstId.map_of_indexed_list
              (opt_indexed_map_of_json assoc_const_id_of_json
                 trait_assoc_const_of_json ctx json))
            ctx consts
        in
        let* types =
          (fun ctx json ->
            Result.map AssocTypeId.map_of_indexed_list
              (opt_indexed_map_of_json assoc_type_id_of_json
                 (binder_of_json trait_assoc_ty_of_json)
                 ctx json))
            ctx types
        in
        let* methods =
          (fun ctx json ->
            Result.map TraitMethodId.map_of_indexed_list
              (opt_indexed_map_of_json trait_method_id_of_json
                 (binder_of_json trait_method_of_json)
                 ctx json))
            ctx methods
        in
        let* vtable = option_of_json type_decl_ref_of_json ctx vtable in
        Ok
          ({
             def_id;
             item_meta;
             generics;
             implied_clauses;
             consts;
             types;
             methods;
             vtable;
           }
            : trait_decl)
    | _ -> Error "")

and trait_impl_of_json (ctx : of_json_ctx) (js : json) :
    (trait_impl, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc
        [
          ("def_id", def_id);
          ("item_meta", item_meta);
          ("impl_trait", impl_trait);
          ("generics", generics);
          ("implied_trait_refs", implied_trait_refs);
          ("consts", consts);
          ("types", types);
          ("methods", methods);
          ("vtable", vtable);
        ] ->
        let* def_id = trait_impl_id_of_json ctx def_id in
        let* item_meta = item_meta_of_json ctx item_meta in
        let* impl_trait = trait_decl_ref_of_json ctx impl_trait in
        let* generics = generic_params_of_json ctx generics in
        let* implied_trait_refs =
          index_vec_of_json trait_clause_id_of_json trait_ref_of_json ctx
            implied_trait_refs
        in
        let* consts =
          (fun ctx json ->
            Result.map AssocConstId.map_of_indexed_list
              (opt_indexed_map_of_json assoc_const_id_of_json
                 global_decl_ref_of_json ctx json))
            ctx consts
        in
        let* types =
          (fun ctx json ->
            Result.map AssocTypeId.map_of_indexed_list
              (opt_indexed_map_of_json assoc_type_id_of_json
                 (binder_of_json trait_assoc_ty_impl_of_json)
                 ctx json))
            ctx types
        in
        let* methods =
          (fun ctx json ->
            Result.map TraitMethodId.map_of_indexed_list
              (opt_indexed_map_of_json trait_method_id_of_json
                 (binder_of_json fun_decl_ref_of_json)
                 ctx json))
            ctx methods
        in
        let* vtable = option_of_json global_decl_ref_of_json ctx vtable in
        Ok
          ({
             def_id;
             item_meta;
             impl_trait;
             generics;
             implied_trait_refs;
             consts;
             types;
             methods;
             vtable;
           }
            : trait_impl)
    | _ -> Error "")

and trait_item_name_of_json (ctx : of_json_ctx) (js : json) :
    (trait_item_name, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | x -> string_of_json ctx x
    | _ -> Error "")

and trait_method_of_json (ctx : of_json_ctx) (js : json) :
    (trait_method, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc
        [
          ("name", name);
          ("item_meta", item_meta);
          ("signature", signature);
          ("default", default);
        ] ->
        let* name = trait_item_name_of_json ctx name in
        let* item_meta = item_meta_of_json ctx item_meta in
        let* signature = fun_sig_of_json ctx signature in
        let* default = option_of_json fun_decl_ref_of_json ctx default in
        Ok ({ name; item_meta; signature; default } : trait_method)
    | _ -> Error "")

and translated_crate_of_json (ctx : of_json_ctx) (js : json) :
    (translated_crate, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc
        [
          ("crate_name", crate_name);
          ("options", options);
          ("target_information", target_information);
          ("files", files);
          ("item_names", item_names);
          ("assoc_item_names", assoc_item_names);
          ("short_names", short_names);
          ("type_decls", type_decls);
          ("fun_decls", fun_decls);
          ("global_decls", global_decls);
          ("trait_decls", trait_decls);
          ("trait_impls", trait_impls);
          ("ordered_decls", ordered_decls);
        ] ->
        let* crate_name = string_of_json ctx crate_name in
        let* options = cli_options_of_json ctx options in
        let* target_information =
          index_map_of_json string_of_json target_info_of_json int_of_json ctx
            target_information
        in
        let* files = index_vec_of_json file_id_of_json file_of_json ctx files in
        let* item_names =
          index_map_of_json item_id_of_json name_of_json int_of_json ctx
            item_names
        in
        let* assoc_item_names =
          (fun ctx json ->
            Result.map TraitDeclId.map_of_indexed_list
              (opt_indexed_map_of_json trait_decl_id_of_json
                 assoc_item_names_of_json ctx json))
            ctx assoc_item_names
        in
        let* short_names =
          index_map_of_json item_id_of_json name_of_json int_of_json ctx
            short_names
        in
        let* type_decls =
          (fun ctx json ->
            Result.map TypeDeclId.map_of_indexed_list
              (opt_indexed_map_of_json type_decl_id_of_json type_decl_of_json
                 ctx json))
            ctx type_decls
        in
        let* fun_decls =
          (fun ctx json ->
            Result.map FunDeclId.map_of_indexed_list
              (opt_indexed_map_of_json fun_decl_id_of_json fun_decl_of_json ctx
                 json))
            ctx fun_decls
        in
        let* global_decls =
          (fun ctx json ->
            Result.map GlobalDeclId.map_of_indexed_list
              (opt_indexed_map_of_json global_decl_id_of_json
                 global_decl_of_json ctx json))
            ctx global_decls
        in
        let* trait_decls =
          (fun ctx json ->
            Result.map TraitDeclId.map_of_indexed_list
              (opt_indexed_map_of_json trait_decl_id_of_json trait_decl_of_json
                 ctx json))
            ctx trait_decls
        in
        let* trait_impls =
          (fun ctx json ->
            Result.map TraitImplId.map_of_indexed_list
              (opt_indexed_map_of_json trait_impl_id_of_json trait_impl_of_json
                 ctx json))
            ctx trait_impls
        in
        let* ordered_decls =
          option_of_json
            (list_of_json declaration_group_of_json)
            ctx ordered_decls
        in
        Ok
          ({
             crate_name;
             options;
             target_information;
             files;
             item_names;
             assoc_item_names;
             short_names;
             type_decls;
             fun_decls;
             global_decls;
             trait_decls;
             trait_impls;
             ordered_decls;
           }
            : translated_crate)
    | _ -> Error "")

and type_decl_of_json (ctx : of_json_ctx) (js : json) :
    (type_decl, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc
        [
          ("def_id", def_id);
          ("item_meta", item_meta);
          ("generics", generics);
          ("src", src);
          ("kind", kind);
          ("layout", layout);
          ("ptr_metadata", ptr_metadata);
        ] ->
        let* def_id = type_decl_id_of_json ctx def_id in
        let* item_meta = item_meta_of_json ctx item_meta in
        let* generics = generic_params_of_json ctx generics in
        let* src = item_source_of_json ctx src in
        let* kind = type_decl_kind_of_json ctx kind in
        let* layout =
          index_map_of_json string_of_json layout_of_json int_of_json ctx layout
        in
        let* ptr_metadata = ptr_metadata_of_json ctx ptr_metadata in
        Ok
          ({ def_id; item_meta; generics; src; kind; layout; ptr_metadata }
            : type_decl)
    | _ -> Error "")

and type_decl_kind_of_json (ctx : of_json_ctx) (js : json) :
    (type_decl_kind, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc [ ("Struct", struct_) ] ->
        let* struct_ =
          index_vec_of_json field_id_of_json field_of_json ctx struct_
        in
        Ok (Struct struct_)
    | `Assoc [ ("Enum", enum) ] ->
        let* enum =
          index_vec_of_json variant_id_of_json variant_of_json ctx enum
        in
        Ok (Enum enum)
    | `Assoc [ ("Union", union) ] ->
        let* union =
          index_vec_of_json field_id_of_json field_of_json ctx union
        in
        Ok (Union union)
    | `String "Opaque" -> Ok Opaque
    | `Assoc [ ("Alias", alias) ] ->
        let* alias = ty_of_json ctx alias in
        Ok (Alias alias)
    | `Assoc [ ("Error", error) ] ->
        let* error = string_of_json ctx error in
        Ok (TDeclError error)
    | _ -> Error "")

and v_table_field_of_json (ctx : of_json_ctx) (js : json) :
    (v_table_field, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `String "Size" -> Ok VTableSize
    | `String "Align" -> Ok VTableAlign
    | `String "Drop" -> Ok VTableDrop
    | `Assoc [ ("Method", method_) ] ->
        let* method_ = trait_method_id_of_json ctx method_ in
        Ok (VTableMethod method_)
    | `Assoc [ ("SuperTrait", super_trait) ] ->
        let* super_trait = trait_clause_id_of_json ctx super_trait in
        Ok (VTableSuperTrait super_trait)
    | _ -> Error "")

and variant_of_json (ctx : of_json_ctx) (js : json) : (variant, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc
        [
          ("id", id);
          ("span", span);
          ("attr_info", attr_info);
          ("name", name);
          ("fields", fields);
          ("discriminant", discriminant);
        ] ->
        let* id = variant_id_of_json ctx id in
        let* span = span_of_json ctx span in
        let* attr_info = attr_info_of_json ctx attr_info in
        let* variant_name = string_of_json ctx name in
        let* fields =
          index_vec_of_json field_id_of_json field_of_json ctx fields
        in
        let* discriminant = literal_of_json ctx discriminant in
        Ok
          ({ id; span; attr_info; variant_name; fields; discriminant }
            : variant)
    | _ -> Error "")

and variant_layout_of_json (ctx : of_json_ctx) (js : json) :
    (variant_layout, string) result =
  combine_error_msgs js __FUNCTION__
    (match js with
    | `Assoc
        [
          ("field_offsets", field_offsets);
          ("uninhabited", uninhabited);
          ("tagger", tagger);
        ] ->
        let* field_offsets =
          index_vec_of_json field_id_of_json int_of_json ctx field_offsets
        in
        let* uninhabited = bool_of_json ctx uninhabited in
        let* tagger =
          list_of_json
            (pair_of_json int_of_json scalar_value_of_json)
            ctx tagger
        in
        Ok ({ field_offsets; uninhabited; tagger } : variant_layout)
    | _ -> Error "")
