digitalmars.D - immutable ctors, immutable members, and TDPL
- Steven Schveighoffer (42/42) May 23 2013 An interesting subject is being debated by some of the heavy hitters of ...
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (13/15) May 23 2013 Makes sense to me.
- Kenji Hara (6/20) May 23 2013 ic.com/issues/show_bug.cgi?id=3D9732>
- Jonathan M Davis (7/13) May 23 2013 Sounds sensible to me. I thought that that's how it worked anyway (clear...
- Dicebot (13/16) May 24 2013 Honestly, I don't know. It is quite a complex question for me to
- Dicebot (19/19) May 24 2013 Also one issue Don has brought my attention to is this snippet:
- deadalnix (3/5) May 24 2013 I think that module constructor are pain and suffering.
- TommiT (23/42) May 24 2013 That shouldn't compile because the non-shared module constructor
- Steven Schveighoffer (10/29) May 24 2013 This is not what I am looking to fix. Module ctors are very different
- Dicebot (7/11) May 24 2013 Oh, awesome! I did not know this. Well, than modules can somewhat
- TommiT (17/36) May 24 2013 I think immutable is something you cannot change. Also, the
An interesting subject is being debated by some of the heavy hitters of D on the latest beta on the announce NG. However, I have found that there is an inconsistency in TDPL that needs to be addressed. Forgetting the controversy currently brewing, we have the following current situation: struct S { immutable int x; this(int n) { x = n; int y = x; x = 0; } } This compiles, and shows that one can use an immutable, and then the immutable can be changed. This is no good, for obvious reasons. TDPL does not specifically address this issue (from what I can find via manual search), but it does talk about immutable constructors. It's prescription is for immutable constructors to be prohibited from reading any members, and prohibited from calling any functions with 'this' as a parameter. You are allowed to write the members as many times as you want. The idea is if you can't read the data, it can't be inconsistent. Note that this mechanism is not currently implemented in the compiler. I thought "great, let's apply the same technique here". But we have a problem. It would be too restrictive to say you can't call another member function or any other function in a *normal* ctor, just because you declared an immutable member. An immutable member is generally set once and then read from then on. I think both mechanisms (protecting immutable members in the ctor, and protecting all members in an immutable ctor) should be consistent. I think the 'no calling any functions' restriction is to restrictive to apply to normal ctors. My leaning is to re-define how immutable ctors and normal ctors that can initialize immutable members should behave. The immutability should be applied on the first read of the member, or calling a member function/passing 'this' somewhere. Some flow analysis is required for this, but we can be pretty conservative about it. There aren't too many use cases for this stuff anyway. What do you think? -Steve
May 23 2013
On 05/23/2013 08:41 AM, Steven Schveighoffer wrote:The immutability should be applied on the first read of the member,Makes sense to me. Not exactly the same issue but here is a related past discussion: http://forum.dlang.org/thread/khu6tl$q8o$1 digitalmars.com Quoting deadalnix: "Yes, in general, first assignment in a constructor should be considered as a declaration if the value is not read before. This allow for the mentioned optimization, but many very other important stuff as well, like the construction of immutable objects." And the enhancement request: http://d.puremagic.com/issues/show_bug.cgi?id=9732 Ali
May 23 2013
2013/5/24 Ali =C3=87ehreli <acehreli yahoo.com>On 05/23/2013 08:41 AM, Steven Schveighoffer wrote:um.dlang.org/thread/khu6tl$q8o$1 digitalmars.com>The immutability should be applied on the first read of the member,Makes sense to me. Not exactly the same issue but here is a related past discussion: http://forum.dlang.org/thread/**khu6tl$q8o$1 digitalmars.com<http://for=Quoting deadalnix: "Yes, in general, first assignment in a constructor should be considered as a declaration if the value is not read before. This allow for the mentioned optimization, but many very other important stuff as well, like the construction of immutable objects." And the enhancement request: http://d.puremagic.com/issues/**show_bug.cgi?id=3D9732<http://d.puremag=ic.com/issues/show_bug.cgi?id=3D9732> Enh 9732 is a dup of bug 9665? http://d.puremagic.com/issues/show_bug.cgi?id=3D9665 Kenji Hara
May 23 2013
On Thursday, May 23, 2013 11:41:29 Steven Schveighoffer wrote:An interesting subject is being debated by some of the heavy hitters of D on the latest beta on the announce NG. However, I have found that there is an inconsistency in TDPL that needs to be addressed. What do you think?Sounds sensible to me. I thought that that's how it worked anyway (clearly, I remember wrong - I should probably reread TDPL again one of these days soon, as I sometimes forget little tidbits like this). Sometimes, keeping all of this straight can be quite difficult when you start getting down to the nitty gritty details. - Jonathan M Davis
May 23 2013
On Thursday, 23 May 2013 at 15:41:32 UTC, Steven Schveighoffer wrote:... What do you think? -SteveHonestly, I don't know. It is quite a complex question for me to grasp at once. Only thing I have a string feeling about is that those two cases should be smiliar from the point of type system ("a" type is the same in constructed variables): struct S1 { int a; } struct S2 { immutable int a; } // ... auto s1 = immutable(S1)(); auto s2 = S2();
May 24 2013
Also one issue Don has brought my attention to is this snippet: // ----------------------------- immutable int x = 1; void main() { import std.stdio; writeln(x); } static this() { x = 42; } // (does not compile in 2.062 and won't in 2.063) // ------------------------------ Whatever approach is taken, I think it should be consistent with structs/classes in a sense that global variables are module members and module constructor is, well, constructor. But it looks very hard to do because "immutable" is implicitly "shared". Ideas?
May 24 2013
On Friday, 24 May 2013 at 08:47:40 UTC, Dicebot wrote:But it looks very hard to do because "immutable" is implicitly "shared". Ideas?I think that module constructor are pain and suffering. Anyway, this should not work if the ctor isn't shared.
May 24 2013
On Friday, 24 May 2013 at 08:47:40 UTC, Dicebot wrote:Also one issue Don has brought my attention to is this snippet: // ----------------------------- immutable int x = 1; void main() { import std.stdio; writeln(x); } static this() { x = 42; } // (does not compile in 2.062 and won't in 2.063) // ------------------------------ Whatever approach is taken, I think it should be consistent with structs/classes in a sense that global variables are module members and module constructor is, well, constructor. But it looks very hard to do because "immutable" is implicitly "shared". Ideas?That shouldn't compile because the non-shared module constructor writes to the shared variable x whenever a new thread starts with that module. But a better question is whether or not it should compile with a shared module constructor: immutable int x = 1; shared static this() { x = 42; } ... I don't know, but I think it should follow the same logic as with a non-static immutable member variable and a shared default constructor. Also, I think the following shouldn't compile due to a non-shared module constructor assigning to a shared variable (currently it does compile): immutable int x; static this() { import std.random; x = uniform(0, 100); }
May 24 2013
On Fri, 24 May 2013 04:47:38 -0400, Dicebot <m.strashun gmail.com> wrote:Also one issue Don has brought my attention to is this snippet: // ----------------------------- immutable int x = 1; void main() { import std.stdio; writeln(x); } static this() { x = 42; } // (does not compile in 2.062 and won't in 2.063) // ------------------------------ Whatever approach is taken, I think it should be consistent with structs/classes in a sense that global variables are module members and module constructor is, well, constructor.This is not what I am looking to fix. Module ctors are very different from struct ctors. Also, I specifically avoided the "pre-initialized" values, because that is outside the scope of this problem. We assume that for the sake of this argument, the value is uninitialized before the ctor is called.But it looks very hard to do because "immutable" is implicitly "shared". Ideas?Use shared static this, and the runtime should run your module ctors in dependency order. That is, another module that uses x must have this module's ctors run before it. -Steve
May 24 2013
On Friday, 24 May 2013 at 13:56:06 UTC, Steven Schveighoffer wrote:Use shared static this, and the runtime should run your module ctors in dependency order. That is, another module that uses x must have this module's ctors run before it. -SteveOh, awesome! I did not know this. Well, than modules can somewhat mimic struct/class behavior. They are not the same, but they try to look similar in other parts of language (for example, protection attributes) and (in my opinion!) should try the same here.
May 24 2013
On Thursday, 23 May 2013 at 15:41:32 UTC, Steven Schveighoffer wrote:An interesting subject is being debated by some of the heavy hitters of D on the latest beta on the announce NG. However, I have found that there is an inconsistency in TDPL that needs to be addressed. Forgetting the controversy currently brewing, we have the following current situation: struct S { immutable int x; this(int n) { x = n; int y = x; x = 0; } } This compiles, and shows that one can use an immutable, and then the immutable can be changed. This is no good, for obvious reasons.I think immutable is something you cannot change. Also, the reverse is true, if you can change something, it's not immutable. According to this logic, x is not immutable inside the scope of the constructor, because you *can* change it. Therefore it should be so that: import std.traits; struct S { immutable int x; this(int n) { static assert(isMutable!(typeof(x))); } } static assert(!isMutable!(typeof(S.init.x)));
May 24 2013