diff src/elaborate.sml @ 1303:c7b9a33c26c8

Hopeful fix for the Great Unification Bug
author Adam Chlipala <adam@chlipala.net>
date Sun, 10 Oct 2010 14:41:03 -0400
parents d008c4c43a0a
children f0afe61a6f8b
line wrap: on
line diff
--- a/src/elaborate.sml	Sun Oct 10 13:07:38 2010 -0400
+++ b/src/elaborate.sml	Sun Oct 10 14:41:03 2010 -0400
@@ -207,7 +207,7 @@
                      "U" ^ Int.toString (n - 26)
      in
          count := n + 1;
-         (L'.CUnif (loc, k, s, ref NONE), loc)
+         (L'.CUnif (0, loc, k, s, ref NONE), loc)
      end
 
  end
@@ -495,7 +495,7 @@
        | _ => false
  fun cunifsRemain c =
      case c of
-         L'.CUnif (loc, _, _, ref NONE) => SOME loc
+         L'.CUnif (_, loc, _, _, ref NONE) => SOME loc
        | _ => NONE
 
  val kunifsInDecl = U.Decl.exists {kind = kunifsRemain,
@@ -516,13 +516,11 @@
 
  fun occursCon r =
      U.Con.exists {kind = fn _ => false,
-                   con = fn L'.CUnif (_, _, _, r') => r = r'
+                   con = fn L'.CUnif (_, _, _, _, r') => r = r'
                           | _ => false}
 
  exception CUnify' of cunify_error
 
- exception SynUnif = E.SynUnif
-
  type record_summary = {
       fields : (L'.con * L'.con) list,
       unifs : (L'.con * L'.con option ref) list,
@@ -588,7 +586,7 @@
             | k => raise CUnify' (CKindof (k, c, "tuple")))
 
        | L'.CError => kerror
-       | L'.CUnif (_, k, _, _) => k
+       | L'.CUnif (_, _, k, _, _) => k
 
        | L'.CKAbs (x, c) => (L'.KFun (x, kindof (E.pushKRel env x) c), loc)
        | L'.CKApp (c, k) =>
@@ -644,7 +642,7 @@
             | k => raise CUnify' (CKindof (k, c, "tuple")))*)
 
        | L'.CError => false
-       | L'.CUnif (_, k, _, _) => #1 k = L'.KUnit
+       | L'.CUnif (_, _, k, _, _) => #1 k = L'.KUnit
 
        | L'.CKAbs _ => false
        | L'.CKApp _ => false
@@ -701,8 +699,8 @@
                       unifs = #unifs s1 @ #unifs s2,
                       others = #others s1 @ #others s2}
                  end
-               | (L'.CUnif (_, _, _, ref (SOME c)), _) => recordSummary env c
-               | c' as (L'.CUnif (_, _, _, r), _) => {fields = [], unifs = [(c', r)], others = []}
+               | (L'.CUnif (nl, _, _, _, ref (SOME c)), _) => recordSummary env (E.mliftConInCon nl c)
+               | c' as (L'.CUnif (0, _, _, _, r), _) => {fields = [], unifs = [(c', r)], others = []}
                | c' => {fields = [], unifs = [], others = [c']}
      in
          sum
@@ -735,8 +733,8 @@
  and unifySummaries env (loc, k, s1 : record_summary, s2 : record_summary) =
      let
          (*val () = eprefaces "Summaries" [("loc", PD.string (ErrorMsg.spanToString loc)),
-                                           ("#1", p_summary env s1),
-                                           ("#2", p_summary env s2)]*)
+                                         ("#1", p_summary env s1),
+                                         ("#2", p_summary env s2)]*)
 
          fun eatMatching p (ls1, ls2) =
              let
@@ -922,7 +920,7 @@
                              unfold (r2, c2');
                              unifyCons env loc r (L'.CConcat (r1, r2), loc)
                          end
-                       | L'.CUnif (_, _, _, ur) =>
+                       | L'.CUnif (0, _, _, _, ur) =>
                          ur := SOME (L'.CApp ((L'.CApp ((L'.CMap (dom, ran), loc), f), loc), r), loc)
                        | _ => raise ex
              in
@@ -970,7 +968,7 @@
                                      onFail ()
                          in
                              case #1 (hnormCon env c2) of
-                                 L'.CUnif (_, k, _, r) =>
+                                 L'.CUnif (0, _, k, _, r) =>
                                  (case #1 (hnormKind k) of
                                       L'.KTuple ks =>
                                       let
@@ -986,7 +984,7 @@
                        | _ => onFail ()
              in
                  case #1 (hnormCon env c1) of
-                     L'.CUnif (_, k, _, r) =>
+                     L'.CUnif (0, _, k, _, r) =>
                      (case #1 (hnormKind k) of
                           L'.KTuple ks =>
                           let
@@ -1002,7 +1000,7 @@
 
          fun projSpecial2 (c2, n2, onFail) =
              case #1 (hnormCon env c2) of
-                 L'.CUnif (_, k, _, r) =>
+                 L'.CUnif (0, _, k, _, r) =>
                  (case #1 (hnormKind k) of
                       L'.KTuple ks =>
                       let
@@ -1035,19 +1033,24 @@
            | (L'.CConcat _, _) => isRecord ()
            | (_, L'.CConcat _) => isRecord ()
 
-           | (L'.CUnif (_, k1, _, r1), L'.CUnif (_, k2, _, r2)) =>
-             if r1 = r2 then
+           | (L'.CUnif (nl1, loc1, k1, _, r1), L'.CUnif (nl2, loc2, k2, _, r2)) =>
+             if r1 = r2 andalso nl1 = nl2 then
                  ()
-             else
+             else if nl1 = 0 then
                  (unifyKinds env k1 k2;
                   r1 := SOME c2All)
-
-           | (L'.CUnif (_, _, _, r), _) =>
+             else if nl2 = 0 then
+                 (unifyKinds env k1 k2;
+                  r2 := SOME c2All)
+             else
+                 err (fn _ => TooLifty (loc1, loc2))
+
+           | (L'.CUnif (0, _, _, _, r), _) =>
              if occursCon r c2All then
                  err COccursCheckFailed
              else
                  r := SOME c2All
-           | (_, L'.CUnif (_, _, _, r)) =>
+           | (_, L'.CUnif (0, _, _, _, r)) =>
              if occursCon r c1All then
                  err COccursCheckFailed
              else
@@ -1167,6 +1170,11 @@
                    | _ => false)
               | _ => false
 
+ fun subConInCon env x y =
+     ElabOps.subConInCon x y
+     handle SubUnif => (cunifyError env (TooUnify (#2 x, y));
+                        cerror)
+
  fun elabHead (env, denv) infer (e as (_, loc)) t =
      let
          fun unravelKind (t, e) =
@@ -1195,7 +1203,7 @@
                  let
                      val u = cunif (loc, k)
 
-                     val t'' = subConInCon (0, u) t'
+                     val t'' = subConInCon env (0, u) t'
                  in
                      unravel (t'', (L'.ECApp (e, u), loc))
                  end
@@ -1282,7 +1290,7 @@
                     val k = (L'.KType, loc)
                     val unifs = map (fn _ => cunif (loc, k)) xs
                     val nxs = length unifs - 1
-                    val t = ListUtil.foldli (fn (i, u, t) => subConInCon (nxs - i, u) t) t unifs
+                    val t = ListUtil.foldli (fn (i, u, t) => subConInCon env (nxs - i, u) t) t unifs
                     val dn = foldl (fn (u, dn) => (L'.CApp (dn, u), loc)) dn unifs
                 in
                     ignore (checkPatCon env p' pt t);
@@ -1469,7 +1477,7 @@
 
                     val (t1, args) = unapp (hnormCon env q1, [])
                     val t1 = hnormCon env t1
-                    fun doSub t = foldl (fn (arg, t) => subConInCon (0, arg) t) t args
+                    fun doSub t = foldl (fn (arg, t) => subConInCon env (0, arg) t) t args
 
                     fun dtype (dtO, names) =
                         let
@@ -1653,7 +1661,7 @@
             (L'.TFun (c1, c2), loc)
         end
       | L'.TCFun (expl, x, k, c1) => (L'.TCFun (expl, x, k, normClassConstraint env c1), loc)
-      | L'.CUnif (_, _, _, ref (SOME c)) => normClassConstraint env c
+      | L'.CUnif (nl, _, _, _, ref (SOME c)) => normClassConstraint env (E.mliftConInCon nl c)
       | _ => unmodCon env (c, loc)
 
 fun findHead e e' =
@@ -1863,9 +1871,7 @@
                   | L'.TCFun (_, x, k, eb) =>
                     let
                         val () = checkKind env c' ck k
-                        val eb' = subConInCon (0, c') eb
-                            handle SynUnif => (expError env (Unif ("substitution", loc, eb));
-                                               cerror)
+                        val eb' = subConInCon env (0, c') eb
 
                         val ef = (L'.ECApp (e', c'), loc)
                         val (ef, eb', gs3) =
@@ -3303,7 +3309,7 @@
                               (SOME c1, SOME c2) => SOME (L.CConcat (c1, c2), loc)
                             | _ => NONE)
                        | L'.CUnit => SOME (L.CUnit, loc)
-                       | L'.CUnif (_, _, _, ref (SOME c)) => decompileCon env c
+                       | L'.CUnif (nl, _, _, _, ref (SOME c)) => decompileCon env (E.mliftConInCon nl c)
 
                        | _ => NONE