diff options
author | Ori Bernstein <ori@eigenstate.org> | 2015-05-03 15:21:22 -0700 |
---|---|---|
committer | Ori Bernstein <ori@eigenstate.org> | 2015-05-03 15:21:22 -0700 |
commit | 04f4b9d625a9a88777ec9f7cace3d8dd0487a0ac (patch) | |
tree | 1161e71fb73e3e2509e05ab651cb333c420c7f17 | |
parent | cef6964b4b74f2f7cd63fe1dd7a3394a20d68bc6 (diff) | |
download | mc-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.
-rw-r--r-- | parse/infer.c | 12 | ||||
-rw-r--r-- | parse/type.c | 6 | ||||
-rw-r--r-- | parse/use.c | 12 |
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); |