-
Notifications
You must be signed in to change notification settings - Fork 264
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
Add -experimental flag #617
base: master
Are you sure you want to change the base?
Changes from 3 commits
d529659
2b2f815
1c27756
4ed31ad
1686c3a
8c29ad0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,177 @@ | ||||||
Add -experimental flag | ||||||
====================== | ||||||
|
||||||
.. author:: Moritz Angermann, Julian Ospald | ||||||
.. date-accepted:: | ||||||
.. ticket-url:: | ||||||
.. implemented:: | ||||||
.. highlight:: haskell | ||||||
.. header:: This proposal is `discussed at this pull request <https://github.com/ghc-proposals/ghc-proposals/pull/617>`_. | ||||||
.. sectnum:: | ||||||
.. contents:: | ||||||
|
||||||
Introduce a new compiler flag ``-experimental`` which guards experimental | ||||||
features. We distinguish between experimental and non-experimental features by | ||||||
their respective breaking change processes. Experimental features may introduce | ||||||
breaking changes without prior warning at any time. Non-experimental (stable) | ||||||
features on the other hand would need to follow a change evolution/deprecation | ||||||
process and could only under exceptional circumstances introduce breaking | ||||||
changes. | ||||||
|
||||||
Motivation | ||||||
---------- | ||||||
As GHC continues to evolve, there's a need to introduce new features that may | ||||||
not be fully stabilized or might undergo significant changes in future releases. | ||||||
These experimental features can potentially introduce breaking changes without | ||||||
warning between different compiler versions. By introducing the | ||||||
``-experimental`` flag, developers can opt-in to use these features, fully | ||||||
aware of the potential risks. This ensures that features available without this | ||||||
flag are stable and will only have breaking changes with a proper deprecation | ||||||
cycle. | ||||||
|
||||||
What is _currently_ considered experimental can at best be found out by proxy | ||||||
via a `GHC User Guide's search for EXPERIMENTAL <https://downloads.haskell.org/ghc/latest/docs/users_guide/search.html?q=EXPERIMENTAL&check_keywords=yes&area=default>`_. | ||||||
|
||||||
|
||||||
Proposed Change Specification | ||||||
----------------------------- | ||||||
- Introduce a new compiler flag ``-experimental``. | ||||||
- Introduce a new compiler flag ``-no-experimental`` (default). | ||||||
- Features not behind the ``-experimental`` flag will have to adhere to a | ||||||
deprecation cycle before introducing breaking changes. | ||||||
|
||||||
``-experimental`` is a superset, therefore ``-experimental`` could | ||||||
depend on code without ``-experimental``. The inverse does not hold. | ||||||
|
||||||
Semantically the last ``-[no-]experimental`` flag passed to GHC will win. | ||||||
|
||||||
Examples | ||||||
-------- | ||||||
Consider a hypothetical experimental feature ``X``. Without the | ||||||
``-experimental`` flag, trying to use ``X`` would result in a compiler error. | ||||||
However, with the flag, the feature can be used, but with the understanding that | ||||||
it might change in future releases. :: | ||||||
|
||||||
-- Without -experimental | ||||||
ghc Main.hs -- This will throw an error if Feature X is used | ||||||
|
||||||
-- With -experimental | ||||||
ghc -experimental Main.hs -- This will compile successfully with Feature X | ||||||
|
||||||
-- With -no-experimental | ||||||
ghc -experimental -no-experimental Main.hs -- This will throw an error if Feature X is used | ||||||
|
||||||
ghc -no-experimental Main.hs -package foo -- This will throw an error if Feature X is used anywhere in Main.hs or the package foo. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This implies a feature that's not listed in the change specification: that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @angerman Are you planning to address this comment from @michaelpj? The Proposed Change Specification is currently very brief. I think we need a lot more detail about the semantics of the flag: how does it relate to |
||||||
|
||||||
Effect and Interactions | ||||||
----------------------- | ||||||
The introduction of this flag provides a clear distinction between stable and | ||||||
experimental features. It ensures that developers are aware of the potential | ||||||
risks of using experimental features while providing a sandbox for testing out | ||||||
new GHC capabilities. | ||||||
|
||||||
Costs and Drawbacks | ||||||
------------------- | ||||||
- There might be an initial learning curve for developers to understand the | ||||||
distinction between experimental and stable features. | ||||||
- Maintaining two sets of features (stable and experimental) might increase the | ||||||
complexity of the compiler codebase. | ||||||
|
||||||
The authors believe the benefit of clearly separating experimental and those | ||||||
that adhere to a more rigourous change evolution easily offsets the costs for | ||||||
both end users and feature developers. For developers of experimental feature | ||||||
this also means they reserve the rigth to break them without warning in | ||||||
angerman marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
backwards incompatible ways at any moment in time leading to significantly | ||||||
lighter processes for experimental features. | ||||||
|
||||||
Prior Work | ||||||
---------- | ||||||
The ``-experimental`` feature is similar to solutions for experimental | ||||||
features and implementation in other languages, and GHC would not have a | ||||||
bespoke solution here, but share a common approach with many other compilers. | ||||||
Do note that the provided approaches mix editions, channels, and feature gates. | ||||||
The goal is to illustrate that the concept of separating experimental features | ||||||
explicitly behind opt-in gates. | ||||||
|
||||||
- **Rust**: Rust has so called channels, which delineate stability by stable, | ||||||
beta, and nightly. To opt-in locally to nightly features you'd use the | ||||||
``+nightly`` toolchain modifier. Effectively using a different Rust compiler | ||||||
provided by ``rustup``. | ||||||
- **Java**: Java has the ``--enable-preview`` flag since Java 9, which allows | ||||||
opt-in to experimental features. | ||||||
- **Gnu Compiler Collection**: GCC provides flags to opt-in to experimental | ||||||
features through the ``-std=...`` flag. For example, it has flags like | ||||||
``-std=c++1z`` for experimental C++ features before they were standardized in | ||||||
C++17. | ||||||
|
||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure if this needs to be added to this proposal. However, I think it might be worth to take a look at https://kotlinlang.org/docs/opt-in-requirements.html 😸 N.B. this relates to API features, not Compiler features. |
||||||
Backward Compatibility | ||||||
---------------------- | ||||||
The introduction of this flag is expected to have minimal impact on existing | ||||||
code. The initial set of features behind the ``-experimental`` flag will be | ||||||
the empty set. Follow up proposals will be required to move existing features | ||||||
behind the `-experimental` flag. New features should by default be behind | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't moving a feature behind There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The beauty of the proposal is that stable part is not actually stable. it just won't change without a deprecation period. So we can still argue on how long something needs to be deprecated before moved to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Despite @phadej For extensions there is #601 which aims to describe a lifecycle. This would cover features as well. But most importantly, I think what is in -experimental and not in -experimental, should primarily be governed by how we treat it. You can't make breaking changes without an change evolution in -no-experimental parts of the compiler, while you can do that pretty freely with -experimental features and extensions.
angerman marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
the `-experimental` flag, unless the respective authors consider them stable | ||||||
angerman marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
and not subject to sudden change. | ||||||
|
||||||
Conditional Compilation | ||||||
-------------------------- | ||||||
For maintainers there will be a ``__GHC_EXPERIMENTAL__`` macro to use with ``CPP`` | ||||||
to allow for conditional compilation if ``-experimental`` is active. This can | ||||||
be used with the usual version macros to tailor to specific GHC versions as needed. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What would you use this for? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's assume you want to try some experimental feature but make it opt-in. You could have a flag in your cabal file There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you have a flag then you can simply pass your own CPP defines, so I don't see there being a reason for having this hard coded into the compiler. The only situation where you might need this is if you don't define a flag and expect users to add ghc-options in their cabal.project file but that doesn't seem like an idiomatic way to do this. I seriously doubt as well that users will even do the flag approach as most of our tooling doesn't support optional features of packages. It would be better to just have two packages one that is experimental and one that isn't. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indeed you're not supposed to change API surface based on flags or CPPs. But that's not what the proposal implies. |
||||||
|
||||||
Garbage Collection | ||||||
------------------ | ||||||
A follow up proposal will need to address the lifecycle of features behind the | ||||||
``-experimental`` flag. How features (not just extensions as in `#601`_), | ||||||
will either be removed or migrate from ``-experimental`` into the stable | ||||||
compiler. | ||||||
|
||||||
Relationship to ``Haskell98``, ``Haskell2010``, ``GHC2021``, and ``-fglasgow-exts`` | ||||||
----------------------------------------------------------------------------------- | ||||||
GHC today provides the option to *opt-in* to a collection of Extensions | ||||||
considered stable. It does *not* permit the exclusion of experimental features. | ||||||
The proposed ``-experimental`` provides the assurances on the other end of | ||||||
the spectrum. It provides a binary option to those who want to stay out of | ||||||
highly experimental features, still allowing them to augment existing | ||||||
collections within the limits of *stable* extensions. | ||||||
|
||||||
Alternatives | ||||||
------------ | ||||||
1. **Feature Flags for Each Experimental Feature**: Instead of a single flag for | ||||||
all experimental features, individual flags for each feature could be | ||||||
introduced. However, this could lead to a proliferation of flags and increase | ||||||
complexity. | ||||||
2. **Separate GHC Builds**: Provide separate GHC builds for experimental | ||||||
features. This ensures a clear separation but might be cumbersome for | ||||||
developers to manage multiple GHC installations. | ||||||
Comment on lines
+144
to
+146
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sidenote: I've been wanting to write a proposal for this. But after talking to @simonpj about this briefly, I believe it would require much more research (e.g. how does rust team deal with this), work, convincing etc. The |
||||||
|
||||||
Unresolved Questions | ||||||
-------------------- | ||||||
|
||||||
.. _`#601`: https://github.com/ghc-proposals/ghc-proposals/pull/601 | ||||||
|
||||||
1. What is the process for moving a feature from experimental to stable? Or from | ||||||
stable to experimental? This is being addressed in `#601`_. | ||||||
|
||||||
|
||||||
Risks | ||||||
----- | ||||||
|
||||||
If ``-experimental`` ends up becoming the default because library authors | ||||||
and other end up depending on experimental features, the value of having | ||||||
``-experimental`` diminishes greatly. It is therefore prudent to follow | ||||||
up with `#601`_, to provide a clear path for experimental features transitioning | ||||||
into the stable compiler. | ||||||
|
||||||
Implementation Plan | ||||||
------------------- | ||||||
The authors will try to provide a PoC for an implementation. | ||||||
|
||||||
Endorsements | ||||||
------------- | ||||||
- Erik de Castro Lopo (@erikd) | ||||||
- Kevin Hammond | ||||||
- Jens Petersen (@juhp) | ||||||
- Hécate (@kleidukos) | ||||||
- Arnaud Bailly (@abailly) | ||||||
- Matthias Benkort (@KtorZ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to bury the lede! The proposal says it is about adding a new flag, but in fact it is about instituting a much more stringent change process for a large fraction of GHC development work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This flag gives us a binary distinction between what is experimental and what is not. The exact process of lifecycle would be governed by e.g. #601 or similar proposals.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After writing the other comments further down. Let me stress that this explicitly permits to have experimental features in the compiler that can (and are permitted to) undergo rapid evolution with breaking changes at any point.