Repository: spack/spack

Issue:
criterion "number of non-default variants (non-roots)" seems incorrect
### Steps to reproduce

Currently on develop:

```
spack spec spfft+rocm
```

picks up rocm 4.3.1, but 4.5.2 is the latest. When I add `^hip@4.5:` I do get 4.5.2. The solve output shows it prefers 4.3.1 because of the following:

```diff
--- spfft+rocm
+++ spfft+rocm ^hip@4.5:

    Priority  Criterion                                            Installed  ToBuild
    1         number of packages to build (vs. reuse)                      -        0
    2         deprecated versions used                                     0        0
    3         version weight                                               0        0
    4         number of non-default variants (roots)                       0        0
    5         preferred providers for roots                                0        0
    6         default values of variants not being used (roots)            0        1
-   7         number of non-default variants (non-roots)                   0        0
+   7         number of non-default variants (non-roots)                   0        1
    8         preferred providers (non-roots)                              0        1
    9         compiler mismatches                                          0        0
    10        OS mismatches                                                0        0
    11        non-preferred OS's                                           0        0
-   12        version badness                                              0       26
+   12        version badness                                              0        4
    13        default values of variants not being used (non-roots)        0        2
    14        non-preferred compilers                                      0        0
    15        target mismatches                                            0        0
    16        non-preferred targets                                        0        0


```
so without the `^hip@4.5:` constraint it manages to find a way to do without "non-default variants", except I don't see any difference in variant values when I compare the concrete specs (using #28885). And default values don't depend on versions as far as I can tell. The only "variants" that change are patches, but this might be a red herring.


### Information on your system

* **Spack:** 0.17.1-1229-5235315a51
* **Python:** 3.8.10
* **Platform:** linux-ubuntu20.04-zen2
* **Concretizer:** clingo


Discussion:
When I comment out

```diff
diff --git a/lib/spack/spack/solver/concretize.lp b/lib/spack/spack/solver/concretize.lp
index 13902d0892..f868a1d7dd 100644
--- a/lib/spack/spack/solver/concretize.lp
+++ b/lib/spack/spack/solver/concretize.lp
@@ -468,7 +468,7 @@ variant_not_default(Package, Variant, Value)
  :- variant_value(Package, Variant, Value),
     not variant_default_value(Package, Variant, Value),
     % variants set explicitly on the CLI don't count as non-default
-    not variant_set(Package, Variant, Value),
+    % not variant_set(Package, Variant, Value),
     % variants set on externals that we could use don't count as non-default
     % this makes spack prefer to use an external over rebuilding with the
     % default configuration
```

it concretizes to the latest, with those costs for criterion 7 equal:

```diff
--- spfft+rocm ^hip@:4.3
+++ spfft+rocm 
    Priority  Criterion                                            Installed  ToBuild
    1         number of packages to build (vs. reuse)                      -        0
    2         deprecated versions used                                     0        0
    3         version weight                                               0        0
    4         number of non-default variants (roots)                       0        0
    5         preferred providers for roots                                0        0
    6         default values of variants not being used (roots)            0        1
    7         number of non-default variants (non-roots)                   0        2
    8         preferred providers (non-roots)                              0        1
    9         compiler mismatches                                          0        0
    10        OS mismatches                                                0        0
    11        non-preferred OS's                                           0        0
-   12        version badness                                              0       26
+   12        version badness                                              0        4
    13        default values of variants not being used (non-roots)        0        2
    14        non-preferred compilers                                      0        0
    15        target mismatches                                            0        0
    16        non-preferred targets                                        0        0

```

my guess is some logic in `variant_set` is incorrect
You don't have variants set in your spec in a non-root node, so it seems correct that commenting line 468 doesn't have an effect on optimization "7". What does it happen for priority "4"?
```diff
diff --git a/var/spack/repos/builtin/packages/hip/package.py b/var/spack/repos/builtin/packages/hip/package.py
index f22de204f4..4821c75e25 100644
--- a/var/spack/repos/builtin/packages/hip/package.py
+++ b/var/spack/repos/builtin/packages/hip/package.py
@@ -37,7 +37,7 @@ class Hip(CMakePackage):
 
     depends_on('cmake@3:', type='build')
     depends_on('perl@5.10:', type=('build', 'run'))
-    depends_on('mesa~llvm@21:')
+    depends_on('mesa')
 
     for ver in ['3.5.0', '3.7.0', '3.8.0', '3.9.0', '3.10.0', '4.0.0', '4.1.0',
                 '4.2.0', '4.3.0', '4.3.1']:
```

this makes it concretize to the latest :confused: but it's at least a case of a "set" variant.

I think `llvm-amdgpu` can now be used in mesa thanks to the virtual llvm package. Why hip depends on mesa, I have no clue. As a workaround... we can go with the above patch.

I still think there is a bug in Spack, given that that depends_on was unconditional in the hip package, so no way for the concretizer to work around it?

Resolving patch:
diff --git a/var/spack/repos/builtin/packages/hip-rocclr/package.py b/var/spack/repos/builtin/packages/hip-rocclr/package.py
--- a/var/spack/repos/builtin/packages/hip-rocclr/package.py
+++ b/var/spack/repos/builtin/packages/hip-rocclr/package.py
@@ -42,7 +42,7 @@ def url_for_version(self, version):
     variant('build_type', default='Release', values=("Release", "Debug", "RelWithDebInfo"), description='CMake build type')
 
     depends_on('cmake@3:', type='build')
-    depends_on('mesa~llvm@21: swr=none', type='link')
+    depends_on('mesa~llvm@21:', type='link')
     depends_on('libelf', type='link', when="@3.7.0:3.8.0")
     depends_on('numactl', type='link', when="@3.7.0:")
 
diff --git a/var/spack/repos/builtin/packages/mesa/package.py b/var/spack/repos/builtin/packages/mesa/package.py
--- a/var/spack/repos/builtin/packages/mesa/package.py
+++ b/var/spack/repos/builtin/packages/mesa/package.py
@@ -50,10 +50,8 @@ class Mesa(MesonPackage):
     _SWR_DISABLED_VALUES = ('none',)
     variant('swr', default=_SWR_AUTO_VALUE,
             values=_SWR_DISABLED_VALUES + _SWR_ENABLED_VALUES,
-            multi=True,
+            multi=True, when='+llvm',
             description="Enable the SWR driver.")
-    for swr_enabled_value in _SWR_ENABLED_VALUES:
-        conflicts('~llvm', when='swr={0}'.format(swr_enabled_value))
 
     # Front ends
     variant('osmesa', default=True, description="Enable the OSMesa frontend.")


Test patch: