www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 5498] New: array of elements of subtypes of a common supertype

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5498

           Summary: array of elements of subtypes of a common supertype
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: normal
          Priority: P2
         Component: DMD
        AssignedTo: nobody puremagic.com
        ReportedBy: denis.spir gmail.com


--- Comment #0 from Denis Derman <denis.spir gmail.com> 2011-01-28 06:59:48 PST
---
Hello,

Seems there is no way to create an array of elements which types are subtypes
of a common supertype:

void test0 () {
    auto t1 = new T1();
    auto t2 = new T2();
    T0[] array = [t1, t2];
}
==>
Error: cannot implicitly convert expression (t1) of type __trials__.T0 to
__trials__.T2
Error: cannot implicitly convert expression ([(__error),t2]) of type T2[] to
T0[]

The array value is obviously correct. But there is here no common compatible
type between T1 & T2 that D could directly choose; instead, they have a common
super-type, which is the one intended as array element type.
D logically does not take our specification of the wished common type, in the
target part of the assignment, into account; since the source array must in any
case first exist at all. And it does not try to guess a common supertype by
climbing up the type hierarchy tree. This would be naughty-bug-prone since D
could find a common type which is not the intended one, precisely in case of
programmer error. And anyway Object would always be convenient, while this is
certainly not the programmer intention in the general case.
The core issue is that the language must first create a valid array value,
before any attempt to convert to any explicitely specified type (if ever this
feature was implemented). For this reason, cast or to! applied on the array
cannot help neither; the original array must first initially be correct
according to D rules for literal:

    T0[] array = cast(T0[])[t1, t2];
==>
Same error.

A workaround is to cast one of the elements, instead of the array, to the
intended common type (*):

void test2 () {
    auto t1 = new T1();
    auto t2 = new T2();
    T0[] array1 = [cast(T0)t1, t2];     // ok
    T0[] array2 = [t1, cast(T0)t2];     // ok
}

But this trick raises a conceptual problem: what we mean is specifying the
array literal's common type; what is in fact written is a cast of an element.
Far to be obvious.

A library solution can be made via an "array-feeding" helper function; it uses
a variadic argument to avoid the user writing an array literal:

void feed (T) (ref T[] array, T[] elements...) {
    array ~= elements;
}
void test3 () {
    auto t1 = new T1();
    auto t2 = new T2();
    T0[] array;
    array.feed(t1, t2);    // means: array = [t1,t2];
    array.feed(t2, t1);    // means: array ~= [t2,t1];
    writeln(array);
}
==>
[arraydef.T1, arraydef.T2, arraydef.T2, arraydef.T1]

As shown, feed can also extend an existing array, replacing "~=" which fails
for the same cause as "=". (Reason why I called the func "feed", not "init".)
This is still a workaround, maybe a better one. Programmers need to know about
the issue and the provided solution, thus this should be mentionned in good
place in doc about arrays.

A true solution would require having a way to hint the compiler about the
intended type, in literal syntax itself --a hint taken into account by the
language before any initial array is created. Just like postfixes 'w' & 'd' for
chars and strings. The best I could think at is, by analogy, postfixing the
element type to the array literal:

    T0[] array = [t1, t2]T0;

Not very nice :-(


Denis


(*) to! cannot be used at all because we hit another, unrelated, bug; namely
one about non mutually exclusive template constraints:

    T0[] array1 = [to!(T0)(t1), t2];
==>
/usr/include/d/dmd/phobos/std/conv.d(99): Error: template std.conv.toImpl(T,S)
if (!implicitlyConverts!(S,T) && isSomeString!(T) && isInputRange!(Unqual!(S))
&& isSomeChar!(ElementType!(S))) toImpl(T,S) if (!implicitlyConverts!(S,T) &&
isSomeString!(T) && isInputRange!(Unqual!(S)) && isSomeChar!(ElementType!(S)))
matches more than one template declaration,
/usr/include/d/dmd/phobos/std/conv.d(559):toImpl(Target,Source) if
(implicitlyConverts!(Source,Target)) and
/usr/include/d/dmd/phobos/std/conv.d(626):toImpl(T,S) if (is(S : Object) &&
is(T : Object))

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jan 28 2011
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5498


Steven Schveighoffer <schveiguy yahoo.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |schveiguy yahoo.com


--- Comment #1 from Steven Schveighoffer <schveiguy yahoo.com> 2011-03-09
05:39:44 PST ---
I just noticed, your example lacks definition of T0, T1 and T2.

Should be:

class T0 {}
class T1 : T0 {}
class T2 : T0 {}

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 09 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5498


Steven Schveighoffer <schveiguy yahoo.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |wilfried.kirschenmann gmail
                   |                            |.com


--- Comment #2 from Steven Schveighoffer <schveiguy yahoo.com> 2011-03-09
05:41:07 PST ---
*** Issue 5723 has been marked as a duplicate of this issue. ***

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 09 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5498


yebblies <yebblies gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |pull, rejects-valid
                 CC|                            |yebblies gmail.com
            Version|D2                          |D1 & D2
         AssignedTo|nobody puremagic.com        |yebblies gmail.com
            Summary|array of elements of        |wrong common type deduction
                   |subtypes of a common        |for array of classes
                   |supertype                   |


--- Comment #3 from yebblies <yebblies gmail.com> 2012-02-02 16:47:47 EST ---
https://github.com/D-Programming-Language/dmd/pull/684

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Feb 01 2012
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5498


yebblies <yebblies gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jens.k.mueller gmx.de


--- Comment #4 from yebblies <yebblies gmail.com> 2012-07-07 21:23:26 EST ---
*** Issue 8353 has been marked as a duplicate of this issue. ***

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jul 07 2012