www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - implicit casting between arrays

reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
running

class Foo {
  int a,b,c;
}
int main() {
  Foo[] x = new Foo[1];
  Object[] y = x;
  y[0] = new Object;
  printf("%d %d %d\n", x[0].a, x[0].b, x[0].c);
  return 0;
}

prints
0 0 8851408

I think Foo[] shouldn't be implicitly castable to Object[] (and perhaps not 
even explicitly castable). 
Apr 16 2005
parent reply Manfred Nowak <svv1999 hotmail.com> writes:
"Ben Hinkle" <ben.hinkle gmail.com> wrote:

[...]
 I think Foo[] shouldn't be implicitly castable to Object[] (and
 perhaps not even explicitly castable). 

I see that you know, that according to the specs this behaviour currently is not a bug (except that the ints are not initialized). If this implicit casting will be declared as an error, then I see at least an asymmetry to the implicit casting that can be made with unions <code> import std.stdio; void main() { union U{ int a; Object p; }; U u; u.p= new Object; writefln(u.a); } </code> which also prints out a nonnull value. Because I see reasons to allow implicit castings with unions I would rather add to the docs that the basetype to which array handles can be implicitely casted has to be treated as though it _is_ a union of its derived types. -manfred
Apr 16 2005
parent reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
"Manfred Nowak" <svv1999 hotmail.com> wrote in message 
news:d3t0e9$14rs$1 digitaldaemon.com...
 "Ben Hinkle" <ben.hinkle gmail.com> wrote:

 [...]
 I think Foo[] shouldn't be implicitly castable to Object[] (and
 perhaps not even explicitly castable).

I see that you know, that according to the specs this behaviour currently is not a bug (except that the ints are not initialized).

correct - maybe I shouldn't have posted this to the D.bugs list but it seems like a pretty obvious bug IMO.
 If this implicit casting will be declared as an error, then I see
 at least an asymmetry to the implicit casting that can be made with
 unions

 <code>
 import std.stdio;
 void main() {
  union U{
    int a;
    Object p;
  };

  U u;
  u.p= new Object;
  writefln(u.a);
 }
 </code>

 which also prints out a nonnull value.

I don't see where there are any implicit casts in that example. With unions the definition is that is reuses the same storage locations for different types without knowing which is "active". So there isn't a cast but a reuse of storage. The two are different in that a cast takes a value and makes a new value while storage reuses takes some bits and interprets them in a new value. Besides, D unions are treated like C unions, and in C it is illegal to do short** x; int** y = x; and that's essentially what implicitly casting arrays of object references is doing.
Apr 17 2005
parent reply Manfred Nowak <svv1999 hotmail.com> writes:
"Ben Hinkle" <ben.hinkle gmail.com> wrote:

[...]
 The two are different in that a cast takes a value and makes a
 new value while storage reuses takes some bits and interprets
 them in a new value. 

Is that really true? <code> uint u= uint.max; int i= u; </code> Now what should that "new value" be that you proposed? I think that sometimes casts have to degrade to storage reuses (or interpretation changes), so that there is no clear line to distinguish between them.
 Besides, D unions are treated like C unions, and in C
 it is illegal to do
 short** x;
 int** y = x;
 and that's essentially what implicitly casting arrays of object
 references is doing.

Agreed that it is currently this way. But again I see an asymmetry: why shouldn't derived types be (implicitely) castable, if their base types are (implicitely) castable to _each_ other and the structure of the derivation is identical? And after stating this I agree with you, that at least the implicitely casting this thread started with should be treated as an error and the specs changed, because the base type `Object' is _not_ castable into its dericed type. -manfred
Apr 17 2005
parent "Ben Hinkle" <ben.hinkle gmail.com> writes:
"Manfred Nowak" <svv1999 hotmail.com> wrote in message 
news:d3ue1p$29p8$1 digitaldaemon.com...
 "Ben Hinkle" <ben.hinkle gmail.com> wrote:

 [...]
 The two are different in that a cast takes a value and makes a
 new value while storage reuses takes some bits and interprets
 them in a new value.

Is that really true? <code> uint u= uint.max; int i= u; </code> Now what should that "new value" be that you proposed? I think that sometimes casts have to degrade to storage reuses (or interpretation changes), so that there is no clear line to distinguish between them.

Are we really going to argue about casting? sigh. I guess so since you believe that unions involve casting - though I hope I'm misunderstanding you. Casting between types tries as best it can to preserve the value when it creates the new value. For example casting from 1.0 as a floating point number to 1 as an int doesn't take the bits in a double and interpret them as an int - it make a new value with a different bit pattern. In the case you give about a value out of range for the destination type C does indeed take the bit pattern in the source value (but not the storage location - there is a huge difference) and creates the new value with the same bit pattern. Casting pointers reinterprets the bits in a given storage location (or in the case of casting to void* it throws away any interpretation at all). Unions don't involve any casting but do involve sharing storage locations which is why people sometimes get it confused with casting, I guess. Anyhow, for a reference I dusted off K+R C second ed and I recommend sections A8.3, A7.5 and A6 for more info.
 Besides, D unions are treated like C unions, and in C
 it is illegal to do
 short** x;
 int** y = x;
 and that's essentially what implicitly casting arrays of object
 references is doing.

Agreed that it is currently this way. But again I see an asymmetry: why shouldn't derived types be (implicitely) castable, if their base types are (implicitely) castable to _each_ other and the structure of the derivation is identical? And after stating this I agree with you, that at least the implicitely casting this thread started with should be treated as an error and the specs changed, because the base type `Object' is _not_ castable into its dericed type. -manfred

Try compiling the following C++ program: class A{}; class B:A{}; int main() { A**x; B**y; x = y; return 0; } It will fail in the implicit cast just as the D program class A{} class B:A{} int main() { A*x; B*y; x = y; return 0; } will fail. I argue class A{} class B:A{} int main() { A[] x; B[] y; x = y; return 0; } should fail. The only argument I can see for treating it differently is that maybe arrays in general should be COW instead of just strings.
Apr 17 2005