October 19, 2014
On Sunday, 19 October 2014 at 15:21:02 UTC, anonymous wrote:
>              version(none) _outer = data; /* "Error: mutable method
>                  [...].Array.opAssign is not callable using a
> const object" */

What do these comments containing Error messages mean? Doesn't this code compile?
October 19, 2014
On Sunday, 19 October 2014 at 18:58:50 UTC, Nordlöw wrote:
> On Sunday, 19 October 2014 at 15:21:02 UTC, anonymous wrote:
>>             version(none) _outer = data; /* "Error: mutable method
>>                 [...].Array.opAssign is not callable using a
>> const object" */
>
> What do these comments containing Error messages mean? Doesn't this code compile?

Yes, they don't compile. It's three slightly different versions
of initializing _outer.

The first one, `_outer = data;`, is the original one. It's
understandable that it doesn't work anymore with the workaround
in place.

I don't know why the second one, `_outer_[0] = data;`, doesn't
work. Maybe it triggers the same (or a related) postblit compiler
bug again. It's essentially the same as the third one, `_outer_ =
data;`, which happens to work.
October 19, 2014
On Sunday, 19 October 2014 at 19:13:33 UTC, anonymous wrote:
> Yes, they don't compile. It's three slightly different versions
> of initializing _outer.
>
> The first one, `_outer = data;`, is the original one. It's
> understandable that it doesn't work anymore with the workaround
> in place.
>
> I don't know why the second one, `_outer_[0] = data;`, doesn't
> work. Maybe it triggers the same (or a related) postblit compiler
> bug again. It's essentially the same as the third one, `_outer_ =
> data;`, which happens to work.

So there's currently no complete solution to this problem yet, then?
October 19, 2014
On Sunday, 19 October 2014 at 19:30:40 UTC, Nordlöw wrote:
> On Sunday, 19 October 2014 at 19:13:33 UTC, anonymous wrote:
>> Yes, they don't compile. It's three slightly different versions
>> of initializing _outer.
>>
>> The first one, `_outer = data;`, is the original one. It's
>> understandable that it doesn't work anymore with the workaround
>> in place.
>>
>> I don't know why the second one, `_outer_[0] = data;`, doesn't
>> work. Maybe it triggers the same (or a related) postblit compiler
>> bug again. It's essentially the same as the third one, `_outer_ =
>> data;`, which happens to work.
>
> So there's currently no complete solution to this problem yet, then?

The last variant works: `_outer_ = data;`.

And that one is enabled in my code, while the other two are
`version(none)`-ed away.
October 19, 2014
On Sunday, 19 October 2014 at 19:36:46 UTC, anonymous wrote:
> On Sunday, 19 October 2014 at 19:30:40 UTC, Nordlöw wrote:
>> On Sunday, 19 October 2014 at 19:13:33 UTC, anonymous wrote:
>>> Yes, they don't compile. It's three slightly different versions
>>> of initializing _outer.
>>>
>>> The first one, `_outer = data;`, is the original one. It's
>>> understandable that it doesn't work anymore with the workaround
>>> in place.
>>>
>>> I don't know why the second one, `_outer_[0] = data;`, doesn't
>>> work. Maybe it triggers the same (or a related) postblit compiler
>>> bug again. It's essentially the same as the third one, `_outer_ =
>>> data;`, which happens to work.
>>
>> So there's currently no complete solution to this problem yet, then?
>
> The last variant works: `_outer_ = data;`.
>
> And that one is enabled in my code, while the other two are
> `version(none)`-ed away.

Used your ideas here

https://github.com/nordlow/phobos/commit/be6b5f8c4d428a9708a52757a3f31aab6878d379

but unittests now fails as

array.d(234,13): Error: mutable method std.container.array.Array!int.Array.opAssign is not callable using a const object
../../std/algorithm.d(2364,9): Error: cannot modify const expression result
array.d(297,24): Error: template instance std.algorithm.move!(const(int)) error instantiating
array.d(465,5):        instantiated from here: Range!(const(Array!int))
array.d(877,5):        instantiated from here: Array!int
array.d(320,26): Error: cast(int)__dop1738.opIndex(this._a + i) is not an lvalue
array.d(346,30): Error: None of the overloads of 'opSliceAssign' are callable using a const object, candidates are:
array.d(533,10):        std.container.array.Array!int.Array.opSliceAssign(int value)
array.d(540,10):        std.container.array.Array!int.Array.opSliceAssign(int value, ulong i, ulong j)
array.d(352,38): Error: None of the overloads of 'opSliceAssign' are callable using a const object, candidates are:
array.d(533,10):        std.container.array.Array!int.Array.opSliceAssign(int value)
array.d(540,10):        std.container.array.Array!int.Array.opSliceAssign(int value, ulong i, ulong j)
array.d(325,32): Error: mutable method std.container.array.Array!int.Array.Range!(Array!int).Range.this is not callable using a const object
array.d(335,32): Error: mutable method std.container.array.Array!int.Array.Range!(Array!int).Range.this is not callable using a const object
array.d(469,5): Error: template instance std.container.array.Array!int.Array.Range!(Array!int) error instantiating
array.d(877,5):        instantiated from here: Array!int
../../std/typecons.d(3889,17): Error: template instance object.destroy!(Payload) error instantiating
array.d(169,26):        instantiated from here: RefCounted!(Payload, cast(RefCountedAutoInitialize)0)
array.d(877,5):        instantiated from here: Array!int
array.d(906,5): Error: static assert  (!true) is false

Comint exited abnormally with code 1 at Sun Oct 19 22:06:48
October 19, 2014
On Sunday, 19 October 2014 at 20:10:33 UTC, Nordlöw wrote:
> Used your ideas here
>
> https://github.com/nordlow/phobos/commit/be6b5f8c4d428a9708a52757a3f31aab6878d379
>
> but unittests now fails as
>
> array.d(234,13): Error: mutable method std.container.array.Array!int.Array.opAssign is not callable using a const object

You didn't make the change we just discussed.

Change line 234 from `_outer = data;` to `_outer_ = data;`.

You also need to guard much more with `static if (isMutable!A)`:
* everything that returns (non-const) T,
* everything that returns Range!A,
* everything that mutates elements (e.g. opSliceAssign).

And you can't do `return typeof(this)(...);` when the return type
is `Range!(const(A))`, because `typeof(this)` can be
`const(Range!A)` which is not the same. Spell the type out or use
`typeof(result)`.
October 19, 2014
On Sunday, 19 October 2014 at 20:39:18 UTC, anonymous wrote:
> Spell the type out or  use `typeof(result)`.

Should be `typeof(return)`.
October 19, 2014
On Sunday, 19 October 2014 at 15:21:02 UTC, anonymous wrote:
> ----
> struct RefCounted
> {
>      this(this) /* const doesn't help */ {}
>      ~this() /* const doesn't help */ {}
> }
> struct Array
> {
>      RefCounted _data;
> }
> void main() {const Array a; const copy = a;} /* works */
> struct RangeM {Array a;} /* works */
> struct RangeC {const Array a;} /* error */
> ----
>
> Looks like a compiler bug to me.

Has already been filed:
https://issues.dlang.org/show_bug.cgi?id=13629
October 19, 2014
On Sunday, 19 October 2014 at 20:39:18 UTC, anonymous wrote:
>> array.d(234,13): Error: mutable method std.container.array.Array!int.Array.opAssign is not callable using a const object
>
> You didn't make the change we just discussed.
>
> Change line 234 from `_outer = data;` to `_outer_ = data;`.
>
> You also need to guard much more with `static if (isMutable!A)`:
> * everything that returns (non-const) T,
> * everything that returns Range!A,
> * everything that mutates elements (e.g. opSliceAssign).
>
> And you can't do `return typeof(this)(...);` when the return type
> is `Range!(const(A))`, because `typeof(this)` can be
> `const(Range!A)` which is not the same. Spell the type out or use
> `typeof(result)`.

New response at

https://github.com/nordlow/phobos/commit/ce6b9e9ae600b7c28ecddd1e3af7b1516247fb33

now errors as

array.d(927,15): Error: None of the overloads of 'opSlice' are callable using a const object, candidates are:
array.d(472,25):        std.container.array.Array!int.Array.opSlice()
array.d(495,25):        std.container.array.Array!int.Array.opSlice(ulong i, ulong j)
October 20, 2014
On Sunday, 19 October 2014 at 22:19:05 UTC, Nordlöw wrote:
> https://github.com/nordlow/phobos/commit/ce6b9e9ae600b7c28ecddd1e3af7b1516247fb33
>
> now errors as
>
> array.d(927,15): Error: None of the overloads of 'opSlice' are callable using a const object, candidates are:
> array.d(472,25):        std.container.array.Array!int.Array.opSlice()
> array.d(495,25):        std.container.array.Array!int.Array.opSlice(ulong i, ulong j)

The error is because of this (lines 470 through 483):
----
     static if (isMutable!T)
     {
         Range!(Array!T) opSlice()
         {
             return typeof(return)(this, 0, length);
         }
     }
     else
     {
         Range!(const(Array!T)) opSlice() const
         {
             return typeof(return)(this, 0, length);
         }
     }
----

You're disabling the const version when T is mutable. Consider
const(Array!int): T is int is mutable, so there is no const
opSlice. But the Array itself is const, so the non-const version
can't be used. Do not disable the const versions of the methods.
Only ever disable the non-const ones.

Also, the opSlice we're looking at here is Array's, not
Array.Range's. You don't need to touch Array's methods at all.
Only Array.Range's non-const methods need special treatment,
because you need to catch the special case when the Range is
mutable, but the referenced Array is not.

And it's really `isMutableA!`, not `isMutable!T`. I guess you
went for that because `A` is only defined in Array.Range, not in
Array itself. But T's mutability isn't of interest.

For example, Array.Range.opSlice should look like this:
----
         static if (isMutable!A) /* !A, not !T */
         {
             Range!(A) opSlice() {/* ... */}
             Range!(A) opSlice(size_t i, size_t j) {/* ... */}
         }
         /* No `else`, the const versions should always be
available. */
         Range!(const(A)) opSlice() const {/* ... */}
         Range!(const(A)) opSlice(size_t i, size_t j) const {/*
... */}
----

Then there are still various methods of Array.Range left to be
`static if(isMutable!A)` guarded:
* move*
* opIndex
* opSlice*

By the way, since we're in D.learn, I'm assuming you want to do
this yourself. But if you'd like, I could make a pull request
with my suggestions to your branch.