Bug 14736 – [REG2.060] Function Default Parameters Are Lost

Status
RESOLVED
Resolution
INVALID
Severity
regression
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2015-06-25T23:36:00Z
Last change time
2015-06-26T13:53:33Z
Assigned to
nobody
Creator
paul.d.anderson

Comments

Comment #0 by paul.d.anderson — 2015-06-25T23:36:25Z
I'm trying to pass a function pointer while keeping the default parameter values intact. Given the following: import std.traits; import std.stdio; int foo(int a, int b = 1) { return a; } alias FOOP = int function(int, int = 1); struct ST(POOF) { FOOP fctn; this(POOF fctn) { this.fctn = fctn; } void details() { alias PDVA = ParameterDefaultValueTuple!fctn; writefln("typeid(PDVA[0]) = %s", typeid(PDVA[0])); writefln("typeid(PDVA[1]) = %s", typeid(PDVA[1])); } } void main() { FOOP fp = &foo; auto st = ST!FOOP(fp); st.details; } The default parameter value types are void, int: a has no default and b has an int value as its default. If I change line 14 from FOOP fctn; to POOF fctn; The default parameter value types are void, void. In other words the default value for b is no longer there. Why doesn't invoking the template (ST!FOOP) replace POOF in line 14 with FOOP? I don't know if this is related to #3646. If it is, the status of FIXED may be wrong.
Comment #1 by dlang-bugzilla — 2015-06-26T10:52:58Z
Reduced: //////////////// test.d //////////////// alias int function(int, int = 1) FunPtr; struct ST(T) { T fctn; void foo() { fctn(1); } } ST!FunPtr st; //////////////////////////////////////// This is a regression. Introduced in https://github.com/D-Programming-Language/dmd/commit/acc22ce25db42facfe4917aeceabd28a410f4c95
Comment #2 by k.hara.pg — 2015-06-26T13:53:33Z
(In reply to Vladimir Panteleev from comment #1) > Reduced: > [snip] > > This is a regression. > > Introduced in > https://github.com/D-Programming-Language/dmd/commit/ > acc22ce25db42facfe4917aeceabd28a410f4c95 No, it's intentional side-effect to kill cross-talks between function types (issue 3866). A function pointer/delegate type passed to template type parameter, cannot save the default arguments. Explanation code why it's necessary: module test; template X(FP) {} alias x1 = X!(void function(int)); alias x2 = X!(void function(int a = 1)); pragma(msg, x1.mangleof); // 4test12__T1XTPFiZvZ pragma(msg, x2.mangleof); // 4test12__T1XTPFiZvZ A function type does not encode default arguments (it's documented in abi page), so the two instantiations x1 and x2 needs to be mangled as identical. For the reason, compiler intentionally strips off all default arguments in the FP type. Theoretically, default arguments are associated with symbols, not types. So if you pass symbols via alias parameter, it will make different instances, and associated default arguments will work inside template. auto callWithoutArgs(alias f)() { // f is functions or function pointer variables with default arguments. return f(); } void main() { int func1(int x = 1) { return x; } int func2(int x = 2) { return x; } assert(callWithoutArgs!func1() == 1); assert(callWithoutArgs!func2() == 2); int function(int x = 1) fp1 = x => x; int function(int x = 2) fp2 = x => x; assert(callWithoutArgs!fp1() == 1); assert(callWithoutArgs!fp2() == 2); }