ref: f50159ce18288e7c22fbef33617e6226bd1ef87b
parent: 29bd0da380f893e1f031c36878676a460fd18402
author: Ori Bernstein <ori@eigenstate.org>
date: Fri Jan 29 20:00:40 EST 2016
Give better errors on infinite types. We used to miss some of them, and we used to givea a confusing error about incompatibility.
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -262,7 +262,7 @@
* Recursive types that contain themselves through
* pointers or slices are fine, but any other self-inclusion
* would lead to a value of infinite size */
-static int tyinfinite(Inferstate *st, Type *t, Type *sub)
+static int occurs(Inferstate *st, Type *t, Type *sub)
{
size_t i;
@@ -278,20 +278,21 @@
switch (sub->type) {
case Tystruct:
for (i = 0; i < sub->nmemb; i++)
- if (tyinfinite(st, t, decltype(sub->sdecls[i])))
+ if (occurs(st, t, decltype(sub->sdecls[i])))
return 1;
break;
case Tyunion:
for (i = 0; i < sub->nmemb; i++) {
- if (sub->udecls[i]->etype && tyinfinite(st, t, sub->udecls[i]->etype))
+ if (sub->udecls[i]->etype && occurs(st, t, sub->udecls[i]->etype))
return 1;
}
break;
case Typtr:
- case Tyslice: return 0;
+ case Tyslice:
+ return 0;
default:
for (i = 0; i < sub->nsub; i++)
- if (tyinfinite(st, t, sub->sub[i]))
+ if (occurs(st, t, sub->sub[i]))
return 1;
break;
}
@@ -426,7 +427,7 @@
bsunion(t->traits, base->traits);
else if (base->traits)
t->traits = bsdup(base->traits);
- if (tyinfinite(st, t, NULL))
+ if (occurs(st, t, NULL))
lfatal(t->loc, "type %s includes itself", tystr(t));
st->ingeneric--;
if (t->type == Tyname || t->type == Tygeneric) {
@@ -784,21 +785,6 @@
}
}
-/* Tells us if we have an index hack on the type */
-/* prevents types that contain themselves in the unification;
- * eg @a U (@a -> foo) */
-static int occurs(Type *a, Type *b)
-{
- size_t i;
-
- if (a == b)
- return 1;
- for (i = 0; i < b->nsub; i++)
- if (occurs(a, b->sub[i]))
- return 1;
- return 0;
-}
-
/* Computes the 'rank' of the type; ie, in which
* direction should we unify. A lower ranked type
* should be mapped to the higher ranked (ie, more
@@ -954,6 +940,13 @@
free(to);
}
+ /* Disallow recursive types */
+ if (a->type == Tyvar && b->type != Tyvar) {
+ if (occurs(st, a, b))
+ fatal(ctx, "%s occurs within %s, leading to infinite type near %s\n",
+ tystr(a), tystr(b), ctxstr(st, ctx));
+ }
+
r = NULL;
if (a->type == Tyvar) {
tytab[a->tid] = b;
@@ -962,12 +955,6 @@
if (ea && eb)
unify(st, ctx, ea, eb);
r = b;
- }
-
- /* Disallow recursive types */
- if (a->type == Tyvar && b->type != Tyvar) {
- if (occurs(a, b))
- typeerror(st, a, b, ctx, "Infinite type\n");
}
if (a->type == Tyarray && b->type == Tyarray) {
--- a/parse/type.c
+++ b/parse/type.c
@@ -515,7 +515,8 @@
char *end;
char *sep;
- t = tysearch(t);
+ if (t)
+ t = tysearch(t);
sep = "";
p = buf;
end = p + len;