[Issue 16131] A struct is being copied unnecessarily when initialized

2016-06-06 Thread via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=16131

--- Comment #1 from Sobirari Muhomori  ---
I'd say it's moved. It was said many times that move semantics exists in D, but
nothing about that is documented :(

--


[Issue 16131] A struct is being copied unnecessarily when initialized

2016-06-07 Thread via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=16131

Ketmar Dark  changed:

   What|Removed |Added

 Status|NEW |RESOLVED
 CC||ket...@ketmar.no-ip.org
 Resolution|--- |INVALID

--- Comment #2 from Ketmar Dark  ---
structs are value types, so compiler is free to move 'em (i.e. just memcpy
without calling postblit/dtor/ctor). this is a feature of value types. that's
why you should never store a pointer to stack-allocated struct, even if it is
guaranteed that the pointer will not outlive the struct itself.

i'm closing this bug as INVALID, but feel free to open an ER with the request
for better documentation for copy/move semantic.

--


[Issue 16131] A struct is being copied unnecessarily when initialized

2016-06-07 Thread via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=16131

Eyal  changed:

   What|Removed |Added

 Status|RESOLVED|REOPENED
 Resolution|INVALID |---

--- Comment #3 from Eyal  ---
Perhaps I can illustrate that there is an actual issue with a more convincing
example (and more similar to the actual problem I experienced):

import core.thread : Fiber;
import std.stdio : writeln;

struct Foo {
int x;
Fiber fib;
@disable this(this);
this(int x) {
this.x = x;
fib = new Fiber(&run);
}
void run() {
writeln("Hello from: ", x);
}
}

void main() {
Foo[10] foos; // OR with:  = void;
foreach(int i, ref foo; foos) {
foo = Foo(i);
}
foreach(ref foo; foos) {
foo.fib.call();
}
}

This will print out:
Hello from: 9
Hello from: 9
Hello from: 9
...

`move` semantics often require updating ptrs, so just moving structs via memcpy
will often hide atrocious bugs.

Another example where `move` is problematic is an intrusive list head:

struct Chain {
  struct Chain *prev, *next;
  ..
}

An important invariant you would want to preserve is that chain.next.prev =
&chain;

Once D freely moves Chains (or any struct that indirectly contains Chain)
around, terrible bugs will ensue.

Having move by default is OK, but is there any reason to allow move for structs
that specifically disable this(this)? I'd say this violates expectations. At
the very least a way to disable unwanted moves should exist.

--


[Issue 16131] A struct is being copied unnecessarily when initialized

2016-06-08 Thread via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=16131

Ketmar Dark  changed:

   What|Removed |Added

 Status|REOPENED|RESOLVED
 Resolution|--- |INVALID

--- Comment #4 from Ketmar Dark  ---
sorry, but i have to close this bug again. it is perfectly valid to move
*value* type. struct is *value* type. you can't disable "move" operations on
structs, and this is not an oversight, it was designed like that. it gives
compiler some freedom, and it won't be changed.

never ever store a pointer to stack-allocated struct anywhere. this is The
Rule.

as for lists... allocate your structs with `new` — and compiler will not move
'em. then you can do what you want.


import core.thread : Fiber;
import std.stdio : writeln;

struct Foo {
int x;
Fiber fib;
@disable this(this);
this(int x) {
this.x = x;
fib = new Fiber(&run);
}
void run() {
writeln("Hello from: ", x);
}
}

void main() {
Foo*[10] foos; // OR with:  = void;
foreach(int i, ref foo; foos) {
foo = new Foo(i);
}
foreach(ref foo; foos) {
foo.fib.call();
}
}

This will print out:
Hello from: 0
Hello from: 1
Hello from: 2
Hello from: 3
Hello from: 4
Hello from: 5
Hello from: 6
Hello from: 7
Hello from: 8
Hello from: 9

as you can see, heap-allocated structs won't be moved, never (unless somebody
will write compating GC ;-).


so, to summarise: there is no sense to complain about "move" semantic for
structs, it works as designed, and will stay with us. just have it in mind when
you designing your code. sorry.

--


[Issue 16131] A struct is being copied unnecessarily when initialized

2016-06-08 Thread via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=16131

Steven Schveighoffer  changed:

   What|Removed |Added

 CC||schvei...@yahoo.com

--- Comment #5 from Steven Schveighoffer  ---
(In reply to Eyal from comment #3)

> fib = new Fiber(&run);

This is your problem. This stores a context pointer to 'this', which may
change.

In general, it's a bad idea to use delegates to structs unless you know they
won't move (e.g. part of a heap allocation).

Ketmar is right that it's perfectly valid to memcpy a struct in D. You have to
expect that.

--


[Issue 16131] A struct is being copied unnecessarily when initialized

2016-06-08 Thread via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=16131

--- Comment #6 from Sobirari Muhomori  ---
Try this:

struct Foo {
int x;
Fiber fib;
@disable this(this);
void create(int x) {
this.x = x;
fib = new Fiber(&run);
}
void run() {
writeln("Hello from: ", x);
}
}

void main() {
Foo[10] foos; // OR with:  = void;
foreach(int i, ref foo; foos) {
foo.create(i);
}
foreach(ref foo; foos) {
foo.fib.call();
}
}

--