-
Notifications
You must be signed in to change notification settings - Fork 847
Description
I was always under the impression that in Stack, we take the idea, "One package, one version!" very seriously. So imagine my surprise when I was reading the Stack source code and I noticed the following strangeness in its definition of Package:
data Package =
...
,packageDeps :: !(Map PackageName VersionRange) -- ^ Packages that the package depends on.
,packageTools :: !(Map ExeName VersionRange) -- ^ A build tool name.
Why does Stack need to know the VersionRange here? This seems inconsistent with the "One package, one version" philosophy. Boldly, I decided to delete this information and see what happened.
Here were the major places where this information was being used in a nontrivial way:
depsPresentuses the version range to do a check against theInstalledMap(a map from package name to information--one version assumption!) to see if we should actually accept the installed package or not.checkPackageBuildPlanuses the version range to see if version bounds of a package were actually satisfied by its dependencies.addPackageDepsuses the version range to decide if a package selected byaddDepis acceptable. But even if it's not acceptable, there are two cases where it can overrule the decision: ifallow-newerwas passed, or if the snapshot implicitly states that the version combination is acceptablewithSingleContextuses the version range to select version dependencies from themdepsargument. I am not sure when multiple instances of the package could ever show up here (violation of the one version principle), so it seems like defensive coding that was added when custom setup support was added. Maybe @mgsloan remembers what's going on here.
To summarize, Stack never actually uses the version range to pick between multiple possible choices (except the Setup case, but I think that's impossible); instead, it uses it to do various consistency checks and slap the user on the wrist if they try to use a package whose dependency bounds don't match.
So, let me suggest something radical: why don't we just drop all of these checks. The version bound purists can add some sort of lint which checks if your install plan has inconsistent version ranges and lets the user know if the version ranges are not right... but it seems to me that it would be much simpler if Stack internally trusted in the snapshot (and the user extensions). I feel this would also reduce a lot of the friction with version bound updates and Hackage revisions, since a bound update wouldn't actually stop Stack from working (Stack already has special case code to trust snapshot versions, and I think that's exactly what you should do; go further!)
CC @snoyberg