Skip to content

Commit

Permalink
Merge pull request #983 from 9rnsr/fix8129
Browse files Browse the repository at this point in the history
Issue 8129 - Cannot deduce template function when using partially specified type in function parameter
  • Loading branch information
WalterBright committed Jun 12, 2012
2 parents a210628 + 4b7c17d commit 8fa7bdd
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 10 deletions.
36 changes: 36 additions & 0 deletions src/mtype.c
Original file line number Diff line number Diff line change
Expand Up @@ -4708,6 +4708,15 @@ MATCH TypeAArray::constConv(Type *to)
return Type::constConv(to);
}

Type *TypeAArray::reliesOnTident(TemplateParameters *tparams)
{
Type *t = TypeNext::reliesOnTident(tparams);
if (!t)
t = index->reliesOnTident(tparams);
return t;
}


/***************************** TypePointer *****************************/

TypePointer::TypePointer(Type *t)
Expand Down Expand Up @@ -6814,6 +6823,33 @@ Dsymbol *TypeInstance::toDsymbol(Scope *sc)
return s;
}

Type *TypeInstance::reliesOnTident(TemplateParameters *tparams)
{
if (tparams)
{
for (size_t i = 0; i < tparams->dim; i++)
{
TemplateParameter *tp = (*tparams)[i];
if (tempinst->name == tp->ident)
return this;
}
if (!tempinst->tiargs)
return NULL;
for (size_t i = 0; i < tempinst->tiargs->dim; i++)
{
Type *t = isType((*tempinst->tiargs)[i]);
t = t ? t->reliesOnTident(tparams) : NULL;
if (t)
return t;
}
return NULL;
}
else
{
return Type::reliesOnTident(tparams);
}
}


/***************************** TypeTypeof *****************************/

Expand Down
2 changes: 2 additions & 0 deletions src/mtype.h
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,7 @@ struct TypeAArray : TypeArray
int isZeroInit(Loc loc);
int checkBoolean();
TypeInfoDeclaration *getTypeInfoDeclaration();
Type *reliesOnTident(TemplateParameters *tparams);
Expression *toExpression();
int hasPointers();
TypeTuple *toArgTypes();
Expand Down Expand Up @@ -722,6 +723,7 @@ struct TypeInstance : TypeQualified
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
Type *semantic(Loc loc, Scope *sc);
Dsymbol *toDsymbol(Scope *sc);
Type *reliesOnTident(TemplateParameters *tparams = NULL);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL);
};

Expand Down
40 changes: 30 additions & 10 deletions src/template.c
Original file line number Diff line number Diff line change
Expand Up @@ -954,6 +954,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec
int fvarargs; // function varargs
Objects dedtypes; // for T:T*, the dedargs is the T*, dedtypes is the T
unsigned wildmatch = 0;
TemplateParameters *inferparams = parameters;

TypeFunction *tf = (TypeFunction *)fd->type;

Expand Down Expand Up @@ -1050,6 +1051,16 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec
if (!paramscope->insert(sparam))
goto Lnomatch;
}
if (n < parameters->dim)
{
inferparams = new TemplateParameters();
inferparams->setDim(parameters->dim - n);
memcpy(inferparams->tdata(),
parameters->tdata() + n,
inferparams->dim * sizeof(*inferparams->tdata()));
}
else
inferparams = NULL;
}
#if 0
for (size_t i = 0; i < dedargs->dim; i++)
Expand Down Expand Up @@ -1391,6 +1402,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec
i += tuple_dim - 1;

Parameter *fparam = Parameter::getNth(fparameters, parami);
Type *prmtype = fparam->type;

if (i >= nfargs) // if not enough arguments
{
Expand All @@ -1412,20 +1424,28 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec
Lretry:
#if 0
printf("\tfarg->type = %s\n", farg->type->toChars());
printf("\tfparam->type = %s\n", fparam->type->toChars());
printf("\tfparam->type = %s\n", prmtype->toChars());
#endif
Type *argtype = farg->type;

// Apply function parameter storage classes to parameter types
fparam->type = fparam->type->addStorageClass(fparam->storageClass);
prmtype = prmtype->addStorageClass(fparam->storageClass);

// If parameter type doesn't depend on inferred template parameters,
// semantic it to get actual type.
if (!inferparams || !prmtype->reliesOnTident(inferparams))
{
// should copy prmtype to avoid affecting semantic result
prmtype = prmtype->syntaxCopy()->semantic(loc, paramscope);
}

#if DMDV2
/* Allow string literals which are type [] to match with [dim]
*/
if (farg->op == TOKstring)
{ StringExp *se = (StringExp *)farg;
if (!se->committed && argtype->ty == Tarray &&
fparam->type->toBasetype()->ty == Tsarray)
prmtype->toBasetype()->ty == Tsarray)
{
argtype = new TypeSArray(argtype->nextOf(), new IntegerExp(se->loc, se->len, Type::tindex));
argtype = argtype->semantic(se->loc, NULL);
Expand All @@ -1437,7 +1457,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec
*/
if (farg->op == TOKfunction)
{ FuncExp *fe = (FuncExp *)farg;
Type *tp = fparam->type;
Type *tp = prmtype;
Expression *e = fe->inferType(tp, 1, parameters);
if (!e)
goto Lvarargs;
Expand All @@ -1463,7 +1483,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec
goto Lvarargs;

unsigned wm = 0;
MATCH m = argtype->deduceType(paramscope, fparam->type, parameters, &dedtypes, &wm);
MATCH m = argtype->deduceType(paramscope, prmtype, parameters, &dedtypes, &wm);
//printf("\tdeduceType m = %d\n", m);
//printf("\twildmatch = x%x m = %d\n", wildmatch, m);
wildmatch |= wm;
Expand All @@ -1472,17 +1492,17 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec
* implicit conversions.
*/
if (!m)
m = farg->implicitConvTo(fparam->type);
m = farg->implicitConvTo(prmtype);

/* If no match, see if there's a conversion to a delegate
*/
if (!m)
{ Type *tbp = fparam->type->toBasetype();
{ Type *tbp = prmtype->toBasetype();
Type *tba = farg->type->toBasetype();
AggregateDeclaration *ad;
if (tbp->ty == Tdelegate)
{
TypeDelegate *td = (TypeDelegate *)fparam->type->toBasetype();
TypeDelegate *td = (TypeDelegate *)prmtype->toBasetype();
TypeFunction *tf = (TypeFunction *)td->next;

if (!tf->varargs && Parameter::dim(tf->parameters) == 0)
Expand Down Expand Up @@ -1540,7 +1560,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec
{ if (!farg->isLvalue())
goto Lnomatch;
}
if (!m && (fparam->storageClass & STClazy) && fparam->type->ty == Tvoid &&
if (!m && (fparam->storageClass & STClazy) && prmtype->ty == Tvoid &&
farg->type->ty != Tvoid)
m = MATCHconvert;

Expand All @@ -1560,7 +1580,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec

/* Check for match with function parameter T...
*/
Type *tb = fparam->type->toBasetype();
Type *tb = prmtype->toBasetype();
switch (tb->ty)
{
// Perhaps we can do better with this, see TypeFunction::callMatch()
Expand Down
35 changes: 35 additions & 0 deletions test/runnable/template9.d
Original file line number Diff line number Diff line change
Expand Up @@ -1394,6 +1394,40 @@ void test14()
static assert( Params[2] == 1);
}

/**********************************/
// 8129

class X8129 {}
class A8129 {}
class B8129 : A8129 {}

int foo8129(T : A8129)(X8129 x) { return 1; }
int foo8129(T : A8129)(X8129 x, void function (T) block) { return 2; }

int bar8129(T, R)(R range, T value) { return 1; }

int baz8129(T, R)(R range, T value) { return 1; }
int baz8129(T, R)(R range, Undefined value) { return 2; }

void test8129()
{
auto x = new X8129;
assert(x.foo8129!B8129() == 1);
assert(x.foo8129!B8129((a){}) == 2);
assert(foo8129!B8129(x) == 1);
assert(foo8129!B8129(x, (a){}) == 2);
assert(foo8129!B8129(x) == 1);
assert(foo8129!B8129(x, (B8129 b){}) == 2);

ubyte[] buffer = [0, 1, 2];
assert(bar8129!ushort(buffer, 915) == 1);

// While deduction, parameter type 'Undefined' shows semantic error.
static assert(!__traits(compiles, {
baz8129!ushort(buffer, 915);
}));
}

/**********************************/

int main()
Expand Down Expand Up @@ -1452,6 +1486,7 @@ int main()
test8125();
test13();
test14();
test8129();

printf("Success\n");
return 0;
Expand Down

0 comments on commit 8fa7bdd

Please sign in to comment.