Strictly speaking, the Kelvin scale is not measured in degrees, so the
previous name was incorrect. Changing it in all cases preserves
consistency.
Fixes#10540
Previously, code that already knew the desired index was forced to
compute a type to pass to get!T or memberName!T, just for get!T or
memberName!T to turn that type back into an index. Removing this
unnecessary round trip simplifies the code.
Additionally, since memberName is no longer dependent on SumType.Types,
it can be moved to module scope, and its instantiations can be shared
across different SumType instances.
This is a useful technique, and non-obvious enough that other D
community members were surprised when I showed it to them.
The unusual formatting and code layout used here achieves the following
goals:
1. Have this example appear below "Basic usage".
2. Have the overload set appear as it would at module level.
3. Have as much of the example code unit-tested as possible.
Goal (2), in particular, rules out the use of a "wrapper" struct to
create an overload set of static methods, which is the technique that's
normally used to include an overload set in a unittest block.
This technique has turned out not to be very useful in practice, and the
example is a bit subtle and tricky to understand. Removing it will make
room for more useful and less confusing examples.
A common cause of the "handler never matches" error is a template
handler that contains a typo or other compile-time error. Since the
location of the actual error is suppressed by __traits(compiles), users
often do not think to look for a mistake inside the handler itself. Now,
the message itself includes a hint to do so.
According to earlier versions of the language spec, checking the
invariant of a struct would also cause its fields' invariants to be
checked, recursively. SumType's invariant was added to make SumType
behave consistently with other structs in this regard.
The spec, however, was wrong: invariants of struct fields are not
checked unless the field is accessed directly, and never have been.
Thus, to make SumType behave consistently with other structs, its
invariant must be removed.
This change should not break any valid programs, since code that relies
on the failure of an invariant has undefined behavior per the spec.
Spec correction PR: https://github.com/dlang/dlang.org/pull/3405
TagTuple wass previously nested within matchImpl, meaning it gets
a different instantiation for each match call with different handlers.
This is not required, as the only template parameters it needs are
the SumTypes being used. In practice, we might even get away with
using the length, but the gain is likely to be marginal compared
to the gains from moving it out of matchImpl.
Another underlying motivation for this change is that it works around
a compiler bug triggered with complex code using const SumType
(the compiler complains that 'this' for 'invariant' is of the wrong type,
const vs non-const).
The template `canMatch` does not account for `ref`.
The template `valueTypes` stores all types of the member values and uses SumTypes's `get` function, which returns a `ref`.
However, ref does not persist and the type is not sent to `canMatch` as a `ref`.
Because of this, when matching, `canMatch` will fail as it will test for a copy, and returning a reference of that value results in escaping it.
Fix Issue 23101
Signed-off-by: João Lourenço <jlourenco5691@gmail.com>
The template constraint is needed to ensure that the inout constructor
overload is only considered when it is an exact match, without qualifier
conversions.
Without the constraint, a constructor call such as
const(SumType!(int[]))([1, 2, 3])
...would be ambiguous, since it would match both the const constructor
overload and the inout constructor overload at the "match with qualifier
conversion" level.
Previously, SumType incorrectly assumed that all members of an
inout(SumType) must themselves be inout-qualified. However, this is not
the case when one of those member types is declared as immutable, since
the qualifier combination `immutable inout` collapses to just
`immutable`.
Attempting to copy an immutable member type as though it were inout
caused matching to fail in SumType's copy constructor, due to the
following (gagged) error:
Error: `inout` on `return` means `inout` must be on a parameter as
well for `pure nothrow @nogc @safe inout(Storage)(ref immutable(Value)
value)`
Previously, the assignment of the local variable 'newStorage' to the
longer-lived member variable 'storage' caused scope inference to
(correctly) fail.
newStorage was necessary to work around issues 21229 and 22118. Since
those issues have been fixed, newStorage can be safely removed.
Previously, SumType would define the wrong set of constructors for types
whose copyability varies depending on their mutability--a situation that
was impossible with postblits, but is now possible with copy
constructors.