Thread overview
implicit casting between arrays
Apr 16, 2005
Ben Hinkle
Apr 17, 2005
Manfred Nowak
Apr 17, 2005
Ben Hinkle
Apr 17, 2005
Manfred Nowak
Apr 17, 2005
Ben Hinkle
April 16, 2005
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).


April 17, 2005
"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
April 17, 2005
"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.


April 17, 2005
"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
April 17, 2005
"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.