May 16, 2013
2013/5/16 Михаил Страшун <m.strashun@gmail.com>

> Wall of text incoming.
>
> First. I'd like to remind to several important properties of D structs:
>
> * They have both compile-time initialization and run-time one. First is T.init, second is T(...). Needing both is a perfectly valid need from the programmer, especially with generic code in question.
>

T.init is statically known constant default value of a type and T(..)
expression when applied to
the struct can be a struct literal, constructor invocation or an opCall.

Default value (T.init) is same both in compile time and runtime unless you
deliberatly hack
generated object file at runtime. But this has nothing to do with
"compile-time initialization" and "runtime initialization".


>
> * structs always have constructors. So this snippet is wrong:
> >   struct S
> >   {
> >       immutable int c = 123; // This should be static, compiler issues
> error
> >       // No constructor
> >   }
> In fact, S has constructor. All structs have constructor with parameter count that matches member field count. And judging only by S definition you can't ever possibly say if "c" will be the same in all S instances or not.
>

No. This S does not have a constructor. Expressions with "parameter count
that mathces
member field count" is struct literal and it has nothing to do with
implicit constructor generation
or calling any function. Please check things before you type.


May 16, 2013
On Thu, May 16, 2013 at 1:02 PM, Maxim Fomin <maxim@maxim-fomin.ru> wrote:
>
>
>
> 2013/5/16 Михаил Страшун <m.strashun@gmail.com>
>>
>> Wall of text incoming.
>>
>> First. I'd like to remind to several important properties of D structs:
>>
>> * They have both compile-time initialization and run-time one. First is T.init, second is T(...). Needing both is a perfectly valid need from the programmer, especially with generic code in question.
>
>
> T.init is statically known constant default value of a type and T(..)
> expression when applied to
> the struct can be a struct literal, constructor invocation or an opCall.
>
> Default value (T.init) is same both in compile time and runtime unless you
> deliberatly hack
> generated object file at runtime. But this has nothing to do with
> "compile-time initialization" and "runtime initialization".

You have just said the very same but in different words. What is important that you need both "const x = ..." syntax to change T.init and ability to change it in literal/constructor when struct is created at run-time.

>> * structs always have constructors. So this snippet is wrong:
>> >   struct S
>> >   {
>> >       immutable int c = 123; // This should be static, compiler issues
>> > error
>> >       // No constructor
>> >   }
>> In fact, S has constructor. All structs have constructor with parameter count that matches member field count. And judging only by S definition you can't ever possibly say if "c" will be the same in all S instances or not.
>
>
> No. This S does not have a constructor. Expressions with "parameter count
> that mathces
> member field count" is struct literal and it has nothing to do with implicit
> constructor generation
> or calling any function. Please check things before you type.

Difference does not matter in this context (I apologize for bad
wording though). What I am saying, you can never say that immutable
field value will always stay the same even in absence of explicit
constructors. What you say does not contradict it.
_______________________________________________
dmd-beta mailing list
dmd-beta@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-beta
May 17, 2013
15-May-2013 09:05, Walter Bright пишет:
> http://ftp.digitalmars.com/dmd2beta.zip
>
> I think it's time we officially started the beta process. Yes, I need to start a 2.063 branch.

I understand that Phobos bug fixes are lower priority.
Still I believe we shouldn't ship it without at least
these fixes reviewed and pulled in:

Long standing bug 5524, std.algorithm remove with unstable policy
(might need review but passes, been there for 3 months(!))
https://github.com/D-Programming-Language/phobos/pull/1162

Bug in std.regex back-looper and consequently \b (reviewed, need somebody to merge):
https://github.com/D-Programming-Language/phobos/pull/1273

And this one on BigInt (probably needs Don to take a look):
https://github.com/D-Programming-Language/phobos/pull/1231

P.S. I suggest to make a pass over pulls to seek out other pure bugfix pulls.
All in all ~70 open pulls for Phobos? Now DMD has only 64 ... :)

-- 
Dmitry Olshansky

_______________________________________________
dmd-beta mailing list
dmd-beta@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-beta
May 16, 2013
On 5/16/13 3:40 PM, Dmitry Olshansky wrote:
> 15-May-2013 09:05, Walter Bright пишет:
>> http://ftp.digitalmars.com/dmd2beta.zip
>>
>> I think it's time we officially started the beta process. Yes, I need
>> to start a 2.063 branch.
>
> I understand that Phobos bug fixes are lower priority.

Not sure where you got that understanding, but it's not true.

_______________________________________________
dmd-beta mailing list
dmd-beta@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-beta
May 17, 2013
17.05.2013, в 3:46, Brad Roberts <braddr@puremagic.com> написал(а):

> On 5/16/13 3:40 PM, Dmitry Olshansky wrote:
>> 15-May-2013 09:05, Walter Bright пишет:
>>> http://ftp.digitalmars.com/dmd2beta.zip
>>> 
>>> I think it's time we officially started the beta process. Yes, I need to start a 2.063 branch.
>> 
>> I understand that Phobos bug fixes are lower priority.
> 
> Not sure where you got that understanding, but it's not true.
> 

This was intentionaly a bit provocative, it may be my impression only. Got to a definte no, it isn't.

What leads me to this conclusion is that it seems that compared to dmd, Phobos lacks the focus of prioritizing bug fixes. Or we just had a long downtime w.r.t. pulling fixes.

> _______________________________________________
> dmd-beta mailing list
> dmd-beta@puremagic.com
> http://lists.puremagic.com/mailman/listinfo/dmd-beta
_______________________________________________
dmd-beta mailing list
dmd-beta@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-beta
May 17, 2013
On Friday, May 17, 2013 09:18:34 Dmitry Olshansky wrote:
> 17.05.2013, в 3:46, Brad Roberts <braddr@puremagic.com> написал(а):
> > On 5/16/13 3:40 PM, Dmitry Olshansky wrote:
> >> 15-May-2013 09:05, Walter Bright пишет:
> >>> http://ftp.digitalmars.com/dmd2beta.zip
> >>> 
> >>> I think it's time we officially started the beta process. Yes, I need to start a 2.063 branch.
> >> 
> >> I understand that Phobos bug fixes are lower priority.
> > 
> > Not sure where you got that understanding, but it's not true.
> 
> This was intentionaly a bit provocative, it may be my impression only. Got to a definte no, it isn't.
> 
> What leads me to this conclusion is that it seems that compared to dmd, Phobos lacks the focus of prioritizing bug fixes. Or we just had a long downtime w.r.t. pulling fixes.

Well, compiler bugs usually get more attention (and usually do have worse consequences), so in that sense, they end up being higher priority, but I suspect that the problem with Phobos pull requests is simply that those of us with commit rights are not particularly consistent in merging stuff (likely primarily being driven by time constraints). The compiler devs have improved considerably on that count (particularly once people other than Walter had commit rights), so they now at least give the appearance of doing a better job at merging stuff in (especially if it's high priority).

- Jonathan M Davis
_______________________________________________
dmd-beta mailing list
dmd-beta@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-beta
May 17, 2013
> * structs always have constructors. So this snippet is wrong:
> >   struct S
> >   {
> >       immutable int c = 123; // This should be static, compiler issues
> error
> >       // No constructor
> >   }
> In fact, S has constructor. All structs have constructor with parameter count that matches member field count. And judging only by S definition you can't ever possibly say if "c" will be the same in all S instances or not.
>

You're talking about a struct static initializer. That is not the same as a constructor.

> Second, it is consistent because it stays the same both for
struct members and local variables. This is much more important than prohibiting something based on use case approach.

It is inconsistent with module variables.

const int x = 7;
static this()
{
   x = 5;
}

You cannot change the value of a local-scope const variable, once it has been initialized.

You cannot change the value of a module-scope const variable, once it has been initialized. Not even in a constructor.

Up to now:
You cannot change the value of a struct member const variable, once it has
been initialized. Not even in a constructor.

I think the consistency argument acts AGAINST this new behaviour.

And so I strongly disagree with this:

* They have both compile-time initialization and run-time one. First
> is T.init, second is T(...). Needing both is a perfectly valid need from the programmer, especially with generic code in question.
>

I think that the reason that having both an initializer and a constructor
appears desirable, is actually as a workaround for the lack of struct
default constructors.
If we really need a solution for that, we should consider doing something
like allowing struct default constructors, but requiring them to be
CTFEable.
Rather than allowing const members to be initialized twice, which is
confusing for both the programmer and the compiler to understand. (Both
compiler and programmer would need to inspect all of the code looking for a
possible constructor, in order to know if a const initializer is
meaningful).

But in any case, the situation is that with this beta, code which used to
declare a manifest constant in a struct, now allocates memory in each
struct, and each copy of that memory contains the same value. Those two
behaviours have nothing in common, so *all* existing cases will need to be
modified. (basically by adding 'static' to the front of each one).
We can't silently break code in this way.

Therefore:
We should make non-static const/immutable members with initializers into an
error in this release. Then all existing cases will have 'static'
explicitly added to them. Up to now it's been implicitly added, which is an
unnecessary feature and somewhat surprising behaviour.

What we actually want the behaviour to be in the long term can be discussed later.


May 17, 2013
On Fri, May 17, 2013 at 9:54 AM, Don Clugston <dclugston@gmail.com> wrote:

> ...
> What we actually want the behaviour to be in the long term can be
> discussed later.
>
> +1


May 17, 2013
On Fri, May 17, 2013 at 10:54 AM, Don Clugston <dclugston@gmail.com> wrote:
> You're talking about a struct static initializer. That is not the same as a constructor.

Yes, I have already been corrected and sorry for choosing wrong term. What essential though is that both constructor and struct literal initializer allow to initialize immutable struct members.

> You cannot change the value of a local-scope const variable, once it has been initialized.

Because there is no constructor-like entity for local scope.

>
> You cannot change the value of a module-scope const variable, once it has been initialized. Not even in a constructor.

If this was not changed together with struct/class changes, it sounds like yet another bug.

> Up to now:
> You cannot change the value of a struct member const variable, once it has
> been initialized. Not even in a constructor.
>
> I think the consistency argument acts AGAINST this new behaviour.

Consistency is not about behavior of single feature (const initialized variable), it is more about what place it takes in the overall type system. If const variable behaves like this, it is no different from "enum" and you have two ways to do the same thing without a single way to do what I am expecting from const variable.

>> * They have both compile-time initialization and run-time one. First is T.init, second is T(...). Needing both is a perfectly valid need from the programmer, especially with generic code in question.
>
>
> I think that the reason that having both an initializer and a constructor
> appears desirable, is actually as a workaround for the lack of struct
> default constructors.
> If we really need a solution for that, we should consider doing something
> like allowing struct default constructors, but requiring them to be
> CTFEable.

And what if you want to have BOTH default CTFE initialization and additional initialization based on some run-time data?

> Rather than allowing const members to be initialized twice, which is confusing for both the programmer and the compiler to understand. (Both compiler and programmer would need to inspect all of the code looking for a possible constructor, in order to know if a const initializer is meaningful).

It is not more confusing than the fact that immutable is mutable in a constructor. Actually, most confusing part here is that this bug was not fixed 20-30 compiler release ago, it never made sense.

> But in any case, the situation is that with this beta, code which used to
> declare a manifest constant in a struct, now allocates memory in each
> struct, and each copy of that memory contains the same value. Those two
> behaviours have nothing in common, so *all* existing cases will need to be
> modified. (basically by adding 'static' to the front of each one).
> We can't silently break code in this way.

Yes and I fully agree that this is a horrible breaking change. That is why I suggested to use "-transition=XXX" as a default approach to simplify such situations. And eternal gratitude goes to Kenji who has actually implemented it. I am completely on your side when it comes to silent breakages, only thing I argue is that old behavior was right.

> Therefore:
> We should make non-static const/immutable members with initializers into an
> error in this release. Then all existing cases will have 'static' explicitly
> added to them. Up to now it's been implicitly added, which is an unnecessary
> feature and somewhat surprising behaviour.

What do you find unacceptable/inconvenient in "-transition=XXX" approach?
_______________________________________________
dmd-beta mailing list
dmd-beta@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-beta

May 17, 2013
> If const variable behaves like this, it is no different from
"enum" and you have two ways to do the same thing without a single way to do what I am expecting from const variable.

No!!!!! You've got a fundamental misunderstanding here. Both those statements are wrong.

A const member in a struct, that does not have an initializer, has ALWAYS
been stored in the struct (even in D1).
The issue is what to do with const members that have initializers.
Historically, they've been treated as manifest constants. There's a good
argument that that is wrong.
But treating them as a value stored in every struct, where every value is
the same, is even worse.
I think we just have to make it illegal to provide an initializer on a
const member.

> And what if you want to have BOTH default CTFE initialization and
additional initialization based on some run-time data?

Then you have a flaw in your thinking. That doesn't make sense.
And, I still do not believe that there is a single valid use case for the
new behaviour.

Here's the reason:
If you can provide an initializer for a struct member, that is the same for
all instances of that struct, and you will never change that member, it
shouldn't be a member of the struct in the first place. It should be static
const or an enum value.
If however you're going to change the member in the constructor, based on a
runtime value, the initializer is meaningless and shouldn't have existed.


> What do you find unacceptable/inconvenient in "-transition=XXX" approach?

Because 100% of existing cases must be changed.

This isn't even like static variables becoming shared by default, where
some of the cases needed to change to __gshared but the rest were OK with
becoming shared.
Every existing usage becomes a bug. There are no exceptions.



On 17 May 2013 10:29, Михаил Страшун <m.strashun@gmail.com> wrote:

> On Fri, May 17, 2013 at 10:54 AM, Don Clugston <dclugston@gmail.com> wrote:
> > You're talking about a struct static initializer. That is not the same
> as a
> > constructor.
>
> Yes, I have already been corrected and sorry for choosing wrong term. What essential though is that both constructor and struct literal initializer allow to initialize immutable struct members.
>
> > You cannot change the value of a local-scope const variable, once it has been initialized.
>
> Because there is no constructor-like entity for local scope.
>
> >
> > You cannot change the value of a module-scope const variable, once it has been initialized. Not even in a constructor.
>
> If this was not changed together with struct/class changes, it sounds like yet another bug.
>
> > Up to now:
> > You cannot change the value of a struct member const variable, once it
> has
> > been initialized. Not even in a constructor.
> >
> > I think the consistency argument acts AGAINST this new behaviour.
>
> Consistency is not about behavior of single feature (const initialized variable), it is more about what place it takes in the overall type system. If const variable behaves like this, it is no different from "enum" and you have two ways to do the same thing without a single way to do what I am expecting from const variable.
>
> >> * They have both compile-time initialization and run-time one. First is T.init, second is T(...). Needing both is a perfectly valid need from the programmer, especially with generic code in question.
> >
> >
> > I think that the reason that having both an initializer and a constructor
> > appears desirable, is actually as a workaround for the lack of struct
> > default constructors.
> > If we really need a solution for that, we should consider doing something
> > like allowing struct default constructors, but requiring them to be
> > CTFEable.
>
> And what if you want to have BOTH default CTFE initialization and additional initialization based on some run-time data?
>
> > Rather than allowing const members to be initialized twice, which is confusing for both the programmer and the compiler to understand. (Both compiler and programmer would need to inspect all of the code looking
> for a
> > possible constructor, in order to know if a const initializer is meaningful).
>
> It is not more confusing than the fact that immutable is mutable in a constructor. Actually, most confusing part here is that this bug was not fixed 20-30 compiler release ago, it never made sense.
>
> > But in any case, the situation is that with this beta, code which used to declare a manifest constant in a struct, now allocates memory in each struct, and each copy of that memory contains the same value. Those two behaviours have nothing in common, so *all* existing cases will need to
> be
> > modified. (basically by adding 'static' to the front of each one). We can't silently break code in this way.
>
> Yes and I fully agree that this is a horrible breaking change. That is why I suggested to use "-transition=XXX" as a default approach to simplify such situations. And eternal gratitude goes to Kenji who has actually implemented it. I am completely on your side when it comes to silent breakages, only thing I argue is that old behavior was right.
>
> > Therefore:
> > We should make non-static const/immutable members with initializers into
> an
> > error in this release. Then all existing cases will have 'static'
> explicitly
> > added to them. Up to now it's been implicitly added, which is an
> unnecessary
> > feature and somewhat surprising behaviour.
>
> What do you find unacceptable/inconvenient in "-transition=XXX" approach?
> _______________________________________________
> dmd-beta mailing list
> dmd-beta@puremagic.com
> http://lists.puremagic.com/mailman/listinfo/dmd-beta
>