shithub: mc

Download patch

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