A recent F# language version brought several features, including for instance match! support.
As releases of Visual Studio, .NET Core SDK, Visual F# Tools and FSharp.Core are synchronised, newer features are available when all these components are updated, which I suppose can be updated together by user.
When using third-party tooling, versions of bundled FCS, an actual compiler resolved by MSBuild and FSharp.Core may be misaligned which in turn may lead to some language features being available in the tooling but could be missing in the old compiler bundled in the SDK or on CI server.
I propose we introduce an additional compiler flag which would specify a target language version with an MSBuild LangVersion property, just like how it is handled in C# and VB tooling. Unlike specifying FSharp.Core version in MSBuild that flag should restrict language features available by compiler like the match! example above along with other lexing, parsing and type-checking changes, not the target language core library version. Using such property would ensure both the compiler and tooling have same language features available.
A possible problem may arise when using latest or default language versions that _again_ may be different between the bundled FCS and the actual compiler, say 4.5 and 4.1 respectively. However, it is possible to produce a warning when the current compiler version is known to be lower than the one in FCS which would help in local builds during development.
@KevinRansom and I discussed this a bit, and we're just not set up to be able to handle this sort of thing with our testing and infrastructure without dropping significant work to build it out, verify nothing broke, and have a sane maintenance story.
However, we are strongly considering two trains for F# components in VS: release and "canary" (or something like that). Since we are side-by-side, we can do this sort of thing without infecting stable bits on someone's machine. This would let you test things like upcoming F# features (e.g., Anonymous Records), then back off onto stable bits just by toggling something in settings.
Making this story cross-platform is challenging for the compiler, because we need to insert into a build of the .NET SDK to hop onto their daily builds. Not sure how that would work out, but a configuration story could probably be done with global.json files?
@auduchinok @cartermp This was mentioned in #4499.
There are two things proposed:
a /langversion:5.0 switch (which is either /langversion:5.0 or perhaps /langversion:latest in new project files) which enables new language features
a /langfixes:5.0 switch (which is either /langfixes:5.0 or perhaps /langfixes:latest in new project files) which enables not-purely-backwards-compatible adjustments or "fixes" to existing language features.
I don't have strong feelings about (1) but as language designer I do have strong feelings about (2) - we absolutely need this to be able to make progress on some corner cases of the language design.
So my feeling is that we should add a /langfixes switch. Like the whole FSharp.Core version discussion, my feeling is also that the version should be pinned in the project files, so tooling upgrades don't change the compilation of existing projects in substantive ways.
Exactly what counts as a "language fix" is a little subjective but roughly speaking it's anything where there is a substantial chance that the change is no fully backwards compatible according to our existing bar (we accept some bug fixes that are not backwards compatible).
For testing, we should simply make sure that each such fix is tested negatively and positively with compilations using the appropriate /langfixes level.
I'm less concerned by /langversion because historically we've been able to roll out new features without too much drama - indeed tooling often gets these features first because integrations into FCS often happen before the finalized version of a Visual Studio or .NET SDK or Mono release.
Doing (1) brings us much more in line with C# and is what I'd prefer. I think "langfixes" is a bit murky and it would be strange to have different versions of features in the same language version, or a "partial F# 5.0" language version that depends on compatibility choices.
So /langversion:5.0 would imply /langfixes:5.0 in my terminology? I may be comfortable with that.
@KevinRansom How can we proceed with the MSBuild property? That is essential from a usability standpoint
Most helpful comment
@auduchinok @cartermp This was mentioned in #4499.
There are two things proposed:
a
/langversion:5.0switch (which is either/langversion:5.0or perhaps/langversion:latestin new project files) which enables new language featuresa
/langfixes:5.0switch (which is either/langfixes:5.0or perhaps/langfixes:latestin new project files) which enables not-purely-backwards-compatible adjustments or "fixes" to existing language features.I don't have strong feelings about (1) but as language designer I do have strong feelings about (2) - we absolutely need this to be able to make progress on some corner cases of the language design.
So my feeling is that we should add a
/langfixesswitch. Like the whole FSharp.Core version discussion, my feeling is also that the version should be pinned in the project files, so tooling upgrades don't change the compilation of existing projects in substantive ways.Exactly what counts as a "language fix" is a little subjective but roughly speaking it's anything where there is a substantial chance that the change is no fully backwards compatible according to our existing bar (we accept some bug fixes that are not backwards compatible).
For testing, we should simply make sure that each such fix is tested negatively and positively with compilations using the appropriate
/langfixeslevel.I'm less concerned by
/langversionbecause historically we've been able to roll out new features without too much drama - indeed tooling often gets these features first because integrations into FCS often happen before the finalized version of a Visual Studio or .NET SDK or Mono release.