Cabal: Cabal backwards-compatibility guidelines proposal

Created on 19 Jul 2016  路  6Comments  路  Source: haskell/cabal

This is a proposal for some backwards-compatibility guidelines. It is incomplete so please make me more complete.


So you've decided you need to change the type of some function in the Cabal library, usually because you need some extra information, etc. The normal workflow in a Haskell project is to change the signature, and then keep editing files to adjust to the new signature until your project compiles again.

If the function in question is exported and part of the public API, here's what you should do instead:

  1. Rename the function into a new name, give it the new type, and update all code to use this new function (using the type checker to help you).


    1. Reintroduce a function at the old name with a {-# DEPRECATED #-} tag what the new function name is called, what the deprecated function does in relation to it, how to change to use the new function, and when this function will be removed. The default policy is that functions are removed the next release after deprecation. (Note that deprecation descriptions don't support multiple lines, so you'll have to keep everything on the same line) Here is an example:

{-# DEPRECATED "This function now always assumes tests and benchmarks are disabled; use finalizePD with ComponentEnabledSpec to specify something more specific. This function will be removed in Cabal 2.2." #-}
  1. Add an entry to changelog describing what function you deprecated and what the new form is.

If you think no one is using a function, get a copy of Hackage https://stackoverflow.com/questions/14758423/how-can-one-make-a-private-copy-of-hackage and grep for the identifier. If you can demonstrate there are no uses, go ahead and change the type but make sure you still add a changelog entry.

discussion

Most helpful comment

I would like for {-# DEPRECATED #-} pragmas to also list a "sunset date," a version when the deprecated feature will be removed. For most features, I think removal in the next major release is appropriate, i.e. for a feature deprecated in Cabal 2.0,

.haskell {-# DEPRECATED foo "Use `bar' instead. `foo' will be removed in Cabal 2.2." #-}

All 6 comments

I would like for {-# DEPRECATED #-} pragmas to also list a "sunset date," a version when the deprecated feature will be removed. For most features, I think removal in the next major release is appropriate, i.e. for a feature deprecated in Cabal 2.0,

.haskell {-# DEPRECATED foo "Use `bar' instead. `foo' will be removed in Cabal 2.2." #-}

OK, I modified the text to mention this.

Though I wonder now if we shouldn't create "deprecation" tickets describing in detail how the interface changed and how to update code to use it. Only having one line is a bit restrictive.

@ezyang this is about functions... and I guess it can mostly be applied to class methods as well... but what about changing data types?

I feel like we are screwed forever. Here are some observations:

  • For data types which are just a bag of fields, if we had the foresight to introduce a defaultFoo function, and if userland actually uses that to construct it, then it is not BC-breaking to add a new field. But otherwise it is. See for example #3549. This is a bit troublesome because sometimes users don't client to use the default function to make sure they really did get all the fields.
  • We can safely add a new variant, as long as no user code is actually casing on it.
  • One possible way to maintain BC is to keep the old data type around, create a new one, and then marshal between the formats. But I definitely feel we should not do this except in extreme cases. One example where we have done this is Distribution.Simple.GHC.IPI642; this was expressly because we needed a working Read/Show instance for exactly this data type.

I don't have any general guidance when you should do what. I try not to rename fields; e.g. #3597 sucks but I'd just not fix it.

I feel like we are screwed forever.

I think setup-depends should lift this burden from us. I think we don't need to worry about library BC if we require that all packages with a custom Setup have an upper bound on a released version of Cabal (with an implict Cabal < 2 upper bound on pre-setup-depends packages). That way, we only need to worry about the command-line interface. Then we can just go back to following the PVP.

I'd say, Cabal is just a library. Use version bounds.

Was this page helpful?
0 / 5 - 0 ratings