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
-XUnstable, protecting GHC's unstable features #524
base: master
Are you sure you want to change the base?
Conversation
Introducing, changing or removing unstable features should require a proposal nevertheless. Proposal process was set up to bring transparency to GHC development. |
|
Even if changes are going though GHC proposal process, I'm sceptical about this proposal:
|
So at first glance this does look like a reincarnation of But the actual contents of the proposal is not a language feature, but marking library code (even if I think it would be good to characterize this as something like Deprecation warnings / Safe Haskell --- a "taint system" on code. Indeed, I would like to be usable by regular users for Implementing that would go nicely with implementing #134 |
Also, there is a lot of prior art with Rust for this sort of thing. I would recommend becoming familiar with that. We have some sort of annotation system in GHC today that would allow marking individual definitions within modules, like Rust does, for this. But I understand it is little used because it depends on the template haskell interpreter. |
Can you give specific links to relevant documentation? Thanks! |
Several thoughts, all of which suggest changes to the proposal. MotivationThere are actually two distinct motivations here, only one of which is discussed in the proposal:
The over-arching motivation (which again isn't terribly clearly stated) is this: Note: "unstable" is not the same as "unsafe". For example Distinguishing between "internals" and "public API"Here's some code from GHC.Base
All this is part of the list-fusion mechanism.
and then be discombobulated when we change the implementation of fusion and abolish Motivation: we need a way to distinguish the "internals" of GHC from its externally-advertised API. Note:
Releasing
|
I don't think so. |
Why not make this a warning Possibly we could even have Personally I don't think there is a huge amount of value in I do think it would be nice if users could designate particular modules as unstable for importing in other packages. It's fairly common for libraries to expose their internals without making stability guarantees about them. |
Co-authored-by: tomjaguarpaw <tom-github.com@jaguarpaw.co.uk>
My motivation for this proposal is as stated in the proposal. That is, I don't see On the other hand, changing
Yes, and also a way for the general Haskelling public to contribute to GHC's direction. But what, precisely, is subject to the transparency policy? I don't think we want a process where a proposal is written for every refactoring. This suggests that some changes to GHC are too far from public view for a proposal. What about error messages? These have generally been deemed out of scope, but yet are very important to user experience. What this proposal does is to declare that some changes -- even if users might notice them -- are considered to be internal changes. This could be abused, of course, by declaring everything unstable and then emancipating us from this proposal process. However, we could have similar abuses today, by downgrading the quality of errors without public comment. Yet we don't do this. My hope would be that large features, such as linear types, would indeed continue to go through the proposal process, because this is helpful for making a great GHC. Put another way: I want to take things that right now require proposals and turn some cases into judgment calls. As one important example, #518 asks the committee to decide on an internal matter that few people are informed about other than @simonpj and me. The committee is not really offering informed consent, but rather rubber-stamping an issue that just happens to affect the language. Yes, the public debate is helpful in refining the design, but the decision isn't really an independent one. Even with
Nothing prevents something from being unstable for years, although that's something to be avoided. If it happens, someone could always write a proposal saying it should become stable. As for the other examples, only users who know that these features are unstable are using it knowledgeably at their own risk. A user who comes across LinearTypes or OverloadedRecordUpdate on a blog post might miss the disclaimer and thus not know that the ice is thinner there. |
Gladly! https://rustc-dev-guide.rust-lang.org/stability.html
Sorry, in my original comment I was contrasting "at first glance" with "the actual contents. I agree it is not, in fact, the return of I will say though that the Rust thing does force one to categorize why things are unstable, and I think that is good practice. Making an instability category that merely bundles other categories helps deal with coordinating concurrent migration cycles, where different things may end up becoming stable at different rates. Also love the shout-out to splitting base! |
Thanks for the link to the Rust approach. I agree that having multiple different bins is likely a good design, a nudge toward the warning approach instead of the language-extension approach. However, the Rust page describes a way for anyone to mark features as unstable. That's not part of this proposal, which is just about introducing a fixed, non-extensible mechanism, though I agree that having a way to extend it would be good. |
@goldfirere The Rust mechanism looks like it would be for anyone but actually it isn't; it only works properly in standard-library crates (crates = libraries here) :) |
But this proposal won't make #518 into an internal judgment call, or is there something which could be marked unstable, and thus make I politely disagree that it's an internal change. The addition of |
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.
TL;DR of my first thoughts: This may better be a warning than a pragma, and maybe better only applies to language feature (e.g. other extensions) rather than specific imports. If it applies to imports, there ought to be a developer-accessible mechanism to mark certain modules or identifiers as unstable.
This proposal also includes a separate extension, ``-XStable``, which prevents | ||
``-XUnstable`` from being used. A project's ``.cabal`` file might then specify | ||
``-XStable`` to prevent any of the project's modules from using ``-XUnstable``. | ||
There is no ``-XNoStable``, unlike most other extensions. This ``-XStable`` component | ||
is optional and may be removed from this proposal without affecting the | ||
utility of ``-XUnstable``. |
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.
I’d leave this out. So far we have no precedence for “.cabal file gets to set boundaries for haskell files”, and it assumes a division of roles with different “privileges” between those editing the .cabal file and those editing source files that I am not sure is realistic.
Using -XUnstable
is just one of many many things a local programming policy might want to forbid (such as other extensions, unsafe features, use of emoji keywords…), and is better served by a custom hlint database maybe.
* For years, we GHC developers knew that ``-XImpredicativeTypes`` was more of | ||
a bug than a feature. It had no specification, and any code that type-checked | ||
because of it was simply lucky. The feature was in essence unstable. Since |
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.
Did we know that even already when -XImpredicativeTypes
was fist introduced, or was that hindsight? This only counts as motivation in the former case, does it?
#. (Technically beyond the scope of this proposal process) Tooling that helps | ||
users automatically insert extensions (i.e. HLS) would not automatically enable | ||
``-XUnstable`` from this message; users would have to add it manually. |
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.
What is itabout -XUnstable
that makes it deserve that treatment? Are there other extensions that should not be “easily enabled”? (Maybe Trustworthy
, IncoherentInstances
)?
And is it even good style? If the user already added ghc-prim
to their cabal file, and added the imports, they are very likely determined to use ghc-prim
and hopefully know why. Why make them do manual busy work that the tool could do for them?
(Yes, it’s not technically part of the proposal and the HLS authors might just choose to ignore it, or implement it by allowing automatic after a warning.)
1. Instead of making a new language extension, we could imagine a new warning ``-Wunstable-features``. | ||
This warning would be werror-by-default (no warnings are like this today) but could be disabled | ||
with ``-Wno-unstable-features``. Similarly, ``-XStable`` could become something like ``-fstable``, | ||
but this seems harder to specify in a ``.cabal`` file. |
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 is an interesting point. The nix
tool guard additional subcommand (a bit like extensions) under an “enable experimental features” configuration option.
So using a flag -fenable-experimental-features
or -Wno-unstable-features
is an alternative worth discussing.
I don’t think it’s harder to specify this in the .cabal
file,
ghc-options: -Wno-unstable-features`. People already know how to set warning flags in the cabal file. And those who don’t know are certainly not the target audience for this flag.
Ah, I see the discussion covers a bit of that already. Simon writes about “Distinguishing between "internals" and "public API"” and then talks about GHC in particular, but there isn't really anything GHC specific in the desire to distinguish internal APIs and public APIs, and the issues arises in many normal libraries as well. So a solution available to “mortal” library authors would probably be better. |
The list of identifiers exported from
The remaining functions are exported either by |
Thanks, @monoidal. Hoogle does not report all of those re-exports from |
@simonpj and I brainstormed this idea about a way to have features in GHC that we know may change, but we don't want to get stuck supporting forever.
Rendered