shithub: mc

Download patch

ref: 2f319b2408075aa5165cbc8201bca4ec8a5a58b2
parent: f2fa59d669b6e1470a3c18c545abfbb6fda39ff8
author: Ori Bernstein <[email protected]>
date: Fri Dec 20 06:28:53 EST 2013

Specialize specializes specialized types correctly

    If we specialize option(@a) -> option(@b), we
    used to respecialize on @a, not @b. This would
    lead to spurious type variables if we had,
    for example:

        (x:foo(@x) -> option(@x))

    Because we would generate the following
    specializations:

        foo(@x) => foo($123)
        option(@a) => foo($234)

    instead of

        foo(@x) => foo($123)
        option(@x) => foo($123)

--- a/parse/specialize.c
+++ b/parse/specialize.c
@@ -45,6 +45,7 @@
 {
     Type *ret, *tmp;
     size_t i;
+    Type **subst;
 
     if (hthas(tsmap, t))
         return htget(tsmap, t);
@@ -57,17 +58,21 @@
             if (!hasparams(t)) {
                 ret = t;
             } else {
+                if (t->narg)
+                    subst = t->arg;
+                else
+                    subst = t->param;
                 for (i = 0; i < t->nparam; i++) {
-                    if (hthas(tsmap, t->param[i]))
+                    if (subst[i]->type != Typaram || hthas(tsmap, subst[i]))
                         continue;
-                    tmp = mktyvar(t->param[i]->line);
-                    htput(tsmap, t->param[i], tmp);
+                    tmp = mktyvar(subst[i]->line);
+                    htput(tsmap, subst[i], tmp);
                 }
                 ret = mktyname(t->line, t->name, t->param, t->nparam, tyspecialize(t->sub[0], tsmap));
                 ret->issynth = 1;
                 htput(tsmap, t, ret);
                 for (i = 0; i < t->nparam; i++)
-                    lappend(&ret->arg, &ret->narg, tyspecialize(t->param[i], tsmap));
+                    lappend(&ret->arg, &ret->narg, tyspecialize(subst[i], tsmap));
                 ret->isgeneric = hasparams(ret);
             }
             break;