Re: Copy Constructor DIP

2018-07-11 Thread Manu via Digitalmars-d
On Wed, 11 Jul 2018 at 00:40, RazvanN via Digitalmars-d
 wrote:
>
> On Tuesday, 10 July 2018 at 20:58:09 UTC, Manu wrote:
> > On Tue, 10 Jul 2018 at 03:50, RazvanN via Digitalmars-d
> >  wrote:
> >>
> >> Hi everyone!
> >>
> >> I managed to put together a first draft of the DIP for adding
> >> the copy constructor to the language [1]. If anyone is
> >> interested, please take a look. Suggestions and comments about
> >> technical aspects and wording are all welcome.
> >>
> >> Thanks,
> >> RazvanN
> >>
> >> [1] https://github.com/dlang/DIPs/pull/129
> >
> > I feel there's some things missing.
> >
> > 1. Explain the need and reasoning behind `@implicit`... that's
> > weird
>
> It is a simple way of defining a copy constructor without the
> need of
> adding new keywords and with minimal additions to the parser.

What's wrong with:
struct S {
  this(ref S copyFrom);
}

That looks like a perfectly good copy constructor declaration ;)
I'm just saying, the DIP needs to explain this.

> > and I don't like it at face value.
> > 2. It looks like copy constructors are used to perform
> > assignments
> > (and not constructions)... but, there is also opAssign. What
> > gives?
> > Eg:
> >   S b = a; // <- copy construction? looks like an
> > assignment.
> > And not:
> >   S b = S(a); // <- actually looks like a construction, but
> > this
> > syntax seems to not be intended (and rightly so, it's pretty
> > terrible)
> > 3. In C++, copy constructors and copy assignment operators come
> > in
> > pairs (which is totally lame!), but we don't see that same
> > pattern
> > extend here, and it's not clear at all why.
> > 4. Given the special rules where assignments are lifted to
> > constructions, I want to know when that occurs (maybe that is
> > already
> > spec-ed wrt postblit?)
> >
> > - Manu
>
> Copy construction is used solely when the object was not
> initialized and it
> cannot be used otherwise. Consider this example:
>
> struct A
> {
>  immutable int a = 7;
>  @implicit this(ref A another)
>  {
>   this.a = A.a;  // first assignment over .init state
> - ok
>  }
>
>  void opAssign(A rhs)
>  {
>  this.a = rhs.a;
>  }
> }
>
> void main()
> {
>  A a = A(2);
>  A b = a; //  initialization -> calls copy
> constructor
>  b = a;   // cannot call copy constructor because
> it will
>   // modify immutable; call opAssign.
> }
>
> The first assignment of b calls the copy constructor and the
> immutable field is
> initialized; later assignments to b.a will result in "modify
> immutable" error.
> The second assignment of b cannot call the copy constructor
> because it would then modify an initialized immutable field.
> However, with opAssign the compiler knows that A.a cannot be
> modified because it is immutable.

Right. This is all obvious and intuitive.
What I'm hearing is that under this proposal, copy constructors and
assignment operators DO come in pairs (just like in C++), but that's
not mentioned here in this DIP. Since this proposal will introduce
that recommended pattern from C++, it may be worth mentioning.


Re: Copy Constructor DIP

2018-07-11 Thread vit via Digitalmars-d

On Wednesday, 11 July 2018 at 07:40:32 UTC, RazvanN wrote:
But there's a super explicit `@implicit` thing written right 
there... so should we expect that an *explicit* call to the 
copy constructor is not allowed? Or maybe it is allowed and 
`@implicit` is a lie?


The @implicit is there to point out that you cannot call that 
method
explicitly; it gets called for you implicitly when you 
construct an object

as a copy of another object.


Can be explicit constructor overloaded with implicit constructor 
when both have same signature?


Re: Copy Constructor DIP

2018-07-11 Thread Atila Neves via Digitalmars-d

On Wednesday, 11 July 2018 at 07:40:32 UTC, RazvanN wrote:
But there's a super explicit `@implicit` thing written right 
there... so should we expect that an *explicit* call to the 
copy constructor is not allowed? Or maybe it is allowed and 
`@implicit` is a lie?


The @implicit is there to point out that you cannot call that 
method
explicitly; it gets called for you implicitly when you 
construct an object

as a copy of another object.


How is this different from other types of constructors or 
destructors?


I also very much dislike the syntax - it makes no sense to me at 
all. I commented on the PR itself asking why it differs so much 
from C++ - specifically, what's bad about the C++ way of doing 
things there that we want to avoid?


Atila


Re: Copy Constructor DIP

2018-07-11 Thread Nick Treleaven via Digitalmars-d

On Tuesday, 10 July 2018 at 10:47:04 UTC, RazvanN wrote:

[1] https://github.com/dlang/DIPs/pull/129


Thanks for making the DIP. I can't get this code to compile (my 
struct has an `int i` field):


static foreach (i, ref field; src.tupleof)
this.tupleof[i] = field;

Error: constant value src.i cannot be ref

https://run.dlang.io/is/qeugC8

Removing `static` works. Otherwise I tried changing `ref` to 
`alias`:


Error: variable src cannot be read at compile time

But this shorter code seems to work fine:

this.tupleof = src.tupleof;


Re: Copy Constructor DIP

2018-07-11 Thread RazvanN via Digitalmars-d
But there's a super explicit `@implicit` thing written right 
there... so should we expect that an *explicit* call to the 
copy constructor is not allowed? Or maybe it is allowed and 
`@implicit` is a lie?


The @implicit is there to point out that you cannot call that 
method
explicitly; it gets called for you implicitly when you construct 
an object

as a copy of another object.




Re: Copy Constructor DIP

2018-07-11 Thread RazvanN via Digitalmars-d

On Tuesday, 10 July 2018 at 20:58:09 UTC, Manu wrote:
On Tue, 10 Jul 2018 at 03:50, RazvanN via Digitalmars-d 
 wrote:


Hi everyone!

I managed to put together a first draft of the DIP for adding 
the copy constructor to the language [1]. If anyone is 
interested, please take a look. Suggestions and comments about 
technical aspects and wording are all welcome.


Thanks,
RazvanN

[1] https://github.com/dlang/DIPs/pull/129


I feel there's some things missing.

1. Explain the need and reasoning behind `@implicit`... that's 
weird


It is a simple way of defining a copy constructor without the 
need of

adding new keywords and with minimal additions to the parser.


and I don't like it at face value.
2. It looks like copy constructors are used to perform 
assignments
(and not constructions)... but, there is also opAssign. What 
gives?

Eg:
  S b = a; // <- copy construction? looks like an 
assignment.

And not:
  S b = S(a); // <- actually looks like a construction, but 
this
syntax seems to not be intended (and rightly so, it's pretty 
terrible)
3. In C++, copy constructors and copy assignment operators come 
in
pairs (which is totally lame!), but we don't see that same 
pattern

extend here, and it's not clear at all why.
4. Given the special rules where assignments are lifted to
constructions, I want to know when that occurs (maybe that is 
already

spec-ed wrt postblit?)

- Manu


Copy construction is used solely when the object was not 
initialized and it

cannot be used otherwise. Consider this example:

struct A
{
immutable int a = 7;
@implicit this(ref A another)
{
 this.a = A.a;  // first assignment over .init state 
- ok

}

void opAssign(A rhs)
{
this.a = rhs.a;
}
}

void main()
{
A a = A(2);
A b = a; //  initialization -> calls copy 
constructor
b = a;   // cannot call copy constructor because 
it will

 // modify immutable; call opAssign.
}

The first assignment of b calls the copy constructor and the 
immutable field is
initialized; later assignments to b.a will result in "modify 
immutable" error.
The second assignment of b cannot call the copy constructor 
because it would then modify an initialized immutable field. 
However, with opAssign the compiler knows that A.a cannot be 
modified because it is immutable.




Re: Copy Constructor DIP

2018-07-10 Thread Manu via Digitalmars-d
On Tue, 10 Jul 2018 at 15:23, Jonathan M Davis via Digitalmars-d
 wrote:
>
> On Tuesday, 10 July 2018 14:58:09 MDT Manu via Digitalmars-d wrote:
> > 2. It looks like copy constructors are used to perform assignments
> > (and not constructions)... but, there is also opAssign. What gives?
> > Eg:
> >   S b = a; // <- copy construction? looks like an assignment.
> > And not:
> >   S b = S(a); // <- actually looks like a construction, but this
> > syntax seems to not be intended (and rightly so, it's pretty terrible)
>
> S b = a;
>
> has never been assignment in either C++ or D. It's initialization /
> construction, which means that it calls a constructor - be that a postblit
> constructor or a copy constructor. Assignment only occurs when you're giving
> an existing object a new value.

I know this, but it's not syntactically obvious, it just depends on
the fact that you already know that fact... I feel a DIP about copy
construction needs to have some text explaining that, and where the
edges are.
Is an initialisation assignment can use a copy constructor, why can't
a normal assignment implicitly use a copy constructor? (implicit
destruct then copy-construct)

> And why would
>
> S b = S(a);
>
> not be intended? Sure, it's kind of pointless if a is an S, but if you have
> a copy constructor, it makes perfect sense that S(a) would work and would be
> pretty bizarre if it didn't, since it's explicitly calling the copy
> constructor.

But there's a super explicit `@implicit` thing written right there...
so should we expect that an *explicit* call to the copy constructor is
not allowed? Or maybe it is allowed and `@implicit` is a lie?

> It even works right now if you give S a constructor that takes
> an S. It just isn't actually treated as a proper copy constructor at the
> moment, since that's currently the postblit constructor's job.

Current language doesn't have `@implicit` written anywhere...


Re: Copy Constructor DIP

2018-07-10 Thread Jonathan M Davis via Digitalmars-d
On Tuesday, 10 July 2018 14:58:09 MDT Manu via Digitalmars-d wrote:
> 2. It looks like copy constructors are used to perform assignments
> (and not constructions)... but, there is also opAssign. What gives?
> Eg:
>   S b = a; // <- copy construction? looks like an assignment.
> And not:
>   S b = S(a); // <- actually looks like a construction, but this
> syntax seems to not be intended (and rightly so, it's pretty terrible)

S b = a;

has never been assignment in either C++ or D. It's initialization /
construction, which means that it calls a constructor - be that a postblit
constructor or a copy constructor. Assignment only occurs when you're giving
an existing object a new value.

And why would

S b = S(a);

not be intended? Sure, it's kind of pointless if a is an S, but if you have
a copy constructor, it makes perfect sense that S(a) would work and would be
pretty bizarre if it didn't, since it's explicitly calling the copy
constructor. It even works right now if you give S a constructor that takes
an S. It just isn't actually treated as a proper copy constructor at the
moment, since that's currently the postblit constructor's job.

- Jonathan M Davis





Re: Copy Constructor DIP

2018-07-10 Thread Manu via Digitalmars-d
On Tue, 10 Jul 2018 at 03:50, RazvanN via Digitalmars-d
 wrote:
>
> Hi everyone!
>
> I managed to put together a first draft of the DIP for adding the
> copy constructor to the language [1]. If anyone is interested,
> please take a look. Suggestions and comments about technical
> aspects and wording are all welcome.
>
> Thanks,
> RazvanN
>
> [1] https://github.com/dlang/DIPs/pull/129

I feel there's some things missing.

1. Explain the need and reasoning behind `@implicit`... that's weird
and I don't like it at face value.
2. It looks like copy constructors are used to perform assignments
(and not constructions)... but, there is also opAssign. What gives?
Eg:
  S b = a; // <- copy construction? looks like an assignment.
And not:
  S b = S(a); // <- actually looks like a construction, but this
syntax seems to not be intended (and rightly so, it's pretty terrible)
3. In C++, copy constructors and copy assignment operators come in
pairs (which is totally lame!), but we don't see that same pattern
extend here, and it's not clear at all why.
4. Given the special rules where assignments are lifted to
constructions, I want to know when that occurs (maybe that is already
spec-ed wrt postblit?)

- Manu


Re: Copy Constructor DIP

2018-07-10 Thread FeepingCreature via Digitalmars-d

On Tuesday, 10 July 2018 at 13:38:33 UTC, Jonathan M Davis wrote:
He thought that it was critical that the invariant be valid 
when opAssign was called - and there are cases where that's 
arguably true - but since it doesn't work once you try to do 
fancier stuff like emplace, I'm of the opinion that invariants 
are unfortunately a waste of time - even without getting into 
the issue of init values.


- Jonathan M Davis


moveEmplace bypasses opAssign, since it memcopies directly. 
However, it resets its source value to T.init... so if T.init 
isn't valid, you simply crash whenever the source value goes out 
of scope.


Using types with an invalid T.init feels like playing musical 
chairs with a crash. You can shuffle things around, and make some 
parts work, but *something* is always left crashing at the end.


Re: Copy Constructor DIP

2018-07-10 Thread Uknown via Digitalmars-d

On Tuesday, 10 July 2018 at 14:28:09 UTC, FeepingCreature wrote:
On Tuesday, 10 July 2018 at 13:38:33 UTC, Jonathan M Davis 
wrote:

[...]
Using types with an invalid T.init feels like playing musical 
chairs with a crash. You can shuffle things around, and make 
some parts work, but *something* is always left crashing at the 
end.


This is where I feel being able to redefine T.init would be 
useful, but as Andrei said, that is beyond the scope of this DIP


Re: Copy Constructor DIP

2018-07-10 Thread Andrei Alexandrescu via Digitalmars-d

On 07/10/2018 06:52 AM, Guillaume Piolat wrote:

On Tuesday, 10 July 2018 at 10:47:04 UTC, RazvanN wrote:

Hi everyone!

I managed to put together a first draft of the DIP for adding the copy 
constructor to the language [1]. If anyone is interested, please take 
a look. Suggestions and comments about technical aspects and wording 
are all welcome.


Thanks,
RazvanN

[1] https://github.com/dlang/DIPs/pull/129


Does it allow to remove the "T.init must always be valid for structs" rule?


That's not part of this proposal's charter.


Re: Copy Constructor DIP

2018-07-10 Thread Jonathan M Davis via Digitalmars-d
On Tuesday, 10 July 2018 06:34:34 MDT Guillaume Piolat via Digitalmars-d 
wrote:
> On Tuesday, 10 July 2018 at 11:58:53 UTC, Jonathan M Davis wrote:
> >> Does it allow to remove the "T.init must always be valid for
> >> structs" rule?
> >
> > Why would it? init is the state of the object before any
> > constructor runs, and quite a few things rely on it. The fact
> > that we've allowed default initialization to be disabled
> > already causes plenty of problems as it is. It's occasionally
> > useful, but it definitely complicates things. D was designed
> > with the idea that every type has an init value.
> >
> > What problem are you trying to solve here?
> >
> > - Jonathan M Davis
>
> None, I was just reacting to
> https://medium.com/@feepingcreature/d-structs-dont-work-for-domain-data-c0
> 9332349f43
>
> Proper D structs almost require having a T.init that is valid,
> and in turn many public members may get to check for internal
> validity before doing things. This is in stark contrast to C++
> where "proper" constructor is guaranteed so you don't check such
> validity.
>
> What is a "correct" T.init for a mutex RAII struct? It is a null
> handle value. It's obviously an invalid value for any purpose,
> but the D wrapper has to be a valid struct.

It's not necessarily expected that all of the functions on T.init are going
to work. It's the stuff like copying it, assigning it, destroying it, etc.
that have to work (and aside from destruction, you can even @disable them if
you need to). Not even toString actually needs to work. It's just that it's
so common for folks to print values that it gets annoying when it doesn't
work. And yes, if T.init does not match the invariant, then you can start
running into problems, though it isn't necessarily fatal. Basically, in that
case, you're forced to disable default initialization and avoid actually
doing much with the init value.

Honestly though, the reason that I think that invariants are terrible has
nothing to do with T.init specifically but with opAssign. The invariant gets
checked before opAssign, and in many cases, this makes sense, but in the
case where you're doing something like void initialization or using emplace
on uninitialized memory, it blows up in your face if the garbage that
happened to be in the struct didn't match the invariant. The same would
happen if T.init does not pass the invariant, but T.init isn't required to
hit the problem. It's the fact that you can't bypass the invariant when
giving the object a new value that's the main problem. If both assignment
and copying worked without checking the invariant, then invariants would be
a _lot_ more useful. Unfortunately, when I argued about this quite a bit
with regards to opAssign several years ago, Walter didn't agree at all. He
thought that it was critical that the invariant be valid when opAssign was
called - and there are cases where that's arguably true - but since it
doesn't work once you try to do fancier stuff like emplace, I'm of the
opinion that invariants are unfortunately a waste of time - even without
getting into the issue of init values.

- Jonathan M Davis





Re: Copy Constructor DIP

2018-07-10 Thread Guillaume Piolat via Digitalmars-d

On Tuesday, 10 July 2018 at 11:58:53 UTC, Jonathan M Davis wrote:


Does it allow to remove the "T.init must always be valid for 
structs" rule?


Why would it? init is the state of the object before any 
constructor runs, and quite a few things rely on it. The fact 
that we've allowed default initialization to be disabled 
already causes plenty of problems as it is. It's occasionally 
useful, but it definitely complicates things. D was designed 
with the idea that every type has an init value.


What problem are you trying to solve here?

- Jonathan M Davis


None, I was just reacting to 
https://medium.com/@feepingcreature/d-structs-dont-work-for-domain-data-c09332349f43


Proper D structs almost require having a T.init that is valid, 
and in turn many public members may get to check for internal 
validity before doing things. This is in stark contrast to C++ 
where "proper" constructor is guaranteed so you don't check such 
validity.


What is a "correct" T.init for a mutex RAII struct? It is a null 
handle value. It's obviously an invalid value for any purpose, 
but the D wrapper has to be a valid struct.


Re: Copy Constructor DIP

2018-07-10 Thread rikki cattermole via Digitalmars-d

I'm not keen on the added attribute.

Something along the lines of:

this(this; ref Foo foo) {}

might look a little better no?

And now no super special attribute to worry about parsing.


Re: Copy Constructor DIP

2018-07-10 Thread Jonathan M Davis via Digitalmars-d
On Tuesday, 10 July 2018 04:52:18 MDT Guillaume Piolat via Digitalmars-d 
wrote:
> On Tuesday, 10 July 2018 at 10:47:04 UTC, RazvanN wrote:
> > Hi everyone!
> >
> > I managed to put together a first draft of the DIP for adding
> > the copy constructor to the language [1]. If anyone is
> > interested, please take a look. Suggestions and comments about
> > technical aspects and wording are all welcome.
> >
> > Thanks,
> > RazvanN
> >
> > [1] https://github.com/dlang/DIPs/pull/129
>
> Does it allow to remove the "T.init must always be valid for
> structs" rule?

Why would it? init is the state of the object before any constructor runs,
and quite a few things rely on it. The fact that we've allowed default
initialization to be disabled already causes plenty of problems as it is.
It's occasionally useful, but it definitely complicates things. D was
designed with the idea that every type has an init value.

What problem are you trying to solve here?

- Jonathan M Davis





Re: Copy Constructor DIP

2018-07-10 Thread Guillaume Piolat via Digitalmars-d

On Tuesday, 10 July 2018 at 10:47:04 UTC, RazvanN wrote:

Hi everyone!

I managed to put together a first draft of the DIP for adding 
the copy constructor to the language [1]. If anyone is 
interested, please take a look. Suggestions and comments about 
technical aspects and wording are all welcome.


Thanks,
RazvanN

[1] https://github.com/dlang/DIPs/pull/129


Does it allow to remove the "T.init must always be valid for 
structs" rule?


Copy Constructor DIP

2018-07-10 Thread RazvanN via Digitalmars-d

Hi everyone!

I managed to put together a first draft of the DIP for adding the 
copy constructor to the language [1]. If anyone is interested, 
please take a look. Suggestions and comments about technical 
aspects and wording are all welcome.


Thanks,
RazvanN

[1] https://github.com/dlang/DIPs/pull/129


<    1   2