Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Issue 9393 - Partial template specialization and template lambda does not work #1550

Merged
merged 1 commit into from

3 participants

@9rnsr 9rnsr referenced this pull request in D-Programming-Language/phobos
Merged

Add ML style exception handling #1090

@idanarye

Your fix ignores default values for template arguments. If you have:

void foo(T=int)(void delegate(T) bar){
    bar(T.init);
}

Then this will work:

foo!int((x){writeln(x);});

but this won't:

foo((x){writeln(x);});

Those two statements should be identical, since T defaults to int.

@9rnsr
Collaborator

Unfortunately, those are not identical. If a type parameter T appears in the function parameter types, it must be deduced from function arguments.

But, overloading templates based on the specification of T should work.

void foo(T)(void delegate(T) bar){ bar(T.init); }  // #1
void foo()(void delegate(int) bar){ foo!int(bar); }  // #2
foo!int((x){writeln(x);});  // call #1
foo((x){writeln(x);});  // call #2

I'll update this.

@idanarye

If you write the template argument explicitly, the compiler uses that. If you don't, it checks if it can determine it from the function arguments. If not, it checks for default values for the template arguments.

Shouldn't the rule of least surprise dictate that this is how it should work for delegate-argument argument types?

@9rnsr
Collaborator

As I wrote already, "If a type parameter T appears in the function parameter types, it must be deduced from function arguments".
In this case, T appears in the type void delegate(T). So it must be deduced form the lambda argument (x){writeln(x);}. But it does not have an actual parameter type (it must be deduced from void delegate(T)). Current IFTI mechanism never considers T's default type at this point.

Therefore, it is a current IFTI mechanism limitation, not a bug.

@idanarye

I see. Thanks for the lesson!

@9rnsr
Collaborator

Updated.

@WalterBright WalterBright merged commit 5af207f into D-Programming-Language:master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jan 26, 2013
  1. @9rnsr
This page is out of date. Refresh to see the latest.
View
28 src/cast.c
@@ -1745,15 +1745,18 @@ Expression *CommaExp::castTo(Scope *sc, Type *t)
/****************************************
* Set type inference target
+ * t Target type
* flag 1: don't put an error when inference fails
+ * sc it is used for the semantic of t, when != NULL
+ * tparams template parameters should be inferred
*/
-Expression *Expression::inferType(Type *t, int flag, TemplateParameters *tparams)
+Expression *Expression::inferType(Type *t, int flag, Scope *sc, TemplateParameters *tparams)
{
return this;
}
-Expression *ArrayLiteralExp::inferType(Type *t, int flag, TemplateParameters *tparams)
+Expression *ArrayLiteralExp::inferType(Type *t, int flag, Scope *sc, TemplateParameters *tparams)
{
if (t)
{
@@ -1764,7 +1767,7 @@ Expression *ArrayLiteralExp::inferType(Type *t, int flag, TemplateParameters *tp
for (size_t i = 0; i < elements->dim; i++)
{ Expression *e = (*elements)[i];
if (e)
- { e = e->inferType(tn, flag, tparams);
+ { e = e->inferType(tn, flag, sc, tparams);
(*elements)[i] = e;
}
}
@@ -1773,7 +1776,7 @@ Expression *ArrayLiteralExp::inferType(Type *t, int flag, TemplateParameters *tp
return this;
}
-Expression *AssocArrayLiteralExp::inferType(Type *t, int flag, TemplateParameters *tparams)
+Expression *AssocArrayLiteralExp::inferType(Type *t, int flag, Scope *sc, TemplateParameters *tparams)
{
if (t)
{
@@ -1785,14 +1788,14 @@ Expression *AssocArrayLiteralExp::inferType(Type *t, int flag, TemplateParameter
for (size_t i = 0; i < keys->dim; i++)
{ Expression *e = (*keys)[i];
if (e)
- { e = e->inferType(ti, flag, tparams);
+ { e = e->inferType(ti, flag, sc, tparams);
(*keys)[i] = e;
}
}
for (size_t i = 0; i < values->dim; i++)
{ Expression *e = (*values)[i];
if (e)
- { e = e->inferType(tv, flag, tparams);
+ { e = e->inferType(tv, flag, sc, tparams);
(*values)[i] = e;
}
}
@@ -1801,7 +1804,7 @@ Expression *AssocArrayLiteralExp::inferType(Type *t, int flag, TemplateParameter
return this;
}
-Expression *FuncExp::inferType(Type *to, int flag, TemplateParameters *tparams)
+Expression *FuncExp::inferType(Type *to, int flag, Scope *sc, TemplateParameters *tparams)
{
if (!to)
return this;
@@ -1859,7 +1862,10 @@ Expression *FuncExp::inferType(Type *to, int flag, TemplateParameters *tparams)
Type *tprm = p->type;
if (tprm->reliesOnTident(tparams))
goto L1;
- tprm = tprm->semantic(loc, td->scope);
+ if (sc)
+ tprm = tprm->semantic(loc, sc);
+ if (tprm->ty == Terror)
+ goto L1;
tiargs->push(tprm);
u = dim; // break inner loop
}
@@ -1915,13 +1921,13 @@ Expression *FuncExp::inferType(Type *to, int flag, TemplateParameters *tparams)
return e;
}
-Expression *CondExp::inferType(Type *t, int flag, TemplateParameters *tparams)
+Expression *CondExp::inferType(Type *t, int flag, Scope *sc, TemplateParameters *tparams)
{
if (t)
{
t = t->toBasetype();
- e1 = e1->inferType(t, flag, tparams);
- e2 = e2->inferType(t, flag, tparams);
+ e1 = e1->inferType(t, flag, sc, tparams);
+ e2 = e2->inferType(t, flag, sc, tparams);
}
return this;
}
View
10 src/expression.h
@@ -142,7 +142,7 @@ struct Expression : Object
virtual MATCH implicitConvTo(Type *t);
virtual IntRange getIntRange();
virtual Expression *castTo(Scope *sc, Type *t);
- virtual Expression *inferType(Type *t, int flag = 0, TemplateParameters *tparams = NULL);
+ virtual Expression *inferType(Type *t, int flag = 0, Scope *sc = NULL, TemplateParameters *tparams = NULL);
virtual void checkEscape();
virtual void checkEscapeRef();
virtual Expression *resolveLoc(Loc loc, Scope *sc);
@@ -453,7 +453,7 @@ struct ArrayLiteralExp : Expression
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
- Expression *inferType(Type *t, int flag = 0, TemplateParameters *tparams = NULL);
+ Expression *inferType(Type *t, int flag = 0, Scope *sc = NULL, TemplateParameters *tparams = NULL);
dt_t **toDt(dt_t **pdt);
Expression *doInline(InlineDoState *ids);
@@ -479,7 +479,7 @@ struct AssocArrayLiteralExp : Expression
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
- Expression *inferType(Type *t, int flag = 0, TemplateParameters *tparams = NULL);
+ Expression *inferType(Type *t, int flag = 0, Scope *sc = NULL, TemplateParameters *tparams = NULL);
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
@@ -684,7 +684,7 @@ struct FuncExp : Expression
Expression *implicitCastTo(Scope *sc, Type *t);
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
- Expression *inferType(Type *t, int flag = 0, TemplateParameters *tparams = NULL);
+ Expression *inferType(Type *t, int flag = 0, Scope *sc = NULL, TemplateParameters *tparams = NULL);
char *toChars();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
elem *toElem(IRState *irs);
@@ -1654,7 +1654,7 @@ struct CondExp : BinExp
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
- Expression *inferType(Type *t, int flag = 0, TemplateParameters *tparams = NULL);
+ Expression *inferType(Type *t, int flag = 0, Scope *sc = NULL, TemplateParameters *tparams = NULL);
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
View
4 src/template.c
@@ -1507,7 +1507,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec
if (farg->op == TOKfunction)
{ FuncExp *fe = (FuncExp *)farg;
Type *tp = prmtype;
- Expression *e = fe->inferType(tp, 1, parameters);
+ Expression *e = fe->inferType(tp, 1, paramscope, inferparams);
if (!e)
goto Lvarargs;
farg = e;
@@ -1695,7 +1695,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec
{ FuncExp *fe = (FuncExp *)arg;
Type *tp = tb->nextOf();
- Expression *e = fe->inferType(tp, 1, parameters);
+ Expression *e = fe->inferType(tp, 1, paramscope, inferparams);
if (!e)
goto Lnomatch;
arg = e;
View
25 test/runnable/funclit.d
@@ -717,6 +717,30 @@ void test9153()
}
/***************************************************/
+// 9393
+
+template ifThrown9393a(E)
+{
+ void ifThrown9393a(T)(scope T delegate(E) errHandler)
+ {
+ }
+}
+void ifThrown9393b(E, T)(scope T delegate(E) errHandler)
+{
+}
+
+void foo9393(T)(void delegate(T) dg){ dg(T.init); }
+void foo9393()(void delegate(int) dg){ foo9393!int(dg); }
+
+void test9393()
+{
+ ifThrown9393a!Exception(e => 10);
+ ifThrown9393b!Exception(e => 10);
+
+ foo9393((x){ assert(x == int.init); });
+}
+
+/***************************************************/
int main()
{
@@ -758,6 +782,7 @@ int main()
test8496();
test8575();
test9153();
+ test9393();
printf("Success\n");
return 0;
Something went wrong with that request. Please try again.