Comparisons of list expressions
The specification states that structure-valued expressions can be used in comparisons (== or !=) in section 8.12 ("Structure-valued expressions can be used... in comparisons..."), but it does not say so for list expressions in section 8.11. Since those two kinds of expressions are very similar, this inconsistency here seems weird and probably needs some clarification.
Similarly, it probably should be clarified in section 8.10 whether tuples support comparisons (== or !=).
Lastly, the example of structure-valued expressions used in comparisons in 8.12 is perhaps a bad example ( bool b = s == (S) { a = 1, b = 2 } ) since that essentially compares two structures instead of two structure-valued expressions.
Example:
struct S {
bit<4> a;
}
bool x = {a = 1} == {a = 1};
bool y = {1} == {1};
Based on the spec the first comparison is allowed, but the second is not.
I have tested all types of comparisons in BMV2:
struct S {
bit<32> a;
bit<32> b;
}
control compute(inout hdr h) {
apply {
// bool b1_ = { a = 1, b = 2 } == { a = 1, b = 2 }; // BMV2: Compiler Bug: Could not find type for <Constant>(11032) 1
bool b1 = { a = 8w1, b = 8w2 } == { a = 8w1, b = 8w2 };
bool b2 = (S) { a = 1, b = 2 } == { a = 1, b = 2 };
// bool b3 = { a = 1, b = 2 } == (S) { a = 1, b = 2 }; // BMV2: error: ==: Cannot unify struct S to unknown struct
bool b4 = (S) { a = 1, b = 2 } == (S) { a = 1, b = 2 };
bool b5 = { 1, 2 } == { 1, 2 };
S s1 = { a = 1, b = 2 };
S s2 = { a = 1, b = 2 };
bool b6 = s1 == { a = 1, b = 2 };
bool b7 = s1 == (S) { a = 1, b = 2 };
bool b8 = s1 == s2;
tuple<bit<8>, bit<8>> t1 = {1, 2};
tuple<bit<8>, bit<8>> t2 = {1, 2};
bool b9 = t1 == { 1, 2 };
bool b10 = t1 == t2;
You can see that the comparisons between structure-valued expressions, list expressions, structs, and tuples are all allowed, except two cases.
For b1_, it seems to be some other issue with the compiler since b1 works well.
For b3, it seems weird that BMV2 cannot infer the type of the LHS. Given that b2 works well, and there is no rule in the spec enforcing the direction of type inference, I think it is more likely a problem with the compiler.
Overall, this experiment seems to suggest that (in)equality comparisons should be allowed in structure-valued expressions, list expressions, structs, and tuples.
If you find compiler bugs it would be very useful to file them as issues in the compiler repository.
@mbudiu-vmw I would be happy to file them. Maybe after we finish changing the spec so that I can confirm that it is actually a compiler problem.
Ok, so we'll count on you to keep track of the compiler bugs related to these fixes. There is a lot of information in your comments; ideally each different bug should eventually be filed as a separate issue.
Without introducing "cast" and “types" (#953), one way to generalize this can be that
- A list expression can be compared with a list expression, a
tuple, astruct, or aheaderfor equality (==) or inequality (!=) - A structure-valued expression can be compared with a structure-valued expression, a
struct, or aheaderfor equality (==) or inequality (!=)
But there is one corner case this description cannot handle: a list expression can also be compared with a structure-valued expression when typRef is explicit.
bool b11 = (S) { a = 1, b = 2 } == {1, 2}; // Good
// bool b12 = { a = 1, b = 2 } == {1, 2}; // Rejected by the BMV2 compiler
It seems reasonable for b11 to work since with (S), the LHS gain the type of S and then the RHS is cast to the same type. But this means that in order to explain this well, we probably need to introduce new types for the list and structure-valued expressions and new casts to the spec, which may be undesirable.
In the interest of tidying up the set of active issues on the P4 specification repository, I'm marking this as "stalled" and closing it. Of course, we can always re-open it in the future if there is interest in resurrecting it.