shithub: mc

Download patch

ref: eff57189af8d9eb2d05005f65d3598b28379b199
parent: 6c0abd35bf78b06cc3e25d36312609934e443952
author: Ori Bernstein <[email protected]>
date: Mon Oct 21 19:44:40 EDT 2013

Improve error messages.

--- a/parse/infer.c
+++ b/parse/infer.c
@@ -99,7 +99,23 @@
     return s;
 }
 
+void typeerror(Inferstate *st, Type *a, Type *b, Node *ctx, char *msg)
+{
+    char *t1, *t2, *c;
 
+    t1 = tystr(a);
+    t2 = tystr(b);
+    c = ctxstr(st, ctx);
+    if (msg)
+        fatal(ctx->line, "Type \"%s\" incompatible with \"%s\" near %s: %s", t1, t2, c, msg);
+    else
+        fatal(ctx->line, "Type \"%s\" incompatible with \"%s\" near %s", t1, t2, c);
+    free(t1);
+    free(t2);
+    free(c);
+}
+
+
 /* Set a scope's enclosing scope up correctly.
  * We don't do this in the parser for some reason. */
 static void setsuper(Stab *st, Stab *super)
@@ -473,7 +489,7 @@
             a->cstrs = mkbs();
         setcstr(a, c);
     } else if (!a->cstrs || !bshas(a->cstrs, c->cid)) {
-            fatal(ctx->line, "%s needs %s near %s", tystr(a), c->name, ctxstr(st, ctx));
+        fatal(ctx->line, "%s needs %s near %s", tystr(a), c->name, ctxstr(st, ctx));
     }
 }
 
@@ -581,6 +597,7 @@
     Type *t, *r;
     Type *a, *b;
     char *from, *to;
+    char buf[256];
     size_t i;
 
     /* a ==> b */
@@ -616,20 +633,25 @@
             htput(st->delayed, b, htget(st->delayed, a));
         else if (hthas(st->delayed, b) && !hthas(st->delayed, a))
             htput(st->delayed, a, htget(st->delayed, b));
+    } else if (hthas(st->delayed, a)) {
+        t = htget(st->delayed, a);
+        if (tybase(t)->type != tybase(b)->type)
+            typeerror(st, t, b, ctx, NULL);
     }
 
     /* Disallow recursive types */
-    if (a->type == Tyvar && b->type != Tyvar) 
+   if (a->type == Tyvar && b->type != Tyvar)  {
         if (occurs(a, b))
-            fatal(ctx->line, "Infinite type %s in %s near %s",
-                  tystr(a), tystr(b), ctxstr(st, ctx));
+            typeerror(st, a, b, ctx, "Infinite type\n");
+   }
 
     /* if the tyrank of a is 0 (ie, a raw tyvar), just unify.
      * Otherwise, match up subtypes. */
     if ((a->type == b->type || idxhacked(a, b)) && tyrank(a) != 0) {
-        if (a->nsub != b->nsub)
-            fatal(ctx->line, "%s has wrong subtype count for %s (got %d, expected %d) near %s",
-                  tystr(a), tystr(b), a->nsub, b->nsub, ctxstr(st, ctx));
+        if (a->nsub != b->nsub) {
+            snprintf(buf, sizeof buf, "Wrong subtype count - Got %zu, expected %zu", a->nsub, b->nsub);
+            typeerror(st, a, b, ctx, buf);
+        }
         for (i = 0; i < b->nsub; i++)
             unify(st, ctx, a->sub[i], b->sub[i]);
         r = b;
@@ -637,16 +659,13 @@
         /* Only Tygeneric and Tyname should be able to unify. And they
          * should have the same names for this to be true. */
         if (!nameeq(a->name, b->name))
-            fatal(ctx->line, "%s incompatible with %s near %s",
-                  tystr(a), tystr(b), ctxstr(st, ctx));
+            typeerror(st, a, b, ctx, NULL);
         if (a->narg != b->narg)
-            fatal(ctx->line, "%s has wrong parameter list for %s near %s",
-                  tystr(a), tystr(b), ctxstr(st, ctx));
+            typeerror(st, a, b, ctx, "Incompatible parameter lists");
         for (i = 0; i < a->narg; i++)
             unify(st, ctx, a->arg[i], b->arg[i]);
     } else if (a->type != Tyvar) {
-        fatal(ctx->line, "%s incompatible with %s near %s",
-              tystr(a), tystr(b), ctxstr(st, ctx));
+        typeerror(st, a, b, ctx, NULL);
     }
     mergecstrs(st, ctx, a, b);
     membunify(st, ctx, a, b);