Thread overview
Is this a bug in return type inference?
Apr 26, 2015
Meta
Apr 26, 2015
Ali Çehreli
Apr 26, 2015
Meta
April 26, 2015
import std.random;

auto test(int n)
{
    if (n >= 0 && n < 33)
    {
        return int(0);
    }
    else if (n >= 33 && n < 66)
    {
        return float(0);
    }
    else
    {
        return real(0);
    }
}

void main()
{
    auto n = uniform(0, 100);
    auto res = test(n);
    //Prints "float"
    pragma(msg, typeof(res));
}

I expected the result to be real. Why is the return type of test inferred as float instead? I would expect it to choose real, as both int and float can be converted to real without precision loss, but the opposite is not true. Is this a bug?
April 26, 2015
On 04/26/2015 12:32 PM, Meta wrote:
> import std.random;
>
> auto test(int n)
> {
>      if (n >= 0 && n < 33)
>      {
>          return int(0);
>      }
>      else if (n >= 33 && n < 66)
>      {
>          return float(0);
>      }
>      else
>      {
>          return real(0);
>      }
> }
>
> void main()
> {
>      auto n = uniform(0, 100);
>      auto res = test(n);
>      //Prints "float"
>      pragma(msg, typeof(res));
> }
>
> I expected the result to be real. Why is the return type of test
> inferred as float instead? I would expect it to choose real, as both int
> and float can be converted to real without precision loss, but the
> opposite is not true. Is this a bug?

Yes, a bug for floating types only. It seems that not the common type but the first type is used among floating point types. I wrote a short program to prove it to myself:

import std.traits;
import std.typetuple;
import std.format;

auto foo(A, B)(int n)
{
    if (n) {
        return A(0);

    } else {

        return B(0);
    }
}

void main()
{
    alias types = TypeTuple!(float, double, real);

    foreach (A; types) {
        foreach (B; types) {
            alias ReturnType = typeof(foo!(A, B)(0));

            pragma(msg, format("%s %s -> %s%s",
                               A.stringof, B.stringof,
                               ReturnType.stringof,
                               (is (ReturnType == CommonType!(A, B))
                                ? ""
                                : " <-- BUG")));
        }
    }
}

float float -> float
float double -> float <-- BUG
float real -> float <-- BUG
double float -> double
double double -> double
double real -> double <-- BUG
real float -> real
real double -> real
real real -> real

Ali

April 26, 2015
On Sunday, 26 April 2015 at 20:21:32 UTC, Ali Çehreli wrote:
> Yes, a bug for floating types only. It seems that not the common type but the first type is used among floating point types. I wrote a short program to prove it to myself:
>
> import std.traits;
> import std.typetuple;
> import std.format;
>
> auto foo(A, B)(int n)
> {
>     if (n) {
>         return A(0);
>
>     } else {
>
>         return B(0);
>     }
> }
>
> void main()
> {
>     alias types = TypeTuple!(float, double, real);
>
>     foreach (A; types) {
>         foreach (B; types) {
>             alias ReturnType = typeof(foo!(A, B)(0));
>
>             pragma(msg, format("%s %s -> %s%s",
>                                A.stringof, B.stringof,
>                                ReturnType.stringof,
>                                (is (ReturnType == CommonType!(A, B))
>                                 ? ""
>                                 : " <-- BUG")));
>         }
>     }
> }
>
> float float -> float
> float double -> float <-- BUG
> float real -> float <-- BUG
> double float -> double
> double double -> double
> double real -> double <-- BUG
> real float -> real
> real double -> real
> real real -> real
>
> Ali

https://issues.dlang.org/show_bug.cgi?id=14506