diff --git a/changelog/dmd.template-value-param-init.dd b/changelog/dmd.template-value-param-init.dd new file mode 100644 index 000000000000..7e3953be2de6 --- /dev/null +++ b/changelog/dmd.template-value-param-init.dd @@ -0,0 +1,32 @@ +Template value parameters now support the same initialization semantics as local variable declarations + +Default values for template value parameters now undergo the same initialization +semantics as regular variable declarations, allowing implicit construction via +constructors and `static opCall`. + +Previously, the following would fail to compile even though equivalent variable +and function parameter declarations work fine: + +--- +struct Color +{ + ubyte r, g, b; + this(uint hex) { r = (hex >> 16) & 0xFF; g = (hex >> 8) & 0xFF; b = hex & 0xFF; } +} + +template fill(Color c = 0xFF0000) // red by default +{ +} + +alias redFill = fill!(); // now compiles +--- + +This also applies to static arrays initialized from a scalar: + +--- +template withPadding(byte[4] padding = 0) +{ +} + +alias noPadding = withPadding!(); // now compiles +--- diff --git a/compiler/src/dmd/templatesem.d b/compiler/src/dmd/templatesem.d index 351a622227d0..bf6d7bfd030a 100644 --- a/compiler/src/dmd/templatesem.d +++ b/compiler/src/dmd/templatesem.d @@ -4108,7 +4108,15 @@ private RootObject defaultArg(TemplateParameter tp, Loc instLoc, Scope* sc) } if ((e = resolveProperties(sc, e)) is null) return null; - e = e.optimize(WANTvalue); + + // Apply the same initialization semantics as for variable declarations + // to handle e.g. implicit constructor calls for struct types + // https://github.com/dlang/dmd/issues/20994 + Type vt = tvp.valType.typeSemantic(tvp.loc, sc); + Initializer init = new ExpInitializer(tvp.loc, e); + init = init.initializerSemantic(sc, vt, INITinterpret); + if (auto ei2 = init.isExpInitializer()) + e = ei2.exp; return e; } diff --git a/compiler/test/compilable/test20994.d b/compiler/test/compilable/test20994.d new file mode 100644 index 000000000000..5a5556f753c3 --- /dev/null +++ b/compiler/test/compilable/test20994.d @@ -0,0 +1,30 @@ +// https://github.com/dlang/dmd/issues/20994 + +// Struct with constructor +struct S { this(int x) {} } + +void foo(S a = 0) {} // ok + +template Foo(S a = 0) {} + +void main() +{ + S a = 0; // ok + foo(); // ok + alias F = Foo!(); // should compile +} + +// Struct with opCall +struct T +{ + static T opCall(int x) { T t; return t; } +} + +template Bar(T a = 0) {} +alias G = Bar!(); + +// Array initializer +alias g = f!(); +template f(byte[3] a = -1) +{ +}