summaryrefslogtreecommitdiff
path: root/parse
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2015-05-03 15:21:22 -0700
committerOri Bernstein <ori@eigenstate.org>2015-05-03 15:21:22 -0700
commit04f4b9d625a9a88777ec9f7cace3d8dd0487a0ac (patch)
tree1161e71fb73e3e2509e05ab651cb333c420c7f17 /parse
parentcef6964b4b74f2f7cd63fe1dd7a3394a20d68bc6 (diff)
downloadmc-04f4b9d625a9a88777ec9f7cace3d8dd0487a0ac.tar.gz
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.
Diffstat (limited to 'parse')
-rw-r--r--parse/infer.c12
-rw-r--r--parse/type.c6
-rw-r--r--parse/use.c12
3 files changed, 22 insertions, 8 deletions
diff --git a/parse/infer.c b/parse/infer.c
index 69fcd2d..cd0e940 100644
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -351,7 +351,7 @@ static int needfreshen(Inferstate *st, Type *t)
}
/* 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 @@ static Type *tysubst(Inferstate *st, Type *t, Type *orig)
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 @@ static Type *initvar(Inferstate *st, Node *n, Node *s)
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 @@ static void inferdecl(Inferstate *st, Node *n)
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 @@ static void checkvar(Inferstate *st, Node *n)
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)
diff --git a/parse/type.c b/parse/type.c
index 7b2433a..6a29d1d 100644
--- a/parse/type.c
+++ b/parse/type.c
@@ -353,11 +353,15 @@ int hasparamsrec(Type *t, Bitset *visited)
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))
diff --git a/parse/use.c b/parse/use.c
index 4050d29..546a3cf 100644
--- a/parse/use.c
+++ b/parse/use.c
@@ -720,6 +720,16 @@ static Stab *findstab(Stab *st, char *pkg)
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 @@ static void fixtypemappings(Stab *st)
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);