-
Notifications
You must be signed in to change notification settings - Fork 696
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
Qualified constraints (issue #3502) #4219
Conversation
I modified the pretty-printing code so that it uses the 'Text.PrettyPrint' system rather than raw strings. I updated the syntax of pretty-printed qualifiers to use colons as separators rather than hyphens to fix an ambiguity problem (since hyphens can occur in package names). See issue 3502.
Refactored PackageConstraint in two ways: 1) split it into a package name and a 'PackageProperty' to make the code a bit cleaner; 2) changed PackageName to 'Qualified PackageName'. Added a Binary instance for Qualifier in PackagePath.hs (needed for PackageConstraint). Added pretty-printing code for PackageConstraint. For now, all the code that creates a PackageConstraint just sets the qualifier to 'unqualified', so this commit will not change the external behaviour of cabal-install.
Changed PackageConstraint to PackageProperty in both cases, since the name in the PackageConstraint was redundant.
This eliminates some boilerplate code.
Amended parsing and pretty-printing code of UserConstraint to handle qualifiers. Qualified constraints are now accepted on the command line, but the solver and other subsystems currently just ignore the qualifiers and don't do anything differently from before.
/cc @kosmikus |
AppVeyor failure seems to be genuine:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking great! Thanks for working on this feature and refactoring the surrounding code. Is there anything else that needs to be done, besides enforcing the constraints in Distribution.Solver.Modular.Preference
?
@@ -346,7 +348,7 @@ dontUpgradeNonUpgradeablePackages params = | |||
where | |||
extraConstraints = | |||
[ LabeledPackageConstraint | |||
(PackageConstraintInstalled pkgname) | |||
(PackageConstraint (unqualified pkgname) PackagePropertyInstalled) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These constraints should still apply to dependencies with any qualifier. I would expand PackageConstraint
so that it can take either a qualified or unqualified PackageName
, because there will probably be other situations where it is useful to constrain a package everywhere it appears as a dependency.
It would also be nice to allow users to specify unqualified constraints, but I don't think that's necessary for this set of PRs. I think that --constraint pkg==2
should always apply to the top-level pkg
dependency, as implemented in this PR. Once the solver part is done, it will fix an issue with bootstrapping packages such as time
: #4154. (See the comment at #4154 (comment).)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I see your point. This may require a little thought, so I'll make a new PR after this one. Would it make sense instead of expanding PackageConstraint
to expand Qualifier
by adding a new constructor? I see two obvious choices:
- Let 'Unqualified' mean top-level dependency and add a new constructor called e.g.
Any
. - Let 'Unqualified' mean applies everywhere and add a new constructor
Toplevel
.
Option 1 seems somewhat confusing semantically, so maybe option 2 is better - what do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On second thoughts, having looked at how Qualifier
is used in the solver, I think my last suggestion was incorrect. So, if I understand you, I should modify PackageConstraint
to support a wildcard or 'any' qualifier as an extra alternative, but leave the Qualifier
and QPN
datatypes as they are?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, if I understand you, I should modify PackageConstraint to support a wildcard or 'any' qualifier as an extra alternative, but leave the Qualifier and QPN datatypes as they are?
Yes, the solver still needs QPN to refer to a single instance of a package in many places. It might be worth adding a new type for the scope of the constraint, since we'll probably need other scopes later, such as "all setup dependencies". For example:
data PackageConstraint = PackageConstraint ConstraintScope PackageProperty
data ConstraintScope =
Qualified QPN
| AnyQualifier PackageName
| AnySetupQualifier PackageName
Let 'Unqualified' mean applies everywhere and add a new constructor Toplevel.
I think Toplevel is a lot clearer than the current use of Unqualified. (I'm not suggesting a change for these PRs, though.)
-- | ||
NamedPackage PackageName [PackageConstraint] | ||
NamedPackage PackageName [PackageProperty] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice!
|
||
-- | A package constraint consists of a package plus a property | ||
-- that must hold for that package. | ||
data PackageConstraint = PackageConstraint QPN PackageProperty | ||
deriving (Eq, Show, Generic) | ||
|
||
instance Binary PackageConstraint |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that your changes to PackageSpecifier
removed the need for this instance and most of the new Binary instances.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I think you're right - I'll look into that.
instance Binary Namespace | ||
|
||
-- | Pretty-prints a namespace. The result is either empty or | ||
-- ends in a period, so it can be prepended onto a package name. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this say "qualifier" instead of "package name"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agreed
@@ -744,35 +733,42 @@ readUserConstraint str = | |||
++ "either a version range, 'installed', 'source' or flags" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This message should probably mention that the package name is qualified.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agreed
Thanks very much! I'm going to merge this PR now, and then I'll create a new PR addressing the points you've made. Regarding your question is there anything else that needs to be done, I think the top priority is to add in the ability to distinguish between 'any' and 'toplevel' qualifiers, as you pointed out. Probably best not to modify the solver until the any vs. toplevel distinction is done. After that I'll see if I can think of anything else that we may have missed. |
Do we need any documentation for this or is this purely an internal thing? |
Documentation for the new syntax would be very helpful. I am a little worried that it will look similar but be subtly different from the current component qualification syntax in new-build. |
We can still change the syntax, the feature is not in any released version. |
@23Skidoo @ezyang Would you mind giving me a link to the code or info concerning the component qualification syntax, as I am not familiar with that feature. I'd like to compare it with the |
Thanks. Also, just a quick question to check I've understood the semantics of
In the current provisional syntax this is pretty-printed as:
As I understand it, this means the following:
So, for example, specifying the following constraint:
means that when building My question is: have I understood this correctly? |
Yep. |
The changelog should also mention that the meaning of constraints that use the old syntax has changed. They applied to all dependencies in 1.24, but now they only apply to top-level dependencies. |
Looking at #4219 (comment), can somebody explain to me the meaning of the
? Is When do I use |
…ifiers. This commit comments out the part of haskell#4219 that parses build tool dependency qualifiers, to disable the feature until we finalize the syntax. It also comments out the part of haskell#4236 that tests the parsing.
…ifiers. This commit comments out the part of haskell#4219 that parses build tool dependency qualifiers, to disable the feature until we finalize the syntax. It also comments out the part of haskell#4236 that tests the parsing.
The main changes are:
The only difference to the overall behaviour of cabal due to this patch is that qualified constraints will be parsed on the command line. Currently the solver etc. just ignores these qualifiers, however everything should be all set now to make the solver act on them.
One last thing: I'm going to add some new unit tests for the UserConstraint parser, but if it's okay I'll leave that till the next submission to stop this one getting too big.