shithub: mc

Download patch

ref: 5bf79c58e3124fa34d04403e0558b5a2ee9233c9
parent: 4dd119870c7bc83217c5719d187ebadb0a3d1bb7
author: Ori Bernstein <[email protected]>
date: Tue Jul 17 10:54:37 EDT 2012

Only allow generics in valid places.

    Don't allow generics outside of generic declarations. This means
    you should no longer be able to do 'const foo : @a' and have it
    get past type checking.

--- a/parse/infer.c
+++ b/parse/infer.c
@@ -680,13 +680,13 @@
     switch (n->type) {
         case Nfile:
             pushstab(n->file.globls);
-            /* exports allow us to specify types later in the body, so we
-             * need to patch the types in if they don't have a definition */
             inferstab(st, n->file.globls);
             inferstab(st, n->file.exports);
             for (i = 0; i < n->file.nstmts; i++) {
                 d  = n->file.stmts[i];
                 infernode(st, d, NULL, sawret);
+                /* exports allow us to specify types later in the body, so we
+                 * need to patch the types in if they don't have a definition */
                 if (d->type == Ndecl)  {
                     s = getdcl(file->file.exports, d->decl.name);
                     if (s)
@@ -696,9 +696,15 @@
             popstab();
             break;
         case Ndecl:
+            if (n->decl.isgeneric)
+                st->ingeneric++;
             bind(st, n);
             inferdecl(st, n);
             unbind(st, n);
+            if (type(st, n)->type == Typaram && !st->ingeneric)
+                fatal(n->line, "Generic type %s in non-generic near %s\n", tystr(type(st, n)), ctxstr(n));
+            if (n->decl.isgeneric)
+                st->ingeneric--;
             break;
         case Nblock:
             setsuper(n->block.scope, curstab());
--- a/test/tests
+++ b/test/tests
@@ -60,3 +60,4 @@
 F union-extraarg
 F union-missingarg
 F match-badtypes
+F generic-in-const