浏览代码

fix GADT handling of enum field parameters (closes #4578)

Simon Krajewski 10 年之前
父节点
当前提交
009e1594e2
共有 2 个文件被更改,包括 46 次插入1 次删除
  1. 3 1
      matcher.ml
  2. 43 0
      tests/unit/src/unit/issues/Issue4578.hx

+ 3 - 1
matcher.ml

@@ -397,7 +397,9 @@ let to_pattern ctx e t =
 						[]
 				in
 				let el = loop2 0 el tl in
-				List.iter2 (fun m (_,t) -> match follow m with TMono _ -> Type.unify m t | _ -> ()) monos ef.ef_params;
+				(* We want to change the original monomorphs back to type parameters, but we don't want to do that
+				   if they are bound to other monomorphs (issue #4578). *)
+				List.iter2 (fun m (_,t) -> match m,follow m with TMono m1, TMono m2 when m1 == m2 -> Type.unify m t | _ -> ()) monos ef.ef_params;
 				pctx.pc_is_complex <- true;
 				mk_con_pat (CEnum(en,ef)) el r p
 			| _ -> perror p)

+ 43 - 0
tests/unit/src/unit/issues/Issue4578.hx

@@ -0,0 +1,43 @@
+package unit.issues;
+
+private class TList {}
+private class TCons<U,V:TList> extends TList {}
+private class TNil extends TList {}
+
+private enum Stack<L:TList> {
+    Nil: Stack<TNil>;
+    Cons<X,L:TList>(x: X, xs: Stack<L>): Stack<TCons<X,L>>;
+}
+
+private interface Instr<L1:TList,L2:TList> {
+    function denote(s: Stack<L1>): Stack<L2>;
+}
+
+private class IUnOp<X,Y,S:TList> implements Instr<TCons<X,S>,TCons<Y,S>> {
+    var f: X->Y;
+
+    public function new(f) {
+        this.f = f;
+    }
+
+    public function denote(s: Stack<TCons<X,S>>): Stack<TCons<Y,S>> {
+        return switch(s) {
+            case Cons(x, s):
+                Cons(f(x), s);
+        }
+    }
+}
+
+class Issue4578 extends Test {
+	function test() {
+		var i = new IUnOp(function(x) return x * 2);
+		var v = i.denote(Cons(10, Nil));
+		eq(20, getHead(v));
+	}
+
+	static function getHead<S, T:TList>(s:Stack<TCons<S,T>>):S {
+		return switch (s) {
+			case Cons(x, _): x;
+		}
+	}
+}