www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Fields with the same name not causing a warning?

reply Vinay Sajip <vinay_sajip yahoo.co.uk> writes:
This code should IMO give at least a warning, but it doesn't:

abstract class A {
     int kind;
}

class B : A {
     int kind;

     this(int k) {
         kind = k;
     }
}

In my actual code, the declaration of field "kind" in B was left 
in accidentally. Surprisingly, however, no warning was emitted 
when I compiled this, leading to B having two fields called kind 
which are distinct from one another. The complete program

import std.stdio;

abstract class A {
     int kind;
}

class B : A {
     int kind;

     this(int k) {
         kind = k;
     }
}

void main()
{
     auto b = new B(4);
     A a = b;

     writeln(b.kind);
     writeln(a.kind);
}

prints

4
0

Given that this is the kind of thing that is easily done, surely 
the default behaviour should be for the compiler to emit at least 
a warning that field "kind" is ambiguous in B? This behaviour 
occurs even when the field is declared as "public" or "protected" 
in both classes. What am I missing?
Nov 16 2018
next sibling parent reply Basile B. <b2.temp gmx.com> writes:
On Friday, 16 November 2018 at 15:59:14 UTC, Vinay Sajip wrote:
 This code should IMO give at least a warning, but it doesn't:

 abstract class A {
     int kind;
 }

 class B : A {
     int kind;

     this(int k) {
         kind = k;
     }
 }

 In my actual code, the declaration of field "kind" in B was 
 left in accidentally. Surprisingly, however, no warning was 
 emitted when I compiled this, leading to B having two fields 
 called kind which are distinct from one another. The complete 
 program

 import std.stdio;

 abstract class A {
     int kind;
 }

 class B : A {
     int kind;

     this(int k) {
         kind = k;
     }
 }

 void main()
 {
     auto b = new B(4);
     A a = b;

     writeln(b.kind);
     writeln(a.kind);
 }

 prints

 4
 0

 Given that this is the kind of thing that is easily done, 
 surely the default behaviour should be for the compiler to emit 
 at least a warning that field "kind" is ambiguous in B? This 
 behaviour occurs even when the field is declared as "public" or 
 "protected" in both classes. What am I missing?
When you re declare with the same name in a sub class each generation has its own variable. To distinguish you can use the type for which you want "kind": writeln(b.A.kind); // the one from A writeln(b.B.kind); // the one from B I agree that this is almost a case of shadowing but i don't know the exact rationale for allowing this.
Nov 16 2018
parent reply Vinay Sajip <vinay_sajip yahoo.co.uk> writes:
On Friday, 16 November 2018 at 17:08:00 UTC, Basile B. wrote:

 I agree that this is almost a case of shadowing but i don't 
 know the exact rationale for allowing this.
I'm not saying it shouldn't be allowed - just that the compiler could warn you about what might very well be a mistake (as it was in my case) - hard to debug with printf debugging, and source level debug for D is a bit thin on the ground, ISTM.
Nov 16 2018
parent reply Basile B. <b2.temp gmx.com> writes:
On Friday, 16 November 2018 at 17:28:15 UTC, Vinay Sajip wrote:
 On Friday, 16 November 2018 at 17:08:00 UTC, Basile B. wrote:

 I agree that this is almost a case of shadowing but i don't 
 know the exact rationale for allowing this.
I'm not saying it shouldn't be allowed - just that the compiler could warn you about what might very well be a mistake (as it was in my case) - hard to debug with printf debugging, and source level debug for D is a bit thin on the ground, ISTM.
D is not a compiler that warns much. You can still open an issue asking for this (and the warning must be easy to add at first glance), but the policy applied to warnings is "compilers warnings are a sign of design flaws so instead of emitting one we should rather fix the flaw".
Nov 16 2018
parent reply Vinay Sajip <vinay_sajip yahoo.co.uk> writes:
On Friday, 16 November 2018 at 17:35:13 UTC, Basile B. wrote:
 D is not a compiler that warns much. You can still open an 
 issue asking for this (and the warning must be easy to add at 
 first glance), but the policy applied to warnings is "compilers 
 warnings are a sign of design flaws so instead of emitting one 
 we should rather fix the flaw".
Design flaws in what? In this case, the flaw was in my code, but I would expect some help from the compiler in catching such an ambiguity, and so fixing the flaw in my code. That it didn't try to help me might itself be considered a design flaw in the compiler ;-)
Nov 16 2018
parent reply Dennis <dkorpel gmail.com> writes:
On Friday, 16 November 2018 at 18:37:00 UTC, Vinay Sajip wrote:
 Design flaws in what?
Design flaws in the language. Quoting Jonathan M Davis: "Honestly, in general, warnings are a terrible idea. Anything that's a warning in your code has to be fixed, because it's bad practice to leave warnings in your code, meaning that ultimately, there's not much difference between a warning and an error. To make matters worse, there's a compiler flag that turns warnings into errors. And when you combine that with stuff like is(typeof(...)) and template constraints, whether you use that compiler flag or not could actually change the resulting program. So, as it stands, warnings are an even worse idea in D than they are in other languages. Walter likes to talk about how warnings in C/C++ are there simply because folks couldn't agree on what should or shouldn't be an error in the language. If something is definitively wrong, then it should be an error. If it's not definitively wrong, then the compiler shouldn't say anything about it, and it should be left up to a linter tool of some kind like dcd." https://forum.dlang.org/post/mailman.3986.1537881312.29801.digitalmars-d puremagic.com The language design could be fixed by requiring the use of the generic code (with mixins) more complicated, though I personally have never found a use for hiding member variables so I don't know the rationale.
Nov 16 2018
parent reply Vinay Sajip <vinay_sajip yahoo.co.uk> writes:
On Friday, 16 November 2018 at 19:12:42 UTC, Dennis wrote:
 If something is definitively wrong, then it should be an error. 
 If it's not definitively wrong, then the compiler shouldn't say 
 anything about it, and it should be left up to a linter tool of 
 some kind like dcd."

 https://forum.dlang.org/post/mailman.3986.1537881312.29801.digitalmars-d puremagic.com
Thanks for that link, it helps to understand the thinking behind the way things are.
 The language design could be fixed by requiring the use of the 

 generic code (with mixins) more complicated, though I 
 personally have never found a use for hiding member variables 
 so I don't know the rationale.
More complicated for the compiler writers, or users of mixins/generics? In any case, the example I showed was more commonplace than mixins and templates. Perhaps the default should be to fail compilation with an error, and allow `override` when someone actually wants to hide/shadow members in base classes, for whatever reason. I suggested "warning" rather than "error" in the OP, because I didn't know the philosophy behind warnings in D that you've now made me aware of. But presumably making it an error would potentially be a breaking change?
Nov 16 2018
parent Dennis <dkorpel gmail.com> writes:
On Friday, 16 November 2018 at 20:13:42 UTC, Vinay Sajip wrote:
 More complicated for the compiler writers, or users of 
 mixins/generics?
For users of generics. It's hard to come up with an actual example because I don't know why one would ever use this, but in this concocted scenario: ``` mixin template initRange() { typeof(this) front = typeof(this).init; enum empty = true; void popFront() {} } class A { mixin initRange; } class B : A { mixin initRange; } ``` The initRange template would need a static if to decide whether to add `override` or not. On Friday, 16 November 2018 at 20:13:42 UTC, Vinay Sajip wrote:
 But presumably making it an error would potentially be a 
 breaking change?
It would be breaking. The question is how much breakage there is of 'correct' hiding vs. how often unintended hiding leads to problems.
Nov 16 2018
prev sibling parent Norm <norm.rowtree gmail.com> writes:
On Friday, 16 November 2018 at 15:59:14 UTC, Vinay Sajip wrote:
 This code should IMO give at least a warning, but it doesn't:

 abstract class A {
     int kind;
 }

 [...]
This is not unique to D you can do the same in Java or C++. bye, Norm
Nov 16 2018