Thread overview
ushort calls byte overload
May 30, 2017
Oleg B
May 30, 2017
Oleg B
May 30, 2017
Daniel Kozak
May 30, 2017
Oleg B
May 31, 2017
nkm1
May 30, 2017
Hello. I have this code

import std.stdio;

void foo(byte a) { writeln(typeof(a).stringof); }
void foo(short a) { writeln(typeof(a).stringof); }
void foo(int a) { writeln(typeof(a).stringof); }

void main()
{
    foo(0); // int, and byte if not define foo(int)
    foo(ushort(0)); // byte (unexpected for me)
    foo(cast(ushort)0); // byte (unexpected too)

    foo(cast(short)0); // short
    foo(short(0)); // short

    ushort x = 0;
    foo(x); // short
}

Is this a bug or I don't understand something?
May 30, 2017
and this is unexpected for me too

    immutable ushort y = 0;
    foo(y); // byte
May 30, 2017

Dne 30.5.2017 v 23:16 Oleg B via Digitalmars-d-learn napsal(a):
> Hello. I have this code
>
> import std.stdio;
>
> void foo(byte a) { writeln(typeof(a).stringof); }
> void foo(short a) { writeln(typeof(a).stringof); }
> void foo(int a) { writeln(typeof(a).stringof); }
>
> void main()
> {
>     foo(0); // int, and byte if not define foo(int)
>     foo(ushort(0)); // byte (unexpected for me)
>     foo(cast(ushort)0); // byte (unexpected too)
>
>     foo(cast(short)0); // short
>     foo(short(0)); // short
>
>     ushort x = 0;
>     foo(x); // short
> }
>
> Is this a bug or I don't understand something?

It is "not" a bug, and it is how compiler works. Compiler do many assumptions (it is sometimes useful). So if it see something like
immutable ushort y = 0 (compile time value) or just "0" (still compile time value) it knows its value so it knows it can be saftly represent in byte, ubyte and so on.

However ushort x = 0;
foo(x); // here x is runtime value so compilere does not know the size, so it will use the type.

Lets look to an another example

immutable ushort y = 0;
byte x = y;

this will compile because of current rules.

but this:

ushort y = 0;
byte x = y;

will produce this error: Error: cannot implicitly convert expression (y) of type ushort to byte

And in this example is everything ok:

import std.stdio;

void f(ushort u)
{
    writeln("ushort");
}

void f(ubyte u)
{
    writeln("ubyte");
}

void main()
{
    ushort y = 0;
    immutable ushort x = 0;

    f(y);
    f(x);
}

RESULT IS:
ushort
ushort

but obviously in follow example it could be misleading

import std.stdio;

void f(short u)
{
    writeln("short");
}

void f(ubyte u) // or byte u
{
    writeln("ubyte or byte");
}

void main()
{
    ushort y = 0;
    immutable ushort x = 0;

    f(y);
    f(x);
}

RESULT IS:
ushort
[u]byte

But it make sense, compiler will select the best match in this case it is byte or ubyte but if we change x to something like 128
wi will get different results for byte and ubyte


May 30, 2017
On Tuesday, 30 May 2017 at 21:42:03 UTC, Daniel Kozak wrote:
> Compiler do many assumptions (it is sometimes useful).

but if compiler find one-to-one correspondence it don't make assumptions, like here?

> import std.stdio;
>
> void f(ushort u)
> {
>     writeln("ushort");
> }
>
> void f(ubyte u)
> {
>     writeln("ubyte");
> }
>
> void main()
> {
>     ushort y = 0;
>     immutable ushort x = 0;
>
>     f(y);
>     f(x);
> }
>
> RESULT IS:
> ushort
> ushort

or it can?
May 31, 2017
On Tuesday, 30 May 2017 at 21:16:26 UTC, Oleg B wrote:
> Hello. I have this code
>
> import std.stdio;
>
> void foo(byte a) { writeln(typeof(a).stringof); }
> void foo(short a) { writeln(typeof(a).stringof); }
> void foo(int a) { writeln(typeof(a).stringof); }
>
> void main()
> {
>     foo(0); // int, and byte if not define foo(int)
>     foo(ushort(0)); // byte (unexpected for me)
>     foo(cast(ushort)0); // byte (unexpected too)
>
>     foo(cast(short)0); // short
>     foo(short(0)); // short
>
>     ushort x = 0;
>     foo(x); // short
> }
>
> Is this a bug or I don't understand something?

Hm, interesting. I think what you're seeing here is an unexpected application of value range propagation: http://www.drdobbs.com/tools/value-range-propagation/229300211

None of these functions can be called with ushort without conversions. As the manual says:

The function with the best match is selected. The levels of matching are:
    no match
    match with implicit conversions
    match with conversion to const
    exact match

All of your functions require some implicit conversions (the ushort here can be converted to byte because of value range propagation). So the next rule is in effect - the functions are ordered and the "most specialized" is chozen. The byte function is the most specialized, so it is called.
Or something like that :)

> but if compiler find one-to-one correspondence it don't make assumptions, like here?
Apparently then it just chooses the function that is "exact match".