July 29, 2018
On 7/28/18 6:09 PM, aliak wrote:
> On Friday, 27 July 2018 at 14:38:27 UTC, Steven Schveighoffer wrote:
>> On 7/27/18 9:29 AM, aliak wrote:
>>> Ok, thanks to Simen from another post [0], I just figured out what the correct constructor and factory method for a template wrapper should be:
>>>
>>> https://run.dlang.io/is/S4vHzL
>>>
>>> struct W(T) {
>>>      T val;
>>>      this(U : T, this This)(auto ref U val) {
>>>          this.val = val;
>>>      }
>>> }
>>>
>>> auto wrap(T)(auto ref T t) {
>>>      return W!T(t);
>>> }
>>>
>>> Seems to catch all cases!
>>
>> And instantiate a new template for all mutabilities. Whereas inout would only instantiate one (and disallows modification of val if not const or immutable).
>>
>> -Steve
> 
> If you change the ctor to be inout then you get (from the link above):
> 
> onlineapp.d(4): Error: cannot implicitly convert expression val of type onlineapp.C to inout(C)
> onlineapp.d(28): Error: template instance `onlineapp.W!(C).W.__ctor!(C)` error instantiating
> onlineapp.d(4): Error: cannot implicitly convert expression val of type S1 to inout(S1)
> onlineapp.d(44): Error: template instance `onlineapp.W!(S1).W.__ctor!(S1)` error instantiating
> onlineapp.d(4): Error: cannot implicitly convert expression val of type onlineapp.C to inout(C)
> onlineapp.d(9): Error: template instance `onlineapp.W!(C).W.__ctor!(C)` error instantiating
> onlineapp.d(52):        instantiated from here: wrap!(C)
> onlineapp.d(4): Error: cannot implicitly convert expression val of type const(C) to inout(const(C))
> onlineapp.d(9): Error: template instance `onlineapp.W!(const(C)).W.__ctor!(const(C))` error instantiating
> onlineapp.d(53):        instantiated from here: wrap!(const(C))
> 
> Am I applying inout incorrectly?

No, you need to apply it to wrap as well. I can't get run.dlang.io to work for posting a link, so here is my modified version:

struct W(T) {
    T val;
    this(U : T)(auto ref inout(U) val) inout {
        this.val = val;
    }
}

auto wrap(T)(auto ref inout(T) t) {
    return inout W!T(t);
}

class C {}
struct S0 {}
struct S1 { C c; }

void f_dprimitive() {
    int a = 3;
    const int b = 3;
    immutable int c = 3;
    const int d = a;
    immutable int e = a;

    auto sc = wrap(const(int)(3));      // note the modifications here
    auto si = wrap(immutable(int)(3));
}

void f_class() {
    W!C a = new C();
    const W!C b = new C();
    immutable W!C c = new immutable C();
    const W!C d = a;

    //immutable W!C e = a; // cannot implicitly convert mutable to immutable
}

void f_struct() {
    W!S0 a = S0();
    const W!S0 b = S0();
    immutable W!S0 c = S0();
    const W!S0 d = a;
    immutable W!S0 e = a;
}

void f_struct_with_indirection() {
    W!S1 a = S1();
    const W!S1 b = S1();
    immutable W!S1 c = immutable S1();
    const W!S1 d = a;
//    immutable W!S1 e = a; // cannot implicitly convert mutable to immutable
}

void f_wrapper() {
    auto a = wrap(new C);
    auto b = wrap(new const C);
    auto c = wrap(new immutable C);
    const W!C d = a;
//    immutable W!C e = a; // cannot implicitly convert mutable to immutable
}

void f_wrapper2() {
    Object ma = new C();
    Object ca = new const C();
    Object ia = new immutable C();

    auto a = wrap(cast(C)ma);
    auto b = wrap(cast(const C)ma);
    auto c = wrap(cast(immutable C)ma);
}

void main() {

}
July 29, 2018
On Sunday, 29 July 2018 at 12:45:48 UTC, Steven Schveighoffer wrote:
>> 
>> Am I applying inout incorrectly?
>
> No, you need to apply it to wrap as well. I can't get run.dlang.io to work for posting a link, so here is my modified version:
>

Ah bugger, right!

Ok so there's no way to make explicit instantiation involving immutable work in the face of an inout parameter? Seems rather inconsistent no?

https://issues.dlang.org/show_bug.cgi?id=19126

Thanks,
- Ali
July 31, 2018
On 7/29/18 1:46 PM, aliak wrote:
> On Sunday, 29 July 2018 at 12:45:48 UTC, Steven Schveighoffer wrote:
>>>
>>> Am I applying inout incorrectly?
>>
>> No, you need to apply it to wrap as well. I can't get run.dlang.io to work for posting a link, so here is my modified version:
>>
> 
> Ah bugger, right!
> 
> Ok so there's no way to make explicit instantiation involving immutable work in the face of an inout parameter? Seems rather inconsistent no?

It's not that there's no way, the issue is simply that you are explicitly instantiating incorrectly.

wrap!int(immutable(int)(3));

-Steve
July 31, 2018
On Tuesday, 31 July 2018 at 12:37:34 UTC, Steven Schveighoffer wrote:
> On 7/29/18 1:46 PM, aliak wrote:
>> On Sunday, 29 July 2018 at 12:45:48 UTC, Steven Schveighoffer wrote:
>>>>
>>>> Am I applying inout incorrectly?
>>>
>>> No, you need to apply it to wrap as well. I can't get run.dlang.io to work for posting a link, so here is my modified version:
>>>
>> 
>> Ah bugger, right!
>> 
>> Ok so there's no way to make explicit instantiation involving immutable work in the face of an inout parameter? Seems rather inconsistent no?
>
> It's not that there's no way, the issue is simply that you are explicitly instantiating incorrectly.
>
> wrap!int(immutable(int)(3));
>
> -Steve

Ok bear with me, but I'm really confused why "wrap!int(immutable(int)(3))" is "correct".

This all seems very inconsistent:

1. wrap!(int)(3); // ok
2. wrap!(const int)(3); // ok
3. wrap!(immutable int)(3); // nope
4. wrap!(int)(3); // ok
5. wrap!(const int)(const(int)(3)); // ok
6. wrap!(immutable int)(immutable(int)(3)); // ok!

So for 3, compiler sees the instantiation:

 inout(W!(immutable int)) wrap(immutable(int))

If I understood you correctly?

But then what does it see in number 6, which works fine? And why is 2 ok if 3 is not? And finally, why can't the compiler leave the inout there and then it doesn't need to complain about it?

Cheers,
- Ali
July 31, 2018
On 7/31/18 5:29 PM, aliak wrote:
> On Tuesday, 31 July 2018 at 12:37:34 UTC, Steven Schveighoffer wrote:
>> On 7/29/18 1:46 PM, aliak wrote:
>>> On Sunday, 29 July 2018 at 12:45:48 UTC, Steven Schveighoffer wrote:
>>>>>
>>>>> Am I applying inout incorrectly?
>>>>
>>>> No, you need to apply it to wrap as well. I can't get run.dlang.io to work for posting a link, so here is my modified version:
>>>>
>>>
>>> Ah bugger, right!
>>>
>>> Ok so there's no way to make explicit instantiation involving immutable work in the face of an inout parameter? Seems rather inconsistent no?
>>
>> It's not that there's no way, the issue is simply that you are explicitly instantiating incorrectly.
>>
>> wrap!int(immutable(int)(3));
>>
> 
> Ok bear with me, but I'm really confused why "wrap!int(immutable(int)(3))" is "correct".

Because inout is trying to combine all mutability modifiers into one. You want to specify the type, not the mutability, in the template parameter T.

Essentially, if this were a normal function that takes only ints, you would write it once for all mutabilities:

auto wrap(inout(int) x)

Which works for mutable, const, or immutable int.

> 
> This all seems very inconsistent:
> 
> 1. wrap!(int)(3); // ok
> 2. wrap!(const int)(3); // ok
> 3. wrap!(immutable int)(3); // nope
> 4. wrap!(int)(3); // ok
> 5. wrap!(const int)(const(int)(3)); // ok
> 6. wrap!(immutable int)(immutable(int)(3)); // ok!

This doesn't make sense. Can you post runnable code?

When I go back to your original failing example, and replace the 3 with immutable(int)(3), it still fails.

> 
> So for 3, compiler sees the instantiation:
> 
>   inout(W!(immutable int)) wrap(immutable(int))
> 
> If I understood you correctly?

Yes. You can see for yourself with pragma msg:

pragma(msg, typeof(t)); // immutable(int)

> 
> But then what does it see in number 6, which works fine?

I'm skeptical this is the case.

Note that you may only see the instantiation error ONCE.

> And why is 2 ok if 3 is not?

because inout(const(T)) cannot have its inout removed.

> And finally, why can't the compiler leave the inout there and then it doesn't need to complain about it?
It has to strip inout to be consistent -- we want canonical types. It's the same reason immutable(const(int)) is just immutable(int), and const(const(const(int))) is just const(int). Having the original types be left in place would make for some weird rules.

But the complaint is really the issue. Clearly inout is specified, so it shouldn't complain that it isn't.

-Steve
July 31, 2018
On Tuesday, 31 July 2018 at 21:54:54 UTC, Steven Schveighoffer wrote:
> Because inout is trying to combine all mutability modifiers into one. You want to specify the type, not the mutability, in the template parameter T.

Ahhh. Ok I see... I think.

> This doesn't make sense. Can you post runnable code?

Hehe, ok, so I fell victim to compiler generating an error for number 3 and then nothing else :p But yes you're right, if I comment out number 3 then 6 errors as well. Sorry my bad!

>
> When I go back to your original failing example, and replace the 3 with immutable(int)(3), it still fails.
>
>> 
>> So for 3, compiler sees the instantiation:
>> 
>>   inout(W!(immutable int)) wrap(immutable(int))
>> 
>> If I understood you correctly?
>
> Yes. You can see for yourself with pragma msg:
>
> pragma(msg, typeof(t)); // immutable(int)
>
>> 
>> But then what does it see in number 6, which works fine?
>
> I'm skeptical this is the case.
>
> Note that you may only see the instantiation error ONCE.

Yep, you nailed that one.

>
>> And why is 2 ok if 3 is not?
>
> because inout(const(T)) cannot have its inout removed.

Because it may be an immutable? Or?

> But the complaint is really the issue. Clearly inout is specified, so it shouldn't complain that it isn't.

Aye. I guess that's right.

>
> -Steve


1 2
Next ›   Last »