Jump to page: 1 25  
Page
Thread overview
***** D method override mechanisms borked ******
Jun 24, 2006
kris
Jun 24, 2006
Lars Ivar Igesund
Jun 24, 2006
John Reimer
Jun 24, 2006
kris
Jun 25, 2006
Sean Kelly
Jun 25, 2006
Bruno Medeiros
Jun 25, 2006
Sean Kelly
Jun 26, 2006
Bruno Medeiros
Jun 25, 2006
kris
Jun 26, 2006
Bruno Medeiros
Jun 26, 2006
kris
Jun 26, 2006
Regan Heath
Jun 26, 2006
John Reimer
Jun 27, 2006
Regan Heath
Jun 27, 2006
kris
Jun 27, 2006
Dave
Jun 28, 2006
Bruno Medeiros
Jun 28, 2006
Dave
Jul 06, 2006
jcc7
Jun 27, 2006
Regan Heath
Jun 27, 2006
Carlos Santander
Jun 27, 2006
kris
Jun 27, 2006
Carlos Santander
Jun 27, 2006
kris
Jun 27, 2006
John Reimer
Jun 27, 2006
Bruno Medeiros
Jun 27, 2006
Sean Kelly
Jun 27, 2006
John Reimer
Re: ***** D method override mechanisms borked ****** (some more borkiness)
Jul 01, 2006
Bruno Medeiros
Jul 01, 2006
Sean Kelly
Jul 01, 2006
Derek Parnell
Jul 01, 2006
Derek Parnell
Jun 30, 2006
Bruno Medeiros
Jun 25, 2006
Sean Kelly
Jun 25, 2006
Dave
Jun 25, 2006
Lars Ivar Igesund
Jun 26, 2006
xs0
Jun 25, 2006
Dave
June 24, 2006
Used to be that overriding methods in subclasses had some logic to it. Now? Well, who knows:

1) you can override a protected method and make it public. Doh!

2) you can override a public method and make it private ... ok, but get this -- the overload is not virtual -- it doesn't "actually" overload at all. Very sneaky bug in the making, especially when the base class is altered just slightly.

3) to fix #2 let's use the override keyword! Yay! That will ensure we're actually overriding the base class method instance! Well, it compiles, but does *not* override. Bork Bork Bork.

And so on, ad infinitum.

This was not a problem at some distant point in the past. Now the rules are (a) too murky for this simple dude to even comprehend and (b) apparently thoroughly broken. The behaviour turns D into a land-mine for both the unwary and for the seasoned professional. How to turn people away from D in one easy lesson.

Please, please, please revert whatever cleverness was injected there and make it work in a clear, precise, /obvious/, and above all, *dependable* manner. Heck, make the "override" keyword mandatory if you need to. The latter should at least work, or cause a compie-time error.


June 24, 2006
kris wrote:

> Used to be that overriding methods in subclasses had some logic to it. Now? Well, who knows:
> 
> 1) you can override a protected method and make it public. Doh!
> 
> 2) you can override a public method and make it private ... ok, but get this -- the overload is not virtual -- it doesn't "actually" overload at all. Very sneaky bug in the making, especially when the base class is altered just slightly.
> 
> 3) to fix #2 let's use the override keyword! Yay! That will ensure we're actually overriding the base class method instance! Well, it compiles, but does *not* override. Bork Bork Bork.
> 
> And so on, ad infinitum.
> 
> This was not a problem at some distant point in the past. Now the rules are (a) too murky for this simple dude to even comprehend and (b) apparently thoroughly broken. The behaviour turns D into a land-mine for both the unwary and for the seasoned professional. How to turn people away from D in one easy lesson.
> 
> Please, please, please revert whatever cleverness was injected there and make it work in a clear, precise, /obvious/, and above all, *dependable* manner. Heck, make the "override" keyword mandatory if you need to. The latter should at least work, or cause a compie-time error.

I couldn't agree more, and make sure the rules are thouroughly documented!

-- 
Lars Ivar Igesund
blog at http://larsivi.net
DSource & #D: larsivi
June 24, 2006
Lars Ivar Igesund wrote:
> kris wrote:
> 
>> Used to be that overriding methods in subclasses had some logic to it.
>> Now? Well, who knows:
>>
>> 1) you can override a protected method and make it public. Doh!
>>
>> 2) you can override a public method and make it private ... ok, but get
>> this -- the overload is not virtual -- it doesn't "actually" overload at
>> all. Very sneaky bug in the making, especially when the base class is
>> altered just slightly.
>>
>> 3) to fix #2 let's use the override keyword! Yay! That will ensure we're
>> actually overriding the base class method instance! Well, it compiles,
>> but does *not* override. Bork Bork Bork.
>>
>> And so on, ad infinitum.
>>
>> This was not a problem at some distant point in the past. Now the rules
>> are (a) too murky for this simple dude to even comprehend and (b)
>> apparently thoroughly broken. The behaviour turns D into a land-mine for
>> both the unwary and for the seasoned professional. How to turn people
>> away from D in one easy lesson.
>>
>> Please, please, please revert whatever cleverness was injected there and
>> make it work in a clear, precise, /obvious/, and above all, *dependable*
>> manner. Heck, make the "override" keyword mandatory if you need to. The
>> latter should at least work, or cause a compie-time error.
> 
> I couldn't agree more, and make sure the rules are thouroughly documented!
>  

Agree... Please fix!

(yes, another "me, too" post, but I'm hoping this helps get Walter's attention).

-JJR
June 24, 2006
Lars Ivar Igesund wrote:
> kris wrote:
> 
> 
>>Used to be that overriding methods in subclasses had some logic to it.
>>Now? Well, who knows:
>>
>>1) you can override a protected method and make it public. Doh!
>>
>>2) you can override a public method and make it private ... ok, but get
>>this -- the overload is not virtual -- it doesn't "actually" overload at
>>all. Very sneaky bug in the making, especially when the base class is
>>altered just slightly.
>>
>>3) to fix #2 let's use the override keyword! Yay! That will ensure we're
>>actually overriding the base class method instance! Well, it compiles,
>>but does *not* override. Bork Bork Bork.
>>
>>And so on, ad infinitum.
>>
>>This was not a problem at some distant point in the past. Now the rules
>>are (a) too murky for this simple dude to even comprehend and (b)
>>apparently thoroughly broken. The behaviour turns D into a land-mine for
>>both the unwary and for the seasoned professional. How to turn people
>>away from D in one easy lesson.
>>
>>Please, please, please revert whatever cleverness was injected there and
>>make it work in a clear, precise, /obvious/, and above all, *dependable*
>>manner. Heck, make the "override" keyword mandatory if you need to. The
>>latter should at least work, or cause a compie-time error.
> 
> 
> I couldn't agree more, and make sure the rules are thouroughly documented!
>  

Before Bruno gives me a ticket for terminology abuse, I should note that the use of "overload" in #2 was completely unintentional. One should at least wake up properly before getting one's daily dose of D frustration.

I seriously hope this is all just a mistake/bug/whatever, which will be fixed quickly and appropriately. However ...

The original behaviour limited the exposure of an overridden method to be less than or equal to the exposure of the original. For example, protected could not be made public via an override. The compiler would give you an error if you attempted to do so. The compiler used to prevent you from intercepting a superclass method where the original intent (of the designer) was that said method whould be internal usage only. For example, final, package, or private methods.

Now, you can intercept all you like. The compiler does not give an error at all. The following example illustrates a litany of places where the compiler should halt. Just ask yourself how one is supposed to design superclass functionality that should not be exposed, overridden or otherwise subverted by a subclass?


extern(C) int printf (char*, ...);

class Super
{
        protected void fu()
        {
                printf ("super fu\n");
        }

        package void bar()
        {
                printf ("super bar\n");
        }

        private void snafu()
        {
                printf ("super snafu\n");
        }

        private void fu1()
        {
                printf ("super fu\n");
        }

        final void bar1()
        {
                printf ("super bar\n");
        }

        final private void snafu1()
        {
                printf ("super snafu\n");
        }
}


class Sub : Super
{
	// illegal: exposing a protected method
        public void fu()
        {
                printf ("sub fu\n");
        }

	// illegal: exposing a package method
        public void bar()
        {
                printf ("sub bar\n");
        }

	// illegal: exposing a private method
        public void snafu()
        {
                printf ("sub snafu\n");
        }

	// illegal: "override" a private method
        private override void fu1()
        {
                printf ("sub fu1\n");
        }

	// illegal: "override" a final method
        private override void bar1()
        {
                printf ("sub bar1\n");
        }

	// illegal: override & expose a final private method
        public void snafu1()
        {
                printf ("sub snafu1\n");
        }
}


void main()
{
        auto s = new Sub;

        s.fu;
        s.bar;
        s.snafu;
        s.fu1;
        s.bar1;
        s.snafu1;
}


output:

sub fu
sub bar
sub snafu
sub fu1
sub bar1
sub snafu1


Basically, several well-known and fundamental OO tenets no longer exist in D; I personally have over two years of carefully designed libraries that are now little more than trash because of this (any subclass can now intercept any type of method implementation). Would imagine others are in the same boat.

Anyone who's ever tried to provide "read only" or immutable class implementation, particularly to make multi-threaded code so much more deterministic, can kiss that goodbye ... let's all wave together :/
June 25, 2006
kris wrote:
> 
> Basically, several well-known and fundamental OO tenets no longer exist in D; I personally have over two years of carefully designed libraries that are now little more than trash because of this (any subclass can now intercept any type of method implementation). Would imagine others are in the same boat.

This simply has to be a bug, as I can't imagine such a fundamental change occurring both intentionally and silently.  It strikes me as odd, however, that the language I remember in the spec concerning this seems absent.  It was in the "function inheritance and overriding" section, wasn't it?  At the very least, I remember quite clearly that private functions were not meant to be overridden by a base class, which contradicts the results of your example.  Perhaps a new ticket should be opened for this?


Sean
June 25, 2006
kris wrote:
> Lars Ivar Igesund wrote:
>> kris wrote:
>>
>>
>>> Used to be that overriding methods in subclasses had some logic to it.
>>> Now? Well, who knows:
>>>
>>> 1) you can override a protected method and make it public. Doh!
>>>
>>> 2) you can override a public method and make it private ... ok, but get
>>> this -- the overload is not virtual -- it doesn't "actually" overload at
>>> all. Very sneaky bug in the making, especially when the base class is
>>> altered just slightly.
>>>
>>> 3) to fix #2 let's use the override keyword! Yay! That will ensure we're
>>> actually overriding the base class method instance! Well, it compiles,
>>> but does *not* override. Bork Bork Bork.
>>>
>>> And so on, ad infinitum.
>>>
>>> This was not a problem at some distant point in the past. Now the rules
>>> are (a) too murky for this simple dude to even comprehend and (b)
>>> apparently thoroughly broken. The behaviour turns D into a land-mine for
>>> both the unwary and for the seasoned professional. How to turn people
>>> away from D in one easy lesson.
>>>
>>> Please, please, please revert whatever cleverness was injected there and
>>> make it work in a clear, precise, /obvious/, and above all, *dependable*
>>> manner. Heck, make the "override" keyword mandatory if you need to. The
>>> latter should at least work, or cause a compie-time error.
>>
>>
>> I couldn't agree more, and make sure the rules are thouroughly documented!
>>  
> 

> I seriously hope this is all just a mistake/bug/whatever, which will be fixed quickly and appropriately. However ...

#2 and #3 are clearly a bug, both because override must *always* override, and because " Private members cannot be overridden" (http://www.digitalmars.com/d/attribute.html).

But #1 is not a bug or incorrect, see below.

> 
> The original behaviour limited the exposure of an overridden method to be less than or equal to the exposure of the original. For example, protected could not be made public via an override. The compiler would give you an error if you attempted to do so. The compiler used to prevent you from intercepting a superclass method where the original intent (of the designer) was that said method whould be internal usage only. For example, final, package, or private methods.
> 

If that was the original behavior, that behavior was broken. You see, when overriding a method, limiting the protection level is unsafe, whereas widening the protection level is safe. The protection level is a call-site contract (like the return type) and as such is only safe when overridden invariantly or *covariantly*.

If you designed your classes around that original behavior, they're broken.


> Now, you can intercept all you like. The compiler does not give an error at all. The following example illustrates a litany of places where the compiler should halt. Just ask yourself how one is supposed to design superclass functionality that should not be exposed, overridden or otherwise subverted by a subclass?
> 
> 
> extern(C) int printf (char*, ...);
> ...

As per what I said above, some of those examples are not incorrect. The others are.


> Before Bruno gives me a ticket for terminology abuse, I should note that
> the use of "overload" in #2 was completely unintentional. One should at
> least wake up properly before getting one's daily dose of D frustration.
>

No problem if it was unintentional. ;)

-- 
Bruno Medeiros - CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
June 25, 2006
kris wrote:

> Used to be that overriding methods in subclasses had some logic to it. Now? Well, who knows:
> 
> 1) you can override a protected method and make it public. Doh!

Yeah, as Bruno previously said, that should be allowed.

> 2) you can override a public method and make it private ... ok, but get this -- the overload is not virtual -- it doesn't "actually" overload at all. Very sneaky bug in the making, especially when the base class is altered just slightly.
> 
> 3) to fix #2 let's use the override keyword! Yay! That will ensure we're actually overriding the base class method instance! Well, it compiles, but does *not* override. Bork Bork Bork.
> 
> And so on, ad infinitum.

Damn, now all visibility / accessibility rules in D are totally broken.

I really don't think the system is ever going to work the way it is documented now. The interface stuff and part of classes use the covariance rule in inheritance. It's also possible to contravariantly inherit a base class using class foo: private bar {} (a la C++). Then there are private attributes in classes and modules that don't work so well either. Hmmpf, hope someone has time to sort this out. We're counting on you, Walter :)
June 25, 2006
Bruno Medeiros wrote:
> kris wrote:
>>
>> The original behaviour limited the exposure of an overridden method to be less than or equal to the exposure of the original. For example, protected could not be made public via an override. The compiler would give you an error if you attempted to do so. The compiler used to prevent you from intercepting a superclass method where the original intent (of the designer) was that said method whould be internal usage only. For example, final, package, or private methods.
>>
> 
> If that was the original behavior, that behavior was broken. You see, when overriding a method, limiting the protection level is unsafe, whereas widening the protection level is safe. The protection level is a call-site contract (like the return type) and as such is only safe when overridden invariantly or *covariantly*.
> 
> If you designed your classes around that original behavior, they're broken.

I'm not sure I agree.  However, if overriding behaves this way then it makes sense that aliasing should as well, and I would be surprised if aliasing ever behaved this way.  Perhaps this is one area where one should rely on programming style and not on the compiler?


Sean
June 25, 2006
Jari-Matti Mäkelä wrote:
> 
> Damn, now all visibility / accessibility rules in D are totally broken.
> 
> I really don't think the system is ever going to work the way it is
> documented now. The interface stuff and part of classes use the covariance
> rule in inheritance. It's also possible to contravariantly inherit a base
> class using class foo: private bar {} (a la C++). Then there are private
> attributes in classes and modules that don't work so well either. Hmmpf,
> hope someone has time to sort this out. We're counting on you, Walter :)

I think a careful programmer could make it work through extensive use of 'final'.  However, it's obviously preferable to simply fix the bug :-)


Sean
June 25, 2006
Sean Kelly wrote:
> Jari-Matti Mäkelä wrote:
>>
>> Damn, now all visibility / accessibility rules in D are totally broken.
>>
>> I really don't think the system is ever going to work the way it is
>> documented now. The interface stuff and part of classes use the
>> covariance
>> rule in inheritance. It's also possible to contravariantly inherit a base
>> class using class foo: private bar {} (a la C++). Then there are private
>> attributes in classes and modules that don't work so well either. Hmmpf,
>> hope someone has time to sort this out. We're counting on you, Walter :)
> 
> I think a careful programmer could make it work through extensive use of 'final'.  However, it's obviously preferable to simply fix the bug :-)

True, a careful programmer doesn't need these protection mechanics at all. In fact we could write some l33t stuff in pure asm as well! But that's not my point. I really cannot believe there's only one bug preventing us from having a working compiler.

There's not only some base classes and derived classes. They can also be
nested in multiple levels and then there's modules & packages that need
a consistent protection mechanics system with all classes. (then there's
also templates and other possible stuff implementing protection) I don't
get it - those all should be pretty consistent on a very high level. Now
it seems like DMD has pretty ugly ad-hoc solutions for different situations.

Then, to me it also seems to be totally braindead to mix both covariance and contravariance in inheritance semantics. Overriding in Java uses covariance (and that's the way it should work in D too, I think). Okay. Then there's public/protected/etc. inheritance from C++. Not only does it break possible elegant uses of interfaces a la Java, but it's also badly documented and implemented. In fact last time I checked it wasn't implemented at all. If it will be implemented some day, should we expect some kind of runtime exceptions when using these privately inherited classes covariantly? That works fine in C++ because C++ does not have interfaces, but IMO here it only adds confusion. Well, it might just be that I don't "get" it yet.

Another problem related to these mechanics is that DMD is not able to handle the whole module hierarchy when judging the visibility / protection rules. A simple diamond shaped import hierarchy breaks the system. I wonder how it works with diamond shaped inner class hierarchies.

-- 
Jari-Matti
« First   ‹ Prev
1 2 3 4 5