Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions changelog/dmd.template-value-param-init.dd
Original file line number Diff line number Diff line change
@@ -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
---
10 changes: 9 additions & 1 deletion compiler/src/dmd/templatesem.d
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
30 changes: 30 additions & 0 deletions compiler/test/compilable/test20994.d
Original file line number Diff line number Diff line change
@@ -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)
{
}
Loading