diff options
author | Ori Bernstein <ori@eigenstate.org> | 2017-10-29 18:17:29 -0700 |
---|---|---|
committer | Ori Bernstein <ori@eigenstate.org> | 2017-10-29 18:17:29 -0700 |
commit | d359a98ab9cfc42de66ad35333bd6d6c0571b7ca (patch) | |
tree | 863b83c7653535a5e0c141733a0553381052921c /parse | |
parent | 4adc2f773870b45442ed27e5e794ade92e4fe2f0 (diff) | |
download | mc-d359a98ab9cfc42de66ad35333bd6d6c0571b7ca.tar.gz |
Fix traits when exported cross-namespaces.
Diffstat (limited to 'parse')
-rw-r--r-- | parse/export.c | 8 | ||||
-rw-r--r-- | parse/infer.c | 36 | ||||
-rw-r--r-- | parse/node.c | 1 | ||||
-rw-r--r-- | parse/parse.h | 2 | ||||
-rw-r--r-- | parse/stab.c | 3 | ||||
-rw-r--r-- | parse/use.c | 25 |
6 files changed, 41 insertions, 34 deletions
diff --git a/parse/export.c b/parse/export.c index d0657c7..314f880 100644 --- a/parse/export.c +++ b/parse/export.c @@ -278,9 +278,8 @@ tagexports(Node *file, int hidelocal) free(k); /* tag the impls */ - k = htkeys(st->impl, &n); - for (i = 0; i < n; i++) { - s = getimpl(st, k[i]); + for (i = 0; i < file->file.nimpl; i++) { + s = file->file.impl[i]; if (s->impl.vis != Visexport) continue; tagnode(st, s, 0, hidelocal); @@ -289,7 +288,4 @@ tagexports(Node *file, int hidelocal) for (j = 0; j < tr->naux; j++) tr->aux[j]->vis = tr->vis; } - free(k); - } - diff --git a/parse/infer.c b/parse/infer.c index 34c4155..3d84dd1 100644 --- a/parse/infer.c +++ b/parse/infer.c @@ -1923,19 +1923,21 @@ specializeimpl(Node *n) Node *dcl, *proto, *name, *sym; Tysubst *subst; Type *ty; - Trait *t; + Trait *tr; size_t i, j; int generic; + char *traitns; - t = gettrait(curstab(), n->impl.traitname); - if (!t) + tr = gettrait(curstab(), n->impl.traitname); + if (!tr) fatal(n, "no trait %s\n", namestr(n->impl.traitname)); - n->impl.trait = t; + n->impl.trait = tr; + traitns = tr->name->name.ns; dcl = NULL; - if (n->impl.naux != t->naux) + if (n->impl.naux != tr->naux) fatal(n, "%s incompatibly specialized with %zd types instead of %zd types", - namestr(n->impl.traitname), n->impl.naux, t->naux); + namestr(n->impl.traitname), n->impl.naux, tr->naux); n->impl.type = tf(n->impl.type); pushenv(n->impl.type->env); for (i = 0; i < n->impl.naux; i++) @@ -1953,24 +1955,24 @@ specializeimpl(Node *n) here. */ if (file->file.globls->name) - setns(dcl->decl.name, file->file.globls->name); - for (j = 0; j < t->nproto; j++) { - if (nsnameeq(dcl->decl.name, t->proto[j]->decl.name)) { - proto = t->proto[j]; + setns(dcl->decl.name, traitns); + for (j = 0; j < tr->nproto; j++) { + if (nsnameeq(dcl->decl.name, tr->proto[j]->decl.name)) { + proto = tr->proto[j]; break; } } if (!proto) fatal(n, "declaration %s missing in %s, near %s", namestr(dcl->decl.name), - namestr(t->name), ctxstr(n)); + namestr(tr->name), ctxstr(n)); /* infer and unify types */ pushenv(proto->decl.env); - verifytraits(n, t->param, n->impl.type); + verifytraits(n, tr->param, n->impl.type); subst = mksubst(); - substput(subst, t->param, n->impl.type); - for (j = 0; j < t->naux; j++) - substput(subst, t->aux[j], n->impl.aux[j]); + substput(subst, tr->param, n->impl.type); + for (j = 0; j < tr->naux; j++) + substput(subst, tr->aux[j], n->impl.aux[j]); ty = tyspecialize(type(proto), subst, delayed, NULL); substfree(subst); popenv(proto->decl.env); @@ -1987,7 +1989,7 @@ specializeimpl(Node *n) sym = getdcl(file->file.globls, name); if (sym) fatal(n, "trait %s already specialized with %s on %s:%d", - namestr(t->name), tystr(n->impl.type), + namestr(tr->name), tystr(n->impl.type), fname(sym->loc), lnum(sym->loc)); dcl->decl.name = name; putdcl(file->file.globls, dcl); @@ -1998,7 +2000,7 @@ specializeimpl(Node *n) lappend(&proto->decl.gimpl, &proto->decl.ngimpl, dcl); lappend(&proto->decl.gtype, &proto->decl.ngtype, ty); } - dcl->decl.vis = t->vis; + dcl->decl.vis = tr->vis; lappend(&impldecl, &nimpldecl, dcl); if (generic) diff --git a/parse/node.c b/parse/node.c index f6827de..6e9a8ce 100644 --- a/parse/node.c +++ b/parse/node.c @@ -553,6 +553,7 @@ nameeq(void *p1, void *p2) void setns(Node *n, char *ns) { + assert(!ns || !n->name.ns || !strcmp(n->name.ns, ns)); if (!ns) return; n->name.ns = strdup(ns); diff --git a/parse/parse.h b/parse/parse.h index aaba54f..07c0e03 100644 --- a/parse/parse.h +++ b/parse/parse.h @@ -205,6 +205,8 @@ struct Node { Node **init; /* all __init__ function names of our deps. NB, this is a Nname, not an Ndecl */ size_t ninit; + Node **impl; /* impls defined in this file, across all namespaces */ + size_t nimpl; Node *localinit;/* and the local one, if any */ Stab *globls; /* global symtab */ Stab *builtins; /* global symtab */ diff --git a/parse/stab.c b/parse/stab.c index 023e9f7..49fc776 100644 --- a/parse/stab.c +++ b/parse/stab.c @@ -581,6 +581,9 @@ putimpl(Stab *st, Node *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 this is not a duplicate, record it for later export */ + if (!impl) + lappend(&file->file.impl, &file->file.nimpl, n); /* The impl is not defined in this file, so setting the trait name would be a bug here. diff --git a/parse/use.c b/parse/use.c index b25e914..28c48f6 100644 --- a/parse/use.c +++ b/parse/use.c @@ -1032,10 +1032,17 @@ foundextlib: impl = unpickle(f); impl->impl.isextern = 1; impl->impl.vis = vis; - /* specialized declarations always go into the global stab */ + /* + * Unfortunately, impls can insert their symbols into whatever + * namespace the trait comes from. This complicates things a bit. + */ for (i = 0; i < impl->impl.ndecls; i++) { - impl->impl.decls[i]->decl.isglobl = 1; - putdcl(file->file.globls, impl->impl.decls[i]); + dcl = impl->impl.decls[i]; + dcl->decl.isglobl = 1; + ns = file->file.globls; + if (dcl->decl.name->name.ns) + ns = findstab(s, dcl->decl.name->name.ns); + putdcl(ns, dcl); } break; case EOF: @@ -1212,9 +1219,8 @@ writeuse(FILE *f, Node *file) } } - k = htkeys(st->tr, &n); - for (i = 0; i < n; i++) { - tr = gettrait(st, k[i]); + for (i = 0; i < ntraittab; i++) { + tr = traittab[i]; if (tr->uid < Ntraits) continue; if (tr->vis == Visexport || tr->vis == Vishidden) { @@ -1222,19 +1228,16 @@ writeuse(FILE *f, Node *file) traitpickle(f, tr); } } - free(k); - k = htkeys(st->impl, &n); - for (i = 0; i < n; i++) { + for (i = 0; i < nimpltab; i++) { /* merging during inference should remove all protos */ - s = getimpl(st, k[i]); + s = impltab[i]; assert(!s->impl.isproto); if (s->impl.vis == Visexport || s->impl.vis == Vishidden) { wrbyte(f, 'I'); pickle(f, s); } } - free(k); k = htkeys(st->dcl, &n); for (i = 0; i < n; i++) { |