dmd 2.063 beta 5
Steven Schveighoffer
schveiguy at yahoo.com
Thu May 23 14:06:57 PDT 2013
On Thu, 23 May 2013 16:42:30 -0400, Artur Skawina <art.08.09 at gmail.com>
wrote:
> On 05/23/13 18:26, Steven Schveighoffer wrote:
>> On Thu, 23 May 2013 11:36:00 -0400, Artur Skawina <art.08.09 at gmail.com>
>> wrote:
>>
>>> If it wasn't clear - it is about the _language_, not what some compiler
>>> currently happens to do. Being able to mutate /initialized/ immutables
>>> is a bad idea. IOW you should not be able to modify 'Packet.type'
>>> above.
>>
>> The immutable isn't initialized. The memory it happens to be using
>> before initialization happens to have the '7' bit pattern in it.
>>
>> Once it is initialized, I agree it should be immutable from that point
>> on.
>
> It's all about the definition. Again, I'll point out that the code that
> we're
> talking about here *can not* exist right now - until now the compiler
> has not
> allowed mutation.
compiles:
struct S
{
const int x;
this(int n)
{
x = n;
}
}
> So this is about a /change/ to the language, and isn't really
> related to fixing that implicit-static bug - it's just that once that
> change
> is made it then becomes possible to support the in-ctor re-initialization
> of immutable fields. Which isn't really all that useful, but carries a
> cost.
The change to the language allows something that wasn't easily allowed
before -- defining the pre-initialization bit pattern that is blitted to
the const member. Until now, the only way to have a const member that is
ctor-initialized is to make it have the default bit pattern for that type.
Hm... I just figured out something interesting. We can mimic the "new"
behavior in old compilers by creating a type that has a different default
initialization:
import std.stdio;
struct myInt
{
int x = 7;
}
struct S
{
const myInt m;
this(int n)
{
m.x = n;
}
}
void main()
{
S s;
auto s2 = S(5);
writefln("%d %d", s.m.x, s2.m.x");
}
Output on 2.061:
7 5
>>> Keep in mind that modifying Packet.type is illegal /right now/. Even
>>> from
>>> a ctor or static-ctor. This does not need to change when such fields
>>> are
>>> no longer always implicitly static. While allowing re-initialization
>>> of immutables from a ctor is possible, it does not really give you
>>> much,
>>> while weakening const. (eg by making CT evaluation of such fields
>>> impossible).
>>
>> That's an issue of where Packet.type lives. It doesn't live inside an
>> instance right now, in the new version it does.
>>
>> If Packet.type is not given an initializer, it's inside the instance
>> and it (correctly IMO) can be modified inside a ctor until it is used.
>>
>> These rules are perfectly consistent.
>>
>> I don't see how they make CT evaluation impossible.
>
> The old way meant that the value was statically known and could be
> accessed at CT.
And it still can, as long as you *properly* declare it as static (as it
should have been).
> Allowing ctors to modify the fields means that the compiler can not make
> any
> assumptions about the value. [1] Which affects CT and constant
> folding/propagation
> etc.
And it shouldn't be able to on a value that is different for every
instance, but constant for that instance. However, it can make
assumptions based on the fact that it can't change. For example:
writeln(x.constmember);
....
auto n = x.constmember + 5; // can assume constmember is the same as
before.
> For example you couldn't then do this:
>
> struct Packet(uint TY) { /*...*/immutable uint type=TY; immutable ubyte
> len=PLen(TY); /*...*/ }
> auto PProcess(PT)(PT* p) { static if (p.type<128) if (p.type==42)
> sendp(p, p.len*4); }
static if(TY < 128) if(TY == 42) ....
> Even w/o the static-if it would be much less efficient. Yes, there are
> other
> ways to achieve a similar effect, but they are significantly more
> complicated.
No, you are using the WRONG tool for the job. If you want to make
compile-time decisions, don't use run-time constants.
> The most conservative approach is to initially disallow mutation from
> ctors - this
> restriction can always be lifted later and doing so does not affect any
> existing
> program.
> Treating 'const' differently from 'immutable' is also a possibility, and
> could
> be a future option.
It's already allowed. Disallowing it would break code.
> Then there's the issue of 'immutable one=1;' being very misleading; it
> certainly
> would be misinterpreted often enough (by assuming that ODR applies here).
use enum for compile-time constants, or static if you need an addressable
constant. There is no loss of functionality here, only gains.
> [1] BTW, I'm wondering if these changes also affect module-level
> const/immutable
> members... No DMD here to test, though.
Of course not, there is no changing of what is const and what is not. All
that is changing is whether a default-initialized member becomes a static
member or not. The original rules as to when a const value can be
initialized still apply.
-Steve
More information about the Digitalmars-d-announce
mailing list