Thread overview
Fields with the same name not causing a warning?
Nov 16, 2018
Vinay Sajip
Nov 16, 2018
Basile B.
Nov 16, 2018
Vinay Sajip
Nov 16, 2018
Basile B.
Nov 16, 2018
Vinay Sajip
Nov 16, 2018
Dennis
Nov 16, 2018
Vinay Sajip
Nov 16, 2018
Dennis
Nov 16, 2018
Norm
November 16, 2018
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?
November 16, 2018
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.
November 16, 2018
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.
November 16, 2018
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".
November 16, 2018
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 ;-)

November 16, 2018
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 `override` keyword  like in C#. However, in D it *might* make 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.
November 16, 2018
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 `override` keyword  like in C#. However, in D it *might* make 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?
November 16, 2018
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
November 16, 2018
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.