November 20, 2022

On Saturday, 19 November 2022 at 02:54:01 UTC, Walter Bright wrote:

>

With the syntax $e to look up an enum member, the compiler will need to search every enum that is in scope. Since one of D's strengths is whole program compilation, this can be slow. To speed that up, it will likely require that the compiler maintain a hash table of all the enum fields.

I.e. a parallel symbol table will have to be maintained alongside the regular symbol table.

This is a juncture where being an implementer gives you a lot more insight into this process than me. That said, please forgive (and correct) me if this sounds ridiculous and/or impossible…

Here's a quick example:

enum A{ a,b,c }
auto fn(int x){}
auto fn(A x){}

void main(){
  fn($b);
}

At fn($b); the compiler checks the signature of each overload of fn to see if any of them accept an enum type for this argument.
The compiler ONLY finds auto fn(A x), so it checks if b is a member of A. It is, so $b becomes A.b.

Now, if we also define:

enum B{ a,b,c }
auto fn(B x){}

The compiler finds auto fn(A x) AND auto fn(B x), so it checks if b is a member of A or B... both checks return true, so the compiler returns an ambiguity error.

November 20, 2022
On Friday, 18 November 2022 at 21:09:41 UTC, Walter Bright wrote:
> What happens in combination with function and template overloading is not discussed.

Wrong: https://github.com/dlang/DIPs/blob/e2ca557ab9d3e60305a37da0d5b58299e0a9de0e/DIPs/DIP1044.md#other-considerations

On Friday, 18 November 2022 at 21:09:41 UTC, Walter Bright wrote:
> That's the simplest case. More complex cases come when there are multiple overloaded functions with diverse enum arguments, resulting in an unbounded combinatorial problem of which combination of enum members will be selected.

I must simply disagree. Unless there's some issue with an implementation along the lines of my previous post, I fail to see how this is more than a trivial syntax change that nobody is required to use if they don't want to.

On Friday, 18 November 2022 at 21:09:41 UTC, Walter Bright wrote:
> [...] worse than the function overloading problem is the template overloading problem, as the compiler will need to instantiate the template with each combination of enum inferences just to figure out what the type of the template is.)

Could you please provide a concrete example of this so I can better understand what you mean? (ideally one that I can run if I substitute out the ETI)


November 21, 2022

On Friday, 18 November 2022 at 21:29:15 UTC, Walter Bright wrote:

>

The following is not addressed:

enum E { e };
int e;
auto x = e;  // which e?

void bahb(int);
void bahb(E);
bahb(e);  // which bahb?

Your example is written without using ETI.
It should look like this if you want to use the enum member with ETI:

enum E { e }
int e;
auto x = $e; //E.e

void bahb(int);
void bahb(E x);
bahb($e); //E.e

Otherwise the local variable will be used, because that's how D works.

November 21, 2022

On Friday, 18 November 2022 at 22:02:30 UTC, Walter Bright wrote:

>

Scoping rules are not addressed. For example:

enum E { e };

void blue()
{
    int e;
    auto x = e;  // which e?
}

As with the previous message, this one does not use ETI at all.
Here's an example with ETI:

E { e }

blue(){
    int e;
    auto x = $e;  //E.e
}
November 21, 2022

On Saturday, 19 November 2022 at 02:35:19 UTC, Walter Bright wrote:

>

Under "Prior Work", the C style of enums should be mentioned.

No. C-style enums are inserted into the same scope as the enum declaration, not an otherwise explicit declaration with a contextually inferred type.

>

While this is a bit clumsy when there are lot of enum members, it suggests a special syntax for making it easy:

enum NewKeywordHere E { ex = 1; }

void tab() {
    E x = ex; // ok
    E y = E.ex;  // also ok
}

I.e. going at this problem the opposite way C++ did.

I submit this is less disruptive to the language than adding $ and new lookup rules.

This proposal is inadequate as it may cause old code to break, which is actually disruptive to users of the language. It also makes it harder to distinguish between enums with inferred types and variables with the same names, and will cause confusing name conflicts.

>

It also puts the choice into the hands of the designer of the enum rather than the user of the enum. Isn't it better to make this a choice the designer should have?

In practice, designers often make bad decisions. In my experience D has a highly flexible syntax that allows you to write ergonomic code in the face of awful library design.

November 21, 2022
On 11/20/2022 8:52 AM, IchorDev wrote:
> Could you please provide a concrete example of this so I can better understand what you mean? (ideally one that I can run if I substitute out the ETI)



enum A { a }
enum B { a }

void foo(A);
void foo(B);

auto bar(T)(T x) { return ....; } // is bar returning an A or a B?

foo(bar!($a));

The template bar will have to be instantiated twice in order to determine the type of the argument being passed to foo(). If there are multiple arguments with $field somewhere in them, this is a combinatorial problem.
November 22, 2022

On Monday, 21 November 2022 at 17:50:24 UTC, Walter Bright wrote:

>

enum A { a }
enum B { a }

void foo(A);
void foo(B);

auto bar(T)(T x) { return ....; } // is bar returning an A or a B?

foo(bar!($a));

First thing: I'm going to assume you made a small mistake and actually meant foo(bar($a)); instead of foo(bar!($a));. The latter would not compile anyway, since you would be trying to bind an enum member to a type.

With that assumption in mind, your example would not compile once ETI is implemented, because according to the DIP:

>

3. Argument lists

ETI is allowed in the argument lists of function calls and template instantiations when they can bind to explicitly typed enum parameters.

enum A{ a,b,c,d }
//[...]
void myTempFn(T)(T param){}

void main(){
//[...]
    myTempFn!A($a);
    myTempFn($a); // error, can't infer a type to instantiate the template with from "$a"
}

Why is this? Well, bar(T)(T x) has no explicitly typed enum parameters! When you try to use ETI via bar($a) there will be no way for the compiler to infer the type of a, and you will get an ambiguity error.
You might argue that your example shows you instantiating the bar template inside a call to foo which has 2 overloads that take an enum parameter. I want to clarify that—just like with nested arrays—this is completely meaningless to the evaluation of ETI. I will add examples covering this case in the next revision of the DIP so that there isn't any doubt it.

November 21, 2022
On 11/21/2022 10:20 PM, IchorDev wrote:
> I will add examples covering this case in the next revision of the DIP so that there isn't any doubt it.

Good, thank you.
November 23, 2022

I know it sounds nitpicky, but I really dislike like acronym. “ETI” is used (at least) in C++ for “explicit template instantiation.” D has templates, so ETI can be a source for confusion. The term has been used in the forum unrelated to C++.

I don’t care for the wording of the DIP, but for what people will refer to it in the forum. If it makes it into the spec, it would be great if you could find something else. E.g. “type-inferred enums” (TIE) is not that different, IMO “type inferred enum members” (TIEM) is even better. Another one would be “implicit enum member” (IEM).

November 23, 2022

On Friday, 18 November 2022 at 15:38:59 UTC, Mike Parker wrote:

>

Feedback Thread

This is the feedback thread for the first round of Community Review of DIP 1044, "Enum Type Inference".

THIS IS NOT A DISCUSSION THREAD

I'm against this DIP because...

  1. using new symbols $(or any other unused symbol) for a minor feature is wasteful, compared to adding new meta/codegen features etc.

  2. Implicit 'with' for switch statements as proposed by Walter is more elegant and doesn't require any new symbols/syntax and is also more efficient from a compiler performance perspective as $ could refer to any enum, whereas the implicit 'with' only adds one enum.

I propose changing the DIP to "implicit with".