View mode: basic / threaded / horizontal-split · Log in · Help
September 11, 2012
auto limitation?
I have this code, but it works not as expected:
http://dpaste.dzfl.pl/6ce5b4dd

I get 0 instead of 42 if my type is Int.
My value is correct (as you can see) but "writeln" prints still 0 
instead of 42.
I think "auto" compiles first to float and cannot handle then 
integers.
Am I right? And could you explain me how this could work?
September 11, 2012
Re: auto limitation?
On 09/11/2012 11:10 AM, Namespace wrote:
> I have this code, but it works not as expected:
> http://dpaste.dzfl.pl/6ce5b4dd
>
> I get 0 instead of 42 if my type is Int.
> My value is correct (as you can see) but "writeln" prints still 0
> instead of 42.
> I think "auto" compiles first to float and cannot handle then integers.
> Am I right? And could you explain me how this could work?

Here is a reduced code:

import std.stdio;

enum Type { Int, Float }

auto foo(Type t)
{
    final switch (t) {
    case Type.Int:
        return 42;
    case Type.Float:
        return 1.5;
    }
}

void main()
{
    writeln(foo(Type.Int));
    writeln(foo(Type.Float));
}

The return type of foo() is double. (It's float in your code but it 
doesn't matter.)

I think this is a bug. I guess that 'return 42' is still placing an int 
onto the program stack instead of a float. A workarounds are returning 
to!float(this._num.ivalue).

But I think this is a compiler bug.

Ali
September 11, 2012
Re: auto limitation?
> Here is a reduced code:
>
> import std.stdio;
>
> enum Type { Int, Float }
>
> auto foo(Type t)
> {
>     final switch (t) {
>     case Type.Int:
>         return 42;
>     case Type.Float:
>         return 1.5;
>     }
> }
>
> void main()
> {
>     writeln(foo(Type.Int));
>     writeln(foo(Type.Float));
> }
>
> The return type of foo() is double. (It's float in your code 
> but it doesn't matter.)
>
> I think this is a bug. I guess that 'return 42' is still 
> placing an int onto the program stack instead of a float. A 
> workarounds are returning to!float(this._num.ivalue).
>
> But I think this is a compiler bug.
>
> Ali

I should begin to count the bugs I find with stuff like this. :)
So no correct workaround, hm?

I tried to use a Variant and in the getter method "get" and even 
"coerce" but then i get the error, that the type of "get" cannot 
be detected.
September 11, 2012
Re: auto limitation?
On 09/11/2012 11:40 AM, Namespace wrote:
>> Here is a reduced code:
>>
>> import std.stdio;
>>
>> enum Type { Int, Float }
>>
>> auto foo(Type t)
>> {
>> final switch (t) {
>> case Type.Int:
>> return 42;
>> case Type.Float:
>> return 1.5;
>> }
>> }
>>
>> void main()
>> {
>> writeln(foo(Type.Int));
>> writeln(foo(Type.Float));
>> }
>>
>> The return type of foo() is double. (It's float in your code but it
>> doesn't matter.)
>>
>> I think this is a bug. I guess that 'return 42' is still placing an
>> int onto the program stack instead of a float. A workarounds are
>> returning to!float(this._num.ivalue).
>>
>> But I think this is a compiler bug.
>>
>> Ali
>
> I should begin to count the bugs I find with stuff like this. :)

Please create a bug about this one:

  http://d.puremagic.com/issues/

But wait until someone else confirms that it really is a bug. :)

> So no correct workaround, hm?

You have to cast the types to the largest one. The following does not 
work because foo() is not defined yet:

import std.traits;
// ...
auto foo(Type t)
{
    final switch (t) {
    case Type.Int:
        return to!(ReturnType!(typeof(&foo)))(42);
    case Type.Float:
        return 1.5;
    }
}

  Error: forward reference to foo

Explicitly casting is a way:

        return to!double(42);

Or you can write or find a template that produces the largest type among 
the members of a union.

Ali
September 11, 2012
Re: auto limitation?
That's not what i want. I would avoid casting if it's possible.
I hope it is a bug and will fixed in 2.061.
September 11, 2012
Re: auto limitation?
On Tuesday, 11 September 2012 at 18:32:47 UTC, Ali Çehreli wrote:
>
> Here is a reduced code:
>

I guess it may be reduced to:

auto foo(bool val)
{
   if (val)
      return 42;
   else
      return 1.5;
}

void main()
{
   assert(foo(true) == 42); // assertion failure
   assert(foo(false) == 1.5);
}


>
> The return type of foo() is double. (It's float in your code 
> but it doesn't matter.)
>
> I think this is a bug. I guess that 'return 42' is still 
> placing an int onto the program stack instead of a float. A 
> workarounds are returning to!float(this._num.ivalue).
>
> But I think this is a compiler bug.
>
> Ali

I think it is UB rather than a bug. The spec says that return 
types must match exactly. AFAIK auto is a feature to infer return 
type, not to magically adjust to multiple incompatible types.
September 11, 2012
Re: auto limitation?
> I think it is UB rather than a bug. The spec says that return 
> types must match exactly. AFAIK auto is a feature to infer 
> return type, not to magically adjust to multiple incompatible 
> types.

But i thought Variant is one. ;)
September 11, 2012
Re: auto limitation?
On Tue, 11 Sep 2012 20:48:25 +0200, Ali Çehreli <acehreli@yahoo.com> wrote:

> Or you can write or find a template that produces the largest type among  
> the members of a union.

std.traits.CommonType.

-- 
Simen
September 11, 2012
Re: auto limitation?
On Tue, 11 Sep 2012 20:57:07 +0200, Maxim Fomin <maxim@maxim-fomin.ru>  
wrote:

> I think it is UB rather than a bug. The spec says that return types must  
> match exactly. AFAIK auto is a feature to infer return type, not to  
> magically adjust to multiple incompatible types.

I'd be surprised if this were not a bug. My expectation would be that the
types be combined as with the ?: operator, just like std.traits.CommonType.

If this is not a bug, it's certainly worth filing as an enhancement  
request.

-- 
Simen
September 11, 2012
Re: auto limitation?
On Tuesday, 11 September 2012 at 19:03:56 UTC, Namespace wrote:
>> I think it is UB rather than a bug. The spec says that return 
>> types must match exactly. AFAIK auto is a feature to infer 
>> return type, not to magically adjust to multiple incompatible 
>> types.
>
> But i thought Variant is one. ;)

I guess (never used Variant) that it uses templated getter which 
correctly returns value. Float values are returned in %xmm 
registers and integer values are returned in %eax. Without 
knowing return type a caller doesn't know where to take return 
value. For example in this case foo function correctly places 
return values, but main takes in both cases return value from 
%xmm.
« First   ‹ Prev
1 2 3
Top | Discussion index | About this forum | D home