www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - DIP 1007 Preliminary Review Round 1

reply Mike Parker <aldacron gmail.com> writes:
DIP 1007 is titled "'future symbol' Compiler Concept".

https://github.com/dlang/DIPs/blob/master/DIPs/DIP1007.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 15 (3:59 AM GMT May 16), 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!
Apr 24
next sibling parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Monday, 24 April 2017 at 15:03:53 UTC, Mike Parker wrote:
 DIP 1007 is titled "'future symbol' Compiler Concept".
«In all the mentioned languages but D, a common convention is to only use unqualified access for symbols in the standard library.» Not quite right for C++. The common convention in modern C++ is to use full std::name qualification for the standard library. It is common to use unqualified access for the local namespace(s) only.
Apr 24
parent reply Atila Neves <atila.neves gmail.com> writes:
On Monday, 24 April 2017 at 15:22:15 UTC, Ola Fosheim Grøstad 
wrote:
 On Monday, 24 April 2017 at 15:03:53 UTC, Mike Parker wrote:
 DIP 1007 is titled "'future symbol' Compiler Concept".
«In all the mentioned languages but D, a common convention is to only use unqualified access for symbols in the standard library.» Not quite right for C++. The common convention in modern C++ is to use full std::name qualification for the standard library. It is common to use unqualified access for the local namespace(s) only.
In headers. Not in source files, and I don't know why anyone would want to keep typing `std::` all the time. Do some people do what you're describing? Yes, but I see no evidence that that's the common convention in modern C++. In fact, from the core guidelines: " ##### Example #include<string> #include<vector> #include<iostream> #include<memory> #include<algorithm> using namespace std; // ... Here (obviously), the standard library is used pervasively and apparently no other library is used, so requiring `std::` everywhere could be distracting." Never mind the monstrosity that would be trying to use the C++ user-defined literal without `using namespace std`: #include <string> using namespace std::operator""s; // Argh! My eyes! No thanks. I even had to look that up, and I'll probably forget it.
Apr 24
parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Monday, 24 April 2017 at 22:22:14 UTC, Atila Neves wrote:
 In headers. Not in source files, and I don't know why anyone 
 would want to keep typing `std::` all the time.
C++ is increasingly becoming dependent on templates so header files are expanding at the cost of ".cpp source files". If more than half the code base is in header files then it makes little sense to not use "std::" fully qualified, both for clarity, name-resolution and usability reasons (cut and paste). (For templates the core guidelines says that one should use "std::" and only use unqualified names for situations where you want to override the "std::" provided definition with a local implementation if it exists.)
 Never mind the monstrosity that would be trying to use the C++ 
 user-defined literal without `using namespace std`:

 #include <string>
 using namespace std::operator""s;  // Argh! My eyes!
You could just wrap that up in an application level string header.
Apr 25
prev sibling next sibling parent reply rikki cattermole <rikki cattermole.co.nz> writes:
On 24/04/2017 4:03 PM, Mike Parker wrote:
 DIP 1007 is titled "'future symbol' Compiler Concept".

 https://github.com/dlang/DIPs/blob/master/DIPs/DIP1007.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 15 (3:59 AM GMT May 16), 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!
This DIP concerns me, for any other language I would go so far as to saying, I would expect people to overuse this to the extreme. Going by what they "think" they may need in the future instead of what they definitely will need. On the flip side, it would be great for development, feature not yet done but planned? Annotate it. Even before a release ever happens. Although I would prefer to see a unifying syntax to merge deprecated and this into it, making it more user configurable. More complex to design but most importantly less special rules in language.
Apr 24
next sibling parent reply "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Mon, Apr 24, 2017 at 04:58:12PM +0100, rikki cattermole via Digitalmars-d
wrote:
 On 24/04/2017 4:03 PM, Mike Parker wrote:
 DIP 1007 is titled "'future symbol' Compiler Concept".
 
 https://github.com/dlang/DIPs/blob/master/DIPs/DIP1007.md
[...]
 This DIP concerns me, for any other language I would go so far as to
 saying, I would expect people to overuse this to the extreme. Going by
 what they "think" they may need in the future instead of what they
 definitely will need.
Initially I also had the same concern, but after reading the DIP in its entirety, I think it may be worth considering. The DIP, as it stands, proposes to make this feature available *only to the compiler* as a hard-coded list of symbols, meaning that in its first incarnation it will only be used for adding new symbols to e.g., druntime. *If* it passes this first round of implementation / general usage in the D community, then a followup DIP can be made to make this feature available to the general user. But if any major issues arise in this first stage, we can simply forego further implementation, perhaps even revert the feature. I think this is a perfectly acceptable implementation plan. IMO it's worth a try. (And I would make it a point that IMO the first implementation of this DIP should NOT make this feature generally available to the user; that should be done only as a followup DIP.)
 On the flip side, it would be great for development, feature not yet
 done but planned? Annotate it. Even before a release ever happens.
[...] This is good and bad. If overused, it could lead to the situation you described, where people aggressively "reserve" future symbols that eventually turn out to be unnecessary, thus potentially "wasting" good names in the namespace. T -- WINDOWS = Will Install Needless Data On Whole System -- CompuMan
Apr 25
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 4/25/17 12:24 PM, H. S. Teoh via Digitalmars-d wrote:
 On Mon, Apr 24, 2017 at 04:58:12PM +0100, rikki cattermole via Digitalmars-d
wrote:
 On 24/04/2017 4:03 PM, Mike Parker wrote:
 DIP 1007 is titled "'future symbol' Compiler Concept".

 https://github.com/dlang/DIPs/blob/master/DIPs/DIP1007.md
[...]
 This DIP concerns me, for any other language I would go so far as to
 saying, I would expect people to overuse this to the extreme. Going by
 what they "think" they may need in the future instead of what they
 definitely will need.
Initially I also had the same concern, but after reading the DIP in its entirety, I think it may be worth considering. The DIP, as it stands, proposes to make this feature available *only to the compiler* as a hard-coded list of symbols, meaning that in its first incarnation it will only be used for adding new symbols to e.g., druntime. *If* it passes this first round of implementation / general usage in the D community, then a followup DIP can be made to make this feature available to the general user. But if any major issues arise in this first stage, we can simply forego further implementation, perhaps even revert the feature.
I missed this part. Now that I read that, I think we aren't going to gain much by having this language feature internal to the compiler. If we want to limit usage, what I'd *rather* see is that the future (or TBD attribute) only has special meaning inside object.d. Having to adjust a hard-coded compiler list seems like it will result in zero PR changes (save the one that prompted this DIP) that might give us any insight into whether this is a useful feature. If this DIP does not address the actual language, I would vote no. You can always make a special case solution in the compiler without a DIP.
 On the flip side, it would be great for development, feature not yet
 done but planned? Annotate it. Even before a release ever happens.
[...] This is good and bad. If overused, it could lead to the situation you described, where people aggressively "reserve" future symbols that eventually turn out to be unnecessary, thus potentially "wasting" good names in the namespace.
I think this is not really that big of a deal. Other than object.d, there's nothing people absolutely have to include. Just don't import libraries that abuse this, and you won't have this problem. I'd also hazard to guess that a very popular project that abused this feature would simply develop forks which didn't. -Steve
Apr 25
parent reply Olivier FAURE <olivier.faure epitech.eu> writes:
On Tuesday, 25 April 2017 at 18:32:09 UTC, Steven Schveighoffer 
wrote:
 I missed this part. Now that I read that, I think we aren't 
 going to gain much by having this language feature internal to 
 the compiler.
The way I understood it, the feature will only stay internal to the compiler until it's deemed "safe" for general use.
 If we want to limit usage, what I'd *rather* see is that the 
  future (or TBD attribute) only has special meaning inside 
 object.d. Having to adjust a hard-coded compiler list seems 
 like it will result in zero PR changes (save the one that 
 prompted this DIP) that might give us any insight into whether 
 this is a useful feature.
The proposal does include something like that.
 Alternatively, if it proves to be simpler to implement, the 
 feature can be added as an attribute with reserved 
 double-underscore prefix (i.e.  __future) with compiler checks 
 ensuring that it is not used outside of core.*/std.*/object 
 modules. If that course of action is chosen, such an attribute 
 should be defined in the core.attribute module of DRuntime.
Apr 26
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 4/26/17 4:32 AM, Olivier FAURE wrote:
 On Tuesday, 25 April 2017 at 18:32:09 UTC, Steven Schveighoffer wrote:
 I missed this part. Now that I read that, I think we aren't going to
 gain much by having this language feature internal to the compiler.
The way I understood it, the feature will only stay internal to the compiler until it's deemed "safe" for general use.
The question I have is: who is going to adjust this list? If the answer is nobody, then when is it deemed "safe" for general use? How do we judge whether it's safe to allow others to use it, when nobody is using it? What's more useful to me is to require the future attribute on all new symbols in object.d, and then see how that process works. Given that the very nature of future is that it's supposed to be temporary, then if we decide it's not worth the hassle, we can just abandon the feature.
 If we want to limit usage, what I'd *rather* see is that the  future
 (or TBD attribute) only has special meaning inside object.d. Having to
 adjust a hard-coded compiler list seems like it will result in zero PR
 changes (save the one that prompted this DIP) that might give us any
 insight into whether this is a useful feature.
The proposal does include something like that.
I may have missed it. There's a lot of text, it's hard to see what is actually being proposed and what isn't.
 Alternatively, if it proves to be simpler to implement, the feature
 can be added as an attribute with reserved double-underscore prefix
 (i.e.  __future) with compiler checks ensuring that it is not used
 outside of core.*/std.*/object modules. If that course of action is
 chosen, such an attribute should be defined in the core.attribute
 module of DRuntime.
I'm wondering if you actually wrote this? It seems to be quoted. Sure, we can allow such a thing, and prepending double underscores seems like a reasonable thing, since this should be used lightly and infrequently. -Steve
Apr 26
parent reply Olivier FAURE <olivier.faure epitech.eu> writes:
On Wednesday, 26 April 2017 at 11:26:19 UTC, Steven Schveighoffer 
wrote:
 I'm wondering if you actually wrote this? It seems to be quoted.
That was a quote from the DIP. (guess I should have used a colon)
Apr 28
parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 4/28/17 4:31 AM, Olivier FAURE wrote:
 On Wednesday, 26 April 2017 at 11:26:19 UTC, Steven Schveighoffer wrote:
 I'm wondering if you actually wrote this? It seems to be quoted.
That was a quote from the DIP. (guess I should have used a colon)
Ah, OK. Sorry for the confusion, I wasn't sure where it came from. -Steve
Apr 30
prev sibling parent Leandro Lucarella <leandro.lucarella sociomantic.com> writes:
On Monday, 24 April 2017 at 15:58:12 UTC, rikki cattermole wrote:
 On the flip side, it would be great for development, feature 
 not yet done but planned? Annotate it. Even before a release 
 ever happens.
This is not the intended usage of this DIP. The intention here is to only mark symbols that are already implemented but to avoid breakage without a clean (non-breaking) update path in a development branch. This is not to "reserve" symbols for future plan. Even when at first this is intended to be used only internally by the compiler (and runtime), I will give a more general example: In semver terms, suppose that you have a library at v1.0.0 release and you want to add a symbol to a base case that is supposed to be subclassed by user code. Normally you will do this in a v1.1.0 release, since you are adding a new feature, but since adding a new method to a base class is not really a non-breaking change, because if user code added a method with the same name in a subclass, then it will break. So this change needs to be delayed for v2.0.0, you write the code in that branch to add the method. You don't just plan it. Then you go to v1.x.x branch add the ` future` declaring that the symbol will appear in an upcoming release. So when you release v1.1.0 your user gets a nice warning and can plan how to adapt his code to the upcoming v2.0.0. At some point the user upgrades to v2.0.0 and since he had a clean non-breaking update path, what in essence will be a breaking change actually never really broke the user's code (if he incrementally upgraded from v1.0.0 to v1.1.0 and then v2.0.0). Boom! This not only allows the user to do incremental upgrades without *ever* breaking his code, it also *encourages* users to stay up to date, since doing so guarantees no breaking changing, while making a big jump from an old version to a newer one will in fact break his code. This is the spirit of this DIP. Of course it could be abused, as many other features, this is why it is suggested that at first it's only available to the compiler. But even if it makes it to the user (which I think it will be very beneficial for D), if a library author abuses this feature, just educate them, ask not to reserve arbitrary symbols as reserving symbols that are not used in the short term just annoys the users for no reason. Is like if a library author would change the name of the functions in every release just for fun. Of course he could do it, but what would be the point to it?
May 10
prev sibling next sibling parent Dominikus Dittes Scherkl <Dominikus.Scherkl continental-corporation.com> writes:
On Monday, 24 April 2017 at 15:03:53 UTC, Mike Parker wrote:
 DIP 1007 is titled "'future symbol' Compiler Concept".

 https://github.com/dlang/DIPs/blob/master/DIPs/DIP1007.md
+1 I like the idea of beeing warned about new symbols in libraries, so that I can change my symbols ahead.
Apr 25
prev sibling next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2017-04-24 17:03, Mike Parker wrote:
 DIP 1007 is titled "'future symbol' Compiler Concept".

 https://github.com/dlang/DIPs/blob/master/DIPs/DIP1007.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 15 (3:59 AM GMT May 16), 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!
How is this supposed to be used? * Take the example of the recent __cmp addition to object.d, would we say: "this PR has to wait one year because we need to add the future attribute and let users update their code"? * When the future attribute is added, would one add it on a dummy symbol or would one provide the implementation as well? * If the implementation is provided, is it possible to use the symbol by the users the symbol was added for in the beginning? In the above example that would be the compiler generating a code to __cmp -- /Jacob Carlborg
Apr 25
next sibling parent rikki cattermole <rikki cattermole.co.nz> writes:
On 25/04/2017 12:29 PM, Jacob Carlborg wrote:
 On 2017-04-24 17:03, Mike Parker wrote:
 DIP 1007 is titled "'future symbol' Compiler Concept".

 https://github.com/dlang/DIPs/blob/master/DIPs/DIP1007.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 15 (3:59 AM GMT May 16), 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!
How is this supposed to be used? * Take the example of the recent __cmp addition to object.d, would we say: "this PR has to wait one year because we need to add the future attribute and let users update their code"?
Mitigation: version(none) { void foo() { ... } } else { future void foo(); }
Apr 25
prev sibling parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 4/25/17 7:29 AM, Jacob Carlborg wrote:
 On 2017-04-24 17:03, Mike Parker wrote:
 DIP 1007 is titled "'future symbol' Compiler Concept".

 https://github.com/dlang/DIPs/blob/master/DIPs/DIP1007.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 15 (3:59 AM GMT May 16), 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!
How is this supposed to be used? * Take the example of the recent __cmp addition to object.d, would we say: "this PR has to wait one year because we need to add the future attribute and let users update their code"?
__symbol is reserved by the language. I don't think we need to worry about those. In the general case, one year is too long. A couple compiler releases should be sufficient.
 * When the  future attribute is added, would one add it on a dummy
 symbol or would one provide the implementation as well?
dummy symbol. Think of it as disable, but with warning output instead of error.
 * If the implementation is provided, is it possible to use the symbol by
 the users the symbol was added for in the beginning? In the above
 example that would be the compiler generating a code to __cmp
I would think the implementation should not be provided. The idea is to reserve the symbol for future use, not to implement it. If you add an implementation and the compiler allows using that implementation, then you potentially break code. This DIP should aim not to break any code. Really, what you are doing is reserving the overload spot. In cases where the overload would have selected your local function, then you should get no warning (as the additional symbol won't conflict). In cases where your function conflicts with a newly-reserved base class function, then the warning should be that you will eventually need to include the `override` keyword. Actually, that brings up a problem with this, what is the mechanism to say "maybe override"? Let's say you have: // in imported library class Base { void foo() future; } // in user library class Derived : Base { void foo() {...} // triggers warning } What is the next step the user has to take to remove the deprecation warning, but still have valid code? If you put override on foo, it's not really overriding anything as Base.foo doesn't really exist (right?). Basically, we need a way to write Derived such that it works with both the future reserved Base.foo, and the permanent Base.foo. With deprecation, the path is clear, you just stop using that symbol. This is not as clear. If adding override is allowed even when base symbol doesn't really exist, that might work, but it needs to be explicit in the DIP. -Steve
Apr 25
next sibling parent Leandro Lucarella <leandro.lucarella sociomantic.com> writes:
On Tuesday, 25 April 2017 at 12:33:44 UTC, Steven Schveighoffer 
wrote:
 Really, what you are doing is reserving the overload spot. In 
 cases where the overload would have selected your local 
 function, then you should get no warning (as the additional 
 symbol won't conflict). In cases where your function conflicts 
 with a newly-reserved base class function, then the warning 
 should be that you will eventually need to include the 
 `override` keyword.

 Actually, that brings up a problem with this, what is the 
 mechanism to say "maybe override"? Let's say you have:

 // in imported library
 class Base
 {
    void foo()  future;
 }

 // in user library
 class Derived : Base
 {
    void foo() {...} // triggers warning
 }

 What is the next step the user has to take to remove the 
 deprecation warning, but still have valid code? If you put 
 override on foo, it's not really overriding anything as 
 Base.foo doesn't really exist (right?). Basically, we need a 
 way to write Derived such that it works with both the  future 
 reserved Base.foo, and the permanent Base.foo. With 
 deprecation, the path is clear, you just stop using that 
 symbol. This is not as clear.

 If adding override is allowed even when base symbol doesn't 
 really exist, that might work, but it needs to be explicit in 
 the DIP.
This is a very good point. We'll send a PR with a proposed solution to address this issue soon. Thanks!
May 10
prev sibling next sibling parent reply Dicebot <public dicebot.lv> writes:
On Tuesday, 25 April 2017 at 12:33:44 UTC, Steven Schveighoffer 
wrote:
 Actually, that brings up a problem with this, what is the 
 mechanism to say "maybe override"? Let's say you have:

 // in imported library
 class Base
 {
    void foo()  future;
 }

 // in user library
 class Derived : Base
 {
    void foo() {...} // triggers warning
 }

 What is the next step the user has to take to remove the 
 deprecation warning, but still have valid code?
Right now I have two possible approaches in mind. One is to simply allow overriding ` future` symbol which doesn't require any extra stuff but can be viewed sub-optimal because it couples two loosely related concepts and would require special cases in how future symbols are handled inside compiler (they stop being completely ephemeral). Other would be an accompanying DIP to be able to specify `overide(strict)` (default, same as plain `override`) vs `override(optional)` to be able to define methods that may or may not override base one, with no specific relation to ` future`. I don't have any hard opinion on the matter of my own, what do you think?
May 10
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 5/10/17 11:15 AM, Dicebot wrote:
 On Tuesday, 25 April 2017 at 12:33:44 UTC, Steven Schveighoffer wrote:
 Actually, that brings up a problem with this, what is the mechanism to
 say "maybe override"? Let's say you have:

 // in imported library
 class Base
 {
    void foo()  future;
 }

 // in user library
 class Derived : Base
 {
    void foo() {...} // triggers warning
 }

 What is the next step the user has to take to remove the deprecation
 warning, but still have valid code?
Right now I have two possible approaches in mind. One is to simply allow overriding ` future` symbol which doesn't require any extra stuff but can be viewed sub-optimal because it couples two loosely related concepts and would require special cases in how future symbols are handled inside compiler (they stop being completely ephemeral). Other would be an accompanying DIP to be able to specify `overide(strict)` (default, same as plain `override`) vs `override(optional)` to be able to define methods that may or may not override base one, with no specific relation to ` future`. I don't have any hard opinion on the matter of my own, what do you think?
I prefer the first one. The reason is simply because it doesn't require any new grammar. The override requirement is already a protection against changing base class. In this case, we have two possible outcomes: 1. The base class finally implements the method and removes future. In this case, the derived class continues to function as expected, overriding the new function. 2. The base class removes the method. In this case, the override now fails to compile. This is not as ideal, as this does not result in a version that will compile with two consecutive versions of the base. But there is a possible path for this too -- mark it as deprecated future :) -Steve
May 10
next sibling parent Dicebot <public dicebot.lv> writes:
On Thursday, 11 May 2017 at 00:04:52 UTC, Steven Schveighoffer 
wrote:
 I prefer the first one. The reason is simply because it doesn't 
 require any new grammar. The override requirement is already a 
 protection against changing base class. In this case, we have 
 two possible outcomes:

 1. The base class finally implements the method and removes 
 future. In this case, the derived class continues to function 
 as expected, overriding the new function.

 2. The base class removes the method. In this case, the 
 override now fails to compile. This is not as ideal, as this 
 does not result in a version that will compile with two 
 consecutive versions of the base. But there is a possible path 
 for this too -- mark it as  deprecated  future :)

 -Steve
Sounds reasonable. I'll submit an update to the DIP.
May 11
prev sibling parent Dicebot <public dicebot.lv> writes:
https://github.com/dlang/DIPs/pull/63
May 14
prev sibling parent reply "Nick Sabalausky (Abscissa)" <SeeWebsiteToContactMe semitwist.com> writes:
On 04/25/2017 08:33 AM, Steven Schveighoffer wrote:
 In the general case, one year is too long. A couple compiler releases
 should be sufficient.

 * When the  future attribute is added, would one add it on a dummy
 symbol or would one provide the implementation as well?
dummy symbol. Think of it as disable, but with warning output instead of error.
This is a pointless limitation. What is the benefit of requiring the author to *not* provide an implementation until the transition period is over? It runs counter to normal workflow. Instead, why not just say "Here's a new function. But !!ZOMG!! what if somebody is already using a function by that name??!? They'd have use FQNs to disambiguate! Gasp!!! We can't have that! So, fine, if it's that big of a deal, we'll just instruct the compiler to just NOT pick up this function unless it's specifically requested via FQN". That sounds FAR better to me than "Here's a new function, but we gotta keep it hidden in a separate branch/version/etc and not let anyone use it until we waste a bunch of time making sure everyone's code is all updated and ready so that once we let people use it nobody will have to update their code with FQNs, because we can't have that, can we?" Pardon me for saying so, and so bluntly, but honestly, this whole discussion is just stupid. It's full-on C++-grade anti-breakage hysteria. There are times when code breakage is a legitimate problem. This is not REMOTELY one of them.
May 10
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 5/11/17 12:11 AM, Nick Sabalausky (Abscissa) wrote:
 On 04/25/2017 08:33 AM, Steven Schveighoffer wrote:
 In the general case, one year is too long. A couple compiler releases
 should be sufficient.

 * When the  future attribute is added, would one add it on a dummy
 symbol or would one provide the implementation as well?
dummy symbol. Think of it as disable, but with warning output instead of error.
This is a pointless limitation. What is the benefit of requiring the author to *not* provide an implementation until the transition period is over? It runs counter to normal workflow.
The idea (I think) is to have a version of the library that functions *exactly* like the old version, but helpfully identifies where a future version will not function properly. This is like deprecate. You don't put a deprecate on a symbol and at the same time remove the symbol's implementation -- you leave it as it was, and just tag it so the warning shows up. That's step one.
 Instead, why not just say "Here's a new function. But !!ZOMG!! what if
 somebody is already using a function by that name??!? They'd have use
 FQNs to disambiguate! Gasp!!! We can't have that! So, fine, if it's that
 big of a deal, we'll just instruct the compiler to just NOT pick up this
 function unless it's specifically requested via FQN".
The point is not to break code without fair warning. This is the progression I have in mind: In Library version 1 (LV1), the function doesn't exist. In LV2, the function is marked as future. In LV3, the function is implemented and the future tag is removed. LV1 + user code version 1 (UCV1) -> works * library writer updates his version LV2 + UCV1 -> works, but warns that it will not work in a future version. * user updates his code to mitigate the potential conflict LV2 + UCV2 -> works, no warnings. LV3 + UCV2 -> works as expected. The important thing here is that the library writer gives fair warning that a breaking change is coming, giving the user time to update his code at his convenience. If he does so before the next version of the library comes out, then his code works for both the existing library version AND the new one without needing to rush a change through.
 That sounds FAR better to me than "Here's a new function, but we gotta
 keep it hidden in a separate branch/version/etc and not let anyone use
 it until we waste a bunch of time making sure everyone's code is all
 updated and ready so that once we let people use it nobody will have to
 update their code with FQNs, because we can't have that, can we?"
It depends on both the situation and the critical nature of the symbol in question. I'd say the need for this tag is going to be very rare, but necessary when it is needed. I don't think there's a definitive methodology for deciding when it's needed and when it's not. Would be case-by-case.
 Pardon me for saying so, and so bluntly, but honestly, this whole
 discussion is just stupid. It's full-on C++-grade anti-breakage
 hysteria. There are times when code breakage is a legitimate problem.
 This is not REMOTELY one of them.
This is not anti-breakage. Code is going to break. It's just a warning that the breaking is coming. -Steve
May 11
parent reply "Nick Sabalausky (Abscissa)" <SeeWebsiteToContactMe semitwist.com> writes:
On 05/11/2017 07:19 AM, Steven Schveighoffer wrote:
 On 5/11/17 12:11 AM, Nick Sabalausky (Abscissa) wrote:
 This is a pointless limitation. What is the benefit of requiring the
 author to *not* provide an implementation until the transition period is
 over? It runs counter to normal workflow.
The idea (I think) is to have a version of the library that functions *exactly* like the old version, but helpfully identifies where a future version will not function properly. This is like deprecate. You don't put a deprecate on a symbol and at the same time remove the symbol's implementation -- you leave it as it was, and just tag it so the warning shows up. That's step one.
Yes, I'm aware that's the idea the author had in mind, but that still doesn't begin to address this: What is the *benefit* of requiring of requiring the author to *not* provide an implementation until the transition period is over? I maintain there is no benefit to that. Drawing a parallel to "how you do it with deprecated symbols" is not demonstrating a benefit. For that matter, I see the parallel with deprecated symbols as being "The deprecation tag goes with an implemented function. Symmetry would imply that a 'newly added' tag also goes on an implemented function." So the symmetry arguments goes both ways. But regardless, what we *don't* usually do is develop functionality *after* first finalizing its name. That's just silly.
 The point is not to break code without fair warning. This is the
 progression I have in mind:

 In Library version 1 (LV1), the function doesn't exist.
 In LV2, [the lib author makes a guess that they're going to write a 
function with a particular name and the] function is marked as future.
 In LV3, the function is implemented and the  future tag is removed.
Fixed step 2 for you. And yes, that *is* the progression suggested by this DIP, but one of my key points is: that's a downright silly progression. This is better: - In Library version 1 (LV1), the function doesn't exist. - In LV2, the new function is marked as new_symbol to prevent the (somehow) TERRIBLE HORRIBLE AWFUL consequence of the new symbol causing people to be required to toss in a FQN, but there's no harm in STOPPING people from actually using the new functionality if they request it unambiguously, now is there? No, there isn't. - In LV3, the new_symbol tag is removed.
 The important thing here is that the library writer gives fair warning
 that a breaking change is coming, giving the user time to update his
 code at his convenience.
Or, if the tag is added to the actual implementation then there IS NO FREAKING BREAKING CHANGE until the new_func or whatever tag is removed, but the library user is STILL given fair (albiet useless, imo) warning that it will be (kinda sorta) broken (with a downright trivial fix) in a followup release.
 I'd say the need for this tag is going to be very rare,
That's for certain.
 but necessary when it is needed.
I can't even begin to comprehend a situation where a heads-up about a mere "FQN needed here" qualifies as something remotely as strong as "necessary". Unless the scenario hinges on the current brokenness of FQNs, which seriously need to be fixed anyway.
 I don't think there's a definitive
 methodology for deciding when it's needed and when it's not. Would be
 case-by-case.
Sounds like useless cognitive bother on the library author for extremely minimal (at best) benefit to the library user. Doesn't sound like sufficient justification for a new language feature to me.
 This is not anti-breakage. Code is going to break. It's just a
 warning that the breaking is coming.
It's going out of the way to create and use a new language feature purely out of fear of a trivial breakage situation. Actual breakage or not, it's "all breakages are scary and we must bend over backwards because of them" paranoia, just the same.
May 11
parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 5/11/17 1:21 PM, Nick Sabalausky (Abscissa) wrote:
 On 05/11/2017 07:19 AM, Steven Schveighoffer wrote:
 On 5/11/17 12:11 AM, Nick Sabalausky (Abscissa) wrote:
 This is a pointless limitation. What is the benefit of requiring the
 author to *not* provide an implementation until the transition period is
 over? It runs counter to normal workflow.
The idea (I think) is to have a version of the library that functions *exactly* like the old version, but helpfully identifies where a future version will not function properly. This is like deprecate. You don't put a deprecate on a symbol and at the same time remove the symbol's implementation -- you leave it as it was, and just tag it so the warning shows up. That's step one.
Yes, I'm aware that's the idea the author had in mind, but that still doesn't begin to address this: What is the *benefit* of requiring of requiring the author to *not* provide an implementation until the transition period is over?
How does this work? class Base { void foo() future { ... } } class Derived : Base { void foo() { ... } } void bar(Base b) // could be instance of Derived { // which one is called? Derived.foo may not have been intended for // the same purpose as Base.foo b.foo(); }
 The point is not to break code without fair warning. This is the
 progression I have in mind:

 In Library version 1 (LV1), the function doesn't exist.
 In LV2, [the lib author makes a guess that they're going to write a
function with a particular name and the] function is marked as future.
 In LV3, the function is implemented and the  future tag is removed.
Fixed step 2 for you.
No, an implementation is in mind and tested. Just not available. You could even have the implementation commented out. In Phobos/Druntime, we wouldn't accept such a prospect without requiring a fleshing out of the details ahead of time. If it makes sense to just add the symbol with an implementation, then I'd rather do that. Otherwise, we create a new way to overload/override, and suddenly things work very differently than people are used to. Suddenly templates start calling the wrong thing and code actually breaks before a change is actually made.
 And yes, that *is* the progression suggested by this DIP, but one of my
 key points is: that's a downright silly progression. This is better:

 - In Library version 1 (LV1), the function doesn't exist.
 - In LV2, the new function is marked as  new_symbol to prevent the
 (somehow) TERRIBLE HORRIBLE AWFUL consequence of the new symbol causing
 people to be required to toss in a FQN, but there's no harm in STOPPING
 people from actually using the new functionality if they request it
 unambiguously, now is there? No, there isn't.
 - In LV3, the  new_symbol tag is removed.
It's also possible to implement the symbol with a different temporary name, and use that name if you need it before it's ready. I'm just more comfortable with a symbol that changes absolutely nothing about how a function can be called, but is a warning that something is coming than I am with a callable symbol that acts differently in terms of overloading and overriding. I'll admit, I'm not the DIP author, and I don't know the intention of whether the implementation is allowed to be there or not.
 The important thing here is that the library writer gives fair warning
 that a breaking change is coming, giving the user time to update his
 code at his convenience.
Or, if the tag is added to the actual implementation then there IS NO FREAKING BREAKING CHANGE until the new_func or whatever tag is removed, but the library user is STILL given fair (albiet useless, imo) warning that it will be (kinda sorta) broken (with a downright trivial fix) in a followup release.
Not sure I agree there would be no breakage. The symbol is there, it can be called in some cases. This changes behavior without warning. I've had my share of is(typeof(trycallingThis())) blow up spectacularly in ways I didn't predict. To change what happens there is a bad idea IMO. -Steve
May 11
prev sibling next sibling parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 4/24/17 11:03 AM, Mike Parker wrote:
 DIP 1007 is titled "'future symbol' Compiler Concept".

 https://github.com/dlang/DIPs/blob/master/DIPs/DIP1007.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 15 (3:59 AM GMT May 16), 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!
As I mentioned elsewhere, an intermediate step for a symbol that will eventually need an override needs to be outlined. When you create a base class member that conflicts with existing derived class members, the mitigation may not simply be "you have to remove the derived function", it could also be to override the future function. How do you override a function that doesn't really exist? I like the general idea, and it makes sense, even if it only affects a small set of files (those that are heavily imported). -Steve
Apr 25
prev sibling parent reply "Nick Sabalausky (Abscissa)" <SeeWebsiteToContactMe semitwist.com> writes:
This is what FQNs are for. At least, it was before FQNs were broken, 
first by an incomplete "package.d" system and second by a goofy 
half-baked change to import rules.

FQNs need fixed. This DIP is just a questionable workaround for our 
borked FQNs that that smacks of C++-style "no breakage at all costs" 
design philosophies being applied to both D language and D libraries.
May 10
parent reply "Nick Sabalausky (Abscissa)" <SeeWebsiteToContactMe semitwist.com> writes:
On 05/10/2017 09:51 PM, Nick Sabalausky (Abscissa) wrote:
 This is what FQNs are for. At least, it was before FQNs were broken,
 first by an incomplete "package.d" system and second by a goofy
 half-baked change to import rules.

 FQNs need fixed. This DIP is just a questionable workaround for our
 borked FQNs that that smacks of C++-style "no breakage at all costs"
 design philosophies being applied to both D language and D libraries.
I guess that's my overview. More specifically, what I mean is this: D's system of fully-qualified names ("FQNs") was intended to address the matter of conflicting symbols: When a symbol name is ambiguous, instead of blindly choosing one, the compiler errors and forces the programmer to clarify. For this DIP to be convincing, I would need to see this DIP address the following: 1. Why it would be insufficient to simply rely on D's system of FQNs (if fixed from their current admittedly half-broken state)? Currently, FQNs are not addressed, or even mentioned at all, in the "Existing solutions" section. 2. Why having to disambiguate a symbol with a FQN when upgrading a library is a sufficiently large problem to justify a new language feature. (This would seem very difficult to justify, since with or without this DIP, programmer will be informed by the compiler either way that they need to disambiguate which symbol they want). Aside from FQNs, I have additional concerns: 3. Can we even except a library's author to *reliably* know ahead of time they're going to add a symbol with a particular name? Seems to me a library author would need a magic crystal ball to make effective use of this feature... 4. Unless...once they've developed a new version of their lib that's sufficiently close to release that they know that their API changes won't...umm...change any further, then they retroactively create an interim "transition" release which adds these "future" declarations...so that the programmer knows they need to adjust their code to disambiguate. But again, as in #2, the programmer will be told that *anyway* when compiling with the new version. So what's the point? 5. Once the programmer *is* informed they need to disambiguate a symbol (via this DIP or via a normal ambiguous symbol error), it's an inherently trivial (and inherently backwards-compatible) fix (which can't always be said of fixing removed-symbol deprecations - as this DIP tries to draw parallels to). So, unlike deprecated symbols, I fail to see what non-trivial benefit is to be gained by an "early notification" of a to-be-added symbol. I think this DIP would have merit in a language that had a tendency for symbols to hijack each other. But D's module system already eliminates that, so AFAICT, the only thing this DIP is left "improving" is to allow lib authors, only under very select circumstances, to go out of their way to provide ahead-of-time notice of a guaranteed-trivial fix they must make (at least once FQNs are actually fixed). Therefore, I find the whole idea extremely unconvincing.
May 10
parent reply "Nick Sabalausky (Abscissa)" <SeeWebsiteToContactMe semitwist.com> writes:
On 05/10/2017 11:04 PM, Nick Sabalausky (Abscissa) wrote:
 On 05/10/2017 09:51 PM, Nick Sabalausky (Abscissa) wrote:
 This is what FQNs are for. At least, it was before FQNs were broken,
 first by an incomplete "package.d" system and second by a goofy
 half-baked change to import rules.

 FQNs need fixed. This DIP is just a questionable workaround for our
 borked FQNs that that smacks of C++-style "no breakage at all costs"
 design philosophies being applied to both D language and D libraries.
I guess that's my overview. More specifically, what I mean is this:
Ugh, frustrating... Seems like every time I try to clarify something I manage to make a jumbled mess of it. Lemme see one last time if I can distill that down my basic counter-arguments: 1. Why are FQNs alone (assume they still worked like they're supposed to) not good enough? Needs to be addressed in DIP. Currently isn't. 2. The library user is already going to be informed they need to fix an ambiguity anyway, with or without this DIP. 3. Updating code to fix the ambiguity introduced by a new symbol is always trivial (or would be if FQNs were still working properly and hadn't become needlessly broken) and inherently backwards-compatible with the previous version of the lib. 3. Unlike deprecations, this only provides a heads-up for trivial matters that don't really need a heads-up notice: Unlike when symbols being added to a lib, the fix in user-code for a deprecation *can* be non-trivial and *can* be non-backwards-compatible with the previous version of the lib, depending on the exact circumstances. Therefore, unlike added symbols, the "deprecation" feature for removed symbols is justified. 4. Unlike deprecation, this feature works contrary to the actual flow of development and basic predictability: When a lib author wants to remove a symbol, they already what the symbol is, what it's named and that they have X or Y reason to remove it. But when a lib author wants to add a symbol, it's more speculative: They don't actually KNOW such details until some feature is actually written, implemented and just about ready for release. At which point it's a bit late, and awkward, to go putting in a "foo *will* be added".
May 10
parent reply Dicebot <public dicebot.lv> writes:
On Thursday, 11 May 2017 at 03:46:55 UTC, Nick Sabalausky 
(Abscissa) wrote:
 1. Why are FQNs alone (assume they still worked like they're 
 supposed to) not good enough? Needs to be addressed in DIP. 
 Currently isn't.
It is already addressed in the DIP. FQNs only help if they are used and current idiomatic D code tends to rely on unqualified imports/names.
 2. The library user is already going to be informed they need 
 to fix an ambiguity anyway, with or without this DIP.
Only if you consider "after compiler/library upgrade your project doesn't work anymore" a sufficient "informing" which we definitely don't.
 3. Updating code to fix the ambiguity introduced by a new 
 symbol is always trivial (or would be if FQNs were still 
 working properly and hadn't become needlessly broken) and 
 inherently backwards-compatible with the previous version of 
 the lib.
Trivial compilation error fixup that takes 5 minutes to address in a single project takes up to one month to propagate across all our libraries in projects per my experience. Actually fixing code is hardly a problem with breaking changes, ever. It is synchronization between developers and projects that makes it so painful. And in override case, there is no backwards compatible solution available at all (see Steven comment).
 Unlike when symbols being added to a lib, the fix in user-code 
 for a deprecation *can* be non-trivial and *can* be 
 non-backwards-compatible with the previous version of the lib, 
 depending on the exact circumstances. Therefore, unlike added 
 symbols, the "deprecation" feature for removed symbols is 
 justified.
Please elaborate. User code fix is always either using FQN or renaming, what non-trivial case comes to your mind?
 4. Unlike deprecation, this feature works contrary to the 
 actual flow of development and basic predictability:

 When a lib author wants to remove a symbol, they already what 
 the symbol is, what it's named and that they have X or Y reason 
 to remove it. But when a lib author wants to add a symbol, it's 
 more speculative: They don't actually KNOW such details until 
 some feature is actually written, implemented and just about 
 ready for release. At which point it's a bit late, and awkward, 
 to go putting in a "foo *will* be added".
You describe a typical library that doesn't follow SemVer and generally doesn't bother much about providing any upgrade stability. Naturally, such library developer will ignore ` future` completely and keep following same development patterns. Not everyone is like that though. This document (https://github.com/sociomantic-tsunami/neptune/blob/master/doc/lib ary-maintainer.rst) explains the versioning/development model we use for all D libraries and within such model feature that is written in one major version can be added as ` future` in the previous major version at the same time. And for druntime object.d case it is pretty much always worth the gain to delay merging already implemented addition for one release, putting ` future` stub in the one before. There can never be any hurry so there is no way to be "late".
May 11
parent reply "Nick Sabalausky (Abscissa)" <SeeWebsiteToContactMe semitwist.com> writes:
On 05/11/2017 06:10 AM, Dicebot wrote:
 On Thursday, 11 May 2017 at 03:46:55 UTC, Nick Sabalausky (Abscissa) wrote:
 1. Why are FQNs alone (assume they still worked like they're supposed
 to) not good enough? Needs to be addressed in DIP. Currently isn't.
It is already addressed in the DIP. FQNs only help if they are used and current idiomatic D code tends to rely on unqualified imports/names.
I didn't see that. Certainly not in the "Existing solutions" section. It needs to be there. But in any case, I'm not talking about the "existing solution" of projects *already* using FQNs for things, I'm talking about the "existing solution" of just letting a library user spend two seconds adding an FQN when they need to disambiguate.
 2. The library user is already going to be informed they need to fix
 an ambiguity anyway, with or without this DIP.
Only if you consider "after compiler/library upgrade your project doesn't work anymore" a sufficient "informing" which we definitely don't.
I definitely do. But even if you don't, see my " new_func" alternate suggestion.
 3. Updating code to fix the ambiguity introduced by a new symbol is
 always trivial (or would be if FQNs were still working properly and
 hadn't become needlessly broken) and inherently backwards-compatible
 with the previous version of the lib.
Trivial compilation error fixup that takes 5 minutes to address in a single project takes up to one month to propagate across all our libraries in projects per my experience. Actually fixing code is hardly a problem with breaking changes, ever. It is synchronization between developers and projects that makes it so painful.
This needs to go in the DIP.
 And in override case, there is no backwards compatible solution
 available at all (see Steven comment).
This needs to be made explicit in the DIP. Currently, I see nothing in the DIP clarifying that FQNs cannot address the override case.
 Unlike when symbols being added to a lib, the fix in user-code for a
 deprecation *can* be non-trivial and *can* be non-backwards-compatible
 with the previous version of the lib, depending on the exact
 circumstances. Therefore, unlike added symbols, the "deprecation"
 feature for removed symbols is justified.
Please elaborate. User code fix is always either using FQN or renaming, what non-trivial case comes to your mind?
For *added* symbols, yes. Which is why I find this DIP to be of questionable value compared to " deprecated". That's what my quoted paragraph above is referring to: *removed* (ie, deprecated) symbols. When a symbol is *removed*, the user code fix is NOT always guaranteed to be trivial. That's what justifies the existence of deprecated. future, OTOH, doesn't meet the same criteria strength because, as you say, when a symbol is added, "User code fix is always either using FQN or renaming".
May 11
parent Dicebot <public dicebot.lv> writes:
On Thursday, 11 May 2017 at 17:35:31 UTC, Nick Sabalausky 
(Abscissa) wrote:
 It is already addressed in the DIP. FQNs only help if they are 
 used and
 current idiomatic D code tends to rely on unqualified 
 imports/names.
I didn't see that. Certainly not in the "Existing solutions" section. It needs to be there.
It is mostly discussed in "Comparison with other languages" section - it is not a solution for the DIP problem, it is one of problems the DIP tries to solve. You put it kind of backwards in my opinion.
 Only if you consider "after compiler/library upgrade your 
 project
 doesn't work anymore" a sufficient "informing" which we 
 definitely don't.
I definitely do. But even if you don't, see my " new_func" alternate suggestion.
This suggestion seems considerably more complex - it requires either additional tools to specify "yes, I truly want to use that new function" or forcing developer to always use FQN to do it. Required compiler changes are likely to be more convoluted too because same symbols would have to be interpreted as regular of "fake" ones depending on the context. Most importantly, I don't see motivation behind it. For conservatively maintained libraries defining no-op stub one version before introducing actual implementation is hardly a problem. Everyone else won't bother about it at all and just add new symbols in a regular manner.
 Trivial compilation error fixup that takes 5 minutes to 
 address in a
 single project takes up to one month to propagate across all 
 our
 libraries in projects per my experience. Actually fixing code 
 is hardly
 a problem with breaking changes, ever. It is synchronization 
 between
 developers and projects that makes it so painful.
This needs to go in the DIP.
No, it does not. That paragraph is a generic rationale why _any_ breaking changes without deprecation paths are so painful. I have no interest in trying to convince anyone who doesn't get it by now.
 And in override case, there is no backwards compatible solution
 available at all (see Steven comment).
This needs to be made explicit in the DIP. Currently, I see nothing in the DIP clarifying that FQNs cannot address the override case.
Yeah, will do.
May 14