digitalmars.D - Postblit bug
- IgorStepanov (63/63) Oct 16 2014 I've found a strange postblit bug (or not a bug?):
- ketmar via Digitalmars-d (9/10) Oct 16 2014 it's just an anomaly. const postblit can do alot of things besides
- IgorStepanov (42/57) Oct 16 2014 I think, this is unexpected behaviour:
- ketmar via Digitalmars-d (6/7) Oct 16 2014 that's what i mean when i was talking about "unforeseen
- monarch_dodra (15/30) Oct 17 2014 AFAIK, Kenji has submitted a DIP, and has begun working on
- ketmar via Digitalmars-d (9/19) Oct 17 2014 const is a nice way to make sure that your data will not be modified.
- IgorStepanov (3/36) Oct 17 2014 What happends if we will ignore const/immutable modifier for
- ketmar via Digitalmars-d (4/6) Oct 17 2014 it will break "const promise". i.e. "const/immutable data is not really
- IgorStepanov (13/21) Oct 17 2014 It's just common words=)
- monarch_dodra (20/31) Oct 17 2014 That's way too many words for a single sentence for me to
- IgorStepanov (23/38) Oct 17 2014 Yes, I've understood.
- ketmar via Digitalmars-d (6/10) Oct 17 2014 `@disable this (this);` means that struct can't be copied. it's
- IgorStepanov (5/18) Oct 17 2014 This error will be raised if I try to copy the my struct. But I
- Marco Leise (18/38) Oct 17 2014 Consider that when passing a variable you can always remove
- monarch_dodra (4/40) Oct 18 2014 Unsure how that's relevant? This code looks wrong to me no matter
- Marco Leise (17/38) Oct 18 2014 This is the only relevant point to discuss. The act of
- ketmar via Digitalmars-d (12/35) Oct 17 2014 what if compiler knows 'v2' value at compile time? compiler can put
- Dmitry Olshansky (8/27) Oct 19 2014 s/can/need to/
- Marco Leise (9/9) Oct 17 2014 Am Fri, 17 Oct 2014 00:42:24 +0000
- Marco Leise (17/27) Oct 17 2014 Here is a reduced test case, that I wish I had before I
- Dmitry Olshansky (5/12) Oct 19 2014 Been there. Which implies that we can't have ref-counted const object
- Marco Leise (24/39) Oct 20 2014 mutable object
- "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= (6/9) Oct 20 2014 c++ shared_ptr is implemented as a separate object, an extra
- Jonathan M Davis via Digitalmars-d (16/30) Oct 20 2014 Yeah. Ref-counting and const do not mix in D. The ref-counting would vio...
- Dmitry Olshansky (5/36) Oct 21 2014 Awful.
- Jonathan M Davis via Digitalmars-d (12/21) Oct 21 2014 Yeah. Using it everywhere is definitely bad, but the question is then wh...
- H. S. Teoh via Digitalmars-d (29/45) Oct 20 2014 [...]
- "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= (6/10) Oct 20 2014 Please note that an important reason for using const is
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
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
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: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(); }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
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
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: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 muchCan 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 17 2014
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 muchconst 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
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:What happends if we will ignore const/immutable modifier for postblits? Is it create any holes?On Fri, 17 Oct 2014 00:42:24 +0000 IgorStepanov via Digitalmars-d <digitalmars-d puremagic.com> wrote: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 muchCan 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 17 2014
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
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: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.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".
Oct 17 2014
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
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:Yes, my english is so bad:)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?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
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
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: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.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".
Oct 17 2014
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
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>:D has it for primitives, such as pointers, slices...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 orelse 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
Am Sat, 18 Oct 2014 08:28:40 +0000 schrieb "monarch_dodra" <monarchdodra gmail.com>: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. -- MarcoConsider 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 orD 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
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: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.On Fri, 17 Oct 2014 14:41:36 +0000 IgorStepanov via Digitalmars-d <digitalmars-d puremagic.com>=20 wrote:=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 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".
Oct 17 2014
17-Oct-2014 18:18, monarch_dodra пишет:On Friday, 17 October 2014 at 00:55:25 UTC, ketmar via Digitalmars-d wrote: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 OlshanskyOn Fri, 17 Oct 2014 00:42:24 +0000 IgorStepanov via Digitalmars-d <digitalmars-d puremagic.com> wrote: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.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 19 2014
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
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
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
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:mutable objectAm 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=mmutable objectError: mutable method Lib.Sys.File.File.~this is not callable using a i=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 Marcohaha! 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).
Oct 20 2014
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" insteadc++ 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
On Sunday, October 19, 2014 22:33:32 Dmitry Olshansky via Digitalmars-d wrote:17-Oct-2014 16:42, Marco Leise пишет: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 DavisAm 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).
Oct 20 2014
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:They pretty much boil down to DO NOT use const everywhere, honestly.17-Oct-2014 16:42, Marco Leise пишет: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.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).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
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. 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 DavisYeah. 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.
Oct 21 2014
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
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