Infer types correctly for P4-14 action parameters and clone primitives #339
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
We infer different types for action parameters than
p4c-bm
on a number of our internal test cases. I investigated, and it turns out that there are a few different issues in the P4-14 type inference algorithm that contribute to this problem. This PR fixes those issues.ef71fd6 adds type inference information for the
clone_spec
operand of the variousclone
primitives. Previously, this operand was defaulting toType_Unknown
.This didn't fix most of my test cases, and the reason turned out to be that the P4-14 type inference passes are Modifiers. This implies that, by default, they only visit each node once. However, TypeCheck::Pass1, we replace all references to an action argument with the ActionArg node they refer to. This means that only the first reference the type inference passes encounter gets considered for type inference.
There is an escape hatch for this: you can set
visitDagOnce = false
on a Modifier instance to allow it to visit the same node more than once. However, it clones the node anew each time, which prevents you from accumulating information from each visit to the node. We need to store that information off to the side instead, and we need to avoid invalidating the data structure we use until we have all the information we need.This suggests that we should collect the necessary information in Inspector passes and then apply it in a Modifier pass. 905bb61 separates
TypeCheck::Pass2
(the bottom-up pass) andTypeCheck::Pass3
(the top-down pass) into two bottom-up passes and two top-down passes. One pair of passes is for expressions; these passes continue to perform in-place modifications to the tree. The second pair is for action arguments; these passes are simply Inspectors that accumulate type information for each ActionArg. A final Modifier pass then applies the type information accumulated by the Inspectors to each ActionArg in the tree. Having names likePass1
andPass2
doesn't really scale to this many passes, so I renamed each pass to clarify what's going on.This change makes us gather the correct information, but it introduces a number of type errors in existing test cases, because considering the different uses of each ActionArg leads us to infer different types for it. In particular we run into a number of cases where we infer
bit<>
types with several different widths. 5afa055 permits widening when combining these types, which fixes the type errors.With these changes, we infer the same types that
p4c-bm
infers. The existing tests actually have pretty good coverage for all of these issues; all I needed to do was update the expected results, which is taken care of by 71e8592.