@@ -631,6 +631,25 @@ public struct Listener (API)
631631 package BindChn data;
632632}
633633
634+ // / Helper template to allow default parameters to work
635+ private template ParamsRef (alias Func)
636+ {
637+ import std.meta : EraseAll;
638+ import std.traits : ParameterDefaults;
639+
640+ // / All of the function parameters
641+ private alias All = Parameters! Func;
642+
643+ // / Default parameters matching `Optional`
644+ private enum Default = EraseAll! (void , ParameterDefaults! Func);
645+
646+ // / Only parameters that don't have a default
647+ private alias Required = All[0 .. $ - Default.length];
648+
649+ // / Parameters with a default value
650+ private alias Optional = All[$ - Default.length .. $];
651+ }
652+
634653/* ******************************************************************************
635654
636655 A reference to an alread-instantiated node
@@ -1221,13 +1240,14 @@ public final class RemoteAPI (API, alias S = VibeJSONSerializer!()) : API
12211240 static foreach (ovrld; __traits (getOverloads , API , member))
12221241 {
12231242 mixin (q{
1224- override ReturnType! (ovrld) } ~ member ~ q{ (Parameters! ovrld params)
1243+ override ReturnType! (ovrld) } ~ member ~ q{ (
1244+ ParamsRef! (ovrld).Required required,
1245+ ParamsRef! (ovrld).Optional optional = ParamsRef! (ovrld).Default)
12251246 {
1226-
12271247 // `geod24.concurrency.send/receive[Only]` is not `@safe` but
12281248 // this overload needs to be
12291249 auto res = () @trusted {
1230- auto serialized = S.serialize(ArgWrapper! (Parameters! ovrld)(params ));
1250+ auto serialized = S.serialize(ArgWrapper! (Parameters! ovrld)(required, optional ));
12311251 auto command = Command(this .conn.getNextCommandId(), ovrld.mangleof, SerializedData(serialized));
12321252
12331253 if (! this .conn.sendCommand(command))
@@ -2713,3 +2733,57 @@ unittest
27132733 atomicStore(node1Addr, node1.ctrl.listener());
27142734 node1.call0();
27152735}
2736+
2737+ // Make sure default parameters work correctly
2738+ unittest
2739+ {
2740+ static interface API
2741+ {
2742+ public uint call1 (uint value = 69 ) @safe ;
2743+ public size_t call2 (string required, string optional = " Hello world" ) @safe ;
2744+ public size_t call3 (string file = __FILE__ , uint line = __LINE__ ) @safe ; // L2744
2745+ }
2746+
2747+ static class Node : API
2748+ {
2749+ public override uint call1 (uint value) @safe
2750+ {
2751+ return value;
2752+ }
2753+
2754+ public override size_t call2 (string required, string optional) @safe
2755+ {
2756+ return required.length + optional.length;
2757+ }
2758+
2759+ public override size_t call3 (string file, uint line) @safe
2760+ {
2761+ // Test disabled. With LDC v1.28.1 installed with Homebrew on MacOS,
2762+ // the defaults I got were:
2763+ // file: "/usr/local/opt/dmd/include/dlang/dmd/std/traits.d"
2764+ // line: 1444
2765+ return file.length + line;
2766+ }
2767+ }
2768+
2769+ auto node1 = RemoteAPI! API .spawn! Node();
2770+ scope (exit)
2771+ {
2772+ node1.ctrl.shutdown();
2773+ thread_joinAll();
2774+ }
2775+
2776+ assert (node1.call1() == 69 );
2777+ assert (node1.call1(42 ) == 42 );
2778+ assert (node1.call2(" WYSIWYG" ) == " WYSIWYG" .length + " Hello World" .length);
2779+ assert (node1.call2(" WYSIWYG" , null ) == " WYSIWYG" .length);
2780+ version (none )
2781+ {
2782+ // Does not work! There are various issues.
2783+ // First, https://issues.dlang.org/show_bug.cgi?id=18919 means we'd probably
2784+ // get the wrong line. But worse, because of `std.traits` eagerly interpreting
2785+ // the default (e.g. see https://issues.dlang.org/show_bug.cgi?id=14369),
2786+ // the `__FILE__` we get is actually... std.traits! And the line to match.
2787+ assert (node1.call3() == __FILE__ .length + __LINE__ );
2788+ }
2789+ }
0 commit comments