www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - DIP 1004 Preliminary Review Round 1

reply Mike Parker <aldacron gmail.com> writes:
DIP 1004 is titled "Inherited Constructors.

https://github.com/dlang/DIPs/blob/master/DIPs/DIP1004.md

All review-related feedback on and discussion of the DIP should 
occur in this thread. Due to DConf taking place during the review 
period, the period will be extended by a week. The review period 
will end at 11:59 PM ET on May 22 (3:59 AM GMT May 23), or when I 
make a post declaring it complete.

At the end of Round 1, if further review is deemed necessary, the 
DIP will be scheduled for another round. Otherwise, it will be 
queued for the formal review and evaluation by the language 
authors.

Thanks in advance to all who participate.

Destroy!
May 01
next sibling parent reply Basile B. <b2.temp gmx.com> writes:
On Monday, 1 May 2017 at 14:55:28 UTC, Mike Parker wrote:
 DIP 1004 is titled "Inherited Constructors. [...]
 All review-related feedback on and discussion of the DIP should 
 occur in this thread. [...]
 Destroy!
An obvious omission in the syntax variations [1] - alias this() = super.this(); or - alias this = super.this; Why ? 1/ AliasDeclarationY [2] is the most modern and most used alias syntax nowadays. 2/ it's less confusing with the "alias this" that's used for static inheritance. [1] https://github.com/dlang/DIPs/blob/master/DIPs/DIP1004.md#syntax-variations [2] https://dlang.org/spec/declaration.html#AliasDeclarationY
May 01
next sibling parent Basile B. <b2.temp gmx.com> writes:
On Monday, 1 May 2017 at 15:33:47 UTC, Basile B. wrote:
 On Monday, 1 May 2017 at 14:55:28 UTC, Mike Parker wrote:
 DIP 1004 is titled "Inherited Constructors. [...]
 All review-related feedback on and discussion of the DIP 
 should occur in this thread. [...]
 Destroy!
An obvious omission in the syntax variations [1] - alias this() = super.this(); or - alias this = super.this;
or even alias this() = Base.this() with Base the identifier for the base class, which is already the syntax for virtual methods ;)
May 01
prev sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On Monday, 1 May 2017 at 15:33:47 UTC, Basile B. wrote:
 On Monday, 1 May 2017 at 14:55:28 UTC, Mike Parker wrote:
 DIP 1004 is titled "Inherited Constructors. [...]
 All review-related feedback on and discussion of the DIP 
 should occur in this thread. [...]
 Destroy!
An obvious omission in the syntax variations [1] - alias this() = super.this(); or - alias this = super.this;
I thought people would catch on that this is implied. :) The old-style or new-style alias syntax should both be allowed, in my opinion. The main issue is what to do about the parentheses, whether to include them or not.
May 01
next sibling parent reply "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Mon, May 01, 2017 at 04:08:36PM +0000, Andrej Mitrovic via Digitalmars-d
wrote:
 On Monday, 1 May 2017 at 15:33:47 UTC, Basile B. wrote:
 On Monday, 1 May 2017 at 14:55:28 UTC, Mike Parker wrote:
 DIP 1004 is titled "Inherited Constructors. [...]
 All review-related feedback on and discussion of the DIP should
 occur in this thread. [...]
 Destroy!
An obvious omission in the syntax variations [1] - alias this() = super.this(); or - alias this = super.this;
I thought people would catch on that this is implied. :) The old-style or new-style alias syntax should both be allowed, in my opinion. The main issue is what to do about the parentheses, whether to include them or not.
I don't think new-style syntax is supported for `alias X this;`. I vaguely remember in the original discussions when new-style alias syntax was first introduced, that we decided against allowing `alias this = X;` because alias this held a special meaning that's different from the usual alias declaration, so the fact that they now have different syntaxes was seen as an advantage. T -- Тише едешь, дальше будешь.
May 01
parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On Monday, 1 May 2017 at 18:34:43 UTC, H. S. Teoh wrote:
 so the fact that they now have different syntaxes was seen as 
 an advantage.
Yeah, I remember that decision. I don't think I've ever agreed with it, though. :o) We'll see.. I don't personally find it very important, I'm fine with either styles of syntax.
May 01
prev sibling parent Basile B. <b2.temp gmx.com> writes:
On Monday, 1 May 2017 at 16:08:36 UTC, Andrej Mitrovic wrote:
 On Monday, 1 May 2017 at 15:33:47 UTC, Basile B. wrote:
 On Monday, 1 May 2017 at 14:55:28 UTC, Mike Parker wrote:
 DIP 1004 is titled "Inherited Constructors. [...]
 All review-related feedback on and discussion of the DIP 
 should occur in this thread. [...]
 Destroy!
An obvious omission in the syntax variations [1] - alias this() = super.this(); or - alias this = super.this;
I thought people would catch on that this is implied. :) The old-style or new-style alias syntax should both be allowed, in my opinion. The main issue is what to do about the parentheses, whether to include them or not.
Then i have nothing to say and you can count me as a supporter of this DIP. As a personal matter i don't even care about the problem that's to have the ability to select a restricted set among the __ctors of the base. About protection attributes i think that the rules applied to OOP should be followed. Private __ctors can only be inherited in derived if derived is in the same module, otherwise not. Protected and public __ctors can always be inherited. Package __ctors can be inherited in the same package. Note that i always wondered why in the first place constructors and destructors were not designed to be virtual functions, like in other languages...
May 02
prev sibling next sibling parent reply "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Mon, May 01, 2017 at 02:55:28PM +0000, Mike Parker via Digitalmars-d wrote:
 DIP 1004 is titled "Inherited Constructors.
 
 https://github.com/dlang/DIPs/blob/master/DIPs/DIP1004.md
[...] I'm appalled that the only discussion that has come up so far is related to syntax rather than semantics. ;-) Overall, I like this DIP. Reducing boilerplate is always a good thing IMO, and is one of the things that attracted me to D in the first place. That said, there are a few points I feel could be more thoroughly explored: 1) Suppose my base class has 3 ctors, and I only want my derived class to inherit 1 of them. Does this DIP allow for that? 2) If my derived class has no ctors (and the base class has a default ctor but also several other ctors), what if I want to suppress inheriting base class ctors (except the default)? Do I need to individually list all base class ctors and attach disable to them? How would this interact with future-proofing my derived class in case the base class changes in the future (e.g., more ctors got added)? 3) Is it legal to write ` disable this(int,int)` when the base class doesn't have a matching ctor? This might happen, e.g., if the base class ctor was removed after the fact. Or would all derived classes that disabled the original ctor have to be updated? 4) If my derived class has no (explicit) ctors, is there any semantic difference between writing: class Derived : Base {} vs.: class Derived : Base { alias super.this this; } ? Would it be better to require the latter explicit form so that this DIP is opt-in (and also prevents breaking existing code that uses compile-time introspection)? Or would the added boilerplate (have to write that alias line for all derived classes) make this DIP less attractive? (Note that this essentially nullifies implicit ctor inheritance, which is one of main points of this DIP. But the point is that alternatives like this should be considered and argued against to make this DIP stronger.) 5) How would this DIP interact with access controls? E.g., if the base class has a private ctor, will that be inherited implicitly? Or if the base class has a protected ctor, will the inherit ctor remain as protected? Will there be a way to inherit a base class protected ctor and make it public instead? (I.e., a form of forwarding, from a public derived class ctor to a protected base class ctor.) If the base class introduces new private ctors, will that cause any problems with derived classes implicitly inheriting all ctors (assuming they do inherit private ctors)? At what point does it cross the line of requiring explicit declaration of a forwarding ctor in the derived class? T -- Just because you can, doesn't mean you should.
May 01
parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On Monday, 1 May 2017 at 19:02:11 UTC, H. S. Teoh wrote:
 1) Suppose my base class has 3 ctors, and I only want my 
 derived class to inherit 1 of them. Does this DIP allow for 
 that?
Initially when designing the DIP I haven't thought about this use-case, but I've had more thought put into it recently. Unfortunately it came a bit late, but I thought about an alternate DIP design to this one, where instead of inheriting *all* base class ctors, the user would selectively inherit *specific* ctors. The alternate proposal is just a PR for now: https://github.com/dlang/DIPs/pull/60 (direct link https://github.com/AndrejMitrovic/DIPs/blob/d4ae8866d52f1a17a5c4ff9f2c843d61dad5e7e7/DIPs/DIP1004-alternative.md)
 2) If my derived class has no ctors (and the base class has a 
 default ctor but also several other ctors), what if I want to 
 suppress inheriting base class ctors (except the default)?  Do 
 I need to individually list all base class ctors and attach 
  disable to them? How would this interact with future-proofing 
 my derived class in case the base class changes in the future 
 (e.g., more ctors got added)?
Very good question, especially about future-proofing. This goes back to my response to #1, and makes me think that in fact the alternate design in https://github.com/dlang/DIPs/pull/60 is probably a better idea.
 3) Is it legal to write ` disable this(int,int)` when the base 
 class doesn't have a matching ctor?  This might happen, e.g., 
 if the base class ctor was removed after the fact.  Or would 
 all derived classes that disabled the original ctor have to be 
 updated?
It would have to be illegal.
 4) If my derived class has no (explicit) ctors, is there any 
 semantic
 difference between writing:

 	class Derived : Base {}

 vs.:

 	class Derived : Base { alias super.this this; }
 ?
There shouldn't be any semantic difference.
 Would it be better to require the latter explicit form so that 
 this DIP is opt-in (and also prevents breaking existing code 
 that uses compile-time introspection)?
I'm not really sure of real-world examples where this would be the case, where a class designer has explicitly derived from a class but failed to write any constructors *and* intends for that class not to be constructible. In such a case, surely the designer of the class would label the class as `abstract`.
 Or would the added boilerplate (have to write that alias line 
 for all derived classes) make this DIP less attractive? (Note 
 that this essentially nullifies implicit ctor inheritance, 
 which is one of main points of this DIP. But the point is that 
 alternatives like this should be considered and argued against 
 to make this DIP stronger.)
I feel like implicit constructor inheritance where there are no new additional constructors being introduced in the derived class would be a safe default to have. I can't imagine a case where this would cause bugs in user code. But I'm open to seeing such examples, of course.
 5) How would this DIP interact with access controls? E.g., if 
 the base class has a private ctor, will that be inherited 
 implicitly? Or if the base class has a protected ctor, will the 
 inherit ctor remain as protected?
Not unless the two classes were part of the same module (and thus had symbol visibility). However the implicitly inherited constructor would also be private in the derived class as well, so that should answer the second part of that question.
 Will there be a way to inherit a base class protected ctor and 
 make it public instead? (I.e., a form of forwarding, from a 
 public derived class ctor to a protected base class ctor.)
Interesting idea. That would be another point for the alternate proposal in https://github.com/AndrejMitrovic/DIPs/blob/d4ae8866d52f1a17a5c4ff9f2c843d61dad5e7e7/DIPs/DIP 004-alternative.md, which would allow code such as: class A { protected this ( int x ) { } } class B { public alias super.this(int) this; }
 If the base class introduces new private ctors, will that cause 
 any problems with derived classes implicitly inheriting all 
 ctors (assuming they do inherit private ctors)?

 At what point does it cross the line of requiring explicit 
 declaration of a forwarding ctor in the derived class?
It's hard to tell whether it would cause problems, although it is indeed possible to accidentally inherit a ctor even if it's unwanted. I see the general sentiment, and I think the big question to be asked here is: do we want a way to inherit "everything at once", or have a simple syntax to selectively inherit some constructors as in https://github.com/AndrejMitrovic/DIPs/blob/d4ae8866d52f1a17a5c4ff9f2c843d61dad5e7e7/DIPs/DIP1004-alternative.md.
May 01
prev sibling next sibling parent reply deadalnix <deadalnix gmail.com> writes:
On Monday, 1 May 2017 at 14:55:28 UTC, Mike Parker wrote:
 DIP 1004 is titled "Inherited Constructors.

 https://github.com/dlang/DIPs/blob/master/DIPs/DIP1004.md

 All review-related feedback on and discussion of the DIP should 
 occur in this thread. Due to DConf taking place during the 
 review period, the period will be extended by a week. The 
 review period will end at 11:59 PM ET on May 22 (3:59 AM GMT 
 May 23), or when I make a post declaring it complete.

 At the end of Round 1, if further review is deemed necessary, 
 the DIP will be scheduled for another round. Otherwise, it will 
 be queued for the formal review and evaluation by the language 
 authors.

 Thanks in advance to all who participate.

 Destroy!
100% in favor of the constructor behavior change in case no constructor is in the derived class. Not convinced by the alias this trick. It doesn't pays for itself, IMO. It could be provided by a mixin or something and shouldn't be baked into the language.
May 02
next sibling parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 5/2/17 11:03 AM, deadalnix wrote:
 On Monday, 1 May 2017 at 14:55:28 UTC, Mike Parker wrote:
 DIP 1004 is titled "Inherited Constructors.

 https://github.com/dlang/DIPs/blob/master/DIPs/DIP1004.md

 All review-related feedback on and discussion of the DIP should occur
 in this thread. Due to DConf taking place during the review period,
 the period will be extended by a week. The review period will end at
 11:59 PM ET on May 22 (3:59 AM GMT May 23), or when I make a post
 declaring it complete.

 At the end of Round 1, if further review is deemed necessary, the DIP
 will be scheduled for another round. Otherwise, it will be queued for
 the formal review and evaluation by the language authors.

 Thanks in advance to all who participate.

 Destroy!
100% in favor of the constructor behavior change in case no constructor is in the derived class. Not convinced by the alias this trick. It doesn't pays for itself, IMO. It could be provided by a mixin or something and shouldn't be baked into the language.
+1 Let's keep it simple. --- Dmitry Olshansky
May 02
prev sibling next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On Tuesday, 2 May 2017 at 09:03:27 UTC, deadalnix wrote:
 100% in favor of the constructor behavior change in case no 
 constructor is in the derived class.
I think we could even split this up into two separate proposals, because this part of the DIP is fairly non-controversial and could be approved much faster (and implementation-wise it should be fairly simple to support).
May 02
parent deadalnix <deadalnix gmail.com> writes:
On Tuesday, 2 May 2017 at 11:13:35 UTC, Andrej Mitrovic wrote:
 On Tuesday, 2 May 2017 at 09:03:27 UTC, deadalnix wrote:
 100% in favor of the constructor behavior change in case no 
 constructor is in the derived class.
I think we could even split this up into two separate proposals, because this part of the DIP is fairly non-controversial and could be approved much faster (and implementation-wise it should be fairly simple to support).
<3
May 04
prev sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Tuesday, 2 May 2017 at 09:03:27 UTC, deadalnix wrote:
 100% in favor of the constructor behavior change in case no 
 constructor is in the derived class.
I agree.
May 02
parent reply Daniel N <no public.email> writes:
On Tuesday, 2 May 2017 at 18:02:15 UTC, Adam D. Ruppe wrote:
 On Tuesday, 2 May 2017 at 09:03:27 UTC, deadalnix wrote:
 100% in favor of the constructor behavior change in case no 
 constructor is in the derived class.
I agree.
So do I. However I oppose the other part of the DIP since it's already possible today. class FileException : Exception { this(ErrorCode error_code, string file = __FILE__, uint line = __LINE__ ) { super("FileNotFound", file, line); } alias __ctor = super.__ctor; }
May 03
parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On Wednesday, 3 May 2017 at 09:13:54 UTC, Daniel N wrote:
 However I oppose the other part of the DIP since it's already 
 possible today.

 class FileException : Exception
 {
     this(ErrorCode error_code, string file = __FILE__, uint 
 line = __LINE__ )
     {
         super("FileNotFound", file, line);
     }

     alias __ctor = super.__ctor;
 }
I was excited for a second, but that doesn't actually compile. Error: alias test.FileException.__ctor is not a constructor; identifiers starting with __ are reserved for the implementation
May 03
parent reply Daniel N <no public.email> writes:
On Wednesday, 3 May 2017 at 12:46:19 UTC, Andrej Mitrovic wrote:
 On Wednesday, 3 May 2017 at 09:13:54 UTC, Daniel N wrote:
 However I oppose the other part of the DIP since it's already 
 possible today.

 class FileException : Exception
 {
     this(ErrorCode error_code, string file = __FILE__, uint 
 line = __LINE__ )
     {
         super("FileNotFound", file, line);
     }

     alias __ctor = super.__ctor;
 }
I was excited for a second, but that doesn't actually compile. Error: alias test.FileException.__ctor is not a constructor; identifiers starting with __ are reserved for the implementation
I used this technique many times with many different compiler versions... The trick is that your child class need to have defined at least 1 constructor before the alias. This should work: this() {} alias __ctor = super.__ctor; This will give the error message you saw: alias __ctor = super.__ctor; this() {}
May 03
parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On Wednesday, 3 May 2017 at 12:58:17 UTC, Daniel N wrote:
 The trick is that your child class need to have defined at 
 least 1 constructor before the alias.

 This should work:
 this() {}
 alias __ctor = super.__ctor;

 This will give the error message you saw:
 alias __ctor = super.__ctor;
 this() {}
I see. It does look like an accidental feature (as in, that it could break in the future).
May 03
next sibling parent Mike Wey <mike-wey example.com> writes:
On 05/03/2017 05:09 PM, Andrej Mitrovic wrote:
 On Wednesday, 3 May 2017 at 12:58:17 UTC, Daniel N wrote:
 The trick is that your child class need to have defined at least 1 
 constructor before the alias.

 This should work:
 this() {}
 alias __ctor = super.__ctor;

 This will give the error message you saw:
 alias __ctor = super.__ctor;
 this() {}
I see. It does look like an accidental feature (as in, that it could break in the future).
You could switch to: ``` this(A...)(auto ref A a) { import std.functional; super(forward!a); } ``` but that doesn't work with all the parameter storage classes. lazy is no longer lazy for example. -- Mike Wey
May 03
prev sibling parent Daniel N <no public.email> writes:
On Wednesday, 3 May 2017 at 15:09:03 UTC, Andrej Mitrovic wrote:
 On Wednesday, 3 May 2017 at 12:58:17 UTC, Daniel N wrote:
 The trick is that your child class need to have defined at 
 least 1 constructor before the alias.

 This should work:
 this() {}
 alias __ctor = super.__ctor;

 This will give the error message you saw:
 alias __ctor = super.__ctor;
 this() {}
I see. It does look like an accidental feature (as in, that it could break in the future).
Well, I was thinking one could put it in a mixin, then it would be officially supported and user-facing code wouldn't have to use __symbols. One benefit with using __ctor is that the syntax doesn't clash with future "alias this" improvements.
May 03
prev sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On Monday, 1 May 2017 at 14:55:28 UTC, Mike Parker wrote:
 DIP 1004 is titled "Inherited Constructors.
Mike, given the general feedback I've received here, I think the next best take of action is to split the implicit inheritance proposal into a separate, smaller DIP, and update DIP 1004 with a second draft. Thoughts?
May 08
next sibling parent reply deadalnix <deadalnix gmail.com> writes:
On Monday, 8 May 2017 at 08:25:24 UTC, Andrej Mitrovic wrote:
 Thoughts?
It seems like the most sensible path forward. Mike ?
May 09
parent Mike Parker <aldacron gmail.com> writes:
On Tuesday, 9 May 2017 at 12:52:38 UTC, deadalnix wrote:
 On Monday, 8 May 2017 at 08:25:24 UTC, Andrej Mitrovic wrote:
 Thoughts?
It seems like the most sensible path forward. Mike ?
Works for me.
May 09
prev sibling parent Mike Parker <aldacron gmail.com> writes:
On Monday, 8 May 2017 at 08:25:24 UTC, Andrej Mitrovic wrote:
 On Monday, 1 May 2017 at 14:55:28 UTC, Mike Parker wrote:
 DIP 1004 is titled "Inherited Constructors.
Mike, given the general feedback I've received here, I think the next best take of action is to split the implicit inheritance proposal into a separate, smaller DIP, and update DIP 1004 with a second draft. Thoughts?
To expand on my shorter post above: let's call this review round officially closed. I'll wait for your updates, then we'll schedule a second round for the new draft of 1004.
May 10