Skip to content

Commit

Permalink
Merge pull request #3210 from 9rnsr/fix12077
Browse files Browse the repository at this point in the history
Issue 12077 - Instantiated type does not match to the specialized alias parameter
  • Loading branch information
WalterBright committed Feb 24, 2014
2 parents cfa49e6 + 60ae588 commit 46832fb
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 26 deletions.
110 changes: 84 additions & 26 deletions src/template.c
Expand Up @@ -582,6 +582,42 @@ void TemplateDeclaration::semantic(Scope *sc)
}
}

/* Calculate TemplateParameter::dependent
*/
TemplateParameters tparams;
tparams.setDim(1);
for (size_t i = 0; i < parameters->dim; i++)
{
TemplateParameter *tp = (*parameters)[i];
tparams[0] = tp;

for (size_t j = 0; j < parameters->dim; j++)
{
// Skip cases like: X(T : T)
if (i == j)
continue;

if (TemplateTypeParameter *ttp = (*parameters)[j]->isTemplateTypeParameter())
{
Type *t = ttp->specType;
if (t && t->reliesOnTident(&tparams))
tp->dependent = true;
}
else if (TemplateAliasParameter *tap = (*parameters)[j]->isTemplateAliasParameter())
{
Type *t = tap->specType;
if (t && t->reliesOnTident(&tparams))
tp->dependent = true;
else if (tap->specAlias)
{
t = isType(tap->specAlias);
if (t && t->reliesOnTident(&tparams))
tp->dependent = true;
}
}
}
}

paramscope->pop();

// Compute again
Expand Down Expand Up @@ -4196,6 +4232,7 @@ TemplateParameter::TemplateParameter(Loc loc, Identifier *ident)
{
this->loc = loc;
this->ident = ident;
this->dependent = false;
this->sparam = NULL;
}

Expand Down Expand Up @@ -4366,7 +4403,8 @@ MATCH TemplateTypeParameter::matchArg(Scope *sc, RootObject *oarg,
//printf("\tcalling deduceType(): ta is %s, specType is %s\n", ta->toChars(), specType->toChars());
MATCH m2 = deduceType(ta, sc, specType, parameters, dedtypes);
if (m2 <= MATCHnomatch)
{ //printf("\tfailed deduceType\n");
{
//printf("\tfailed deduceType\n");
goto Lnomatch;
}

Expand All @@ -4378,11 +4416,13 @@ MATCH TemplateTypeParameter::matchArg(Scope *sc, RootObject *oarg,
else
{
if ((*dedtypes)[i])
{ // Must match already deduced type
{
// Must match already deduced type
Type *t = (Type *)(*dedtypes)[i];

if (!t->equals(ta))
{ //printf("t = %s ta = %s\n", t->toChars(), ta->toChars());
{
//printf("t = %s ta = %s\n", t->toChars(), ta->toChars());
goto Lnomatch;
}
}
Expand All @@ -4397,7 +4437,7 @@ MATCH TemplateTypeParameter::matchArg(Scope *sc, RootObject *oarg,
if (psparam)
*psparam = new AliasDeclaration(loc, ident, ta);
//printf("\tm = %d\n", m);
return m;
return dependent ? MATCHexact : m;

Lnomatch:
if (psparam)
Expand Down Expand Up @@ -4443,10 +4483,8 @@ void TemplateTypeParameter::toCBuffer(OutBuffer *buf, HdrGenState *hgs)

void *TemplateTypeParameter::dummyArg()
{
Type *t;
if (specType)
t = specType;
else
Type *t = specType;
if (!t)
{
// Use this for alias-parameter's too (?)
if (!tdummy)
Expand Down Expand Up @@ -4605,6 +4643,7 @@ MATCH TemplateAliasParameter::matchArg(Scope *sc, RootObject *oarg,
Declaration **psparam)
{
//printf("TemplateAliasParameter::matchArg()\n");
MATCH m = MATCHexact;
RootObject *sa = getDsymbol(oarg);
Expression *ea = isExpression(oarg);
if (ea && (ea->op == TOKthis || ea->op == TOKsuper))
Expand All @@ -4613,11 +4652,15 @@ MATCH TemplateAliasParameter::matchArg(Scope *sc, RootObject *oarg,
sa = ((ScopeExp *)ea)->sds;
if (sa)
{
if (((Dsymbol *)sa)->isAggregateDeclaration())
m = MATCHconvert;

/* specType means the alias must be a declaration with a type
* that matches specType.
*/
if (specType)
{ Declaration *d = ((Dsymbol *)sa)->isDeclaration();
{
Declaration *d = ((Dsymbol *)sa)->isDeclaration();
if (!d)
goto Lnomatch;
if (!d->type->equals(specType))
Expand All @@ -4628,12 +4671,18 @@ MATCH TemplateAliasParameter::matchArg(Scope *sc, RootObject *oarg,
{
sa = oarg;
if (ea)
{ if (specType)
{
if (specType)
{
if (!ea->type->equals(specType))
goto Lnomatch;
}
}
else if (sa && sa == TemplateTypeParameter::tdummy)
{
// Bugzilla 2025: Aggregate Types should preferentially
// match to the template type parameter.
}
else
goto Lnomatch;
}
Expand All @@ -4642,22 +4691,29 @@ MATCH TemplateAliasParameter::matchArg(Scope *sc, RootObject *oarg,
{
if (sa == sdummy)
goto Lnomatch;
if (sa != specAlias && isDsymbol(sa))
Dsymbol *sx = isDsymbol(sa);
if (sa != specAlias && sx)
{
TemplateInstance *ti = isDsymbol(sa)->isTemplateInstance();
Type *ta = isType(specAlias);
if (!ti || !ta)
if (!ta)
goto Lnomatch;

TemplateInstance *ti = sx->isTemplateInstance();
if (!ti && sx->parent)
ti = sx->parent->isTemplateInstance();
if (!ti)
goto Lnomatch;

Type *t = new TypeInstance(Loc(), ti);
MATCH m = deduceType(t, sc, ta, parameters, dedtypes);
if (m <= MATCHnomatch)
MATCH m2 = deduceType(t, sc, ta, parameters, dedtypes);
if (m2 <= MATCHnomatch)
goto Lnomatch;
}
}
else if ((*dedtypes)[i])
{ // Must match already deduced symbol
{
// Must match already deduced symbol
RootObject *si = (*dedtypes)[i];

if (!sa || si != sa)
goto Lnomatch;
}
Expand All @@ -4669,6 +4725,10 @@ MATCH TemplateAliasParameter::matchArg(Scope *sc, RootObject *oarg,
{
*psparam = new AliasDeclaration(loc, ident, s);
}
else if (Type *t = isType(sa))
{
*psparam = new AliasDeclaration(loc, ident, t);
}
else
{
assert(ea);
Expand All @@ -4681,7 +4741,7 @@ MATCH TemplateAliasParameter::matchArg(Scope *sc, RootObject *oarg,
*psparam = v;
}
}
return MATCHexact;
return dependent ? MATCHexact : m;

Lnomatch:
if (psparam)
Expand Down Expand Up @@ -4724,9 +4784,8 @@ void TemplateAliasParameter::toCBuffer(OutBuffer *buf, HdrGenState *hgs)


void *TemplateAliasParameter::dummyArg()
{ RootObject *s;

s = specAlias;
{
RootObject *s = specAlias;
if (!s)
{
if (!sdummy)
Expand Down Expand Up @@ -4967,7 +5026,7 @@ MATCH TemplateValueParameter::matchArg(Scope *sc, RootObject *oarg,
sparam->storage_class = STCmanifest;
*psparam = sparam;
}
return m;
return dependent ? MATCHexact : m;

Lnomatch:
//printf("\tno match\n");
Expand Down Expand Up @@ -5006,9 +5065,8 @@ void TemplateValueParameter::toCBuffer(OutBuffer *buf, HdrGenState *hgs)


void *TemplateValueParameter::dummyArg()
{ Expression *e;

e = specValue;
{
Expression *e = specValue;
if (!e)
{
// Create a dummy value
Expand Down Expand Up @@ -5130,7 +5188,7 @@ MATCH TemplateTupleParameter::matchArg(Scope *sc, RootObject *oarg,

if (psparam)
*psparam = new TupleDeclaration(loc, ident, &ovar->objects);
return MATCHexact;
return dependent ? MATCHexact : MATCHconvert;
}


Expand Down
10 changes: 10 additions & 0 deletions src/template.h
Expand Up @@ -133,6 +133,16 @@ class TemplateParameter
Loc loc;
Identifier *ident;

/* True if this is a part of precedent parameter specialization pattern.
*
* template A(T : X!TL, alias X, TL...) {}
* // X and TL are dependent template parameter
*
* A dependent template parameter should return MATCHexact in matchArg()
* to respect the match level of the corresponding precedent parameter.
*/
bool dependent;

Declaration *sparam;

TemplateParameter(Loc loc, Identifier *ident);
Expand Down
53 changes: 53 additions & 0 deletions test/runnable/template9.d
Expand Up @@ -203,6 +203,47 @@ void test1780()
static assert(is(SQ1780 == Tuple1780!(bool, short)));
}

/**********************************/
// 1659

class Foo1659 { }
class Bar1659 : Foo1659 { }

void f1659(T : Foo1659)() { }
void f1659(alias T)() { static assert(false); }

void test1659()
{
f1659!Bar1659();
}

/**********************************/
// 2025

struct S2025 {}
void f2025() {}

template Foo2025(int i) { enum Foo2025 = 1; }
template Foo2025(TL...) { enum Foo2025 = 2; }
static assert(Foo2025!1 == 1);
static assert(Foo2025!int == 2);
static assert(Foo2025!S2025 == 2);
static assert(Foo2025!f2025 == 2);

template Bar2025(T) { enum Bar2025 = 1; }
template Bar2025(A...) { enum Bar2025 = 2; }
static assert(Bar2025!1 == 2);
static assert(Bar2025!int == 1); // 2 -> 1
static assert(Bar2025!S2025 == 1); // 2 -> 1
static assert(Bar2025!f2025 == 2);

template Baz2025(T) { enum Baz2025 = 1; }
template Baz2025(alias A) { enum Baz2025 = 2; }
static assert(Baz2025!1 == 2);
static assert(Baz2025!int == 1);
static assert(Baz2025!S2025 == 1); // 2 -> 1
static assert(Baz2025!f2025 == 2);

/**********************************/
// 3608

Expand Down Expand Up @@ -3043,6 +3084,18 @@ void test11843()
static assert(!is(typeof(bar3) == typeof(bar4)));
}

/******************************************/
// 12077

struct S12077(A) {}

alias T12077(alias T : Base!Args, alias Base, Args...) = Base;
static assert(__traits(isSame, T12077!(S12077!int), S12077));

alias U12077(alias T : Base!Args, alias Base, Args...) = Base;
alias U12077( T : Base!Args, alias Base, Args...) = Base;
static assert(__traits(isSame, U12077!(S12077!int), S12077));

/******************************************/
// 12122

Expand Down

0 comments on commit 46832fb

Please sign in to comment.