shithub: mc

Download patch

ref: 6e4bf0cdecce71d9a839c1e7f6a42409c2f9d961
parent: dfed30d87b4f9dbae24b16ddd32ea0be69a5d602
author: Ori Bernstein <ori@eigenstate.org>
date: Sun Aug 20 13:49:01 EDT 2017

Fix trait shit.

--- a/parse/export.c
+++ b/parse/export.c
@@ -75,9 +75,9 @@
 		return;
 	t->vis = Vishidden;
 	/* export the user defined traits */
-	if (t->traits)
-		for (i = Ntraits; bsiter(t->traits, &i); i++)
-			tagtrait(st, traittab[i], ingeneric, hidelocal);
+	//if (t->traits)
+	//	for (i = Ntraits; bsiter(t->traits, &i); i++)
+	//		tagtrait(st, traittab[i], ingeneric, hidelocal);
 	for (i = 0; i < t->nsub; i++)
 		tagtype(st, t->sub[i], ingeneric, hidelocal);
 	switch (t->type) {
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -1081,7 +1081,9 @@
 
 	for (i = 0; i < ntraittab; i++) {
 		if (!strcmp(namestr(traittab[i]->name), str)) {
-			settrait(t, traittab[i]);
+			if (!t->trneed)
+				t->trneed = mkbs();
+			bsput(t->trneed, i);
 			return;
 		}
 	}
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -15,6 +15,21 @@
 #include "util.h"
 #include "parse.h"
 
+typedef struct Traitmap Traitmap;
+typedef struct Enttype Enttype;
+
+struct Traitmap {
+	Bitset *traits;
+	Traitmap *sub[Ntypes];
+
+	Htab *name;	/* name => bitset(traits) */
+	Type **filter;
+	size_t nfilter;
+	Trait **filtertr;
+	size_t nfiltertr;
+};
+
+
 static void infernode(Node **np, Type *ret, int *sawret);
 static void inferexpr(Node **np, Type *ret, int *sawret);
 static void inferdecl(Node *n);
@@ -51,6 +66,7 @@
 static Stab **specializationscope;
 static size_t nspecializationscope;
 static Htab *seqbase;
+static Traitmap *traitmap;
 
 static void
 ctxstrcall(char *buf, size_t sz, Node *n)
@@ -239,8 +255,8 @@
 
 	tr = traittab[Tcdisp];
 	ty = decltype(n);
-	if (!ty->traits || !bshas(ty->traits, Tcdisp))
-		return;
+	//if (!ty->traits || !bshas(ty->traits, Tcdisp))
+	//	return;
 	assert(tr->nproto == 1);
 	if (hthas(tr->proto[0]->decl.impls, ty))
 		return;
@@ -250,7 +266,7 @@
 }
 
 static void
-additerspecializations(Node *n, Stab *stab)
+additerspecialization(Node *n, Stab *stab)
 {
 	Trait *tr;
 	Type *ty;
@@ -258,8 +274,8 @@
 
 	tr = traittab[Tciter];
 	ty = exprtype(n->iterstmt.seq);
-	if (!ty->traits || !bshas(ty->traits, Tciter))
-		return;
+	//if (!ty->traits || !bshas(ty->traits, Tciter))
+	//	return;
 	if (ty->type == Tyslice || ty->type == Tyarray || ty->type == Typtr)
 		return;
 	for (i = 0; i < tr->nproto; i++) {
@@ -516,11 +532,6 @@
 		}
 	}
 	base = tybase(t);
-	/* no-ops if base == t */
-	if (t->traits && base->traits)
-		bsunion(t->traits, base->traits);
-	else if (base->traits)
-		t->traits = bsdup(base->traits);
 	if (occurs(t))
 		lfatal(t->loc, "type %s includes itself", tystr(t));
 	popenv(t->env);
@@ -642,6 +653,17 @@
 		marksrc(t, n->loc);
 }
 
+static Type*
+mktylike(Srcloc l, Ty other)
+{
+	Type *t;
+
+	t = mktyvar(l);
+	/* not perfect in general, but good enough for all places mktylike is used. */
+	t->trneed = bsdup(traitmap->sub[other]->traits);
+	return t;
+}
+
 /* Gets the type of a literal value */
 static Type *
 littype(Node *n)
@@ -669,19 +691,11 @@
 delayeducon(Type *fallback)
 {
 	Type *t;
-	char *from, *to;
 
 	if (fallback->type != Tyunion)
 		return fallback;
 	t = mktylike(fallback->loc, fallback->type);
 	htput(delayed, t, fallback);
-	if (debugopt['u']) {
-		from = tystr(t);
-		to = tystr(fallback);
-		indentf(indentdepth, "Delay %s -> %s\n", from, to);
-		free(from);
-		free(to);
-	}
 	return t;
 }
 
@@ -746,43 +760,108 @@
  * constraint list. Otherwise, the type is checked to see
  * if it has the required constraint */
 static void
-constrain(Node *ctx, Type *a, Trait *c)
+constrain(Node *ctx, Type *base, Trait *tr)
 {
-	if (a->type == Tyvar) {
-		if (!a->traits)
-			a->traits = mkbs();
-		settrait(a, c);
-	} else if (!a->traits || !bshas(a->traits, c->uid)) {
-		fatal(ctx, "%s needs %s near %s", tystr(a), namestr(c->name), ctxstr(ctx));
+	Traitmap *tm;
+	Bitset *bs;
+	Type *ty;
+	size_t i;
+
+	while(1) {
+		ty = base;
+		tm = traitmap->sub[ty->type];
+		while (1) {
+			if (ty->type == Typaram && bshas(ty->trneed, tr->uid))
+				return;
+			if (ty->type == Tyvar) {
+				if (!ty->trneed)
+					ty->trneed = mkbs();
+				bsput(ty->trneed, tr->uid);
+				return;
+			} 
+			if (bshas(tm->traits, tr->uid))
+				return;
+			if (tm->name && ty->type == Tyname) {
+				bs = htget(tm->name, ty->name);
+				if (bs && bshas(bs, tr->uid))
+					return;
+			}
+			for (i = 0; i < tm->nfilter; i++) {
+				if (tm->filtertr[i]->uid != tr->uid)
+					continue;
+				if (tymatchrank(tm->filter[i], ty) >= 0)
+					return;
+			}
+			if (!tm->sub[ty->type])
+				break;
+			assert(ty->nsub == 1);
+			tm = tm->sub[ty->type];
+			ty = ty->sub[0];
+		}
+		if (base->type != Tyname)
+			break;
+		base = base->sub[0];
 	}
+	fatal(ctx, "%s needs trait %s near %s", tystr(ty), namestr(tr->name), ctxstr(ctx));
 }
 
-static int
-satisfiestraits(Type *a, Type *b)
+static void
+traitsfor(Type *base, Bitset *dst)
 {
-	if (!a->traits || bscount(a->traits) == 0)
-		return 1;
-	if (b->traits)
-		return bsissubset(a->traits, b->traits);
-	return 0;
+	Traitmap *tm;
+	Type *ty;
+	size_t i;
+
+	while(1) {
+		ty = base;
+		tm = traitmap->sub[ty->type];
+		while (1) {
+			if (ty->type == Tyvar)
+				break;
+			bsunion(dst, tm->traits);
+			for (i = 0; i < tm->nfilter; i++) {
+				if (tymatchrank(tm->filter[i], ty) >= 0)
+					bsput(dst, tm->filtertr[i]->uid);
+			}
+			if (!tm->sub[ty->type] || ty->nsub != 1)
+				break;
+			tm = tm->sub[ty->type];
+			ty = ty->sub[0];
+		}
+		if (base->type != Tyname)
+			break;
+		base = base->sub[0];
+	}
 }
 
 static void
 verifytraits(Node *ctx, Type *a, Type *b)
 {
+	char traitbuf[64], abuf[64], bbuf[64];
+	char asrc[64], bsrc[64];
+	Bitset *abs, *bbs;
 	size_t i, n;
 	Srcloc l;
 	char *sep;
-	char traitbuf[64], abuf[64], bbuf[64];
-	char asrc[64], bsrc[64];
 
-	if (!satisfiestraits(a, b)) {
+	abs = a->trneed;
+	if (!abs) {
+		abs = mkbs();
+		traitsfor(a, abs);
+	}
+	bbs = b->trneed;
+	if (!bbs) {
+		bbs = mkbs();
+		traitsfor(b, bbs);
+	}
+	if (!bsissubset(abs, bbs)) {
 		sep = "";
 		n = 0;
-		for (i = 0; bsiter(a->traits, &i); i++) {
-			if (!b->traits || !bshas(b->traits, i))
+		*traitbuf = 0;
+		for (i = 0; bsiter(abs, &i); i++) {
+			if (!bshas(bbs, i))
 				n += bprintf(traitbuf + n, sizeof(traitbuf) - n, "%s%s", sep,
-						namestr(traittab[i]->name));
+					namestr(traittab[i]->name));
 			sep = ",";
 		}
 		tyfmt(abuf, sizeof abuf, a);
@@ -792,10 +871,13 @@
 			l = unifysrc[b->tid];
 			snprintf(bsrc, sizeof asrc, "\n\t%s from %s:%d", bbuf, fname(l), lnum(l));
 		}
-		fatal(ctx, "%s missing traits %s for %s near %s%s%s",
-				bbuf, traitbuf, abuf, ctxstr(ctx),
-				srcstr(a), srcstr(b));
+		fatal(ctx, "%s needs trait %s near %s%s%s",
+			bbuf, traitbuf, ctxstr(ctx), srcstr(a), srcstr(b));
 	}
+	if (!a->trneed)
+		bsfree(abs);
+	if (!b->trneed)
+		bsfree(bbs);
 }
 
 /* Merges the constraints on types */
@@ -802,14 +884,15 @@
 static void
 mergetraits(Node *ctx, Type *a, Type *b)
 {
+// TRFIX
 	if (b->type == Tyvar) {
 		/* make sure that if a = b, both have same traits */
-		if (a->traits && b->traits)
-			bsunion(b->traits, a->traits);
-		else if (a->traits)
-			b->traits = bsdup(a->traits);
-		else if (b->traits)
-			a->traits = bsdup(b->traits);
+		if (a->trneed && b->trneed)
+			bsunion(b->trneed, a->trneed);
+		else if (a->trneed)
+			b->trneed = bsdup(a->trneed);
+		else if (b->trneed)
+			a->trneed = bsdup(b->trneed);
 	} else {
 		verifytraits(ctx, a, b);
 	}
@@ -963,7 +1046,6 @@
 	Type *t, *r;
 	Type *a, *b;
 	Type *ea, *eb;
-	char *from, *to;
 	size_t i;
 
 	/* a ==> b */
@@ -979,16 +1061,6 @@
 		b = t;
 	}
 
-	if (debugopt['u']) {
-		from = tystr(a);
-		to = tystr(b);
-		indentf(indentdepth, "Unify %s => %s\n", from, to);
-		indentf(indentdepth + 1, "indexes: %s => %s\n",
-			tystr(htget(seqbase, a)), tystr(htget(seqbase, b)));
-		free(from);
-		free(to);
-	}
-
 	/* Disallow recursive types */
 	if (a->type == Tyvar && b->type != Tyvar) {
 		if (occursin(a, b))
@@ -1075,7 +1147,6 @@
 {
 	size_t i;
 	Type *ft;
-	char *ret, *ctx;
 
 	ft = type(n->expr.args[0]);
 
@@ -1100,14 +1171,6 @@
 	if (i < ft->nsub && ft->sub[i]->type != Tyvalist)
 		fatal(n, "%s arity mismatch (expected %zd args, got %zd)",
 				ctxstr(n->expr.args[0]), ft->nsub - 1, i - 1);
-	if (debugopt['u']) {
-		ret = tystr(ft->sub[0]);
-		ctx = ctxstr(n->expr.args[0]);
-		indentf(indentdepth, "Call of %s returns %s\n", ctx, ret);
-		free(ctx);
-		free(ret);
-	}
-
 	settype(n, ft->sub[0]);
 }
 
@@ -1811,10 +1874,6 @@
 			lappend(&proto->decl.gimpl, &proto->decl.ngimpl, dcl);
 			lappend(&proto->decl.gtype, &proto->decl.ngtype, ty);
 		}
-		if (debugopt['S'])
-			printf("specializing trait [%d]%s:%s => %s:%s\n", n->loc.line,
-					namestr(proto->decl.name), tystr(type(proto)), namestr(name),
-					tystr(ty));
 		dcl->decl.vis = t->vis;
 		lappend(&impldecl, &nimpldecl, dcl);
 
@@ -1901,8 +1960,6 @@
 		popstab();
 		break;
 	case Ndecl:
-		if (debugopt['u'])
-			indentf(indentdepth, "--- infer %s ---\n", declname(n));
 		if (n->decl.isgeneric)
 			ingeneric++;
 		indentdepth++;
@@ -1915,8 +1972,6 @@
 			constrain(n, type(n), traittab[Tcdisp]);
 		popenv(n->decl.env);
 		indentdepth--;
-		if (debugopt['u'])
-			indentf(indentdepth, "--- done ---\n");
 		if (n->decl.isgeneric)
 			ingeneric--;
 		break;
@@ -2011,7 +2066,6 @@
 	static Type *tyint, *tyflt;
 	Type *t, *d, *base;
 	Tyenv *env;
-	char *from, *to;
 	size_t i;
 	char buf[1024];
 
@@ -2036,10 +2090,10 @@
 					tystr(d), ctxstr(ctx));
 		}
 	}
-	if (t->type == Tyvar) {
-		if (hastrait(t, traittab[Tcint]) && satisfiestraits(t, tyint))
+	if (t->type == Tyvar && t->trneed) {
+		if (bshas(t->trneed, Tcint) && bshas(t->trneed, Tcnum))
 			t = tyint;
-		if (hastrait(t, traittab[Tcfloat]) && satisfiestraits(t, tyflt))
+		else if (bshas(t->trneed, Tcflt) && bshas(t->trneed, Tcnum))
 			t = tyflt;
 	} else if (!t->fixed) {
 		t->fixed = 1;
@@ -2066,19 +2120,8 @@
 			t->sub[i] = tyfix(ctx, t->sub[i], noerr);
 	}
 
-	if (t->type == Tyvar && !noerr) {
-		if (debugopt['T'])
-			dump(file, stdout);
+	if (t->type == Tyvar && !noerr)
 		fatal(ctx, "underconstrained type %s near %s", tyfmt(buf, 1024, t), ctxstr(ctx));
-	}
-
-	if (debugopt['u'] && !tyeq(orig, t)) {
-		from = tystr(orig);
-		to = tystr(t);
-		indentf(indentdepth, "subst %s => %s\n", from, to);
-		free(from);
-		free(to);
-	}
 	if (base)
 		htput(seqbase, t, base);
 	if (env)
@@ -2439,7 +2482,7 @@
 		typesub(n->iterstmt.elt, noerr);
 		typesub(n->iterstmt.seq, noerr);
 		typesub(n->iterstmt.body, noerr);
-		additerspecializations(n, curstab());
+		additerspecialization(n, curstab());
 		break;
 	case Nmatchstmt:
 		typesub(n->matchstmt.val, noerr);
@@ -2560,39 +2603,141 @@
 		popstab();
 	}
 }
+static void
+builtintraits(void)
+{
+	size_t i;
 
+	/* char::(numeric,integral) */
+	for (i = 0; i < Ntypes; i++) {
+		traitmap->sub[i] = zalloc(sizeof(Traitmap));
+		traitmap->sub[i]->traits = mkbs();
+		traitmap->sub[i]->name = mkht(namehash, nameeq);
+	}
+
+	bsput(traitmap->sub[Tychar]->traits, Tcnum);
+	bsput(traitmap->sub[Tychar]->traits, Tcint);
+
+	bsput(traitmap->sub[Tybyte]->traits, Tcnum);
+	bsput(traitmap->sub[Tybyte]->traits, Tcint);
+
+	/* <integer types>::(numeric,integral) */
+	for (i = Tyint8; i < Tyflt32; i++) {
+		bsput(traitmap->sub[i]->traits, Tcnum);
+		bsput(traitmap->sub[i]->traits, Tcint);
+	}
+
+	/* <floats>::(numeric,floating) */
+	bsput(traitmap->sub[Tyflt32]->traits, Tcnum);
+	bsput(traitmap->sub[Tyflt32]->traits, Tcflt);
+	bsput(traitmap->sub[Tyflt64]->traits, Tcnum);
+	bsput(traitmap->sub[Tyflt64]->traits, Tcflt);
+
+	/* @a*::(sliceable) */
+	bsput(traitmap->sub[Typtr]->traits, Tcslice);
+
+	/* @a[:]::(indexable,sliceable) */
+	bsput(traitmap->sub[Tyslice]->traits, Tcidx);
+	bsput(traitmap->sub[Tyslice]->traits, Tcslice);
+	bsput(traitmap->sub[Tyslice]->traits, Tciter);
+
+	/* @a[SZ]::(indexable,sliceable) */
+	bsput(traitmap->sub[Tyarray]->traits, Tcidx);
+	bsput(traitmap->sub[Tyarray]->traits, Tcslice);
+	bsput(traitmap->sub[Tyarray]->traits, Tciter);
+
+	/* @a::function */
+	bsput(traitmap->sub[Tyfunc]->traits, Tcfunc);
+}
+
+static Trait*
+findtrait(Node *impl)
+{
+	Trait *tr;
+	Node *n;
+	Stab *ns;
+
+	tr = impl->impl.trait;
+	if (!tr) {
+		n = impl->impl.traitname;
+		ns = file->file.globls;
+		if (n->name.ns)
+			ns = getns(file, n->name.ns);
+		if (ns)
+			tr = gettrait(ns, n);
+		if (!tr)
+			fatal(impl, "trait %s does not exist near %s",
+					namestr(impl->impl.traitname), ctxstr(impl));
+		if (tr->naux != impl->impl.naux)
+			fatal(impl, "incompatible implementation of %s: mismatched aux types",
+					namestr(impl->impl.traitname), ctxstr(impl));
+	}
+	return tr;
+}
+
 static void
-applytraits(void)
+addtraittab(Traitmap *m, Trait *tr, Type *ty)
 {
+	Bitset *bs;
+	Traitmap *mm;
+
+	if (!m->sub[ty->type]) {
+		m->sub[ty->type] = zalloc(sizeof(Traitmap));
+		m->sub[ty->type]->traits = mkbs();
+		m->sub[ty->type]->name = mkht(namehash, nameeq);
+	}
+	mm = m->sub[ty->type];
+	switch (ty->type) {
+	case Tygeneric:
+	case Typaram:
+		lappend(&mm->filter, &m->nfilter, ty);
+		lappend(&mm->filtertr, &m->nfiltertr, tr);
+		break;
+	case Tyname:
+		if (ty->ngparam == 0) {
+			bs = htget(mm->name, ty->name);
+			if (!bs) {
+				bs = mkbs();
+				htput(mm->name, ty->name, bs);
+			}
+			bsput(bs, tr->uid);
+		} else {
+			lappend(&mm->filter, &m->nfilter, ty);
+			lappend(&mm->filtertr, &m->nfiltertr, tr);
+		}
+		break;
+	case Typtr:
+	case Tyarray:
+		addtraittab(mm, tr, ty->sub[0]);
+		break;
+	default:
+		if (istyprimitive(ty)) {
+			bsput(mm->traits, tr->uid);
+		} else {
+			lappend(&mm->filter, &m->nfilter, ty);
+			lappend(&mm->filtertr, &m->nfiltertr, tr);
+		}
+	}
+}
+
+static void
+initimpl(void)
+{
 	size_t i;
-	Node *impl, *n;
+	Node *impl;
 	Trait *tr;
 	Type *ty;
-	Stab *ns;
 
-	tr = NULL;
 	pushstab(file->file.globls);
-	/* for now, traits can only be declared globally */
+	traitmap = zalloc(sizeof(Traitmap));
+	builtintraits();
 	for (i = 0; i < nimpltab; i++) {
 		impl = impltab[i];
-		tr = impl->impl.trait;
-		if (!tr) {
-			n = impl->impl.traitname;
-			ns = file->file.globls;
-			if (n->name.ns)
-				ns = getns(file, n->name.ns);
-			if (ns)
-				tr = gettrait(ns, n);
-			if (!tr)
-				fatal(impl, "trait %s does not exist near %s",
-						namestr(impl->impl.traitname), ctxstr(impl));
-			if (tr->naux != impl->impl.naux)
-				fatal(impl, "incompatible implementation of %s: mismatched aux types",
-						namestr(impl->impl.traitname), ctxstr(impl));
-		}
+		tr = findtrait(impl);
+
 		pushenv(impl->impl.env);
 		ty = tf(impl->impl.type);
-		settrait(ty, tr);
+		addtraittab(traitmap, tr, ty);
 		if (tr->uid == Tciter) {
 			htput(seqbase, tf(impl->impl.type), tf(impl->impl.aux[0]));
 		}
@@ -2601,7 +2746,7 @@
 	popstab();
 }
 
-void
+static void
 verify(void)
 {
 	Type *t;
@@ -2630,15 +2775,14 @@
 }
 
 void
-infer()
+infer(void)
 {
 	delayed = mkht(tyhash, tyeq);
 	seqbase = mkht(tyhash, tyeq);
-	/* set up the symtabs */
 	loaduses();
+	initimpl();
 
 	/* do the inference */
-	applytraits();
 	infernode(&file, NULL, NULL);
 	postinfer();
 
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -124,7 +124,6 @@
 	Srcloc loc;
 	Vis vis;
 
-	Bitset *traits;		/* the type constraints matched on this type */
 
 	Type **gparam;		/* Tygeneric: type parameters that match the type args */
 	size_t ngparam;		/* Tygeneric: count of type parameters */
@@ -137,6 +136,7 @@
 	Type **sub;		/* sub-types; shared by all composite types */
 	size_t nsub;		/* For compound types */
 	size_t nmemb;		/* for aggregate types (struct, union) */
+	Bitset *trneed;		/* traits needed by this Tyvar/Typaram */
 	union {
 		Node *name;	/* Tyname: unresolved name. Tyalias: alias name */
 		Node *asize;	/* array size */
@@ -146,7 +146,6 @@
 	};
 
 	char hasparams;		/* cache for whether this type has params */
-	char issynth;		/* Tyname: whether this is synthesized or not */
 	char ishidden;		/* Tyname: whether this is hidden or not */
 	char ispkglocal;	/* Tyname: whether this is package local or not */
 	char isimport;		/* Tyname: whether tyis type was imported. */
@@ -379,6 +378,7 @@
 ulong tyhash(void *t);
 int tyeq(void *a, void *b);
 int tystricteq(void *a, void *b);
+int tymatchrank(Type *pat, Type *to);
 ulong namehash(void *t);
 int nameeq(void *a, void *b);
 ulong nsnamehash(void *t);
@@ -454,7 +454,6 @@
 	Type **aux, size_t naux,
 	Node **proto, size_t nproto,
 	int isproto);
-Type *mktylike(Srcloc l, Ty ty); /* constrains tyvar t like it was builtin ty */
 Ucon *finducon(Type *t, Node *name);
 int isstacktype(Type *t);
 int istysigned(Type *t);
@@ -469,8 +468,6 @@
 char *tystr(Type *t);
 size_t tyidfmt(char *buf, size_t len, Type *t);
 
-int hastrait(Type *t, Trait *c);
-int settrait(Type *t, Trait *c);
 int traiteq(Type *t, Trait **traits, size_t len);
 int traitfmt(char *buf, size_t len, Type *t);
 char *traitstr(Type *t);
@@ -531,8 +528,6 @@
 void substfree(Tysubst *subst);
 void substput(Tysubst *subst, Type *from, Type *to);
 Type *substget(Tysubst *subst, Type *from);
-void substpush(Tysubst *subst);
-void substpop(Tysubst *subst);
 Node *specializedcl(Node *n, Type *param, Type *to, Node **name);
 Type *tyspecialize(Type *t, Tysubst *tymap, Htab *delayed, Htab *tybase);
 Node *genericname(Node *n, Type *param, Type *t);
--- a/parse/specialize.c
+++ b/parse/specialize.c
@@ -15,33 +15,13 @@
 
 static Node *specializenode(Node *g, Tysubst *tsmap);
 
-Tysubst *
-mksubst()
-{
-	Tysubst *subst;
-
-	subst = zalloc(sizeof(Tysubst));
-	substpush(subst);
-	return subst;
-}
-
-void
-substfree(Tysubst *subst)
-{
-	size_t i;
-
-	for (i = 0; i < subst->nsubst; i++)
-		htfree(subst->subst[i]);
-	lfree(&subst->subst, &subst->nsubst);
-}
-
-void
+static void
 substpush(Tysubst *subst)
 {
 	lappend(&subst->subst, &subst->nsubst, mkht(tyhash, tyeq));
 }
 
-void
+static void
 substpop(Tysubst *subst)
 {
 	Htab *ht;
@@ -71,14 +51,24 @@
 	return t;
 }
 
+Tysubst *
+mksubst(void)
+{
+	Tysubst *subst;
+
+	subst = zalloc(sizeof(Tysubst));
+	substpush(subst);
+	return subst;
+}
+
 void
-addtraits(Type *t, Bitset *traits)
+substfree(Tysubst *subst)
 {
-	size_t b;
+	size_t i;
 
-	if (traits)
-		for (b = 0; bsiter(traits, &b); b++)
-			settrait(t, traittab[b]);
+	for (i = 0; i < subst->nsubst; i++)
+		htfree(subst->subst[i]);
+	lfree(&subst->subst, &subst->nsubst);
 }
 
 /*
@@ -106,7 +96,7 @@
 	switch (t->type) {
 	case Typaram:
 		ret = mktyvar(t->loc);
-		addtraits(ret, t->traits);
+		ret->trneed = bsdup(t->trneed);
 		substput(tsmap, t, ret);
 		break;
 	case Tygeneric:
@@ -124,7 +114,6 @@
 			substpop(tsmap);
 		ret->arg = arg;
 		ret->narg = narg;
-		ret->traits = bsdup(t->traits);
 		tytab[var->tid] = ret;
 		break;
 	case Tyname:
@@ -135,7 +124,6 @@
 		for (i = 0; i < t->narg; i++)
 			lappend(&arg, &narg, tyspecialize(t->arg[i], tsmap, delayed, trbase));
 		ret = mktyname(t->loc, t->name, tyspecialize(t->sub[0], tsmap, delayed, trbase));
-		ret->traits = bsdup(t->traits);
 		ret->arg = arg;
 		ret->narg = narg;
 		if (trbase && hthas(trbase, orig) && !hthas(trbase, ret)) {
@@ -474,90 +462,7 @@
 	return name;
 }
 
-/* this doesn't walk through named types, so it can't recurse infinitely. */
-int
-matchquality(Type *pat, Type *to)
-{
-	int match, q;
-	size_t i;
-	Ucon *puc, *tuc;
-
-	if (pat->type == Typaram)
-		return 0;
-	else if (pat->type != to->type)
-		return -1;
-
-	match = 0;
-	switch (pat->type) {
-	case Tystruct:
-		if (pat->nmemb != to->nmemb)
-			return -1;
-		for (i = 0; i < pat->nmemb; i++) {
-			if (!streq(declname(pat->sdecls[i]),declname( to->sdecls[i])))
-				return -1;
-			q = matchquality(decltype(pat->sdecls[i]), decltype(to->sdecls[i]));
-			if (q < 0)
-				return -1;
-			match += q;
-		}
-		break;
-	case Tyunion:
-		if (pat->nmemb != to->nmemb)
-			return -1;
-		for (i = 0; i < pat->nmemb; i++) {
-			if (!nameeq(pat->udecls[i], to->udecls[i]))
-				return -1;
-			puc = pat->udecls[i];
-			tuc = to->udecls[i];
-			if (puc->etype && tuc->etype) {
-				q = matchquality(puc->etype, tuc->etype);
-				if (q < 0)
-					return -1;
-				match += q;
-			} else if (puc->etype != tuc->etype) {
-				return -1;
-			}
-		}
-		break;
-	case Tyname:
-		if (!nameeq(pat->name, to->name))
-			return -1;
-		if (pat->narg != to->narg)
-			return -1;
-		for (i = 0; i < pat->narg; i++) {
-			q = matchquality(pat->arg[i], to->arg[i]);
-			if (q < 0)
-				return -1;
-			match += q;
-		}
-		break;
-	case Tyarray:
-		/* unsized arrays are ok */
-		if (pat->asize && to->asize) {
-			if (!!litvaleq(pat->asize->expr.args[0], to->asize->expr.args[0]))
-				return -1;
-		} else if (pat->asize != to->asize) {
-			return -1;
-		}
-		else return matchquality(pat->sub[0], to->sub[0]);
-		break;
-	default:
-		if (pat->nsub != to->nsub)
-			break;
-		if (pat->type == to->type)
-			match = 1;
-		for (i = 0; i < pat->nsub; i++) {
-			q = matchquality(pat->sub[i], to->sub[i]);
-			if (q < 0)
-				return -1;
-			match += q;
-		}
-		break;
-	}
-	return match;
-}
-
-Node *
+static Node *
 bestimpl(Node *n, Type *to)
 {
 	Node **gimpl, **ambig, *match;
@@ -574,7 +479,7 @@
 	gimpl = n->decl.gimpl;
 	ngimpl = n->decl.ngimpl;
 	for (i = 0; i < ngimpl; i++) {
-		score = matchquality(decltype(gimpl[i]), to);
+		score = tymatchrank(decltype(gimpl[i]), to);
 		if (score > best) {
 			lfree(&ambig, &nambig);
 			best = score;
--- a/parse/trait.def
+++ b/parse/trait.def
@@ -1,7 +1,7 @@
 /* Definitions of built in constraints */
 Tc(Tcnum,	"numeric")      /* arith ops */
 Tc(Tcint,	"integral")     /* behaves like an int, defaults to int as fallback */
-Tc(Tcfloat,	"floating")     /* behaves like a float, defaults to float as fallback */
+Tc(Tcflt,	"floating")     /* behaves like a float, defaults to float as fallback */
 Tc(Tcidx,	"indexable")    /* indexable */
 Tc(Tcslice,	"sliceable")    /* sliceable */
 Tc(Tcfunc,	"function")     /* behaves like a function */
--- a/parse/type.c
+++ b/parse/type.c
@@ -15,11 +15,6 @@
 #include "parse.h"
 
 typedef struct Typename Typename;
-struct Typename {
-	Ty ty;
-	char *name;
-};
-
 Type **tytab = NULL;
 Type **types = NULL;
 size_t ntypes;
@@ -30,7 +25,6 @@
 
 static Htab *tydeduptab;
 /* Built in type constraints */
-static Trait *traits[Ntypes + 1][4];
 static int tybfmt(char *buf, size_t len, Bitset *visted, Type *t);
 
 char stackness[] = {
@@ -64,7 +58,6 @@
 mktype(Srcloc loc, Ty ty)
 {
 	Type *t;
-	int i;
 
 	/* the first 'n' types will be identity mapped: tytab[Tyint], eg,
 	 * will map to an instantitaion of Tyint.
@@ -87,9 +80,6 @@
 	if (ty <= Tyvalist) /* the last builtin atomic type */
 		t->vis = Visbuiltin;
 
-	for (i = 0; traits[ty][i]; i++)
-		settrait(t, traits[ty][i]);
-
 	return t;
 }
 
@@ -106,8 +96,6 @@
 	r->resolved = 0;	/* re-resolving doesn't hurt */
 	r->fixed = 0;		/* re-resolving doesn't hurt */
 
-	r->traits = bsdup(t->traits);
-
 	r->arg = memdup(t->arg, t->narg * sizeof(Type *));
 	r->narg = t->narg;
 	r->inst = memdup(t->arg, t->narg * sizeof(Type *));
@@ -128,22 +116,6 @@
 	return r;
 }
 
-/*
- * Creates a Tyvar with the same
- * constrants as the 'like' type
- */
-Type *
-mktylike(Srcloc loc, Ty like)
-{
-	Type *t;
-	int i;
-
-	t = mktyvar(loc);
-	for (i = 0; traits[like][i]; i++)
-		settrait(t, traits[like][i]);
-	return t;
-}
-
 /* steals memb, funcs */
 Trait *
 mktrait(Srcloc loc, Node *name, Type *param,
@@ -217,7 +189,6 @@
 	t = mktype(loc, Tygeneric);
 	t->name = name;
 	t->nsub = 1;
-	t->traits = bsdup(base->traits);
 	t->sub = xalloc(sizeof(Type *));
 	t->sub[0] = base;
 	t->gparam = param;
@@ -240,7 +211,6 @@
 	t = mktype(loc, Tyname);
 	t->name = name;
 	t->nsub = 1;
-	t->traits = bsdup(base->traits);
 	t->sub = xalloc(sizeof(Type *));
 	t->sub[0] = base;
 	return t;
@@ -485,18 +455,6 @@
 }
 
 int
-settrait(Type *t, Trait *c)
-{
-	if (!t->traits)
-		t->traits = mkbs();
-	bsput(t->traits, c->uid);
-	return 1;
-}
-
-int
-hastrait(Type *t, Trait *c) { return t->traits && bshas(t->traits, c->uid); }
-
-int
 traitfmt(char *buf, size_t len, Type *t)
 {
 	size_t i;
@@ -504,7 +462,7 @@
 	char *end;
 	char *sep;
 
-	if (!t->traits || !bscount(t->traits))
+	if (!t->trneed || !bscount(t->trneed))
 		return 0;
 
 	p = buf;
@@ -512,11 +470,9 @@
 
 	p += bprintf(p, end - p, " :: ");
 	sep = "";
-	for (i = 0; i < ntraittab; i++) {
-		if (bshas(t->traits, i)) {
-			p += bprintf(p, end - p, "%s%s", sep, namestr(traittab[i]->name));
-			sep = ",";
-		}
+	for (i = 0; bsiter(t->trneed, &i); i++) {
+		p += bprintf(p, end - p, "%s%s", sep, namestr(traittab[i]->name));
+		sep = ",";
 	}
 	return p - buf;
 }
@@ -895,6 +851,89 @@
 	return eq;
 }
 
+/* this doesn't walk through named types, so it can't recurse infinitely. */
+int
+tymatchrank(Type *pat, Type *to)
+{
+	int match, q;
+	size_t i;
+	Ucon *puc, *tuc;
+
+	if (pat->type == Typaram)
+		return 0;
+	else if (pat->type != to->type)
+		return -1;
+
+	match = 0;
+	switch (pat->type) {
+	case Tystruct:
+		if (pat->nmemb != to->nmemb)
+			return -1;
+		for (i = 0; i < pat->nmemb; i++) {
+			if (!streq(declname(pat->sdecls[i]),declname( to->sdecls[i])))
+				return -1;
+			q = tymatchrank(decltype(pat->sdecls[i]), decltype(to->sdecls[i]));
+			if (q < 0)
+				return -1;
+			match += q;
+		}
+		break;
+	case Tyunion:
+		if (pat->nmemb != to->nmemb)
+			return -1;
+		for (i = 0; i < pat->nmemb; i++) {
+			if (!nameeq(pat->udecls[i], to->udecls[i]))
+				return -1;
+			puc = pat->udecls[i];
+			tuc = to->udecls[i];
+			if (puc->etype && tuc->etype) {
+				q = tymatchrank(puc->etype, tuc->etype);
+				if (q < 0)
+					return -1;
+				match += q;
+			} else if (puc->etype != tuc->etype) {
+				return -1;
+			}
+		}
+		break;
+	case Tyname:
+		if (!nameeq(pat->name, to->name))
+			return -1;
+		if (pat->narg != to->narg)
+			return -1;
+		for (i = 0; i < pat->narg; i++) {
+			q = tymatchrank(pat->arg[i], to->arg[i]);
+			if (q < 0)
+				return -1;
+			match += q;
+		}
+		break;
+	case Tyarray:
+		/* unsized arrays are ok */
+		if (pat->asize && to->asize) {
+			if (!!litvaleq(pat->asize->expr.args[0], to->asize->expr.args[0]))
+				return -1;
+		} else if (pat->asize != to->asize) {
+			return -1;
+		}
+		else return tymatchrank(pat->sub[0], to->sub[0]);
+		break;
+	default:
+		if (pat->nsub != to->nsub)
+			break;
+		if (pat->type == to->type)
+			match = 1;
+		for (i = 0; i < pat->nsub; i++) {
+			q = tymatchrank(pat->sub[i], to->sub[i]);
+			if (q < 0)
+				return -1;
+			match += q;
+		}
+		break;
+	}
+	return match;
+}
+
 size_t
 tyidfmt(char *buf, size_t sz, Type *ty)
 {
@@ -1067,7 +1106,6 @@
 void
 tyinit(Stab *st)
 {
-	int i;
 	Type *ty;
 	Trait *tr;
 
@@ -1083,41 +1121,6 @@
 	puttrait(st, tr->name, tr);
 #include "trait.def"
 #undef Tc
-
-	/* char::(numeric,integral) */
-	traits[Tychar][0] = traittab[Tcnum];
-	traits[Tychar][1] = traittab[Tcint];
-
-	traits[Tybyte][0] = traittab[Tcnum];
-	traits[Tybyte][1] = traittab[Tcint];
-
-	/* <integer types>::(numeric,integral) */
-	for (i = Tyint8; i < Tyflt32; i++) {
-		traits[i][0] = traittab[Tcnum];
-		traits[i][1] = traittab[Tcint];
-	}
-
-	/* <floats>::(numeric,floating) */
-	traits[Tyflt32][0] = traittab[Tcnum];
-	traits[Tyflt32][1] = traittab[Tcfloat];
-	traits[Tyflt64][0] = traittab[Tcnum];
-	traits[Tyflt64][1] = traittab[Tcfloat];
-
-	/* @a*::(sliceable) */
-	traits[Typtr][0] = traittab[Tcslice];
-
-	/* @a[:]::(indexable,sliceable) */
-	traits[Tyslice][0] = traittab[Tcidx];
-	traits[Tyslice][1] = traittab[Tcslice];
-	traits[Tyslice][2] = traittab[Tciter];
-
-	/* @a[SZ]::(indexable,sliceable) */
-	traits[Tyarray][0] = traittab[Tcidx];
-	traits[Tyarray][1] = traittab[Tcslice];
-	traits[Tyarray][2] = traittab[Tciter];
-
-	/* @a::function */
-	traits[Tyfunc][0] = traittab[Tcfunc];
 
 	/* Definining and registering the types has to go after we define the
 	 * constraints, otherwise they will have no constraints set on them. */
--- a/parse/use.c
+++ b/parse/use.c
@@ -230,11 +230,11 @@
 	/* FIXME: since we only support hardcoded traits, we just write
 	* out the set of them. we should write out the trait list a
 	* well */
-	if (!ty->traits) {
+	if (!ty->trneed) {
 		wrint(fd, 0);
 	} else {
-		wrint(fd, bscount(ty->traits));
-		for (i = 0; bsiter(ty->traits, &i); i++) {
+		wrint(fd, bscount(ty->trneed));
+		for (i = 0; bsiter(ty->trneed, &i); i++) {
 			if (i < Ntraits)
 				wrint(fd, i | Builtinmask);
 			else
@@ -263,7 +263,7 @@
 	case Tyvar:	die("Attempting to pickle %s. This will not work.\n", tystr(ty));	break;
 	case Tyname:
 		pickle(fd, ty->name);
-		wrbool(fd, ty->issynth);
+		wrbool(fd, 0); /* TRFIX: fixme, compat */
 		wrint(fd, ty->narg);
 		for (i = 0; i < ty->narg; i++)
 			wrtype(fd, ty->arg[i]);
@@ -271,7 +271,7 @@
 		break;
 	case Tygeneric:
 		pickle(fd, ty->name);
-		wrbool(fd, ty->issynth);
+		wrbool(fd, 0);	/* TRFIX: fixme, compat */
 		wrint(fd, ty->ngparam);
 		for (i = 0; i < ty->ngparam; i++)
 			wrtype(fd, ty->gparam[i]);
@@ -335,8 +335,11 @@
 	if (tid & Builtinmask) {
 		if (dest)
 			*dest = traittab[tid & ~Builtinmask];
-		if (ty)
-			settrait(ty, traittab[tid & ~Builtinmask]);
+		if (ty) {
+			if (!ty->trneed)
+				ty->trneed = mkbs();
+			bsput(ty->trneed, traittab[tid & ~Builtinmask]->uid);
+		}
 	} else {
 		traitfix = xrealloc(traitfix, (ntraitfix + 1) * sizeof(traitfix[0]));
 		traitfix[ntraitfix++] = (Traitfix){dest, ty, tid};
@@ -366,8 +369,12 @@
 	if (ty->nsub > 0)
 		ty->sub = zalloc(ty->nsub * sizeof(Type *));
 	switch (ty->type) {
-	case Tyunres:	ty->name = unpickle(fd);	break;
-	case Typaram:	ty->pname = rdstr(fd);	break;
+	case Tyunres:
+		ty->name = unpickle(fd);
+		break;
+	case Typaram:	
+		ty->pname = rdstr(fd);
+		break;
 	case Tystruct:
 		ty->nmemb = rdint(fd);
 		ty->sdecls = zalloc(ty->nmemb * sizeof(Node *));
@@ -389,7 +396,7 @@
 		break;
 	case Tyname:
 		ty->name = unpickle(fd);
-		ty->issynth = rdbool(fd);
+		/*TRFIX: ty->issynth = */ rdbool(fd);
 		ty->narg = rdint(fd);
 		ty->arg = zalloc(ty->narg * sizeof(Type *));
 		for (i = 0; i < ty->narg; i++)
@@ -398,7 +405,7 @@
 		break;
 	case Tygeneric:
 		ty->name = unpickle(fd);
-		ty->issynth = rdbool(fd);
+		/* TRFIX: ty->issynth = */ rdbool(fd);
 		ty->ngparam = rdint(fd);
 		ty->gparam = zalloc(ty->ngparam * sizeof(Type *));
 		for (i = 0; i < ty->ngparam; i++)
@@ -799,7 +806,7 @@
 	/* check for duplicate type definitions */
 	for (i = 0; i < ntypefix; i++) {
 		t = htget(tidmap, itop(typefix[i].id));
-		if ((t->type != Tyname && t->type != Tygeneric) || t->issynth)
+		if ((t->type != Tyname && t->type != Tygeneric))
 			continue;
 		old = tydedup(t);
 		if (!tyeq(t, old) && !isspecialization(t, old))
@@ -834,7 +841,7 @@
 		if (traitfix[i].dest)
 			*traitfix[i].dest = tr;
 		if (traitfix[i].type)
-			settrait(traitfix[i].type, tr);
+			bsput(traitfix[i].type->trneed, tr->uid);
 	}
 
 	free(traitfix);
@@ -882,7 +889,6 @@
 		if (getimpl(st, impl))
 			continue;
 		putimpl(st, impl);
-		settrait(impl->impl.type, tr);
 		for (j = 0; j < impl->impl.ndecls; j++) {
 			putdcl(file->file.globls, impl->impl.decls[j]);
 			protomap(tr, impl->impl.type, impl->impl.decls[j]);
@@ -1008,8 +1014,6 @@
 			htput(tidmap, itop(tid), ty);
 			/* fix up types */
 			if (ty->type == Tyname || ty->type == Tygeneric) {
-				if (ty->issynth)
-					break;
 				if (!streq(s->name, ty->name->name.ns))
 					ty->ishidden = 1;
 				if (!gettype(s, ty->name) && !ty->ishidden)