www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - "<Type> is not mutable" when using ref return type

reply %u <wfunction hotmail.com> writes:
Hi!

Is this a bug, or is it intentional that this fails? I can't come up
with any case where it would cause a problem, but the compiler doesn't
like the fact that there's a const in the structure:

    struct Temp { const int a; int b; }

    auto ref foo(Temp* t) { return *t; } //Error
May 18 2011
next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-05-18 20:55, %u wrote:
 Hi!
 
 Is this a bug, or is it intentional that this fails? I can't come up
 with any case where it would cause a problem, but the compiler doesn't
 like the fact that there's a const in the structure:
 
     struct Temp { const int a; int b; }
 
     auto ref foo(Temp* t) { return *t; } //Error

As soon as you do *t, you're copying the value. As such, I don't know why the ref is working at all. And it's impossible to assign to a struct with a const or immutable member, so the struct is not mutable. Why that's a problem here... My guess would be that it's a bug relating to copying from or assigning to const. If you declare this(this), you'll notice that it doesn't currently work with const, and if declared, this(this) would be called upon copying the struct. Still, something like auto t = Temp(); auto u = t; works with your definition of Temp, so just copying a non-mutable struct works as long as it doesn't declare this(this). It's probably treating auto ref as if it must be mutable or something like that, and Temp isn't. But I don't know what the problem is exactly. In any case, I would definitely advise that you _not_ create structs with const or immutable values, because you can never reassign to them, which causes all kinds of fun problems - including making it very hard to use them in arrays (_any_ place that would use Temp.init is stuck with Temp.init). It's generally better to just make the variables private and provide property functions for getting the variables but not provide any for setting them. That way, they're read-only and you can still re-assign the whole struct if need be. - Jonathan M davis
May 18 2011
parent Mehrdad <wfunction hotmail.com> writes:
On 5/18/2011 9:22 PM, Jonathan M Davis wrote:
 On 2011-05-18 20:55, %u wrote:
 Hi!

 Is this a bug, or is it intentional that this fails? I can't come up
 with any case where it would cause a problem, but the compiler doesn't
 like the fact that there's a const in the structure:

      struct Temp { const int a; int b; }

      auto ref foo(Temp* t) { return *t; } //Error

ref is working at all. And it's impossible to assign to a struct with a const or immutable member, so the struct is not mutable. Why that's a problem here... My guess would be that it's a bug relating to copying from or assigning to const. If you declare this(this), you'll notice that it doesn't currently work with const, and if declared, this(this) would be called upon copying the struct. Still, something like auto t = Temp(); auto u = t; works with your definition of Temp, so just copying a non-mutable struct works as long as it doesn't declare this(this). It's probably treating auto ref as if it must be mutable or something like that, and Temp isn't. But I don't know what the problem is exactly. In any case, I would definitely advise that you _not_ create structs with const or immutable values, because you can never reassign to them, which causes all kinds of fun problems - including making it very hard to use them in arrays (_any_ place that would use Temp.init is stuck with Temp.init). It's generally better to just make the variables private and provide property functions for getting the variables but not provide any for setting them. That way, they're read-only and you can still re-assign the whole struct if need be. - Jonathan M davis

By the way, it doesn't matter if I use auto or not. It does the same thing if I say "ref Temp". Interesting notes about postblit and everything, I'll keep those in mind, thanks!
May 18 2011
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-05-18 21:52, Mehrdad wrote:
 On 5/18/2011 9:22 PM, Jonathan M Davis wrote:
 On 2011-05-18 20:55, %u wrote:
 Hi!
 
 Is this a bug, or is it intentional that this fails? I can't come up
 with any case where it would cause a problem, but the compiler doesn't
 
 like the fact that there's a const in the structure:
      struct Temp { const int a; int b; }
      
      auto ref foo(Temp* t) { return *t; } //Error

As soon as you do *t, you're copying the value. As such, I don't know why the ref is working at all. And it's impossible to assign to a struct with a const or immutable member, so the struct is not mutable. Why that's a problem here... My guess would be that it's a bug relating to copying from or assigning to const. If you declare this(this), you'll notice that it doesn't currently work with const, and if declared, this(this) would be called upon copying the struct. Still, something like auto t = Temp(); auto u = t; works with your definition of Temp, so just copying a non-mutable struct works as long as it doesn't declare this(this). It's probably treating auto ref as if it must be mutable or something like that, and Temp isn't. But I don't know what the problem is exactly. In any case, I would definitely advise that you _not_ create structs with const or immutable values, because you can never reassign to them, which causes all kinds of fun problems - including making it very hard to use them in arrays (_any_ place that would use Temp.init is stuck with Temp.init). It's generally better to just make the variables private and provide property functions for getting the variables but not provide any for setting them. That way, they're read-only and you can still re-assign the whole struct if need be. - Jonathan M davis

By the way, it doesn't matter if I use auto or not. It does the same thing if I say "ref Temp". Interesting notes about postblit and everything, I'll keep those in mind, thanks!

If I wasn't clear enough, postblit is _supposed_ to work with const but currently doesn't. I wasn't saying that it won't ever, just that it's currently broken. http://d.puremagic.com/issues/show_bug.cgi?id=4867 - Jonathan M Davis
May 18 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 19 May 2011 00:22:42 -0400, Jonathan M Davis <jmdavisProg gmx.com>  
wrote:

 On 2011-05-18 20:55, %u wrote:
 Hi!

 Is this a bug, or is it intentional that this fails? I can't come up
 with any case where it would cause a problem, but the compiler doesn't
 like the fact that there's a const in the structure:

     struct Temp { const int a; int b; }

     auto ref foo(Temp* t) { return *t; } //Error

As soon as you do *t, you're copying the value.

That's not true, if it's ref, it just copies the reference. example: void foo(ref int i) { i = 5; } void main() { int i; int *p = &i; foo(*p); assert(i == 5); } To further drive home the point, this actually compiles: Temp foo(Temp* t) { return *t; } // no error There should be no restrictions on returning ref there, no matter what's inside Temp. Definitely a bug with the original, please file with bugzilla. -Steve
May 19 2011
prev sibling next sibling parent Muffin <mydog muffin.com> writes:
On 19/05/11 1:25 PM, %u wrote:
 Hi!

 Is this a bug, or is it intentional that this fails? I can't come up
 with any case where it would cause a problem, but the compiler doesn't
 like the fact that there's a const in the structure:

      struct Temp { const int a; int b; }

      auto ref foo(Temp* t) { return *t; } //Error

Just about all D type modifier keywords like const, shared, immutable and friends are completely broken semantically (i.e. TFBR**) and so there is very little hope that there will ever be a fix for these type system issue problems. (** TFBR Totally fucked beyond repair) Muffin's tip on the programming languages stocks (aka the PLS-2011 index) is to stay with your current investment in D2 for as long as the proprietary digitalmars implementation serves your purpose and to short sell otherwise. This is code for saying that the open source world is unlikely to ever provide any alternative to the currently available bug-ridden proprietary implementation of D2 which is itself, as a language specification, is riddled with bugs. Unfortunately there is no options market on D stock so that those of you that might be thinking of doing a PUT or CALL on D will be as bitterly disappointed as others that have tried to measure temperature in a vaccuum. xxx
May 19 2011
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
 On Thu, 19 May 2011 00:22:42 -0400, Jonathan M Davis <jmdavisProg gmx.com>
 
 wrote:
 On 2011-05-18 20:55, %u wrote:
 Hi!
 
 Is this a bug, or is it intentional that this fails? I can't come up
 with any case where it would cause a problem, but the compiler doesn't
 
 like the fact that there's a const in the structure:
 struct Temp { const int a; int b; }
 
 auto ref foo(Temp* t) { return *t; } //Error

As soon as you do *t, you're copying the value.

That's not true, if it's ref, it just copies the reference.

Well, I wasn't sure either way, and when I tested it by creating a postblit which printed, it printed. So, either I ran into a bug (quite possible), or I definitely misunderstood what was going on. - Jonathan M Davis
May 20 2011
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 20 May 2011 14:42:57 -0400, Jonathan M Davis <jmdavisProg gmx.com>  
wrote:

 On Thu, 19 May 2011 00:22:42 -0400, Jonathan M Davis  
 <jmdavisProg gmx.com>

 wrote:
 On 2011-05-18 20:55, %u wrote:
 Hi!

 Is this a bug, or is it intentional that this fails? I can't come up
 with any case where it would cause a problem, but the compiler  


 like the fact that there's a const in the structure:
 struct Temp { const int a; int b; }

 auto ref foo(Temp* t) { return *t; } //Error

As soon as you do *t, you're copying the value.

That's not true, if it's ref, it just copies the reference.

Well, I wasn't sure either way, and when I tested it by creating a postblit which printed, it printed. So, either I ran into a bug (quite possible), or I definitely misunderstood what was going on.

It depends on the example, if you are assigning the result to another variable, that is where the copy may occur. But if you do something like just take the address of the return, or pass it to something else that accepts ref, it should not call the postblit. Most certainly it's not within the function. -Steve
May 22 2011