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);