www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Property assignment problem

reply "SebastianA" <sebastian.ahlman remedygames.com> writes:
This is related to this thread: 
http://forum.dlang.org/thread/cnwpmhihmckpjhlaszzy forum.dlang.org

I am posting it here as well, since it no longer concerns only 
GDC. Also, I am not sure if this is a bug or intended behaviour. 
Consider the following code:

====
void runTest()
{
	Thing t;
	t.vPosition = (Clock.currStdTime % 2 == 0) ? Vec(2, 2) : Vec(3, 
3);
	Vec v = t.vPosition;

	writefln("%d %d\n", v.x, v.y);
}

struct Vec
{
	int x;
	int y;
}

struct Thing
{
	 property Vec vPosition() { return mPosition; }
	 property Vec vPosition( const ref Vec value ) { return 
mPosition = value; }

private:
	Vec mPosition;
}
====

The line that sets the value of the vPosition property does not 
compile on DMD. Instead it gives the error "Error: not a property 
t.vPosition". On GDC this compiles but it does not work in 
release mode, only in debug mode. In release mode it sets the 
property to 0 0. If I assign the vector to a temp variable before 
assigning it to the position it works. It also works if I replace 
the time expression with a constant like "true" or some other 
value known at compile time.

Is this a bug or is it supposed to refuse to compile the code? 
Also, why does it compile on GDC?

BR,
Sebastian Ahlman
May 10 2012
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Friday, May 11, 2012 08:52:14 SebastianA wrote:
 This is related to this thread:
 http://forum.dlang.org/thread/cnwpmhihmckpjhlaszzy forum.dlang.org
 
 I am posting it here as well, since it no longer concerns only
 GDC. Also, I am not sure if this is a bug or intended behaviour.
 Consider the following code:
 
 ====
 void runTest()
 {
 	Thing t;
 	t.vPosition = (Clock.currStdTime % 2 == 0) ? Vec(2, 2) : Vec(3,
 3);
 	Vec v = t.vPosition;
 
 	writefln("%d %d\n", v.x, v.y);
 }
 
 struct Vec
 {
 	int x;
 	int y;
 }
 
 struct Thing
 {
 	 property Vec vPosition() { return mPosition; }
 	 property Vec vPosition( const ref Vec value ) { return
 mPosition = value; }
 
 private:
 	Vec mPosition;
 }
 ====
 
 The line that sets the value of the vPosition property does not
 compile on DMD. Instead it gives the error "Error: not a property
 t.vPosition". On GDC this compiles but it does not work in
 release mode, only in debug mode. In release mode it sets the
 property to 0 0. If I assign the vector to a temp variable before
 assigning it to the position it works. It also works if I replace
 the time expression with a constant like "true" or some other
 value known at compile time.
 
 Is this a bug or is it supposed to refuse to compile the code?
 Also, why does it compile on GDC?
Remove the ref from the setter. Either that or duplicate it: property Vec vPosition( const Vec value ) { return mPosition = value; } property Vec vPosition( const ref Vec value ) { return mPosition = value; } ref does not currently accept rvalues, even if it's const (unlike C++). There are issues in C++ caused by the fact that const& parameters can be either lvalues or rvalues, so D insists that ref is always an lvalue, even if it's const. There has been some discussion of making it possible for ref and const ref to take rvalues with some set of restrictions to avoid the problems that it causes in C++, but that hasn't been fully sorted out yet. - Jonathan M Davis
May 11 2012
parent reply "SebastianA" <sebastian.ahlman remedygames.com> writes:
On Friday, 11 May 2012 at 07:03:10 UTC, Jonathan M Davis wrote:
 On Friday, May 11, 2012 08:52:14 SebastianA wrote:
 This is related to this thread:
 http://forum.dlang.org/thread/cnwpmhihmckpjhlaszzy forum.dlang.org
 
 I am posting it here as well, since it no longer concerns only
 GDC. Also, I am not sure if this is a bug or intended 
 behaviour.
 Consider the following code:
 
 ====
 void runTest()
 {
 	Thing t;
 	t.vPosition = (Clock.currStdTime % 2 == 0) ? Vec(2, 2) : 
 Vec(3,
 3);
 	Vec v = t.vPosition;
 
 	writefln("%d %d\n", v.x, v.y);
 }
 
 struct Vec
 {
 	int x;
 	int y;
 }
 
 struct Thing
 {
 	 property Vec vPosition() { return mPosition; }
 	 property Vec vPosition( const ref Vec value ) { return
 mPosition = value; }
 
 private:
 	Vec mPosition;
 }
 ====
 
 The line that sets the value of the vPosition property does not
 compile on DMD. Instead it gives the error "Error: not a 
 property
 t.vPosition". On GDC this compiles but it does not work in
 release mode, only in debug mode. In release mode it sets the
 property to 0 0. If I assign the vector to a temp variable 
 before
 assigning it to the position it works. It also works if I 
 replace
 the time expression with a constant like "true" or some other
 value known at compile time.
 
 Is this a bug or is it supposed to refuse to compile the code?
 Also, why does it compile on GDC?
Remove the ref from the setter. Either that or duplicate it: property Vec vPosition( const Vec value ) { return mPosition = value; } property Vec vPosition( const ref Vec value ) { return mPosition = value; } ref does not currently accept rvalues, even if it's const (unlike C++). There are issues in C++ caused by the fact that const& parameters can be either lvalues or rvalues, so D insists that ref is always an lvalue, even if it's const. There has been some discussion of making it possible for ref and const ref to take rvalues with some set of restrictions to avoid the problems that it causes in C++, but that hasn't been fully sorted out yet. - Jonathan M Davis
Okay, thanks for the info. The weird thing is, if I change the line to: t.vPosition = Vec(2, 2); it compiles and works, even if the property is ref. As far as I know, this does nothing towards correcting the rvalue issue. Should this also cause an error?
May 11 2012
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Friday, May 11, 2012 09:10:37 SebastianA wrote:
 Okay, thanks for the info. The weird thing is, if I change the
 line to:
 
 t.vPosition = Vec(2, 2);
 
 it compiles and works, even if the property is ref. As far as I
 know, this does nothing towards correcting the rvalue issue.
 Should this also cause an error?
struct literals work. They at least used to be lvalues for some bizarre reason. I'm not sure if they are now, because it went back and forth prior to the last release. They're either still lvalues or the first part of making rvalues work with ref has been implemented (but only with struct literals). I'm not sure which. - Jonathan M Davis
May 11 2012
next sibling parent reply "SebastianA" <sebastian.ahlman remedygames.com> writes:
On Friday, 11 May 2012 at 07:18:30 UTC, Jonathan M Davis wrote:
 On Friday, May 11, 2012 09:10:37 SebastianA wrote:
 Okay, thanks for the info. The weird thing is, if I change the
 line to:
 
 t.vPosition = Vec(2, 2);
 
 it compiles and works, even if the property is ref. As far as I
 know, this does nothing towards correcting the rvalue issue.
 Should this also cause an error?
struct literals work. They at least used to be lvalues for some bizarre reason. I'm not sure if they are now, because it went back and forth prior to the last release. They're either still lvalues or the first part of making rvalues work with ref has been implemented (but only with struct literals). I'm not sure which. - Jonathan M Davis
I did this very naive test: "Vec(2, 2) = Vec(3, 4);" which gave me the error "test.d(30): Error: Vec(2,2) is not an lvalue" so apparently it's not an lvalue, at least not in that sense. Anyway, thanks for the info. We can probably get around the problem by using non-ref parameters for now. It is very weird that GDC accepts the code though, and it even works when running a debug build. BR, Sebastian Ahlman
May 11 2012
parent Iain Buclaw <ibuclaw ubuntu.com> writes:
On 11 May 2012 08:26, SebastianA <sebastian.ahlman remedygames.com> wrote:
 On Friday, 11 May 2012 at 07:18:30 UTC, Jonathan M Davis wrote:
 On Friday, May 11, 2012 09:10:37 SebastianA wrote:
 Okay, thanks for the info. The weird thing is, if I change the
 line to:

 t.vPosition = Vec(2, 2);

 it compiles and works, even if the property is ref. As far as I
 know, this does nothing towards correcting the rvalue issue.
 Should this also cause an error?
struct literals work. They at least used to be lvalues for some bizarre reason. I'm not sure if they are now, because it went back and forth prior to the last release. They're either still lvalues or the first part of making rvalues work with ref has been implemented (but only with struct literals). I'm not sure which. - Jonathan M Davis
I did this very naive test: "Vec(2, 2) = Vec(3, 4);" which gave me the error "test.d(30): Error: Vec(2,2) is not an lvalue" so apparently it's not an lvalue, at least not in that sense. Anyway, thanks for the info. We can probably get around the problem by using non-ref parameters for now. It is very weird that GDC accepts the code though, and it even works when running a debug build.
The copy of GDC you have is probably on build 2.057 - two releases behind the current language implementation. I have been testing your example on my development tree, and can't reproduce the issue of it returning (0,0) after the ternary assignment - though it does compile fine. -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';
May 11 2012
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-05-11 09:18, Jonathan M Davis wrote:

 struct literals work. They at least used to be lvalues for some bizarre
 reason. I'm not sure if they are now, because it went back and forth prior to
 the last release. They're either still lvalues or the first part of making
 rvalues work with ref has been implemented (but only with struct literals).
 I'm not sure which.

 - Jonathan M Davis
Why would the ternary operator make any difference? -- /Jacob Carlborg
May 11 2012
next sibling parent kenji hara <k.hara.pg gmail.com> writes:
Just before the release of 2.059, I implemented the behavior to avoid
breaking of existing codes for only struct literals. I didn't support
other rvalues with it, like such ternary expression. It was minimum
hack.

I think it is a special behavior of 2.059, and I've been highly
skeptical to leave it up to the future, even if changing it breaks
existing codes.

I also think that a need of 'auto ref stroage class for non-template
function parameter' is increasing.

Kenji Hara

2012/5/11 Jacob Carlborg <doob me.com>:
 On 2012-05-11 09:18, Jonathan M Davis wrote:

 struct literals work. They at least used to be lvalues for some bizarre
 reason. I'm not sure if they are now, because it went back and forth prior
 to
 the last release. They're either still lvalues or the first part of making
 rvalues work with ref has been implemented (but only with struct
 literals).
 I'm not sure which.

 - Jonathan M Davis
Why would the ternary operator make any difference? -- /Jacob Carlborg
May 11 2012
prev sibling parent reply Manu <turkeyman gmail.com> writes:
On 11 May 2012 11:24, kenji hara <k.hara.pg gmail.com> wrote:

 Just before the release of 2.059, I implemented the behavior to avoid
 breaking of existing codes for only struct literals. I didn't support
 other rvalues with it, like such ternary expression. It was minimum
 hack.

 I think it is a special behavior of 2.059, and I've been highly
 skeptical to leave it up to the future, even if changing it breaks
 existing codes.

 I also think that a need of 'auto ref stroage class for non-template
 function parameter' is increasing.
Yeah, I've run into a need for 'auto ref' a few times now actually, and I've also been running into these lvalue->ref problems all week. What are the odds that full const ref support might be fleshed out some time soon? We're having to implement quite a few work around for it... This problem has gotten me thinking though, should ref just be a proper storage class? (why isn't it?) It seems that would address almost all problems with it immediately. - There are also some syntactical issues/ambiguities that ref(type) would solve. - You'd be able to declare ref locals (which would be super useful) - 'auto' would work, no need to special case said 'ref auto', which seems a but nasty, in generic code you might not always want that... It'll only be a matter of days before someone wants a 'true' auto. - Solve these recently discussed issues where you can't describe a function/delegate that returns by ref without piping it through an alias. All ref should really be, is syntactical sugar for a pointer, which asserts that it be non-null/initialised, and that it not expose the pointer assignment mechanism. Is there something more that 'ref' does in D that wouldn't work under that setup?
May 11 2012
parent reply travert phare.normalesup.org (Christophe) writes:
Manu , dans le message (digitalmars.D:166891), a écrit :
 All ref should really be, is syntactical sugar for a pointer, which asserts
 that it be non-null/initialised, and that it not expose the pointer
 assignment mechanism.
And implicit conversion of l-values to their ref type.
 Is there something more that 'ref' does in D that wouldn't work under that
 setup?
May 11 2012
parent Manu <turkeyman gmail.com> writes:
On 11 May 2012 13:21, Christophe <travert phare.normalesup.org> wrote:

 Manu , dans le message (digitalmars.D:166891), a =C3=A9crit :
 All ref should really be, is syntactical sugar for a pointer, which
asserts
 that it be non-null/initialised, and that it not expose the pointer
 assignment mechanism.
And implicit conversion of l-values to their ref type.
Indeed, and vice versa.
May 11 2012