shithub: mc

Download patch

ref: 78827d2e1df10175dbdb8dd0d70c7e4fcf4dbb81
parent: fc9b380ddee2c251420e7d26772f68b3a10a9167
author: Ori Bernstein <[email protected]>
date: Sun May 3 11:21:22 EDT 2015

Fix exports of specialized types.

    We had some bugs when exporting a type that had a specialization,
    eg, if a function specialized std.htab, so that one of it's args
    was:

        std.htab(byte[:], byte[:])

    would conflict with the very generic definition it was using
    in some circumstances.

--- a/parse/infer.c
+++ b/parse/infer.c
@@ -351,7 +351,7 @@
 }
 
 /* Freshens the type of a declaration. */
-static Type *_tyfreshen(Inferstate *st, Htab *subst, Type *t)
+static Type *tyfreshen(Inferstate *st, Htab *subst, Type *t)
 {
     char *from, *to;
 
@@ -467,9 +467,9 @@
 
     subst = mkht(tyhash, tyeq);
     for (i = 0; i < t->ngparam; i++) {
-        htput(subst, t->gparam[i], orig->arg[i]);
+        htput(subst, t->gparam[i], tf(st, orig->arg[i]));
     }
-    t = _tyfreshen(st, subst, t);
+    t = tyfreshen(st, subst, t);
     htfree(subst);
     return t;
 }
@@ -1022,7 +1022,7 @@
     n->expr.did = s->decl.did;
     n->expr.isconst = s->decl.isconst;
     if (s->decl.isgeneric && !st->ingeneric) {
-        t = _tyfreshen(st, NULL, t);
+        t = tyfreshen(st, NULL, t);
         addspecialization(st, n, curstab());
         if (t->type == Tyvar) {
             settype(st, n, mktyvar(n->loc));
@@ -1541,7 +1541,7 @@
 
     t = tf(st, decltype(n));
     if (t->type == Tygeneric && !n->decl.isgeneric) {
-        t = _tyfreshen(st, NULL, t);
+        t = tyfreshen(st, NULL, t);
         unifyparams(st, n, t, decltype(n));
     }
     settype(st, n, t);
@@ -1851,7 +1851,7 @@
     Node *dcl;
 
     dcl = decls[n->expr.did];
-    unify(st, n, type(st, n), _tyfreshen(st, NULL, type(st, dcl)));
+    unify(st, n, type(st, n), tyfreshen(st, NULL, type(st, dcl)));
 }
 
 static void postcheck(Inferstate *st, Node *file)
--- a/parse/type.c
+++ b/parse/type.c
@@ -353,11 +353,15 @@
         case Tygeneric:
             return 1;
         case Tyname:
-        case Tyunres:
             for (i = 0; i < t->narg; i++)
                 if (hasparamsrec(t->arg[i], visited))
                     return 1;
             return hasparamsrec(t->sub[0], visited);
+        case Tyunres:
+            for (i = 0; i < t->narg; i++)
+                if (hasparamsrec(t->arg[i], visited))
+                    return 1;
+            break;
         case Tystruct:
             for (i = 0; i < t->nmemb; i++)
                 if (hasparamsrec(t->sdecls[i]->decl.type, visited))
--- a/parse/use.c
+++ b/parse/use.c
@@ -720,6 +720,16 @@
     return s;
 }
 
+static int isspecialization(Type *t1, Type *t2)
+{
+    if ((t1->type != Tygeneric || t2->type != Tyname) &&
+        (t1->type != Tyname || t2->type != Tygeneric) &&
+        (t1->type != Tyname || t2->type != Tyname))
+        return 0;
+    /* FIXME: this should be done better */
+    return nameeq(t1->name, t2->name);
+}
+
 static void fixtypemappings(Stab *st)
 {
     size_t i;
@@ -746,7 +756,7 @@
         if ((t->type != Tyname && t->type != Tygeneric) || t->issynth)
             continue;
         old = htget(tydedup, t);
-        if (old && !tyeq(t, old))
+        if (old && !tyeq(t, old) && !isspecialization(t, old))
             lfatal(t->loc, "Duplicate definition of type %s on %s:%d", tystr(old), file->file.files[old->loc.file], old->loc.line);
     }
     lfree(&typefixdest, &ntypefixdest);