shithub: mc

Download patch

ref: 77a5bd52ac777a95a22395227f29084e49569370
parent: 3dc461b0b09aae0b89c6310fe572f1bd7f693395
author: Ori Bernstein <ori@eigenstate.org>
date: Thu Dec 24 17:00:51 EST 2015

Fix scoping issues.

--- a/parse/infer.c
+++ b/parse/infer.c
@@ -1598,7 +1598,6 @@
 	n->impl.trait = t;
 
 	dcl = NULL;
-	proto = NULL;
 	if (n->impl.naux != t->naux)
 		fatal(n, "%s incompatibly specialized with %zd types instead of %zd types",
 			namestr(n->impl.traitname), n->impl.naux, t->naux);
@@ -1620,7 +1619,7 @@
 		if (file->file.globls->name)
 			setns(dcl->decl.name, file->file.globls->name);
 		for (j = 0; j < t->nfuncs; j++) {
-			if (nameeq(dcl->decl.name, t->funcs[j]->decl.name)) {
+			if (nsnameeq(dcl->decl.name, t->funcs[j]->decl.name)) {
 				proto = t->funcs[j];
 				break;
 			}
@@ -2397,8 +2396,8 @@
 	/* tag the traits */
 	free(k);
 	k = htkeys(st->tr, &n);
-	for (i = 0; i < n; i++) {
-		tr = gettrait(st, k[i]);
+	for (j = 0; j < n; j++) {
+		tr = gettrait(st, k[j]);
 		if (tr->vis == Visexport) {
 			tr->param->vis = Visexport;
 			for (i = 0; i < tr->nmemb; i++) {
@@ -2448,22 +2447,35 @@
 void applytraits(Inferstate *st, Node *f)
 {
 	size_t i;
-	Node *n;
+	Node *impl, *n;
 	Trait *tr;
 	Type *ty;
+	Stab *ns;
 
+	tr = NULL;
 	pushstab(f->file.globls);
 	/* for now, traits can only be declared globally */
 	for (i = 0; i < nimpltab; i++) {
-		n = impltab[i];
-		tr = gettrait(f->file.globls, n->impl.traitname);
-		if (!tr)
-			fatal(n, "trait %s does not exist near %s",
-					namestr(n->impl.traitname), ctxstr(st, n));
-		ty = tf(st, n->impl.type);
+		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(st, impl));
+			if (tr->naux != impl->impl.naux)
+				fatal(impl, "incompatible implementation of %s: mismatched aux types",
+						namestr(impl->impl.traitname), ctxstr(st, impl));
+		}
+		ty = tf(st, impl->impl.type);
 		settrait(ty, tr);
 		if (tr->uid == Tciter) {
-			htput(st->seqbase, tf(st, n->impl.type), tf(st, n->impl.aux[0]));
+			htput(st->seqbase, tf(st, impl->impl.type), tf(st, impl->impl.aux[0]));
 		}
 	}
 	popstab();
--- a/parse/node.c
+++ b/parse/node.c
@@ -471,7 +471,10 @@
 
 void setns(Node *n, char *ns)
 {
-	assert(!n->name.ns || !strcmp(n->name.ns, ns));
+	assert(!ns || !n->name.ns || !strcmp(n->name.ns, ns));
+
+	if (!ns)
+		return;
 	n->name.ns = strdup(ns);
 }
 
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -230,6 +230,7 @@
 			size_t ninit;
 			Node *localinit; /* and the local one, if any */
 			Stab *globls;	/* global symtab */
+			Stab *builtins;	/* global symtab */
 			Htab *ns;	/* namespaces */
 		} file;
 
@@ -465,6 +466,8 @@
 int tyeq(void *a, void *b);
 ulong namehash(void *t);
 int nameeq(void *a, void *b);
+ulong nsnamehash(void *t);
+int nsnameeq(void *a, void *b);
 
 /* util functions */
 char *fname(Srcloc l);
--- a/parse/stab.c
+++ b/parse/stab.c
@@ -53,9 +53,15 @@
 /* name hashing: we want namespaced lookups to find the
  * name even if we haven't set the namespace up, since
  * we can update it after the fact. */
-static ulong nsnamehash(void *n) { return strhash(namestr(n)); }
+ulong nsnamehash(void *n)
+{
+	return strhash(namestr(n));
+}
 
-static int nsnameeq(void *a, void *b) { return a == b || !strcmp(namestr(a), namestr(b)); }
+int nsnameeq(void *a, void *b)
+{
+	return a == b || !strcmp(namestr(a), namestr(b));
+}
 
 static ulong implhash(void *p)
 {
@@ -68,6 +74,21 @@
 	return h;
 }
 
+Stab *findstab(Stab *st, Node *n)
+{
+	Stab *ns;
+
+	if (n->name.ns) {
+		ns = getns(file, n->name.ns);
+		if (!ns) {
+			ns = mkstab(0);
+			updatens(ns, n->name.ns);
+		}
+		st = ns;
+	}
+	return st;
+}
+
 static int impleq(void *pa, void *pb)
 {
 	Node *a, *b;
@@ -252,8 +273,7 @@
 		fatal(e, "export %s declared with different externness on %s:%d", declname(e),
 				fname(g->loc), lnum(g->loc));
 
-	if (new->decl.name->name.ns)
-		setns(old->decl.name, new->decl.name->name.ns);
+	setns(old->decl.name, new->decl.name->name.ns);
 	if (e->decl.type->type == Tyvar)
 		e->decl.type = g->decl.type;
 	else if (g->decl.type->type == Tyvar)
@@ -277,8 +297,7 @@
 
 void forcedcl(Stab *st, Node *s)
 {
-	if (st->name)
-		setns(s->decl.name, st->name);
+	setns(s->decl.name, st->name);
 	htput(st->dcl, s->decl.name, s);
 	assert(htget(st->dcl, s->decl.name) != NULL);
 }
@@ -285,18 +304,9 @@
 
 void putdcl(Stab *st, Node *s)
 {
-	Node *name, *old;
-	Stab *ns;
+	Node *old;
 
-	name = s->decl.name;
-	if (name->name.ns) {
-		ns = getns(file, name->name.ns);
-		if (!ns) {
-			ns = mkstab(0);
-			updatens(ns, name->name.ns);
-		}
-		st = ns;
-	}
+	st = findstab(st, s->decl.name);
 	old = htget(st->dcl, s->decl.name);
 	if (!old)
 		forcedcl(st, s);
@@ -342,8 +352,8 @@
 	Tydefn *td;
 	Type *ty;
 
-	if (st->name)
-		setns(n, st->name);
+	st = findstab(st, n);
+	setns(n, st->name);
 	if (st->name && t && t->name)
 		setns(t->name, st->name);
 
@@ -395,6 +405,7 @@
 	Trait *t;
 	Type *ty;
 
+	st = findstab(st, n);
 	t = gettrait(st, n);
 	if (t && !mergetrait(t, c))
 		fatal(n, "Trait %s already defined on %s:%d", namestr(n), fname(t->loc),
@@ -407,6 +418,7 @@
 	td->loc = n->loc;
 	td->name = n;
 	td->trait = c;
+	setns(td->name, st->name);
 	htput(st->tr, td->name, td);
 }
 
@@ -434,25 +446,17 @@
 
 void putimpl(Stab *st, Node *n)
 {
-	Node *impl, *name;
-	Stab *ns;
+	Node *impl;
 
-	name = n->impl.traitname;
-	if (name->name.ns) {
-		ns = getns(file, name->name.ns);
-		if (!ns) {
-			ns = mkstab(0);
-			updatens(ns, name->name.ns);
-		}
-		st = ns;
-	}
-
+	st = findstab(st, n->impl.traitname);
 	impl = getimpl(st, n);
 	if (impl && !mergeimpl(impl, n))
 		fatal(n, "Trait %s already implemented over %s at %s:%d",
 				namestr(n->impl.traitname), tystr(n->impl.type), fname(n->loc), lnum(n->loc));
-	if (st->name)
-		setns(n->impl.traitname, st->name);
+	/*
+	 * The impl is not defined in this file, so setting the trait name would be a bug here.
+	*/
+	setns(n->impl.traitname, st->name);
 	htput(st->impl, n, n);
 }
 
@@ -493,10 +497,12 @@
 		die("Stab %s already has namespace; Can't set to %s", st->name, name);
 	st->name = strdup(name);
 	htput(file->file.ns, st->name, st);
+
 	k = htkeys(st->dcl, &nk);
 	for (i = 0; i < nk; i++)
 		setns(k[i], name);
 	free(k);
+
 	k = htkeys(st->ty, &nk);
 	for (i = 0; i < nk; i++)
 		setns(k[i], name);