What's the deal with the massive duplication in std.meta?

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Sun May 2 12:21:53 UTC 2021


On 5/1/21 4:08 AM, Walter Bright wrote:
> On 4/30/2021 3:03 PM, Andrei Alexandrescu wrote:
>> ```D
>> template staticIndexOf(T, TList...)
>> {
>>     enum staticIndexOf = genericIndexOf!(T, TList);
>> }
>>
>> template staticIndexOf(alias T, TList...)
>> {
>>     enum staticIndexOf = genericIndexOf!(T, TList);
>> }
>> ```
> 
> I'm curious why genericIndexOf is not renamed to staticIndexOf and the 
> previous staticIndexOf templates removed.

I don't know. I speculate that the following sequence of events happened:

1. Someone writes `staticIndexOf` "reasonably" with types (could have 
been aliases, but I recall the first historical uses were with types):

/** ... docs ... */
template staticIndexOf(T, TList...) { ... }

2. Someone else figures staticIndexOf should also work with values. They 
try to add "alias" to `T` in there but unittests fail due to bugs and 
undue limitations in the compiler. They figure the right solution is to 
add an "overload":

/** ... docs ... */
template staticIndexOf(T, TList...) { ... }
/// ditto
template staticIndexOf(alias T, TList...) { ... }

This does not upset the names in the documentation (they are still `T` 
and `TList`) so it's an entirely transparent and reasonable way to work 
around said bugs and undue limitations. That contributor might have 
thought that there may be subtle reasons for which `alias` parameters 
don't accept type arguments transparently, so they perhaps chose not to 
protest it all that much. The reviewer of the code might have accepted 
the same reasoning with a sigh.

3. Someone else (or the same contributor in the same PR) figures there's 
a way to eliminate the duplication in code:

/** ... docs ... */
template staticIndexOf(T, TList...)
{
     enum staticIndexOf = genericIndexOf!(T, TList);
}
/// ditto
template staticIndexOf(alias T, TList...)
{
     enum staticIndexOf = genericIndexOf!(T, TList);
}
// private
private template genericIndexOf(args...) { ... }

This does not upset the documentation and remains transparent to the 
user, so it seems like a reasonable thing to do.

4. Other people (or, again, the same contributor in that or other PRs) 
figured the same pattern can be applied to other artifacts as well. And 
reviews accept that code because otherwise it's impossible to make the 
unittests pass.

5. Now the pattern is an accepted way of doing things whenever an 
artifact must work with both types and aliases. The concern that the 
pattern scales poorly and indicates a massive problem with the language 
was not raised; after all, we had working code using the pattern.

This has happened before, and will happen again unless we do something 
about it.

>> This code should have NEVER been accepted upon review. Instead, the 
>> reviewers should have filed a TOP PRIORITY bug report to dmd "Not 
>> binding types to alias templates forces unscalable code duplication 
>> for all typelist primitives".
>>
>> This needs to be fixed, and very urgently.
> 
> Please file a bug report!

Apparently Nick Treleaven proposed a solution or a part of it:

https://github.com/dlang/dmd/pull/11320

The bug report related to the process is more subtle and does not belong 
in bugzilla.


More information about the Digitalmars-d mailing list