[Issue 4028] New: delegates with differing default arguments lead to same template instantiation
d-bugmail at puremagic.com
d-bugmail at puremagic.com
Mon Mar 29 16:02:32 PDT 2010
http://d.puremagic.com/issues/show_bug.cgi?id=4028
Summary: delegates with differing default arguments lead to
same template instantiation
Product: D
Version: 1.057
Platform: Other
OS/Version: All
Status: NEW
Keywords: wrong-code
Severity: major
Priority: P2
Component: DMD
AssignedTo: nobody at puremagic.com
ReportedBy: nfxjfg at gmail.com
--- Comment #0 from nfxjfg at gmail.com 2010-03-29 16:02:30 PDT ---
Look at these two delegates:
void delegate(int x = 123) D_A;
void delegate(int x) D_B;
They have the same type, but they behave differently. E.g. you can call D_A(),
but not D_B().
They lead to the same template instantiation:
void foo(T)(T del) {
}
foo(D_A) and foo(D_B) will be the same template instantiations.
This is a bug, because foo(D_B) will think that del has a default parameter,
which is obviously not the case. dmd should instantiate two different templates
for it. Maybe make delegates with different default args have different types.
Here's a test case, which demonstrates how this can lead to trouble in real
world programs. The code is ripped out from a scripting wrapper, which tries to
support default arguments. (The reason why doMethod is templated on a delegate
and not on the class/method is to drastically reduce the number of template
instantiations.)
import std.stdio;
template ParameterTupleOf( Fn )
{
static if( is( Fn Params == function ) )
alias Params ParameterTupleOf;
else static if( is( Fn Params == delegate ) )
alias ParameterTupleOf!(Params) ParameterTupleOf;
else static if( is( Fn Params == Params* ) )
alias ParameterTupleOf!(Params) ParameterTupleOf;
else
static assert( false, "Argument has no parameters." );
}
int requiredArgCount(alias Fn)() {
alias ParameterTupleOf!(typeof(Fn)) Params;
Params p;
static if (is(typeof(Fn())))
return 0;
foreach (int idx, x; p) {
static if (is(typeof(Fn(p[0..idx+1]))))
return idx+1;
}
assert(false);
}
class Foo {
void moo1() {}
void moo2(short x) {}
void moo3(int x = 123) {}
void moo4(int x) {}
}
void doMethod(T)(T del, char[] name, char[] expect) {
writefln("method %s, required arg count: got %s, expected %s", name,
requiredArgCount!(del)(), expect);
}
void method(Class, char[] name)(char[] expect) {
auto fn = mixin("&Class." ~ name);
doMethod(fn, name, expect);
}
void main() {
//just to prove that the other code works
method!(Foo, "moo1")("0");
method!(Foo, "moo2")("1");
//here starts the problem
//moo3 instantiates doMethod!(void delegate(int x = 123))
method!(Foo, "moo3")("0");
//moo4 _should_ instantiate doMethod!(void delegate(int x))
//but it really insantiates the same as moo3:
// doMethod!(void delegate(int x = 123))
//this is obviously wrong!
//doMethod() will think that moo4 has a default argument, when it
//really hasn't (you can see that in the runtime output of this program)
method!(Foo, "moo4")("1");
}
--
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
More information about the Digitalmars-d-bugs
mailing list