Skip to content
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

Cabal backwards-compatibility guidelines proposal #3573

Closed
ezyang opened this issue Jul 19, 2016 · 6 comments
Closed

Cabal backwards-compatibility guidelines proposal #3573

ezyang opened this issue Jul 19, 2016 · 6 comments

Comments

@ezyang
Copy link
Contributor

ezyang commented Jul 19, 2016

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).
  2. 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.

@ttuegel
Copy link
Member

ttuegel commented Jul 21, 2016

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,

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

@ezyang
Copy link
Contributor Author

ezyang commented Jul 21, 2016

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.

@hvr
Copy link
Member

hvr commented Jul 22, 2016

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

@ezyang
Copy link
Contributor Author

ezyang commented Jul 22, 2016

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 nix-local-build is too tightly coupled to ConfigFlags, etc. #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.

@ttuegel
Copy link
Member

ttuegel commented Jul 22, 2016

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.

@phadej
Copy link
Collaborator

phadej commented Oct 9, 2020

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

@phadej phadej closed this as completed Oct 9, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants