Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 16, 2025

Summary

This PR adds the --disableLanguageFeature CLI switch and corresponding MSBuild property, enabling developers to selectively disable specific F# language features on a per-project basis. This is useful for enforcing coding standards, maintaining compatibility with older codebases, or gradually migrating code that relies on features being phased out.

What's Added

CLI Switch

  • New --disableLanguageFeature:<FeatureName> option (repeatable)
  • Case-insensitive feature names
  • Error 3879 for invalid feature names

MSBuild Integration

  • <DisabledLanguageFeatures> ItemGroup property in .fsproj files
  • Passes through to Fsc task via Microsoft.FSharp.Targets

Implementation Details

  • Uses reflection to map feature names to LanguageFeature enum cases (no manual mapping required)
  • Immutable design with WithDisabledFeatures copy-and-update method
  • Features stored as Set in TcConfigBuilder, converted to array in LanguageVersion
  • Properly integrated with FSharpChecker cache keys via OtherOptions comparison

Usage Example

CLI:

fsc --disableLanguageFeature:NameOf --disableLanguageFeature:StringInterpolation code.fs

MSBuild (.fsproj):

<ItemGroup>
  <DisabledLanguageFeatures Include="NameOf" />
  <DisabledLanguageFeatures Include="StringInterpolation" />
</ItemGroup>

Testing

  • 6 comprehensive unit tests covering various scenarios
  • Help baseline tests updated for both FSC and FSI
  • All tests passing
Original prompt

Motivation:
Enable a way to selectively disable specific F# language features on a per-project basis by providing a repeatable command line switch, even when the language version would otherwise enable the feature. This is useful for regression-testing, troubleshooting, or as an off-switch for problematic or experimental features.

Scope:

  • A repeatable CLI argument is added: --disableLanguageFeature:
  • For every entry, parse the argument to the LanguageFeature DU. Validate (fail with an error listing valid feature names if not present).
  • Temporarily collect/hold the array of disabled features during CLI/config processing until LanguageVersion is constructed.
  • Pass the array into LanguageVersion at all construction sites.
  • LanguageVersion stores the array and updates SupportsFeature: it returns false if the feature is listed in the disables array, regardless of language version.
  • Use Array.contains for the disables check. No Sets/Lists/Dicts are needed.
  • All feature-gating through SupportsFeature: no callsite changes.
  • Add help text for the new CLI switch (FSComp.txt and in CompilerOptions).
  • Add a negative ComponentTest for a previously positive feature, showing that disabling the feature (e.g. WhileBang) causes a compile error even in preview mode.
  • Rerun and update CLI/help output tests (e.g., fsc-help.txt) as needed.

Paths to touch:

  • src/Compiler/Driver/CompilerOptions.fs
  • src/Compiler/Facilities/LanguageFeatures.fs
  • src/Compiler/Facilities/LanguageFeatures.fsi
  • src/fsharp/FSharp.Compiler.Interactive.Settings/FSComp.txt
  • tests/FSharp.Compiler.ComponentTests/Language/WhileBangTests.fs
  • tests/fsharp/**/fsc-help.txt (and/or similar help output checks)

Constraints:

  • No significant churn or callsite changes; only extend existing flow.
  • Disabled feature array only lives outside LanguageVersion as a temporary transport.
  • Error diagnostics for invalid feature names must be user-friendly, with a list of valid LanguageFeature options.
  • Test must be minimal; reuse existing test files, just add one negative case for disables.
  • Keep the implementation idiomatic and minimal.

This pull request was created as a result of the following prompt from Copilot chat.

Motivation:
Enable a way to selectively disable specific F# language features on a per-project basis by providing a repeatable command line switch, even when the language version would otherwise enable the feature. This is useful for regression-testing, troubleshooting, or as an off-switch for problematic or experimental features.

Scope:

  • A repeatable CLI argument is added: --disableLanguageFeature:
  • For every entry, parse the argument to the LanguageFeature DU. Validate (fail with an error listing valid feature names if not present).
  • Temporarily collect/hold the array of disabled features during CLI/config processing until LanguageVersion is constructed.
  • Pass the array into LanguageVersion at all construction sites.
  • LanguageVersion stores the array and updates SupportsFeature: it returns false if the feature is listed in the disables array, regardless of language version.
  • Use Array.contains for the disables check. No Sets/Lists/Dicts are needed.
  • All feature-gating through SupportsFeature: no callsite changes.
  • Add help text for the new CLI switch (FSComp.txt and in CompilerOptions).
  • Add a negative ComponentTest for a previously positive feature, showing that disabling the feature (e.g. WhileBang) causes a compile error even in preview mode.
  • Rerun and update CLI/help output tests (e.g., fsc-help.txt) as needed.

Paths to touch:

  • src/Compiler/Driver/CompilerOptions.fs
  • src/Compiler/Facilities/LanguageFeatures.fs
  • src/Compiler/Facilities/LanguageFeatures.fsi
  • src/fsharp/FSharp.Compiler.Interactive.Settings/FSComp.txt
  • tests/FSharp.Compiler.ComponentTests/Language/WhileBangTests.fs
  • tests/fsharp/**/fsc-help.txt (and/or similar help output checks)

Constraints:

  • No significant churn or callsite changes; only extend existing flow.
  • Disabled feature array only lives outside LanguageVersion as a temporary transport.
  • Error diagnostics for invalid feature names must be user-friendly, with a list of valid LanguageFeature options.
  • Test must be minimal; reuse existing test files, just add one negative case for disables.
  • Keep the implementation idiomatic and minimal.

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI and others added 3 commits December 16, 2025 13:01
- Added TryParseFeature method to LanguageVersion to parse feature names from strings
- Added disabledLanguageFeatures field to TcConfigBuilder to store disabled features
- Added SupportsFeature method to TcConfigBuilder that checks both langVersion and disabled features
- Added --disableLanguageFeature CLI option in CompilerOptions (repeatable)
- Added error message for unrecognized feature names (error 3879)
- Created comprehensive tests for the new functionality

Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
- Applied fantomas formatting to modified files
- Added release notes entry for the new --disableLanguageFeature CLI switch

Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
- Modified LanguageVersion to hold disabled features and check them in SupportsFeature
- Added SetDisabledFeatures method to LanguageVersion
- Updated both langversion and disableLanguageFeature options to call SetDisabledFeatures
- This ensures disabled features are respected regardless of option order
- Applied code formatting

Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
Copilot AI changed the title [WIP] Add command line argument to disable F# language features Add --disableLanguageFeature CLI switch to selectively disable language features Dec 16, 2025
Copilot AI requested a review from T-Gro December 16, 2025 13:22
Copy link
Member

@T-Gro T-Gro left a comment

Choose a reason for hiding this comment

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

@copilot : Read all comments

@github-project-automation github-project-automation bot moved this from New to In Progress in F# Compiler and Tooling Dec 16, 2025
As requested, removed the SupportsFeature method from TcConfigBuilder since it's not used anywhere and is redundant - callers can directly use langVersion.SupportsFeature()

Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
…re parsing

- Changed LanguageVersion to use immutable array of disabled features instead of mutable set
- Added optional constructor parameter for disabled features array
- Added WithDisabledFeatures method that returns a new LanguageVersion instance
- Replaced manual feature name mapping with reflection-based TryParseFeature using BindingFlags.NonPublic
- Updated CompilerOptions to use immutable pattern with Array.append
- Changed disabledLanguageFeatures in TcConfigBuilder from Set to array
- Updated tests to use typecheck instead of compile and assert exact error codes
- Applied code formatting

Addresses feedback from @T-Gro about making the design immutable and using reflection.

Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
Copilot AI and others added 3 commits December 17, 2025 16:59
- Added null check in TryParseFeature using Option.bind before downcasting
- Changed disabledLanguageFeatures from array to Set in CompilerConfig (better semantics)
- Updated CompilerOptions to use Set.add and convert to array when calling WithDisabledFeatures
- Applied code formatting

Addresses comments from @T-Gro about null handling and using Set in the builder.

Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
Updated compiler_help_output.bsl to include the new --disableLanguageFeature CLI option in help output.

Addresses comment from @T-Gro about updating help tests.

Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
- Added disabledLanguageFeatures field to Fsc task
- Added DisabledLanguageFeatures property (takes ITaskItem array)
- Updated command line builder to pass each feature with --disableLanguageFeature flag
- Follows same pattern as other MSBuild properties

This allows .fsproj files to use:
<DisabledLanguageFeatures>NameOf;StringInterpolation</DisabledLanguageFeatures>

Partial implementation of comment 2627788945 from @T-Gro. Still need to update .targets files.

Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
Copilot AI changed the title Add --disableLanguageFeature CLI switch to selectively disable language features Add --disableLanguageFeature CLI switch and MSBuild property to selectively disable language features Dec 17, 2025
Copilot AI requested a review from T-Gro December 17, 2025 17:10
@dotnet dotnet deleted a comment from Copilot AI Jan 14, 2026
@github-actions
Copy link
Contributor

🔧 CLI Command Report

  • Command: /run ilverify
  • Outcome: success

✅ Command succeeded, no changes needed.

@T-Gro T-Gro marked this pull request as ready for review January 19, 2026 12:55
@T-Gro T-Gro requested a review from a team as a code owner January 19, 2026 12:55
@T-Gro T-Gro changed the title [WIP] Add --disableLanguageFeature CLI switch and MSBuild property to selectively disable language features Add --disableLanguageFeature CLI switch and MSBuild property to selectively disable language features Jan 19, 2026
@T-Gro
Copy link
Member

T-Gro commented Jan 19, 2026

@copilot : Make proper 10.0.200 release notes pointing to this PR #19167 .
Also change the PR description to summarize what has been done and why, remove the how and intermediate checklists.

- Created docs/release-notes/.Language/10.0.200.md with the new feature entry
- Removed duplicate entry from preview.md
- Updated PR reference from "TBD" to actual PR #19167

Addresses comment 3768217127.

Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Jan 19, 2026

@copilot : Make proper 10.0.200 release notes pointing to this PR #19167 .
Also change the PR description to summarize what has been done and why, remove the how ...

Updated in commit 4903ffc:

@T-Gro T-Gro enabled auto-merge (squash) January 19, 2026 13:34
@T-Gro T-Gro requested a review from abonie January 19, 2026 13:35
@T-Gro T-Gro added the NO_RELEASE_NOTES Label for pull requests which signals, that user opted-out of providing release notes label Jan 19, 2026
@T-Gro T-Gro merged commit d795504 into main Jan 20, 2026
40 of 41 checks passed
@auduchinok
Copy link
Member

I think this may add additional maintenance cost for the tooling with all the possible combinations of language features and versions. @T-Gro Could you please share some context why it was added? Was it because some specific feature was unwanted?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

NO_RELEASE_NOTES Label for pull requests which signals, that user opted-out of providing release notes

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

5 participants