Repository: spack/spack

Issue:
Multiple virtual providers are pulled into the same spec graph in some circumstances
### Steps to reproduce

Previous behaviour when requesting a specific virtual provider was to build using spec syntax like: `quantum-espresso ^intel-oneapi-mkl` or `quantum-espresso ^amdfftw`.  Following the merging of #35322 it seems that this is no longer sufficient in the case of some packages, such as quantum espresso, and multiple providers for virtual deps get pulled into the spec graph.

For example, on a fresh AWS instance, attempting to build with AOCL components we find that `fftw` and `amdfftw` are both pulled in.

```
[ec2-user] $  sudo dnf groupinstall "development tools"
...
[ec2-user] $  sudo dnf install gcc-gfortran
...
[ec2-user] $  git clone https://github.com/spack/spack
...
[ec2-user] $  source spack/share/spack/setup-env.sh
...
[ec2-user] $  spack compiler find
==> Added 1 new compiler to /home/ec2-user/.spack/linux/compilers.yaml
    gcc@11.4.1
==> Compilers are defined in the following files:
    /home/ec2-user/.spack/linux/compilers.yaml

[ec2-user] $ spack spec -I quantum-espresso ^amdblis ^amdlibflame ^amdfftw ^amdscalapack
Input spec
--------------------------------
 -   quantum-espresso
 -       ^amdblis
 -       ^amdfftw
 -       ^amdlibflame
 -       ^amdscalapack

Concretized
--------------------------------
 -   quantum-espresso@7.3%gcc@11.4.1~clock~elpa+epw~fox~gipaw~ipo~libxc+mpi~nvtx+openmp+patch~qmcpack+scalapack build_system=cmake build_type=Release generator=make hdf5=none arch=linux-rhel9-zen4
 -       ^amdblis@4.1%gcc@11.4.1~aocl_gemm+blas+cblas~ilp64+suphandling build_system=makefile libs=shared,static threads=openmp arch=linux-rhel9-zen4
 -           ^python@3.11.6%gcc@11.4.1+bz2+crypt+ctypes+dbm~debug+libxml2+lzma~nis~optimizations+pic+pyexpat+pythoncmd+readline+shared+sqlite3+ssl~tkinter+uuid+zlib build_system=generic patches=13fa8bf,b0615b2,ebdca64,f2fd060 arch=linux-rhel9-zen4
 -               ^bzip2@1.0.8%gcc@11.4.1~debug~pic+shared build_system=generic arch=linux-rhel9-zen4
 -               ^gdbm@1.23%gcc@11.4.1 build_system=autotools arch=linux-rhel9-zen4
 -               ^libffi@3.4.4%gcc@11.4.1 build_system=autotools patches=070b1f3 arch=linux-rhel9-zen4
 -               ^libxcrypt@4.4.35%gcc@11.4.1~obsolete_api build_system=autotools patches=4885da3 arch=linux-rhel9-zen4
 -               ^readline@8.2%gcc@11.4.1 build_system=autotools patches=bbf97f1 arch=linux-rhel9-zen4
 -               ^sqlite@3.43.2%gcc@11.4.1+column_metadata+dynamic_extensions+fts~functions+rtree build_system=autotools arch=linux-rhel9-zen4
 -               ^util-linux-uuid@2.38.1%gcc@11.4.1 build_system=autotools arch=linux-rhel9-zen4
 -               ^xz@5.4.1%gcc@11.4.1~pic build_system=autotools libs=shared,static arch=linux-rhel9-zen4
 -       ^amdfftw@4.1%gcc@11.4.1+amd-dynamic-dispatcher~amd-fast-planner~amd-mpi-vader-limit~debug+mpi+openmp+shared~static~threads build_system=autotools precision=double,float arch=linux-rhel9-zen4
 -           ^texinfo@7.0.3%gcc@11.4.1 build_system=autotools arch=linux-rhel9-zen4
 -       ^amdlibflame@4.1%gcc@11.4.1~debug~ilp64+lapack2flame+shared+static build_system=autotools patches=4e9ea3f threads=none arch=linux-rhel9-zen4
 -           ^aocl-utils@4.1%gcc@11.4.1~doc~examples~ipo~tests build_system=cmake build_type=Release generator=make arch=linux-rhel9-zen4
 -       ^amdscalapack@4.1%gcc@11.4.1~ilp64~ipo~pic+shared build_system=cmake build_type=Release generator=make arch=linux-rhel9-zen4
 -       ^cmake@3.27.9%gcc@11.4.1~doc+ncurses+ownlibs build_system=generic build_type=Release arch=linux-rhel9-zen4
 -           ^curl@8.4.0%gcc@11.4.1~gssapi~ldap~libidn2~librtmp~libssh~libssh2+nghttp2 build_system=autotools libs=shared,static tls=openssl arch=linux-rhel9-zen4
 -               ^nghttp2@1.57.0%gcc@11.4.1 build_system=autotools arch=linux-rhel9-zen4
 -           ^ncurses@6.4%gcc@11.4.1~symlinks+termlib abi=none build_system=autotools arch=linux-rhel9-zen4
 -           ^zlib-ng@2.1.5%gcc@11.4.1+compat+opt build_system=autotools arch=linux-rhel9-zen4
 -       ^fftw@3.3.10%gcc@11.4.1+mpi+openmp~pfft_patches build_system=autotools precision=double,float arch=linux-rhel9-zen4
 -       ^gcc-runtime@11.4.1%gcc@11.4.1 build_system=generic arch=linux-rhel9-zen4
 -       ^git@2.42.0%gcc@11.4.1+man+nls+perl+subtree~svn~tcltk build_system=autotools arch=linux-rhel9-zen4
 -           ^autoconf@2.72%gcc@11.4.1 build_system=autotools arch=linux-rhel9-zen4
 -           ^automake@1.16.5%gcc@11.4.1 build_system=autotools arch=linux-rhel9-zen4
 -           ^expat@2.5.0%gcc@11.4.1+libbsd build_system=autotools arch=linux-rhel9-zen4
 -               ^libbsd@0.11.7%gcc@11.4.1 build_system=autotools arch=linux-rhel9-zen4
 -                   ^libmd@1.0.4%gcc@11.4.1 build_system=autotools arch=linux-rhel9-zen4
 -           ^gettext@0.22.4%gcc@11.4.1+bzip2+curses+git~libunistring+libxml2+pic+shared+tar+xz build_system=autotools arch=linux-rhel9-zen4
 -               ^libxml2@2.10.3%gcc@11.4.1+pic~python+shared build_system=autotools arch=linux-rhel9-zen4
 -               ^tar@1.34%gcc@11.4.1 build_system=autotools zip=pigz arch=linux-rhel9-zen4
 -                   ^pigz@2.8%gcc@11.4.1 build_system=makefile arch=linux-rhel9-zen4
 -                   ^zstd@1.5.5%gcc@11.4.1+programs build_system=makefile compression=none libs=shared,static arch=linux-rhel9-zen4
 -           ^libiconv@1.17%gcc@11.4.1 build_system=autotools libs=shared,static arch=linux-rhel9-zen4
 -           ^libidn2@2.3.4%gcc@11.4.1 build_system=autotools arch=linux-rhel9-zen4
 -               ^libunistring@1.1%gcc@11.4.1 build_system=autotools arch=linux-rhel9-zen4
 -           ^libtool@2.4.7%gcc@11.4.1 build_system=autotools arch=linux-rhel9-zen4
 -               ^findutils@4.9.0%gcc@11.4.1 build_system=autotools patches=440b954 arch=linux-rhel9-zen4
 -           ^openssh@9.5p1%gcc@11.4.1+gssapi build_system=autotools arch=linux-rhel9-zen4
 -               ^krb5@1.20.1%gcc@11.4.1+shared build_system=autotools arch=linux-rhel9-zen4
 -                   ^bison@3.8.2%gcc@11.4.1 build_system=autotools arch=linux-rhel9-zen4
 -               ^libedit@3.1-20210216%gcc@11.4.1 build_system=autotools arch=linux-rhel9-zen4
 -           ^openssl@3.1.3%gcc@11.4.1~docs+shared build_system=generic certs=mozilla arch=linux-rhel9-zen4
 -               ^ca-certificates-mozilla@2023-05-30%gcc@11.4.1 build_system=generic arch=linux-rhel9-zen4
 -           ^pcre2@10.42%gcc@11.4.1~jit+multibyte build_system=autotools arch=linux-rhel9-zen4
 -           ^perl@5.38.0%gcc@11.4.1+cpanm+opcode+open+shared+threads build_system=generic patches=714e4d1 arch=linux-rhel9-zen4
 -               ^berkeley-db@18.1.40%gcc@11.4.1+cxx~docs+stl build_system=autotools patches=26090f4,b231fcc arch=linux-rhel9-zen4
 -       ^gmake@4.4.1%gcc@11.4.1~guile build_system=generic arch=linux-rhel9-zen4
 -       ^m4@1.4.19%gcc@11.4.1+sigsegv build_system=autotools patches=9dc5fbd,bfdffa7 arch=linux-rhel9-zen4
 -           ^diffutils@3.9%gcc@11.4.1 build_system=autotools arch=linux-rhel9-zen4
 -           ^libsigsegv@2.14%gcc@11.4.1 build_system=autotools arch=linux-rhel9-zen4
 -       ^openmpi@5.0.1%gcc@11.4.1~atomics~cuda~gpfs~internal-hwloc~internal-libevent~internal-pmix~java~legacylaunchers~lustre~memchecker~openshmem~orterunprefix~romio+rsh~static+vt+wrapper-rpath build_system=autotools fabrics=none patches=0a26bba schedulers=none arch=linux-rhel9-zen4
 -           ^hwloc@2.9.1%gcc@11.4.1~cairo~cuda~gl~libudev+libxml2~netloc~nvml~oneapi-level-zero~opencl+pci~rocm build_system=autotools libs=shared,static arch=linux-rhel9-zen4
 -               ^libpciaccess@0.17%gcc@11.4.1 build_system=autotools arch=linux-rhel9-zen4
 -                   ^util-macros@1.19.3%gcc@11.4.1 build_system=autotools arch=linux-rhel9-zen4
 -           ^libevent@2.1.12%gcc@11.4.1+openssl build_system=autotools arch=linux-rhel9-zen4
 -           ^numactl@2.0.14%gcc@11.4.1 build_system=autotools patches=4e1d78c,62fc8a8,ff37630 arch=linux-rhel9-zen4
 -           ^pkgconf@1.9.5%gcc@11.4.1 build_system=autotools arch=linux-rhel9-zen4
 -           ^pmix@5.0.1%gcc@11.4.1~docs+pmi_backwards_compatibility~python~restful build_system=autotools arch=linux-rhel9-zen4
```

### Error message

Similarly for `intel-oneapi-mkl` we find openblas also being pulled in.

```
[ec2-user] $  spack spec quantum-espresso ^intel-oneapi-mkl
Input spec
--------------------------------
 -   quantum-espresso
 -       ^intel-oneapi-mkl

Concretized
--------------------------------
 -   quantum-espresso@7.3%gcc@11.4.1~clock~elpa+epw~fox~gipaw~ipo~libxc+mpi~nvtx+openmp+patch~qmcpack+scalapack build_system=cmake build_type=Release generator=make hdf5=none arch=linux-amzn2023-zen4
 -       ^cmake@3.27.9%gcc@11.4.1~doc+ncurses+ownlibs build_system=generic build_type=Release arch=linux-amzn2023-zen4
 -           ^curl@8.4.0%gcc@11.4.1~gssapi~ldap~libidn2~librtmp~libssh~libssh2+nghttp2 build_system=autotools libs=shared,static tls=openssl arch=linux-amzn2023-zen4
 -               ^nghttp2@1.57.0%gcc@11.4.1 build_system=autotools arch=linux-amzn2023-zen4
 -           ^ncurses@6.4%gcc@11.4.1~symlinks+termlib abi=none build_system=autotools arch=linux-amzn2023-zen4
 -           ^zlib-ng@2.1.5%gcc@11.4.1+compat+opt build_system=autotools arch=linux-amzn2023-zen4
 -       ^gcc-runtime@11.4.1%gcc@11.4.1 build_system=generic arch=linux-amzn2023-zen4
 -       ^git@2.42.0%gcc@11.4.1+man+nls+perl+subtree~svn~tcltk build_system=autotools arch=linux-amzn2023-zen4
 -           ^autoconf@2.72%gcc@11.4.1 build_system=autotools arch=linux-amzn2023-zen4
 -           ^automake@1.16.5%gcc@11.4.1 build_system=autotools arch=linux-amzn2023-zen4
 -           ^expat@2.5.0%gcc@11.4.1+libbsd build_system=autotools arch=linux-amzn2023-zen4
 -               ^libbsd@0.11.7%gcc@11.4.1 build_system=autotools arch=linux-amzn2023-zen4
 -                   ^libmd@1.0.4%gcc@11.4.1 build_system=autotools arch=linux-amzn2023-zen4
 -           ^gettext@0.22.4%gcc@11.4.1+bzip2+curses+git~libunistring+libxml2+pic+shared+tar+xz build_system=autotools arch=linux-amzn2023-zen4
 -               ^bzip2@1.0.8%gcc@11.4.1~debug~pic+shared build_system=generic arch=linux-amzn2023-zen4
 -               ^libxml2@2.10.3%gcc@11.4.1+pic~python+shared build_system=autotools arch=linux-amzn2023-zen4
 -               ^tar@1.34%gcc@11.4.1 build_system=autotools zip=pigz arch=linux-amzn2023-zen4
 -                   ^pigz@2.8%gcc@11.4.1 build_system=makefile arch=linux-amzn2023-zen4
 -                   ^zstd@1.5.5%gcc@11.4.1+programs build_system=makefile compression=none libs=shared,static arch=linux-amzn2023-zen4
 -               ^xz@5.4.1%gcc@11.4.1~pic build_system=autotools libs=shared,static arch=linux-amzn2023-zen4
 -           ^libiconv@1.17%gcc@11.4.1 build_system=autotools libs=shared,static arch=linux-amzn2023-zen4
 -           ^libidn2@2.3.4%gcc@11.4.1 build_system=autotools arch=linux-amzn2023-zen4
 -               ^libunistring@1.1%gcc@11.4.1 build_system=autotools arch=linux-amzn2023-zen4
 -           ^libtool@2.4.7%gcc@11.4.1 build_system=autotools arch=linux-amzn2023-zen4
 -               ^findutils@4.9.0%gcc@11.4.1 build_system=autotools patches=440b954 arch=linux-amzn2023-zen4
 -           ^openssh@9.5p1%gcc@11.4.1+gssapi build_system=autotools arch=linux-amzn2023-zen4
 -               ^krb5@1.20.1%gcc@11.4.1+shared build_system=autotools arch=linux-amzn2023-zen4
 -                   ^bison@3.8.2%gcc@11.4.1 build_system=autotools arch=linux-amzn2023-zen4
 -               ^libedit@3.1-20210216%gcc@11.4.1 build_system=autotools arch=linux-amzn2023-zen4
 -               ^libxcrypt@4.4.35%gcc@11.4.1~obsolete_api build_system=autotools patches=4885da3 arch=linux-amzn2023-zen4
 -           ^openssl@3.1.3%gcc@11.4.1~docs+shared build_system=generic certs=mozilla arch=linux-amzn2023-zen4
 -               ^ca-certificates-mozilla@2023-05-30%gcc@11.4.1 build_system=generic arch=linux-amzn2023-zen4
 -           ^pcre2@10.42%gcc@11.4.1~jit+multibyte build_system=autotools arch=linux-amzn2023-zen4
 -           ^perl@5.38.0%gcc@11.4.1+cpanm+opcode+open+shared+threads build_system=generic patches=714e4d1 arch=linux-amzn2023-zen4
 -               ^berkeley-db@18.1.40%gcc@11.4.1+cxx~docs+stl build_system=autotools patches=26090f4,b231fcc arch=linux-amzn2023-zen4
 -               ^gdbm@1.23%gcc@11.4.1 build_system=autotools arch=linux-amzn2023-zen4
 -                   ^readline@8.2%gcc@11.4.1 build_system=autotools patches=bbf97f1 arch=linux-amzn2023-zen4
 -       ^gmake@4.4.1%gcc@11.4.1~guile build_system=generic arch=linux-amzn2023-zen4
 -       ^intel-oneapi-mkl@2024.0.0%gcc@11.4.1~cluster+envmods~ilp64+shared build_system=generic mpi_family=none threads=none arch=linux-amzn2023-zen4
 -           ^intel-tbb@2021.9.0%gcc@11.4.1~ipo+shared+tm build_system=cmake build_type=Release cxxstd=default generator=make patches=91755c6 arch=linux-amzn2023-zen4
 -       ^m4@1.4.19%gcc@11.4.1+sigsegv build_system=autotools patches=9dc5fbd,bfdffa7 arch=linux-amzn2023-zen4
 -           ^diffutils@3.9%gcc@11.4.1 build_system=autotools arch=linux-amzn2023-zen4
 -           ^libsigsegv@2.14%gcc@11.4.1 build_system=autotools arch=linux-amzn2023-zen4
 -       ^netlib-scalapack@2.2.0%gcc@11.4.1~ipo~pic+shared build_system=cmake build_type=Release generator=make patches=072b006,1c9ce5f,244a9aa arch=linux-amzn2023-zen4
 -       ^openblas@0.3.26%gcc@11.4.1~bignuma~consistent_fpcsr+fortran~ilp64+locking+pic+shared build_system=makefile symbol_suffix=none threads=openmp arch=linux-amzn2023-zen4
 -       ^openmpi@5.0.1%gcc@11.4.1~atomics~cuda~gpfs~internal-hwloc~internal-libevent~internal-pmix~java~legacylaunchers~lustre~memchecker~openshmem~orterunprefix~romio+rsh~static+vt+wrapper-rpath build_system=autotools fabrics=none patches=0a26bba schedulers=none arch=linux-amzn2023-zen4
 -           ^hwloc@2.9.1%gcc@11.4.1~cairo~cuda~gl~libudev+libxml2~netloc~nvml~oneapi-level-zero~opencl+pci~rocm build_system=autotools libs=shared,static arch=linux-amzn2023-zen4
 -               ^libpciaccess@0.17%gcc@11.4.1 build_system=autotools arch=linux-amzn2023-zen4
 -                   ^util-macros@1.19.3%gcc@11.4.1 build_system=autotools arch=linux-amzn2023-zen4
 -           ^libevent@2.1.12%gcc@11.4.1+openssl build_system=autotools arch=linux-amzn2023-zen4
 -           ^numactl@2.0.14%gcc@11.4.1 build_system=autotools patches=4e1d78c,62fc8a8,ff37630 arch=linux-amzn2023-zen4
 -           ^pkgconf@1.9.5%gcc@11.4.1 build_system=autotools arch=linux-amzn2023-zen4
 -           ^pmix@5.0.1%gcc@11.4.1~docs+pmi_backwards_compatibility~python~restful build_system=autotools arch=linux-amzn2023-zen4
```

[qe-oneapi.spack.debug.log](https://github.com/spack/spack/files/14127847/qe-oneapi.spack.debug.log)

Notably, this does not occur if the verbose spec syntax `quantum-espresso ^[virtuals=blas,lapack,fftw-api] intel-oneapi-mkl` is used.  In these cases the expected behaviour of a single provider is restored.

### Information on your system

This is the first affected commit based on a git bisect.  Develop remains affected as of writing.

```
* **Spack:** 0.21.0.dev0 (6cd2241e49a393d7ac32b46064a2d2f4e53f7d86)
* **Python:** 3.9.10
* **Platform:** linux-amzn2023-zen4
* **Concretizer:** clingo
```

### General information

- [X] I have run `spack debug report` and reported the version of Spack/Python/Platform
- [X] I have searched the issues of this repo and believe this is not a duplicate
- [X] I have run the failing commands in debug mode and reported the output


Discussion:
Similar behavior can be observed with `spack solve flecsi ^mpich`, which will pull in both `mpich` and `openmpi` at the same time. One way to resolve it is to instead do `spack solve flecsi ^[virtuals=mpi] mpich`.
Can you post the graph that you obtain? The command would be:
```
$ spack graph -dc ... > qe.dot
```


Resolving patch:
diff --git a/lib/spack/spack/audit.py b/lib/spack/spack/audit.py
--- a/lib/spack/spack/audit.py
+++ b/lib/spack/spack/audit.py
@@ -796,10 +796,30 @@ def check_virtual_with_variants(spec, msg):
                 except spack.repo.UnknownPackageError:
                     # This dependency is completely missing, so report
                     # and continue the analysis
+                    summary = f"{pkg_name}: unknown package '{dep_name}' in 'depends_on' directive"
+                    details = [f" in {filename}"]
+                    errors.append(error_cls(summary=summary, details=details))
+                    continue
+
+                # Check for self-referential specs similar to:
+                #
+                # depends_on("foo@X.Y", when="^foo+bar")
+                #
+                # That would allow clingo to choose whether to have foo@X.Y+bar in the graph.
+                problematic_edges = [
+                    x for x in when.edges_to_dependencies(dep_name) if not x.virtuals
+                ]
+                if problematic_edges and not dep.patches:
                     summary = (
-                        f"{pkg_name}: unknown package '{dep_name}' in " "'depends_on' directive"
+                        f"{pkg_name}: dependency on '{dep.spec}' when '{when}' is self-referential"
                     )
-                    details = [f" in {filename}"]
+                    details = [
+                        (
+                            f" please specify better using '^[virtuals=...] {dep_name}', or "
+                            f"substitute with an equivalent condition on '{pkg_name}'"
+                        ),
+                        f" in {filename}",
+                    ]
                     errors.append(error_cls(summary=summary, details=details))
                     continue
 


Test patch: