open Prims
let dbg_Gen : Prims.bool FStarC_Effect.ref= FStarC_Debug.get_toggle "Gen"
let showable_univ_var :
  FStarC_Syntax_Syntax.universe_uvar FStarC_Class_Show.showable=
  {
    FStarC_Class_Show.show =
      (fun u ->
         FStarC_Class_Show.show FStarC_Syntax_Print.showable_univ
           (FStarC_Syntax_Syntax.U_unif u))
  }
let gen_univs (env : FStarC_TypeChecker_Env.env)
  (x : FStarC_Syntax_Syntax.universe_uvar FStarC_FlatSet.t) :
  FStarC_Syntax_Syntax.univ_name Prims.list=
  let uu___ =
    FStarC_Class_Setlike.is_empty ()
      (Obj.magic
         (FStarC_FlatSet.setlike_flat_set FStarC_Syntax_Free.ord_univ_uvar))
      (Obj.magic x) in
  if uu___
  then []
  else
    (let s =
       let uu___1 =
         let uu___2 = FStarC_TypeChecker_Env.univ_vars env in
         Obj.magic
           (FStarC_Class_Setlike.diff ()
              (Obj.magic
                 (FStarC_FlatSet.setlike_flat_set
                    FStarC_Syntax_Free.ord_univ_uvar)) (Obj.magic x)
              (Obj.magic uu___2)) in
       FStarC_Class_Setlike.elems ()
         (Obj.magic
            (FStarC_FlatSet.setlike_flat_set FStarC_Syntax_Free.ord_univ_uvar))
         (Obj.magic uu___1) in
     (let uu___2 = FStarC_Effect.op_Bang dbg_Gen in
      if uu___2
      then
        let uu___3 =
          let uu___4 = FStarC_TypeChecker_Env.univ_vars env in
          FStarC_Class_Show.show
            (FStarC_FlatSet.showable_set FStarC_Syntax_Free.ord_univ_uvar
               showable_univ_var) uu___4 in
        FStarC_Format.print1 "univ_vars in env: %s\n" uu___3
      else ());
     (let r =
        FStar_Pervasives_Native.Some (FStarC_TypeChecker_Env.get_range env) in
      let u_names =
        FStarC_List.map
          (fun u ->
             let u_name = FStarC_Syntax_Syntax.new_univ_name r in
             (let uu___3 = FStarC_Effect.op_Bang dbg_Gen in
              if uu___3
              then
                let uu___4 =
                  let uu___5 = FStarC_Syntax_Unionfind.univ_uvar_id u in
                  FStarC_Class_Show.show FStarC_Class_Show.showable_int
                    uu___5 in
                let uu___5 =
                  FStarC_Class_Show.show FStarC_Syntax_Print.showable_univ
                    (FStarC_Syntax_Syntax.U_unif u) in
                let uu___6 =
                  FStarC_Class_Show.show FStarC_Syntax_Print.showable_univ
                    (FStarC_Syntax_Syntax.U_name u_name) in
                FStarC_Format.print3 "Setting ?%s (%s) to %s\n" uu___4 uu___5
                  uu___6
              else ());
             FStarC_Syntax_Unionfind.univ_change u
               (FStarC_Syntax_Syntax.U_name u_name);
             u_name) s in
      u_names))
let gather_free_univnames (env : FStarC_TypeChecker_Env.env)
  (t : FStarC_Syntax_Syntax.term) :
  FStarC_Syntax_Syntax.univ_name FStarC_FlatSet.t=
  let ctx_univnames = FStarC_TypeChecker_Env.univnames env in
  let tm_univnames = FStarC_Syntax_Free.univnames t in
  let univnames =
    Obj.magic
      (FStarC_Class_Setlike.diff ()
         (Obj.magic
            (FStarC_FlatSet.setlike_flat_set FStarC_Syntax_Syntax.ord_ident))
         (Obj.magic tm_univnames) (Obj.magic ctx_univnames)) in
  univnames
let check_universe_generalization
  (explicit_univ_names : FStarC_Syntax_Syntax.univ_name Prims.list)
  (generalized_univ_names : FStarC_Syntax_Syntax.univ_name Prims.list)
  (t : FStarC_Syntax_Syntax.term) :
  FStarC_Syntax_Syntax.univ_name Prims.list=
  match (explicit_univ_names, generalized_univ_names) with
  | ([], uu___) -> generalized_univ_names
  | (uu___, []) -> explicit_univ_names
  | uu___ ->
      let uu___1 =
        let uu___2 =
          FStarC_Class_Show.show FStarC_Syntax_Print.showable_term t in
        Prims.strcat
          "Generalized universe in a term containing explicit universe annotation : "
          uu___2 in
      FStarC_Errors.raise_error (FStarC_Syntax_Syntax.has_range_syntax ()) t
        FStarC_Errors_Codes.Fatal_UnexpectedGeneralizedUniverse ()
        (Obj.magic FStarC_Errors_Msg.is_error_message_string)
        (Obj.magic uu___1)
let generalize_universes (env : FStarC_TypeChecker_Env.env)
  (t0 : FStarC_Syntax_Syntax.term) : FStarC_Syntax_Syntax.tscheme=
  FStarC_Errors.with_ctx "While generalizing universes"
    (fun uu___ ->
       let t =
         FStarC_TypeChecker_Normalize.normalize
           [FStarC_TypeChecker_Env.NoFullNorm;
           FStarC_TypeChecker_Env.Beta;
           FStarC_TypeChecker_Env.DoNotUnfoldPureLets] env t0 in
       let univnames =
         let uu___1 = gather_free_univnames env t in
         FStarC_Class_Setlike.elems ()
           (Obj.magic
              (FStarC_FlatSet.setlike_flat_set FStarC_Syntax_Syntax.ord_ident))
           (Obj.magic uu___1) in
       (let uu___2 = FStarC_Effect.op_Bang dbg_Gen in
        if uu___2
        then
          let uu___3 =
            FStarC_Class_Show.show FStarC_Syntax_Print.showable_term t in
          let uu___4 =
            FStarC_Class_Show.show
              (FStarC_Class_Show.show_list FStarC_Ident.showable_ident)
              univnames in
          FStarC_Format.print2
            "generalizing universes in the term (post norm): %s with univnames: %s\n"
            uu___3 uu___4
        else ());
       (let univs = FStarC_Syntax_Free.univs t in
        (let uu___3 = FStarC_Effect.op_Bang dbg_Gen in
         if uu___3
         then
           let uu___4 =
             FStarC_Class_Show.show
               (FStarC_FlatSet.showable_set FStarC_Syntax_Free.ord_univ_uvar
                  showable_univ_var) univs in
           FStarC_Format.print1 "univs to gen : %s\n" uu___4
         else ());
        (let gen = gen_univs env univs in
         (let uu___4 = FStarC_Effect.op_Bang dbg_Gen in
          if uu___4
          then
            let uu___5 =
              FStarC_Class_Show.show FStarC_Syntax_Print.showable_term t in
            let uu___6 =
              FStarC_Class_Show.show
                (FStarC_Class_Show.show_list FStarC_Ident.showable_ident) gen in
            FStarC_Format.print2
              "After generalization, t: %s and univs: %s\n" uu___5 uu___6
          else ());
         (let univs1 = check_universe_generalization univnames gen t0 in
          let t1 = FStarC_TypeChecker_Normalize.reduce_uvar_solutions env t in
          let ts = FStarC_Syntax_Subst.close_univ_vars univs1 t1 in
          (univs1, ts)))))
let gen (env : FStarC_TypeChecker_Env.env) (is_rec : Prims.bool)
  (lecs :
    (FStarC_Syntax_Syntax.lbname * FStarC_Syntax_Syntax.term *
      FStarC_Syntax_Syntax.comp) Prims.list)
  :
  (FStarC_Syntax_Syntax.lbname * FStarC_Syntax_Syntax.univ_name Prims.list *
    FStarC_Syntax_Syntax.term * FStarC_Syntax_Syntax.comp *
    FStarC_Syntax_Syntax.binder Prims.list) Prims.list
    FStar_Pervasives_Native.option=
  let uu___ =
    let uu___1 =
      FStarC_Util.for_all
        (fun uu___2 ->
           match uu___2 with
           | (uu___3, uu___4, c) ->
               FStarC_Syntax_Util.is_pure_or_ghost_comp c) lecs in
    Prims.op_Negation uu___1 in
  if uu___
  then FStar_Pervasives_Native.None
  else
    (let norm c =
       (let uu___2 = FStarC_Debug.medium () in
        if uu___2
        then
          let uu___3 =
            FStarC_Class_Show.show FStarC_Syntax_Print.showable_comp c in
          FStarC_Format.print1 "Normalizing before generalizing:\n\t %s\n"
            uu___3
        else ());
       (let c1 =
          FStarC_TypeChecker_Normalize.normalize_comp
            [FStarC_TypeChecker_Env.Beta;
            FStarC_TypeChecker_Env.Exclude FStarC_TypeChecker_Env.Zeta;
            FStarC_TypeChecker_Env.NoFullNorm;
            FStarC_TypeChecker_Env.DoNotUnfoldPureLets] env c in
        (let uu___3 = FStarC_Debug.medium () in
         if uu___3
         then
           let uu___4 =
             FStarC_Class_Show.show FStarC_Syntax_Print.showable_comp c1 in
           FStarC_Format.print1 "Normalized to:\n\t %s\n" uu___4
         else ());
        c1) in
     let env_uvars = FStarC_TypeChecker_Env.uvars_in_env env in
     let gen_uvars uvs =
       let uu___1 =
         Obj.magic
           (FStarC_Class_Setlike.diff ()
              (Obj.magic
                 (FStarC_FlatSet.setlike_flat_set
                    FStarC_Syntax_Free.ord_ctx_uvar)) (Obj.magic uvs)
              (Obj.magic env_uvars)) in
       FStarC_Class_Setlike.elems ()
         (Obj.magic
            (FStarC_FlatSet.setlike_flat_set FStarC_Syntax_Free.ord_ctx_uvar))
         (Obj.magic uu___1) in
     let univs_and_uvars_of_lec uu___1 =
       match uu___1 with
       | (lbname, e, c) ->
           let c1 = norm c in
           let t = FStarC_Syntax_Util.comp_result c1 in
           let univs = FStarC_Syntax_Free.univs t in
           let uvt = FStarC_Syntax_Free.uvars t in
           ((let uu___3 = FStarC_Effect.op_Bang dbg_Gen in
             if uu___3
             then
               let uu___4 =
                 FStarC_Class_Show.show
                   (FStarC_FlatSet.showable_set
                      FStarC_Syntax_Free.ord_univ_uvar showable_univ_var)
                   univs in
               let uu___5 =
                 FStarC_Class_Show.show
                   (FStarC_FlatSet.showable_set
                      FStarC_Syntax_Free.ord_ctx_uvar
                      FStarC_Syntax_Print.showable_ctxu) uvt in
               FStarC_Format.print2
                 "^^^^\n\tFree univs = %s\n\tFree uvt=%s\n" uu___4 uu___5
             else ());
            (let univs1 =
               let uu___3 =
                 FStarC_Class_Setlike.elems ()
                   (Obj.magic
                      (FStarC_FlatSet.setlike_flat_set
                         FStarC_Syntax_Free.ord_ctx_uvar)) (Obj.magic uvt) in
               FStarC_List.fold_left
                 (fun uu___5 uu___4 ->
                    (fun univs2 uv ->
                       let uu___4 =
                         let uu___5 = FStarC_Syntax_Util.ctx_uvar_typ uv in
                         FStarC_Syntax_Free.univs uu___5 in
                       Obj.magic
                         (FStarC_Class_Setlike.union ()
                            (Obj.magic
                               (FStarC_FlatSet.setlike_flat_set
                                  FStarC_Syntax_Free.ord_univ_uvar))
                            (Obj.magic univs2) (Obj.magic uu___4))) uu___5
                      uu___4) univs uu___3 in
             let uvs = gen_uvars uvt in
             (let uu___4 = FStarC_Effect.op_Bang dbg_Gen in
              if uu___4
              then
                let uu___5 =
                  FStarC_Class_Show.show
                    (FStarC_FlatSet.showable_set
                       FStarC_Syntax_Free.ord_univ_uvar showable_univ_var)
                    univs1 in
                let uu___6 =
                  FStarC_Class_Show.show
                    (FStarC_Class_Show.show_list
                       FStarC_Syntax_Print.showable_ctxu) uvs in
                FStarC_Format.print2
                  "^^^^\n\tFree univs = %s\n\tgen_uvars = %s\n" uu___5 uu___6
              else ());
             (univs1, uvs, (lbname, e, c1)))) in
     let uu___1 = univs_and_uvars_of_lec (FStarC_List.hd lecs) in
     match uu___1 with
     | (univs, uvs, lec_hd) ->
         let force_univs_eq lec2 u1 u2 =
           let uu___2 =
             FStarC_Class_Setlike.equal ()
               (Obj.magic
                  (FStarC_FlatSet.setlike_flat_set
                     FStarC_Syntax_Free.ord_univ_uvar)) (Obj.magic u1)
               (Obj.magic u2) in
           if uu___2
           then ()
           else
             (let uu___3 = lec_hd in
              match uu___3 with
              | (lb1, uu___4, uu___5) ->
                  let uu___6 = lec2 in
                  (match uu___6 with
                   | (lb2, uu___7, uu___8) ->
                       let msg =
                         let uu___9 =
                           FStarC_Class_Show.show
                             (FStarC_Class_Show.show_either
                                FStarC_Syntax_Print.showable_bv
                                FStarC_Syntax_Syntax.showable_fv) lb1 in
                         let uu___10 =
                           FStarC_Class_Show.show
                             (FStarC_FlatSet.showable_set
                                FStarC_Syntax_Free.ord_univ_uvar
                                showable_univ_var) u1 in
                         let uu___11 =
                           FStarC_Class_Show.show
                             (FStarC_Class_Show.show_either
                                FStarC_Syntax_Print.showable_bv
                                FStarC_Syntax_Syntax.showable_fv) lb2 in
                         let uu___12 =
                           FStarC_Class_Show.show
                             (FStarC_FlatSet.showable_set
                                FStarC_Syntax_Free.ord_univ_uvar
                                showable_univ_var) u2 in
                         FStarC_Format.fmt4
                           "Generalizing the types of these mutually recursive definitions requires an incompatible set of universes for %s %s and %s %s"
                           uu___9 uu___10 uu___11 uu___12 in
                       FStarC_Errors.raise_error
                         FStarC_TypeChecker_Env.hasRange_env env
                         FStarC_Errors_Codes.Fatal_IncompatibleSetOfUniverse
                         ()
                         (Obj.magic FStarC_Errors_Msg.is_error_message_string)
                         (Obj.magic msg))) in
         let force_uvars_eq lec2 u1 u2 =
           let uvars_subseteq u11 u21 =
             FStarC_Util.for_all
               (fun u ->
                  FStarC_Util.for_some
                    (fun u' ->
                       FStarC_Syntax_Unionfind.equiv
                         u.FStarC_Syntax_Syntax.ctx_uvar_head
                         u'.FStarC_Syntax_Syntax.ctx_uvar_head) u21) u11 in
           let uu___2 =
             let uu___3 = uvars_subseteq u1 u2 in
             if uu___3 then uvars_subseteq u2 u1 else false in
           if uu___2
           then ()
           else
             (let uu___3 = lec_hd in
              match uu___3 with
              | (lb1, uu___4, uu___5) ->
                  let uu___6 = lec2 in
                  (match uu___6 with
                   | (lb2, uu___7, uu___8) ->
                       let msg =
                         let uu___9 =
                           FStarC_Class_Show.show
                             (FStarC_Class_Show.show_either
                                FStarC_Syntax_Print.showable_bv
                                FStarC_Syntax_Syntax.showable_fv) lb1 in
                         let uu___10 =
                           FStarC_Class_Show.show
                             (FStarC_Class_Show.show_either
                                FStarC_Syntax_Print.showable_bv
                                FStarC_Syntax_Syntax.showable_fv) lb2 in
                         FStarC_Format.fmt2
                           "Generalizing the types of these mutually recursive definitions requires an incompatible number of types for %s and %s"
                           uu___9 uu___10 in
                       FStarC_Errors.raise_error
                         FStarC_TypeChecker_Env.hasRange_env env
                         FStarC_Errors_Codes.Fatal_IncompatibleNumberOfTypes
                         ()
                         (Obj.magic FStarC_Errors_Msg.is_error_message_string)
                         (Obj.magic msg))) in
         let lecs1 =
           FStarC_List.fold_right
             (fun this_lec lecs2 ->
                let uu___2 = univs_and_uvars_of_lec this_lec in
                match uu___2 with
                | (this_univs, this_uvs, this_lec1) ->
                    (force_univs_eq this_lec1 univs this_univs;
                     force_uvars_eq this_lec1 uvs this_uvs;
                     this_lec1
                     ::
                     lecs2)) (FStarC_List.tl lecs) [] in
         let lecs2 = lec_hd :: lecs1 in
         let gen_types uvs1 =
           FStarC_List.concatMap
             (fun u ->
                if
                  FStar_Pervasives_Native.uu___is_Some
                    u.FStarC_Syntax_Syntax.ctx_uvar_meta
                then []
                else
                  (let uu___2 =
                     FStarC_Syntax_Unionfind.find
                       u.FStarC_Syntax_Syntax.ctx_uvar_head in
                   match uu___2 with
                   | FStar_Pervasives_Native.Some uu___3 ->
                       FStarC_Effect.failwith
                         "Unexpected instantiation of mutually recursive uvar"
                   | uu___3 ->
                       let k =
                         let uu___4 = FStarC_Syntax_Util.ctx_uvar_typ u in
                         FStarC_TypeChecker_Normalize.normalize
                           [FStarC_TypeChecker_Env.Beta;
                           FStarC_TypeChecker_Env.Exclude
                             FStarC_TypeChecker_Env.Zeta] env uu___4 in
                       let uu___4 = FStarC_Syntax_Util.arrow_formals k in
                       (match uu___4 with
                        | (bs, kres) ->
                            let uu___5 =
                              let uu___6 =
                                let uu___7 =
                                  FStarC_TypeChecker_Normalize.unfold_whnf
                                    env kres in
                                FStarC_Syntax_Util.unrefine uu___7 in
                              uu___6.FStarC_Syntax_Syntax.n in
                            (match uu___5 with
                             | FStarC_Syntax_Syntax.Tm_type uu___6 ->
                                 let free = FStarC_Syntax_Free.names kres in
                                 let uu___7 =
                                   let uu___8 =
                                     FStarC_Class_Setlike.is_empty ()
                                       (Obj.magic
                                          (FStarC_FlatSet.setlike_flat_set
                                             FStarC_Syntax_Syntax.ord_bv))
                                       (Obj.magic free) in
                                   Prims.op_Negation uu___8 in
                                 if uu___7
                                 then []
                                 else
                                   (let a =
                                      FStarC_Syntax_Syntax.new_bv
                                        (FStar_Pervasives_Native.Some
                                           (FStarC_TypeChecker_Env.get_range
                                              env)) kres in
                                    let t =
                                      match bs with
                                      | [] ->
                                          FStarC_Syntax_Syntax.bv_to_name a
                                      | uu___8 ->
                                          let uu___9 =
                                            FStarC_Syntax_Syntax.bv_to_name a in
                                          FStarC_Syntax_Util.abs bs uu___9
                                            (FStar_Pervasives_Native.Some
                                               (FStarC_Syntax_Util.residual_tot
                                                  kres)) in
                                    FStarC_Syntax_Util.set_uvar
                                      u.FStarC_Syntax_Syntax.ctx_uvar_head t;
                                    [(a,
                                       (FStarC_Syntax_Syntax.as_bqual_implicit
                                          true))])
                             | uu___6 -> [])))) uvs1 in
         let gen_univs1 = gen_univs env univs in
         let gen_tvars = gen_types uvs in
         let ecs =
           FStarC_List.map
             (fun uu___2 ->
                match uu___2 with
                | (lbname, e, c) ->
                    let uu___3 =
                      match (gen_tvars, gen_univs1) with
                      | ([], []) -> (e, c, [])
                      | uu___4 ->
                          let uu___5 = (e, c) in
                          (match uu___5 with
                           | (e0, c0) ->
                               let c1 =
                                 FStarC_TypeChecker_Normalize.normalize_comp
                                   [FStarC_TypeChecker_Env.Beta;
                                   FStarC_TypeChecker_Env.DoNotUnfoldPureLets;
                                   FStarC_TypeChecker_Env.CompressUvars;
                                   FStarC_TypeChecker_Env.NoFullNorm;
                                   FStarC_TypeChecker_Env.Exclude
                                     FStarC_TypeChecker_Env.Zeta] env c in
                               let e1 =
                                 FStarC_TypeChecker_Normalize.reduce_uvar_solutions
                                   env e in
                               let e2 =
                                 if is_rec
                                 then
                                   let tvar_args =
                                     FStarC_List.map
                                       (fun uu___6 ->
                                          match uu___6 with
                                          | (x, uu___7) ->
                                              let uu___8 =
                                                FStarC_Syntax_Syntax.bv_to_name
                                                  x in
                                              FStarC_Syntax_Syntax.iarg
                                                uu___8) gen_tvars in
                                   let instantiate_lbname_with_app tm fv =
                                     if
                                       FStarC_Syntax_Syntax.fv_eq fv
                                         (FStar_Pervasives.__proj__Inr__item__v
                                            lbname)
                                     then
                                       FStarC_Syntax_Syntax.mk_Tm_app tm
                                         tvar_args
                                         tm.FStarC_Syntax_Syntax.pos
                                     else tm in
                                   FStarC_Syntax_InstFV.inst
                                     instantiate_lbname_with_app e1
                                 else e1 in
                               let tvars_bs =
                                 FStarC_List.map
                                   (fun uu___6 ->
                                      match uu___6 with
                                      | (x, q) ->
                                          FStarC_Syntax_Syntax.mk_binder_with_attrs
                                            x q FStar_Pervasives_Native.None
                                            []) gen_tvars in
                               let t =
                                 let uu___6 =
                                   let uu___7 =
                                     FStarC_Syntax_Subst.compress
                                       (FStarC_Syntax_Util.comp_result c1) in
                                   uu___7.FStarC_Syntax_Syntax.n in
                                 match uu___6 with
                                 | FStarC_Syntax_Syntax.Tm_arrow
                                     { FStarC_Syntax_Syntax.bs1 = bs;
                                       FStarC_Syntax_Syntax.comp = cod;_}
                                     ->
                                     let uu___7 =
                                       FStarC_Syntax_Subst.open_comp bs cod in
                                     (match uu___7 with
                                      | (bs1, cod1) ->
                                          FStarC_Syntax_Util.arrow
                                            (FStarC_List.op_At tvars_bs bs1)
                                            cod1)
                                 | uu___7 ->
                                     FStarC_Syntax_Util.arrow tvars_bs c1 in
                               let e' =
                                 let uu___6 =
                                   let uu___7 =
                                     FStarC_Syntax_Util.residual_comp_of_comp
                                       c1 in
                                   FStar_Pervasives_Native.Some uu___7 in
                                 FStarC_Syntax_Util.abs tvars_bs e2 uu___6 in
                               let uu___6 = FStarC_Syntax_Syntax.mk_Total t in
                               (e', uu___6, tvars_bs)) in
                    (match uu___3 with
                     | (e1, c1, gvs) -> (lbname, gen_univs1, e1, c1, gvs)))
             lecs2 in
         FStar_Pervasives_Native.Some ecs)
let generalize' (env : FStarC_TypeChecker_Env.env) (is_rec : Prims.bool)
  (lecs :
    (FStarC_Syntax_Syntax.lbname * FStarC_Syntax_Syntax.term *
      FStarC_Syntax_Syntax.comp) Prims.list)
  :
  (FStarC_Syntax_Syntax.lbname * FStarC_Syntax_Syntax.univ_names *
    FStarC_Syntax_Syntax.term * FStarC_Syntax_Syntax.comp *
    FStarC_Syntax_Syntax.binder Prims.list) Prims.list=
  (let uu___1 = FStarC_Debug.low () in
   if uu___1
   then
     let uu___2 =
       let uu___3 =
         FStarC_List.map
           (fun uu___4 ->
              match uu___4 with
              | (lb, uu___5, uu___6) ->
                  FStarC_Class_Show.show
                    (FStarC_Class_Show.show_either
                       FStarC_Syntax_Print.showable_bv
                       FStarC_Syntax_Syntax.showable_fv) lb) lecs in
       FStarC_Class_Show.show
         (FStarC_Class_Show.show_list FStarC_Class_Show.showable_string)
         uu___3 in
     FStarC_Format.print1 "Generalizing: %s\n" uu___2
   else ());
  (let univnames_lecs =
     let empty =
       Obj.magic
         (FStarC_Class_Setlike.from_list ()
            (Obj.magic
               (FStarC_FlatSet.setlike_flat_set
                  FStarC_Syntax_Syntax.ord_ident)) []) in
     FStarC_List.fold_left
       (fun uu___2 uu___1 ->
          (fun out uu___1 ->
             match uu___1 with
             | (l, t, c) ->
                 let uu___2 = gather_free_univnames env t in
                 Obj.magic
                   (FStarC_Class_Setlike.union ()
                      (Obj.magic
                         (FStarC_FlatSet.setlike_flat_set
                            FStarC_Syntax_Syntax.ord_ident)) (Obj.magic out)
                      (Obj.magic uu___2))) uu___2 uu___1) empty lecs in
   let univnames_lecs1 =
     FStarC_Class_Setlike.elems ()
       (Obj.magic
          (FStarC_FlatSet.setlike_flat_set FStarC_Syntax_Syntax.ord_ident))
       (Obj.magic univnames_lecs) in
   let generalized_lecs =
     let uu___1 = gen env is_rec lecs in
     match uu___1 with
     | FStar_Pervasives_Native.None ->
         FStarC_List.map
           (fun uu___2 -> match uu___2 with | (l, t, c) -> (l, [], t, c, []))
           lecs
     | FStar_Pervasives_Native.Some luecs ->
         ((let uu___3 = FStarC_Debug.medium () in
           if uu___3
           then
             FStarC_List.iter
               (fun uu___4 ->
                  match uu___4 with
                  | (l, us, e, c, gvs) ->
                      let uu___5 =
                        FStarC_Class_Show.show
                          FStarC_Range_Ops.showable_range
                          e.FStarC_Syntax_Syntax.pos in
                      let uu___6 =
                        FStarC_Class_Show.show
                          (FStarC_Class_Show.show_either
                             FStarC_Syntax_Print.showable_bv
                             FStarC_Syntax_Syntax.showable_fv) l in
                      let uu___7 =
                        FStarC_Class_Show.show
                          FStarC_Syntax_Print.showable_term
                          (FStarC_Syntax_Util.comp_result c) in
                      let uu___8 =
                        FStarC_Class_Show.show
                          FStarC_Syntax_Print.showable_term e in
                      let uu___9 =
                        FStarC_Class_Show.show
                          (FStarC_Class_Show.show_list
                             FStarC_Syntax_Print.showable_binder) gvs in
                      FStarC_Format.print5
                        "(%s) Generalized %s at type %s\n%s\nVars = (%s)\n"
                        uu___5 uu___6 uu___7 uu___8 uu___9) luecs
           else ());
          luecs) in
   FStarC_List.map
     (fun uu___1 ->
        match uu___1 with
        | (l, generalized_univs, t, c, gvs) ->
            let uu___2 =
              check_universe_generalization univnames_lecs1 generalized_univs
                t in
            (l, uu___2, t, c, gvs)) generalized_lecs)
let generalize (env : FStarC_TypeChecker_Env.env) (is_rec : Prims.bool)
  (lecs :
    (FStarC_Syntax_Syntax.lbname * FStarC_Syntax_Syntax.term *
      FStarC_Syntax_Syntax.comp) Prims.list)
  :
  (FStarC_Syntax_Syntax.lbname * FStarC_Syntax_Syntax.univ_names *
    FStarC_Syntax_Syntax.term * FStarC_Syntax_Syntax.comp *
    FStarC_Syntax_Syntax.binder Prims.list) Prims.list=
  FStarC_Errors.with_ctx "While generalizing"
    (fun uu___ ->
       FStarC_Profiling.profile (fun uu___1 -> generalize' env is_rec lecs)
         (FStar_Pervasives_Native.Some
            (FStarC_Ident.string_of_lid
               (FStarC_TypeChecker_Env.current_module env)))
         "FStarC.TypeChecker.Util.generalize")
