February 17, 2012
On Fri, Feb 17, 2012 at 05:27:11PM +0000, Michal Minich wrote: [...]
> Will the 'inheritance' of attributes work for interfaces too?
> 
>      interface I { void foo() @safe pure nothrow const; }
>      class B : I { void foo() { } }  // is it @safe pure nothrow const ?

I think it would make sense to do this.


--T
February 17, 2012
On 2/17/2012 9:27 AM, Michal Minich wrote:
> Will the 'inheritance' of attributes work for interfaces too?
>
>       interface I { void foo() @safe pure nothrow const; }
>       class B : I { void foo() { } }  // is it @safe pure nothrow const ?

Yes.
February 17, 2012
On Friday, 17 February 2012 at 16:17:23 UTC, Andrei Alexandrescu wrote:
> Agreed. Timon, could you please submit to bugzilla?
>

Filed as an enhancement:
http://d.puremagic.com/issues/show_bug.cgi?id=7534

> BTW I referred to the converse problem:
>
> class C {
>   void foo() {}
>   void foo() const {}
> }
>
> class D : C {
>   void foo() const {} // should only override the const overload
> }
>
>
> Andrei
>

OK. Note that alias C.foo foo; inside Ds body is required in order to make the code compile by inheriting the overload.
February 17, 2012
On Thu, 16 Feb 2012 21:49:40 -0500, Walter Bright <newshound2@digitalmars.com> wrote:

> Given:
>
>      class A { void foo() { } }
>      class B : A { override pure void foo() { } }
>
> This works great, because B.foo is covariant with A.foo, meaning it can "tighten", or place more restrictions, on foo. But:
>
>      class A { pure void foo() { } }
>      class B : A { override void foo() { } }
>
> fails, because B.foo tries to loosen the requirements, and so is not covariant.
>
> Where this gets annoying is when the qualifiers on the base class function have to be repeated on all its overrides. I ran headlong into this when experimenting with making the member functions of class Object pure.
>
> So it occurred to me that an overriding function could *inherit* the qualifiers from the overridden function. The qualifiers of the overriding function would be the "tightest" of its explicit qualifiers and its overridden function qualifiers. It turns out that most functions are naturally pure, so this greatly eases things and eliminates annoying typing.
>
> I want do to this for @safe, pure, nothrow, and even const.
>
> I think it is semantically sound, as well. The overriding function body will be semantically checked against this tightest set of qualifiers.
>
> What do you think?

I think it feels like a (welcome) about face from previous stances.  But I share some concern with others in that we are separating the attributes of a function from its declaration to the point where we need a tool to determine what the exact attributes of a function are.

I shudder to think about how I would understand some of the CSS I have to deal in my daily work if I didn't have firebug.  I hope D doesn't become similar.

Of course, if we get to the point where DDoc is full-featured, one will almost never have to look at function declarations when using them.

Also, I like how you *can* repeat the attributes if it's necessary to.

Could there be a compiler option for requiring overriding functions to repeat base attributes?  Or at least print out where they are while compiling?  At least then you can see where your attributes aren't repeated.

-Steve
February 18, 2012
Le 17/02/2012 04:54, Jonathan M Davis a écrit :
> On Thursday, February 16, 2012 19:41:00 Walter Bright wrote:
>> On 2/16/2012 7:23 PM, Jonathan M Davis wrote:
>>> No. Absolutely not. I hate the fact that C++ does this with virtual. It
>>> makes it so that you have to constantly look at the base classes to
>>> figure out what's virtual and what isn't. It harms maintenance and code
>>> understandability. And now you want to do that with @safe, pure, nothrow,
>>> and const? Yuck.
>> I do not see how it harms maintainability. It does not break any existing
>> code. It makes it easier to convert a function hierarchy to nothrow, pure,
>> etc.
>
> It makes it harder to maintain the code using the derived classes, because you
> end up with a bunch of functions which aren't labeled with their attributes.
> You have to go and find all of the base classes and look at them to find which
> attributes are on their functions to know what the attributes of the functions
> of the derived classes actually are. It will make using all D classes harder.
>
> You should be able to look at a function and know whether it's pure, @safe,
> nothrow, or const without having to dig through documentation and/or code
> elsewhere to figure it out.
>
> Doing this would make the conversion to const easier but be harmful in the
> long run.
>
> - Jonathan M Davis

As long as the overriden keyword is specified, you are warned about this, and so it isn't a problem.

Obviously, this shouldn't apply to override that are not explicitely marked as such (with overriden keyword).
February 18, 2012
Le 17/02/2012 17:17, Andrei Alexandrescu a écrit :
> Agreed. Timon, could you please submit to bugzilla?
>
> BTW I referred to the converse problem:
>
> class C {
> void foo() {}
> void foo() const {}
> }
>
> class D : C {
> void foo() const {} // should only override the const overload
> }
>
>
> Andrei
>
> On 2/17/12 8:00 AM, kenji hara wrote:
>> I think this is a current implementation problem.
>>
>> In this case, just `override void foo()` in class D should override
>> the method in C.
>> And `void foo()const` should be a new overlodad of foo.
>>
>> Kenji Hara
>>
>> 2012/2/17 Timon Gehr<timon.gehr@gmx.ch>:
>>> On 02/17/2012 02:33 PM, Timon Gehr wrote:
>>>>
>>>>
>>>> Introducing a new overload against const in a subclass is illegal:
>>>>
>>>> class C{
>>>> void foo(){}
>>>> }
>>>> class D : C{
>>>> override void foo(){}
>>>> override void foo()const{}
>>>> }
>>>>
>>>> Error: D.foo multiple overrides of same function
>>>
>>>
>>> Oops...
>>>
>>> I meant
>>>
>>>
>>> class C{
>>> void foo(){}
>>> }
>>>
>>> class D:C{
>>> override void foo(){}
>>> void foo()const{}
>>> }
>>>
>>> The error message is the same though.
>

I guess that is such a case, const should be explicited to get rid of abiguous code.
February 18, 2012
Le 17/02/2012 03:49, Walter Bright a écrit :
> Given:
>
> class A { void foo() { } }
> class B : A { override pure void foo() { } }
>
> This works great, because B.foo is covariant with A.foo, meaning it can
> "tighten", or place more restrictions, on foo. But:
>
> class A { pure void foo() { } }
> class B : A { override void foo() { } }
>
> fails, because B.foo tries to loosen the requirements, and so is not
> covariant.
>
> Where this gets annoying is when the qualifiers on the base class
> function have to be repeated on all its overrides. I ran headlong into
> this when experimenting with making the member functions of class Object
> pure.
>
> So it occurred to me that an overriding function could *inherit* the
> qualifiers from the overridden function. The qualifiers of the
> overriding function would be the "tightest" of its explicit qualifiers
> and its overridden function qualifiers. It turns out that most functions
> are naturally pure, so this greatly eases things and eliminates annoying
> typing.
>
> I want do to this for @safe, pure, nothrow, and even const.
>
> I think it is semantically sound, as well. The overriding function body
> will be semantically checked against this tightest set of qualifiers.
>
> What do you think?

Walter, I think you get the const qualifier wrong. const does not qualify the method, but the hidden parameter "this".

I don't think this is a good idea for const/immutable . Simply because you may want to have both defined, and it lead to ambiguity.

However, for pure, @safe, nothrow and basically any qualifier that effectively qualify the function, it is a great idea.

BTW, to keep the source code understandable, this should be enabled only if the overriden keyword is present. So if you see a function with overriden, you'll know about thoses qualifier possibly being present. If the overriden isn't present, the current behaviour should be preserved.
February 18, 2012
After some thoughts, I agree that inheritance of pure @safe, and
nothrow is good feature.
But I disagree to const inference, because const attribute interacts
with overloadings.

Kenji Hara

2012/2/17 Walter Bright <newshound2@digitalmars.com>:
> Given:
>
>    class A { void foo() { } }
>    class B : A { override pure void foo() { } }
>
> This works great, because B.foo is covariant with A.foo, meaning it can "tighten", or place more restrictions, on foo. But:
>
>    class A { pure void foo() { } }
>    class B : A { override void foo() { } }
>
> fails, because B.foo tries to loosen the requirements, and so is not covariant.
>
> Where this gets annoying is when the qualifiers on the base class function have to be repeated on all its overrides. I ran headlong into this when experimenting with making the member functions of class Object pure.
>
> So it occurred to me that an overriding function could *inherit* the qualifiers from the overridden function. The qualifiers of the overriding function would be the "tightest" of its explicit qualifiers and its overridden function qualifiers. It turns out that most functions are naturally pure, so this greatly eases things and eliminates annoying typing.
>
> I want do to this for @safe, pure, nothrow, and even const.
>
> I think it is semantically sound, as well. The overriding function body will be semantically checked against this tightest set of qualifiers.
>
> What do you think?
February 18, 2012
On 02/18/2012 03:46 PM, deadalnix wrote:
> Le 17/02/2012 03:49, Walter Bright a écrit :
>> Given:
>>
>> class A { void foo() { } }
>> class B : A { override pure void foo() { } }
>>
>> This works great, because B.foo is covariant with A.foo, meaning it can
>> "tighten", or place more restrictions, on foo. But:
>>
>> class A { pure void foo() { } }
>> class B : A { override void foo() { } }
>>
>> fails, because B.foo tries to loosen the requirements, and so is not
>> covariant.
>>
>> Where this gets annoying is when the qualifiers on the base class
>> function have to be repeated on all its overrides. I ran headlong into
>> this when experimenting with making the member functions of class Object
>> pure.
>>
>> So it occurred to me that an overriding function could *inherit* the
>> qualifiers from the overridden function. The qualifiers of the
>> overriding function would be the "tightest" of its explicit qualifiers
>> and its overridden function qualifiers. It turns out that most functions
>> are naturally pure, so this greatly eases things and eliminates annoying
>> typing.
>>
>> I want do to this for @safe, pure, nothrow, and even const.
>>
>> I think it is semantically sound, as well. The overriding function body
>> will be semantically checked against this tightest set of qualifiers.
>>
>> What do you think?
>
> Walter, I think you get the const qualifier wrong. const does not
> qualify the method, but the hidden parameter "this".
>

Conceptually, close. Effectively, no. Const methods are the only place in the language where 'contravariant' overrides are allowed.

> I don't think this is a good idea for const/immutable . Simply because
> you may want to have both defined, and it lead to ambiguity.
>

With the current overriding/overloading rules I see no possibility for ambiguity.

This is illegal:

class C{
    void foo() {}
}
class D: C{
    override void foo() {}
    void foo()const {}
}

This is unambiguous:

class C{
    void foo() {}
    void foo()const {}
}

class D: C{
    alias C.foo foo;
    override void foo() {} // overrides first overload
}

A minor issue I see:
Possible hijacking scenario:

abstract class C{
    void foo();
    void foo()const { ... }
}
class D: C{
    alias C.foo foo; // explicitly loosen hijacking prevention
    override void foo() { (cast(const)this).foo(); }
}

"we don't need a non-const overload..." =>

abstract class C{
    void foo()const { ... }
}
class D: C{
    alias C.foo foo; // explicitly loosen hijacking prevention
    override void foo() { (cast(const)this).foo(); } // foo()const hijacked
}

Error under old rules, hijacking that introduces infinite recursion under new rules.


> However, for pure, @safe, nothrow and basically any qualifier that
> effectively qualify the function, it is a great idea.
>

For them, it is certainly safe. It is questionable how large the effective benefit is for const, since the const qualifier would be inherited for the method only, but not for its parameters.

> BTW, to keep the source code understandable, this should be enabled only
> if the overriden keyword is present. So if you see a function with
> overriden, you'll know about thoses qualifier possibly being present. If
> the overriden isn't present, the current behaviour should be preserved.

'override' will be mandatory soon anyway.
February 18, 2012
On 2/18/2012 6:49 AM, kenji hara wrote:
> After some thoughts, I agree that inheritance of pure @safe, and
> nothrow is good feature.
> But I disagree to const inference, because const attribute interacts
> with overloadings.

The const inheritance *only* happens if otherwise you'd get a covariance error. It does not change the meaning of any existing code that compiled successfully.