From 895ceeda388d3bff406077a5c3689102d53a34c0 Mon Sep 17 00:00:00 2001 From: Massimiliano Culpo Date: Thu, 16 Jun 2022 18:25:56 +0200 Subject: concretize.lp: impose a lower bound on the number of version facts if a solution exists (#31142) * concretize.lp: impose a lower bound on the number of version facts if a valid version exists fixes #30864 * Add a unit test --- lib/spack/spack/solver/concretize.lp | 5 +++++ lib/spack/spack/test/concretize.py | 21 +++++++++++++++++++++ .../non-existing-conditional-dep/package.py | 16 ++++++++++++++++ 3 files changed, 42 insertions(+) create mode 100644 var/spack/repos/builtin.mock/packages/non-existing-conditional-dep/package.py diff --git a/lib/spack/spack/solver/concretize.lp b/lib/spack/spack/solver/concretize.lp index 67ea66d6ec..70ff5b438d 100644 --- a/lib/spack/spack/solver/concretize.lp +++ b/lib/spack/spack/solver/concretize.lp @@ -120,6 +120,11 @@ version_weight(Package, Weight) { version(Package, Version) : version_satisfies(Package, Constraint, Version) } :- node_version_satisfies(Package, Constraint). +% If there is at least a version that satisfy the constraint, impose a lower +% bound on the choice rule to avoid false positives with the error below +1 { version(Package, Version) : version_satisfies(Package, Constraint, Version) } + :- node_version_satisfies(Package, Constraint), version_satisfies(Package, Constraint, _). + % 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) diff --git a/lib/spack/spack/test/concretize.py b/lib/spack/spack/test/concretize.py index eafea0ad99..a8f8b86236 100644 --- a/lib/spack/spack/test/concretize.py +++ b/lib/spack/spack/test/concretize.py @@ -1732,3 +1732,24 @@ class TestConcretize(object): if expected_spec in spec: counter += 1 assert counter == occurances, concrete_specs + + @pytest.mark.regression('30864') + def test_misleading_error_message_on_version(self, mutable_database): + # For this bug to be triggered we need a reusable dependency + # that is not optimal in terms of optimization scores. + # We pick an old version of "b" + import spack.solver.asp + if spack.config.get('config:concretizer') == 'original': + pytest.skip('Original concretizer cannot reuse') + + reusable_specs = [ + spack.spec.Spec('non-existing-conditional-dep@1.0').concretized() + ] + root_spec = spack.spec.Spec('non-existing-conditional-dep@2.0') + + with spack.config.override("concretizer:reuse", True): + solver = spack.solver.asp.Solver() + setup = spack.solver.asp.SpackSolverSetup() + with pytest.raises(spack.solver.asp.UnsatisfiableSpecError, + match="'dep-with-variants' satisfies '@999'"): + solver.driver.solve(setup, [root_spec], reuse=reusable_specs) diff --git a/var/spack/repos/builtin.mock/packages/non-existing-conditional-dep/package.py b/var/spack/repos/builtin.mock/packages/non-existing-conditional-dep/package.py new file mode 100644 index 0000000000..2b964948c0 --- /dev/null +++ b/var/spack/repos/builtin.mock/packages/non-existing-conditional-dep/package.py @@ -0,0 +1,16 @@ +# Copyright 2013-2022 Lawrence Livermore National Security, LLC and other +# Spack Project Developers. See the top-level COPYRIGHT file for details. +# +# SPDX-License-Identifier: (Apache-2.0 OR MIT) +from spack.package import * + + +class NonExistingConditionalDep(Package): + """Simple package with no source and one dependency""" + + homepage = "http://www.example.com" + + version('2.0') + version('1.0') + + depends_on('dep-with-variants@999', when='@2.0') -- cgit v1.2.3-70-g09d2