ref: 57813d7182bbe8320407b6722a4093d3bf4f8dcd
parent: 7ce4415a83be2d05432727ee8f672542e1d5e54e
author: Ori Bernstein <[email protected]>
date: Fri Oct 26 11:18:02 EDT 2012
Check if types are generic before specializing them.
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -115,24 +115,6 @@
return 0;
}
-/* Freshens the type of a declaration. */
-static Type *tyfreshen(Inferstate *st, Type *t)
-{
- Htab *ht;
-
- st->ingeneric++;
- t = tf(st, t);
- st->ingeneric--;
-
- tybind(st, t);
- ht = mkht(strhash, streq);
- t = tyspecialize(t, ht);
- htfree(ht);
- tyunbind(st, t);
-
- return t;
-}
-
/* Checks if a type that directly contains itself.
* Recursive types that contain themselves through
* pointers or slices are fine, but any other self-inclusion
@@ -174,6 +156,55 @@
}
return 0;
}
+
+
+static int isgeneric(Inferstate *st, Type *t)
+{
+ size_t i;
+
+ switch (t->type) {
+ case Tygeneric: return 1;
+ case Typaram: return 1;
+ case Tystruct:
+ for (i = 0; i < t->nmemb; i++)
+ if (isgeneric(st, decltype(t->sdecls[i])))
+ return 1;
+ break;
+ case Tyunion:
+ for (i = 0; i < t->nmemb; i++)
+ if (isgeneric(st, t->udecls[i]->etype))
+ return 1;
+ break;
+ default:
+ for (i = 0; i < t->nsub; i++)
+ if (isgeneric(st, t->sub[i]))
+ return 1;
+ break;
+ }
+ return 0;
+}
+
+/* Freshens the type of a declaration. */
+static Type *tyfreshen(Inferstate *st, Type *t)
+{
+ Htab *ht;
+
+ st->ingeneric++;
+ t = tf(st, t);
+ st->ingeneric--;
+
+ if (!isgeneric(st, t))
+ return t;
+
+ tybind(st, t);
+ ht = mkht(strhash, streq);
+ t = tyspecialize(t, ht);
+ htfree(ht);
+ tyunbind(st, t);
+
+ return t;
+}
+
/* Resolves a type and all it's subtypes recursively.*/
static void tyresolve(Inferstate *st, Type *t)