Thread overview
Return type inference
May 17, 2012
Tobias Pankrath
May 17, 2012
Andrej Mitrovic
May 17, 2012
bearophile
May 17, 2012
Dmitry Olshansky
May 17, 2012
Peter Alexander
May 17, 2012
Tobias Pankrath
May 17, 2012
This does not work and I can see why.

---
auto foo(int x)
{
         if(x < 0)
             return foo(-x);
         return x;
}
----

DMD 2.059 says:
oopsc/compiler/test.d(7): Error: forward reference to foo
oopsc/compiler/test.d(14): Error: forward reference to foo

For the human reader it is easy to see that the return type of
foo should be int. Could the following rule be added to make dmd
see this, too?

> If there are multiple ReturnStatements, the types of them must match exactly. If there are no ReturnStatements, the return type is inferred to be void.
> <new>
> If the function is called recursively the type of the result of this call is inferred in the same way. If the recursive call is part of a return statement >  then this statement is not considered for type inference. If all return statements are discarded in this way, it is an error.


May 17, 2012
On 5/17/12, Tobias Pankrath <tobias@pankrath.net> wrote:
> snip

http://d.puremagic.com/issues/show_bug.cgi?id=7483
May 17, 2012
On 17.05.2012 17:10, Tobias Pankrath wrote:
> This does not work and I can see why.
>
> ---
> auto foo(int x)
> {
> if(x < 0)
> return foo(-x);

Pluck in other condition then x < 0 and you may see it's not so easy. Basically compiler has to deduce that recursion stops and trace down to the bottom of it.

> return x;
> }
> ----
>
> DMD 2.059 says:
> oopsc/compiler/test.d(7): Error: forward reference to foo
> oopsc/compiler/test.d(14): Error: forward reference to foo
>
> For the human reader it is easy to see that the return type of
> foo should be int. Could the following rule be added to make dmd
> see this, too?
>
>> If there are multiple ReturnStatements, the types of them must match
>> exactly. If there are no ReturnStatements, the return type is inferred
>> to be void.
>> <new>
>> If the function is called recursively the type of the result of this
>> call is inferred in the same way. If the recursive call is part of a
>> return statement > then this statement is not considered for type
>> inference. If all return statements are discarded in this way, it is
>> an error.
>
>


-- 
Dmitry Olshansky
May 17, 2012
On Thursday, 17 May 2012 at 13:10:20 UTC, Tobias Pankrath wrote:
> For the human reader it is easy to see that the return type of
> foo should be int. Could the following rule be added to make dmd
> see this, too?

> If the function is called recursively the type of the result of this call is inferred in the same way. If the recursive call is part of a return statement >  then this statement is not considered for type inference. If all return statements are discarded in this way, it is an error.

It's not that simple:

--------------------------------
int bar(int x);
real bar(real x);

auto foo(int x)
{
    if (x < 0)
        return bar(foo(x-1));
    return 0;
}
--------------------------------

In order to determine the first return type, it needs to find out what overloaded 'bar' to call, which requires determining the first return type.

If you ignore the first return statement and only consider the int then there could be problems. e.g. if above we had:

real bar(int x);

And we ignored the first return statement then the determined return type would be wrong (would infer int, but bar(foo(x-1)) would return real).
May 17, 2012
On Thu, 17 May 2012 09:10:18 -0400, Tobias Pankrath <tobias@pankrath.net> wrote:

> This does not work and I can see why.
>
> ---
> auto foo(int x)
> {
>           if(x < 0)
>               return foo(-x);
>           return x;
> }
> ----
>
> DMD 2.059 says:
> oopsc/compiler/test.d(7): Error: forward reference to foo
> oopsc/compiler/test.d(14): Error: forward reference to foo
>
> For the human reader it is easy to see that the return type of
> foo should be int.

At this point, I think the human should intervene:

int foo(int x)
...

I would *hate* to have to read code like yours to try and understand it.

-Steve
May 17, 2012
Andrej Mitrovic:

> http://d.puremagic.com/issues/show_bug.cgi?id=7483

Probably related:
http://d.puremagic.com/issues/show_bug.cgi?id=8111

Bye,
bearophile
May 17, 2012
> In order to determine the first return type, it needs to find out what overloaded 'bar' to call, which requires determining the first return type.
>

I didn't think of overloaded functions. If we consider only
direct recursion, it should still work?
May 17, 2012
On 17-05-2012 16:22, Steven Schveighoffer wrote:
> On Thu, 17 May 2012 09:10:18 -0400, Tobias Pankrath
> <tobias@pankrath.net> wrote:
>
>> This does not work and I can see why.
>>
>> ---
>> auto foo(int x)
>> {
>> if(x < 0)
>> return foo(-x);
>> return x;
>> }
>> ----
>>
>> DMD 2.059 says:
>> oopsc/compiler/test.d(7): Error: forward reference to foo
>> oopsc/compiler/test.d(14): Error: forward reference to foo
>>
>> For the human reader it is easy to see that the return type of
>> foo should be int.
>
> At this point, I think the human should intervene:
>
> int foo(int x)
> ...
>
> I would *hate* to have to read code like yours to try and understand it.
>
> -Steve

I have to agree. Sometimes auto can be over-used. Even in functional languages with H-M type inference, I tend to always make my functions have explicit signatures (unless they're supposed to be generic). It's just clearer to the person reading the code later on.

-- 
- Alex