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: nob...@puremagic.com ReportedBy: nfx...@gmail.com --- Comment #0 from nfx...@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: -------