July 13, 2018
>> In a post-blit world, with no opAssign specified, postblit will call
>> for copy construction AND for assignment, thereby assignment is always
>> correct.
>> Once postblit is swapped for a copy-constructor, absence of opAssign
>> will result in invalid behaviour on assignment.

Indeed, but this was the source of the problem also, because you could
modify immutable fields that way.

>> Introduction of copy constructor breaks default assignment, it needs
>> to address it somehow. I think my suggestion is the only practical
>> solution.
>
> Affirmative. The DIP needs to specify how assignment is handled if no opAssign is present but a copy ctor is present. Thanks!

The difference between a copy constructor and opAssign is how the type checking
is performed. This leads to situations where a copy constructor is not suitable as an assignment operator. However, if a copy constructor is defined in a way that is correctly type checked both as a constructor and as a normal function, then there is no problem in using the copy constructor for assignments:

struct A
{
    immutable int b;
    int c;
    @implicit this(ref A rhs)
    {
        this.c = rhs.c;
    }
}

struct B
{
    immutable int b;
    int c;
    @implicit this(ref A rhs)
    {
        this.b = rhs.b;
        this.c = rhs.c;
    }
}

void main()
{
    A a, c;
    A b = a;
    b = c;       // no problem in calling copy constructor, immutable is
                 // not modified
    B d, e;
    B f = d;
    f = d;       // cannot use copy constructor because it will modify immutable
                 // field B.b; for this situation you need an opAssign to specify
                 // how the assignment is dealt with.
}

The problem with this approach is that some copy constructors will also be used as assignment operators while others will not, but with good error messages it could be handled (error on line `f = d` : opAssign not specified and the copy constructor is not suitable for assignments because it modifies immutable field `b`).

What are your opinions on this?
July 13, 2018
The above code contains a typo. The parameter type of the second copy constructor is meant to be B not A
July 13, 2018
On Friday, 13 July 2018 at 03:01:25 UTC, Manu wrote:
> On Thu, 12 Jul 2018 at 19:15, Andrei Alexandrescu via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>>
>> On 7/12/18 6:34 PM, Manu wrote:
>> > On Thu, 12 Jul 2018 at 06:50, Andrei Alexandrescu via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>> >>
> [..]
> doesn't perform copy construction?
>   1. the function is highly unlikely to exist because postblit; it's a
> meaningless function to write. are there any known instances of that
> signature in the wild?

https://github.com/search?q=%22this%5C%28ref%22+language%3AD&type=Code

The answer seems to be: not many. Most of the results above are false positives because github won't let me escape the left parenthesis.

Atila
July 13, 2018
On 7/13/18 8:31 AM, Atila Neves wrote:
> On Friday, 13 July 2018 at 03:01:25 UTC, Manu wrote:
>> On Thu, 12 Jul 2018 at 19:15, Andrei Alexandrescu via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>>>
>>> On 7/12/18 6:34 PM, Manu wrote:
>>> > On Thu, 12 Jul 2018 at 06:50, Andrei Alexandrescu via > 
>>> Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>>> >>
>> [..]
>> doesn't perform copy construction?
>>   1. the function is highly unlikely to exist because postblit; it's a
>> meaningless function to write. are there any known instances of that
>> signature in the wild?
> 
> https://github.com/search?q=%22this%5C%28ref%22+language%3AD&type=Code
> 
> The answer seems to be: not many. Most of the results above are false positives because github won't let me escape the left parenthesis.

A proposal that just works without any user intervention would definitely be attractive.

The drawback is silent modification of code behavior. Consider:

import std.stdio;
struct A {
    this(ref immutable A obj) { writeln("x"); }
}
void main()
{
    immutable A a1;
    A a2 = A(a1);
    A a3 = a1;
}

With the current language, "x" is printed once. If we make the ctor implicit, "x" is printed twice.

In the "levels of hell" of semantics changes, probably the nicest is allowing code to compile that previously didn't. Then, refusing to compile code that previously did would be definitely bad. But if you want to drink the cup of disgrace to the bottom, you must reach for silent change of behavior.
July 13, 2018
On 7/12/18 11:45 PM, Manu wrote:
> On Thu, 12 Jul 2018 at 20:15, Meta via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>> 
>> On Friday, 13 July 2018 at 02:32:59 UTC, Manu wrote:
>>> Seriously, if I was making this proposal to you, and you were in
>>> my position... there is no way in hell that you'd allow any of
>>> us to slip something so substantial by like that with the wave of
>>> a hand. This DIP depends on @implicit. How can you argue
>>> otherwise?
>> 
>> Nothing is being slipped by as far as I'm concerned. @implicit is solely introduced in the DIP as a marker for the copy constructor,
>> and it doesn't seem like it's intended for anything further than
>> avoiding breaking code. It feels to me like you're making a
>> mountain out of an ant hill.
> 
> That's the whole point though. We're debating whether "@implicit" is
> a good idea. And it's the only detail of the DIP that feels
> noteworthy or contentious to me. The rest is pretty much
> common-sense, and long overdue.
> 
> I can see myself getting behind 2 possibilities, no @implicit, or @implicit done right.

A couple of simple ideas are making the process productive. One is to
rely on facts instead of feelings. "It's weird" or "I don't like it" are
less helpful than "semantics of this or that case are not covered".

Another is precision. Stating vague goals and standards ("I want
@implicit done well") and systematically asking others to actually put
in the work is less desirable than providing concrete, motivated, actionable feedback.

To the second point: we have a history of defining features too permissively, to then regret not having waited to accumulate experience. Starting with a restricted version then building on experience with it seems to be a much better strategy. From that perspective, introducing implicit only for restricted copy construction seems like a good step that doesn't take others, without precluding them.

> I don't see myself getting behind introduction of @implicit on such terms that it's nothing but "a marker for the copy constructor". So this 'mountain' is critical to understanding whether I can support this DIP as proposed or not.

I'd put it a slightly different way. "Getting behind" and "supporting or not" suggests a position of power and an emphasis on the politics of the process. The natural counter to this would be asking whether your support is necessary, which put us all in a very unproductive position.

The right emphasis is not getting your support on a given DIP, but instead us all benefiting of your active contribution to a better DIP.


Thanks,

Andrei
July 13, 2018
On 7/12/18 11:01 PM, Manu wrote:
> What existing code are you changing the semantics of?
> It's still not clear to me how accepting `this(ref T)` as a magic
> signature that is a copy constructor can break existing code?
> Is it the unlikely^^2 case that the function exists somewhere and
> doesn't perform copy construction?
>    1. the function is highly unlikely to exist because postblit; it's a
> meaningless function to write. are there any known instances of that
> signature in the wild?
>    2. if the function does exist, it's highly unlikely that it doesn't
> perform a valid copy construction; what else could it possibly do?
>    3. remaining cases are broken by this DIP, but they are probably
> crazy and deserve to be deprecated!
> 
> Is there any reasonable existing use of the signature that would be
> legitimately broken by being invoked implicitly?
> I feel like there's something that I'm missing... but if there's not,
> then just change the semantic.
> 
> I reason; copy construction is something so fundamental. It will be
> written by basically every programmer with relative high frequently,
> and adding awkward syntax or weird language baggage to the concept
> feels like a very poor choice.
> By contrast, if there's 1 user out there who used the copy-constructor
> signature to do some weird thing other than copy construction, and
> their code is broken by this change, his use case does not balance the
> imposition applied to every implementation of copy constructor forever
> from this time forward.
> This is so much more important than that, it's extremely fundamental
> language stuff, and needs to be as friction-less as possible, and it
> should certainly not reek of legacy drama.

Noted. So in summary you would be okay with changing semantics of existing code, under the intuition that the change is unlikely to be destructive anyway.
July 13, 2018
On Friday, 13 July 2018 at 14:12:59 UTC, Andrei Alexandrescu wrote:
> On 7/13/18 8:31 AM, Atila Neves wrote:
>> On Friday, 13 July 2018 at 03:01:25 UTC, Manu wrote:
>>> [...]
>> 
>> https://github.com/search?q=%22this%5C%28ref%22+language%3AD&type=Code
>> 
>> The answer seems to be: not many. Most of the results above are false positives because github won't let me escape the left parenthesis.
>
> A proposal that just works without any user intervention would definitely be attractive.
>
> The drawback is silent modification of code behavior. Consider:
>
> import std.stdio;
> struct A {
>     this(ref immutable A obj) { writeln("x"); }
> }
> void main()
> {
>     immutable A a1;
>     A a2 = A(a1);
>     A a3 = a1;
> }
>
> With the current language, "x" is printed once. If we make the ctor implicit, "x" is printed twice.
>
> In the "levels of hell" of semantics changes, probably the nicest is allowing code to compile that previously didn't. Then, refusing to compile code that previously did would be definitely bad. But if you want to drink the cup of disgrace to the bottom, you must reach for silent change of behavior.

I agree on the levels of hell. I wasn't aware the kind of change above would happen - methinks it should be in the DIP.

I think I now even understand why `@implicit` is there to begin with. I still think it's confusing, so imagine someone new to the language.

Atila
July 13, 2018
On 7/13/18 11:14 AM, Atila Neves wrote:
> On Friday, 13 July 2018 at 14:12:59 UTC, Andrei Alexandrescu wrote:
>> On 7/13/18 8:31 AM, Atila Neves wrote:
>>> On Friday, 13 July 2018 at 03:01:25 UTC, Manu wrote:
>>>> [...]
>>>
>>> https://github.com/search?q=%22this%5C%28ref%22+language%3AD&type=Code
>>>
>>> The answer seems to be: not many. Most of the results above are false positives because github won't let me escape the left parenthesis.
>>
>> A proposal that just works without any user intervention would definitely be attractive.
>>
>> The drawback is silent modification of code behavior. Consider:
>>
>> import std.stdio;
>> struct A {
>>     this(ref immutable A obj) { writeln("x"); }
>> }
>> void main()
>> {
>>     immutable A a1;
>>     A a2 = A(a1);
>>     A a3 = a1;
>> }
>>
>> With the current language, "x" is printed once. If we make the ctor implicit, "x" is printed twice.
>>
>> In the "levels of hell" of semantics changes, probably the nicest is allowing code to compile that previously didn't. Then, refusing to compile code that previously did would be definitely bad. But if you want to drink the cup of disgrace to the bottom, you must reach for silent change of behavior.
> 
> I agree on the levels of hell. I wasn't aware the kind of change above would happen - methinks it should be in the DIP.

Great. Razvan, can you please add this example with discussion to the DIP (probably at the end of the Motivation section as an explanation why we need the addition of @implicit). Thanks.

> I think I now even understand why `@implicit` is there to begin with. I still think it's confusing, so imagine someone new to the language.

Interesting. Coming from a C++ background makes the matter obvious because there's plenty of implicit vs. explicit discussion. To compensate for my bias - what do you think would be a better attribute name?


Andrei

July 13, 2018
On Friday, 13 July 2018 at 16:02:51 UTC, Andrei Alexandrescu wrote:
> On 7/13/18 11:14 AM, Atila Neves wrote:
>> [...]
>
> Great. Razvan, can you please add this example with discussion to the DIP (probably at the end of the Motivation section as an explanation why we need the addition of @implicit). Thanks.
>
>> [...]
>
> Interesting. Coming from a C++ background makes the matter obvious because there's plenty of implicit vs. explicit discussion. To compensate for my bias - what do you think would be a better attribute name?
>
>
> Andrei

Why "@implicit" is an attribute and not a keyword?

-Alexander
July 13, 2018
From the DIP:
> The copy constructor declaration will be recognized by the parser when the tokens @, implicit, this are encountered exactly in this order

Regarding "exactly in this order". The code below would be allowed and define copy c'tor for `A` and usual c'tor for `B` ?


    struct implicit{}

    struct A {
        @safe @implicit this(ref A) {}
    }

    struct B {
        @implicit @safe this(ref B) {}
    }