diff --git a/lib/spack/spack/solver/asp.py b/lib/spack/spack/solver/asp.py index 7023d954e3d..49487df2086 100644 --- a/lib/spack/spack/solver/asp.py +++ b/lib/spack/spack/solver/asp.py @@ -4507,36 +4507,30 @@ def __init__(self): self.selector = ReusableSpecsSelector(configuration=spack.config.CONFIG) @staticmethod - def _check_input_and_extract_concrete_specs(specs): - reusable = [] + def _check_input_and_extract_concrete_specs( + specs: List[spack.spec.Spec], + ) -> List[spack.spec.Spec]: + reusable: List[spack.spec.Spec] = [] + analyzer = create_graph_analyzer() for root in specs: for s in root.traverse(): - candidates = s.edges_to_dependencies(depflag=dt.BUILD) - if candidates: - non_virtuals, virtuals, _ = create_graph_analyzer().possible_dependencies( - s, transitive=False, allowed_deps=dt.LINK | dt.RUN | dt.BUILD - ) - possible_direct_deps = set(non_virtuals) | virtuals - not_possible = set( - [ - x.spec.name - for x in candidates - if x.direct and x.spec.name not in possible_direct_deps - ] - ) - if not_possible: - start_str = f"'{s}' in '{root}'" - if s == root: - start_str = f"'{root}'" - raise UnsatisfiableSpecError( - f"{start_str} cannot have a dependency on {', '.join(not_possible)}, " - f"according to its recipe" - ) - if s.concrete: reusable.append(s) - elif spack.repo.PATH.is_virtual(s.name): - continue + else: + if spack.repo.PATH.is_virtual(s.name): + continue + # Error if direct dependencies cannot be satisfied + deps = {edge.spec.name for edge in s.edges_to_dependencies() if edge.direct} + if deps: + graph = analyzer.possible_dependencies( + s, allowed_deps=dt.ALL, transitive=False + ) + deps.difference_update(graph.real_pkgs, graph.virtuals) + if deps: + start_str = f"'{root}'" if s == root else f"'{s}' in '{root}'" + raise UnsatisfiableSpecError( + f"{start_str} cannot depend on {', '.join(deps)}" + ) try: spack.repo.PATH.get_pkg_class(s.fullname) diff --git a/lib/spack/spack/test/concretization/core.py b/lib/spack/spack/test/concretization/core.py index 232ad9c3e90..76c13fb1d60 100644 --- a/lib/spack/spack/test/concretization/core.py +++ b/lib/spack/spack/test/concretization/core.py @@ -2199,7 +2199,7 @@ def test_unsolved_specs_raises_error(self, monkeypatch, mock_packages): # A package does not exist ("pkg-a ^foo", "since 'foo' does not exist"), # Request a compiler for a package that doesn't need it - ("pkg-c %gcc", "according to its recipe"), + ("pkg-c %gcc", "cannot depend on gcc"), ], ) def test_errors_on_statically_checked_preconditions(self, spec_str, expected_match):