ref: f666a9b2a62c4f8588c6add2bcc2071f95ef357c
parent: 80b458a8b54bf72741c4d61a7723b0997e157fb8
author: Ori Bernstein <[email protected]>
date: Thu Feb 20 17:22:50 EST 2014
Unify the types for traits correctly.
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -335,10 +335,10 @@
;
traitdef: Ttrait Tident generictype Tendln /* trait prototype */ {
- $$ = mktrait($1->line, mkname($2->line, $2->str), NULL, 0, NULL, 0, 1);
+ $$ = mktrait($1->line, mkname($2->line, $2->str), $3, NULL, 0, NULL, 0, 1);
}
| Ttrait Tident generictype Tasn traitbody Tendblk /* trait definition */ {
- $$ = mktrait($1->line, mkname($2->line, $2->str), NULL, 0, $5.nl, $5.nn, 0);
+ $$ = mktrait($1->line, mkname($2->line, $2->str), $3, NULL, 0, $5.nl, $5.nn, 0);
}
;
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -529,7 +529,7 @@
}
/* does b satisfy all the constraints of a? */
-static int traitcheck(Type *a, Type *b)
+static int checktraits(Type *a, Type *b)
{
/* a has no traits to satisfy */
if (!a->traits)
@@ -558,7 +558,7 @@
else if (b->traits)
a->traits = bsdup(b->traits);
} else {
- if (!traitcheck(a, b)) {
+ if (!checktraits(a, b)) {
sep = "";
n = 0;
for (i = 0; bsiter(a->traits, &i); i++) {
@@ -1298,8 +1298,10 @@
static void specializeimpl(Inferstate *st, Node *n)
{
- Trait *t;
Node *dcl, *proto;
+ Htab *ht;
+ Trait *t;
+ Type *ty;
size_t i, j;
t = gettrait(curstab(), n->impl.traitname);
@@ -1323,8 +1325,14 @@
namestr(dcl), namestr(t->name), ctxstr(st, n));
/* infer and unify types */
+ checktraits(t->param, n->impl.type);
+ ht = mkht(tyhash, tyeq);
+ htput(ht, t->param, n->impl.type);
+ ty = tyspecialize(type(st, proto), ht);
+ htfree(ht);
+
inferdecl(st, dcl);
- unify(st, n, type(st, dcl), type(st, proto));
+ unify(st, n, type(st, dcl), ty);
}
}
@@ -1503,9 +1511,9 @@
fatal(ctx->line, "Type %s not compatible with %s near %s\n", tystr(t), tystr(delayed), ctxstr(st, ctx));
}
if (t->type == Tyvar) {
- if (hastrait(t, traittab[Tcint]) && traitcheck(t, tyint))
+ if (hastrait(t, traittab[Tcint]) && checktraits(t, tyint))
return tyint;
- if (hastrait(t, traittab[Tcfloat]) && traitcheck(t, tyflt))
+ if (hastrait(t, traittab[Tcfloat]) && checktraits(t, tyflt))
return tyflt;
} else if (!t->fixed) {
t->fixed = 1;
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -148,8 +148,9 @@
struct Trait {
int cid; /* unique id */
- int isproto; /* is it a prototype for exporting */
+ int isproto; /* is it a prototype (for exporting purposes) */
Node *name; /* the name of the trait */
+ Type *param; /* the type parameter */
Node **memb; /* type must have these members */
size_t nmemb;
Node **funcs; /* and declare these funcs */
@@ -409,7 +410,7 @@
Type *mktyfunc(int line, Node **args, size_t nargs, Type *ret);
Type *mktystruct(int line, Node **decls, size_t ndecls);
Type *mktyunion(int line, Ucon **decls, size_t ndecls);
-Trait *mktrait(int line, Node *name, Node **memb, size_t nmemb, Node **funcs, size_t nfuncs, int isproto);
+Trait *mktrait(int line, Node *name, Type *param, Node **memb, size_t nmemb, Node **funcs, size_t nfuncs, int isproto);
Type *mktylike(int line, Ty ty); /* constrains tyvar t like it was builtin ty */
int istysigned(Type *t);
int istyfloat(Type *t);
--- a/parse/type.c
+++ b/parse/type.c
@@ -111,12 +111,13 @@
}
/* steals memb, funcs */
-Trait *mktrait(int line, Node *name, Node **memb, size_t nmemb, Node **funcs, size_t nfuncs, int isproto)
+Trait *mktrait(int line, Node *name, Type *param, Node **memb, size_t nmemb, Node **funcs, size_t nfuncs, int isproto)
{
Trait *t;
t = zalloc(sizeof(Trait));
t->name = name;
+ t->param = param;
t->memb = memb;
t->nmemb = nmemb;
t->funcs = funcs;
@@ -642,8 +643,10 @@
int i;
Type *ty;
+/* this must be done after all the types are created, otherwise we will
+ * clobber the memoized bunch of types with the type params. */
#define Tc(c, n) \
- mktrait(-1, mkname(-1, n), NULL, 0, NULL, 0, 0);
+ mktrait(-1, mkname(-1, n), NULL, NULL, 0, NULL, 0, 0);
#include "trait.def"
#undef Tc