D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 19394 - Inconsistent overload resolution with named and non-named enums
Summary: Inconsistent overload resolution with named and non-named enums
Status: RESOLVED INVALID
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: x86_64 Linux
: P1 normal
Assignee: No Owner
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2018-11-12 21:00 UTC by Neia Neutuladh
Modified: 2018-11-12 22:12 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Neia Neutuladh 2018-11-12 21:00:34 UTC
---
import std.stdio;
void foo(bool b) { writefln("bool %s", b); }
void foo(int b) { writefln("int %s", b); }
enum : int { a = 0 }
enum A : int { a = 0 }

void main()
{
  foo(a);
  foo(A.a);
}
---

Hoped-for result:
int 0
int 0

Expected result after reading DIP1015 and its rejection:
bool false
bool false

Actual result:
int 0
bool false

To give name to a thing, it seems, is to change its very nature.
Comment 1 Walter Bright 2018-11-12 22:12:16 UTC
Non-named enums are manifest constants, no anonymous type is created. To give a name to a group of enums does indeed change its nature.

A more detailed explanation of what is happening:

  int f(short s) { return 1; }
  int f(int i) { return 2; }

  enum : int { a = 0 }
  enum A : int { a = 0 }

  pragma (msg, f(a));   // calls f(int)
  pragma (msg, f(A.a)); // calls f(short)

I.e. bool is consistent with how other integral types work.

Here's how it works:

f(a): `a` is a manifest constant of type `int`, and `int` is an exact match for f(int), and f(short) requires an implicit conversion. The exact match of f(int) is better.

f(A.a): `a` is an enum of type `A`. `A` gets implicitly converted to `int`. The `int` then gets exact match to f(int), and an implicit match to f(short). The sequence of conversions is folded into one according to:

    <implicit conversion> <exact>               => <implicit conversion>
    <implicit conversion> <implicit conversion> => <implicit conversion>

Both f(int) and f(short) match, because implicit conversions rank the same. To disambiguate, f(short) is pitted against f(int) using partial ordering rules,
which are:

    Can a short be used to call f(int)? Yes.
    Can an int be used to call f(short)? No.

So f(short) is selected, because the "Most Specialized" function is selected when there is an ambiguous match.

Note: the "most specialized" partial ordering rules are independent of the arguments being passed.

The behavior is as intended. Marked as invalid.