March 26, 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1654





------- Comment #10 from htvennik@zonnet.nl  2008-03-26 15:11 -------
The following is of course wrong in my previous comment:
> 
> invariant(S) s = new S(4);   // valid
> 

It should be: invariant(S)* s = new S(4);   // valid


-- 

March 26, 2008
On 26/03/2008, d-bugmail@puremagic.com <d-bugmail@puremagic.com> wrote:
>  Of course a NewExpression would also return a unique reference:

That doesn't follow. Counterexample follows:

    char[1000] globalBuffer;

    class S
    {
        char[] buffer;

        this(int n)
        {
            buffer = globalBuffer[0..n];
        }
    }

   invariant(S) s = new S(4); // not valid

This is harder than you think! :-)
March 28, 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1654





------- Comment #12 from htvennik@zonnet.nl  2008-03-28 14:07 -------
Yes, you are right here... The rule doesn't apply to NewExpressions if they produce a class instance that may contain a pointer to mutable data. So best would be to not apply it to class instances at all (to keep the rule simple).

But it still holds for concatenating arrays of value types and for NewExpressions that produce a struct instance.


-- 

May 01, 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1654





------- Comment #13 from brunodomedeiros+bugz@gmail.com  2008-05-01 12:34 -------
(In reply to comment #2)
> However, this could be alleviated if we had the following rule:
> if X is a data type, and v1 is of the type invariant(X) and v2 is of the type
> X, it is allowed to copy v1 to v2 provided that the X data type is not a
> pointer or a reference or contains any pointers or references.
> I think this rule is sound and really should be an enhancement on its own, but
> it provides a way that my solution could work.  With this rule, my example
> passes the rule since copying an invariant(char) to a char is allowed, but your
> example fails because copying an invariant(int[]) to a int[] fails.
> What do you think?

"copying an invariant(int[]) to a int[]" fails indeed, but copying
invariant(int[]) to an invariant(int)[] would work as well.
So basicly what we are looking into here is tailconst. The concatenation of a
const(T)[] with another const(T)[] conceptually returns a type that is:

  tailconst(T)[]

and similarly for invariant/tailinvariant. This is because the "head-value" of T is copied, so it can be mutable. So these semantics are safe:

int[] ~ int[]                           --> returns int[]
const(int)[] ~ const(int)[]             --> returns int[]
int[][] ~ int[][]                       --> returns int[][]
const(int[])[] ~ const(int[])[]         --> returns const(int)[][]
const(int)[][] ~ const(int)[][]         --> returns const(int)[][]

How about this though? :

const(Foo)[] ~ const(Foo)[]             --> returns ???

Unfortunately there is no way in D to express tailconst for classes (and structs), so the last example would have to use normal const(T) instead of tailconst(T). I'm not sure what the implications of this special, and inconsistent case are tough, it could break generic code or something. Which does not mean these semantics would not be worthwhile.


-- 

May 01, 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1654





------- Comment #14 from schveiguy@yahoo.com  2008-05-01 13:48 -------
(In reply to comment #13)
> "copying an invariant(int[]) to a int[]" fails indeed, but copying
> invariant(int[]) to an invariant(int)[] would work as well.
> So basicly what we are looking into here is tailconst. The concatenation of a
> const(T)[] with another const(T)[] conceptually returns a type that is:
> 
>   tailconst(T)[]

Not exactly.  The enhancement request has kind of mutated, due to the rule that I stipulated (which I think was subsequently added to D 2).

What I think it should be is

const(T)[] ~ const(T)[] should return a type that is T[] if const(T) implicitly
casts to T under the rule.  If T does not implicitly cast, it should return
const(T)[].

The whole idea behind this is that ~ is always generating new data.  Why should the result always be based on the input types?  At the very least, The pieces of the new array that are unique should be unique, and implicitly cast to mutable.

This problem is not an easy one to solve, I realize, but it is solvable.

> 
> and similarly for invariant/tailinvariant. This is because the "head-value" of T is copied, so it can be mutable. So these semantics are safe:
> 
> int[] ~ int[]                           --> returns int[]
> const(int)[] ~ const(int)[]             --> returns int[]
> int[][] ~ int[][]                       --> returns int[][]
> const(int[])[] ~ const(int[])[]         --> returns const(int)[][]
> const(int)[][] ~ const(int)[][]         --> returns const(int)[][]
> 
> How about this though? :
> 
> const(Foo)[] ~ const(Foo)[]             --> returns ???

If Foo is a struct with no pointers, then it returns Foo[].

If Foo is a class, a pointer, or a struct with pointers, then it returns
const(Foo)[].

> Unfortunately there is no way in D to express tailconst for classes (and structs), so the last example would have to use normal const(T) instead of tailconst(T). I'm not sure what the implications of this special, and inconsistent case are tough, it could break generic code or something. Which does not mean these semantics would not be worthwhile.

Yes these cases would have to be handled delicately.  There are other things to consider.

For example, if Foo is an alias to int *, then if you returned a tailconst version of Foo what is that?  It would really be const(int)*, but how is that expressed in terms of Foo?  What if Foo is a typedef to int *?

There are really two problems that need to be solved to allow this enhancement.
 The first I believe is already solved, and that is the ability to implicitly
cast to/from const/invariant/mutable if the type contains no pointers.  The
second is to allow the return type of a function to depend on how it is used
and/or called.  I'm not talking about overloading functions based on return
type, because that isn't enough in itself.  Why should I have to write multiple
functions that act the same way, just so the return type is different?  I keep
thinking that a 'unique' concept needs to be added before this whole solution
is possible.

Anyways, this issue really doesn't look like it will be solved in the near future, without good answers for all the sub-issues involved.


-- 

May 28, 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1654





------- Comment #15 from brunodomedeiros+bugz@gmail.com  2008-05-28 16:46 -------
(In reply to comment #14)
> (In reply to comment #13)
> > "copying an invariant(int[]) to a int[]" fails indeed, but copying
> > invariant(int[]) to an invariant(int)[] would work as well.
> > So basicly what we are looking into here is tailconst. The concatenation of a
> > const(T)[] with another const(T)[] conceptually returns a type that is:
> > 
> >   tailconst(T)[]
> Not exactly.  The enhancement request has kind of mutated, due to the rule that
> I stipulated (which I think was subsequently added to D 2).
> What I think it should be is
> const(T)[] ~ const(T)[] should return a type that is T[] if const(T) implicitly
> casts to T under the rule.  If T does not implicitly cast, it should return
> const(T)[].

I understand your rule, but it is not the most permissive safe-behavior. What I was describing was the most permissive safe-behavior possible.

For example, with your rule:
  const(int[])[] ~ const(int[])[]
would return const(int[])[] .
But it is safe to return const(int)[][] , which is more permissive.


-- 

May 28, 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1654





------- Comment #16 from schveiguy@yahoo.com  2008-05-28 17:36 -------
Yes, you are correct.  The second form is more permissive.  I didn't see that originally.

Concatenating arrays of arrays and arrays of pointers are special cases because a tail-const version exists.

I think as long as the implicit casting works, so:

const(int[])[] a;
const(int)[][] b = a ~ a;
const(int[])[] c = a ~ a;

all works, then it shouldn't be a problem.  It probably will not break generic code because if you have a generic function:

f(T)(const(T)[] input) {...}

How does one construct a 'tailconst' verison of T given just T?  I think that was what I was saying earlier (about a typedef).  You could do an is-expression to get at the underlying type, but then that is specialized for arrays, and it is no more convoluted than the current state of affairs.

If you know T is always going to be an array, you can do:

f(T)(const(T[])[] input) {...}

and you can universally deal with all types of arrays.

So now, I think the rules are:

If concatenating two arrays together, of type T[]:

If T is of the form const(U[]), then one can assign the result to a type of
const(U)[][]

If T is of the form const(U*), then one can assign the result to a type of
const(U)*[]

If T is of the form const(U), and const(U) implicitly casts to U, then one can
assign the result to a type of U[].

For the above rules, if T is invariant(U) the same style rules apply.

In all cases, one can assign to the result type of T[].

If concatenating two arrays together where the element type of the array varies
only in constancy, and const(T) and invariant(T) implicitly cast to/from T,
then the result can be assigned to invariant(T)[], const(T)[] or T[].

Did I miss anything?  Boy this is getting more complex to explain :)


-- 

January 05, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=1654


yebblies <yebblies@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bearophile_hugs@eml.cc


--- Comment #17 from yebblies <yebblies@gmail.com> 2013-01-05 18:32:00 EST ---
*** Issue 9251 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: -------
April 26, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=1654


yebblies <yebblies@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |timon.gehr@gmx.ch


--- Comment #18 from yebblies <yebblies@gmail.com> 2013-04-26 16:37:07 EST ---
*** Issue 7311 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: -------
April 27, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=1654



--- Comment #19 from Andrei Alexandrescu <andrei@erdani.com> 2013-04-27 04:19:53 PDT ---
Wow this is one old one. Whatever the solution to this is, it shouldn't make operator ~ magic, i.e. the behavior should be implementable as a regular function call.

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