ref: 5c7910da4770a4495e90eb5c243993ec778d4e68
parent: c8c4b88ecadf05438561c05f97500e35843218c4
author: Ori Bernstein <ori@eigenstate.org>
date: Mon Sep 28 20:19:22 EDT 2015
Complain about missing trait impls. Because exploding with an abort is confusing for the user.
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -2348,6 +2348,24 @@
popstab();
}
+void verify(Inferstate *st, Node *f)
+{
+ Node *n;
+ size_t i;
+
+ pushstab(f->file.globls);
+ /* for now, traits can only be declared globally */
+ for (i = 0; i < f->file.nstmts; i++) {
+ if (f->file.stmts[i]->type == Nimpl) {
+ n = f->file.stmts[i];
+ /* we merge, so we need to get it back again when error checking */
+ if (n->impl.isproto)
+ fatal(n, "missing implementation for prototype '%s %s'",
+ namestr(n->impl.traitname), tystr(n->impl.type));
+ }
+ }
+}
+
void infer(Node *file)
{
Inferstate st = {0,};
@@ -2366,5 +2384,6 @@
/* and replace type vars with actual types */
typesub(&st, file, 0);
specialize(&st, file);
+ verify(&st, file);
}
--- a/parse/stab.c
+++ b/parse/stab.c
@@ -373,6 +373,9 @@
static int mergetrait(Trait *old, Trait *new)
{
+ Vis vis;
+
+ vis = max(old->vis, new->vis);
if (old->isproto && !new->isproto)
*old = *new;
else if (new->isproto && !old->isproto)
@@ -379,6 +382,8 @@
*new = *old;
else
return 0;
+ old->vis = vis;
+ new->vis = vis;
return 1;
}
@@ -403,6 +408,9 @@
static int mergeimpl(Node *old, Node *new)
{
+ Vis vis;
+
+ vis = max(old->impl.vis, new->impl.vis);
if (old->impl.isproto && !new->impl.isproto)
*old = *new;
else if (new->impl.isproto && !old->impl.isproto)
@@ -409,6 +417,8 @@
*new = *old;
else
return 0;
+ old->impl.vis = vis;
+ new->impl.vis = vis;
return 1;
}