Summary

Overview

Don’t throw an error by default under -Werror when a DEPRECATED module, function, or type is imported or used. Use or import of a module, function, or type marked with the WARNING pragma will still be promoted to an error under -Werror .

The Idea

Some “warnings” are more what you would consider “information” and should not be considered “errors” under -Werror (unless explicitly requested).

Motivation

Consider you’re the maintainer of a widely used library and you wish to remove some function in some later release. There is currently no way of communicating to users of your library that you plan to remove this symbol in some later major release. The natural way to express this would be to add a DEPRECATED pragma to the function in the next minor release, leave it there for some time horizon, and then in a following major release remove the symbol. This currently is not practical because a very large number of projects that use your library compile with -Werror which will then cause builds to fail //simply because you tried to alert your users of future plans//. I posit that this is broken, the crux of this is that a DEPRECATED //should// be considered as //info// and not a true //warning//.

As it stands today, **two major releases** are required to safely deprecate (and remove) part of a public API due to the wide usage of -Werror which causes build failures when a new DEPRECATED pragma is added. The first major release adds the DEPRECATED pragma and the second removed the symbol or module. This discourages deprecating old APIs, introduces unnecessary version churn, and makes it more difficult to communicate to consumers of a library that an upcoming release will remove a feature. As a specific example, when attempting to align the public APIs of containers and unordered-containers (renaming HashMap.lookupDefault to HashMap.findWithDefault to match the API of containers ) the largest issue was how to actually deprecate the old function. The unordered-containers API is relatively stable and it wouldn’t warrant a new major version just to mark a function as DEPRECATED . You can see the discussion here (http://haskell.1045720.n5.nabble.com/Proposal-Rename-HashMap-lookupDefault-to-HashMap-findWithDefault-td5870348.html). = Changes == Flag Changes

*Before**

-Wdeprecations - warn if a module, function, or type marked DEPRECATED or WARNING is imported or used.

-Wwarnings-deprecations - warn if a module, function, or type marked DEPRECATED or WARNING is imported or used. (The name of this flag is unfortunate, imho it should be named -Wwarnings )

-Werror - promote warnings to errors, including both -Wdeprecations and -Wwarnings . In other words, if a DEPRECATED or WARNING module, function, or type is imported or used.

Note that //currently// there is **no distinction** between things marked as WARNING and things marked as DEPRECATED at the flag level, this is problematic.

*After**

-Wdeprecations - warn if a module, function, or type marked DEPRECATED is imported or used.

-Wwarnings-deprecations (or rename to -Wwarnings ) - warn if a function, module, or type marked WARNING is imported or used.

-Werror - promote warnings to errors, including -Wwarnings-deprecations ( WARNING ), **but not** -Wdeprecations ( DEPRECATED ).

(optional) -Wwarnings - warn if a function, module, or type marked WARNING is imported or used. This is a clearer flag name than -Wwarnings-deprecations .

Precedent for excluding warnings from being promoted to errors

The idea that some things considered “warnings” are not actually “errors” already exists, specifically the flag -Wmissed-specialisations (https://downloads.haskell.org/\~ghc/latest/docs/html/users_guide/using-warnings.html\#ghc-flag--Wmissed-specialisations) is already excluded from the set of warnings that are not considered as errors.

How do I get the old behaviour back? aka. treat DEPRECATED as an error

If you’re using a library and you’d like to be extra up to date and cause your build to fail if you’re using a deprecated function then you can pass -Werror=deprecations to GHC and it will treat use of DEPRECATED as an error.

Alternatives Considered

No change (baseline)

The current state of the world as discussed in the //Motivation// section causes real issues related to natural evolution of APIs. I feel that this is not desirable in the long term.

Ask people to exclude DEPRECATED from -Werror

Another option is to ask folks to not treat deprecations as errors by explicitly passing -Wwarn=deprecations (still requires changes to GHC since WARNING and DEPRECATED are grouped together currently). This would “fix” the problem but makes the assumption that everyone updates their build flags appropriately which is an incredibly unreasonable assumption. It also doesn’t actually address the core problem of use of deprecated APIs being treated as erroneous.

Related Work/Proposals

There is an open PR to the PVP to no longer require a major version bump when a DEPRECATED pragma is added which has received support from both the community and members of the CLC (https://github.com/haskell/pvp/pull/18) and follows the same reasoning as here, namely that deprecating something is not meant to (and should not) break anything since it doesn’t change the API, it simply provides some information to users of the library.

Example Implementation

I've put together a possible implementation of this at !89, but please do not comment on design there, keep that in the trac issue here.