Should `...` be supported in structure-valued expressions?
It seems like a fairly small and useful generalization of the current language spec to explicitly allow , ... inside of a structure-valued expression (only at the end, just before the closing }). This proposal is that would be supported in structure-valued expressions, which can appear anywhere that an R-value is needed with a struct or header type.
A strict reading of the current language spec in https://p4.org/p4-spec/docs/P4-16-v1.2.2.html#sec-initializing-with-default-values only allows ... in initialization expressions, seems to imply in spec version 1.2.2 that ... is only allowed in initializations.
This PR is for review if people believe the answer to the question raised by this issue should be "yes": https://github.com/p4lang/p4-spec/pull/1031
This is not an easy topic. We just merged a very complex PR in the compiler which deals with such cases, often by generating errors. Consider an expression like { a = 2, ... } == { b = 3, ... }. This has an infinite number of completions; it is not clear what the missing fields are, although we can guarantee that the expression evaluates to false for any well-typed completion.
Let me just provide some context here. Besides the variables that we explicitly instantiate inside parsers or controls, we also have parameters, such as hdr and meta structs. The latter almost always requires explicit initialization and, in fact, that's precisely what prompted the initial requests, because in the real data plane programs, this struct can be huge.
If we just allow these constructs as initializers, then this important case will not be covered.
In a case like {a=2, ...} == {b=3, ...}, it seems reasonable to make that an error since there is no way for the compiler to determine what the type of the two structure-valued expressions should be.
If the compiler just said "These structure-valued expressions must have a (typeRef) prefix to specify their type", does that make the resulting semantics more straightforward? And is it perhaps straightforward to determine when that proposed error message can be issued? It seems to me quite reasonable if the compiler gives up if it isn't "obvious" what the types should be.
The point I am trying to make is that we have to be careful what we put in the spec.
I have also tried to implement support for something like {a = 2} == {a = 2}, and even this is tricky, because you cannot just generate an associated struct type for these expressions, since structs cannot have int fields.
But yes, if the type is specified explicitly things are simpler.
By the way, this is the point I made at the LDWG yesterday. Some of the options we are considering, like this one, do not specify the type of the value. And that can make things more complicated.
My comment was dismissed with a response that the compiler already handles this in type inference.
I do agree we can separate type inference from the semantics of fully-typed terms. And that's a good principle to follow. But type inference gets very tricky. And even if we settle on a conservative inference scheme, I worry the result will be unintuitive for programmers -- relatively small changes to the programs can cause the type checker to flip from accepting to rejecting a program, or vice versa.
Personally, I am perfectly fine if every structure-valued expression must be preceded by an explicit (typeRef), by the way. Are all of the difficulties and issues being discussed here have a root cause that this (typeRef) is optional?
Part of my confusion stems from the fact that the current spec for structure-valued expressions (without ... allowed inside of them) says that (typeRef) is optional. Are the concerns being raised here applicable to the current spec as written, especially this sentence in Section 8.12 "Structure-valued expressions"?
"For a structure-valued expression typeRef is the name of a struct or header type. The typeRef can be omitted if it can be inferred from context, e.g., when initializing a variable with a struct type."
Closing this issue, since https://github.com/p4lang/p4-spec/pull/1251 was merged to address it.