Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DIP 1004: Inherited Constructors #42

Merged
merged 9 commits into from Nov 28, 2016

Conversation

AndrejMitrovic
Copy link
Contributor

@AndrejMitrovic AndrejMitrovic commented Sep 4, 2016

@mihails-strasuns
Copy link
Contributor

Thanks! I will be unavailable for two weeks starting tomorrow but will check it right after.

@Bolpat
Copy link
Contributor

Bolpat commented Sep 4, 2016

You only mention alias super.this this;. How about alias this = super.this;? The spec features the latter. I don't like the first syntax as it collides with alias … this; which means something completely different, but it should be supported.

@AndrejMitrovic
Copy link
Contributor Author

You only mention alias super.this this;. How about alias this = super.this;?

I think both could be supported. At some point there was talk about allowing alias this = type; for subtyping as well. Anyway I don't see why we can't support either or both syntaxes, super.this should be apparently different to subtyping.

Alternatively if there really is a visibility issue we could do something like: alias super.this() this(); and alias this() = super.this().

@AndrejMitrovic
Copy link
Contributor Author

I think technically we have access to the __ctor symbol already, but that would look a bit ugly in user code.

@PetarKirov
Copy link
Member

IIRC, it was proposed that alias member this, should be changed to alias this : member (instead of alias this = member) in order to emphasize the subtyping relationship and to avoid conflicts with alias this = super, which incidentally this DIP proposes. That proposal went nowhere, so alias this() = super.this() sounds like a good solution in the meantime.

Copy link
Contributor

@mihails-strasuns mihails-strasuns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall, just need to polish the details

The process of writing forwarding constructors is tedious and may even be
error-prone. It's possible to use existing language features such as
template mixins to generate forwarding constructors, however this increases
compilation times and also generates more object code.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

afair the main issue wasn't compilation time but the fact it creates reference loop for semantic pass (can't reliably reflect on an aggregate while trying to mix in is method)


The rationale for this current limitation: If the `Derived` object was constructible
by calling only the `Base` class constructor then the `Derived` object itself
could be left in an *unexpected* state. This is because the `Derived` constructors could
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest also mentioning also the code example when derived class has no own constructors (thus us rationale is not applicable) but it still doesn't work. Probably separate this section in two blocks as per https://github.com/dlang/DIPs/pull/42/files#diff-3830fabd6166499fcffc5e7cb94d0c69R32

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ping?

}

/// inherit base class constructors
alias super.this this;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if alias super this makes more sense - there is no way to refer to constructor method by this name in language and at the same time semantically by forwarding constructors you are saying derived is a strict superset of base.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's sort of odd to use alias super this; because it looks like subtyping, but on the other hand the derived object is a base class object already (implicitly converts to base).

I think I'll simply list a couple of proposed syntaxes and then let the community decide on the best choice.


## Breaking changes

There are no expected breaking changes with this proposal.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not true, same as for adding any new feature there is a risk that some code that didn't compile in is(typeof()) will start doing so :) It is very unlikely to make difference for existing code bases but DIPs need to mention all possible risks.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah true. :)


The feature syntax shares a similarity with object subtyping,
however `alias this.super this` would not conflict with the subtyping feature
since `super` is a reserved word.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you checked if existing grammar supports it already (I suppose alias this grammar is generic but need to make sure)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm I haven't, I did assume the compiler would currently reject alias this.super this.

@MartinNowak
Copy link
Member

Just bringing in previous discussions about this.
Issue 9066 – Add constructor inheritance feature
In particularly the one proposal mentioned in Comment 13.

@AndrejMitrovic
Copy link
Contributor Author

the one proposal mentioned in Comment 13.

You mean the disabling specific base class ctors? Yeah I must have skipped that part. I'll amend the DIP soon.

@mihails-strasuns
Copy link
Contributor

Ping @AndrejMitrovic ;)

@AndrejMitrovic
Copy link
Contributor Author

Ok updated with the proposed changes. I think with regards to syntax proposals this can still be discussed in the community. I'm sure we can come up with a reasonable syntax most people are happy with. But the basic idea for the feature is there.

Copy link
Contributor

@mihails-strasuns mihails-strasuns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I like the content, now it is only matter of formalizing and improving structure. I made some inline comments but checking existing state against https://github.com/dlang/DIPs/blob/master/README.md#advices-for-writing-great-dips can be a good idea too.

You may also want to re-generate table of contents now that more sections have been added.


The rationale for this current limitation: If the `Derived` object was constructible
by calling only the `Base` class constructor then the `Derived` object itself
could be left in an *unexpected* state. This is because the `Derived` constructors could
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ping?

new Derived(1, 2); // error: constructor is disabled
}
```

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on Andrei latest comment for DIP1002, would be a good idea to add here a section showing existing constructor boilerplate in public projects and how it would be simplified.

@AndrejMitrovic AndrejMitrovic force-pushed the inherited-constructors branch 3 times, most recently from 75674cf to e8b7b70 Compare October 1, 2016 16:16
@AndrejMitrovic
Copy link
Contributor Author

I'd suggest also mentioning also the code example when derived class has no own constructors

This was added at the start of the examples in the previous push.

Based on Andrei latest comment for DIP1002, would be a good idea to add here a section showing existing constructor boilerplate in public projects and how it would be simplified.

Good idea. I've added examples from an open source project, from Phobos, and I've also included the forwarding constructors mixin template as an example of what's already possible in library code (but which has its shortcomings).

@AndrejMitrovic AndrejMitrovic changed the title DIP 1004: Inheriting Constructors DIP 1004: Inherited Constructors Oct 1, 2016
@AndrejMitrovic
Copy link
Contributor Author

Changed title in PR / code and commit message to Inherited Constructors rather than Inheriting Constructors, I think it sounds better this way.

Dicebot added 5 commits October 24, 2016 08:50
Changes reading flow to first explain the problem and show existing
solutions first and only to proceed with proposed changes after.
- Proposed changes are phrased as directives for compiler
- Proposed changes are explained with straighforward before/after samples
- @disable of constructors is split onto own section
Shows how common it is to define wrong exception
class constructors with existing language semantics.
@mihails-strasuns
Copy link
Contributor

I have created a pull request against tour branch with various proposed changes : AndrejMitrovic#1

@AndrejMitrovic
Copy link
Contributor Author

@Dicebot let me know if you need this squashed (perhaps 1 origin commit and 1 fixup commit by you), or we could just keep the history as is.

@mihails-strasuns
Copy link
Contributor

Don't bother, it will be all squashed into one commit on merge anyway. I'll wait for Andrei to prepare his final judgement of existing DIPs in the queue and merge this one if it doesn't fail any of possibly mentioned requirements.

@mihails-strasuns
Copy link
Contributor

@AndrejMitrovic
Copy link
Contributor Author

Yup, saw it. I'm not planning on throwing a tantrum if the DIP is rejected. :)

{
// Error: class Derived cannot implicitly generate a default ctor when
// base class Base is missing a default ctor
auto d = new Derived(10, 10);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(10,10): Is there some code missing elsewhere, or should this be () ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is the wrong snippet and error message, fix: AndrejMitrovic#2

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

Dicebot and others added 2 commits November 20, 2016 14:43
@mihails-strasuns mihails-strasuns merged commit 68bb203 into dlang:master Nov 28, 2016
@deadalnix
Copy link

Ok 2 quick things.

1/ I love the general idea.
2/ I don't think the alias super.this this is necessary. Why not provide a mixin template to do this ? i would prefer a library solution here, as the proposed solution add to language complexity for a very specific use case and looks arcane and probably isn't necessary. If there is a major obstacle to this being done as a library, I'd like to know what it is.

@AndrejMitrovic
Copy link
Contributor Author

Why not provide a mixin template to do this ?

We could certainly try. The question is if it will end up being a half-solution like the current Typedef situation.

@deadalnix
Copy link

I would consider that having a half working solution here to be a problem with out mixin mechanism, and that we should fix that rather than baking a workaround for a specific use case in the language itself.

@mihails-strasuns
Copy link
Contributor

My 5 cents.

There are several proposed changes:

  1. https://github.com/dlang/DIPs/blob/master/DIPs/DIP1004.md#implicit-constructor-inheritance-for-derived-classes-with-no-constructors

This can't truly be replaced by any library solution because they all have a problem with one of stated goals - make correct approach the default by making class MyException : Exception { } "just work".

  1. https://github.com/dlang/DIPs/blob/master/DIPs/DIP1004.md#syntax-for-inheriting-base-class-constructors-for-derived-classes and https://github.com/dlang/DIPs/blob/master/DIPs/DIP1004.md#selective-disabling-of-inherited-constructors

Those certainly can be done a library utility (I remember having issues with semantic analysis cycles in the past but that was definitely a compiler bug). One can argue though that those are not new features and already work for any other class method - omitting constructors makes an artificial exception. I am less opinionated on this part though.

Anyway, before it gets to review stage, we should collect all proposed library implementations from NG and evaluate them as part of the DIP.

@deadalnix
Copy link

@Dicebot It was never question of making 1 as a library solution, so I'm not sure where you are going with that.

For 2, it is about copying a set a function from place to another. If we can't use reflection and mixin to do this, I'd argue this is the problem that need to be solved.

@jmdavis
Copy link
Member

jmdavis commented Nov 30, 2016

For exceptions, we do now have http://dlang.org/phobos/std_exception.html#.basicExceptionCtors, which at least makes mixing in the constructors easy, though it's not automatic. You have to explicitly mix them in. But thanks to improvements in the compiler, it actually works with ddoc, which wasn't the case in the past when such solutions were brought up.

@AndrejMitrovic AndrejMitrovic deleted the inherited-constructors branch January 28, 2017 00:11
@mdparker
Copy link
Member

@andrej-mitrovic-sociomantic Please email me. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
9 participants