www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Postblit bug

reply "IgorStepanov" <wazar mail.ru> writes:
I've found a strange postblit bug (or not a bug?):

************************************

struct A
{
     this(this)
     {
     }
}

struct B
{
     A a;
}


struct C
{
     const B b;
}

void main()
{
     C c;
}

************************************

When I try to compile it, compiler raises the error: (Error: 
mutable method testaa2.B.__fieldPostBlit is not callable using a 
const object)

If I mark this(this) as const (BTW, is "this(this) const" a 
correct definition?) error still raises.
When I tried to reduce this code, I've found the next:

************************************

struct A
{
     this(this)
     {
     }
}

struct B
{
     const A a;
}


void main()
{
     B b;
}

************************************

Error: mutable method testaa2.A.__postblit is not callable using 
a const object

If I change this(this) to const, error has been lost.

************************************

struct A
{
     this(this) const
     {
     }
}

struct B
{
     const A a;
}


void main()
{
     B b;
}

************************************

Can someone comment this code? Should I think that it's a bug.
Oct 16 2014
next sibling parent reply ketmar via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Fri, 17 Oct 2014 00:42:24 +0000
IgorStepanov via Digitalmars-d <digitalmars-d puremagic.com> wrote:

 Can someone comment this code? Should I think that it's a bug.
it's just an anomaly. const postblit can do alot of things besides adjusting struct fields, and it's logical that compiler cannot call non-const methods for const objects. yet it's still on of those "unforseen consequences" that arises from conjunction of different features. i don't think that it's a bug, but i think that this must be discussed anyway, and then documented.
Oct 16 2014
next sibling parent reply "IgorStepanov" <wazar mail.ru> writes:
On Friday, 17 October 2014 at 00:55:25 UTC, ketmar via 
Digitalmars-d wrote:
 On Fri, 17 Oct 2014 00:42:24 +0000
 IgorStepanov via Digitalmars-d <digitalmars-d puremagic.com> 
 wrote:

 Can someone comment this code? Should I think that it's a bug.
it's just an anomaly. const postblit can do alot of things besides adjusting struct fields, and it's logical that compiler cannot call non-const methods for const objects. yet it's still on of those "unforseen consequences" that arises from conjunction of different features. i don't think that it's a bug, but i think that this must be discussed anyway, and then documented.
I think, this is unexpected behaviour: Compiler generates "__fieldPostBlit" for all structs, and call it when postblit is needed. In this example compiler generates something like the next code: struct A { this(this) { } } struct B { A a; void __fieldPostBlit() { a.__postblit(); //a has an explicit postblit } } struct C { const B b; void __fieldPostBlit() { b.__fieldPostBlit(); //Error: b is const } } void main() { C c; C c2 = c; //=> //memcpy(&c2, &c, C.sizeof) //c2.__fieldPostBlit(); } However, __postblit and __fieldPostBlit are always called for new object, thus it can neglect const guarantee and generate postblits like: void __fieldPostBlit() { (cast()b).__fieldPostBlit(); }
Oct 16 2014
parent ketmar via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Fri, 17 Oct 2014 01:30:51 +0000
IgorStepanov via Digitalmars-d <digitalmars-d puremagic.com> wrote:

 I think, this is unexpected behaviour:
that's what i mean when i was talking about "unforeseen consequences". ;-) when exactly "const" should be in effect? that is the question! ;-) let's wait what other people will say about this.
Oct 16 2014
prev sibling parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Friday, 17 October 2014 at 00:55:25 UTC, ketmar via 
Digitalmars-d wrote:
 On Fri, 17 Oct 2014 00:42:24 +0000
 IgorStepanov via Digitalmars-d <digitalmars-d puremagic.com> 
 wrote:

 Can someone comment this code? Should I think that it's a bug.
it's just an anomaly. const postblit can do alot of things besides adjusting struct fields, and it's logical that compiler cannot call non-const methods for const objects. yet it's still on of those "unforseen consequences" that arises from conjunction of different features. i don't think that it's a bug, but i think that this must be discussed anyway, and then documented.
AFAIK, Kenji has submitted a DIP, and has begun working on "fixing" the const/immutable/inout posblit issue. However, there are some very subtle corner cases, so (afaik) work is slow. To be honest, I think people use "const" way too much in D. It's *not* the C++ head const you can use anywhere. It's really just the "base" attribute between mutable and immutable data. In particular, due to the transitive nature of const, any time you use const it means "you can't modify this, or anything produced or acquired from this, ever". It's usually not what people think they are signing for... When it makes little sense to have your type as immutable, then I don't think you should bother much
Oct 17 2014
next sibling parent ketmar via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Fri, 17 Oct 2014 14:18:30 +0000
monarch_dodra via Digitalmars-d <digitalmars-d puremagic.com> wrote:

 To be honest, I think people use "const" way too much in D. It's=20
 *not* the C++ head const you can use anywhere. It's really just=20
 the "base" attribute between mutable and immutable data. In=20
 particular, due to the transitive nature of const, any time you=20
 use const it means "you can't modify this, or anything produced=20
 or acquired from this, ever". It's usually not what people think=20
 they are signing for...
=20
 When it makes little sense to have your type as immutable, then I=20
 don't think you should bother much
const is a nice way to make sure that your data will not be modified. it needs some time to adjust your head to the fact that "const is const all way down to the bytes", but then it's nice. yet i still missing c++-like const, which will not try to eat everything underneath. i.e. a way to tell compiler "this field cannot be modified, but the data it points to can be changed". this will let me to get rid of annoying getters.
Oct 17 2014
prev sibling next sibling parent reply "IgorStepanov" <wazar mail.ru> writes:
On Friday, 17 October 2014 at 14:18:31 UTC, monarch_dodra wrote:
 On Friday, 17 October 2014 at 00:55:25 UTC, ketmar via 
 Digitalmars-d wrote:
 On Fri, 17 Oct 2014 00:42:24 +0000
 IgorStepanov via Digitalmars-d <digitalmars-d puremagic.com> 
 wrote:

 Can someone comment this code? Should I think that it's a bug.
it's just an anomaly. const postblit can do alot of things besides adjusting struct fields, and it's logical that compiler cannot call non-const methods for const objects. yet it's still on of those "unforseen consequences" that arises from conjunction of different features. i don't think that it's a bug, but i think that this must be discussed anyway, and then documented.
AFAIK, Kenji has submitted a DIP, and has begun working on "fixing" the const/immutable/inout posblit issue. However, there are some very subtle corner cases, so (afaik) work is slow. To be honest, I think people use "const" way too much in D. It's *not* the C++ head const you can use anywhere. It's really just the "base" attribute between mutable and immutable data. In particular, due to the transitive nature of const, any time you use const it means "you can't modify this, or anything produced or acquired from this, ever". It's usually not what people think they are signing for... When it makes little sense to have your type as immutable, then I don't think you should bother much
What happends if we will ignore const/immutable modifier for postblits? Is it create any holes?
Oct 17 2014
parent reply ketmar via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Fri, 17 Oct 2014 14:41:36 +0000
IgorStepanov via Digitalmars-d <digitalmars-d puremagic.com> wrote:

 What happends if we will ignore const/immutable modifier for=20
 postblits? Is it create any holes?
it will break "const promise". i.e. "const/immutable data is not really immutable now, it can be modified".
Oct 17 2014
parent reply "IgorStepanov" <wazar mail.ru> writes:
On Friday, 17 October 2014 at 15:20:50 UTC, ketmar via 
Digitalmars-d wrote:
 On Fri, 17 Oct 2014 14:41:36 +0000
 IgorStepanov via Digitalmars-d <digitalmars-d puremagic.com> 
 wrote:

 What happends if we will ignore const/immutable modifier for 
 postblits? Is it create any holes?
it will break "const promise". i.e. "const/immutable data is not really immutable now, it can be modified".
It's just common words=) I meant that when postblit is called when new object is being creating and doesn't exists for user code. E.g. const S v1 = v2; Ok, v1 _will_ be const when it will be _created_. However postblit can think that object is mutable, because it called before the first accessing to the object from user code. Thus I ask about case when postblit may mutate a const object, which created before postblitted object and may been accessed from user code before this postblitting.
Oct 17 2014
next sibling parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Friday, 17 October 2014 at 16:19:47 UTC, IgorStepanov wrote:
 It's just common words=)
 I meant that when postblit is called when new object is being 
 creating and doesn't exists for user code.
 E.g.
 const S v1 = v2;
 Ok, v1 _will_ be const when it will be _created_.
 However postblit can think that object is mutable, because it 
 called before the first accessing to the object from user code.
 Thus I ask about case when postblit may mutate a const object, 
 which created before postblitted object and may been accessed 
 from user code before this postblitting.
That's way too many words for a single sentence for me to understand ;) But maybe this answers your question? import std.stdio; struct S { int* p; this(this) { ++*p; } } void main() { immutable i = 0; auto s1 = immutable(S)(&i); auto s2 = s1; assert(*&i == 0); }
Oct 17 2014
next sibling parent reply "IgorStepanov" <wazar mail.ru> writes:
On Friday, 17 October 2014 at 17:25:47 UTC, monarch_dodra wrote:
 On Friday, 17 October 2014 at 16:19:47 UTC, IgorStepanov wrote:
 It's just common words=)
 I meant that when postblit is called when new object is being 
 creating and doesn't exists for user code.
 E.g.
 const S v1 = v2;
 Ok, v1 _will_ be const when it will be _created_.
 However postblit can think that object is mutable, because it 
 called before the first accessing to the object from user code.
 Thus I ask about case when postblit may mutate a const object, 
 which created before postblitted object and may been accessed 
 from user code before this postblitting.
That's way too many words for a single sentence for me to understand ;)
Yes, my english is so bad:)
 But maybe this answers your question?
Yes, I've understood. TBH, I have got this error while I am working on new AA, and I want to fix it as posdible faster (one way or another). I have the next code: struct AssociativeArray(Key, Value) { ... struct Entry { Key key; Value value; ... } } If key or value is a const struct with postblit I have got a error. I don't need an any postblit in Entry. Thus I suggest another solution: Do not generate helper functions like __fieldPostBlit, if struct has a disabled this(this); Destroy it.
Oct 17 2014
parent reply ketmar via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Fri, 17 Oct 2014 19:39:39 +0000
IgorStepanov via Digitalmars-d <digitalmars-d puremagic.com> wrote:

 Thus I suggest another solution:
 Do not generate helper functions like __fieldPostBlit, if struct=20
 has a  disabled this(this);
 Destroy it.
` disable this (this);` means that struct can't be copied. it's irrelevant what code compiler generates behind our backs, it will not be executed anyway, 'cause compiler will complain: "Error: struct XXX is not copyable because it is annotated with disable".
Oct 17 2014
parent "IgorStepanov" <wazar mail.ru> writes:
On Friday, 17 October 2014 at 19:45:43 UTC, ketmar via 
Digitalmars-d wrote:
 On Fri, 17 Oct 2014 19:39:39 +0000
 IgorStepanov via Digitalmars-d <digitalmars-d puremagic.com> 
 wrote:

 Thus I suggest another solution:
 Do not generate helper functions like __fieldPostBlit, if 
 struct has a  disabled this(this);
 Destroy it.
` disable this (this);` means that struct can't be copied. it's irrelevant what code compiler generates behind our backs, it will not be executed anyway, 'cause compiler will complain: "Error: struct XXX is not copyable because it is annotated with disable".
This error will be raised if I try to copy the my struct. But I don't want to do it. Now the error raised when I define the struct.
Oct 17 2014
prev sibling parent reply Marco Leise <Marco.Leise gmx.de> writes:
Am Fri, 17 Oct 2014 17:25:46 +0000
schrieb "monarch_dodra" <monarchdodra gmail.com>:

 But maybe this answers your question?
 
 import std.stdio;
 
 struct S
 {
      int* p;
      this(this)
      {
          ++*p;
      }
 }
 
 void main()
 {
      immutable i = 0;
      auto s1 = immutable(S)(&i);
      auto s2 = s1;
      assert(*&i == 0);
 }
Consider that when passing a variable you can always remove top level const-ness because a copy is made. This holds for returns, parameters, assignments, ... Post-blit is no different. The issue as I see it, is that D doesn't have strong support for this notion of head-mutable or else it would work with this type during post-blit: struct S { immutable(int)* p; this(this) { ++*p; } } -- Marco
Oct 17 2014
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Saturday, 18 October 2014 at 06:43:28 UTC, Marco Leise wrote:
 Am Fri, 17 Oct 2014 17:25:46 +0000
 schrieb "monarch_dodra" <monarchdodra gmail.com>:

 But maybe this answers your question?
 
 import std.stdio;
 
 struct S
 {
      int* p;
      this(this)
      {
          ++*p;
      }
 }
 
 void main()
 {
      immutable i = 0;
      auto s1 = immutable(S)(&i);
      auto s2 = s1;
      assert(*&i == 0);
 }
Consider that when passing a variable you can always remove top level const-ness because a copy is made. This holds for returns, parameters, assignments, ... Post-blit is no different. The issue as I see it, is that D doesn't have strong support for this notion of head-mutable or
D has it for primitives, such as pointers, slices...
 else it would work with this type during post-blit:

 struct S
 {
      immutable(int)* p;
      this(this)
      {
          ++*p;
      }
 }
Unsure how that's relevant? This code looks wrong to me no matter how you look at it?
Oct 18 2014
parent Marco Leise <Marco.Leise gmx.de> writes:
Am Sat, 18 Oct 2014 08:28:40 +0000
schrieb "monarch_dodra" <monarchdodra gmail.com>:

 Consider that when passing a variable you can always remove
 top level const-ness because a copy is made. This holds for
 returns, parameters, assignments, ...
 Post-blit is no different. The issue as I see it, is that D
 doesn't have strong support for this notion of head-mutable or
D has it for primitives, such as pointers, slices...
 else it would work with this type during post-blit:

 struct S
 {
      immutable(int)* p;
      this(this)
      {
          ++*p;
      }
 }
Unsure how that's relevant? This code looks wrong to me no matter how you look at it?
This is the only relevant point to discuss. The act of blitting is a shallow copy. Hence while the copy is created there is no risk in modifying its bits. Hence the proposal to make make it mutable. But then you added deepness in form of a pointer to the structure that a shallow copy doesn't cover. So I concluded that the issue with making postblit mutable is that it removes immutable transitively through pointers, while for a shallow copy it must be shallow, too. That's just a basic observation. The imaginary struct I showed is the result of that. It only removes the top level immutable from the struct and would error out as you try modify the dereferenced immutable(int) while reassignment would work. -- Marco
Oct 18 2014
prev sibling parent ketmar via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Fri, 17 Oct 2014 16:19:46 +0000
IgorStepanov via Digitalmars-d <digitalmars-d puremagic.com> wrote:

 On Friday, 17 October 2014 at 15:20:50 UTC, ketmar via=20
 Digitalmars-d wrote:
 On Fri, 17 Oct 2014 14:41:36 +0000
 IgorStepanov via Digitalmars-d <digitalmars-d puremagic.com>=20
 wrote:

 What happends if we will ignore const/immutable modifier for=20
 postblits? Is it create any holes?
it will break "const promise". i.e. "const/immutable data is=20 not really immutable now, it can be modified".
=20 It's just common words=3D) I meant that when postblit is called when new object is being=20 creating and doesn't exists for user code. E.g. const S v1 =3D v2; Ok, v1 _will_ be const when it will be _created_. However postblit can think that object is mutable, because it=20 called before the first accessing to the object from user code. Thus I ask about case when postblit may mutate a const object,=20 which created before postblitted object and may been accessed=20 from user code before this postblitting.
what if compiler knows 'v2' value at compile time? compiler can put 'v1' in read-only section, and then postblitter will try to mutate 'v1'... ah, segfault. yet postblitter can do some other things, like, for example, registering 'v1' in some king of runtime storage, so it can't be optimized away. and then the programmer changes postblitter to mutate some fields. it all compiles fine and segfaults. const promises can't be dropped that easy. yes, the compiler doesn't do such things *now*, but it's ok for it to do it later and... kaboom! previously working code is not working anymore.
Oct 17 2014
prev sibling parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
17-Oct-2014 18:18, monarch_dodra пишет:
 On Friday, 17 October 2014 at 00:55:25 UTC, ketmar via Digitalmars-d wrote:
 On Fri, 17 Oct 2014 00:42:24 +0000
 IgorStepanov via Digitalmars-d <digitalmars-d puremagic.com> wrote:

 Can someone comment this code? Should I think that it's a bug.
it's just an anomaly. const postblit can do alot of things besides adjusting struct fields, and it's logical that compiler cannot call non-const methods for const objects. yet it's still on of those "unforseen consequences" that arises from conjunction of different features. i don't think that it's a bug, but i think that this must be discussed anyway, and then documented.
AFAIK, Kenji has submitted a DIP, and has begun working on "fixing" the const/immutable/inout posblit issue. However, there are some very subtle corner cases, so (afaik) work is slow. To be honest, I think people use "const" way too much in D. It's *not* the C++ head const you can use anywhere.
s/can/need to/ Which in case of const T& is a just a kind of mnemonic to accept both l-value and r-value. Anyhow I think we can probably extend final to mean single-assignment field (a-la Java). But the gain to semantic load factor is too small IMHO. -- Dmitry Olshansky
Oct 19 2014
prev sibling parent reply Marco Leise <Marco.Leise gmx.de> writes:
Am Fri, 17 Oct 2014 00:42:24 +0000
schrieb "IgorStepanov" <wazar mail.ru>:

OK, I've run into the same problem and there is no line
number, just:

Error: immutable method Lib.Sys.File.File.~this is not callable using a mutable
object
Error: mutable method Lib.Sys.File.File.~this is not callable using a immutable
object

haha! I should start from scratch.

-- 
Marco
Oct 17 2014
next sibling parent Marco Leise <Marco.Leise gmx.de> writes:
Am Fri, 17 Oct 2014 14:42:53 +0200
schrieb Marco Leise <Marco.Leise gmx.de>:

 Am Fri, 17 Oct 2014 00:42:24 +0000
 schrieb "IgorStepanov" <wazar mail.ru>:
 
 OK, I've run into the same problem and there is no line
 number, just:
 
 Error: immutable method Lib.Sys.File.File.~this is not callable using a
mutable object
 Error: mutable method Lib.Sys.File.File.~this is not callable using a
immutable object
 
 haha! I should start from scratch.
Here is a reduced test case, that I wish I had before I tried to make 1000 lines of code work with immutable: struct B { ~this() { /* some cleanup */ } } struct C { immutable B b; } void main() { C(immutable B()); } That's pretty much it. You cannot use compose a mutable struct out of immutable ones with dtors. -- Marco
Oct 17 2014
prev sibling parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
17-Oct-2014 16:42, Marco Leise пишет:
 Am Fri, 17 Oct 2014 00:42:24 +0000
 schrieb "IgorStepanov" <wazar mail.ru>:

 OK, I've run into the same problem and there is no line
 number, just:

 Error: immutable method Lib.Sys.File.File.~this is not callable using a
mutable object
 Error: mutable method Lib.Sys.File.File.~this is not callable using a
immutable object

 haha! I should start from scratch.
Been there. Which implies that we can't have ref-counted const object (or ref-count has to leave outside of immutable section). -- Dmitry Olshansky
Oct 19 2014
next sibling parent reply Marco Leise <Marco.Leise gmx.de> writes:
Am Sun, 19 Oct 2014 22:33:32 +0400
schrieb Dmitry Olshansky <dmitry.olsh gmail.com>:

 17-Oct-2014 16:42, Marco Leise =D0=BF=D0=B8=D1=88=D0=B5=D1=82:
 Am Fri, 17 Oct 2014 00:42:24 +0000
 schrieb "IgorStepanov" <wazar mail.ru>:

 OK, I've run into the same problem and there is no line
 number, just:

 Error: immutable method Lib.Sys.File.File.~this is not callable using a=
mutable object
 Error: mutable method Lib.Sys.File.File.~this is not callable using a i=
mmutable object
 haha! I should start from scratch.
=20 Been there. Which implies that we can't have ref-counted const object=20 (or ref-count has to leave outside of immutable section).
Moving the reference count out, means that as soon as you add another immutable layer around the object, it is in the way again. And at that point you turn to "looking it up" instead of pointing directly to the ref count. And then you wonder why it is impossible to use a pointer into an external table, but using a size_t as an array index to an external table is ok. And then you get flash backs of why it is likewise not possible to store mutable elements in an otherwise immutable container. Wait a second... what is immutable trying to achieve again? * Avoiding string copies, because we know no one can modify them. -> Ok, they have no reference count. * Allowing for pure functions where all parameters are immutable. -> Reference counting would be an impure action. * Act as shared at the same time. -> This is what I would like to make use of to avoid code duplication with shared/unshared methods. --=20 Marco
Oct 20 2014
parent "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Monday, 20 October 2014 at 09:01:15 UTC, Marco Leise wrote:
 Moving the reference count out, means that as soon as you add
 another immutable layer around the object, it is in the way
 again. And at that point you turn to "looking it up" instead
c++ shared_ptr is implemented as a separate object, an extra indirection, but this indirection also makes weak_ptr and ref-counting immutable possible. In performant code you only use shared_ptr to obtain ownership for a thread and raw pointers after that.
Oct 20 2014
prev sibling next sibling parent reply Jonathan M Davis via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Sunday, October 19, 2014 22:33:32 Dmitry Olshansky via Digitalmars-d wrote:
 17-Oct-2014 16:42, Marco Leise пишет:
 Am Fri, 17 Oct 2014 00:42:24 +0000
 schrieb "IgorStepanov" <wazar mail.ru>:

 OK, I've run into the same problem and there is no line
 number, just:

 Error: immutable method Lib.Sys.File.File.~this is not callable using a
 mutable object Error: mutable method Lib.Sys.File.File.~this is not
 callable using a immutable object

 haha! I should start from scratch.
Been there. Which implies that we can't have ref-counted const object (or ref-count has to leave outside of immutable section).
Yeah. Ref-counting and const do not mix in D. The ref-counting would violate const unless it's in a wrapper object or in a table somewhere. The wrapper fails as soon as it ends up being const (either directly or because it's inside of another object that's been marked const). And having a table somewhere outside the object or any wrapper makes it so that it doesn't work with pure. There are some serious, practical downsides to transitive, physical const like D has. And I don't think that any of us really know yet where the line is between where const should and shouldn't be used. Too often, the solution is to use it everywhere or to use it nowhere. And some folks violate it and try and make it more like logical const (e.g. as I understand it, vibe.d does ref-counting with const objects by casting away const and then mutating the ref-count, which is definitely a risky thing to be doing and arguably should never be done - but with the strong restrictions of D's const, it's exactly the sort of thing that people are going to be tempted to do). - Jonathan m Davis
Oct 20 2014
parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
21-Oct-2014 05:38, Jonathan M Davis via Digitalmars-d пишет:
 On Sunday, October 19, 2014 22:33:32 Dmitry Olshansky via Digitalmars-d wrote:
 17-Oct-2014 16:42, Marco Leise пишет:
 Am Fri, 17 Oct 2014 00:42:24 +0000
 schrieb "IgorStepanov" <wazar mail.ru>:

 OK, I've run into the same problem and there is no line
 number, just:

 Error: immutable method Lib.Sys.File.File.~this is not callable using a
 mutable object Error: mutable method Lib.Sys.File.File.~this is not
 callable using a immutable object

 haha! I should start from scratch.
Been there. Which implies that we can't have ref-counted const object (or ref-count has to leave outside of immutable section).
Yeah. Ref-counting and const do not mix in D. The ref-counting would violate const unless it's in a wrapper object or in a table somewhere. The wrapper fails as soon as it ends up being const (either directly or because it's inside of another object that's been marked const). And having a table somewhere outside the object or any wrapper makes it so that it doesn't work with pure. There are some serious, practical downsides to transitive, physical const like D has.
They pretty much boil down to DO NOT use const everywhere, honestly.
 And I don't think that any of us really know yet where the
 line is between where const should and shouldn't be used. Too often, the
 solution is to use it everywhere or to use it nowhere. And some folks violate
 it and try and make it more like logical const (e.g. as I understand it,
 vibe.d does ref-counting with const objects by casting away const and then
 mutating the ref-count, which is definitely a risky thing to be doing and
 arguably should never be done - but with the strong restrictions of D's const,
 it's exactly the sort of thing that people are going to be tempted to do).
Awful. -- Dmitry Olshansky
Oct 21 2014
parent Jonathan M Davis via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Tuesday, October 21, 2014 22:26:26 Dmitry Olshansky via Digitalmars-d 
wrote:
 21-Oct-2014 05:38, Jonathan M Davis via Digitalmars-d пишет:
 Yeah. Ref-counting and const do not mix in D. The ref-counting would
 violate const unless it's in a wrapper object or in a table somewhere.
 The wrapper fails as soon as it ends up being const (either directly or
 because it's inside of another object that's been marked const). And
 having a table somewhere outside the object or any wrapper makes it so
 that it doesn't work with pure. There are some serious, practical
 downsides to transitive, physical const like D has.
They pretty much boil down to DO NOT use const everywhere, honestly.
Yeah. Using it everywhere is definitely bad, but the question is then where you _should_ use it. It's quite useful for avoiding code duplication when immutable is involved (though templatizing everything fixes that too), and there are definitely times when the guarantee that something isn't going to mutated is useful (even if it's only for being able reason about the code well). So, abandoning const entirely seems like a bad idea, but you have to be very careful about where you do use it, or you paint yourself into a corner pretty quickly. pure can do the same thing, but it's nowhere near as bad in that respect. - Jonathan M Davis
Oct 21 2014
prev sibling parent reply "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Mon, Oct 20, 2014 at 06:38:11PM -0700, Jonathan M Davis via Digitalmars-d
wrote:
[...]
 Yeah. Ref-counting and const do not mix in D. The ref-counting would
 violate const unless it's in a wrapper object or in a table somewhere.
 The wrapper fails as soon as it ends up being const (either directly
 or because it's inside of another object that's been marked const).
 And having a table somewhere outside the object or any wrapper makes
 it so that it doesn't work with pure. There are some serious,
 practical downsides to transitive, physical const like D has. And I
 don't think that any of us really know yet where the line is between
 where const should and shouldn't be used. Too often, the solution is
 to use it everywhere or to use it nowhere. And some folks violate it
 and try and make it more like logical const (e.g. as I understand it,
 vibe.d does ref-counting with const objects by casting away const and
 then mutating the ref-count, which is definitely a risky thing to be
 doing and arguably should never be done - but with the strong
 restrictions of D's const, it's exactly the sort of thing that people
 are going to be tempted to do).
[...] I've run into this before, and I've been thinking about whether it would help for the language somehow to support tail-const of wrapper types, such that: /* Note: this is hypothetical syntax */ tail_const(Wrapper!T) x; gets translated to: Wrapper!(const(T)) x; While this can already be manually done now, having it as a keyword (or otherwise dedicated syntax) allows things to work transparently, so that generic code never has to worry about what kind of wrapper(s) may be present in a user-passed object. If used with a reference type, tail_const behaves like Rebindable. If used with a non-template, non-reference, tail_const just "aliases" itself into plain old const, so it would behave sorta like logical const, except that it's actually checkable: the wrapper template can use the resulting physical const type to hold the wrapped type, thus maintaining D's physical const guarantees, while leaving other parts of the wrapper mutable so that it can implement things like reference counting, caching, etc.. Of course, this idea needs to be fleshed out more before it's actually usable, but it's something that has occurred to me multiple times, and may thus represent a pattern that could solve the logical vs. physical const dilemma in D. T -- To err is human; to forgive is not our policy. -- Samuel Adler
Oct 20 2014
parent "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Tuesday, 21 October 2014 at 01:50:55 UTC, H. S. Teoh via 
Digitalmars-d wrote:
 	/* Note: this is hypothetical syntax */
 	tail_const(Wrapper!T) x;

 gets translated to:

 	Wrapper!(const(T)) x;
Please note that an important reason for using const is multi-threading where you may want to accept multiple readers and one writer. So IMO non-const parts of an object should stay on a different cache lines from the const parts…
Oct 20 2014