Mercurial > urweb
comparison src/elab_env.sml @ 1639:6c00d8af6239
Add a new scoping check for unification variables, to fix a type inference bug
author | Adam Chlipala <adam@chlipala.net> |
---|---|
date | Sun, 18 Dec 2011 11:29:13 -0500 |
parents | 287604b4a08d |
children | fca4a6d05ac1 |
comparison
equal
deleted
inserted
replaced
1638:3bf727a08db8 | 1639:6c00d8af6239 |
---|---|
482 | 482 |
483 fun class_name_in (c, _) = | 483 fun class_name_in (c, _) = |
484 case c of | 484 case c of |
485 CNamed n => SOME (ClNamed n) | 485 CNamed n => SOME (ClNamed n) |
486 | CModProj x => SOME (ClProj x) | 486 | CModProj x => SOME (ClProj x) |
487 | CUnif (_, _, _, _, ref (SOME c)) => class_name_in c | 487 | CUnif (_, _, _, _, ref (Known c)) => class_name_in c |
488 | _ => NONE | 488 | _ => NONE |
489 | 489 |
490 fun isClass (env : env) c = | 490 fun isClass (env : env) c = |
491 let | 491 let |
492 fun find NONE = false | 492 fun find NONE = false |
496 end | 496 end |
497 | 497 |
498 fun class_head_in c = | 498 fun class_head_in c = |
499 case #1 c of | 499 case #1 c of |
500 CApp (f, _) => class_head_in f | 500 CApp (f, _) => class_head_in f |
501 | CUnif (_, _, _, _, ref (SOME c)) => class_head_in c | 501 | CUnif (_, _, _, _, ref (Known c)) => class_head_in c |
502 | _ => class_name_in c | 502 | _ => class_name_in c |
503 | 503 |
504 exception Unify | 504 exception Unify |
505 | 505 |
506 fun unifyKinds (k1, k2) = | 506 fun unifyKinds (k1, k2) = |
510 | (KName, KName) => () | 510 | (KName, KName) => () |
511 | (KRecord k1, KRecord k2) => unifyKinds (k1, k2) | 511 | (KRecord k1, KRecord k2) => unifyKinds (k1, k2) |
512 | (KUnit, KUnit) => () | 512 | (KUnit, KUnit) => () |
513 | (KTuple ks1, KTuple ks2) => (ListPair.appEq unifyKinds (ks1, ks2) | 513 | (KTuple ks1, KTuple ks2) => (ListPair.appEq unifyKinds (ks1, ks2) |
514 handle ListPair.UnequalLengths => raise Unify) | 514 handle ListPair.UnequalLengths => raise Unify) |
515 | (KUnif (_, _, ref (SOME k1)), _) => unifyKinds (k1, k2) | 515 | (KUnif (_, _, ref (KKnown k1)), _) => unifyKinds (k1, k2) |
516 | (_, KUnif (_, _, ref (SOME k2))) => unifyKinds (k1, k2) | 516 | (_, KUnif (_, _, ref (KKnown k2))) => unifyKinds (k1, k2) |
517 | (KRel n1, KRel n2) => if n1 = n2 then () else raise Unify | 517 | (KRel n1, KRel n2) => if n1 = n2 then () else raise Unify |
518 | (KFun (_, k1), KFun (_, k2)) => unifyKinds (k1, k2) | 518 | (KFun (_, k1), KFun (_, k2)) => unifyKinds (k1, k2) |
519 | _ => raise Unify | 519 | _ => raise Unify |
520 | 520 |
521 fun eqCons (c1, c2) = | 521 fun eqCons (c1, c2) = |
522 case (#1 c1, #1 c2) of | 522 case (#1 c1, #1 c2) of |
523 (CUnif (nl, _, _, _, ref (SOME c1)), _) => eqCons (mliftConInCon nl c1, c2) | 523 (CUnif (nl, _, _, _, ref (Known c1)), _) => eqCons (mliftConInCon nl c1, c2) |
524 | (_, CUnif (nl, _, _, _, ref (SOME c2))) => eqCons (c1, mliftConInCon nl c2) | 524 | (_, CUnif (nl, _, _, _, ref (Known c2))) => eqCons (c1, mliftConInCon nl c2) |
525 | 525 |
526 | (CRel n1, CRel n2) => if n1 = n2 then () else raise Unify | 526 | (CRel n1, CRel n2) => if n1 = n2 then () else raise Unify |
527 | 527 |
528 | (TFun (d1, r1), TFun (d2, r2)) => (eqCons (d1, d2); eqCons (r1, r2)) | 528 | (TFun (d1, r1), TFun (d2, r2)) => (eqCons (d1, d2); eqCons (r1, r2)) |
529 | (TCFun (_, _, k1, r1), TCFun (_, _, k2, r2)) => (unifyKinds (k1, k2); eqCons (r1, r2)) | 529 | (TCFun (_, _, k1, r1), TCFun (_, _, k2, r2)) => (unifyKinds (k1, k2); eqCons (r1, r2)) |
567 | 567 |
568 fun unifyCons (hnorm : con -> con) rs = | 568 fun unifyCons (hnorm : con -> con) rs = |
569 let | 569 let |
570 fun unify d (c1, c2) = | 570 fun unify d (c1, c2) = |
571 case (#1 (hnorm c1), #1 (hnorm c2)) of | 571 case (#1 (hnorm c1), #1 (hnorm c2)) of |
572 (CUnif (nl, _, _, _, ref (SOME c1)), _) => unify d (mliftConInCon nl c1, c2) | 572 (CUnif (nl, _, _, _, ref (Known c1)), _) => unify d (mliftConInCon nl c1, c2) |
573 | (_, CUnif (nl, _, _, _, ref (SOME c2))) => unify d (c1, mliftConInCon nl c2) | 573 | (_, CUnif (nl, _, _, _, ref (Known c2))) => unify d (c1, mliftConInCon nl c2) |
574 | 574 |
575 | (CUnif _, _) => () | 575 | (CUnif _, _) => () |
576 | 576 |
577 | (c1', CRel n2) => | 577 | (c1', CRel n2) => |
578 if n2 < d then | 578 if n2 < d then |
661 0 | 661 0 |
662 | 662 |
663 exception Bad of con * con | 663 exception Bad of con * con |
664 | 664 |
665 val hasUnif = U.Con.exists {kind = fn _ => false, | 665 val hasUnif = U.Con.exists {kind = fn _ => false, |
666 con = fn CUnif (_, _, _, _, ref NONE) => true | 666 con = fn CUnif (_, _, _, _, ref (Unknown _)) => true |
667 | _ => false} | 667 | _ => false} |
668 | 668 |
669 fun startsWithUnif c = | 669 fun startsWithUnif c = |
670 let | 670 let |
671 fun firstArg (c, acc) = | 671 fun firstArg (c, acc) = |
695 let | 695 let |
696 val (f, equate) = generalize f | 696 val (f, equate) = generalize f |
697 | 697 |
698 fun isRecord () = | 698 fun isRecord () = |
699 let | 699 let |
700 val rk = ref NONE | 700 val rk = ref (KUnknown (fn _ => true)) |
701 val k = (KUnif (loc, "k", rk), loc) | 701 val k = (KUnif (loc, "k", rk), loc) |
702 val r = ref NONE | 702 val r = ref (Unknown (fn _ => true)) |
703 val rc = (CUnif (0, loc, k, "x", r), loc) | 703 val rc = (CUnif (0, loc, k, "x", r), loc) |
704 in | 704 in |
705 ((CApp (f, rc), loc), | 705 ((CApp (f, rc), loc), |
706 fn () => (if consEq (rc, x) then | 706 fn () => (if consEq (rc, x) then |
707 true | 707 true |