March 12, 2012
On Mon, 12 Mar 2012 07:04:52 +0100, Alex Rønne Petersen <xtzgzorex@gmail.com> wrote:

> Or, as a compromise, perhaps the compiler can auto-infer most of the
> attributes without any further effort from the user.
>  No, that has API design issues. You can silently break a guarantee you made previously.

What's wrong with auto-inference. Inferred attributes are only strengthening guarantees.
March 12, 2012
> So I propose instead a bit of a hack. toHash, opEquals, and opCmp as struct members be automatically annotated with pure, nothrow, and @safe (if not already marked as @trusted).

How about complete inference instead of a hack?
March 12, 2012
On 12 March 2012 21:08, Martin Nowak <dawg@dawgfoto.de> wrote:
> On Mon, 12 Mar 2012 07:04:52 +0100, Alex Rønne Petersen <xtzgzorex@gmail.com> wrote:
>
>> Or, as a compromise, perhaps the compiler can auto-infer most of the
>> attributes without any further effort from the user.
>>  No, that has API design issues. You can silently break a guarantee you
>> made previously.
>
>
> What's wrong with auto-inference. Inferred attributes are only strengthening guarantees.

One problem I can think of is relying on the auto-inference can create fragile code. You make a change in one place without concentrating and suddenly a completely different part of your code breaks, because it's expecting pure, or @safe code and you have done something to prevent the inference. I don't know how much of a problem that could be, but its one I can think of.

--
James Miller
March 12, 2012
Am Mon, 12 Mar 2012 07:06:33 +0100
schrieb Alex Rønne Petersen <xtzgzorex@gmail.com>:

> I should point out that I *do* think the idea is good (i.e. if you want the "bad" things, that's what you have to declare), but it's just too late now. Also, there might be issues with const and the likes - should the system assume const or immutable or inout or...?

"@safe pure nothrow" as default could have worked better than manually setting it, I agree. @safe can be set at module level, so it is less of an issue to make it the default in your code. The problem with those attributes is not that pure is used more often than impure or nothrow more often than throws, but that they need to be set transitive in function calls. And even though the attributes do no harm to the user of the function (unlike immutable) they can easily be forgotten or left away, because it is tedious to type them.

-- 
Marco

March 12, 2012
On 3/12/2012 1:08 AM, Martin Nowak wrote:
> What's wrong with auto-inference. Inferred attributes are only strengthening
> guarantees.

Auto-inference is currently done for lambdas and template functions - why? - because the function's implementation is guaranteed to be visible to the compiler. For other functions, not so, and so the attributes must be part of the function signature.
March 12, 2012
> One problem I can think of is relying on the auto-inference can create
> fragile code. You make a change in one place without concentrating and
> suddenly a completely different part of your code breaks, because it's
> expecting pure, or @safe code and you have done something to prevent
> the inference. I don't know how much of a problem that could be, but
> its one I can think of.
>
> --
> James Miller

That sounds intentionally.

Say you have a struct with a getHash method.

struct Key
{
    hash_t getHash() /* inferred pure */
    {
    }
}

Say you have an Set that requires a pure opHash.

void insert(Key key) pure
{
    immutable hash = key.toHash();
}

Now if you change the implementation of Key.getHash
then maybe it can no longer be inserted into that Set.
If OTOH your set.insert were inferred pure itself, then
the impureness would escalate to the set.insert(key) caller.

It's about the same logic that would makes nothrow more useful.
You can omit it most of the times but always have the
possibility to enforce it, e.g. at a much higher level.
March 12, 2012
> That sounds intentionally.
>
> Say you have a struct with a getHash method.
>
> struct Key
> {
>    hash_t getHash() /* inferred pure */
>    {
>    }
> }
>
> Say you have an Set that requires a pure opHash.
>
> void insert(Key key) pure
> {
>    immutable hash = key.toHash();
> }
>
> Now if you change the implementation of Key.getHash
> then maybe it can no longer be inserted into that Set.
> If OTOH your set.insert were inferred pure itself, then
> the impureness would escalate to the set.insert(key) caller.
>
> It's about the same logic that would makes nothrow more useful. You can omit it most of the times but always have the possibility to enforce it, e.g. at a much higher level.

My point was more about distant code breaking. Its more to do with unexpected behavior than code correctness in this case. As i said, I could be worrying about nothing though.

--
James Miller
March 12, 2012
Le 12/03/2012 00:54, Walter Bright a écrit :
> Consider the toHash() function for struct key types:
>
> http://dlang.org/hash-map.html
>
> And of course the others:
>
> const hash_t toHash();
> const bool opEquals(ref const KeyType s);
> const int opCmp(ref const KeyType s);
>
> They need to be, as well as const, pure nothrow @safe.
>
> The problem is:
> 1. a lot of code must be retrofitted
> 2. it's just plain annoying to annotate them
>
> It's the same problem as for Object.toHash(). That was addressed by
> making those attributes inheritable, but that won't work for struct ones.
>
> So I propose instead a bit of a hack. toHash, opEquals, and opCmp as
> struct members be automatically annotated with pure, nothrow, and @safe
> (if not already marked as @trusted).

I don't really see the point. For Objects, we inherit from Object, which can define theses.

For struct, we have inference, so most of the time attributes will correct. const pure nothrow @safe are something we want, but is it something we want to enforce ?
March 12, 2012
On 12/03/12 00:55, Alex Rønne Petersen wrote:
> On 12-03-2012 00:54, Walter Bright wrote:
>> Consider the toHash() function for struct key types:
>>
>> http://dlang.org/hash-map.html
>>
>> And of course the others:
>>
>> const hash_t toHash();
>> const bool opEquals(ref const KeyType s);
>> const int opCmp(ref const KeyType s);
>>
>> They need to be, as well as const, pure nothrow @safe.
>>
>> The problem is:
>> 1. a lot of code must be retrofitted
>>A 2. it's just plain annoying to annotate them

Maybe we need @nice or something, to mean pure nothrow @safe.

>>
>> It's the same problem as for Object.toHash(). That was addressed by
>> making those attributes inheritable, but that won't work for struct ones.
>>
>> So I propose instead a bit of a hack. toHash, opEquals, and opCmp as
>> struct members be automatically annotated with pure, nothrow, and

That was sounding reasonable, but...

> @safe (if not already marked as @trusted).
...this part is a bit scary. It sounds as though the semantics are a bit fuzzy.

There is no way to make a function as 'impure' or 'does_throw'.
But you can annotate with @system.

>
> It may be a hack, but you know, those have special semantics/meanings in
> the first place, so is it really that bad?

Agreed, they are in some sense virtual functions. But how would you declare those functions.  With "pure nothrow @safe", or with "pure nothrow @trusted" ?

> Consider also that contract
> blocks are now implicitly const, etc.

But the clutter problem isn't restricted to those specific functions.

One issue with pure, nothrow is that they have no inverse, so you cannot simply write pure: nothrow: at the top of the file and use 'pure nothrow' by default.

The underlying problem is that, when spelt out in full, those annotations uglify the code.
March 12, 2012
On 12-03-2012 10:40, Walter Bright wrote:
> On 3/12/2012 1:08 AM, Martin Nowak wrote:
>> What's wrong with auto-inference. Inferred attributes are only
>> strengthening
>> guarantees.
>
> Auto-inference is currently done for lambdas and template functions -
> why? - because the function's implementation is guaranteed to be visible
> to the compiler. For other functions, not so, and so the attributes must
> be part of the function signature.

Isn't auto-inference for templates a Bad Thing (TM) since it may give API guarantees that you can end up silently breaking?

-- 
- Alex