Re: Why is this allowed? Inheritance variable shadowing

2021-05-26 Thread mw via Digitalmars-d-learn

On Wednesday, 26 May 2021 at 18:58:47 UTC, JN wrote:

On Tuesday, 13 August 2019 at 04:40:53 UTC, Chris Katko wrote:

You can drop this straight into run.dlang.io:

import std.stdio;

class base{ float x=1;}
class child : base {float x=2;} //shadows base variable!

void main()
{

base []array;
child c = new child;
array ~= c;

writeln(c.x); //=2
writeln(array[0].x); //=1  //uses BASE's interface, yes,
//but why does the CHILD instance one exist at all?
}



Just got bitten by this. When copy pasting code of a bigger 
class, it's easy to miss the redefinition of variable.


Is there any viable usecase for this behavior? I am not buying 
the "C++ does it and it's legal there" argument. There's a 
reason most serious C++ projects use static analysis tools 
anyway. D should be better and protect against dangerous code 
by default. I think a warning in this case would be warranted.


Agree, at least a warning message, a PR someone?



Re: Why is this allowed? Inheritance variable shadowing

2021-05-26 Thread sighoya via Digitalmars-d-learn

On Wednesday, 26 May 2021 at 18:58:47 UTC, JN wrote:

I am not buying the "C++ does it and it's legal there" argument.


A point for it is the consistency with methods which also 
redefine super methods as default strategy.

The question is if the default strategy needs to be changed?
I wouldn't argue so as overriding super methods/fields as default 
is much more dangerous as it might destroy the super class's 
semantics.


What about explicitly tagging fields with override instead, then 
it would be a compile error if the base class hasn't the tagged 
fields.




Re: Why is this allowed? Inheritance variable shadowing

2021-05-26 Thread Ola Fosheim Grostad via Digitalmars-d-learn

On Wednesday, 26 May 2021 at 18:58:47 UTC, JN wrote:
Is there any viable usecase for this behavior? I am not buying 
the "C++ does it and it's legal there" argument. There's a 
reason most serious C++ projects use static analysis tools 
anyway. D should be better and protect against dangerous code 
by default. I think a warning in this case would be warranted.


There are certainly many usecases fo static members, maybe that 
is why designers feel it should be allowed for instance members 
too?


I think this is a clear case of something that should produce a 
warning and provide a silencing annotation fo the cases where you 
really want it.





Re: Why is this allowed? Inheritance variable shadowing

2021-05-26 Thread JN via Digitalmars-d-learn

On Tuesday, 13 August 2019 at 04:40:53 UTC, Chris Katko wrote:

You can drop this straight into run.dlang.io:

import std.stdio;

class base{ float x=1;}
class child : base {float x=2;} //shadows base variable!

void main()
{

base []array;
child c = new child;
array ~= c;

writeln(c.x); //=2
writeln(array[0].x); //=1  //uses BASE's interface, yes,
//but why does the CHILD instance one exist at all?
}



Just got bitten by this. When copy pasting code of a bigger 
class, it's easy to miss the redefinition of variable.


Is there any viable usecase for this behavior? I am not buying 
the "C++ does it and it's legal there" argument. There's a reason 
most serious C++ projects use static analysis tools anyway. D 
should be better and protect against dangerous code by default. I 
think a warning in this case would be warranted.




Re: Why is this allowed

2020-07-01 Thread tsbockman via Digitalmars-d-learn

On Wednesday, 1 July 2020 at 20:05:51 UTC, tsbockman wrote:
If you want the compiler to stop you from accidentally keeping 
references to stack variables past the end of their scope, you 
need to annotate your functions @safe and compile with 
-preview=dip1000: https://run.dlang.io/is/3VdDaN


Furthermore, the problem your example shows has nothing to do 
with implicit static to dynamic array conversion, as without 
@safe the same error can easily be committed with non-array 
types: https://run.dlang.io/is/nBjibd


Hmm. Those run.dlang.io short links seem to allow editing of the 
code, so I'd better paste it here for permanence:


// Compile with -preview=dip1000
struct Database {
int[] data;
void set(int[] _data) @safe {
data = _data;
}
}
void myFunc(ref Database db) @safe {
int[3] x;
db.set(x);  // This is a compile-time error, as it should be.
}

Database theDB;
void main() {
myFunc(theDB);
}

// This version shows that the problem is not using @safe and 
dip1000,

// not anything to do with arrays:
struct Database {
int* data;
void set(ref int _data) {
data = &_data;
}
}
void myFunc(ref Database db) {
int x;
db.set(x);  // oops
}

Database theDB;
void main() {
myFunc(theDB);
}




Re: Why is this allowed

2020-07-01 Thread tsbockman via Digitalmars-d-learn

On Tuesday, 30 June 2020 at 16:36:45 UTC, H. S. Teoh wrote:
And on that note, this implicit static -> dynamic array 
conversion is seriously a nasty misfeature that ought to be 
killed with fire. It leads to bugs like this:


struct Database {
int[] data;
void set(int[] _data) {
data = _data;
}
}
void myFunc(ref Database db) {
int[3] x;
db.set(x);  // oops
}


If you want the compiler to stop you from accidentally keeping 
references to stack variables past the end of their scope, you 
need to annotate your functions @safe and compile with 
-preview=dip1000: https://run.dlang.io/is/3VdDaN


Furthermore, the problem your example shows has nothing to do 
with implicit static to dynamic array conversion, as without 
@safe the same error can easily be committed with non-array 
types: https://run.dlang.io/is/nBjibd


Re: Why is this allowed

2020-07-01 Thread JN via Digitalmars-d-learn

On Wednesday, 1 July 2020 at 15:57:24 UTC, Nathan S. wrote:

On Tuesday, 30 June 2020 at 16:22:57 UTC, JN wrote:
Spent some time debugging because I didn't notice it at first, 
essentially something like this:


int[3] foo = [1, 2, 3];
foo = 5;
writeln(foo);   // 5, 5, 5

Why does such code compile? I don't think this should be 
permitted, because it's easy to make a mistake (when you 
wanted foo[index] but forgot the []). If someone wants to 
assign a value to every element they could do foo[] = 5; 
instead which is explicit.


What's your opinion on using that syntax in the initial 
declaration, like `float[16] foo = 0`?


I don't like it. I'd prefer:

float[16] foo = [ 0 ];

or

float[16] foo = { 0 };

or

float[16] foo(0);


Re: Why is this allowed

2020-07-01 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/1/20 11:57 AM, Nathan S. wrote:

On Tuesday, 30 June 2020 at 16:22:57 UTC, JN wrote:
Spent some time debugging because I didn't notice it at first, 
essentially something like this:


int[3] foo = [1, 2, 3];
foo = 5;
writeln(foo);   // 5, 5, 5

Why does such code compile? I don't think this should be permitted, 
because it's easy to make a mistake (when you wanted foo[index] but 
forgot the []). If someone wants to assign a value to every element 
they could do foo[] = 5; instead which is explicit.


What's your opinion on using that syntax in the initial declaration, 
like `float[16] foo = 0`?


It's important to keep at least something that allows such setting. It 
would be reasonable to do this with a function as well.


Is it possible to have the initialization syntax work differently from 
the assignment (i.e. allow the initialization as above, but require the 
brackets for assignment)?


-Steve


Re: Why is this allowed

2020-07-01 Thread Nathan S. via Digitalmars-d-learn

On Tuesday, 30 June 2020 at 16:22:57 UTC, JN wrote:
Spent some time debugging because I didn't notice it at first, 
essentially something like this:


int[3] foo = [1, 2, 3];
foo = 5;
writeln(foo);   // 5, 5, 5

Why does such code compile? I don't think this should be 
permitted, because it's easy to make a mistake (when you wanted 
foo[index] but forgot the []). If someone wants to assign a 
value to every element they could do foo[] = 5; instead which 
is explicit.


What's your opinion on using that syntax in the initial 
declaration, like `float[16] foo = 0`?


Re: Why is this allowed

2020-07-01 Thread psycha0s via Digitalmars-d-learn

On Tuesday, 30 June 2020 at 16:22:57 UTC, JN wrote:
Why does such code compile? I don't think this should be 
permitted, because it's easy to make a mistake (when you wanted 
foo[index] but forgot the []). If someone wants to assign a 
value to every element they could do foo[] = 5; instead which 
is explicit.


Totally agree. In most of cases implicit actions lead to errors. 
Even if they have a specific use case and really convenient.


Re: Why is this allowed

2020-06-30 Thread tastyminerals via Digitalmars-d-learn

On Tuesday, 30 June 2020 at 16:22:57 UTC, JN wrote:
Spent some time debugging because I didn't notice it at first, 
essentially something like this:


int[3] foo = [1, 2, 3];
foo = 5;
writeln(foo);   // 5, 5, 5

Why does such code compile? I don't think this should be 
permitted, because it's easy to make a mistake (when you wanted 
foo[index] but forgot the []). If someone wants to assign a 
value to every element they could do foo[] = 5; instead which 
is explicit.


auch, that is very nasty. Thanks for posting. This is a good 
example for D gotchas.


Re: Why is this allowed

2020-06-30 Thread Steven Schveighoffer via Digitalmars-d-learn

On 6/30/20 2:22 PM, H. S. Teoh wrote:

On Tue, Jun 30, 2020 at 02:06:13PM -0400, Steven Schveighoffer via 
Digitalmars-d-learn wrote:

On 6/30/20 12:37 PM, Steven Schveighoffer wrote:

[...]

I take it back, I didn't realize this wasn't something that happened
with dynamic arrays:

int[] dyn = [1, 2, 3];

dyn = 5; // error
dyn[] = 5; // ok, brackets required

I would say that's a decent precedent to deprecate and remove that
functionality.

[...]

Could you add this info to the bugzilla issue as additional evidence
that this (mis)feature should be removed?

https://issues.dlang.org/show_bug.cgi?id=15932


That's a different issue. In the case of:

staticarr = 5;

There is no issue with lifetime management or memory safety. It's 
possible that fixing 15932 would fix this issue too, but it's possible 
that's not true (we are assuming it's the implicit cast that is causing 
this issue, but it might be separately implemented).


-Steve


Re: Why is this allowed

2020-06-30 Thread H. S. Teoh via Digitalmars-d-learn
On Tue, Jun 30, 2020 at 02:06:13PM -0400, Steven Schveighoffer via 
Digitalmars-d-learn wrote:
> On 6/30/20 12:37 PM, Steven Schveighoffer wrote:
[...]
> I take it back, I didn't realize this wasn't something that happened
> with dynamic arrays:
> 
> int[] dyn = [1, 2, 3];
> 
> dyn = 5; // error
> dyn[] = 5; // ok, brackets required
> 
> I would say that's a decent precedent to deprecate and remove that
> functionality.
[...]

Could you add this info to the bugzilla issue as additional evidence
that this (mis)feature should be removed?

https://issues.dlang.org/show_bug.cgi?id=15932


T

-- 
"640K ought to be enough" -- Bill G. (allegedly), 1984. "The Internet is not a 
primary goal for PC usage" -- Bill G., 1995. "Linux has no impact on 
Microsoft's strategy" -- Bill G., 1999.


Re: Why is this allowed

2020-06-30 Thread Steven Schveighoffer via Digitalmars-d-learn

On 6/30/20 12:37 PM, Steven Schveighoffer wrote:

On 6/30/20 12:22 PM, JN wrote:
Spent some time debugging because I didn't notice it at first, 
essentially something like this:


int[3] foo = [1, 2, 3];
foo = 5;
writeln(foo);   // 5, 5, 5

Why does such code compile? I don't think this should be permitted, 
because it's easy to make a mistake (when you wanted foo[index] but 
forgot the []). If someone wants to assign a value to every element 
they could do foo[] = 5; instead which is explicit.


That's a feature. I don't think it's going away. The problem of 
accidental assignment is probably not very common.


I take it back, I didn't realize this wasn't something that happened 
with dynamic arrays:


int[] dyn = [1, 2, 3];

dyn = 5; // error
dyn[] = 5; // ok, brackets required

I would say that's a decent precedent to deprecate and remove that 
functionality.


-Steve


Re: Why is this allowed

2020-06-30 Thread H. S. Teoh via Digitalmars-d-learn
On Tue, Jun 30, 2020 at 04:50:07PM +, Adam D. Ruppe via Digitalmars-d-learn 
wrote:
> On Tuesday, 30 June 2020 at 16:41:50 UTC, JN wrote:
> > I like my code to be explicit, even at a cost of some extra typing,
> > rather than get bitten by some unexpected implicit behavior.
> 
> I agree, I think ALL implicit slicing of static arrays are problematic
> and should be removed. If you want to set it all or slice it for any
> other reason, just put on the [].

We've known this for at least 4 years, yet nothing has been done about
it. :-(

https://issues.dlang.org/show_bug.cgi?id=15932

The problem isn't just safety, which is partly addressed by dip1000, but
also mistakes of the kind the OP posted.  Basically, it's a misfeature
with many ill side-effects all in the questionable name of convenience.
It's time we got rid of it.


T

-- 
Truth, Sir, is a cow which will give [skeptics] no more milk, and so they are 
gone to milk the bull. -- Sam. Johnson


Re: Why is this allowed

2020-06-30 Thread Adam D. Ruppe via Digitalmars-d-learn

On Tuesday, 30 June 2020 at 16:41:50 UTC, JN wrote:
I like my code to be explicit, even at a cost of some extra 
typing, rather than get bitten by some unexpected implicit 
behavior.


I agree, I think ALL implicit slicing of static arrays are 
problematic and should be removed. If you want to set it all or 
slice it for any other reason, just put on the [].


Re: Why is this allowed

2020-06-30 Thread JN via Digitalmars-d-learn
On Tuesday, 30 June 2020 at 16:37:12 UTC, Steven Schveighoffer 
wrote:
That's a feature. I don't think it's going away. The problem of 
accidental assignment is probably not very common.


-Steve


What is the benefit of this feature? I feel like D has quite a 
few of such "features". I like my code to be explicit, even at a 
cost of some extra typing, rather than get bitten by some 
unexpected implicit behavior.


Re: Why is this allowed

2020-06-30 Thread Steven Schveighoffer via Digitalmars-d-learn

On 6/30/20 12:22 PM, JN wrote:
Spent some time debugging because I didn't notice it at first, 
essentially something like this:


int[3] foo = [1, 2, 3];
foo = 5;
writeln(foo);   // 5, 5, 5

Why does such code compile? I don't think this should be permitted, 
because it's easy to make a mistake (when you wanted foo[index] but 
forgot the []). If someone wants to assign a value to every element they 
could do foo[] = 5; instead which is explicit.


That's a feature. I don't think it's going away. The problem of 
accidental assignment is probably not very common.


-Steve


Re: Why is this allowed

2020-06-30 Thread H. S. Teoh via Digitalmars-d-learn
On Tue, Jun 30, 2020 at 04:22:57PM +, JN via Digitalmars-d-learn wrote:
> Spent some time debugging because I didn't notice it at first,
> essentially something like this:
> 
> int[3] foo = [1, 2, 3];
> foo = 5;
> writeln(foo);   // 5, 5, 5
> 
> Why does such code compile? I don't think this should be permitted,
> because it's easy to make a mistake (when you wanted foo[index] but
> forgot the []).  If someone wants to assign a value to every element
> they could do foo[] = 5; instead which is explicit.

File a bug?

I suspect that one potential reason is that nasty misfeature of static
arrays implicitly converting to a slice of itself, so `foo = 5;` is in
some sense being translated as `foo[] = 5;`.

(And on that note, this implicit static -> dynamic array conversion is
seriously a nasty misfeature that ought to be killed with fire. It leads
to bugs like this:

struct Database {
int[] data;
void set(int[] _data) {
data = _data;
}
}
void myFunc(ref Database db) {
int[3] x;
db.set(x);  // oops
}
)


T

-- 
Once the bikeshed is up for painting, the rainbow won't suffice. -- Andrei 
Alexandrescu


Why is this allowed

2020-06-30 Thread JN via Digitalmars-d-learn
Spent some time debugging because I didn't notice it at first, 
essentially something like this:


int[3] foo = [1, 2, 3];
foo = 5;
writeln(foo);   // 5, 5, 5

Why does such code compile? I don't think this should be 
permitted, because it's easy to make a mistake (when you wanted 
foo[index] but forgot the []). If someone wants to assign a value 
to every element they could do foo[] = 5; instead which is 
explicit.


Re: Why is this allowed? Inheritance variable shadowing

2019-08-13 Thread a11e99z via Digitalmars-d-learn

On Tuesday, 13 August 2019 at 06:39:24 UTC, a11e99z wrote:

On Tuesday, 13 August 2019 at 05:57:23 UTC, Mike Parker wrote:

On Tuesday, 13 August 2019 at 04:40:53 UTC, Chris Katko wrote:


OT:
and again how to easy to google info about error/warning just 
with one word "CS0108"


D can use attrs for such things.

OT:
1) need to add compiler attrs that speaks with compiler - they 
are change code generation, compiler passes or something. like 
pragmas do.
2) need to separate all attrs in a separate construction like C# 
do

[inline, nextOne, returns: someAttrToReturnValue]
int meth( [argAttrCanBeToo] int x ) { }

or

[hide]
public int x = 2;
cuz its visually separated and easy to skip it with eye when u 
reading/reviewing code.


it can be mess for now:

pure @trusted int meth( int x ) @nogc nothrow { return 5; }
NB all of this attrs is compiler attrs not user, they changes 
compilation.

- no possibility add attr to args or returns
- some attrs with "@" and some don't
- its hard to read when D adds 2-3 attrs more for next 5-10 years

my wishlist of new compilation attrs:
- [hiding] for subj
- [offset(N)] for explicit struct alignment without mess with 
unions/align(4) cuz sometimes I know exactly offset for field and 
I can point it with no side effects calcs adding pads, unions and 
etc
- [inline(bool)] instead of pragma( inline, true ) that looks 
like compiler attr but another way

- [deprecated(text)]
- [nodiscard] cannot discard return value
- etc


Re: Why is this allowed? Inheritance variable shadowing

2019-08-13 Thread a11e99z via Digitalmars-d-learn

On Tuesday, 13 August 2019 at 05:57:23 UTC, Mike Parker wrote:

On Tuesday, 13 August 2019 at 04:40:53 UTC, Chris Katko wrote:


I don't know if I'd call that shadowing. This is how it works 
in Java, too. There's no such thing as a vtable for member 
variables -- each class gets its own set and they don't 
conflict. The only time it could be really be called shadowing 
is when the base class member is protected, as then it's 
accessible in the subclass scope.


Also, it's not the same thing as overriding. Overriding means 
that when you call base.foo(), you get sub.foo()'s 
implementation. But when you access base.var, you get base.var 
and not sub.var.


I would find it extremely annoying if it worked the way you're 
expecting it to.


C# results:
main.cs(8,14): warning CS0108: `B.x' hides inherited member 
`A.x'. Use the new keyword if hiding was intended
main.cs(4,14): (Location of the symbol related to previous 
warning)

Compilation succeeded - 1 warning(s)
mono main.exe
1
2


with "new" keyword that is used to hide a method, property, 
indexer, or event of the base class into the derived class.

class B : A {
  public new int x = 2;
  // I tell "I want hiding. Ensure "x exists in parent"" 
explicitly

  // almost same meaning as "override"
}


OT:
and again how to easy to google info about error/warning just 
with one word "CS0108"


Re: Why is this allowed? Inheritance variable shadowing

2019-08-13 Thread Mike Parker via Digitalmars-d-learn

On Tuesday, 13 August 2019 at 04:40:53 UTC, Chris Katko wrote:

You can drop this straight into run.dlang.io:

import std.stdio;

class base{ float x=1;}
class child : base {float x=2;} //shadows base variable!

void main()
{

base []array;
child c = new child;
array ~= c;

writeln(c.x); //=2
writeln(array[0].x); //=1  //uses BASE's interface, yes,
//but why does the CHILD instance one exist at all?
}

It appears to be legal C++ as well but I can't imagine a 
situation where you'd want to allow the HUGE risk of 
shadowing/aliasing variables in an child class. Why is 
inheritance shadowing allowed? Especially when in D you have to 
explicitly "override" existing _methods_ but not 
fields/variables?


To quote a Stack Overflow comment on C++ having this "It's not 
a compile error, but it's certainly a design one." Is this 
allowed just because "C++ does it" or because it has some sort 
of real world use that justifies the risk?


Personally, I'd love a compile-time warning that I could turn 
on that flags this situation.


Thanks for your help,
--Chris


I don't know if I'd call that shadowing. This is how it works in 
Java, too. There's no such thing as a vtable for member variables 
-- each class gets its own set and they don't conflict. The only 
time it could be really be called shadowing is when the base 
class member is protected, as then it's accessible in the 
subclass scope.


Also, it's not the same thing as overriding. Overriding means 
that when you call base.foo(), you get sub.foo()'s 
implementation. But when you access base.var, you get base.var 
and not sub.var.


I would find it extremely annoying if it worked the way you're 
expecting it to.


Why is this allowed? Inheritance variable shadowing

2019-08-12 Thread Chris Katko via Digitalmars-d-learn

You can drop this straight into run.dlang.io:

import std.stdio;

class base{ float x=1;}
class child : base {float x=2;} //shadows base variable!

void main()
{

base []array;
child c = new child;
array ~= c;

writeln(c.x); //=2
writeln(array[0].x); //=1  //uses BASE's interface, yes,
//but why does the CHILD instance one exist at all?
}

It appears to be legal C++ as well but I can't imagine a 
situation where you'd want to allow the HUGE risk of 
shadowing/aliasing variables in an child class. Why is 
inheritance shadowing allowed? Especially when in D you have to 
explicitly "override" existing _methods_ but not fields/variables?


To quote a Stack Overflow comment on C++ having this "It's not a 
compile error, but it's certainly a design one." Is this allowed 
just because "C++ does it" or because it has some sort of real 
world use that justifies the risk?


Personally, I'd love a compile-time warning that I could turn on 
that flags this situation.


Thanks for your help,
--Chris