ref: 0ef6733ca5602407ccec8be6242c9a9ccd7c9cac
parent: 6950e5fccf4ebe1da730493bca2284e092b43e90
author: Ori Bernstein <ori@eigenstate.org>
date: Tue Dec 15 18:55:12 EST 2015
Keep a list of impls for a given type. We want to know so we can unify in a post check.
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -382,7 +382,8 @@
;
traitdef: Ttrait Tident generictype optauxtypes { /* trait prototype */
- $$ = mktrait($1->loc, mkname($2->loc, $2->id), $3,
+ $$ = mktrait($1->loc,
+ mkname($2->loc, $2->id), $3,
$4.types, $4.ntypes,
NULL, 0,
NULL, 0,
@@ -390,7 +391,8 @@
}
| Ttrait Tident generictype optauxtypes Tasn traitbody Tendblk /* trait definition */ {
size_t i;
- $$ = mktrait($1->loc, mkname($2->loc, $2->id), $3,
+ $$ = mktrait($1->loc,
+ mkname($2->loc, $2->id), $3,
$4.types, $4.ntypes,
NULL, 0,
$6.nl, $6.nn,
@@ -397,6 +399,7 @@
0);
for (i = 0; i < $6.nn; i++) {
$6.nl[i]->decl.trait = $$;
+ $6.nl[i]->decl.impls = mkht(tyhash, tyeq);
$6.nl[i]->decl.isgeneric = 1;
}
}
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -466,20 +466,28 @@
return t;
}
-static Type *tysubst(Inferstate *st, Type *t, Type *orig)
+static Type *tysubstmap(Inferstate *st, Htab *subst, Type *t, Type *orig)
{
- Htab *subst;
size_t i;
- subst = mkht(tyhash, tyeq);
for (i = 0; i < t->ngparam; i++) {
htput(subst, t->gparam[i], tf(st, orig->arg[i]));
}
t = tyfreshen(st, subst, t);
+ return t;
+}
+
+static Type *tysubst(Inferstate *st, Type *t, Type *orig)
+{
+ Htab *subst;
+
+ subst = mkht(tyhash, tyeq);
+ t = tysubstmap(st, subst, t, orig);
htfree(subst);
return t;
}
+
/* fixd the most accurate type mapping we have (ie,
* the end of the unification chain */
static Type *tf(Inferstate *st, Type *orig)
@@ -1058,16 +1066,27 @@
static Type *initvar(Inferstate *st, Node *n, Node *s)
{
- Type *t;
+ Type *t, *param;
+ Htab *subst;
if (s->decl.ishidden)
fatal(n, "attempting to refer to hidden decl %s", ctxstr(st, n));
- if (s->decl.isgeneric)
- t = tysubst(st, tf(st, s->decl.type), s->decl.type);
- else
+
+ param = NULL;
+ if (s->decl.isgeneric) {
+ subst = mkht(tyhash, tyeq);
+ t = tysubstmap(st, subst, tf(st, s->decl.type), s->decl.type);
+ if (s->decl.trait) {
+ param = htget(subst, s->decl.trait->param);
+ delayedcheck(st, n, curstab());
+ }
+ htfree(subst);
+ } else {
t = s->decl.type;
+ }
n->expr.did = s->decl.did;
n->expr.isconst = s->decl.isconst;
+ n->expr.param = param;
if (s->decl.isgeneric && !st->ingeneric) {
t = tyfreshen(st, NULL, t);
addspecialization(st, n, curstab());
@@ -1625,6 +1644,7 @@
fatal(n, "trait %s already specialized with %s on %s:%d",
namestr(t->name), tystr(n->impl.type),
fname(sym->loc), lnum(sym->loc));
+ htput(proto->decl.impls, n->impl.type, ty);
dcl->decl.name = name;
putdcl(file->file.globls, dcl);
if (debugopt['S'])
@@ -1971,7 +1991,11 @@
Type *ty;
dcl = decls[n->expr.did];
- ty = tyfreshen(st, NULL, type(st, dcl));
+ if (n->expr.param) {
+ ty = htget(dcl->decl.impls, tf(st, n->expr.param));
+ } else {
+ ty = tyfreshen(st, NULL, type(st, dcl));
+ }
unify(st, n, type(st, n), ty);
}
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -236,10 +236,11 @@
struct {
Op op;
Type *type;
+ Type *param; /* for specialized traits, the primary param */
int isconst;
- size_t did; /* for Ovar, we want a mapping to the decl id */
+ size_t did; /* for Ovar, we want a mapping to the decl id */
size_t nargs;
- Node *idx; /* used when this is in an indexed initializer */
+ Node *idx; /* used when this is in an indexed initializer */
Node **args;
} expr;
@@ -317,6 +318,7 @@
impl.
*/
Trait *trait;
+ Htab *impls;
char vis;
/* flags */