April 18, 2013
On 04/18/2013 01:46 AM, Walter Bright wrote:
> On 4/17/2013 3:20 PM, Timon Gehr wrote:
>>> "This is the same issue as defining a function with 'auto' in one place
>>> and referring to it having a specific type/attribute in another. So I
>>> think all the same arguments and reasoning discussed above apply
>>> equally."
>>>
>>
>> Why is this a valid form of reasoning? The signature of a function
>> that has its
>> return type inferred includes the function body.
>>
>> Furthermore, it is not the same issue. It is the dual issue. The
>> distinction is
>> very relevant because pure and nothrow are designed in an asymmetric way,
>
> They are the same

No. In one case you infer guarantees only. (those restrict what can be done in the future without potentially breaking code, but that's it.)
In the other case you infer restrictions too, in an unsound way because the inference does not take into consideration the subclasses.

> - adding the attribute retains covariance.
>

I am sorry, but I do not understand your notion of covariance. Covariance is a precise notion from category theory. (A mapping between categories that conserves morphisms is called a covariant functor.)

>> given
>> inference. Attributes can force the specification in one direction
>> only (provide
>> more guarantees to callers), but not in the other one (require less from
>> subclasses).
>
> Pure and nothrow provide more guarantees, hence covariance.
>
>> The concerns the latter can certainly not be dismissed by using the same
>> arguments and reasoning as for the former without any further
>> examination.
>
> They're both the same issue of covariance.
>

class C{
    final foo(){ ... } // <- this signature is foo's signature only
    auto  bar(){ ... } // <- this signature has to fit all overrides
}

In the first case, inference is mostly fine because you cannot unduly restrict someone: The signature will actually match foo's implementation.

In the second case you cannot infer the attributes because you do not know all subclasses. The signature will potentially not match all overrides.

Case in point, I just noticed the following regression on git head:

import std.stdio;

class C(T){
    T foo(){ return 2; }
}

class D : C!int{
    override int foo(){ writeln(super.foo()); return 3; } // error
}


Inference shouldn't be done for virtual functions.

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


April 18, 2013
On 4/17/2013 11:49 PM, Timon Gehr wrote:
> I am sorry, but I do not understand your notion of covariance.

Overriding functions can add pure or nothrow and remain covariant.

> In the second case you cannot infer the attributes because you do not know all
> subclasses. The signature will potentially not match all overrides.

If you want a precise signature, don't use auto. It's the same case as everywhere else.


> Case in point, I just noticed the following regression on git head:
>
> import std.stdio;
>
> class C(T){
>      T foo(){ return 2; }
> }
>
> class D : C!int{
>      override int foo(){ writeln(super.foo()); return 3; } // error
> }
>
>
> Inference shouldn't be done for virtual functions.
>
> http://d.puremagic.com/issues/show_bug.cgi?id=9952

This is not an auto issue.

April 18, 2013
On Thursday, 18 April 2013 at 05:59:20 UTC, kenji hara wrote:
> It will break existing code.
>
> int foo() {
>     typeof(return) bar() { return 1; }
>     return bar();
> }
>
> typeof(return) represents the return type of foo, that is int.
>
> Kenji Hara

It wouldn't break the code though. It would change the meaning, but the code would compile just as it did before.
April 18, 2013
On 4/18/13 2:38 AM, Walter Bright wrote:
> On 4/17/2013 11:34 PM, deadalnix wrote:
>> On Thursday, 18 April 2013 at 05:59:20 UTC, kenji hara wrote:
>>> It will break existing code.
>>>
>>> int foo() {
>>> typeof(return) bar() { return 1; }
>>> return bar();
>>> }
>>>
>>> typeof(return) represents the return type of foo, that is int.
>>>
>>
>> That is true :( Don't seem fixable.
>
> It is fixable if it is special cased, but special cases stink.

Thanks Kenji for a surgical destruction.

Andrei
April 18, 2013
On 4/18/13 2:49 AM, Timon Gehr wrote:
> On 04/18/2013 01:46 AM, Walter Bright wrote:
>> - adding the attribute retains covariance.
>>
>
> I am sorry, but I do not understand your notion of covariance.

I think he means subtyping. An attributed function (pure, nothrow) is a subtype of a non-attributed function. That means it can substitute the non-attributed function.


Andrei
April 19, 2013
W dniu 18.04.2013 16:58, Andrei Alexandrescu pisze:
> On 4/18/13 2:38 AM, Walter Bright wrote:
>> On 4/17/2013 11:34 PM, deadalnix wrote:
>>> On Thursday, 18 April 2013 at 05:59:20 UTC, kenji hara wrote:
>>>> It will break existing code.
>>>>
>>>> int foo() {
>>>> typeof(return) bar() { return 1; }
>>>> return bar();
>>>> }
>>>>
>>>> typeof(return) represents the return type of foo, that is int.
>>>>
>>>
>>> That is true :( Don't seem fixable.
>>
>> It is fixable if it is special cased, but special cases stink.
>
> Thanks Kenji for a surgical destruction.

What about this:

auto inferReturnTypeAndAttributes() { ... }
auto(return) inferOnlyReturnType() { ... }

or since all attributes are constraints, it can be rewritten to:

auto inferOnlyReturnType() pure nothrow @safe { ... }

It really doesn't make sense to infer impurity, throwing or unsafety because these are the default.

I imagine there are some use cases where programmer for example wants to infer all but purity, possibly because some other part of the code relies on pure behavior of his function, and he doesn't care about the other attributes. Example of pure function where nothrow and safety are inferred:

auto inferAllButPurity() pure { ... }

To sum up:

1. auto               - infers all
2. auto(return)       - infers only a return type
3. auto fn() attrs... - infers return type and all not specified attributes

Second and third are equivalent, thus auto(return) is optional.

There were some voices about breaking overriden functions by adding/inferring superclass function attribute. I think this is an oversight, virtual functions should not have attributes inferred.
April 19, 2013
On Friday, 19 April 2013 at 12:43:49 UTC, Piotr Szturmaj wrote:
>
> What about this:
>
> auto inferReturnTypeAndAttributes() { ... }
> auto(return) inferOnlyReturnType() { ... }
>
> or since all attributes are constraints, it can be rewritten to:
>
> auto inferOnlyReturnType() pure nothrow @safe { ... }
>
> It really doesn't make sense to infer impurity, throwing or unsafety because these are the default.
>
> I imagine there are some use cases where programmer for example wants to infer all but purity, possibly because some other part of the code relies on pure behavior of his function, and he doesn't care about the other attributes. Example of pure function where nothrow and safety are inferred:
>
> auto inferAllButPurity() pure { ... }
>
> To sum up:
>
> 1. auto               - infers all
> 2. auto(return)       - infers only a return type
> 3. auto fn() attrs... - infers return type and all not specified attributes
>
> Second and third are equivalent, thus auto(return) is optional.
>
> There were some voices about breaking overriden functions by adding/inferring superclass function attribute. I think this is an oversight, virtual functions should not have attributes inferred.

I like this. It provides a good balance of control and automation.

how would template functions be treated with auto(return)?
April 19, 2013
W dniu 19.04.2013 15:43, John Colvin pisze:
> I like this. It provides a good balance of control and automation.
>
> how would template functions be treated with auto(return)?

I see no need for special treating of template functions. In this case only return type would be inferred. Programmers should then specify attributes explicitly. By default, template functions with auto(return) would be impure, throwing and unsafe.
April 19, 2013
On Friday, 19 April 2013 at 12:43:49 UTC, Piotr Szturmaj wrote:
> What about this:
>
> auto inferReturnTypeAndAttributes() { ... }
> auto(return) inferOnlyReturnType() { ... }
>
> or since all attributes are constraints, it can be rewritten to:
>
> auto inferOnlyReturnType() pure nothrow @safe { ... }
>
> It really doesn't make sense to infer impurity, throwing or unsafety because these are the default.
>
> I imagine there are some use cases where programmer for example wants to infer all but purity, possibly because some other part of the code relies on pure behavior of his function, and he doesn't care about the other attributes. Example of pure function where nothrow and safety are inferred:
>
> auto inferAllButPurity() pure { ... }
>
> To sum up:
>
> 1. auto               - infers all
> 2. auto(return)       - infers only a return type
> 3. auto fn() attrs... - infers return type and all not specified attributes
>
> Second and third are equivalent, thus auto(return) is optional.
>
> There were some voices about breaking overriden functions by adding/inferring superclass function attribute. I think this is an oversight, virtual functions should not have attributes inferred.

Except for 2, this is already what is proposed.

As of for 2 I'd rather have a standard way to have attribute binding to the return type or the declaration. This is a recurring problem, and auto is simply one instance of it.

auto applied to the return type means that we infers the return type, applied to the function it means infers return type AND attributes.
April 19, 2013
On 4/19/2013 6:55 AM, deadalnix wrote:
> As of for 2 I'd rather have a standard way to have attribute binding to the
> return type or the declaration. This is a recurring problem, and auto is simply
> one instance of it.

I'm not understanding it being a recurring problem. There is a recurring misunderstanding that attributes are applying to a type when they are defined as applying to the declaration.

> auto applied to the return type means that we infers the return type, applied to
> the function it means infers return type AND attributes.

auto never applies to a type, it always applies to the declaration and hence the type of that declaration.