Thread overview
Language Versioning
Apr 04, 2019
Jonathan Marler
Apr 04, 2019
Jacob Carlborg
May 26, 2019
KnightMare
April 04, 2019
This is an informal proposal to add a versioning scheme to the D Language.  If you'd like to take the time to read, please let everyone know your thoughts and suggestions for the idea.  To Walter and Andrei, please let me know your thoughts, if you think the idea has merit and if so what the next steps should be (i.e. DIP/PR/More Resarch Discussion Needed).

As I've been thinking about various proposals and additions to the D language, it occurred to me that I'd like to be able to declare inside my code that it requires a certain version or certain features of the D language in order to work properly.  For example, when I look at the changelog for DMD version 2.085, I see that support for Objective-C classes was added.  However, I would be hesitant to use that feature until a certain amount of time has passed. This is because using it would make my libraries/applications only work with a small percentage of compilers in the world, those who have recently updated their compiler, and the error messages people would get could make it difficult to know that they just need to update their compiler for it to work with my code.  Currently the only way to solve this problem is to wait a certain amount of time until I feel its reasonable that enough people will have updated their compiler.

I think we can do better.

My current idea is to implement a list of versions and feature names.  Such a list could be dumped with something like:

> dmd --list-versions
2018_02_03 StaticForeach
2018_02_20 NoGCExceptions
2018_03_10 ObjectiveCClasses
Implemented StaticForeach
Implemented NamedParameters
NotImplemented CopyConstructor
NotImplemented ExpressionBasedContracts

The idea here is that once a feature has been implemented and has been enabled by default, the version would be updated and that particular feature would be assigned to that version.  Also note that the version number represents a date, which allows the compiler to know when that version was implemented so it can know how "out-of-date" it is (i.e. 2 years, 1 month etc). You'll also notice that some features were not assigned a version number but were either assigned an "Implemented" or "NotImplmeented" tag.  This indicates whether or the feature can be enabled, where "Implemented" means it can.  Once a feature has been implemented and enabled by default, then it will be assigned a version number representing the date it was enabled by default.

Then we can add ways for modules to declare version/feature requirements, such as:

pragma(dlangVersionAtLeast, 2017_11_25);
pragma(dlangVersionUpTo, 2018_09_02);
pragma(requireFeature, ObjectiveCClasses);

The way the compiler handles these pragmas can allow the compiler to print nice error messages when it can't satisfy the version/feature requirements of the module.  For example, if a module declares `pragma(dlangVersionAtLeast, 2019_01_02)`, but it only support up to version 2018_05_06, then it can print an error message like:

Error: module 'x' requires dlang version '2019_01_02' but you're at version '2018_05_06'.  Your compiler is 7 months too old to compile this code.

Notice that since the version has the date encoded into it, the compiler knows how old it is compared to the compiler version it needs to compile this module.

Since each version is also tied to a feature name, this would also allow modules to enable features even when they aren't turned on by default, i.e.

pragma(requireFeature, NoGCExceptions);

If possible, this could have the same affect as specifying `-dip1008` on the command-line.  In some cases, there may be features that can't be enabled once you've already started compilation of modules, and in this cases you could get a nice error message like:

Error: module 'x' requires the 'NoGCExceptions' feature.  Please provide the '-dip1008' option to compile this code.

Of course, if this versioning is enabled, each version could use a general command-line syntax such as
`--enable-feature=NoGCExceptions`.

Along with these pragmas, another feature would be to allow code to obtain the version and/or check whether certain features can be enabled at compile time to work with multiple version of the lanaguage.  So adding a couple traits like

__traits(tryEnableFeature, NoGCExceptions)

And could be used like:

static if (__traits(tryEnableFeature, NoGCExceptions))
{
    @nogc:
}

As D matures, these versioning mechanisms could alleviate some of the pain in introducing new features to the language by allowing the compilers of today to be aware of the timeline and feature names of features that are yet to be implemented.  It also allows the code to declare what features it can work with and even allow it to work adapt based on the version of the compiler you are using. Furthermore, it provides the opportunity to support a consistent command-line syntax that will always work when a new feature is introduced.

April 04, 2019
On 2019-04-04 14:38, Jonathan Marler wrote:
> This is an informal proposal to add a versioning scheme to the D Language.  If you'd like to take the time to read, please let everyone know your thoughts and suggestions for the idea.  To Walter and Andrei, please let me know your thoughts, if you think the idea has merit and if so what the next steps should be (i.e. DIP/PR/More Resarch Discussion Needed).
> 
> As I've been thinking about various proposals and additions to the D language, it occurred to me that I'd like to be able to declare inside my code that it requires a certain version or certain features of the D language in order to work properly. For example, when I look at the changelog for DMD version 2.085, I see that support for Objective-C classes was added.  However, I would be hesitant to use that feature until a certain amount of time has passed. This is because using it would make my libraries/applications only work with a small percentage of compilers in the world, those who have recently updated their compiler, and the error messages people would get could make it difficult to know that they just need to update their compiler for it to work with my code.  Currently the only way to solve this problem is to wait a certain amount of time until I feel its reasonable that enough people will have updated their compiler.

Today it's possible to use the special `__VERSION__` token [1]. There's also `__traits(compiles)` which can be used to check if a feature is available. The latest version of Dub supports specifying tool chain requirements. That include which compiler, which version or which version of the frontend that is required [2].

> I think we can do better.
> 
> My current idea is to implement a list of versions and feature names.  Such a list could be dumped with something like:
> 
>> dmd --list-versions
> 2018_02_03 StaticForeach
> 2018_02_20 NoGCExceptions
> 2018_03_10 ObjectiveCClasses
> Implemented StaticForeach
> Implemented NamedParameters
> NotImplemented CopyConstructor
> NotImplemented ExpressionBasedContracts

Which features would be included in the list, all?

In general I think it's better to query if a specific feature is available or not instead of query a version or date.

[1] https://dlang.org/spec/lex.html#special-token-sequence
[2] https://dub.pm/package-format-sdl.html#toolchain-requirements

-- 
/Jacob Carlborg
May 26, 2019
> pragma(dlangVersionAtLeast, 2017_11_25);
IMO pragmas are not very well in all cases.
For example I have thousands LOCs with using std.xml ver1, but current version is ver2.2. I dont want rewrite code to ver2.2, I should point to ver1.

In your case I see it like this:
import std.stdio;
pragma(dlangVersionAtLeast, 2017_11_25);
// I dont sure that it will work now
import std.xml;
pragma(dlangVersionAtLeast, Uptodate);
import std.anotherModules;
// or we can use some attribute @version("2017_11_15")

In my vision I request it explicitly:
import std.xml 1.*; // or
import std.xml 1.* : someFuncAndClassList; // or
import std.xml 2017_11;
// or/and setup some fixed date in project settings for implicit modules

I wrote my vision in topic https://forum.dlang.org/post/hgspjuiqjjtptdexwlus@forum.dlang.org
Probably better to continue talks in one topic.