Note: This website is archived. For up-to-date information about D projects and development, please visit wiki.dlang.org.

Changeset 811

Show
Ignore:
Timestamp:
12/22/10 09:01:22 (14 years ago)
Author:
walter
Message:

better fix for the recursive template constraint issue

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/src/mars.c

    r737 r811  
    7575#else 
    7676#error "fix this" 
    7777#endif 
    7878 
    7979#if TARGET_WINDOS 
    8080    dll_ext  = "dll"; 
    8181#elif TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS 
    8282    dll_ext  = "so"; 
    8383#elif TARGET_OSX 
    8484    dll_ext = "dylib"; 
    8585#else 
    8686#error "fix this" 
    8787#endif 
    8888 
    8989    copyright = "Copyright (c) 1999-2010 by Digital Mars"; 
    9090    written = "written by Walter Bright" 
    9191#if TARGET_NET 
    9292    "\nMSIL back-end (alpha release) by Cristian L. Vlasceanu and associates."; 
    9393#endif 
    9494    ; 
    95     version = "v2.051"; 
     95    version = "v2.052"; 
    9696    global.structalign = 8; 
    9797 
    9898    memset(&params, 0, sizeof(Param)); 
    9999} 
    100100 
    101101char *Loc::toChars() 
    102102{ 
    103103    OutBuffer buf; 
    104104    char *p; 
    105105 
    106106    if (filename) 
    107107    { 
    108108        buf.printf("%s", filename); 
    109109    } 
    110110 
    111111    if (linnum) 
    112112        buf.printf("(%d)", linnum); 
    113113    buf.writeByte(0); 
    114114    return (char *)buf.extractData(); 
    115115} 
  • trunk/src/template.c

    r810 r811  
    12981298            } 
    12991299            declareParameter(paramscope, tparam, oded); 
    13001300            dedargs->data[i] = (void *)oded; 
    13011301        } 
    13021302    } 
    13031303 
    13041304#if DMDV2 
    13051305    if (constraint) 
    13061306    {   /* Check to see if constraint is satisfied. 
    13071307         */ 
    13081308        makeParamNamesVisibleInConstraint(paramscope); 
    13091309        Expression *e = constraint->syntaxCopy(); 
    13101310        paramscope->flags |= SCOPEstaticif; 
    13111311 
    13121312        /* Detect recursive attempts to instantiate this template declaration, 
    13131313         * Bugzilla 4072 
    13141314         *  void foo(T)(T x) if (is(typeof(foo(x)))) { } 
    13151315         *  static assert(!is(typeof(foo(7)))); 
    13161316         * Recursive attempts are regarded as a constraint failure. 
    13171317         */ 
    1318         /* Previous should also store the scope, as instantiations along a different scope branch 
    1319          * should not conflict 
    1320          */ 
    13211318        int nmatches = 0; 
    13221319        for (Previous *p = previous; p; p = p->prev) 
    13231320        { 
    13241321            if (arrayObjectMatch(p->dedargs, dedargs, this, sc)) 
    13251322            { 
    1326                 //printf("recursive, no match %p %s\n", this, this->toChars()); 
    1327                 nmatches++; 
     1323                //printf("recursive, no match p->sc=%p %p %s\n", p->sc, this, this->toChars()); 
     1324                /* It must be a subscope of p->sc, other scope chains are not recursive 
     1325                 * instantiations. 
     1326                 */ 
     1327                for (Scope *scx = sc; scx; scx = scx->enclosing) 
     1328                { 
     1329                    if (scx == p->sc) 
     1330                        goto Lnomatch; 
     1331                } 
    13281332            } 
    13291333            /* BUG: should also check for ref param differences 
    13301334             */ 
    13311335        } 
    1332         /* Look for 2 matches at least, because sometimes semantic3() gets run causing what appears to 
    1333          * be recursion but isn't. 
    1334          * Template A's constraint instantiates B, B's semantic3() run includes something that has A in its constraint. 
    1335          * Perhaps a better solution is to always defer semantic3() rather than doing it eagerly. The risk 
    1336          * with that is what if semantic3() fails, but our constraint "succeeded"? 
    1337          */ 
    1338         if (nmatches >= 2) 
    1339             goto Lnomatch; 
    13401336 
    13411337        Previous pr; 
    13421338        pr.prev = previous; 
     1339        pr.sc = paramscope; 
    13431340        pr.dedargs = dedargs; 
    13441341        previous = ≺                 // add this to threaded list 
    13451342 
    13461343        int nerrors = global.errors; 
    13471344 
    13481345        e = e->semantic(paramscope); 
    13491346 
    13501347        previous = pr.prev;             // unlink from threaded list 
    13511348 
    13521349        if (nerrors != global.errors)   // if any errors from evaluating the constraint, no match 
    13531350            goto Lnomatch; 
    13541351 
    13551352        e = e->optimize(WANTvalue | WANTinterpret); 
    13561353        if (e->isBool(TRUE)) 
    13571354            ; 
    13581355        else if (e->isBool(FALSE)) 
    13591356            goto Lnomatch; 
    13601357        else 
    13611358        { 
    13621359            e->error("constraint %s is not constant or does not evaluate to a bool", e->toChars()); 
     
    37023699 
    37033700    if (s) 
    37043701        ti = (TemplateInstance *)s; 
    37053702    else 
    37063703        ti = new TemplateInstance(loc, name); 
    37073704 
    37083705    ti->tiargs = arraySyntaxCopy(tiargs); 
    37093706 
    37103707    ScopeDsymbol::syntaxCopy(ti); 
    37113708    return ti; 
    37123709} 
    37133710 
    37143711 
    37153712void TemplateInstance::semantic(Scope *sc) 
    37163713{ 
    37173714    semantic(sc, NULL); 
    37183715} 
    37193716 
    37203717void TemplateInstance::semantic(Scope *sc, Expressions *fargs) 
    37213718{ 
    3722     //printf("TemplateInstance::semantic('%s', this=%p, gag = %d)\n", toChars(), this, global.gag); 
     3719    //printf("TemplateInstance::semantic('%s', this=%p, gag = %d, sc = %p)\n", toChars(), this, global.gag, sc); 
    37233720    if (global.errors && name != Id::AssociativeArray) 
    37243721    { 
    37253722        //printf("not instantiating %s due to %d errors\n", toChars(), global.errors); 
    37263723        if (!global.gag) 
    37273724        { 
    37283725            /* Trying to soldier on rarely generates useful messages 
    37293726             * at this point. 
    37303727             */ 
    37313728            fatal(); 
    37323729        } 
    37333730//        return; 
    37343731    } 
    37353732#if LOG 
    37363733    printf("\n+TemplateInstance::semantic('%s', this=%p)\n", toChars(), this); 
    37373734#endif 
    37383735    if (inst)           // if semantic() was already run 
    37393736    { 
    37403737#if LOG 
    37413738        printf("-TemplateInstance::semantic('%s', this=%p) already run\n", inst->toChars(), inst); 
    37423739#endif 
  • trunk/src/template.h

    r809 r811  
    4949struct TemplateDeclaration : ScopeDsymbol 
    5050{ 
    5151    TemplateParameters *parameters;     // array of TemplateParameter's 
    5252 
    5353    TemplateParameters *origParameters; // originals for Ddoc 
    5454    Expression *constraint; 
    5555    Array instances;                    // array of TemplateInstance's 
    5656 
    5757    TemplateDeclaration *overnext;      // next overloaded TemplateDeclaration 
    5858    TemplateDeclaration *overroot;      // first in overnext list 
    5959 
    6060    int semanticRun;                    // 1 semantic() run 
    6161 
    6262    Dsymbol *onemember;         // if !=NULL then one member of this template 
    6363 
    6464    int literal;                // this template declaration is a literal 
    6565    int ismixin;                // template declaration is only to be used as a mixin 
    6666 
    6767    struct Previous 
    6868    {   Previous *prev; 
     69        Scope *sc; 
    6970        Objects *dedargs; 
    7071    }; 
    7172    Previous *previous;         // threaded list of previous instantiation attempts on stack 
    7273 
    7374    TemplateDeclaration(Loc loc, Identifier *id, TemplateParameters *parameters, 
    7475        Expression *constraint, Dsymbols *decldefs, int ismixin); 
    7576    Dsymbol *syntaxCopy(Dsymbol *); 
    7677    void semantic(Scope *sc); 
    7778    int overloadInsert(Dsymbol *s); 
    7879    void toCBuffer(OutBuffer *buf, HdrGenState *hgs); 
    7980    const char *kind(); 
    8081    char *toChars(); 
    8182 
    8283    void emitComment(Scope *sc); 
    8384    void toJsonBuffer(OutBuffer *buf); 
    8485//    void toDocBuffer(OutBuffer *buf); 
    8586 
    8687    MATCH matchWithInstance(TemplateInstance *ti, Objects *atypes, int flag); 
    8788    MATCH leastAsSpecialized(TemplateDeclaration *td2); 
    8889