Thread overview
[Issue 7318] New: Cannot concatenate arrays of super- and subtype
Jan 19, 2012
timon.gehr@gmx.ch
Jan 19, 2012
Walter Bright
Jan 19, 2012
timon.gehr@gmx.ch
Jan 20, 2012
timon.gehr@gmx.ch
January 19, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7318

           Summary: Cannot concatenate arrays of super- and subtype
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: regression
          Priority: P2
         Component: DMD
        AssignedTo: nobody@puremagic.com
        ReportedBy: timon.gehr@gmx.ch


--- Comment #0 from timon.gehr@gmx.ch 2012-01-19 01:57:30 PST ---
The recent fixes regarding array covariance had some side-effects:

void main(){
    auto a = [new Object()];
    auto b = [new Exception("")];
    auto y = a~b; // error
}

This code should still work, even though Exception[] does not implicitly convert to Object[] anymore. (the code works if a is declared const)

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
January 19, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7318


Walter Bright <bugzilla@digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
                 CC|                            |bugzilla@digitalmars.com
         Resolution|                            |INVALID


--- Comment #1 from Walter Bright <bugzilla@digitalmars.com> 2012-01-19 02:19:55 PST ---
To make it work would require an implicit conversion, and that implicit conversion is not valid.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
January 19, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7318


timon.gehr@gmx.ch changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |REOPENED
         Resolution|INVALID                     |


--- Comment #2 from timon.gehr@gmx.ch 2012-01-19 02:36:35 PST ---
It is valid. Exception implicitly converts to Object. Since the resulting array from the concatenation is unique, there is no chance mutable aliasing occurs (which is the only reason covariant arrays are unsound in general).

To further back up my point, this compiles, and it is not a bug:

void main(){
    auto a = [new Object()];
    auto b = [new Exception("")];
    a~=b;
}

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
January 19, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7318


Andrei Alexandrescu <andrei@metalanguage.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |andrei@metalanguage.com
           Severity|regression                  |enhancement


--- Comment #3 from Andrei Alexandrescu <andrei@metalanguage.com> 2012-01-19 12:01:56 PST ---
More general: a ~= b for arrays is valid if element type of b implicitly converts to element type of a.

This is an addition to the language. A good one, but a net addition. It used to work because of a related bug. Let's keep this open for now and think more about it.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
January 19, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7318


Steven Schveighoffer <schveiguy@yahoo.com> changed:

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


--- Comment #4 from Steven Schveighoffer <schveiguy@yahoo.com> 2012-01-19 15:05:30 PST ---
(In reply to comment #2)
> To further back up my point, this compiles, and it is not a bug:
> 
> void main(){
>     auto a = [new Object()];
>     auto b = [new Exception("")];
>     a~=b;
> }

It only is not a bug because of the special case of arrays.  That is, even though the array function takes two mutable arguments, the compiler can deduce that neither array will be molested (same for concatenation).

The same is not true for normal functions, you could not write the append function in user code that accepted a derived array type without applying const/inout to the second argument.

I agree it's not a bug, but is an enhancement.  It would also be a good brainstorming session to figure out how to employ the same assumptions on normal functions.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
January 20, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7318



--- Comment #5 from timon.gehr@gmx.ch 2012-01-20 07:23:55 PST ---
(In reply to comment #4)
> (In reply to comment #2)
> > To further back up my point, this compiles, and it is not a bug:
> > 
> > void main(){
> >     auto a = [new Object()];
> >     auto b = [new Exception("")];
> >     a~=b;
> > }
> 
> It only is not a bug because of the special case of arrays.  That is, even though the array function takes two mutable arguments, the compiler can deduce that neither array will be molested (same for concatenation).
> 
> The same is not true for normal functions, you could not write the append function in user code that accepted a derived array type without applying const/inout to the second argument.

I could use a template to do the job:

ref A[] append(A,B)(ref A[] x, B[] y) if(is(B:A)) {
    foreach(e; y){
        x.length++;
        x[$-1] = e;
    }
    return x;
}

(it is more general than built-in append, but that could be fixed with a better
constraint)

> 
> I agree it's not a bug, but is an enhancement.  It would also be a good brainstorming session to figure out how to employ the same assumptions on normal functions.

Actually it is quite simple. If final means head-const, then final(T)[] is covariant. The second argument to append is conceptually final(T)[] as are both arguments to concat. With templates, those semantics can be emulated in user code, therefore the language can be fixed consistently without introducing another qualifier.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
January 20, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7318



--- Comment #6 from Andrei Alexandrescu <andrei@metalanguage.com> 2012-01-20 07:43:29 PST ---
> I could use a template to do the job:
> 
> ref A[] append(A,B)(ref A[] x, B[] y) if(is(B:A)) {
>     foreach(e; y){
>         x.length++;
>         x[$-1] = e;
>     }
>     return x;
> }
> 
> (it is more general than built-in append, but that could be fixed with a better
> constraint)

This suggests that the compiler should simply translate e1 ~= e2 into .object.append(e1, e2) and let druntime take care of the rest. One up for moving decisions from the compiler to the runtime.

In case of compile-time operation, the compiler should continue doing what it now does.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
January 20, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7318



--- Comment #7 from Steven Schveighoffer <schveiguy@yahoo.com> 2012-01-20 07:50:06 PST ---
(In reply to comment #6)
> > I could use a template to do the job:
> > 
> > ref A[] append(A,B)(ref A[] x, B[] y) if(is(B:A)) {
> >     foreach(e; y){
> >         x.length++;
> >         x[$-1] = e;
> >     }
> >     return x;
> > }
> > 
> > (it is more general than built-in append, but that could be fixed with a better
> > constraint)
> 
> This suggests that the compiler should simply translate e1 ~= e2 into .object.append(e1, e2) and let druntime take care of the rest. One up for moving decisions from the compiler to the runtime.

This would also solve the problem, but would possibly generate unnecessary template bloat.  However, inlining should take care of that problem.

I'm all for the compiler translating things into expressions that can be hooked instead of functions that can be hooked.  It makes things much more upgradable/flexible.

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