Thread overview
Bug in function parameters type matching
Sep 09, 2017
EntangledQuanta
Sep 09, 2017
Adam D. Ruppe
Sep 09, 2017
EntangledQuanta
Sep 09, 2017
Adam D. Ruppe
Sep 10, 2017
EntangledQuanta
September 09, 2017
A very strange bug.

I had a function like

interface I { foo(string x, anEnum e); }
abstract class A : I { }
class C : A { foo(string x, anEnum e) { } }

I decided I needed to extend foo so I changed it to

interface I { foo(string x, int y, anEnum e); }
abstract class A : I { }
class C : A { foo(string x, int y, anEnum e) { } }

but I forgot to change the only call to foo I had, which was

foo("asdf", anEnum.x);

I ran the code and it all compiled but, of course, was bugged because inside foo y was 1, which was the value of anEnum.x.

I thought dmd would through an error since, anEnum is not an int, yet it didn't.

Seems like dmd is broke somewhere.


Here is an (non)working example:

enum anEnum { x }
interface I { void foo(string x, int y, anEnum e = anEnum.x); }
abstract class A : I { }
class C : A { void foo(string x, int y, anEnum e = anEnum.x) { } }

void main()
{
  auto i = cast(I)(new C());
  i.foo("asdf", anEnum.x);
}

note that it removing the enum's default value gives the proper error. Having the default value shouldn't change anything as far as errors are concerned because, unless enum's are implicitly castable to int's, which someone once told me that D didn't like implicit casts because of issues, it should throw an error about type mismatch.

One can even do something like this:

enum anEnum { x }
interface I { void foo(string x, double y, anEnum e); }
abstract class A : I { }
class C : A { void foo(string x, double y, anEnum e) { } }

void main()
{
  auto i = cast(I)(new C());
  i.foo("asdf", anEnum.x, anEnum.x);
}

or even

enum anEnum { x }
interface I { void foo(string x, byte y, anEnum e); }
abstract class A : I { }
class C : A { void foo(string x, byte y, anEnum e) { } }

void main()
{
  auto i = cast(I)(new C());
  i.foo("asdf", anEnum.x, anEnum.x);
}

which is just wrong. I realize enum is a literal BUT there should be some type of type checking. The whole point of using an enum parameter is to enforce type safety.

Those that justify this case then justify other contradictory cases(such as, "Oh, we can't have implicit casting here because it will introduce bugs") are just posers.


September 09, 2017
On Saturday, 9 September 2017 at 20:45:59 UTC, EntangledQuanta wrote:
> unless enum's are implicitly castable to int's

They are, unless you specify some other base type.

https://dlang.org/spec/enum.html#named_enums

See points 3 and 5 there. It will cast to the base type (int by default), but you cannot pass the int as the enum.


> which someone once told me that D didn't like implicit casts because of issues

D has LOTS of implicit casts, including user-defined ones. Some are restricted because of issues, but generally speaking, D is pretty ok with them.
September 09, 2017
On Saturday, 9 September 2017 at 21:08:16 UTC, Adam D. Ruppe wrote:
> On Saturday, 9 September 2017 at 20:45:59 UTC, EntangledQuanta wrote:
>> unless enum's are implicitly castable to int's
>
> They are, unless you specify some other base type.
>
> https://dlang.org/spec/enum.html#named_enums
>
> See points 3 and 5 there. It will cast to the base type (int by default), but you cannot pass the int as the enum.
>
>
>> which someone once told me that D didn't like implicit casts because of issues
>
> D has LOTS of implicit casts, including user-defined ones. Some are restricted because of issues, but generally speaking, D is pretty ok with them.

What's the point then of even having an enum parameter? If it will just be cast to an int, why not use an int? People always complain about making the compiler more complex but this makes it more complex without actually solving any problem or doing anything useful.

I guess those that actually write the code are the ones who get to decide where the arbitrary line is drawn, whatever is convenient for them. Would just be nice if they were up front about it instead of trying to justify with logic why they chose to prevent some things. I'd rather hear "I did it that way because I wanted to" rather than some blather trying to use logical reasoning.
September 09, 2017
On Saturday, 9 September 2017 at 21:15:10 UTC, EntangledQuanta wrote:
> What's the point then of even having an enum parameter?

You must pass the enum to the enum parameter. Implicit casting only goes one way.

You are just also allowed to pass the enum to an int parameter.
September 10, 2017
On Saturday, 9 September 2017 at 21:27:14 UTC, Adam D. Ruppe wrote:
> On Saturday, 9 September 2017 at 21:15:10 UTC, EntangledQuanta wrote:
>> What's the point then of even having an enum parameter?
>
> You must pass the enum to the enum parameter. Implicit casting only goes one way.
>
> You are just also allowed to pass the enum to an int parameter.

I think it should be only implicitly castable if you explicitly set the type on the enum.

Surely you see how semantically wrong calling foo in the last examples I gave?