Re: [GHC] #16163: Don’t throw an error (by default) for use of DEPRECATED symbols under -Werror

GHC ghc-devs at haskell.org
Wed Jan 9 19:16:56 UTC 2019


#16163: Don’t throw an error (by default) for use of DEPRECATED symbols under
-Werror
-------------------------------------+-------------------------------------
        Reporter:  m-renaud          |                Owner:  (none)
            Type:  feature request   |               Status:  new
        Priority:  normal            |            Milestone:
       Component:  Compiler          |              Version:  8.6.3
      Resolution:                    |             Keywords:
Operating System:  Unknown/Multiple  |         Architecture:
                                     |  Unknown/Multiple
 Type of failure:  None/Unknown      |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:                    |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------
Description changed by m-renaud:

Old description:

> = 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” not 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
> https://gitlab.haskell.org/ghc/ghc/merge_requests/89, but please do not
> comment on design there, keep that in the trac issue here.

New description:

 = 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
 https://gitlab.haskell.org/ghc/ghc/merge_requests/89, but please do not
 comment on design there, keep that in the trac issue here.

--

-- 
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/16163#comment:1>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list