shithub: mc

Download patch

ref: 8c6a9b940b85f46056519373fcca1d9aefd49eec
parent: 25e411cf4abf1437c5e7bfebbe8e1190a921d2dd
author: Ori Bernstein <[email protected]>
date: Mon Aug 19 21:31:51 EDT 2013

Unify generics with names.

--- a/parse/htab.c
+++ b/parse/htab.c
@@ -195,7 +195,7 @@
 
 int streq(void *a, void *b)
 {
-    return !strcmp(a, b);
+    return a == b || !strcmp(a, b);
 }
 
 ulong ptrhash(void *key)
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -99,6 +99,14 @@
     return s;
 }
 
+
+static int nameeq(Node *a, Node *b)
+{
+    if (a == b)
+        return 1;
+    return streq(a->name.ns, b->name.ns) && streq(a->name.name, b->name.name);
+}
+
 /* Set a scope's enclosing scope up correctly.
  * We don't do this in the parser for some reason. */
 static void setsuper(Stab *st, Stab *super)
@@ -530,6 +538,11 @@
     return 2;
 }
 
+static int hasparam(Type *t)
+{
+    return t->type == Tygeneric || t->type == Tyname;
+}
+
 /* Unifies two types, or errors if the types are not unifiable. */
 static Type *unify(Inferstate *st, Node *ctx, Type *a, Type *b)
 {
@@ -574,11 +587,22 @@
      * Otherwise, match up subtypes. */
     if ((a->type == b->type || idxhacked(a, b)) && tyrank(a) != 0) {
         if (a->nsub != b->nsub)
-            fatal(ctx->line, "%s has wrong subtype count for %s (got %d, expected %d) near %s\n",
+            fatal(ctx->line, "%s has wrong subtype count for %s (got %d, expected %d) near %s",
                   tystr(a), tystr(b), a->nsub, b->nsub, ctxstr(st, ctx));
         for (i = 0; i < b->nsub; i++)
             unify(st, ctx, a->sub[i], b->sub[i]);
         r = b;
+    } else if (hasparam(a) && hasparam(b)) {
+        /* Only Tygeneric and Tyname should be able to unify. And they
+         * should have the same names for this to be true. */
+        if (!nameeq(a->name, b->name))
+            fatal(ctx->line, "%s incompatible with %s near %s",
+                  tystr(a), tystr(b), ctxstr(st, ctx));
+        if (a->nparam != b->nparam)
+            fatal(ctx->line, "%s has wrong parameter list for %s near %s",
+                  tystr(a), tystr(b), ctxstr(st, ctx));
+        for (i = 0; i < a->nparam; i++)
+            unify(st, ctx, a->param[i], b->param[i]);
     } else if (a->type != Tyvar) {
         fatal(ctx->line, "%s incompatible with %s near %s",
               tystr(a), tystr(b), ctxstr(st, ctx));