www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Bug in function parameters type matching

reply EntangledQuanta <EQ universe.com> writes:
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.
Sep 09 2017
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
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.
Sep 09 2017
parent reply EntangledQuanta <EQ universe.com> writes:
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.
Sep 09 2017
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
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.
Sep 09 2017
parent EntangledQuanta <EQ universe.com> writes:
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?
Sep 09 2017