Split satisfies(..., strict=True/False) into two functions#35681
Split satisfies(..., strict=True/False) into two functions#35681haampie merged 41 commits intospack:developfrom
satisfies(..., strict=True/False) into two functions#35681Conversation
|
@naughtont3 can you review this PR? This PR modifies the following package(s), for which you are listed as a maintainer:
|
| # Architecture | ||
| (ArchSpec, "None-ubuntu20.04-None", "None-None-x86_64", (True, False, False)), | ||
| (ArchSpec, "None-ubuntu20.04-None", "linux-None-x86_64", (True, False, False)), | ||
| (ArchSpec, "None-None-x86_64:", "linux-None-haswell", (True, False, True)), | ||
| (ArchSpec, "None-None-x86_64:haswell", "linux-None-icelake", (False, False, False)), | ||
| (ArchSpec, "linux-None-None", "linux-None-None", (True, True, True)), | ||
| (ArchSpec, "darwin-None-None", "linux-None-None", (False, False, False)), | ||
| (ArchSpec, "None-ubuntu20.04-None", "None-ubuntu20.04-None", (True, True, True)), | ||
| (ArchSpec, "None-ubuntu20.04-None", "None-ubuntu22.04-None", (False, False, False)), | ||
| # Compiler | ||
| (CompilerSpec, "gcc", "clang", (False, False, False)), | ||
| (CompilerSpec, "gcc", "gcc@5", (True, False, True)), | ||
| (CompilerSpec, "gcc@5", "[email protected]", (True, False, True)), | ||
| (CompilerSpec, "gcc@5", "gcc@5-tag", (True, False, True)), | ||
| # Flags (flags are a map, so for convenience we initialize a full Spec) | ||
| # Note: the semantic is that of sv variants, not mv variants | ||
| (Spec, "cppflags=-foo", "cppflags=-bar", (False, False, False)), | ||
| (Spec, "cppflags='-bar -foo'", "cppflags=-bar", (False, False, False)), | ||
| (Spec, "cppflags=-foo", "cppflags=-foo", (True, True, True)), | ||
| (Spec, "cppflags=-foo", "cflags=-foo", (True, False, False)), |
There was a problem hiding this comment.
More cases to test are welcome here, if reviewers have some.
|
I'm not caught up on the history of this but I do seem to recall that the following (which are all used frequently in packages) are slightly different: if "+python" in self.spec:
if self.spec.satisfies("+python"):
if self.spec.satisfies("+python", strict=True):With this PR, will the first two be equivalent and correct? Can't remember what the issue was with these originally. |
45e0dfb to
a03fbd0
Compare
|
@adamjstewart This PR tries to have a slightly more formal notion of self.intersects(other)which roughly corresponds to The other is: self.satisfies(other)which corresponds to This refactor was motivated by the bug in #35597 which, upon investigation, revealed a few inconsistencies in the current API that we are trying to fix here. In the course of preparing this PR I also discovered a few bugs in version comparison and target comparison, that are fixed here. |
| def test_abstract_specs_can_constrain_each_other(self, lhs, rhs, expected): | ||
| """Test that lhs and rhs intersect with each other, and that they can be constrained | ||
| with each other. Also check that the constrained result match the expected spec. | ||
| """ | ||
| lhs, rhs, expected = Spec(lhs), Spec(rhs), Spec(expected) | ||
|
|
||
| def check_constrain(expected, spec, constraint): | ||
| exp = Spec(expected) | ||
| spec = Spec(spec) | ||
| constraint = Spec(constraint) | ||
| spec.constrain(constraint) | ||
| assert exp == spec | ||
| assert lhs.intersects(rhs) | ||
| assert rhs.intersects(lhs) | ||
|
|
||
| c1, c2 = lhs.copy(), rhs.copy() | ||
| c1.constrain(rhs) | ||
| c2.constrain(lhs) | ||
| assert c1 == c2 | ||
| assert c1 == expected |
There was a problem hiding this comment.
Here I always check all the invariants we expect for each of the new parametrized tests.
|
I tried to time a few concretizations with the same setup on and with this branch: Here are the datasets: radiuss_develop.csv I don't see significant differences. |
|
FWIW it looks like outside of the old concretizer, that |
|
The abstract vs concrete case isn't (very?) relevant for satisfies: if the rhs is concrete and has a dag hash, the lhs should have the same dag hash, and if only the lhs is concrete it doesn't matter how you interpret the lhs (as a singleton set with just the spec, or still an infinite set where elements have additional variants defined etc) for the result to make sense. The abstract vs concrete case is relevant for intersects, since then the answer to "is there a more specific spec than a given concrete spec" determines whether intersects(concrete, abstract) returns true or false in some cases. If you see concrete specs as singletons, then intersects(concrete, abstract) with additional variants in abstract is false. If you see concrete specs sort of like very constrained abstract specs, then it could be true. [so for example To me abstract specs as singletons make most sense, since they're elements picked from the solution space, so I would say |
Agreed, since they are basically the same issue. |
|
develop (39adb65, blue) vs. PR (d54611a, orange) radiuss_develop.csv No impact on concretization time: |
hppritcha
left a comment
There was a problem hiding this comment.
Looks good to me! can't seem to check off.
|
@hppritcha it's already merged :) @alalazo is just posting reports on concretization speed on PRs so we can track which ones may have impacted performance. |
…5681) This commit formalizes `satisfies(lhs, rhs, strict=True/False)` and splits it into two functions: `satisfies(lhs, rhs)` and `intersects(lhs, rhs)`. - `satisfies(lhs, rhs)` means: all concrete specs matching the left hand side also match the right hand side - `intersects(lhs, rhs)` means: there exist concrete specs matching both lhs and rhs. `intersects` now has the property that it's commutative, which previously was not guaranteed. For abstract specs, `intersects(lhs, rhs)` implies that `constrain(lhs, rhs)` works. What's *not* done in this PR is ensuring that `intersects(concrete, abstract)` returns false when the abstract spec has additional properties not present in the concrete spec, but `constrain(concrete, abstract)` will raise an error. To accomplish this, some semantics have changed, as well as bugfixes to ArchSpec: - GitVersion is now interpreted as a more constrained version - Compiler flags are interpreted as strings since their order is important - Abstract specs respect variant type (bool / multivalued)



closes #35599
This PR splits each
satisfiesmethod having astrict=argument into two function calls:intersects: corresponds tostrict=Falseand has "intersection" semantic.satisfies: corresponds tostrict=Trueand has "subset" semantic.From 1 it follows that
intersectsis commutative, so in this PR I also tried to remove most of the non-commutative behaviors we had withstrict=False.Modifications:
satisfies(..., strict=...)intosatisfiesandintersectsArchSpecrelated to targets, see ci: fixes for compiler bootstrapping #17563 (review)GitVersionconsistent with theintersectsandsatisfiessemantic (see 10c147f)