summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/spack/solver/asp.py68
-rw-r--r--lib/spack/spack/solver/concretize.lp173
-rw-r--r--lib/spack/spack/solver/display.lp1
-rw-r--r--lib/spack/spack/test/concretize.py3
4 files changed, 122 insertions, 123 deletions
diff --git a/lib/spack/spack/solver/asp.py b/lib/spack/spack/solver/asp.py
index abe325cb86..8e843d60eb 100644
--- a/lib/spack/spack/solver/asp.py
+++ b/lib/spack/spack/solver/asp.py
@@ -586,6 +586,54 @@ def extract_args(model, predicate_name):
return [stringify(sym.arguments) for sym in model if sym.name == predicate_name]
+class ErrorHandler:
+ def __init__(self, model):
+ self.model = model
+ self.error_args = extract_args(model, "error")
+
+ def multiple_values_error(self, attribute, pkg):
+ return f'Cannot select a single "{attribute}" for package "{pkg}"'
+
+ def no_value_error(self, attribute, pkg):
+ return f'Cannot select a single "{attribute}" for package "{pkg}"'
+
+ def handle_error(self, msg, *args):
+ """Handle an error state derived by the solver."""
+ if msg == "multiple_values_error":
+ return self.multiple_values_error(*args)
+
+ if msg == "no_value_error":
+ return self.no_value_error(*args)
+
+ # For variant formatting, we sometimes have to construct specs
+ # to format values properly. Find/replace all occurances of
+ # Spec(...) with the string representation of the spec mentioned
+ msg = msg.format(*args)
+ specs_to_construct = re.findall(r"Spec\(([^)]*)\)", msg)
+ for spec_str in specs_to_construct:
+ msg = msg.replace("Spec(%s)" % spec_str, str(spack.spec.Spec(spec_str)))
+
+ return msg
+
+ def message(self, errors) -> str:
+ messages = [
+ f" {idx+1: 2}. {self.handle_error(msg, *args)}"
+ for idx, (_, msg, args) in enumerate(errors)
+ ]
+ header = "concretization failed for the following reasons:\n"
+ return "\n".join([header] + messages)
+
+ def raise_if_errors(self):
+ if not self.error_args:
+ return
+
+ errors = sorted(
+ [(int(priority), msg, args) for priority, msg, *args in self.error_args], reverse=True
+ )
+ msg = self.message(errors)
+ raise UnsatisfiableSpecError(msg)
+
+
class PyclingoDriver(object):
def __init__(self, cores=True):
"""Driver for the Python clingo interface.
@@ -641,20 +689,6 @@ class PyclingoDriver(object):
if choice:
self.assumptions.append(atom)
- def handle_error(self, msg, *args):
- """Handle an error state derived by the solver."""
- msg = msg.format(*args)
-
- # For variant formatting, we sometimes have to construct specs
- # to format values properly. Find/replace all occurances of
- # Spec(...) with the string representation of the spec mentioned
- specs_to_construct = re.findall(r"Spec\(([^)]*)\)", msg)
- for spec_str in specs_to_construct:
- msg = msg.replace("Spec(%s)" % spec_str, str(spack.spec.Spec(spec_str)))
-
- # TODO: this raises early -- we should handle multiple errors if there are any.
- raise UnsatisfiableSpecError(msg)
-
def solve(self, setup, specs, reuse=None, output=None, control=None):
"""Set up the input and solve for dependencies of ``specs``.
@@ -756,10 +790,8 @@ class PyclingoDriver(object):
min_cost, best_model = min(models)
# first check for errors
- error_args = extract_args(best_model, "error")
- errors = sorted((int(priority), msg, args) for priority, msg, *args in error_args)
- for _, msg, args in errors:
- self.handle_error(msg, *args)
+ error_handler = ErrorHandler(best_model)
+ error_handler.raise_if_errors()
# build specs from spec attributes in the model
spec_attrs = [(name, tuple(rest)) for name, *rest in extract_args(best_model, "attr")]
diff --git a/lib/spack/spack/solver/concretize.lp b/lib/spack/spack/solver/concretize.lp
index 60d48b9fae..632e8926e6 100644
--- a/lib/spack/spack/solver/concretize.lp
+++ b/lib/spack/spack/solver/concretize.lp
@@ -40,6 +40,24 @@ attr(Name, A1, A2, A3, A4) :- literal(LiteralID, Name, A1, A2, A3, A4), literal_
#defined literal/5.
#defined literal/6.
+% Attributes for node packages which must have a single value
+attr_single_value("version").
+attr_single_value("node_platform").
+attr_single_value("node_os").
+attr_single_value("node_target").
+
+% Error when no attribute is selected
+error(100, no_value_error, Attribute, Package)
+ :- attr("node", Package),
+ attr_single_value(Attribute),
+ not attr(Attribute, Package, _).
+
+% Error when multiple attr need to be selected
+error(100, multiple_values_error, Attribute, Package)
+ :- attr("node", Package),
+ attr_single_value(Attribute),
+ 2 { attr(Attribute, Package, Version) }.
+
%-----------------------------------------------------------------------------
% Version semantics
%-----------------------------------------------------------------------------
@@ -77,21 +95,11 @@ version_satisfies(Package, Constraint, HashVersion) :- version_satisfies(Package
% possible
{ attr("version", Package, Version) : version_declared(Package, Version) }
:- attr("node", Package).
-error(2, "No version for '{0}' satisfies '@{1}' and '@{2}'", Package, Version1, Version2)
- :- attr("node", Package),
- attr("version", Package, Version1),
- attr("version", Package, Version2),
- Version1 < Version2. % see[1]
-
-error(2, "No versions available for package '{0}'", Package)
- :- attr("node", Package), not attr("version", Package, _).
% A virtual package may or may not have a version, but never has more than one
-error(2, "No version for '{0}' satisfies '@{1}' and '@{2}'", Virtual, Version1, Version2)
+error(100, "Cannot select a single version for virtual '{0}'", Virtual)
:- attr("virtual_node", Virtual),
- attr("version", Virtual, Version1),
- attr("version", Virtual, Version2),
- Version1 < Version2. % see[1]
+ 2 { attr("version", Virtual, Version) }.
% If we select a deprecated version, mark the package as deprecated
attr("deprecated", Package, Version) :-
@@ -144,10 +152,10 @@ possible_version_weight(Package, Weight)
% More specific error message if the version cannot satisfy some constraint
% Otherwise covered by `no_version_error` and `versions_conflict_error`.
-error(1, "No valid version for '{0}' satisfies '@{1}'", Package, Constraint)
+error(10, "Cannot satisfy '{0}@{1}'", Package, Constraint)
:- attr("node_version_satisfies", Package, Constraint),
- C = #count{ Version : attr("version", Package, Version), version_satisfies(Package, Constraint, Version)},
- C < 1.
+ attr("version", Package, Version),
+ not version_satisfies(Package, Constraint, Version).
attr("node_version_satisfies", Package, Constraint)
:- attr("version", Package, Version), version_satisfies(Package, Constraint, Version).
@@ -253,7 +261,7 @@ attr("node", Dependency) :- attr("node", Package), depends_on(Package, Dependenc
% dependencies) and get a two-node unconnected graph
needed(Package) :- attr("root", Package).
needed(Dependency) :- needed(Package), depends_on(Package, Dependency).
-error(1, "'{0}' is not a valid dependency for any package in the DAG", Package)
+error(10, "'{0}' is not a valid dependency for any package in the DAG", Package)
:- attr("node", Package),
not needed(Package).
@@ -262,7 +270,7 @@ error(1, "'{0}' is not a valid dependency for any package in the DAG", Package)
% this ensures that we solve around them
path(Parent, Child) :- depends_on(Parent, Child).
path(Parent, Descendant) :- path(Parent, A), depends_on(A, Descendant).
-error(2, "Cyclic dependency detected between '{0}' and '{1}'\n Consider changing variants to avoid the cycle", A, B)
+error(100, "Cyclic dependency detected between '{0}' and '{1}' (consider changing variants to avoid the cycle)", A, B)
:- path(A, B),
path(B, A).
@@ -272,7 +280,7 @@ error(2, "Cyclic dependency detected between '{0}' and '{1}'\n Consider chang
%-----------------------------------------------------------------------------
% Conflicts
%-----------------------------------------------------------------------------
-error(0, Msg) :- attr("node", Package),
+error(1, Msg) :- attr("node", Package),
conflict(Package, TriggerID, ConstraintID, Msg),
condition_holds(TriggerID),
condition_holds(ConstraintID),
@@ -301,15 +309,14 @@ attr("virtual_node", Virtual)
% The provider must be selected among the possible providers.
{ provider(Package, Virtual) : possible_provider(Package, Virtual) }
:- attr("virtual_node", Virtual).
-error(2, "Cannot find valid provider for virtual {0}", Virtual)
+
+error(100, "Cannot find valid provider for virtual {0}", Virtual)
:- attr("virtual_node", Virtual),
not provider(_, Virtual).
-error(2, "Spec cannot include multiple providers for virtual '{0}'\n Requested '{1}' and '{2}'", Virtual, P1, P2)
+error(100, "Cannot select a single provider for virtual '{0}'", Virtual)
:- attr("virtual_node", Virtual),
- provider(P1, Virtual),
- provider(P2, Virtual),
- P1 < P2.
+ 2 { provider(P, Virtual) }.
% virtual roots imply virtual nodes, and that one provider is a root
attr("virtual_node", Virtual) :- attr("virtual_root", Virtual).
@@ -398,14 +405,13 @@ possible_provider_weight(Dependency, Virtual, 100, "fallback") :- provider(Depen
{ external_version(Package, Version, Weight):
version_declared(Package, Version, Weight, "external") }
:- external(Package).
-error(2, "Attempted to use external for '{0}' which does not satisfy any configured external spec", Package)
+error(100, "Attempted to use external for '{0}' which does not satisfy any configured external spec", Package)
:- external(Package),
not external_version(Package, _, _).
-error(2, "Attempted to use external for '{0}' which does not satisfy any configured external spec", Package)
+
+error(100, "Attempted to use external for '{0}' which does not satisfy any configured external spec", Package)
:- external(Package),
- external_version(Package, Version1, Weight1),
- external_version(Package, Version2, Weight2),
- (Version1, Weight1) < (Version2, Weight2). % see[1]
+ 2 { external_version(Package, Version, Weight) }.
version_weight(Package, Weight) :- external_version(Package, Version, Weight).
attr("version", Package, Version) :- external_version(Package, Version, Weight).
@@ -440,7 +446,7 @@ external_conditions_hold(Package, LocalIndex) :-
% it cannot happen that a spec is external, but none of the external specs
% conditions hold.
-error(2, "Attempted to use external for '{0}' which does not satisfy any configured external spec", Package)
+error(100, "Attempted to use external for '{0}' which does not satisfy any configured external spec", Package)
:- external(Package),
not external_conditions_hold(Package, _).
@@ -488,7 +494,7 @@ requirement_weight(Package, Group, W) :-
requirement_policy(Package, Group, "any_of"),
requirement_group_satisfied(Package, Group).
-error(2, "Cannot satisfy the requirements in packages.yaml for the '{0}' package. You may want to delete them to proceed with concretization. To check where the requirements are defined run 'spack config blame packages'", Package) :-
+error(100, "Cannot satisfy the requirements in packages.yaml for package '{0}'. You may want to delete them to proceed with concretization. To check where the requirements are defined run 'spack config blame packages'", Package) :-
activate_requirement_rules(Package),
requirement_group(Package, X),
not requirement_group_satisfied(Package, X).
@@ -518,20 +524,20 @@ attr("variant_value", Package, Variant, Value) :-
attr("variant_propagate", Package, Variant, Value, _),
variant_possible_value(Package, Variant, Value).
-error(2, "{0} and {1} cannot both propagate variant '{2}' to package {3} with values '{4}' and '{5}'", Source1, Source2, Variant, Package, Value1, Value2) :-
+error(100, "{0} and {1} cannot both propagate variant '{2}' to package {3} with values '{4}' and '{5}'", Source1, Source2, Variant, Package, Value1, Value2) :-
attr("variant_propagate", Package, Variant, Value1, Source1),
attr("variant_propagate", Package, Variant, Value2, Source2),
variant(Package, Variant),
Value1 < Value2.
% a variant cannot be set if it is not a variant on the package
-error(2, "Cannot set variant '{0}' for package '{1}' because the variant condition cannot be satisfied for the given spec", Variant, Package)
+error(100, "Cannot set variant '{0}' for package '{1}' because the variant condition cannot be satisfied for the given spec", Variant, Package)
:- attr("variant_set", Package, Variant),
not variant(Package, Variant),
build(Package).
% a variant cannot take on a value if it is not a variant of the package
-error(2, "Cannot set variant '{0}' for package '{1}' because the variant condition cannot be satisfied for the given spec", Variant, Package)
+error(100, "Cannot set variant '{0}' for package '{1}' because the variant condition cannot be satisfied for the given spec", Variant, Package)
:- attr("variant_value", Package, Variant, _),
not variant(Package, Variant),
build(Package).
@@ -554,15 +560,14 @@ attr("variant_value", Package, Variant, Value) :-
build(Package).
-error(2, "'{0}' required multiple values for single-valued variant '{1}'\n Requested 'Spec({1}={2})' and 'Spec({1}={3})'", Package, Variant, Value1, Value2)
+error(100, "'{0}' required multiple values for single-valued variant '{1}'", Package, Variant)
:- attr("node", Package),
variant(Package, Variant),
variant_single_value(Package, Variant),
build(Package),
- attr("variant_value", Package, Variant, Value1),
- attr("variant_value", Package, Variant, Value2),
- Value1 < Value2. % see[1]
-error(2, "No valid value for variant '{1}' of package '{0}'", Package, Variant)
+ 2 { attr("variant_value", Package, Variant, Value) }.
+
+error(100, "No valid value for variant '{1}' of package '{0}'", Package, Variant)
:- attr("node", Package),
variant(Package, Variant),
build(Package),
@@ -574,7 +579,7 @@ attr("variant_set", Package, Variant) :- attr("variant_set", Package, Variant, _
% A variant cannot have a value that is not also a possible value
% This only applies to packages we need to build -- concrete packages may
% have been built w/different variants from older/different package versions.
-error(1, "'Spec({1}={2})' is not a valid value for '{0}' variant '{1}'", Package, Variant, Value)
+error(10, "'Spec({1}={2})' is not a valid value for '{0}' variant '{1}'", Package, Variant, Value)
:- attr("variant_value", Package, Variant, Value),
not variant_possible_value(Package, Variant, Value),
build(Package).
@@ -582,7 +587,7 @@ error(1, "'Spec({1}={2})' is not a valid value for '{0}' variant '{1}'", Package
% Some multi valued variants accept multiple values from disjoint sets.
% Ensure that we respect that constraint and we don't pick values from more
% than one set at once
-error(2, "{0} variant '{1}' cannot have values '{2}' and '{3}' as they come from disjoing value sets", Package, Variant, Value1, Value2)
+error(100, "{0} variant '{1}' cannot have values '{2}' and '{3}' as they come from disjoint value sets", Package, Variant, Value1, Value2)
:- attr("variant_value", Package, Variant, Value1),
attr("variant_value", Package, Variant, Value2),
variant_value_from_disjoint_sets(Package, Variant, Value1, Set1),
@@ -650,7 +655,7 @@ variant_default_value(Package, Variant, Value) :-
% Treat 'none' in a special way - it cannot be combined with other
% values even if the variant is multi-valued
-error(2, "{0} variant '{1}' cannot have values '{2}' and 'none'", Package, Variant, Value)
+error(100, "{0} variant '{1}' cannot have values '{2}' and 'none'", Package, Variant, Value)
:- attr("variant_value", Package, Variant, Value),
attr("variant_value", Package, Variant, "none"),
Value != "none",
@@ -698,17 +703,6 @@ attr("node_platform", Package, Platform)
% platform is set if set to anything
attr("node_platform_set", Package) :- attr("node_platform_set", Package, _).
-% each node must have a single platform
-error(2, "No valid platform found for {0}", Package)
- :- attr("node", Package),
- not attr("node_platform", Package, _).
-
-error(2, "Cannot concretize {0} with multiple platforms\n Requested 'platform={1}' and 'platform={2}'", Package, Platform1, Platform2)
- :- attr("node", Package),
- attr("node_platform", Package, Platform1),
- attr("node_platform", Package, Platform2),
- Platform1 < Platform2. % see[1]
-
%-----------------------------------------------------------------------------
% OS semantics
%-----------------------------------------------------------------------------
@@ -718,24 +712,14 @@ os(OS) :- os(OS, _).
% one os per node
{ attr("node_os", Package, OS) : os(OS) } :- attr("node", Package).
-error(2, "Cannot find valid operating system for '{0}'", Package)
- :- attr("node", Package),
- not attr("node_os", Package, _).
-
-error(2, "Cannot concretize {0} with multiple operating systems\n Requested 'os={1}' and 'os={2}'", Package, OS1, OS2)
- :- attr("node", Package),
- attr("node_os", Package, OS1),
- attr("node_os", Package, OS2),
- OS1 < OS2. %see [1]
-
% can't have a non-buildable OS on a node we need to build
-error(2, "Cannot concretize '{0} os={1}'. Operating system '{1}' is not buildable", Package, OS)
+error(100, "Cannot select '{0} os={1}' (operating system '{1}' is not buildable)", Package, OS)
:- build(Package),
attr("node_os", Package, OS),
not buildable_os(OS).
% can't have dependencies on incompatible OS's
-error(2, "{0} and dependency {1} have incompatible operating systems 'os={2}' and 'os={3}'", Package, Dependency, PackageOS, DependencyOS)
+error(100, "{0} and dependency {1} have incompatible operating systems 'os={2}' and 'os={3}'", Package, Dependency, PackageOS, DependencyOS)
:- depends_on(Package, Dependency),
attr("node_os", Package, PackageOS),
attr("node_os", Dependency, DependencyOS),
@@ -779,18 +763,8 @@ attr("node_os", Package, OS) :- attr("node_os_set", Package, OS), attr("node", P
% Each node has only one target chosen among the known targets
{ attr("node_target", Package, Target) : target(Target) } :- attr("node", Package).
-error(2, "Cannot find valid target for '{0}'", Package)
- :- attr("node", Package),
- not attr("node_target", Package, _).
-
-error(2, "Cannot concretize '{0}' with multiple targets\n Requested 'target={1}' and 'target={2}'", Package, Target1, Target2)
- :- attr("node", Package),
- attr("node_target", Package, Target1),
- attr("node_target", Package, Target2),
- Target1 < Target2. % see[1]
-
% If a node must satisfy a target constraint, enforce it
-error(1, "'{0} target={1}' cannot satisfy constraint 'target={2}'", Package, Target, Constraint)
+error(10, "'{0} target={1}' cannot satisfy constraint 'target={2}'", Package, Target, Constraint)
:- attr("node_target", Package, Target),
attr("node_target_satisfies", Package, Constraint),
not target_satisfies(Constraint, Target).
@@ -801,7 +775,7 @@ attr("node_target_satisfies", Package, Constraint)
:- attr("node_target", Package, Target), target_satisfies(Constraint, Target).
% If a node has a target, all of its dependencies must be compatible with that target
-error(2, "Cannot find compatible targets for {0} and {1}", Package, Dependency)
+error(100, "Cannot find compatible targets for {0} and {1}", Package, Dependency)
:- depends_on(Package, Dependency),
attr("node_target", Package, Target),
not node_target_compatible(Dependency, Target).
@@ -816,7 +790,7 @@ node_target_compatible(Package, Target)
#defined target_satisfies/2.
% can't use targets on node if the compiler for the node doesn't support them
-error(2, "{0} compiler '{2}@{3}' incompatible with 'target={1}'", Package, Target, Compiler, Version)
+error(100, "{0} compiler '{2}@{3}' incompatible with 'target={1}'", Package, Target, Compiler, Version)
:- attr("node_target", Package, Target),
node_compiler(Package, CompilerID),
not compiler_supports_target(CompilerID, Target),
@@ -845,7 +819,7 @@ node_target_mismatch(Parent, Dependency)
not node_target_match(Parent, Dependency).
% disallow reusing concrete specs that don't have a compatible target
-error(2, "'{0} target={1}' is not compatible with this machine", Package, Target)
+error(100, "'{0} target={1}' is not compatible with this machine", Package, Target)
:- attr("node", Package),
attr("node_target", Package, Target),
not target(Target).
@@ -878,35 +852,34 @@ attr("node_compiler_version", Package, CompilerName, CompilerVersion)
attr("node_compiler", Package, CompilerName)
:- attr("node_compiler_version", Package, CompilerName, CompilerVersion).
-error(2, "No valid compiler version found for '{0}'", Package)
+error(100, "No valid compiler version found for '{0}'", Package)
:- attr("node", Package),
not node_compiler(Package, _).
% We can't have a compiler be enforced and select the version from another compiler
-error(2, "Cannot concretize {0} with two compilers {1}@{2} and {3}@{4}", Package, C1, V1, C2, V2)
- :- attr("node_compiler_version", Package, C1, V1),
- attr("node_compiler_version", Package, C2, V2),
- (C1, V1) < (C2, V2).
+error(100, "Cannot select a single compiler for package {0}", Package)
+ :- attr("node", Package),
+ 2 { attr("node_compiler_version", Package, C, V) }.
-error(2, "Cannot concretize {0} with two compilers {1} and {2}@{3}", Package, Compiler1, Compiler2, Version)
+error(100, "Cannot concretize {0} with two compilers {1} and {2}@{3}", Package, Compiler1, Compiler2, Version)
:- attr("node_compiler", Package, Compiler1),
attr("node_compiler_version", Package, Compiler2, Version),
Compiler1 != Compiler2.
% If the compiler of a node cannot be satisfied, raise
-error(1, "No valid compiler for {0} satisfies '%{1}'", Package, Compiler)
+error(10, "No valid compiler for {0} satisfies '%{1}'", Package, Compiler)
:- attr("node", Package),
attr("node_compiler_version_satisfies", Package, Compiler, ":"),
not compiler_version_satisfies(Compiler, ":", _).
% If the compiler of a node must satisfy a constraint, then its version
% must be chosen among the ones that satisfy said constraint
-error(2, "No valid version for '{0}' compiler '{1}' satisfies '@{2}'", Package, Compiler, Constraint)
+error(100, "No valid version for '{0}' compiler '{1}' satisfies '@{2}'", Package, Compiler, Constraint)
:- attr("node", Package),
attr("node_compiler_version_satisfies", Package, Compiler, Constraint),
not compiler_version_satisfies(Compiler, Constraint, _).
-error(2, "No valid version for '{0}' compiler '{1}' satisfies '@{2}'", Package, Compiler, Constraint)
+error(100, "No valid version for '{0}' compiler '{1}' satisfies '@{2}'", Package, Compiler, Constraint)
:- attr("node", Package),
attr("node_compiler_version_satisfies", Package, Compiler, Constraint),
not compiler_version_satisfies(Compiler, Constraint, ID),
@@ -932,7 +905,7 @@ attr("node_compiler_version_satisfies", Package, Compiler, Constraint)
% Cannot select a compiler if it is not supported on the OS
% Compilers that are explicitly marked as allowed
% are excluded from this check
-error(2, "{0} compiler '%{1}@{2}' incompatible with 'os={3}'", Package, Compiler, Version, OS)
+error(100, "{0} compiler '%{1}@{2}' incompatible with 'os={3}'", Package, Compiler, Version, OS)
:- attr("node_os", Package, OS),
node_compiler(Package, CompilerID),
compiler_name(CompilerID, Compiler),
@@ -981,7 +954,7 @@ compiler_weight(Package, 100)
not default_compiler_preference(CompilerID, _).
% For the time being, be strict and reuse only if the compiler match one we have on the system
-error(2, "Compiler {1}@{2} requested for {0} cannot be found. Set install_missing_compilers:true if intended.", Package, Compiler, Version)
+error(100, "Compiler {1}@{2} requested for {0} cannot be found. Set install_missing_compilers:true if intended.", Package, Compiler, Version)
:- attr("node_compiler_version", Package, Compiler, Version),
not node_compiler(Package, _).
@@ -1009,7 +982,7 @@ node_flag_inherited(Dependency, FlagType, Flag)
can_inherit_flags(Package, Dependency, FlagType),
attr("node_flag_propagate", Package, FlagType).
-error(2, "{0} and {1} cannot both propagate compiler flags '{2}' to {3}", Source1, Source2, Package, FlagType) :-
+error(100, "{0} and {1} cannot both propagate compiler flags '{2}' to {3}", Source1, Source2, Package, FlagType) :-
depends_on(Source1, Package),
depends_on(Source2, Package),
attr("node_flag_propagate", Source1, FlagType),
@@ -1067,7 +1040,7 @@ attr("no_flags", Package, FlagType)
% You can't install a hash, if it is not installed
:- attr("hash", Package, Hash), not installed_hash(Package, Hash).
% This should be redundant given the constraint above
-:- attr("hash", Package, Hash1), attr("hash", Package, Hash2), Hash1 < Hash2.
+:- attr("node", Package), 2 { attr("hash", Package, Hash) }.
% if a hash is selected, we impose all the constraints that implies
impose(Hash) :- attr("hash", Package, Hash).
@@ -1118,18 +1091,14 @@ build_priority(Package, 0) :- attr("node", Package), not optimize_for_reuse().
% Optimization to avoid errors
%-----------------------------------------------------------------
% Some errors are handled as rules instead of constraints because
-% it allows us to explain why something failed. Here we optimize
-% HEAVILY against the facts generated by those rules.
+% it allows us to explain why something failed.
#minimize{ 0@1000: #true}.
-#minimize{ 0@1001: #true}.
-#minimize{ 0@1002: #true}.
-
-#minimize{ 1000@1000+Priority,Msg: error(Priority, Msg) }.
-#minimize{ 1000@1000+Priority,Msg,Arg1: error(Priority, Msg, Arg1) }.
-#minimize{ 1000@1000+Priority,Msg,Arg1,Arg2: error(Priority, Msg, Arg1, Arg2) }.
-#minimize{ 1000@1000+Priority,Msg,Arg1,Arg2,Arg3: error(Priority, Msg, Arg1, Arg2, Arg3) }.
-#minimize{ 1000@1000+Priority,Msg,Arg1,Arg2,Arg3,Arg4: error(Priority, Msg, Arg1, Arg2, Arg3, Arg4) }.
-#minimize{ 1000@1000+Priority,Msg,Arg1,Arg2,Arg3,Arg4,Arg5: error(Priority, Msg, Arg1, Arg2, Arg3, Arg4, Arg5) }.
+
+#minimize{ Weight@1000,Msg: error(Weight, Msg) }.
+#minimize{ Weight@1000,Msg,Arg1: error(Weight, Msg, Arg1) }.
+#minimize{ Weight@1000,Msg,Arg1,Arg2: error(Weight, Msg, Arg1, Arg2) }.
+#minimize{ Weight@1000,Msg,Arg1,Arg2,Arg3: error(Weight, Msg, Arg1, Arg2, Arg3) }.
+#minimize{ Weight@1000,Msg,Arg1,Arg2,Arg3,Arg4: error(Weight, Msg, Arg1, Arg2, Arg3, Arg4) }.
%-----------------------------------------------------------------------------
% How to optimize the spec (high to low priority)
diff --git a/lib/spack/spack/solver/display.lp b/lib/spack/spack/solver/display.lp
index 6e1cf6391a..fffffb2c04 100644
--- a/lib/spack/spack/solver/display.lp
+++ b/lib/spack/spack/solver/display.lp
@@ -23,6 +23,5 @@
#show error/4.
#show error/5.
#show error/6.
-#show error/7.
% debug
diff --git a/lib/spack/spack/test/concretize.py b/lib/spack/spack/test/concretize.py
index 9754b47f6a..bf492b93d1 100644
--- a/lib/spack/spack/test/concretize.py
+++ b/lib/spack/spack/test/concretize.py
@@ -1762,8 +1762,7 @@ class TestConcretize(object):
solver = spack.solver.asp.Solver()
setup = spack.solver.asp.SpackSolverSetup()
with pytest.raises(
- spack.solver.asp.UnsatisfiableSpecError,
- match="'dep-with-variants' satisfies '@999'",
+ spack.solver.asp.UnsatisfiableSpecError, match="'dep-with-variants@999'"
):
solver.driver.solve(setup, [root_spec], reuse=reusable_specs)