diff --git a/ocaml/fstar-lib/generated/FStar_TypeChecker_Core.ml b/ocaml/fstar-lib/generated/FStar_TypeChecker_Core.ml
index 0adad5fd1c8..53333dbb75a 100644
--- a/ocaml/fstar-lib/generated/FStar_TypeChecker_Core.ml
+++ b/ocaml/fstar-lib/generated/FStar_TypeChecker_Core.ml
@@ -2706,166 +2706,166 @@ and (check' :
                              (E_TOTAL, uu___5) in
                            return uu___4) in
                     with_binders xs1 us uu___2))
-      | FStar_Syntax_Syntax.Tm_app
-          { FStar_Syntax_Syntax.hd = hd;
-            FStar_Syntax_Syntax.args =
-              (t1, FStar_Pervasives_Native.None)::(t2,
-                                                   FStar_Pervasives_Native.None)::[];_}
-          when FStar_TypeChecker_Util.short_circuit_head hd ->
-          let uu___ = check "app head" g hd in
-          op_let_Bang uu___
-            (fun uu___1 ->
-               match uu___1 with
-               | (eff_hd, t_hd) ->
-                   let uu___2 = is_arrow g t_hd in
-                   op_let_Bang uu___2
-                     (fun uu___3 ->
-                        match uu___3 with
-                        | (x, eff_arr1, s1) ->
-                            let uu___4 = check "app arg" g t1 in
-                            op_let_Bang uu___4
-                              (fun uu___5 ->
-                                 match uu___5 with
-                                 | (eff_arg1, t_t1) ->
-                                     let uu___6 =
-                                       with_context "operator arg1"
-                                         FStar_Pervasives_Native.None
-                                         (fun uu___7 ->
-                                            check_subtype g
-                                              (FStar_Pervasives_Native.Some
-                                                 t1) t_t1
-                                              (x.FStar_Syntax_Syntax.binder_bv).FStar_Syntax_Syntax.sort) in
-                                     op_let_Bang uu___6
-                                       (fun uu___7 ->
-                                          let s11 =
-                                            FStar_Syntax_Subst.subst
-                                              [FStar_Syntax_Syntax.NT
-                                                 ((x.FStar_Syntax_Syntax.binder_bv),
-                                                   t1)] s1 in
-                                          let uu___8 = is_arrow g s11 in
-                                          op_let_Bang uu___8
-                                            (fun uu___9 ->
-                                               match uu___9 with
-                                               | (y, eff_arr2, s2) ->
-                                                   let guard_formula =
-                                                     FStar_TypeChecker_Util.short_circuit
-                                                       hd
-                                                       [(t1,
-                                                          FStar_Pervasives_Native.None)] in
-                                                   let g' =
-                                                     match guard_formula with
-                                                     | FStar_TypeChecker_Common.Trivial
-                                                         -> g
-                                                     | FStar_TypeChecker_Common.NonTrivial
-                                                         gf ->
-                                                         push_hypothesis g gf in
-                                                   let uu___10 =
-                                                     let uu___11 =
-                                                       check "app arg" g' t2 in
-                                                     weaken_with_guard_formula
-                                                       guard_formula uu___11 in
-                                                   op_let_Bang uu___10
-                                                     (fun uu___11 ->
-                                                        match uu___11 with
-                                                        | (eff_arg2, t_t2) ->
-                                                            let uu___12 =
-                                                              with_context
-                                                                "operator arg2"
-                                                                FStar_Pervasives_Native.None
-                                                                (fun uu___13
-                                                                   ->
-                                                                   check_subtype
+      | FStar_Syntax_Syntax.Tm_app uu___ ->
+          let rec check_app_arg uu___1 uu___2 =
+            match (uu___1, uu___2) with
+            | ((eff_hd, t_hd), (arg, arg_qual)) ->
+                let uu___3 = is_arrow g t_hd in
+                op_let_Bang uu___3
+                  (fun uu___4 ->
+                     match uu___4 with
+                     | (x, eff_arr, t') ->
+                         let uu___5 = check "app arg" g arg in
+                         op_let_Bang uu___5
+                           (fun uu___6 ->
+                              match uu___6 with
+                              | (eff_arg, t_arg) ->
+                                  let uu___7 =
+                                    with_context "app subtyping"
+                                      FStar_Pervasives_Native.None
+                                      (fun uu___8 ->
+                                         check_subtype g
+                                           (FStar_Pervasives_Native.Some arg)
+                                           t_arg
+                                           (x.FStar_Syntax_Syntax.binder_bv).FStar_Syntax_Syntax.sort) in
+                                  op_let_Bang uu___7
+                                    (fun uu___8 ->
+                                       let uu___9 =
+                                         with_context "app arg qual"
+                                           FStar_Pervasives_Native.None
+                                           (fun uu___10 ->
+                                              check_arg_qual arg_qual
+                                                x.FStar_Syntax_Syntax.binder_qual) in
+                                       op_let_Bang uu___9
+                                         (fun uu___10 ->
+                                            let uu___11 =
+                                              let uu___12 =
+                                                FStar_Syntax_Subst.subst
+                                                  [FStar_Syntax_Syntax.NT
+                                                     ((x.FStar_Syntax_Syntax.binder_bv),
+                                                       arg)] t' in
+                                              ((join_eff eff_hd
+                                                  (join_eff eff_arr eff_arg)),
+                                                uu___12) in
+                                            return uu___11)))) in
+          let check_app hd args =
+            let uu___1 = check "app head" g hd in
+            op_let_Bang uu___1
+              (fun uu___2 ->
+                 match uu___2 with
+                 | (eff_hd, t) -> fold check_app_arg (eff_hd, t) args) in
+          let uu___1 = FStar_Syntax_Util.head_and_args_full e1 in
+          (match uu___1 with
+           | (hd, args) ->
+               (match args with
+                | (t1, FStar_Pervasives_Native.None)::(t2,
+                                                       FStar_Pervasives_Native.None)::[]
+                    when FStar_TypeChecker_Util.short_circuit_head hd ->
+                    let uu___2 = check "app head" g hd in
+                    op_let_Bang uu___2
+                      (fun uu___3 ->
+                         match uu___3 with
+                         | (eff_hd, t_hd) ->
+                             let uu___4 = is_arrow g t_hd in
+                             op_let_Bang uu___4
+                               (fun uu___5 ->
+                                  match uu___5 with
+                                  | (x, eff_arr1, s1) ->
+                                      let uu___6 = check "app arg" g t1 in
+                                      op_let_Bang uu___6
+                                        (fun uu___7 ->
+                                           match uu___7 with
+                                           | (eff_arg1, t_t1) ->
+                                               let uu___8 =
+                                                 with_context "operator arg1"
+                                                   FStar_Pervasives_Native.None
+                                                   (fun uu___9 ->
+                                                      check_subtype g
+                                                        (FStar_Pervasives_Native.Some
+                                                           t1) t_t1
+                                                        (x.FStar_Syntax_Syntax.binder_bv).FStar_Syntax_Syntax.sort) in
+                                               op_let_Bang uu___8
+                                                 (fun uu___9 ->
+                                                    let s11 =
+                                                      FStar_Syntax_Subst.subst
+                                                        [FStar_Syntax_Syntax.NT
+                                                           ((x.FStar_Syntax_Syntax.binder_bv),
+                                                             t1)] s1 in
+                                                    let uu___10 =
+                                                      is_arrow g s11 in
+                                                    op_let_Bang uu___10
+                                                      (fun uu___11 ->
+                                                         match uu___11 with
+                                                         | (y, eff_arr2, s2)
+                                                             ->
+                                                             let guard_formula
+                                                               =
+                                                               FStar_TypeChecker_Util.short_circuit
+                                                                 hd
+                                                                 [(t1,
+                                                                    FStar_Pervasives_Native.None)] in
+                                                             let g' =
+                                                               match guard_formula
+                                                               with
+                                                               | FStar_TypeChecker_Common.Trivial
+                                                                   -> g
+                                                               | FStar_TypeChecker_Common.NonTrivial
+                                                                   gf ->
+                                                                   push_hypothesis
+                                                                    g gf in
+                                                             let uu___12 =
+                                                               let uu___13 =
+                                                                 check
+                                                                   "app arg"
+                                                                   g' t2 in
+                                                               weaken_with_guard_formula
+                                                                 guard_formula
+                                                                 uu___13 in
+                                                             op_let_Bang
+                                                               uu___12
+                                                               (fun uu___13
+                                                                  ->
+                                                                  match uu___13
+                                                                  with
+                                                                  | (eff_arg2,
+                                                                    t_t2) ->
+                                                                    let uu___14
+                                                                    =
+                                                                    with_context
+                                                                    "operator arg2"
+                                                                    FStar_Pervasives_Native.None
+                                                                    (fun
+                                                                    uu___15
+                                                                    ->
+                                                                    check_subtype
                                                                     g'
                                                                     (FStar_Pervasives_Native.Some
                                                                     t2) t_t2
                                                                     (y.FStar_Syntax_Syntax.binder_bv).FStar_Syntax_Syntax.sort) in
-                                                            op_let_Bang
-                                                              uu___12
-                                                              (fun uu___13 ->
-                                                                 let uu___14
-                                                                   =
-                                                                   let uu___15
+                                                                    op_let_Bang
+                                                                    uu___14
+                                                                    (fun
+                                                                    uu___15
+                                                                    ->
+                                                                    let uu___16
+                                                                    =
+                                                                    let uu___17
                                                                     =
                                                                     FStar_Syntax_Subst.subst
                                                                     [
                                                                     FStar_Syntax_Syntax.NT
                                                                     ((y.FStar_Syntax_Syntax.binder_bv),
                                                                     t2)] s2 in
-                                                                   ((join_eff_l
+                                                                    ((join_eff_l
                                                                     [eff_hd;
                                                                     eff_arr1;
                                                                     eff_arr2;
                                                                     eff_arg1;
                                                                     eff_arg2]),
-                                                                    uu___15) in
-                                                                 return
-                                                                   uu___14)))))))
-      | FStar_Syntax_Syntax.Tm_app
-          { FStar_Syntax_Syntax.hd = hd;
-            FStar_Syntax_Syntax.args = (arg, arg_qual)::[];_}
-          ->
-          let uu___ = check "app head" g hd in
-          op_let_Bang uu___
-            (fun uu___1 ->
-               match uu___1 with
-               | (eff_hd, t) ->
-                   let uu___2 = is_arrow g t in
-                   op_let_Bang uu___2
-                     (fun uu___3 ->
-                        match uu___3 with
-                        | (x, eff_arr, t') ->
-                            let uu___4 = check "app arg" g arg in
-                            op_let_Bang uu___4
-                              (fun uu___5 ->
-                                 match uu___5 with
-                                 | (eff_arg, t_arg) ->
-                                     let uu___6 =
-                                       with_context "app subtyping"
-                                         FStar_Pervasives_Native.None
-                                         (fun uu___7 ->
-                                            check_subtype g
-                                              (FStar_Pervasives_Native.Some
-                                                 arg) t_arg
-                                              (x.FStar_Syntax_Syntax.binder_bv).FStar_Syntax_Syntax.sort) in
-                                     op_let_Bang uu___6
-                                       (fun uu___7 ->
-                                          let uu___8 =
-                                            with_context "app arg qual"
-                                              FStar_Pervasives_Native.None
-                                              (fun uu___9 ->
-                                                 check_arg_qual arg_qual
-                                                   x.FStar_Syntax_Syntax.binder_qual) in
-                                          op_let_Bang uu___8
-                                            (fun uu___9 ->
-                                               let uu___10 =
-                                                 let uu___11 =
-                                                   FStar_Syntax_Subst.subst
-                                                     [FStar_Syntax_Syntax.NT
-                                                        ((x.FStar_Syntax_Syntax.binder_bv),
-                                                          arg)] t' in
-                                                 ((join_eff eff_hd
-                                                     (join_eff eff_arr
-                                                        eff_arg)), uu___11) in
-                                               return uu___10)))))
-      | FStar_Syntax_Syntax.Tm_app
-          { FStar_Syntax_Syntax.hd = hd;
-            FStar_Syntax_Syntax.args = arg::args;_}
-          ->
-          let head =
-            FStar_Syntax_Syntax.mk
-              (FStar_Syntax_Syntax.Tm_app
-                 {
-                   FStar_Syntax_Syntax.hd = hd;
-                   FStar_Syntax_Syntax.args = [arg]
-                 }) e1.FStar_Syntax_Syntax.pos in
-          let t =
-            FStar_Syntax_Syntax.mk
-              (FStar_Syntax_Syntax.Tm_app
-                 {
-                   FStar_Syntax_Syntax.hd = head;
-                   FStar_Syntax_Syntax.args = args
-                 }) e1.FStar_Syntax_Syntax.pos in
-          memo_check g t
+                                                                    uu___17) in
+                                                                    return
+                                                                    uu___16)))))))
+                | uu___2 -> check_app hd args))
       | FStar_Syntax_Syntax.Tm_ascribed
           { FStar_Syntax_Syntax.tm = e2;
             FStar_Syntax_Syntax.asc = (FStar_Pervasives.Inl t, uu___, eq);
diff --git a/src/typechecker/FStar.TypeChecker.Core.fst b/src/typechecker/FStar.TypeChecker.Core.fst
index d0d39ca9162..8aa10378c2b 100644
--- a/src/typechecker/FStar.TypeChecker.Core.fst
+++ b/src/typechecker/FStar.TypeChecker.Core.fst
@@ -31,7 +31,7 @@ type env = {
    should_read_cache: bool
 }
 
-let push_binder g b = 
+let push_binder g b =
   if b.binder_bv.index <= g.max_binder_index
   then failwith "Assertion failed: unexpected shadowing in the core environment"
   else { g with tcenv = Env.push_binders g.tcenv [b]; max_binder_index = b.binder_bv.index }
@@ -42,12 +42,12 @@ let fresh_binder (g:env) (old:binder)
   : env & binder
   = let ctr = g.max_binder_index + 1 in
     let bv = { old.binder_bv with index = ctr } in
-    let b = S.mk_binder_with_attrs bv old.binder_qual old.binder_positivity old.binder_attrs in    
+    let b = S.mk_binder_with_attrs bv old.binder_qual old.binder_positivity old.binder_attrs in
     push_binder g b, b
 
-let open_binders (g:env) (bs:binders) 
-  = let g, bs_rev, subst = 
-        List.fold_left 
+let open_binders (g:env) (bs:binders)
+  = let g, bs_rev, subst =
+        List.fold_left
           (fun (g, bs, subst) b ->
             let bv = { b.binder_bv with sort = Subst.subst subst b.binder_bv.sort } in
             let b = { binder_bv = bv;
@@ -91,24 +91,24 @@ let open_pat (g:env) (p:pat)
     open_pat_aux g p []
 
 
-let open_term (g:env) (b:binder) (t:term) 
+let open_term (g:env) (b:binder) (t:term)
   : env & binder & term
   = let g, b' = fresh_binder g b in
     let t = FStar.Syntax.Subst.subst [DB(0, b'.binder_bv)] t in
     g, b', t
 
-let open_term_binders (g:env) (bs:binders) (t:term) 
+let open_term_binders (g:env) (bs:binders) (t:term)
   : env & binders & term
   = let g, bs, subst = open_binders g bs in
     g, bs, Subst.subst subst t
- 
-let open_comp (g:env) (b:binder) (c:comp) 
+
+let open_comp (g:env) (b:binder) (c:comp)
   : env & binder & comp
   = let g, bx = fresh_binder g b in
     let c = FStar.Syntax.Subst.subst_comp [DB(0, bx.binder_bv)] c in
     g, bx, c
 
-let open_comp_binders (g:env) (bs:binders) (c:comp) 
+let open_comp_binders (g:env) (bs:binders) (c:comp)
   : env & binders & comp
   = let g, bs, s = open_binders g bs in
     let c = FStar.Syntax.Subst.subst_comp s c in
@@ -126,14 +126,14 @@ let open_branch (g:env) (br:S.branch)
     g, (p, BU.map_option (Subst.subst s) wopt, Subst.subst s e)
 
 //br0 and br1 are expected to have equal patterns
-let open_branches_eq_pat (g:env) (br0 br1:S.branch) 
+let open_branches_eq_pat (g:env) (br0 br1:S.branch)
   = let (p0, wopt0, e0) = br0 in
-    let (_,  wopt1, e1) = br1 in  
+    let (_,  wopt1, e1) = br1 in
     let g, p0, s = open_pat g p0 in
     g,
     (p0, BU.map_option (Subst.subst s) wopt0, Subst.subst s e0),
-    (p0, BU.map_option (Subst.subst s) wopt1, Subst.subst s e1)    
-  
+    (p0, BU.map_option (Subst.subst s) wopt1, Subst.subst s e1)
+
 let precondition = option typ
 
 let success a = a & precondition
@@ -146,11 +146,11 @@ let relation_to_string = function
   | EQUALITY -> "=?="
   | SUBTYPING None -> "<:?"
   | SUBTYPING (Some tm) -> BU.format1 "( <:? %s)" (P.term_to_string tm)
-  
+
 type context_term =
   | CtxTerm : term -> context_term
   | CtxRel : term -> relation -> term -> context_term
-  
+
 let context_term_to_string (c:context_term) =
   match c with
   | CtxTerm term -> P.term_to_string term
@@ -204,9 +204,9 @@ type hash_entry = {
 }
 module THT = FStar.Syntax.TermHashTable
 type tc_table = THT.hashtable hash_entry
-let equal_term_for_hash t1 t2 = 
+let equal_term_for_hash t1 t2 =
   Profiling.profile (fun _ -> Hash.equal_term t1 t2) None "FStar.TypeChecker.Core.equal_term_for_hash"
-let equal_term t1 t2 =  
+let equal_term t1 t2 =
   Profiling.profile (fun _ -> Hash.equal_term t1 t2) None "FStar.TypeChecker.Core.equal_term"
 let table : tc_table = THT.create 1048576 //2^20
 type cache_stats_t = { hits : int; misses : int }
@@ -217,7 +217,7 @@ let record_cache_hit () =
 let record_cache_miss () =
    let cs = !cache_stats in
     cache_stats := { cs with misses = cs.misses + 1 }
-let reset_cache_stats () =     
+let reset_cache_stats () =
     cache_stats := { hits = 0; misses = 0 }
 let report_cache_stats () = !cache_stats
 let clear_memo_table () = THT.clear table
@@ -495,7 +495,7 @@ let weaken_with_guard_formula (p:FStar.TypeChecker.Common.guard_formula) (g:resu
     | Common.Trivial -> g
     | Common.NonTrivial p -> weaken p g
 
-let push_hypothesis (g:env) (h:term) = 
+let push_hypothesis (g:env) (h:term) =
     let bv = S.new_bv (Some h.pos) h in
     let b = S.mk_binder bv in
     fst (fresh_binder g b)
@@ -513,8 +513,8 @@ let no_guard (g:result 'a)
       | Inl (x, None) -> Inl (x, None)
       | Inl (x, Some g) -> fail (BU.format1 "Unexpected guard: %s" (P.term_to_string g)) ctx
       | err -> err
-      
-let equatable g t = 
+
+let equatable g t =
   t |> U.leftmost_head |> Rel.may_relate_with_logical_guard g.tcenv true
 
 let apply_predicate x p = fun e -> Subst.subst [NT(x.binder_bv, e)] p
@@ -561,7 +561,7 @@ let curry_application hd arg args p =
 
 let lookup (g:env) (e:term) : result (effect_label & typ) =
    match THT.lookup e table with
-   | None -> 
+   | None ->
      record_cache_miss ();
      fail "not in cache"
    | Some he ->
@@ -669,7 +669,7 @@ let guard_not_allowed
   : result bool
   = fun ctx -> Inl (ctx.no_guard, None)
 
-let default_norm_steps : Env.steps = 
+let default_norm_steps : Env.steps =
   let open Env in
   [ Primops;
     Weak;
@@ -678,9 +678,9 @@ let default_norm_steps : Env.steps =
     Unascribe;
     Eager_unfolding;
     Iota;
-    Exclude Zeta ] 
+    Exclude Zeta ]
 
-let debug g f = 
+let debug g f =
   if Env.debug g.tcenv (Options.Other "Core")
   then f ()
 
@@ -691,7 +691,7 @@ let side_to_string = function
   | Neither -> "Neither"
 
 let boolean_negation_simp b =
-  if Hash.equal_term b U.exp_false_bool 
+  if Hash.equal_term b U.exp_false_bool
   then None
   else Some (U.mk_boolean_negation b)
 
@@ -699,7 +699,7 @@ let combine_path_and_branch_condition (path_condition:term)
                                       (branch_condition:option term)
                                       (branch_equality:term)
   : term & term
-  = let this_path_condition = 
+  = let this_path_condition =
         let bc =
             match branch_condition with
             | None -> branch_equality
@@ -725,10 +725,10 @@ let maybe_relate_after_unfolding (g:Env.env) t0 t1 : side =
     | Tm_fvar fv -> Some (Env.delta_depth_of_fv g fv)
     | Tm_match {scrutinee=t} -> delta_depth_of_head t
     | _ -> None in
-  
+
   let dd0 = delta_depth_of_head t0 in
   let dd1 = delta_depth_of_head t1 in
-  
+
   match dd0, dd1 with
   | Some _, None -> Left
   | None, Some _ -> Right
@@ -755,7 +755,7 @@ let rec check_relation (g:env) (rel:relation) (t0 t1:typ)
           fail (BU.format2 "not equal terms: %s <> %s"
                            (P.term_to_string t0)
                            (P.term_to_string t1))
-        | _ -> 
+        | _ ->
           fail (BU.format2 "%s is not a subtype of %s"
                            (P.term_to_string t0)
                            (P.term_to_string t1))
@@ -770,7 +770,7 @@ let rec check_relation (g:env) (rel:relation) (t0 t1:typ)
                    (P.tag_of_term t0)
                    (P.term_to_string t0)
                    (rel_to_string rel)
-                   (P.tag_of_term t1)                   
+                   (P.tag_of_term t1)
                    (P.term_to_string t1);
     let! guard_not_ok = guard_not_allowed in
     let guard_ok = not guard_not_ok in
@@ -782,7 +782,7 @@ let rec check_relation (g:env) (rel:relation) (t0 t1:typ)
         | Tm_fvar fv0, Tm_fvar fv1 -> fv_eq fv0 fv1
         | Tm_name x0, Tm_name x1 -> bv_eq x0 x1
         | Tm_constant c0, Tm_constant c1 -> equal_term head0 head1
-        | Tm_type _, Tm_type _ 
+        | Tm_type _, Tm_type _
         | Tm_arrow _, Tm_arrow _
         | Tm_match _, Tm_match _ -> true
         | _ -> false
@@ -791,13 +791,13 @@ let rec check_relation (g:env) (rel:relation) (t0 t1:typ)
       maybe_relate_after_unfolding g.tcenv t0 t1 in
     let maybe_unfold_side side t0 t1
       : option (term & term)
-      = Profiling.profile (fun _ -> 
+      = Profiling.profile (fun _ ->
         match side with
         | Neither -> None
         | Both -> (
-          match N.maybe_unfold_head g.tcenv t0, 
+          match N.maybe_unfold_head g.tcenv t0,
                 N.maybe_unfold_head g.tcenv t1
-          with 
+          with
           | Some t0, Some t1 -> Some (t0, t1)
           | Some t0, None -> Some (t0, t1)
           | None, Some t1 -> Some (t0, t1)
@@ -853,7 +853,7 @@ let rec check_relation (g:env) (rel:relation) (t0 t1:typ)
 
         | Tm_refine _ ->
           U.flatten_refinement t
-          
+
         | _ -> t
     in
     let beta_iota_reduce t =
@@ -865,11 +865,11 @@ let rec check_relation (g:env) (rel:relation) (t0 t1:typ)
     let t0 = Subst.compress (beta_iota_reduce t0) in
     let t1 = Subst.compress (beta_iota_reduce t1) in
     let check_relation g rel t0 t1 =
-      with_context "check_relation" (Some (CtxRel t0 rel t1)) 
+      with_context "check_relation" (Some (CtxRel t0 rel t1))
         (fun _ -> check_relation g rel t0 t1)
     in
     if equal_term t0 t1 then return ()
-    else 
+    else
       match t0.n, t1.n with
       | Tm_type u0, Tm_type u1 ->
         // when g.allow_universe_instantiation ->
@@ -900,10 +900,10 @@ let rec check_relation (g:env) (rel:relation) (t0 t1:typ)
              else err ()
         )
         else maybe_unfold_and_retry t0 t1
-        
+
       | Tm_fvar _, Tm_fvar _ ->
         maybe_unfold_and_retry t0 t1
-      
+
 
       | Tm_refine {b=x0; phi=f0}, Tm_refine {b=x1; phi=f1} ->
         if head_matches x0.sort x1.sort
@@ -916,7 +916,7 @@ let rec check_relation (g:env) (rel:relation) (t0 t1:typ)
              | true ->
                with_binders [b] [u]
                  (check_relation g EQUALITY f0 f1)
-               
+
              | _ ->
                match rel with
                | EQUALITY ->
@@ -924,7 +924,7 @@ let rec check_relation (g:env) (rel:relation) (t0 t1:typ)
                    (handle_with
                       (check_relation g EQUALITY f0 f1)
                       (fun _ -> guard (U.mk_iff f0 f1)))
-                   
+
                | SUBTYPING (Some tm) ->
                  guard (Subst.subst [NT(b.binder_bv, tm)] (U.mk_imp f0 f1))
 
@@ -936,7 +936,7 @@ let rec check_relation (g:env) (rel:relation) (t0 t1:typ)
           | None -> fallback t0 t1
           | Some (t0, t1) ->
             let lhs = S.mk (Tm_refine {b={x0 with sort = t0}; phi=f0}) t0.pos in
-            let rhs = S.mk (Tm_refine {b={x1 with sort = t1}; phi=f1}) t1.pos in            
+            let rhs = S.mk (Tm_refine {b={x1 with sort = t1}; phi=f1}) t1.pos in
             check_relation g rel (U.flatten_refinement lhs) (U.flatten_refinement rhs)
         )
 
@@ -945,7 +945,7 @@ let rec check_relation (g:env) (rel:relation) (t0 t1:typ)
         then check_relation g rel x0.sort t1
         else (
           match maybe_unfold x0.sort t1 with
-          | None -> fallback t0 t1         
+          | None -> fallback t0 t1
           | Some (t0, t1) ->
             let lhs = S.mk (Tm_refine {b={x0 with sort = t0}; phi=f0}) t0.pos in
             check_relation g rel (U.flatten_refinement lhs) t1
@@ -970,7 +970,7 @@ let rec check_relation (g:env) (rel:relation) (t0 t1:typ)
                 (handle_with
                     (check_relation g EQUALITY U.t_true f1)
                     (fun _ -> guard f1))
-                   
+
             | SUBTYPING (Some tm) ->
                  guard (Subst.subst [NT(b1.binder_bv, tm)] f1)
 
@@ -979,16 +979,16 @@ let rec check_relation (g:env) (rel:relation) (t0 t1:typ)
         )
         else (
           match maybe_unfold t0 x1.sort with
-          | None -> fallback t0 t1         
+          | None -> fallback t0 t1
           | Some (t0, t1) ->
-            let rhs = S.mk (Tm_refine {b={x1 with sort = t1}; phi=f1}) t1.pos in          
+            let rhs = S.mk (Tm_refine {b={x1 with sort = t1}; phi=f1}) t1.pos in
             check_relation g rel t0 (U.flatten_refinement rhs)
-        )               
-      
+        )
+
       | Tm_uinst _, _
       | Tm_fvar _, _
       | Tm_app _, _
-      | _, Tm_uinst _ 
+      | _, Tm_uinst _
       | _, Tm_fvar _
       | _, Tm_app _ ->
         let head_matches = head_matches t0 t1 in
@@ -1020,7 +1020,7 @@ let rec check_relation (g:env) (rel:relation) (t0 t1:typ)
         let body1 = Subst.subst [DB(0, b0.binder_bv)] body1 in
         with_binders [b0] [u]
           (check_relation g EQUALITY body0 body1)
-      
+
       | Tm_arrow {bs=x0::x1::xs; comp=c0}, _ ->
         check_relation g rel (curry_arrow x0 (x1::xs) c0) t1
 
@@ -1117,10 +1117,10 @@ and check_relation_comp (g:env) rel (c0 c1:comp)
         then ct_eq res0 args0 res1 args1
         else (
           let ct0 = Env.unfold_effect_abbrev g.tcenv c0 in
-          let ct1 = Env.unfold_effect_abbrev g.tcenv c1 in          
+          let ct1 = Env.unfold_effect_abbrev g.tcenv c1 in
           if I.lid_equals ct0.effect_name ct1.effect_name
           then ct_eq ct0.result_typ ct0.effect_args ct1.result_typ ct1.effect_args
-          else fail (BU.format2 "Subcomp failed: Unequal computation types %s and %s" 
+          else fail (BU.format2 "Subcomp failed: Unequal computation types %s and %s"
                             (Ident.string_of_lid ct0.effect_name)
                             (Ident.string_of_lid ct1.effect_name))
         )
@@ -1139,7 +1139,7 @@ and check_relation_comp (g:env) rel (c0 c1:comp)
 and check_subtype (g:env) (e:option term) (t0 t1:typ)
   = fun ctx ->
     Profiling.profile
-      (fun () -> 
+      (fun () ->
         let rel = SUBTYPING e in
         with_context (if ctx.no_guard then "check_subtype(no_guard)" else "check_subtype")
                      (Some (CtxRel t0 rel t1))
@@ -1156,7 +1156,7 @@ and memo_check (g:env) (e:term)
       | Inl (res, None) ->
         insert g e (res, None);
         r
-          
+
       | Inl (res, Some guard) ->
         (match g.guard_handler with
          | None -> insert g e (res, Some guard); r
@@ -1175,16 +1175,16 @@ and memo_check (g:env) (e:term)
         match lookup g e ctx with
         | Inr _ -> //cache miss; check and insert
           check_then_memo g e ctx
-  
+
         | Inl (et, None) -> //cache hit with no guard; great, just return
           Inl (et, None)
-  
+
         | Inl (et, Some pre) -> //cache hit with a guard
           match g.guard_handler with
           | None -> Inl (et, Some pre) //if there's no guard handler, then just return
           | Some _ ->
             //otherwise check then memo, since this can
-            //repopulate the cache with a "better" entry that has no guard        
+            //repopulate the cache with a "better" entry that has no guard
             //But, don't read the cache again, since many subsequent lookups
             //are likely to be hits with a guard again
             check_then_memo { g with should_read_cache = false } e ctx
@@ -1193,7 +1193,7 @@ and memo_check (g:env) (e:term)
 and check (msg:string) (g:env) (e:term)
   : result (effect_label & typ)
   = with_context msg (Some (CtxTerm e)) (fun _ -> memo_check g e)
-    
+
 (*  G |- e : Tot t | pre *)
 and check' (g:env) (e:term)
   : result (effect_label & typ) =
@@ -1284,37 +1284,39 @@ and check' (g:env) (e:term)
       return (E_TOTAL, mk_type (S.U_max (u::us)))
     )
 
-  | Tm_app {hd; args=[(t1, None); (t2, None)]}
-    when TcUtil.short_circuit_head hd ->
-    let! eff_hd, t_hd = check "app head" g hd in
-    let! x, eff_arr1, s1 = is_arrow g t_hd in    
-    let! eff_arg1, t_t1 = check "app arg" g t1 in
-    with_context "operator arg1" None (fun _ -> check_subtype g (Some t1) t_t1 x.binder_bv.sort) ;!    
-    let s1 = Subst.subst [NT(x.binder_bv, t1)] s1 in
-    let! y, eff_arr2, s2 = is_arrow g s1 in
-    let guard_formula = TcUtil.short_circuit hd [(t1, None)] in
-    let g' = 
-      match guard_formula with
-      | Common.Trivial -> g
-      | Common.NonTrivial gf -> push_hypothesis g gf
+  | Tm_app _ -> (
+    let rec check_app_arg (eff_hd, t_hd) (arg, arg_qual) =
+      let! x, eff_arr, t' = is_arrow g t_hd in
+      let! eff_arg, t_arg = check "app arg" g arg in
+      with_context "app subtyping" None (fun _ -> check_subtype g (Some arg) t_arg x.binder_bv.sort) ;!
+      with_context "app arg qual" None (fun _ -> check_arg_qual arg_qual x.binder_qual) ;!
+      return (join_eff eff_hd (join_eff eff_arr eff_arg), Subst.subst [NT(x.binder_bv, arg)] t')
     in
-    let! eff_arg2, t_t2 = weaken_with_guard_formula guard_formula (check "app arg" g' t2) in    
-    with_context "operator arg2" None (fun _ -> check_subtype g' (Some t2) t_t2 y.binder_bv.sort) ;!
-    return (join_eff_l [eff_hd; eff_arr1; eff_arr2; eff_arg1; eff_arg2],
-            Subst.subst [NT(y.binder_bv, t2)] s2)
-
-  | Tm_app {hd; args=[(arg, arg_qual)]} ->
-    let! eff_hd, t = check "app head" g hd in
-    let! x, eff_arr, t' = is_arrow g t in
-    let! eff_arg, t_arg = check "app arg" g arg in
-    with_context "app subtyping" None (fun _ -> check_subtype g (Some arg) t_arg x.binder_bv.sort) ;!
-    with_context "app arg qual" None (fun _ -> check_arg_qual arg_qual x.binder_qual) ;!
-    return (join_eff eff_hd (join_eff eff_arr eff_arg), Subst.subst [NT(x.binder_bv, arg)] t')
-
-  | Tm_app {hd; args=arg::args} ->
-    let head = S.mk (Tm_app {hd; args=[arg]}) e.pos in
-    let t = S.mk (Tm_app {hd=head; args}) e.pos in
-    memo_check g t
+    let check_app hd args =
+       let! eff_hd, t = check "app head" g hd in
+       fold check_app_arg (eff_hd, t) args
+    in
+    let hd, args = U.head_and_args_full e in
+    match args with
+    | [(t1, None); (t2, None)] when TcUtil.short_circuit_head hd ->
+      let! eff_hd, t_hd = check "app head" g hd in
+      let! x, eff_arr1, s1 = is_arrow g t_hd in
+      let! eff_arg1, t_t1 = check "app arg" g t1 in
+      with_context "operator arg1" None (fun _ -> check_subtype g (Some t1) t_t1 x.binder_bv.sort) ;!
+      let s1 = Subst.subst [NT(x.binder_bv, t1)] s1 in
+      let! y, eff_arr2, s2 = is_arrow g s1 in
+      let guard_formula = TcUtil.short_circuit hd [(t1, None)] in
+      let g' =
+        match guard_formula with
+        | Common.Trivial -> g
+        | Common.NonTrivial gf -> push_hypothesis g gf
+      in
+      let! eff_arg2, t_t2 = weaken_with_guard_formula guard_formula (check "app arg" g' t2) in
+      with_context "operator arg2" None (fun _ -> check_subtype g' (Some t2) t_t2 y.binder_bv.sort) ;!
+      return (join_eff_l [eff_hd; eff_arr1; eff_arr2; eff_arg1; eff_arg2],
+             Subst.subst [NT(y.binder_bv, t2)] s2)
+    | _ -> check_app hd args
+  )
 
   | Tm_ascribed {tm=e; asc=(Inl t, _, eq)} ->
     let! eff, te = check "ascription head" g e in
@@ -1369,9 +1371,9 @@ and check' (g:env) (e:term)
 
            | Some et ->
              match boolean_negation_simp path_condition with
-             | None -> 
+             | None ->
                return et
-               
+
              | Some g ->
                guard (U.b2t g) ;!
                return et)
@@ -1383,7 +1385,7 @@ and check' (g:env) (e:term)
           let pat_sc_eq =
             U.mk_eq2 u_sc t_sc sc
             (PatternUtils.raw_pat_as_exp g.tcenv p |> must |> fst) in
-          let this_path_condition, next_path_condition = 
+          let this_path_condition, next_path_condition =
               combine_path_and_branch_condition path_condition branch_condition pat_sc_eq
           in
           let g' = push_binders g bs in
@@ -1422,7 +1424,7 @@ and check' (g:env) (e:term)
         | _ ->
           return None
     in
-    let! eff_br, t_br = 
+    let! eff_br, t_br =
       let ctx =
         match branch_typ_opt with
         | None -> None
@@ -1447,9 +1449,9 @@ and check' (g:env) (e:term)
       = match branches with
         | [] ->
           (match boolean_negation_simp path_condition with
-           | None -> 
+           | None ->
              return acc_eff
-             
+
            | Some g ->
              guard (U.b2t g) ;!
              return acc_eff)
@@ -1465,7 +1467,7 @@ and check' (g:env) (e:term)
               combine_path_and_branch_condition path_condition branch_condition pat_sc_eq
           in
           let g' = push_binders g bs in
-          let g' = push_hypothesis g' this_path_condition in 
+          let g' = push_hypothesis g' this_path_condition in
           let! eff_br, tbr =
             with_binders bs us
               (weaken
@@ -1536,7 +1538,7 @@ and check_comp (g:env) (c:comp)
              S.mk_Tm_app head ((as_arg ct.result_typ)::ct.effect_args) ct.result_typ.pos in
            let! _, t = check "effectful comp" g effect_app_tm in
            with_context "comp fully applied" None (fun _ -> check_subtype g None t S.teff);!
-           let c_lid = Env.norm_eff_name g.tcenv ct.effect_name in           
+           let c_lid = Env.norm_eff_name g.tcenv ct.effect_name in
            let is_total = Env.lookup_effect_quals g.tcenv c_lid |> List.existsb (fun q -> q = S.TotalEffect) in
            if not is_total
            then return S.U_zero  //if it is a non-total effect then u0
@@ -1621,7 +1623,7 @@ and check_pat (g:env) (p:pat) (t_sc:typ) : result (binders & universes) =
     let!_ = no_guard (check_scrutinee_pattern_type_compatible g (unrefine_tsc t_sc) t_pat) in
 
     return (bs, us)
-  
+
   | _ -> fail "check_pat called with a dot pattern"
 
 and check_scrutinee_pattern_type_compatible (g:env) (t_sc t_pat:typ)
@@ -1675,10 +1677,10 @@ and pattern_branch_condition (g:env)
                              (pat:pat)
   : result (option term)
   = match pat.v with
-    | Pat_var _ -> 
+    | Pat_var _ ->
       return None
-    | Pat_constant c -> 
-      let const_exp = 
+    | Pat_constant c ->
+      let const_exp =
         match PatternUtils.raw_pat_as_exp g.tcenv pat with
         | None -> failwith "Impossible"
         | Some (e, _) -> e
@@ -1712,18 +1714,18 @@ and pattern_branch_condition (g:env)
         then let discriminator = U.mk_discriminator fv.fv_name.v in
              match Env.try_lookup_lid g.tcenv discriminator with
              | None ->
-               // We don't use the discriminator if we are typechecking it             
+               // We don't use the discriminator if we are typechecking it
                None
              | _ ->
                Some (mk_head_discriminator())
         else None //single constructor inductives do not need a discriminator
       in
       let! sub_term_guards =
-          mapi 
+          mapi
           (fun i (pi, _) ->
             match pi.v with
             | Pat_dot_term _
-            | Pat_var _ -> 
+            | Pat_var _ ->
               return None
             | _ ->
               let scrutinee_sub_term = mk_ith_projector i in
@@ -1735,12 +1737,12 @@ and pattern_branch_condition (g:env)
       | [] -> return None
       | guards -> return (Some (U.mk_and_l guards))
 
-let initial_env g gh = 
-  let max_index = 
+let initial_env g gh =
+  let max_index =
       List.fold_left
         (fun index b ->
           match b with
-          | Binding_var x -> 
+          | Binding_var x ->
             if x.index > index
             then x.index
             else index
@@ -1752,15 +1754,15 @@ let initial_env g gh =
     max_binder_index = max_index;
     guard_handler = gh;
     should_read_cache = true }
-   
+
 let check_term_top g e topt (must_tot:bool) (gh:option guard_handler_t)
   : result (option (effect_label & typ))
   = let g = initial_env g gh in
     let! eff_te = check "top" g e in
     match topt with
     | None -> return (Some eff_te)
-    | Some t -> 
-      let target_comp = 
+    | Some t ->
+      let target_comp =
         if must_tot || fst eff_te = E_TOTAL
         then S.mk_Total t
         else S.mk_GTotal t
@@ -1774,7 +1776,7 @@ let check_term_top g e topt (must_tot:bool) (gh:option guard_handler_t)
       return None
 
 let simplify_steps =
-    [Env.Beta; 
+    [Env.Beta;
      Env.UnfoldUntil delta_constant;
      Env.UnfoldQual ["unfold"];
      Env.UnfoldOnly [PC.pure_wp_monotonic_lid; PC.pure_wp_monotonic0_lid];
@@ -1784,31 +1786,31 @@ let simplify_steps =
 
 
 let check_term_top_gh g e topt (must_tot:bool) (gh:option guard_handler_t)
-  = 
+  =
     if Env.debug g (Options.Other "CoreEq")
     then BU.print1 "(%s) Entering core ... \n"
                    (BU.string_of_int (get_goal_ctr()));
-                   
+
     if Env.debug g (Options.Other "Core")
      || Env.debug g (Options.Other "CoreTop")
     then BU.print3 "(%s) Entering core with %s <: %s\n"
-                   (BU.string_of_int (get_goal_ctr()))    
+                   (BU.string_of_int (get_goal_ctr()))
                    (P.term_to_string e)
                    (match topt with None -> "" | Some t -> P.term_to_string t);
     THT.reset_counters table;
     reset_cache_stats();
     let ctx = { no_guard = false; error_context = [("Top", None)] } in
-    let res = 
-      Profiling.profile 
-        (fun () -> 
+    let res =
+      Profiling.profile
+        (fun () ->
           match check_term_top g e topt must_tot gh ctx with
           | Inl (et, g) -> Inl (et, g)
           | Inr err -> Inr err)
         None
-        "FStar.TypeChecker.Core.check_term_top"        
+        "FStar.TypeChecker.Core.check_term_top"
     in
     (
-    let res = 
+    let res =
       match res with
       | Inl (et, Some guard0) ->
         // Options.push();
@@ -1817,7 +1819,7 @@ let check_term_top_gh g e topt (must_tot:bool) (gh:option guard_handler_t)
         // Options.pop();
         if Env.debug g (Options.Other "CoreExit")
         || Env.debug g (Options.Other "Core")
-        || Env.debug g (Options.Other "CoreTop")        
+        || Env.debug g (Options.Other "CoreTop")
         then begin
           BU.print3 "(%s) Exiting core: Simplified guard from {{%s}} to {{%s}}\n"
             (BU.string_of_int (get_goal_ctr()))
@@ -1835,15 +1837,15 @@ let check_term_top_gh g e topt (must_tot:bool) (gh:option guard_handler_t)
         Inl (et, Some guard)
 
       | Inl _ ->
-        if Env.debug g (Options.Other "Core")        
-        ||  Env.debug g (Options.Other "CoreTop")        
+        if Env.debug g (Options.Other "Core")
+        ||  Env.debug g (Options.Other "CoreTop")
         then BU.print1 "(%s) Exiting core (ok)\n"
                     (BU.string_of_int (get_goal_ctr()));
         res
 
       | Inr _ ->
-        if Env.debug g (Options.Other "Core")        
-        ||  Env.debug g (Options.Other "CoreTop")                
+        if Env.debug g (Options.Other "Core")
+        ||  Env.debug g (Options.Other "CoreTop")
         then BU.print1 "(%s) Exiting core (failed)\n"
                        (BU.string_of_int (get_goal_ctr()));
         res
@@ -1859,7 +1861,7 @@ let check_term_top_gh g e topt (must_tot:bool) (gh:option guard_handler_t)
     res
     )
 
-let check_term g e t must_tot = 
+let check_term g e t must_tot =
   match check_term_top_gh g e (Some t) must_tot None with
   | Inl (_, g) -> Inl g
   | Inr err -> Inr err